App/ApplicationPy.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   (c) Juergen Riegel (juergen.riegel@web.de) 2002                       *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU Library General Public License (LGPL)   *
00008  *   as published by the Free Software Foundation; either version 2 of     *
00009  *   the License, or (at your option) any later version.                   *
00010  *   for detail see the LICENCE text file.                                 *
00011  *                                                                         *
00012  *   FreeCAD is distributed in the hope that it will be useful,            *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU Library General Public License for more details.                  *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU Library General Public     *
00018  *   License along with FreeCAD; if not, write to the Free Software        *
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
00020  *   USA                                                                   *
00021  *                                                                         *
00022  *   Juergen Riegel 2002                                                   *
00023  ***************************************************************************/
00024 
00025 
00026 
00027 #include "PreCompiled.h"
00028 
00029 #ifndef _PreComp_
00030 # include <stdexcept>
00031 #endif
00032 
00033 
00034 #include "Application.h"
00035 #include "Document.h"
00036 #include "DocumentPy.h"
00037 #include "DocumentObserverPython.h"
00038 
00039 // FreeCAD Base header
00040 #include <Base/Interpreter.h>
00041 #include <Base/Exception.h>
00042 #include <Base/Parameter.h>
00043 #include <Base/Console.h>
00044 #include <Base/Factory.h>
00045 #include <Base/FileInfo.h>
00046 #include <Base/UnitsApi.h>
00047 
00048 #define new DEBUG_CLIENTBLOCK
00049 //using Base::GetConsole;
00050 using namespace Base;
00051 using namespace App;
00052 
00053 
00054 
00055 //**************************************************************************
00056 // Python stuff
00057 
00058 // Application Methods                                          // Methods structure
00059 PyMethodDef Application::Methods[] = {
00060     {"ParamGet",       (PyCFunction) Application::sGetParam,       1,
00061      "Get parameters by path"},
00062     {"Version",        (PyCFunction) Application::sGetVersion,     1,
00063      "Print the version to the output."},
00064     {"ConfigGet",      (PyCFunction) Application::sGetConfig,      1,
00065      "ConfigGet([string]) -- Get the value for the given key.\n"
00066      "If no key is given the complete configuration is dumped to\n"
00067      "the output."},
00068     {"ConfigSet",      (PyCFunction) Application::sSetConfig,      1,
00069      "ConfigSet(string, string) -- Set the given key to the given value."},
00070     {"ConfigDump",     (PyCFunction) Application::sDumpConfig,     1,
00071      "Dump the configuration to the output."},
00072     {"addImportType",  (PyCFunction) Application::sAddImportType,  1,
00073      "Register filetype for import"},
00074     {"getImportType",  (PyCFunction) Application::sGetImportType,  1,
00075      "Get the name of the module that can import the filetype"},
00076     {"EndingAdd",      (PyCFunction) Application::sAddImportType  ,1, // deprecated
00077      "deprecated -- use addImportType"},
00078     {"EndingGet",      (PyCFunction) Application::sGetImportType  ,1, // deprecated
00079      "deprecated -- use getImportType"},
00080     {"addExportType",  (PyCFunction) Application::sAddExportType  ,1,
00081      "Register filetype for export"},
00082     {"getExportType",  (PyCFunction) Application::sGetExportType  ,1,
00083      "Get the name of the module that can export the filetype"},
00084     {"getResourceDir", (PyCFunction) Application::sGetResourceDir  ,1,
00085      "Get the root directory of all resources"},
00086     {"getHomePath",    (PyCFunction) Application::sGetHomePath  ,1,
00087      "Get the home path, i.e. the parent directory of the executable"},
00088 
00089     {"loadFile",       (PyCFunction) Application::sLoadFile,   1,
00090      "loadFile(string=filename,[string=module]) -> None\n\n"
00091      "Loads an arbitrary file by delegating to the given Python module:\n"
00092      "* If no module is given it will be determined by the file extension.\n"
00093      "* If more than one module can load a file the first one one will be taken.\n"
00094      "* If no module exists to load the file an exception will be raised."},
00095     {"open",   (PyCFunction) Application::sOpenDocument,   1,
00096      "See openDocument(string)"},
00097     {"openDocument",   (PyCFunction) Application::sOpenDocument,   1,
00098      "openDocument(string) -> object\n\n"
00099      "Create a document and load the project file into the document.\n"
00100      "The string argument must point to an existing file. If the file doesn't exist\n"
00101      "or the file cannot be loaded an I/O exception is thrown. In this case the\n"
00102      "document is kept alive."},
00103 //  {"saveDocument",   (PyCFunction) Application::sSaveDocument,   1,
00104 //   "saveDocument(string) -- Save the document to a file."},
00105 //  {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, 1},
00106     {"newDocument",    (PyCFunction) Application::sNewDocument,    1,
00107      "newDocument([string]) -> object\n\n"
00108      "Create a new document with a given name.\n"
00109      "The document name must be unique which\n"
00110      "is checked automatically."},
00111     {"closeDocument",  (PyCFunction) Application::sCloseDocument,  1,
00112      "closeDocument(string) -> None\n\n"
00113      "Close the document with a given name."},
00114     {"activeDocument", (PyCFunction) Application::sActiveDocument, 1,
00115      "activeDocument() -> object or None\n\n"
00116      "Return the active document or None if there is no one."},
00117     {"setActiveDocument",(PyCFunction) Application::sSetActiveDocument, 1,
00118      "setActiveDocement(string) -> None\n\n"
00119      "Set the active document by its name."},
00120     {"getDocument",    (PyCFunction) Application::sGetDocument,    1,
00121      "getDocument(string) -> object\n\n"
00122      "Get a document by its name or raise an exception\n"
00123      "if there is no document with the given name."},
00124     {"listDocuments",  (PyCFunction) Application::sListDocuments  ,1,
00125      "listDocuments() -> list\n\n"
00126      "Return a list of names of all documents."},
00127     {"addDocumentObserver",  (PyCFunction) Application::sAddDocObserver  ,1,
00128      "addDocumentObserver() -> None\n\n"
00129      "Add an observer to get notified about changes on documents."},
00130     {"removeDocumentObserver",  (PyCFunction) Application::sRemoveDocObserver  ,1,
00131      "removeDocumentObserver() -> None\n\n"
00132      "Remove an added document observer."},
00133 
00134     {NULL, NULL, 0, NULL}               /* Sentinel */
00135 };
00136 
00137 
00138 PyObject* Application::sLoadFile(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00139 {
00140     char *path, *doc="",*mod="";
00141     if (!PyArg_ParseTuple(args, "s|ss", &path, &doc, &mod))     // convert args: Python->C
00142         return 0;                             // NULL triggers exception
00143     try {
00144         Base::FileInfo fi(path);
00145         if (!fi.isFile() || !fi.exists()) {
00146             PyErr_Format(PyExc_IOError, "File %s doesn't exist.", path);
00147             return 0;
00148         }
00149 
00150         std::string module = mod;
00151         if (module.empty()) {
00152             std::string ext = fi.extension(false);
00153             std::vector<std::string> modules = GetApplication().getImportModules(ext.c_str());
00154             if (modules.empty()) {
00155                 PyErr_Format(PyExc_IOError, "Filetype %s is not supported.", ext.c_str());
00156                 return 0;
00157             }
00158             else {
00159                 module = modules.front();
00160             }
00161         }
00162 
00163         std::stringstream str;
00164         str << "import " << module << std::endl;
00165         if (fi.hasExtension("FCStd"))
00166             str << module << ".openDocument('" << path << "')" << std::endl;
00167         else
00168             str << module << ".insert('" << path << "','" << doc << "')" << std::endl;
00169         Base::Interpreter().runString(str.str().c_str());
00170         Py_Return;
00171     }
00172     catch (const Base::Exception& e) {
00173         PyErr_SetString(PyExc_IOError, e.what());
00174         return 0;
00175     }
00176     catch (const std::exception& e) {
00177         // might be subclass from zipios
00178         PyErr_Format(PyExc_IOError, "Invalid project file %s: %s", path, e.what());
00179         return 0;
00180     }
00181 }
00182 
00183 PyObject* Application::sOpenDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00184 {
00185     char *pstr;
00186     if (!PyArg_ParseTuple(args, "s", &pstr))     // convert args: Python->C
00187         return NULL;                             // NULL triggers exception
00188     try {
00189         // return new document
00190         return (GetApplication().openDocument(pstr)->getPyObject());
00191     }
00192     catch (const Base::Exception& e) {
00193         PyErr_SetString(PyExc_IOError, e.what());
00194         return 0L;
00195     }
00196     catch (const std::exception& e) {
00197         // might be subclass from zipios
00198         PyErr_Format(PyExc_IOError, "Invalid project file %s: %s\n", pstr, e.what());
00199         return 0L;
00200     }
00201 }
00202 
00203 PyObject* Application::sNewDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00204 {
00205     char *docName = 0;
00206     char *usrName = 0;
00207     if (!PyArg_ParseTuple(args, "|ss", &docName, &usrName))     // convert args: Python->C
00208         return NULL;                             // NULL triggers exception
00209 
00210     PY_TRY {
00211         return GetApplication().newDocument(docName, usrName)->getPyObject();
00212     }PY_CATCH;
00213 }
00214 
00215 PyObject* Application::sSetActiveDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00216 {
00217     char *pstr = 0;
00218     if (!PyArg_ParseTuple(args, "s", &pstr))     // convert args: Python->C
00219         return NULL;                             // NULL triggers exception
00220 
00221     try {
00222         GetApplication().setActiveDocument(pstr);
00223     }
00224     catch (const Base::Exception& e) {
00225         PyErr_SetString(PyExc_Exception, e.what());
00226         return NULL;
00227     }
00228 
00229     Py_Return;
00230 }
00231 
00232 PyObject* Application::sCloseDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00233 {
00234     char *pstr = 0;
00235     if (!PyArg_ParseTuple(args, "s", &pstr))     // convert args: Python->C
00236         return NULL;                             // NULL triggers exception
00237 
00238     Document* doc = GetApplication().getDocument(pstr);
00239     if (!doc) {
00240         PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
00241         return NULL;
00242     }
00243     if (!doc->isClosable()) {
00244         PyErr_Format(PyExc_RuntimeError, "The document '%s' is not closable for the moment", pstr);
00245         return NULL;
00246     }
00247 
00248     if (GetApplication().closeDocument(pstr) == false) {
00249         PyErr_Format(PyExc_RuntimeError, "Closing the document '%s' failed", pstr);
00250         return NULL;
00251     }
00252 
00253     Py_Return;
00254 }
00255 
00256 PyObject* Application::sSaveDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00257 {
00258     char *pDoc;
00259     if (!PyArg_ParseTuple(args, "s", &pDoc))     // convert args: Python->C
00260         return NULL;                             // NULL triggers exception
00261 
00262     Document* doc = GetApplication().getDocument(pDoc);
00263     if ( doc ) {
00264         if ( doc->save() == false ) {
00265             PyErr_Format(PyExc_Exception, "Cannot save document '%s'", pDoc);
00266             return 0L;
00267         }
00268     }
00269     else {
00270         PyErr_Format(PyExc_NameError, "Unknown document '%s'", pDoc);
00271         return NULL;
00272     }
00273 
00274     Py_Return;
00275 }
00276 #if 0
00277 PyObject* Application::sSaveDocumentAs(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00278 {
00279     char *pDoc, *pFileName;
00280     if (!PyArg_ParseTuple(args, "ss", &pDoc, &pFileName))     // convert args: Python->C
00281         return NULL;                             // NULL triggers exception
00282 
00283     Document* doc = GetApplication().getDocument(pDoc);
00284     if (doc) {
00285         doc->saveAs( pFileName );
00286     }
00287     else {
00288         PyErr_Format(PyExc_NameError, "Unknown document '%s'", pDoc);
00289         return NULL;
00290     }
00291 
00292     Py_Return;
00293 }
00294 #endif
00295 PyObject* Application::sActiveDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00296 {
00297     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C
00298         return NULL;                       // NULL triggers exception
00299 
00300     Document* doc = GetApplication().getActiveDocument();
00301     if (doc) {
00302         return doc->getPyObject();
00303     }
00304     else {
00305         Py_INCREF(Py_None);
00306         return Py_None;
00307     }
00308 }
00309 
00310 PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00311 {
00312     char *pstr=0;
00313     if (!PyArg_ParseTuple(args, "s", &pstr))     // convert args: Python->C
00314         return NULL;                             // NULL triggers exception
00315 
00316     Document* doc = GetApplication().getDocument(pstr);
00317     if ( !doc ) {
00318         PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
00319         return 0L;
00320     }
00321 
00322     return doc->getPyObject();
00323 }
00324 
00325 PyObject* Application::sGetParam(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00326 {
00327     char *pstr=0;
00328     if (!PyArg_ParseTuple(args, "s", &pstr))     // convert args: Python->C
00329         return NULL;                             // NULL triggers exception
00330 
00331     PY_TRY {
00332         return GetPyObject(GetApplication().GetParameterGroupByPath(pstr));
00333     }PY_CATCH;
00334 }
00335 
00336 
00337 PyObject* Application::sGetConfig(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00338 {
00339     char *pstr;
00340 
00341     if (!PyArg_ParseTuple(args, "s", &pstr))     // convert args: Python->C
00342         return NULL;                             // NULL triggers exception
00343     const std::map<std::string, std::string>& Map = GetApplication().Config();
00344 
00345     std::map<std::string, std::string>::const_iterator it = Map.find(pstr);
00346     if (it != Map.end()) {
00347         return Py_BuildValue("s",it->second.c_str());
00348     }
00349     else {
00350         // do not set an error because this may break existing python code
00351         return PyString_FromString("");
00352     }
00353 }
00354 
00355 PyObject* Application::sDumpConfig(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00356 {
00357     if (!PyArg_ParseTuple(args, "") )    // convert args: Python->C
00358         return NULL;                             // NULL triggers exception
00359 
00360     PyObject *dict = PyDict_New();
00361     for (std::map<std::string,std::string>::iterator It= GetApplication()._mConfig.begin();
00362          It!=GetApplication()._mConfig.end();It++) {
00363         PyDict_SetItemString(dict,It->first.c_str(), PyString_FromString(It->second.c_str()));
00364     }
00365     return dict;
00366 }
00367 
00368 PyObject* Application::sSetConfig(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00369 {
00370     char *pstr,*pstr2;
00371 
00372     if (!PyArg_ParseTuple(args, "ss", &pstr,&pstr2))  // convert args: Python->C
00373         return NULL; // NULL triggers exception
00374 
00375     GetApplication()._mConfig[pstr] = pstr2;
00376 
00377     Py_INCREF(Py_None);
00378     return Py_None;
00379 }
00380 
00381 PyObject* Application::sGetVersion(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00382 {
00383     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C
00384         return NULL; // NULL triggers exception
00385 
00386     PyObject* pList = PyList_New(5);
00387     PyObject *pItem;
00388     pItem = PyString_FromString(Application::Config()["BuildVersionMajor"].c_str());
00389     PyList_SetItem(pList, 0, pItem);
00390     pItem = PyString_FromString(Application::Config()["BuildVersionMinor"].c_str());
00391     PyList_SetItem(pList, 1, pItem);
00392     pItem = PyString_FromString(Application::Config()["BuildRevision"].c_str());
00393     PyList_SetItem(pList, 2, pItem);
00394     pItem = PyString_FromString(Application::Config()["BuildRepositoryURL"].c_str());
00395     PyList_SetItem(pList, 4, pItem);
00396     pItem = PyString_FromString(Application::Config()["BuildCurrentDate"].c_str());
00397     PyList_SetItem(pList, 6, pItem);
00398 
00399     return pList;
00400 }
00401 
00402 
00403 PyObject* Application::sAddImportType(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00404 {
00405     char *psKey,*psMod;
00406 
00407     if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod))
00408         return NULL;
00409 
00410     GetApplication().addImportType(psKey,psMod);
00411 
00412     Py_Return;
00413 }
00414 
00415 PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00416 {
00417     char*       psKey=0;
00418 
00419     if (!PyArg_ParseTuple(args, "|s", &psKey))     // convert args: Python->C
00420         return NULL;                             // NULL triggers exception
00421 
00422     if (psKey) {
00423         Py::List list;
00424         std::vector<std::string> modules = GetApplication().getImportModules(psKey);
00425         for (std::vector<std::string>::iterator it = modules.begin(); it != modules.end(); ++it) {
00426             list.append(Py::String(*it));
00427         }
00428 
00429         return Py::new_reference_to(list);
00430     }
00431     else {
00432         Py::Dict dict;
00433         std::vector<std::string> types = GetApplication().getImportTypes();
00434         for (std::vector<std::string>::iterator it = types.begin(); it != types.end(); ++it) {
00435             std::vector<std::string> modules = GetApplication().getImportModules(it->c_str());
00436             if (modules.empty()) {
00437                 dict.setItem(it->c_str(), Py::None());
00438             }
00439             else if (modules.size() == 1) {
00440                 dict.setItem(it->c_str(), Py::String(modules.front()));
00441             }
00442             else {
00443                 Py::List list;
00444                 for (std::vector<std::string>::iterator jt = modules.begin(); jt != modules.end(); ++jt) {
00445                     list.append(Py::String(*jt));
00446                 }
00447                 dict.setItem(it->c_str(), list);
00448             }
00449         }
00450 
00451         return Py::new_reference_to(dict);
00452     }
00453 }
00454 
00455 PyObject* Application::sAddExportType(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00456 {
00457     char *psKey,*psMod;
00458 
00459     if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod))
00460         return NULL;
00461 
00462     GetApplication().addExportType(psKey,psMod);
00463 
00464     Py_Return;
00465 }
00466 
00467 PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00468 {
00469     char*       psKey=0;
00470 
00471     if (!PyArg_ParseTuple(args, "|s", &psKey))     // convert args: Python->C
00472         return NULL;                             // NULL triggers exception
00473 
00474     if (psKey) {
00475         Py::List list;
00476         std::vector<std::string> modules = GetApplication().getExportModules(psKey);
00477         for (std::vector<std::string>::iterator it = modules.begin(); it != modules.end(); ++it) {
00478             list.append(Py::String(*it));
00479         }
00480 
00481         return Py::new_reference_to(list);
00482     }
00483     else {
00484         Py::Dict dict;
00485         std::vector<std::string> types = GetApplication().getExportTypes();
00486         for (std::vector<std::string>::iterator it = types.begin(); it != types.end(); ++it) {
00487             std::vector<std::string> modules = GetApplication().getExportModules(it->c_str());
00488             if (modules.empty()) {
00489                 dict.setItem(it->c_str(), Py::None());
00490             }
00491             else if (modules.size() == 1) {
00492                 dict.setItem(it->c_str(), Py::String(modules.front()));
00493             }
00494             else {
00495                 Py::List list;
00496                 for (std::vector<std::string>::iterator jt = modules.begin(); jt != modules.end(); ++jt) {
00497                     list.append(Py::String(*jt));
00498                 }
00499                 dict.setItem(it->c_str(), list);
00500             }
00501         }
00502 
00503         return Py::new_reference_to(dict);
00504     }
00505 }
00506 
00507 PyObject* Application::sGetResourceDir(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00508 {
00509     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C
00510         return NULL;                       // NULL triggers exception
00511 
00512     Py::String datadir(Application::getResourceDir());
00513     return Py::new_reference_to(datadir);
00514 }
00515 
00516 PyObject* Application::sGetHomePath(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00517 {
00518     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C
00519         return NULL;                       // NULL triggers exception
00520 
00521     Py::String homedir(GetApplication().GetHomePath());
00522     return Py::new_reference_to(homedir);
00523 }
00524 
00525 PyObject* Application::sListDocuments(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00526 {
00527     if (!PyArg_ParseTuple(args, ""))     // convert args: Python->C
00528         return NULL;                       // NULL triggers exception
00529     PY_TRY {
00530         PyObject *pDict = PyDict_New();
00531         PyObject *pKey;
00532         Base::PyObjectBase* pValue;
00533 
00534         for (std::map<std::string,Document*>::const_iterator It = GetApplication().DocMap.begin();
00535              It != GetApplication().DocMap.end();++It) {
00536             pKey   = PyString_FromString(It->first.c_str());
00537             // GetPyObject() increments
00538             pValue = static_cast<Base::PyObjectBase*>(It->second->getPyObject());
00539             PyDict_SetItem(pDict, pKey, pValue);
00540             // now we can decrement again as PyDict_SetItem also has incremented
00541             pValue->DecRef();
00542         }
00543 
00544         return pDict;
00545     } PY_CATCH;
00546 }
00547 
00548 PyObject* Application::sAddDocObserver(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00549 {
00550     PyObject* o;
00551     if (!PyArg_ParseTuple(args, "O",&o))
00552         return NULL;
00553     PY_TRY {
00554         DocumentObserverPython::addObserver(Py::Object(o));
00555         Py_Return;
00556     } PY_CATCH;
00557 }
00558 
00559 PyObject* Application::sRemoveDocObserver(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
00560 {
00561     PyObject* o;
00562     if (!PyArg_ParseTuple(args, "O",&o))
00563         return NULL;
00564     PY_TRY {
00565         DocumentObserverPython::removeObserver(Py::Object(o));
00566         Py_Return;
00567     } PY_CATCH;
00568 }

Generated on Wed Nov 23 18:59:55 2011 for FreeCAD by  doxygen 1.6.1