Download src/App/ApplicationPy.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 39.1 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/App/ApplicationPy.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/App/ApplicationPy.cpp
-
curl -L -o ApplicationPy.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/App/ApplicationPy.cpp
39.1 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> * | |
| * * | |
| * This file is part of the FreeCAD CAx development system. * | |
| * * | |
| * This program is free software; you can redistribute it and/or modify * | |
| * it under the terms of the GNU Library General Public License (LGPL) * | |
| * as published by the Free Software Foundation; either version 2 of * | |
| * the License, or (at your option) any later version. * | |
| * for detail see the LICENCE text file. * | |
| * * | |
| * FreeCAD 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 FreeCAD; if not, write to the Free Software * | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | |
| * USA * | |
| * * | |
| ***************************************************************************/ | |
| // using Base::GetConsole; | |
| using namespace Base; | |
| using namespace App; | |
| //************************************************************************** | |
| // Python stuff | |
| // Application methods structure | |
| PyMethodDef Application::Methods[] = { | |
| {"ParamGet", (PyCFunction)Application::sGetParam, METH_VARARGS, "Get parameters by path"}, | |
| {"saveParameter", | |
| (PyCFunction)Application::sSaveParameter, | |
| METH_VARARGS, | |
| "saveParameter(config='User parameter') -> None\n" | |
| "Save parameter set to file. The default set is 'User parameter'"}, | |
| {"Version", | |
| (PyCFunction)Application::sGetVersion, | |
| METH_VARARGS, | |
| "Print the version to the output."}, | |
| {"ConfigGet", | |
| (PyCFunction)Application::sGetConfig, | |
| METH_VARARGS, | |
| "ConfigGet(string) -- Get the value for the given key."}, | |
| {"ConfigSet", | |
| (PyCFunction)Application::sSetConfig, | |
| METH_VARARGS, | |
| "ConfigSet(string, string) -- Set the given key to the given value."}, | |
| {"ConfigDump", | |
| (PyCFunction)Application::sDumpConfig, | |
| METH_VARARGS, | |
| "Dump the configuration to the output."}, | |
| {"addImportType", | |
| (PyCFunction)Application::sAddImportType, | |
| METH_VARARGS, | |
| "Register filetype for import"}, | |
| {"changeImportModule", | |
| (PyCFunction)Application::sChangeImportModule, | |
| METH_VARARGS, | |
| "Change the import module name of a registered filetype"}, | |
| {"getImportType", | |
| (PyCFunction)Application::sGetImportType, | |
| METH_VARARGS, | |
| "Get the name of the module that can import the filetype"}, | |
| {"addExportType", | |
| (PyCFunction)Application::sAddExportType, | |
| METH_VARARGS, | |
| "Register filetype for export"}, | |
| {"changeExportModule", | |
| (PyCFunction)Application::sChangeExportModule, | |
| METH_VARARGS, | |
| "Change the export module name of a registered filetype"}, | |
| {"getExportType", | |
| (PyCFunction)Application::sGetExportType, | |
| METH_VARARGS, | |
| "Get the name of the module that can export the filetype"}, | |
| {"getResourceDir", | |
| (PyCFunction)Application::sGetResourcePath, | |
| METH_VARARGS, | |
| "Get the root directory of all resources"}, | |
| {"getLibraryDir", | |
| (PyCFunction)Application::sGetLibraryPath, | |
| METH_VARARGS, | |
| "Get the directory of all extension modules"}, | |
| {"getTempPath", | |
| (PyCFunction)Application::sGetTempPath, | |
| METH_VARARGS, | |
| "Get the root directory of cached files"}, | |
| {"getUserCachePath", | |
| (PyCFunction)Application::sGetUserCachePath, | |
| METH_VARARGS, | |
| "Get the root path of cached files"}, | |
| {"getUserConfigDir", | |
| (PyCFunction)Application::sGetUserConfigPath, | |
| METH_VARARGS, | |
| "Get the root path of user config files"}, | |
| {"getUserAppDataDir", | |
| (PyCFunction)Application::sGetUserAppDataPath, | |
| METH_VARARGS, | |
| "Get the root directory of application data"}, | |
| {"getUserMacroDir", | |
| (PyCFunction)Application::sGetUserMacroPath, | |
| METH_VARARGS, | |
| "getUserMacroDir(bool=False) -> str\n\n" | |
| "Get the directory of the user's macro directory\n" | |
| "If parameter is False (the default) it returns the standard path in the" | |
| "user's home directory, otherwise it returns the user-defined path."}, | |
| {"getHelpDir", | |
| (PyCFunction)Application::sGetHelpPath, | |
| METH_VARARGS, | |
| "Get the directory of the documentation"}, | |
| {"getHomePath", | |
| (PyCFunction)Application::sGetHomePath, | |
| METH_VARARGS, | |
| "Get the home path, i.e. the parent directory of the executable"}, | |
| {"loadFile", | |
| (PyCFunction)Application::sLoadFile, | |
| METH_VARARGS, | |
| "loadFile(string=filename,[string=module]) -> None\n\n" | |
| "Loads an arbitrary file by delegating to the given Python module:\n" | |
| "* If no module is given it will be determined by the file extension.\n" | |
| "* If more than one module can load a file the first one will be taken.\n" | |
| "* If no module exists to load the file an exception will be raised."}, | |
| {"open", | |
| reinterpret_cast<PyCFunction>(reinterpret_cast<void (*)()>(Application::sOpenDocument)), | |
| METH_VARARGS | METH_KEYWORDS, | |
| "See openDocument(string)"}, | |
| {"openDocument", | |
| reinterpret_cast<PyCFunction>(reinterpret_cast<void (*)()>(Application::sOpenDocument)), | |
| METH_VARARGS | METH_KEYWORDS, | |
| "openDocument(filepath,hidden=False,temporary=False) -> object\n" | |
| "Create a document and load the project file into the document.\n\n" | |
| "filepath: file path to an existing file. If the file doesn't exist\n" | |
| " or the file cannot be loaded an I/O exception is thrown.\n" | |
| " In this case the document is kept alive.\n" | |
| "hidden: whether to hide document 3D view.\n" | |
| "temporary: whether to hide document in the tree view."}, | |
| // {"saveDocument", (PyCFunction) Application::sSaveDocument, METH_VARARGS, | |
| // "saveDocument(string) -- Save the document to a file."}, | |
| // {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, METH_VARARGS}, | |
| {"newDocument", | |
| reinterpret_cast<PyCFunction>(reinterpret_cast<void (*)()>(Application::sNewDocument)), | |
| METH_VARARGS | METH_KEYWORDS, | |
| "newDocument(name, label=None, hidden=False, temp=False) -> object\n" | |
| "Create a new document with a given name.\n\n" | |
| "name: unique document name which is checked automatically.\n" | |
| "label: optional user changeable label for the document.\n" | |
| "hidden: whether to hide document 3D view.\n" | |
| "temp: mark the document as temporary so that it will not be saved"}, | |
| {"closeDocument", | |
| (PyCFunction)Application::sCloseDocument, | |
| METH_VARARGS, | |
| "closeDocument(string) -> None\n\n" | |
| "Close the document with a given name."}, | |
| {"activeDocument", | |
| (PyCFunction)Application::sActiveDocument, | |
| METH_VARARGS, | |
| "activeDocument() -> object or None\n\n" | |
| "Return the active document or None if there is no one."}, | |
| {"setActiveDocument", | |
| (PyCFunction)Application::sSetActiveDocument, | |
| METH_VARARGS, | |
| "setActiveDocement(string) -> None\n\n" | |
| "Set the active document by its name."}, | |
| {"getDocument", | |
| (PyCFunction)Application::sGetDocument, | |
| METH_VARARGS, | |
| "getDocument(string) -> object\n\n" | |
| "Get a document by its name or raise an exception\n" | |
| "if there is no document with the given name."}, | |
| {"listDocuments", | |
| (PyCFunction)Application::sListDocuments, | |
| METH_VARARGS, | |
| "listDocuments(sort=False) -> list\n\n" | |
| "Return a list of names of all documents, optionally sort in dependency order."}, | |
| {"addDocumentObserver", | |
| (PyCFunction)Application::sAddDocObserver, | |
| METH_VARARGS, | |
| "addDocumentObserver() -> None\n\n" | |
| "Add an observer to get notified about changes on documents."}, | |
| {"removeDocumentObserver", | |
| (PyCFunction)Application::sRemoveDocObserver, | |
| METH_VARARGS, | |
| "removeDocumentObserver() -> None\n\n" | |
| "Remove an added document observer."}, | |
| {"setLogLevel", | |
| (PyCFunction)Application::sSetLogLevel, | |
| METH_VARARGS, | |
| "setLogLevel(tag, level) -- Set the log level for a string tag.\n" | |
| "'level' can either be string 'Log', 'Msg', 'Wrn', 'Error', or an integer value"}, | |
| {"getLogLevel", | |
| (PyCFunction)Application::sGetLogLevel, | |
| METH_VARARGS, | |
| "getLogLevel(tag) -- Get the log level of a string tag"}, | |
| {"checkLinkDepth", | |
| (PyCFunction)Application::sCheckLinkDepth, | |
| METH_VARARGS, | |
| "checkLinkDepth(depth) -- check link recursion depth"}, | |
| {"getLinksTo", | |
| (PyCFunction)Application::sGetLinksTo, | |
| METH_VARARGS, | |
| "getLinksTo(obj,options=0,maxCount=0) -- return the objects linked to 'obj'\n\n" | |
| "options: 1: recursive, 2: check link array. Options can combine.\n" | |
| "maxCount: to limit the number of links returned\n"}, | |
| {"getDependentObjects", | |
| (PyCFunction)Application::sGetDependentObjects, | |
| METH_VARARGS, | |
| "getDependentObjects(obj|[obj,...], options=0)\n" | |
| "Return a list of dependent objects including the given objects.\n\n" | |
| "options: can have the following bit flags,\n" | |
| " 1: to sort the list in topological order.\n" | |
| " 2: to exclude dependency of Link type object."}, | |
| {"setActiveTransaction", | |
| (PyCFunction)Application::sSetActiveTransaction, | |
| METH_VARARGS, | |
| "setActiveTransaction(name, persist=False) -- setup active transaction with the given name\n\n" | |
| "name: the transaction name\n" | |
| "persist(False): by default, if the calling code is inside any invocation of a command, it\n" | |
| " will be auto closed once all commands within the current stack exists. To\n" | |
| " disable auto closing, set persist=True\n" | |
| "Returns the transaction ID for the active transaction. An application-wide\n" | |
| "active transaction causes any document changes to open a transaction with\n" | |
| "the given name and ID."}, | |
| {"getActiveTransaction", | |
| (PyCFunction)Application::sGetActiveTransaction, | |
| METH_VARARGS, | |
| "getActiveTransaction() -> (name,id)\n\n" | |
| "return the current active transaction name and ID"}, | |
| {"closeActiveTransaction", | |
| (PyCFunction)Application::sCloseActiveTransaction, | |
| METH_VARARGS, | |
| "closeActiveTransaction(abort=False) -- commit or abort current active transaction"}, | |
| {"isRestoring", | |
| (PyCFunction)Application::sIsRestoring, | |
| METH_VARARGS, | |
| "isRestoring() -> bool\n\n" | |
| "Test if the application is opening some document"}, | |
| {"checkAbort", | |
| (PyCFunction)Application::sCheckAbort, | |
| METH_VARARGS, | |
| "checkAbort() -- check for user abort in length operation.\n\n" | |
| "This only works if there is an active sequencer (or ProgressIndicator in Python).\n" | |
| "There is an active sequencer during document restore and recomputation. User may\n" | |
| "abort the operation by pressing the ESC key. Once detected, this function will\n" | |
| "trigger a Base.FreeCADAbort exception."}, | |
| {nullptr, nullptr, 0, nullptr} /* Sentinel */ | |
| }; | |
| PyObject* Application::sLoadFile(PyObject* /*self*/, PyObject* args) | |
| { | |
| const char* path; | |
| const char* doc = ""; | |
| const char* mod = ""; | |
| if (!PyArg_ParseTuple(args, "s|ss", &path, &doc, &mod)) { | |
| return nullptr; | |
| } | |
| try { | |
| Base::FileInfo fi(path); | |
| if (!fi.isFile() || !fi.exists()) { | |
| PyErr_Format(PyExc_IOError, "File %s doesn't exist.", path); | |
| return nullptr; | |
| } | |
| std::string module = mod; | |
| if (module.empty()) { | |
| std::string ext = fi.extension(); | |
| std::vector<std::string> modules = GetApplication().getImportModules(ext.c_str()); | |
| if (modules.empty()) { | |
| PyErr_Format(PyExc_IOError, "Filetype %s is not supported.", ext.c_str()); | |
| return nullptr; | |
| } | |
| else { | |
| module = modules.front(); | |
| } | |
| } | |
| // path could contain characters that need escaping, such as quote signs | |
| // therefore use its representation in the Python code string | |
| PyObject* pathObj = PyUnicode_FromString(path); | |
| PyObject* pathReprObj = PyObject_Repr(pathObj); | |
| const char* pathRepr = PyUnicode_AsUTF8(pathReprObj); | |
| std::stringstream str; | |
| str << "import " << module << std::endl; | |
| if (fi.hasExtension("FCStd")) { | |
| str << module << ".openDocument(" << pathRepr << ")" << std::endl; | |
| } | |
| else { | |
| str << module << ".insert(" << pathRepr << ",'" << doc << "')" << std::endl; | |
| } | |
| Py_DECREF(pathObj); | |
| Py_DECREF(pathReprObj); | |
| Base::Interpreter().runString(str.str().c_str()); | |
| Py_Return; | |
| } | |
| catch (const Base::Exception& e) { | |
| e.setPyException(); | |
| return nullptr; | |
| } | |
| catch (const std::exception& e) { | |
| // might be subclass from zipios | |
| PyErr_Format(PyExc_IOError, "Invalid project file %s: %s", path, e.what()); | |
| return nullptr; | |
| } | |
| } | |
| PyObject* Application::sIsRestoring(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Boolean(GetApplication().isRestoring())); | |
| } | |
| PyObject* Application::sOpenDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) | |
| { | |
| char* Name; | |
| PyObject* hidden = Py_False; | |
| PyObject* temporary = Py_False; | |
| static const std::array<const char*, 4> kwlist {"name", "hidden", "temporary", nullptr}; | |
| if (!Base::Wrapped_ParseTupleAndKeywords(args, | |
| kwd, | |
| "et|O!O!", | |
| kwlist, | |
| "utf-8", | |
| &Name, | |
| &PyBool_Type, | |
| &hidden, | |
| &PyBool_Type, | |
| &temporary)) { | |
| return nullptr; | |
| } | |
| std::string EncodedName = std::string(Name); | |
| PyMem_Free(Name); | |
| try { | |
| DocumentInitFlags initFlags { | |
| .createView = !Base::asBoolean(hidden), | |
| .temporary = Base::asBoolean(temporary) | |
| }; | |
| // return new document | |
| return (GetApplication() | |
| .openDocument(EncodedName.c_str(), initFlags) | |
| ->getPyObject()); | |
| } | |
| catch (const Base::Exception& e) { | |
| PyErr_SetString(PyExc_IOError, e.what()); | |
| return nullptr; | |
| } | |
| catch (const std::exception& e) { | |
| // might be subclass from zipios | |
| PyErr_Format(PyExc_IOError, "Invalid project file %s: %s\n", EncodedName.c_str(), e.what()); | |
| return nullptr; | |
| } | |
| } | |
| PyObject* Application::sNewDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) | |
| { | |
| char* docName = nullptr; | |
| char* usrName = nullptr; | |
| PyObject* hidden = Py_False; | |
| PyObject* temp = Py_False; | |
| static const std::array<const char*, 5> kwlist {"name", "label", "hidden", "temp", nullptr}; | |
| if (!Base::Wrapped_ParseTupleAndKeywords(args, | |
| kwd, | |
| "|etetO!O!", | |
| kwlist, | |
| "utf-8", | |
| &docName, | |
| "utf-8", | |
| &usrName, | |
| &PyBool_Type, | |
| &hidden, | |
| &PyBool_Type, | |
| &temp)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| DocumentInitFlags initFlags { | |
| .createView = !Base::asBoolean(hidden), | |
| .temporary = Base::asBoolean(temp) | |
| }; | |
| App::Document* doc = GetApplication().newDocument(docName, | |
| usrName, | |
| initFlags); | |
| PyMem_Free(docName); | |
| PyMem_Free(usrName); | |
| return doc->getPyObject(); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sSetActiveDocument(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* pstr = nullptr; | |
| if (!PyArg_ParseTuple(args, "s", &pstr)) { | |
| return nullptr; | |
| } | |
| try { | |
| GetApplication().setActiveDocument(pstr); | |
| } | |
| catch (const Base::Exception& e) { | |
| e.setPyException(); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* Application::sCloseDocument(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* pstr = nullptr; | |
| if (!PyArg_ParseTuple(args, "s", &pstr)) { | |
| return nullptr; | |
| } | |
| Document* doc = GetApplication().getDocument(pstr); | |
| if (!doc) { | |
| PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr); | |
| return nullptr; | |
| } | |
| if (!doc->isClosable()) { | |
| PyErr_Format(PyExc_RuntimeError, "The document '%s' is not closable for the moment", pstr); | |
| return nullptr; | |
| } | |
| if (!GetApplication().closeDocument(pstr)) { | |
| PyErr_Format(PyExc_RuntimeError, "Closing the document '%s' failed", pstr); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* Application::sSaveDocument(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* pDoc; | |
| if (!PyArg_ParseTuple(args, "s", &pDoc)) { | |
| return nullptr; | |
| } | |
| Document* doc = GetApplication().getDocument(pDoc); | |
| if (doc) { | |
| if (!doc->save()) { | |
| PyErr_Format(Base::PyExc_FC_GeneralError, "Cannot save document '%s'", pDoc); | |
| return nullptr; | |
| } | |
| } | |
| else { | |
| PyErr_Format(PyExc_NameError, "Unknown document '%s'", pDoc); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* Application::sActiveDocument(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Document* doc = GetApplication().getActiveDocument(); | |
| if (doc) { | |
| return doc->getPyObject(); | |
| } | |
| else { | |
| Py_INCREF(Py_None); | |
| return Py_None; | |
| } | |
| } | |
| PyObject* Application::sGetDocument(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* pstr = nullptr; | |
| if (!PyArg_ParseTuple(args, "s", &pstr)) { | |
| return nullptr; | |
| } | |
| Document* doc = GetApplication().getDocument(pstr); | |
| if (!doc) { | |
| PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr); | |
| return nullptr; | |
| } | |
| return doc->getPyObject(); | |
| } | |
| PyObject* Application::sGetParam(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* pstr = nullptr; | |
| if (!PyArg_ParseTuple(args, "s", &pstr)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| return GetPyObject(GetApplication().GetParameterGroupByPath(pstr)); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sSaveParameter(PyObject* /*self*/, PyObject* args) | |
| { | |
| const char* pstr = "User parameter"; | |
| if (!PyArg_ParseTuple(args, "|s", &pstr)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| ParameterManager* param = App::GetApplication().GetParameterSet(pstr); | |
| if (!param) { | |
| std::stringstream str; | |
| str << "No parameter set found with name: " << pstr; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| else if (!param->HasSerializer()) { | |
| std::stringstream str; | |
| str << "Parameter set cannot be serialized: " << pstr; | |
| PyErr_SetString(PyExc_RuntimeError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| param->SaveDocument(); | |
| Py_INCREF(Py_None); | |
| return Py_None; | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sGetConfig(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* pstr; | |
| if (!PyArg_ParseTuple(args, "s", &pstr)) { | |
| return nullptr; | |
| } | |
| const std::map<std::string, std::string>& Map = GetApplication().Config(); | |
| std::map<std::string, std::string>::const_iterator it = Map.find(pstr); | |
| if (it != Map.end()) { | |
| return Py_BuildValue("s", it->second.c_str()); | |
| } | |
| else { | |
| // do not set an error because this may break existing python code | |
| return PyUnicode_FromString(""); | |
| } | |
| } | |
| PyObject* Application::sDumpConfig(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| PyObject* dict = PyDict_New(); | |
| for (const auto& It : GetApplication()._mConfig) { | |
| PyDict_SetItemString(dict, It.first.c_str(), PyUnicode_FromString(It.second.c_str())); | |
| } | |
| return dict; | |
| } | |
| PyObject* Application::sSetConfig(PyObject* /*self*/, PyObject* args) | |
| { | |
| char *pstr, *pstr2; | |
| if (!PyArg_ParseTuple(args, "ss", &pstr, &pstr2)) { | |
| return nullptr; | |
| } | |
| GetApplication()._mConfig[pstr] = pstr2; | |
| Py_INCREF(Py_None); | |
| return Py_None; | |
| } | |
| PyObject* Application::sGetVersion(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::List list; | |
| const std::map<std::string, std::string>& cfg = Application::Config(); | |
| std::map<std::string, std::string>::const_iterator it; | |
| it = cfg.find("BuildVersionMajor"); | |
| list.append(Py::String(it != cfg.end() ? it->second : "")); | |
| it = cfg.find("BuildVersionMinor"); | |
| list.append(Py::String(it != cfg.end() ? it->second : "")); | |
| it = cfg.find("BuildVersionPoint"); | |
| list.append(Py::String(it != cfg.end() ? it->second : "")); | |
| it = cfg.find("BuildRevision"); | |
| list.append(Py::String(it != cfg.end() ? it->second : "")); | |
| it = cfg.find("BuildRepositoryURL"); | |
| list.append(Py::String(it != cfg.end() ? it->second : "")); | |
| it = cfg.find("BuildRevisionDate"); | |
| list.append(Py::String(it != cfg.end() ? it->second : "")); | |
| it = cfg.find("BuildRevisionBranch"); | |
| if (it != cfg.end()) { | |
| list.append(Py::String(it->second)); | |
| } | |
| it = cfg.find("BuildRevisionHash"); | |
| if (it != cfg.end()) { | |
| list.append(Py::String(it->second)); | |
| } | |
| return Py::new_reference_to(list); | |
| } | |
| PyObject* Application::sAddImportType(PyObject* /*self*/, PyObject* args) | |
| { | |
| char *psKey, *psMod; | |
| if (!PyArg_ParseTuple(args, "ss", &psKey, &psMod)) { | |
| return nullptr; | |
| } | |
| GetApplication().addImportType(psKey, psMod); | |
| Py_Return; | |
| } | |
| PyObject* Application::sChangeImportModule(PyObject* /*self*/, PyObject* args) | |
| { | |
| char *key, *oldMod, *newMod; | |
| if (!PyArg_ParseTuple(args, "sss", &key, &oldMod, &newMod)) { | |
| return nullptr; | |
| } | |
| GetApplication().changeImportModule(key, oldMod, newMod); | |
| Py_Return; | |
| } | |
| PyObject* Application::sGetImportType(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* psKey = nullptr; | |
| if (!PyArg_ParseTuple(args, "|s", &psKey)) { | |
| return nullptr; | |
| } | |
| if (psKey) { | |
| Py::List list; | |
| std::vector<std::string> modules = GetApplication().getImportModules(psKey); | |
| for (const auto& it : modules) { | |
| list.append(Py::String(it)); | |
| } | |
| return Py::new_reference_to(list); | |
| } | |
| else { | |
| Py::Dict dict; | |
| std::vector<std::string> types = GetApplication().getImportTypes(); | |
| for (const auto& it : types) { | |
| std::vector<std::string> modules = GetApplication().getImportModules(it.c_str()); | |
| if (modules.empty()) { | |
| dict.setItem(it.c_str(), Py::None()); | |
| } | |
| else if (modules.size() == 1) { | |
| dict.setItem(it.c_str(), Py::String(modules.front())); | |
| } | |
| else { | |
| Py::List list; | |
| for (const auto& jt : modules) { | |
| list.append(Py::String(jt)); | |
| } | |
| dict.setItem(it.c_str(), list); | |
| } | |
| } | |
| return Py::new_reference_to(dict); | |
| } | |
| } | |
| PyObject* Application::sAddExportType(PyObject* /*self*/, PyObject* args) | |
| { | |
| char *psKey, *psMod; | |
| if (!PyArg_ParseTuple(args, "ss", &psKey, &psMod)) { | |
| return nullptr; | |
| } | |
| GetApplication().addExportType(psKey, psMod); | |
| Py_Return; | |
| } | |
| PyObject* Application::sChangeExportModule(PyObject* /*self*/, PyObject* args) | |
| { | |
| char *key, *oldMod, *newMod; | |
| if (!PyArg_ParseTuple(args, "sss", &key, &oldMod, &newMod)) { | |
| return nullptr; | |
| } | |
| GetApplication().changeExportModule(key, oldMod, newMod); | |
| Py_Return; | |
| } | |
| PyObject* Application::sGetExportType(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* psKey = nullptr; | |
| if (!PyArg_ParseTuple(args, "|s", &psKey)) { | |
| return nullptr; | |
| } | |
| if (psKey) { | |
| Py::List list; | |
| std::vector<std::string> modules = GetApplication().getExportModules(psKey); | |
| for (const auto& it : modules) { | |
| list.append(Py::String(it)); | |
| } | |
| return Py::new_reference_to(list); | |
| } | |
| else { | |
| Py::Dict dict; | |
| std::vector<std::string> types = GetApplication().getExportTypes(); | |
| for (const auto& it : types) { | |
| std::vector<std::string> modules = GetApplication().getExportModules(it.c_str()); | |
| if (modules.empty()) { | |
| dict.setItem(it.c_str(), Py::None()); | |
| } | |
| else if (modules.size() == 1) { | |
| dict.setItem(it.c_str(), Py::String(modules.front())); | |
| } | |
| else { | |
| Py::List list; | |
| for (const auto& jt : modules) { | |
| list.append(Py::String(jt)); | |
| } | |
| dict.setItem(it.c_str(), list); | |
| } | |
| } | |
| return Py::new_reference_to(dict); | |
| } | |
| } | |
| PyObject* Application::sGetResourcePath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String datadir(Application::getResourceDir(), "utf-8"); | |
| return Py::new_reference_to(datadir); | |
| } | |
| PyObject* Application::sGetLibraryPath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String datadir(Application::getLibraryDir(), "utf-8"); | |
| return Py::new_reference_to(datadir); | |
| } | |
| PyObject* Application::sGetTempPath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String datadir(Application::getTempPath(), "utf-8"); | |
| return Py::new_reference_to(datadir); | |
| } | |
| PyObject* Application::sGetUserCachePath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String datadir(Application::getUserCachePath(), "utf-8"); | |
| return Py::new_reference_to(datadir); | |
| } | |
| PyObject* Application::sGetUserConfigPath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String datadir(Application::getUserConfigPath(), "utf-8"); | |
| return Py::new_reference_to(datadir); | |
| } | |
| PyObject* Application::sGetUserAppDataPath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String user_data_dir(Application::getUserAppDataDir(), "utf-8"); | |
| return Py::new_reference_to(user_data_dir); | |
| } | |
| PyObject* Application::sGetUserMacroPath(PyObject* /*self*/, PyObject* args) | |
| { | |
| PyObject* actual = Py_False; | |
| if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &actual)) { | |
| return nullptr; | |
| } | |
| std::string macroDir = Application::getUserMacroDir(); | |
| if (Base::asBoolean(actual)) { | |
| macroDir = App::GetApplication() | |
| .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") | |
| ->GetASCII("MacroPath", macroDir.c_str()); | |
| std::replace(macroDir.begin(), macroDir.end(), '/', PATHSEP); | |
| } | |
| Py::String user_macro_dir(macroDir, "utf-8"); | |
| return Py::new_reference_to(user_macro_dir); | |
| } | |
| PyObject* Application::sGetHelpPath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String user_macro_dir(Application::getHelpDir(), "utf-8"); | |
| return Py::new_reference_to(user_macro_dir); | |
| } | |
| PyObject* Application::sGetHomePath(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| Py::String homedir(Application::getHomePath(), "utf-8"); | |
| return Py::new_reference_to(homedir); | |
| } | |
| PyObject* Application::sListDocuments(PyObject* /*self*/, PyObject* args) | |
| { | |
| PyObject* sort = Py_False; | |
| if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| PyObject* pDict = PyDict_New(); | |
| PyObject* pKey; | |
| Base::PyObjectBase* pValue; | |
| std::vector<Document*> docs = GetApplication().getDocuments(); | |
| ; | |
| if (Base::asBoolean(sort)) { | |
| docs = Document::getDependentDocuments(docs, true); | |
| } | |
| for (auto doc : docs) { | |
| pKey = PyUnicode_FromString(doc->getName()); | |
| // GetPyObject() increments | |
| pValue = static_cast<Base::PyObjectBase*>(doc->getPyObject()); | |
| PyDict_SetItem(pDict, pKey, pValue); | |
| // now we can decrement again as PyDict_SetItem also has incremented | |
| pValue->DecRef(); | |
| } | |
| return pDict; | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sAddDocObserver(PyObject* /*self*/, PyObject* args) | |
| { | |
| PyObject* o; | |
| if (!PyArg_ParseTuple(args, "O", &o)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| DocumentObserverPython::addObserver(Py::Object(o)); | |
| Py_Return; | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sRemoveDocObserver(PyObject* /*self*/, PyObject* args) | |
| { | |
| PyObject* o; | |
| if (!PyArg_ParseTuple(args, "O", &o)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| DocumentObserverPython::removeObserver(Py::Object(o)); | |
| Py_Return; | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sSetLogLevel(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* tag; | |
| PyObject* pcObj; | |
| if (!PyArg_ParseTuple(args, "sO", &tag, &pcObj)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| int l; | |
| if (PyUnicode_Check(pcObj)) { | |
| const char* pstr = PyUnicode_AsUTF8(pcObj); | |
| if (strcmp(pstr, "Log") == 0) { | |
| l = FC_LOGLEVEL_LOG; | |
| } | |
| else if (strcmp(pstr, "Warning") == 0) { | |
| l = FC_LOGLEVEL_WARN; | |
| } | |
| else if (strcmp(pstr, "Message") == 0) { | |
| l = FC_LOGLEVEL_MSG; | |
| } | |
| else if (strcmp(pstr, "Error") == 0) { | |
| l = FC_LOGLEVEL_ERR; | |
| } | |
| else if (strcmp(pstr, "Trace") == 0) { | |
| l = FC_LOGLEVEL_TRACE; | |
| } | |
| else if (strcmp(pstr, "Default") == 0) { | |
| l = FC_LOGLEVEL_DEFAULT; | |
| } | |
| else { | |
| Py_Error(PyExc_ValueError, | |
| "Unknown Log Level (use 'Default', 'Error', 'Warning', 'Message', 'Log', " | |
| "'Trace' or an integer)"); | |
| return nullptr; | |
| } | |
| } | |
| else { | |
| l = PyLong_AsLong(pcObj); | |
| } | |
| GetApplication() | |
| .GetParameterGroupByPath("User parameter:BaseApp/LogLevels") | |
| ->SetInt(tag, l); | |
| if (strcmp(tag, "Default") == 0) { | |
| if (l >= 0) { | |
| Base::Console().setDefaultLogLevel(l); | |
| } | |
| } | |
| else if (strcmp(tag, "DebugDefault") == 0) { | |
| if (l >= 0) { | |
| Base::Console().setDefaultLogLevel(l); | |
| } | |
| } | |
| else { | |
| *Base::Console().getLogLevel(tag) = l; | |
| } | |
| Py_INCREF(Py_None); | |
| return Py_None; | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sGetLogLevel(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* tag; | |
| if (!PyArg_ParseTuple(args, "s", &tag)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| int l = -1; | |
| if (strcmp(tag, "Default") == 0) { | |
| l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); | |
| } | |
| else if (strcmp(tag, "DebugDefault") == 0) { | |
| l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); | |
| } | |
| else { | |
| int* pl = Base::Console().getLogLevel(tag, false); | |
| l = pl ? *pl : -1; | |
| } | |
| // For performance reason, we only output integer value | |
| return Py_BuildValue("i", Base::Console().logLevel(l)); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sCheckLinkDepth(PyObject* /*self*/, PyObject* args) | |
| { | |
| short depth = 0; | |
| if (!PyArg_ParseTuple(args, "h", &depth)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| return Py::new_reference_to( | |
| Py::Long(GetApplication().checkLinkDepth(depth, MessageOption::Throw))); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sGetLinksTo(PyObject* /*self*/, PyObject* args) | |
| { | |
| PyObject* pyobj = Py_None; | |
| int options = 0; | |
| short count = 0; | |
| if (!PyArg_ParseTuple(args, "|Oih", &pyobj, &options, &count)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| Base::PyTypeCheck(&pyobj, | |
| &DocumentObjectPy::Type, | |
| "Expect the first argument of type App.DocumentObject or None"); | |
| DocumentObject* obj = nullptr; | |
| if (pyobj) { | |
| obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr(); | |
| } | |
| auto links = GetApplication().getLinksTo(obj, options, count); | |
| Py::Tuple ret(links.size()); | |
| int i = 0; | |
| for (auto o : links) { | |
| ret.setItem(i++, Py::Object(o->getPyObject(), true)); | |
| } | |
| return Py::new_reference_to(ret); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sGetDependentObjects(PyObject* /*self*/, PyObject* args) | |
| { | |
| PyObject* obj; | |
| int options = 0; | |
| if (!PyArg_ParseTuple(args, "O|i", &obj, &options)) { | |
| return nullptr; | |
| } | |
| std::vector<App::DocumentObject*> objs; | |
| if (PySequence_Check(obj)) { | |
| Py::Sequence seq(obj); | |
| for (Py_ssize_t i = 0; i < seq.size(); ++i) { | |
| if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) { | |
| PyErr_SetString(PyExc_TypeError, | |
| "Expect element in sequence to be of type document object"); | |
| return nullptr; | |
| } | |
| objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr()); | |
| } | |
| } | |
| else if (!PyObject_TypeCheck(obj, &DocumentObjectPy::Type)) { | |
| PyErr_SetString( | |
| PyExc_TypeError, | |
| "Expect first argument to be either a document object or sequence of document objects"); | |
| return nullptr; | |
| } | |
| else { | |
| objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr()); | |
| } | |
| PY_TRY | |
| { | |
| auto ret = App::Document::getDependencyList(objs, options); | |
| Py::Tuple tuple(ret.size()); | |
| for (size_t i = 0; i < ret.size(); ++i) { | |
| tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true)); | |
| } | |
| return Py::new_reference_to(tuple); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sSetActiveTransaction(PyObject* /*self*/, PyObject* args) | |
| { | |
| char* name; | |
| PyObject* persist = Py_False; | |
| if (!PyArg_ParseTuple(args, "s|O!", &name, &PyBool_Type, &persist)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| Py::Long ret(GetApplication().setActiveTransaction(name, Base::asBoolean(persist))); | |
| return Py::new_reference_to(ret); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sGetActiveTransaction(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| int id = 0; | |
| const char* name = GetApplication().getActiveTransaction(&id); | |
| if (!name || id <= 0) { | |
| Py_Return; | |
| } | |
| Py::Tuple ret(2); | |
| ret.setItem(0, Py::String(name)); | |
| ret.setItem(1, Py::Long(id)); | |
| return Py::new_reference_to(ret); | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sCloseActiveTransaction(PyObject* /*self*/, PyObject* args) | |
| { | |
| PyObject* abort = Py_False; | |
| int id = 0; | |
| if (!PyArg_ParseTuple(args, "|O!i", &PyBool_Type, &abort, &id)) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| GetApplication().closeActiveTransaction(Base::asBoolean(abort), id); | |
| Py_Return; | |
| } | |
| PY_CATCH; | |
| } | |
| PyObject* Application::sCheckAbort(PyObject* /*self*/, PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| PY_TRY | |
| { | |
| Base::Sequencer().checkAbort(); | |
| Py_Return; | |
| } | |
| PY_CATCH | |
| } | |