App/DocumentPyImp.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) Jürgen Riegel          (juergen.riegel@web.de) 2007     *
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 # include <sstream>
00028 #endif
00029 
00030 #include "Document.h"
00031 #include <Base/FileInfo.h>
00032 #include <Base/PyTools.h>
00033 #include "DocumentObject.h"
00034 #include "DocumentObjectPy.h"
00035 
00036 // inclusion of the generated files (generated By DocumentPy.xml)
00037 #include "DocumentPy.h"
00038 #include "DocumentPy.cpp"
00039 #include <boost/regex.hpp>
00040 
00041 using namespace App;
00042 
00043 
00044 // returns a string which represent the object e.g. when printed in python
00045 std::string DocumentPy::representation(void) const
00046 {
00047     std::stringstream str;
00048     str << "<Document object at " << getDocumentPtr() << ">";
00049 
00050     return str.str();
00051 }
00052 
00053 PyObject*  DocumentPy::save(PyObject * args)
00054 {
00055     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00056         return NULL;                    // NULL triggers exception 
00057     if (!getDocumentPtr()->save()) {
00058         PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set");
00059         return NULL;
00060     }
00061 
00062     const char* filename = getDocumentPtr()->FileName.getValue();
00063     Base::FileInfo fi(filename);
00064     if (!fi.isReadable()) {
00065         PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
00066         return NULL;
00067     }
00068 
00069     Py_Return;
00070 }
00071 
00072 PyObject*  DocumentPy::restore(PyObject * args)
00073 {
00074     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00075         return NULL;                    // NULL triggers exception 
00076     const char* filename = getDocumentPtr()->FileName.getValue();
00077     if (!filename || *filename == '\0') {
00078         PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set");
00079         return NULL;
00080     }
00081     Base::FileInfo fi(filename);
00082     if (!fi.isReadable()) {
00083         PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
00084         return NULL;
00085     }
00086     try {
00087         getDocumentPtr()->restore();
00088     } catch (...) {
00089         PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename);
00090         return NULL;
00091     }
00092     Py_Return;
00093 }
00094 
00095 PyObject*  DocumentPy::addObject(PyObject *args)
00096 {
00097     char *sType,*sName=0;
00098     PyObject* obj=0;
00099     PyObject* view=0;
00100     if (!PyArg_ParseTuple(args, "s|sOO", &sType,&sName,&obj,&view))     // convert args: Python->C
00101         return NULL;                                         // NULL triggers exception 
00102 
00103     DocumentObject *pcFtr;
00104 
00105     pcFtr = getDocumentPtr()->addObject(sType,sName);
00106     if (pcFtr) {
00107         // Allows to hide the handling with Proxy in client python code
00108         if (obj) {
00109             try {
00110                 // the python binding class to the document object
00111                 Py::Object pyftr = Py::asObject(pcFtr->getPyObject());
00112                 // 'pyobj' is the python class with the implementation for DocumentObject
00113                 Py::Object pyobj(obj);
00114                 if (pyobj.hasAttr("__object__")) {
00115                     pyobj.setAttr("__object__", pyftr);
00116                 }
00117                 pyftr.setAttr("Proxy", pyobj);
00118 
00119                 // if a document class is set we also need a view provider defined which must be
00120                 // something different to None
00121                 Py::Object pyvp;
00122                 if (view)
00123                     pyvp = Py::Object(view);
00124                 if (pyvp.isNone())
00125                     pyvp = Py::Int(1);
00126                 // 'pyvp' is the python class with the implementation for ViewProvider
00127                 if (pyvp.hasAttr("__vobject__")) {
00128                     pyvp.setAttr("__vobject__", pyftr.getAttr("ViewObject"));
00129                 }
00130                 pyftr.getAttr("ViewObject").setAttr("Proxy", pyvp);
00131                 return Py::new_reference_to(Py::None());
00132             }
00133             catch (Py::Exception& e) {
00134                 e.clear();
00135             }
00136         }
00137         return pcFtr->getPyObject();
00138     }
00139     else {
00140         std::stringstream str;
00141         str << "No document object found of type '" << sType << "'" << std::ends;
00142         throw Py::Exception(PyExc_Exception,str.str());
00143     }
00144 }
00145 
00146 PyObject*  DocumentPy::removeObject(PyObject *args)
00147 {
00148     char *sName;
00149     if (!PyArg_ParseTuple(args, "s",&sName))     // convert args: Python->C
00150         return NULL;                             // NULL triggers exception
00151 
00152 
00153     DocumentObject *pcFtr = getDocumentPtr()->getObject(sName);
00154     if(pcFtr) {
00155         getDocumentPtr()->remObject( sName );
00156         Py_Return;
00157     } else {
00158         std::stringstream str;
00159         str << "No document object found with name '" << sName << "'" << std::ends;
00160         throw Py::Exception(PyExc_Exception,str.str());
00161     }
00162 }
00163 
00164 PyObject*  DocumentPy::copyObject(PyObject *args)
00165 {
00166     PyObject *obj, *rec=0;
00167     if (!PyArg_ParseTuple(args, "O!|O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec))
00168         return NULL;    // NULL triggers exception
00169 
00170     DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(obj);
00171     DocumentObject* copy = getDocumentPtr()->copyObject(docObj->getDocumentObjectPtr(), rec==Py_True);
00172     if (copy) {
00173         return copy->getPyObject();
00174     }
00175     else {
00176         std::string str("Failed to copy the object");
00177         throw Py::Exception(PyExc_Exception,str);
00178     }
00179 }
00180 
00181 PyObject*  DocumentPy::moveObject(PyObject *args)
00182 {
00183     PyObject *obj, *rec=0;
00184     if (!PyArg_ParseTuple(args, "O!|O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec))
00185         return NULL;    // NULL triggers exception
00186 
00187     DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(obj);
00188     DocumentObject* move = getDocumentPtr()->moveObject(docObj->getDocumentObjectPtr(), rec==Py_True);
00189     if (move) {
00190         return move->getPyObject();
00191     }
00192     else {
00193         std::string str("Failed to move the object");
00194         throw Py::Exception(PyExc_Exception,str);
00195     }
00196 }
00197 
00198 PyObject*  DocumentPy::openTransaction(PyObject *args)
00199 {
00200     char *pstr=0;
00201     if (!PyArg_ParseTuple(args, "|s", &pstr))     // convert args: Python->C 
00202         return NULL;                             // NULL triggers exception 
00203 
00204     getDocumentPtr()->openTransaction(pstr); 
00205     Py_Return; 
00206 }
00207 
00208 PyObject*  DocumentPy::abortTransaction(PyObject * args)
00209 {
00210     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00211         return NULL;                    // NULL triggers exception 
00212     getDocumentPtr()->abortTransaction();
00213     Py_Return;
00214 }
00215 
00216 PyObject*  DocumentPy::commitTransaction(PyObject * args)
00217 {
00218     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00219         return NULL;                    // NULL triggers exception 
00220     getDocumentPtr()->commitTransaction();
00221     Py_Return;
00222 }
00223 
00224 PyObject*  DocumentPy::undo(PyObject * args)
00225 {
00226     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00227         return NULL;                    // NULL triggers exception 
00228     if (getDocumentPtr()->getAvailableUndos())
00229         getDocumentPtr()->undo();
00230     Py_Return;
00231 }
00232 
00233 PyObject*  DocumentPy::redo(PyObject * args)
00234 {
00235     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00236         return NULL;                    // NULL triggers exception 
00237     if (getDocumentPtr()->getAvailableRedos())
00238         getDocumentPtr()->redo();
00239     Py_Return;
00240 }
00241 
00242 PyObject*  DocumentPy::clearUndos(PyObject * args)
00243 {
00244     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00245         return NULL;                    // NULL triggers exception 
00246     getDocumentPtr()->clearUndos();
00247     Py_Return;
00248 }
00249 
00250 PyObject*  DocumentPy::recompute(PyObject * args)
00251 {
00252     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00253         return NULL;                    // NULL triggers exception 
00254     getDocumentPtr()->recompute();
00255     Py_Return;
00256 }
00257 
00258 PyObject*  DocumentPy::getObject(PyObject *args)
00259 {
00260     char *sName;
00261     if (!PyArg_ParseTuple(args, "s",&sName))     // convert args: Python->C 
00262         return NULL;                             // NULL triggers exception 
00263 
00264     DocumentObject *pcFtr = getDocumentPtr()->getObject(sName);
00265     if (pcFtr)
00266         return pcFtr->getPyObject();
00267     else
00268         Py_Return;
00269 }
00270 
00271 PyObject*  DocumentPy::getObjectsByLabel(PyObject *args)
00272 {
00273     char *sName;
00274     if (!PyArg_ParseTuple(args, "s",&sName))     // convert args: Python->C 
00275         return NULL;                             // NULL triggers exception 
00276 
00277     Py::List list;
00278     std::string name = sName;
00279     std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
00280     for (std::vector<DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
00281         if (name == (*it)->Label.getValue())
00282             list.append(Py::asObject((*it)->getPyObject()));
00283     }
00284 
00285     return Py::new_reference_to(list);
00286 }
00287 
00288 PyObject*  DocumentPy::findObjects(PyObject *args)
00289 {
00290     char *sType="App::DocumentObject", *sName=0;
00291     if (!PyArg_ParseTuple(args, "|ss",&sType, &sName))     // convert args: Python->C 
00292         return NULL;                                      // NULL triggers exception 
00293 
00294     Base::Type type = Base::Type::fromName(sType);
00295     if (type == Base::Type::badType()) {
00296         PyErr_Format(PyExc_Exception, "'%s' is not a valid type", sType);
00297         return NULL;
00298     }
00299 
00300     if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) {
00301         PyErr_Format(PyExc_Exception, "Type '%s' does not inherit from 'App::DocumentObject'", sType);
00302         return NULL;
00303     }
00304 
00305     std::vector<DocumentObject*> res;
00306     std::vector<DocumentObject*> objs = getDocumentPtr()->getObjectsOfType(type);
00307 
00308     if (sName) {
00309         try {
00310             boost::regex rx(sName);
00311             boost::cmatch what;
00312             for (std::vector<DocumentObject*>::const_iterator It = objs.begin();It != objs.end();++It) {
00313                 if (boost::regex_match((*It)->getNameInDocument(), what, rx))
00314                     res.push_back(*It);
00315             }
00316         }
00317         catch (const boost::regex_error& e) {
00318             PyErr_SetString(PyExc_RuntimeError, e.what());
00319             return 0;
00320         }
00321     }
00322     else {
00323         res = objs;
00324     }
00325 
00326     Py_ssize_t index=0;
00327     PyObject* list = PyList_New((Py_ssize_t)res.size()); 
00328     for (std::vector<DocumentObject*>::const_iterator It = res.begin();It != res.end();++It, index++)
00329         PyList_SetItem(list, index, (*It)->getPyObject());
00330     return list;
00331 }
00332 
00333 Py::Object DocumentPy::getActiveObject(void) const
00334 {
00335     DocumentObject *pcFtr = getDocumentPtr()->getActiveObject();
00336     if(pcFtr)
00337         return Py::Object(pcFtr->getPyObject(), true);
00338     return Py::None();
00339 }
00340 
00341 PyObject*  DocumentPy::supportedTypes(PyObject *args)
00342 {
00343     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C 
00344         return NULL;                    // NULL triggers exception
00345     
00346     std::vector<Base::Type> ary;
00347     Base::Type::getAllDerivedFrom(App::DocumentObject::getClassTypeId(), ary);
00348     Py::List res;
00349     for (std::vector<Base::Type>::iterator it = ary.begin(); it != ary.end(); ++it)
00350         res.append(Py::String(it->getName()));
00351     return Py::new_reference_to(res);
00352 }
00353 
00354 Py::List DocumentPy::getObjects(void) const 
00355 {
00356     std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
00357     Py::List res;
00358 
00359     for (std::vector<DocumentObject*>::const_iterator It = objs.begin();It != objs.end();++It)
00360         //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter
00361         res.append(Py::Object((*It)->getPyObject(), true));
00362 
00363     return res;
00364 }
00365 
00366 Py::Int DocumentPy::getUndoMode(void) const
00367 {
00368     return Py::Int(getDocumentPtr()->getUndoMode());
00369 }
00370 
00371 void  DocumentPy::setUndoMode(Py::Int arg)
00372 {
00373     getDocumentPtr()->setUndoMode(arg); 
00374 }
00375 
00376 Py::Int DocumentPy::getUndoRedoMemSize(void) const
00377 {
00378     return Py::Int((long)getDocumentPtr()->getUndoMemSize());
00379 }
00380 
00381 Py::Int DocumentPy::getUndoCount(void) const
00382 {
00383     return Py::Int((long)getDocumentPtr()->getAvailableUndos());
00384 }
00385 
00386 Py::Int DocumentPy::getRedoCount(void) const
00387 {
00388     return Py::Int((long)getDocumentPtr()->getAvailableRedos());
00389 }
00390 
00391 Py::List DocumentPy::getUndoNames(void) const
00392 {
00393     std::vector<std::string> vList = getDocumentPtr()->getAvailableUndoNames();
00394     Py::List res;
00395 
00396     for (std::vector<std::string>::const_iterator It = vList.begin();It!=vList.end();++It)
00397         res.append(Py::String(*It));
00398 
00399     return res;
00400 }
00401 
00402 Py::List DocumentPy::getRedoNames(void) const
00403 {
00404     std::vector<std::string> vList = getDocumentPtr()->getAvailableRedoNames();
00405     Py::List res;
00406 
00407     for (std::vector<std::string>::const_iterator It = vList.begin();It!=vList.end();++It)
00408         res.append(Py::String(*It));
00409 
00410     return res;
00411 }
00412 
00413 Py::String  DocumentPy::getDependencyGraph(void) const
00414 {
00415     std::stringstream out;
00416     getDocumentPtr()->writeDependencyGraphViz(out);
00417     return Py::String(out.str());
00418 }
00419 
00420 Py::String DocumentPy::getName(void) const
00421 {
00422     return Py::String(getDocumentPtr()->getName());
00423 }
00424 
00425 PyObject* DocumentPy::getTempFileName(PyObject *args)
00426 {
00427     PyObject *value;
00428     if (!PyArg_ParseTuple(args, "O",&value))
00429         return NULL;    // NULL triggers exception
00430 
00431     std::string string;
00432     if (PyUnicode_Check(value)) {
00433         PyObject* unicode = PyUnicode_AsUTF8String(value);
00434         string = PyString_AsString(unicode);
00435         Py_DECREF(unicode);
00436     }
00437     else if (PyString_Check(value)) {
00438         string = PyString_AsString(value);
00439     }
00440     else {
00441         std::string error = std::string("type must be a string!");
00442         error += value->ob_type->tp_name;
00443         throw Py::TypeError(error);
00444     }
00445 
00446     // search for a temp file name in the document transient directory 
00447     Base::FileInfo fileName(Base::FileInfo::getTempFileName
00448         (string.c_str(),getDocumentPtr()->TransientDir.getValue()));
00449     // delete the created file, we need only the name...
00450     fileName.deleteFile();
00451 
00452     PyObject *p = PyUnicode_DecodeUTF8(fileName.filePath().c_str(),fileName.filePath().size(),0);
00453     if (!p) throw Base::Exception("UTF8 conversion failure at PropertyString::getPyObject()");
00454     return p;
00455 }
00456 
00457 PyObject *DocumentPy::getCustomAttributes(const char* attr) const
00458 {
00459     // Note: Here we want to return only a document object if its
00460     // name matches 'attr'. However, it is possible to have an object
00461     // with the same name as an attribute. If so, we return 0 as other-
00462     // wise it wouldn't be possible to address this attribute any more.
00463     // The object must then be addressed by the getObject() method directly.
00464     App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
00465     if (prop) return 0;
00466     if (this->ob_type->tp_dict == NULL) {
00467         if (PyType_Ready(this->ob_type) < 0)
00468             return 0;
00469     }
00470     PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
00471     if (item) return 0;
00472     // search for an object with this name
00473     DocumentObject* obj = getDocumentPtr()->getObject(attr);
00474     return (obj ? obj->getPyObject() : 0);
00475 }
00476 
00477 int DocumentPy::setCustomAttributes(const char* attr, PyObject *)
00478 {
00479     // Note: Here we want to return only a document object if its
00480     // name matches 'attr'. However, it is possible to have an object
00481     // with the same name as an attribute. If so, we return 0 as other-
00482     // wise it wouldn't be possible to address this attribute any more.
00483     // The object must then be addressed by the getObject() method directly.
00484     App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
00485     if (prop) return 0;
00486     if (this->ob_type->tp_dict == NULL) {
00487         if (PyType_Ready(this->ob_type) < 0)
00488             return 0;
00489     }
00490     PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
00491     if (item) return 0;
00492     DocumentObject* obj = getDocumentPtr()->getObject(attr);
00493     if (obj)
00494     {
00495         std::stringstream str;
00496         str << "'Document' object attribute '" << attr 
00497             << "' must not be set this way" << std::ends;
00498         throw Py::AttributeError(str.str());
00499     }
00500     
00501     return 0;
00502 }

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