From 602aeecaaf9fc69fba96a8dba69d6657a47f1e46 Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 10 Sep 2014 16:14:08 +0200 Subject: [PATCH] add Python objects for Part and GeoFeature --- src/App/CMakeLists.txt | 7 ++ src/App/GeoFeaturePy.xml | 23 ++++++ src/App/GeoFeaturePyImp.cpp | 40 ++++++++++ src/App/Part.cpp | 150 ++++++++++++++++++++++++++++++++++- src/App/Part.h | 45 +++++++++++ src/App/PartPy.xml | 48 ++++++++++++ src/App/PartPyImp.cpp | 151 ++++++++++++++++++++++++++++++++++++ 7 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 src/App/GeoFeaturePy.xml create mode 100644 src/App/GeoFeaturePyImp.cpp create mode 100644 src/App/PartPy.xml create mode 100644 src/App/PartPyImp.cpp diff --git a/src/App/CMakeLists.txt b/src/App/CMakeLists.txt index e7fd4f345..a842f026e 100644 --- a/src/App/CMakeLists.txt +++ b/src/App/CMakeLists.txt @@ -33,6 +33,9 @@ set(FreeCADApp_LIBS generate_from_xml(DocumentPy) generate_from_xml(DocumentObjectPy) generate_from_xml(DocumentObjectGroupPy) +generate_from_xml(GeoFeaturePy) +generate_from_xml(PartPy) + generate_from_xml(ComplexGeoDataPy) generate_from_xml(PropertyContainerPy) generate_from_xml(MaterialPy) @@ -43,6 +46,8 @@ generate_from_py(FreeCADTest TestScript.h) SET(FreeCADApp_XML_SRCS DocumentObjectGroupPy.xml DocumentObjectPy.xml + GeoFeaturePy.xml + PartPy.xml DocumentPy.xml PropertyContainerPy.xml ComplexGeoDataPy.xml @@ -58,6 +63,8 @@ SET(Document_CPP_SRCS DocumentObjectFileIncluded.cpp DocumentObjectGroup.cpp DocumentObjectGroupPyImp.cpp + PartPyImp.cpp + GeoFeaturePyImp.cpp DocumentObjectPyImp.cpp DocumentObserver.cpp DocumentObserverPython.cpp diff --git a/src/App/GeoFeaturePy.xml b/src/App/GeoFeaturePy.xml new file mode 100644 index 000000000..5874da559 --- /dev/null +++ b/src/App/GeoFeaturePy.xml @@ -0,0 +1,23 @@ + + + + + + This class does the whole placement and position handling + + + + returns all posible paths to the root of the document + + + + + diff --git a/src/App/GeoFeaturePyImp.cpp b/src/App/GeoFeaturePyImp.cpp new file mode 100644 index 000000000..fbd3c0b11 --- /dev/null +++ b/src/App/GeoFeaturePyImp.cpp @@ -0,0 +1,40 @@ + +#include "PreCompiled.h" + +#include "App/GeoFeature.h" + +// inclusion of the generated files (generated out of GeoFeaturePy.xml) +#include "GeoFeaturePy.h" +#include "GeoFeaturePy.cpp" + +using namespace App; + +// returns a string which represents the object e.g. when printed in python +std::string GeoFeaturePy::representation(void) const +{ + return std::string(""); +} + + + +PyObject* GeoFeaturePy::getPaths(PyObject * /*args*/) +{ + PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); + return 0; +} + + + + + +PyObject *GeoFeaturePy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int GeoFeaturePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} + + diff --git a/src/App/Part.cpp b/src/App/Part.cpp index 873f7db8d..2d4b24d66 100644 --- a/src/App/Part.cpp +++ b/src/App/Part.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2014 * + * Copyright (c) Juergen Riegel (juergen.riegel@web.de) 2014 * * * * This file is part of the FreeCAD CAx development system. * * * @@ -26,7 +26,9 @@ #ifndef _PreComp_ #endif +#include #include "Part.h" +#include "PartPy.h" //#define new DEBUG_CLIENTBLOCK using namespace App; @@ -47,3 +49,149 @@ Part::~Part(void) { } +DocumentObject* Part::addObject(const char* sType, const char* pObjectName) +{ + DocumentObject* obj = getDocument()->addObject(sType, pObjectName); + if (obj) addObject(obj); + return obj; +} + +void Part::addObject(DocumentObject* obj) +{ + if (!hasObject(obj)) { + std::vector grp = Member.getValues(); + grp.push_back(obj); + Member.setValues(grp); + } +} + +void Part::removeObject(DocumentObject* obj) +{ + std::vector grp = Member.getValues(); + for (std::vector::iterator it = grp.begin(); it != grp.end(); ++it) { + if (*it == obj) { + grp.erase(it); + Member.setValues(grp); + break; + } + } +} + +void Part::removeObjectsFromDocument() +{ + std::vector grp = Member.getValues(); + for (std::vector::iterator it = grp.begin(); it != grp.end(); ++it) { + removeObjectFromDocument(*it); + } +} + +void Part::removeObjectFromDocument(DocumentObject* obj) +{ + // remove all children + if (obj->getTypeId().isDerivedFrom(Part::getClassTypeId())) { + std::vector grp = static_cast(obj)->Member.getValues(); + for (std::vector::iterator it = grp.begin(); it != grp.end(); ++it) { + // recursive call to remove all subgroups + removeObjectFromDocument(*it); + } + } + + this->getDocument()->remObject(obj->getNameInDocument()); +} + +DocumentObject *Part::getObject(const char *Name) const +{ + DocumentObject* obj = getDocument()->getObject(Name); + if (obj && hasObject(obj)) + return obj; + return 0; +} + +bool Part::hasObject(const DocumentObject* obj) const +{ + const std::vector& grp = Member.getValues(); + for (std::vector::const_iterator it = grp.begin(); it != grp.end(); ++it) { + if (*it == obj) + return true; + } + + return false; +} + +bool Part::isChildOf(const Part* group) const +{ + const std::vector& grp = group->Member.getValues(); + for (std::vector::const_iterator it = grp.begin(); it != grp.end(); ++it) { + if (*it == this) + return true; + if ((*it)->getTypeId().isDerivedFrom(Part::getClassTypeId())) { + if (this->isChildOf(static_cast(*it))) + return true; + } + } + + return false; +} + +std::vector Part::getObjects() const +{ + return Member.getValues(); +} + +std::vector Part::getObjectsOfType(const Base::Type& typeId) const +{ + std::vector type; + const std::vector& grp = Member.getValues(); + for (std::vector::const_iterator it = grp.begin(); it != grp.end(); ++it) { + if ( (*it)->getTypeId().isDerivedFrom(typeId)) + type.push_back(*it); + } + + return type; +} + +int Part::countObjectsOfType(const Base::Type& typeId) const +{ + int type=0; + const std::vector& grp = Member.getValues(); + for (std::vector::const_iterator it = grp.begin(); it != grp.end(); ++it) { + if ( (*it)->getTypeId().isDerivedFrom(typeId)) + type++; + } + + return type; +} + + +PyObject *Part::getPyObject() +{ + if (PythonObject.is(Py::_None())){ + // ref counter is set to 1 + PythonObject = Py::Object(new PartPy(this),true); + } + return Py::new_reference_to(PythonObject); +} + +// Python feature --------------------------------------------------------- + +// Not quit sure yet makeing Part derivable in Python is good Idea! +// JR 2014 + +//namespace App { +///// @cond DOXERR +//PROPERTY_SOURCE_TEMPLATE(App::PartPython, App::Part) +//template<> const char* App::PartPython::getViewProviderName(void) const { +// return "Gui::ViewProviderPartPython"; +//} +//template<> PyObject* App::PartPython::getPyObject(void) { +// if (PythonObject.is(Py::_None())) { +// // ref counter is set to 1 +// PythonObject = Py::Object(new FeaturePythonPyT(this),true); +// } +// return Py::new_reference_to(PythonObject); +//} +///// @endcond +// +//// explicit template instantiation +//template class AppExport FeaturePythonT; +//} diff --git a/src/App/Part.h b/src/App/Part.h index a21f08cc7..c2eb2365c 100644 --- a/src/App/Part.h +++ b/src/App/Part.h @@ -50,9 +50,54 @@ public: virtual const char* getViewProviderName(void) const { return "Gui::ViewProviderPart"; } + /** @name Object handling */ + //@{ + /** Adds an object of \a sType with \a pObjectName to the document this group belongs to and + * append it to this group as well. + */ + DocumentObject *addObject(const char* sType, const char* pObjectName); + /* Adds the object \a obj to this group. + */ + void addObject(DocumentObject* obj); + /** Removes an object from this group. + */ + void removeObject(DocumentObject* obj); + /** Removes all children objects from this group and the document. + */ + void removeObjectsFromDocument(); + /** Returns the object of this group with \a Name. If the group doesn't have such an object 0 is returned. + * @note This method might return 0 even if the document this group belongs to contains an object with this name. + */ + DocumentObject *getObject(const char* Name) const; + /** + * Checks whether the object \a obj is part of this group. + */ + bool hasObject(const DocumentObject* obj) const; + /** + * Checks whether this group object is a child (or sub-child) + * of the given group object. + */ + bool isChildOf(const Part*) const; + /** Returns a list of all objects this group does have. + */ + std::vector getObjects() const; + /** Returns a list of all objects of \a typeId this group does have. + */ + std::vector getObjectsOfType(const Base::Type& typeId) const; + /** Returns the number of objects of \a typeId this group does have. + */ + int countObjectsOfType(const Base::Type& typeId) const; + //@} + + virtual PyObject *getPyObject(void); + +private: + void removeObjectFromDocument(DocumentObject*); }; +//typedef App::FeaturePythonT PartPython; + } //namespace App diff --git a/src/App/PartPy.xml b/src/App/PartPy.xml new file mode 100644 index 000000000..eacb638f5 --- /dev/null +++ b/src/App/PartPy.xml @@ -0,0 +1,48 @@ + + + + + + This class handles document objects in Part + + + + Create and add an object with given type and name to the Part + + + + + Add an object to the Part + + + + + Remove an object from the Part + + + + + Remove all child objects from the Part and document + + + + + Return the object with the given name + + + + + Checks if the Part has a given object + + + + + diff --git a/src/App/PartPyImp.cpp b/src/App/PartPyImp.cpp new file mode 100644 index 000000000..16509084b --- /dev/null +++ b/src/App/PartPyImp.cpp @@ -0,0 +1,151 @@ + +#include "PreCompiled.h" + +#include "App/Part.h" + +// inclusion of the generated files (generated out of PartPy.xml) +#include "PartPy.h" +#include "PartPy.cpp" + +using namespace App; + +// returns a string which represents the object e.g. when printed in python +std::string PartPy::representation(void) const +{ + return std::string(""); +} + + + +PyObject* PartPy::newObject(PyObject *args) +{ + char *sType,*sName=0; + if (!PyArg_ParseTuple(args, "s|s", &sType,&sName)) // convert args: Python->C + return NULL; + + DocumentObject *object = getPartPtr()->addObject(sType, sName); + if ( object ) { + return object->getPyObject(); + } + else { + PyErr_Format(PyExc_Exception, "Cannot create object of type '%s'", sType); + return NULL; + } +} + +PyObject* PartPy::addObject(PyObject *args) +{ + PyObject *object; + if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) // convert args: Python->C + return NULL; // NULL triggers exception + + DocumentObjectPy* docObj = static_cast(object); + if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->getNameInDocument()) { + PyErr_SetString(PyExc_Exception, "Cannot add an invalid object"); + return NULL; + } + if (docObj->getDocumentObjectPtr()->getDocument() != getPartPtr()->getDocument()) { + PyErr_SetString(PyExc_Exception, "Cannot add an object from another document to this Part"); + return NULL; + } + if (docObj->getDocumentObjectPtr() == this->getPartPtr()) { + PyErr_SetString(PyExc_Exception, "Cannot add a Part to itself"); + return NULL; + } + if (docObj->getDocumentObjectPtr()->getTypeId().isDerivedFrom(Part::getClassTypeId())) { + PyErr_SetString(PyExc_Exception, "Cannot add a Part to a Part"); + return NULL; + } + + Part* part = getPartPtr(); + + part->addObject(docObj->getDocumentObjectPtr()); + Py_Return; +} + +PyObject* PartPy::removeObject(PyObject *args) +{ + PyObject *object; + if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) // convert args: Python->C + return NULL; // NULL triggers exception + + DocumentObjectPy* docObj = static_cast(object); + if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->getNameInDocument()) { + PyErr_SetString(PyExc_Exception, "Cannot remove an invalid object"); + return NULL; + } + if (docObj->getDocumentObjectPtr()->getDocument() != getPartPtr()->getDocument()) { + PyErr_SetString(PyExc_Exception, "Cannot remove an object from another document from this group"); + return NULL; + } + + Part* part = getPartPtr(); + + + part->removeObject(docObj->getDocumentObjectPtr()); + Py_Return; +} + +PyObject* PartPy::removeObjectsFromDocument(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) // convert args: Python->C + return NULL; // NULL triggers exception + + getPartPtr()->removeObjectsFromDocument(); + Py_Return; +} + +PyObject* PartPy::getObject(PyObject *args) +{ + char* pcName; + if (!PyArg_ParseTuple(args, "s", &pcName)) // convert args: Python->C + return NULL; // NULL triggers exception + + DocumentObject* obj = getPartPtr()->getObject(pcName); + if ( obj ) { + return obj->getPyObject(); + } else { + Py_Return; + } +} + +PyObject* PartPy::hasObject(PyObject *args) +{ + PyObject *object; + if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) // convert args: Python->C + return NULL; // NULL triggers exception + + DocumentObjectPy* docObj = static_cast(object); + if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->getNameInDocument()) { + PyErr_SetString(PyExc_Exception, "Cannot check an invalid object"); + return NULL; + } + if (docObj->getDocumentObjectPtr()->getDocument() != getPartPtr()->getDocument()) { + PyErr_SetString(PyExc_Exception, "Cannot check an object from another document with this group"); + return NULL; + } + + if (getPartPtr()->hasObject(docObj->getDocumentObjectPtr())) { + Py_INCREF(Py_True); + return Py_True; + } + else { + Py_INCREF(Py_False); + return Py_False; + } +} + + + + +PyObject *PartPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int PartPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} + +