DocumentObject.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) Jürgen Riegel          (juergen.riegel@web.de)          *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 #endif
00028 
00029 #include <Base/Writer.h>
00030 
00031 #include "Document.h"
00032 #include "DocumentObject.h"
00033 #include "DocumentObjectPy.h"
00034 #include "PropertyLinks.h"
00035 #define new DEBUG_CLIENTBLOCK
00036 using namespace App;
00037 
00038 
00039 PROPERTY_SOURCE(App::DocumentObject, App::PropertyContainer)
00040 
00041 DocumentObjectExecReturn *DocumentObject::StdReturn = 0;
00042 
00043 //===========================================================================
00044 // DocumentObject
00045 //===========================================================================
00046 
00047 DocumentObject::DocumentObject(void)
00048   : _pDoc(0),pcNameInDocument(0)
00049 {
00050     // define Label of type 'Output' to avoid being marked as touched after relabeling
00051     ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)");
00052 }
00053 
00054 DocumentObject::~DocumentObject(void)
00055 {
00056     if (!PythonObject.is(Py::_None())){
00057         // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed 
00058         // Python object or not. In the constructor we forced the wrapper to own the object so we need
00059         // not to dec'ref the Python object any more.
00060         // But we must still invalidate the Python object because it need not to be
00061         // destructed right now because the interpreter can own several references to it.
00062         Base::PyObjectBase* obj = (Base::PyObjectBase*)PythonObject.ptr();
00063         // Call before decrementing the reference counter, otherwise a heap error can occur
00064         obj->setInvalid();
00065     }
00066 }
00067 
00068 namespace App {
00069 class ObjectExecution
00070 {
00071 public:
00072     ObjectExecution(DocumentObject* o) : obj(o)
00073     { obj->StatusBits.set(3); }
00074     ~ObjectExecution()
00075     { obj->StatusBits.reset(3); }
00076 private:
00077     DocumentObject* obj;
00078 };
00079 }
00080 
00081 App::DocumentObjectExecReturn *DocumentObject::recompute(void)
00082 {
00083     // set/unset the execution bit
00084     ObjectExecution exe(this);
00085     return this->execute();
00086 }
00087 
00088 DocumentObjectExecReturn *DocumentObject::execute(void)
00089 {
00090     return DocumentObject::StdReturn;
00091 }
00092 
00093 short DocumentObject::mustExecute(void) const
00094 {
00095     return (isTouched() ? 1 : 0);
00096 }
00097 
00098 const char* DocumentObject::getStatusString(void) const
00099 {
00100     if (isError()) {
00101         const char* text = getDocument()->getErrorDescription(this);
00102         return text ? text : "Error";
00103     }
00104     else if (isTouched())
00105         return "Touched";
00106     else
00107         return "Valid";
00108 }
00109 
00110 const char *DocumentObject::getNameInDocument(void) const
00111 {
00112     // Note: It can happen that we query the internal name of an object even if it is not
00113     // part of a document (anymore). This is the case e.g. if we have a reference in Python 
00114     // to an object that has been removed from the document. In this case we should rather
00115     // return 0.
00116     //assert(pcNameInDocument);
00117     if (!pcNameInDocument) return 0;
00118     return pcNameInDocument->c_str();
00119 }
00120 
00121 std::vector<DocumentObject*> DocumentObject::getOutList(void) const
00122 {
00123     std::vector<Property*> List;
00124     std::vector<DocumentObject*> ret;
00125     getPropertyList(List);
00126     for (std::vector<Property*>::const_iterator It = List.begin();It != List.end(); ++It) {
00127         if ((*It)->isDerivedFrom(PropertyLinkList::getClassTypeId())) {
00128             const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkList*>(*It)->getValues();
00129             for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
00130                 if (*It2)
00131                     ret.push_back(*It2);
00132             }
00133         }
00134         else if ((*It)->isDerivedFrom(PropertyLinkSubList::getClassTypeId())) {
00135             const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkSubList*>(*It)->getValues();
00136             for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
00137                 if (*It2)
00138                     ret.push_back(*It2);
00139             }
00140         }
00141         else if ((*It)->isDerivedFrom(PropertyLink::getClassTypeId())) {
00142             if (static_cast<PropertyLink*>(*It)->getValue())
00143                 ret.push_back(static_cast<PropertyLink*>(*It)->getValue());
00144         }
00145         else if ((*It)->isDerivedFrom(PropertyLinkSub::getClassTypeId())) {
00146             if (static_cast<PropertyLinkSub*>(*It)->getValue())
00147                 ret.push_back(static_cast<PropertyLinkSub*>(*It)->getValue());
00148         }
00149     }
00150     return ret;
00151 }
00152 
00153 std::vector<App::DocumentObject*> DocumentObject::getInList(void) const
00154 {
00155     if (_pDoc)
00156         return _pDoc->getInList(this);
00157     else
00158         return std::vector<App::DocumentObject*>();
00159 }
00160 
00161 void DocumentObject::onLostLinkToObject(DocumentObject*)
00162 {
00163 
00164 }
00165 
00166 App::Document *DocumentObject::getDocument(void) const
00167 {
00168     return _pDoc;
00169 }
00170 
00171 void DocumentObject::setDocument(App::Document* doc)
00172 {
00173     _pDoc=doc;
00174 }
00175 
00176 void DocumentObject::onBeforeChange(const Property* prop)
00177 {
00178     if (_pDoc)
00179         _pDoc->onBeforeChangeProperty(this,prop);
00180 }
00181 
00183 void DocumentObject::onChanged(const Property* prop)
00184 {
00185     if (_pDoc)
00186         _pDoc->onChangedProperty(this,prop);
00187     if (prop->getType() & Prop_Output)
00188         return;
00189     // set object touched
00190     StatusBits.set(0);
00191 }
00192 
00193 PyObject *DocumentObject::getPyObject(void)
00194 {
00195     if (PythonObject.is(Py::_None())) {
00196         // ref counter is set to 1
00197         PythonObject = Py::Object(new DocumentObjectPy(this),true);
00198     }
00199     return Py::new_reference_to(PythonObject); 
00200 }
00201 
00202 std::vector<PyObject *> DocumentObject::getPySubObjects(const std::vector<std::string>&) const
00203 {
00204     // default implementation returns nothing
00205     return std::vector<PyObject *>();
00206 }
00207 
00208 void DocumentObject::touch(void)
00209 {
00210     StatusBits.set(0);
00211 }
00212 
00213 void DocumentObject::Save (Base::Writer &writer) const
00214 {
00215     writer.ObjectName = this->getNameInDocument();
00216     App::PropertyContainer::Save(writer);
00217 }

Generated on Wed Nov 23 19:00:08 2011 for FreeCAD by  doxygen 1.6.1