1
/***************************************************************************
2
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This program is free software; you can redistribute it and/or modify *
7
* it under the terms of the GNU Library General Public License (LGPL) *
8
* as published by the Free Software Foundation; either version 2 of *
9
* the License, or (at your option) any later version. *
10
* for detail see the LICENCE text file. *
12
* FreeCAD is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU Library General Public License for more details. *
17
* You should have received a copy of the GNU Library General Public *
18
* License along with FreeCAD; if not, write to the Free Software *
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
22
***************************************************************************/
25
#include "PreCompiled.h"
27
#include <Base/Console.h>
28
#include <Base/Exception.h>
29
#include <Base/FileInfo.h>
30
#include <Base/Interpreter.h>
31
#include <Base/Parameter.h>
32
#include <Base/PyWrapParseTupleAndKeywords.h>
33
#include <Base/Sequencer.h>
35
#include "Application.h"
36
#include "DocumentPy.h"
37
#include "DocumentObserverPython.h"
38
#include "DocumentObjectPy.h"
41
//using Base::GetConsole;
46
//**************************************************************************
49
// Application methods structure
50
PyMethodDef Application::Methods[] = {
51
{"ParamGet", (PyCFunction) Application::sGetParam, METH_VARARGS,
52
"Get parameters by path"},
53
{"saveParameter", (PyCFunction) Application::sSaveParameter, METH_VARARGS,
54
"saveParameter(config='User parameter') -> None\n"
55
"Save parameter set to file. The default set is 'User parameter'"},
56
{"Version", (PyCFunction) Application::sGetVersion, METH_VARARGS,
57
"Print the version to the output."},
58
{"ConfigGet", (PyCFunction) Application::sGetConfig, METH_VARARGS,
59
"ConfigGet(string) -- Get the value for the given key."},
60
{"ConfigSet", (PyCFunction) Application::sSetConfig, METH_VARARGS,
61
"ConfigSet(string, string) -- Set the given key to the given value."},
62
{"ConfigDump", (PyCFunction) Application::sDumpConfig, METH_VARARGS,
63
"Dump the configuration to the output."},
64
{"addImportType", (PyCFunction) Application::sAddImportType, METH_VARARGS,
65
"Register filetype for import"},
66
{"changeImportModule", (PyCFunction) Application::sChangeImportModule, METH_VARARGS,
67
"Change the import module name of a registered filetype"},
68
{"getImportType", (PyCFunction) Application::sGetImportType, METH_VARARGS,
69
"Get the name of the module that can import the filetype"},
70
{"addExportType", (PyCFunction) Application::sAddExportType, METH_VARARGS,
71
"Register filetype for export"},
72
{"changeExportModule", (PyCFunction) Application::sChangeExportModule, METH_VARARGS,
73
"Change the export module name of a registered filetype"},
74
{"getExportType", (PyCFunction) Application::sGetExportType, METH_VARARGS,
75
"Get the name of the module that can export the filetype"},
76
{"getResourceDir", (PyCFunction) Application::sGetResourcePath, METH_VARARGS,
77
"Get the root directory of all resources"},
78
{"getLibraryDir", (PyCFunction) Application::sGetLibraryPath, METH_VARARGS,
79
"Get the directory of all extension modules"},
80
{"getTempPath", (PyCFunction) Application::sGetTempPath, METH_VARARGS,
81
"Get the root directory of cached files"},
82
{"getUserCachePath", (PyCFunction) Application::sGetUserCachePath, METH_VARARGS,
83
"Get the root path of cached files"},
84
{"getUserConfigDir", (PyCFunction) Application::sGetUserConfigPath, METH_VARARGS,
85
"Get the root path of user config files"},
86
{"getUserAppDataDir", (PyCFunction) Application::sGetUserAppDataPath, METH_VARARGS,
87
"Get the root directory of application data"},
88
{"getUserMacroDir", (PyCFunction) Application::sGetUserMacroPath, METH_VARARGS,
89
"getUserMacroDir(bool=False) -> string"
90
"Get the directory of the user's macro directory\n"
91
"If parameter is False (the default) it returns the standard path in the"
92
"user's home directory, otherwise it returns the user-defined path."},
93
{"getHelpDir", (PyCFunction) Application::sGetHelpPath, METH_VARARGS,
94
"Get the directory of the documentation"},
95
{"getHomePath", (PyCFunction) Application::sGetHomePath, METH_VARARGS,
96
"Get the home path, i.e. the parent directory of the executable"},
98
{"loadFile", (PyCFunction) Application::sLoadFile, METH_VARARGS,
99
"loadFile(string=filename,[string=module]) -> None\n\n"
100
"Loads an arbitrary file by delegating to the given Python module:\n"
101
"* If no module is given it will be determined by the file extension.\n"
102
"* If more than one module can load a file the first one will be taken.\n"
103
"* If no module exists to load the file an exception will be raised."},
104
{"open", reinterpret_cast<PyCFunction>(reinterpret_cast<void (*) ()>( Application::sOpenDocument )), METH_VARARGS|METH_KEYWORDS,
105
"See openDocument(string)"},
106
{"openDocument", reinterpret_cast<PyCFunction>(reinterpret_cast<void (*) ()>( Application::sOpenDocument )), METH_VARARGS|METH_KEYWORDS,
107
"openDocument(filepath,hidden=False) -> object\n"
108
"Create a document and load the project file into the document.\n\n"
109
"filepath: file path to an existing file. If the file doesn't exist\n"
110
" or the file cannot be loaded an I/O exception is thrown.\n"
111
" In this case the document is kept alive.\n"
112
"hidden: whether to hide document 3D view."},
113
// {"saveDocument", (PyCFunction) Application::sSaveDocument, METH_VARARGS,
114
// "saveDocument(string) -- Save the document to a file."},
115
// {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, METH_VARARGS},
116
{"newDocument", reinterpret_cast<PyCFunction>(reinterpret_cast<void (*) ()>( Application::sNewDocument )), METH_VARARGS|METH_KEYWORDS,
117
"newDocument(name, label=None, hidden=False, temp=False) -> object\n"
118
"Create a new document with a given name.\n\n"
119
"name: unique document name which is checked automatically.\n"
120
"label: optional user changeable label for the document.\n"
121
"hidden: whether to hide document 3D view.\n"
122
"temp: mark the document as temporary so that it will not be saved"},
123
{"closeDocument", (PyCFunction) Application::sCloseDocument, METH_VARARGS,
124
"closeDocument(string) -> None\n\n"
125
"Close the document with a given name."},
126
{"activeDocument", (PyCFunction) Application::sActiveDocument, METH_VARARGS,
127
"activeDocument() -> object or None\n\n"
128
"Return the active document or None if there is no one."},
129
{"setActiveDocument", (PyCFunction) Application::sSetActiveDocument, METH_VARARGS,
130
"setActiveDocement(string) -> None\n\n"
131
"Set the active document by its name."},
132
{"getDocument", (PyCFunction) Application::sGetDocument, METH_VARARGS,
133
"getDocument(string) -> object\n\n"
134
"Get a document by its name or raise an exception\n"
135
"if there is no document with the given name."},
136
{"listDocuments", (PyCFunction) Application::sListDocuments, METH_VARARGS,
137
"listDocuments(sort=False) -> list\n\n"
138
"Return a list of names of all documents, optionally sort in dependency order."},
139
{"addDocumentObserver", (PyCFunction) Application::sAddDocObserver, METH_VARARGS,
140
"addDocumentObserver() -> None\n\n"
141
"Add an observer to get notified about changes on documents."},
142
{"removeDocumentObserver", (PyCFunction) Application::sRemoveDocObserver, METH_VARARGS,
143
"removeDocumentObserver() -> None\n\n"
144
"Remove an added document observer."},
145
{"setLogLevel", (PyCFunction) Application::sSetLogLevel, METH_VARARGS,
146
"setLogLevel(tag, level) -- Set the log level for a string tag.\n"
147
"'level' can either be string 'Log', 'Msg', 'Wrn', 'Error', or an integer value"},
148
{"getLogLevel", (PyCFunction) Application::sGetLogLevel, METH_VARARGS,
149
"getLogLevel(tag) -- Get the log level of a string tag"},
150
{"checkLinkDepth", (PyCFunction) Application::sCheckLinkDepth, METH_VARARGS,
151
"checkLinkDepth(depth) -- check link recursion depth"},
152
{"getLinksTo", (PyCFunction) Application::sGetLinksTo, METH_VARARGS,
153
"getLinksTo(obj,options=0,maxCount=0) -- return the objects linked to 'obj'\n\n"
154
"options: 1: recursive, 2: check link array. Options can combine.\n"
155
"maxCount: to limit the number of links returned\n"},
156
{"getDependentObjects", (PyCFunction) Application::sGetDependentObjects, METH_VARARGS,
157
"getDependentObjects(obj|[obj,...], options=0)\n"
158
"Return a list of dependent objects including the given objects.\n\n"
159
"options: can have the following bit flags,\n"
160
" 1: to sort the list in topological order.\n"
161
" 2: to exclude dependency of Link type object."},
162
{"setActiveTransaction", (PyCFunction) Application::sSetActiveTransaction, METH_VARARGS,
163
"setActiveTransaction(name, persist=False) -- setup active transaction with the given name\n\n"
164
"name: the transaction name\n"
165
"persist(False): by default, if the calling code is inside any invocation of a command, it\n"
166
" will be auto closed once all commands within the current stack exists. To\n"
167
" disable auto closing, set persist=True\n"
168
"Returns the transaction ID for the active transaction. An application-wide\n"
169
"active transaction causes any document changes to open a transaction with\n"
170
"the given name and ID."},
171
{"getActiveTransaction", (PyCFunction) Application::sGetActiveTransaction, METH_VARARGS,
172
"getActiveTransaction() -> (name,id) return the current active transaction name and ID"},
173
{"closeActiveTransaction", (PyCFunction) Application::sCloseActiveTransaction, METH_VARARGS,
174
"closeActiveTransaction(abort=False) -- commit or abort current active transaction"},
175
{"isRestoring", (PyCFunction) Application::sIsRestoring, METH_VARARGS,
176
"isRestoring() -> Bool -- Test if the application is opening some document"},
177
{"checkAbort", (PyCFunction) Application::sCheckAbort, METH_VARARGS,
178
"checkAbort() -- check for user abort in length operation.\n\n"
179
"This only works if there is an active sequencer (or ProgressIndicator in Python).\n"
180
"There is an active sequencer during document restore and recomputation. User may\n"
181
"abort the operation by pressing the ESC key. Once detected, this function will\n"
182
"trigger a Base.FreeCADAbort exception."},
183
{nullptr, nullptr, 0, nullptr} /* Sentinel */
187
PyObject* Application::sLoadFile(PyObject * /*self*/, PyObject *args)
192
if (!PyArg_ParseTuple(args, "s|ss", &path, &doc, &mod))
195
Base::FileInfo fi(path);
196
if (!fi.isFile() || !fi.exists()) {
197
PyErr_Format(PyExc_IOError, "File %s doesn't exist.", path);
201
std::string module = mod;
202
if (module.empty()) {
203
std::string ext = fi.extension();
204
std::vector<std::string> modules = GetApplication().getImportModules(ext.c_str());
205
if (modules.empty()) {
206
PyErr_Format(PyExc_IOError, "Filetype %s is not supported.", ext.c_str());
210
module = modules.front();
214
// path could contain characters that need escaping, such as quote signs
215
// therefore use its representation in the Python code string
216
PyObject *pathObj = PyUnicode_FromString(path);
217
PyObject *pathReprObj = PyObject_Repr(pathObj);
218
const char *pathRepr = PyUnicode_AsUTF8(pathReprObj);
220
std::stringstream str;
221
str << "import " << module << std::endl;
222
if (fi.hasExtension("FCStd"))
223
str << module << ".openDocument(" << pathRepr << ")" << std::endl;
225
str << module << ".insert(" << pathRepr << ",'" << doc << "')" << std::endl;
228
Py_DECREF(pathReprObj);
230
Base::Interpreter().runString(str.str().c_str());
233
catch (const Base::Exception& e) {
237
catch (const std::exception& e) {
238
// might be subclass from zipios
239
PyErr_Format(PyExc_IOError, "Invalid project file %s: %s", path, e.what());
244
PyObject* Application::sIsRestoring(PyObject * /*self*/, PyObject *args) {
245
if (!PyArg_ParseTuple(args, ""))
247
return Py::new_reference_to(Py::Boolean(GetApplication().isRestoring()));
250
PyObject* Application::sOpenDocument(PyObject * /*self*/, PyObject *args, PyObject *kwd)
253
PyObject *hidden = Py_False;
254
static const std::array<const char *, 3> kwlist {"name", "hidden", nullptr};
255
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "et|O!", kwlist,
256
"utf-8", &Name, &PyBool_Type, &hidden)) {
259
std::string EncodedName = std::string(Name);
262
// return new document
263
return (GetApplication().openDocument(EncodedName.c_str(), !Base::asBoolean(hidden))->getPyObject());
265
catch (const Base::Exception& e) {
266
PyErr_SetString(PyExc_IOError, e.what());
269
catch (const std::exception& e) {
270
// might be subclass from zipios
271
PyErr_Format(PyExc_IOError, "Invalid project file %s: %s\n", EncodedName.c_str(), e.what());
276
PyObject* Application::sNewDocument(PyObject * /*self*/, PyObject *args, PyObject *kwd)
278
char *docName = nullptr;
279
char *usrName = nullptr;
280
PyObject *hidden = Py_False;
281
PyObject *temp = Py_False;
282
static const std::array<const char *, 5> kwlist {"name", "label", "hidden", "temp", nullptr};
283
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|etetO!O!", kwlist,
284
"utf-8", &docName, "utf-8", &usrName, &PyBool_Type, &hidden, &PyBool_Type, &temp)) {
289
App::Document* doc = GetApplication().newDocument(docName, usrName, !Base::asBoolean(hidden), Base::asBoolean(temp));
292
return doc->getPyObject();
296
PyObject* Application::sSetActiveDocument(PyObject * /*self*/, PyObject *args)
298
char *pstr = nullptr;
299
if (!PyArg_ParseTuple(args, "s", &pstr))
303
GetApplication().setActiveDocument(pstr);
305
catch (const Base::Exception& e) {
313
PyObject* Application::sCloseDocument(PyObject * /*self*/, PyObject *args)
315
char *pstr = nullptr;
316
if (!PyArg_ParseTuple(args, "s", &pstr))
319
Document* doc = GetApplication().getDocument(pstr);
321
PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
324
if (!doc->isClosable()) {
325
PyErr_Format(PyExc_RuntimeError, "The document '%s' is not closable for the moment", pstr);
329
if (!GetApplication().closeDocument(pstr)) {
330
PyErr_Format(PyExc_RuntimeError, "Closing the document '%s' failed", pstr);
337
PyObject* Application::sSaveDocument(PyObject * /*self*/, PyObject *args)
340
if (!PyArg_ParseTuple(args, "s", &pDoc))
343
Document* doc = GetApplication().getDocument(pDoc);
346
PyErr_Format(Base::PyExc_FC_GeneralError, "Cannot save document '%s'", pDoc);
351
PyErr_Format(PyExc_NameError, "Unknown document '%s'", pDoc);
358
PyObject* Application::sActiveDocument(PyObject * /*self*/, PyObject *args)
360
if (!PyArg_ParseTuple(args, ""))
363
Document* doc = GetApplication().getActiveDocument();
365
return doc->getPyObject();
373
PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args)
376
if (!PyArg_ParseTuple(args, "s", &pstr))
379
Document* doc = GetApplication().getDocument(pstr);
381
PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
385
return doc->getPyObject();
388
PyObject* Application::sGetParam(PyObject * /*self*/, PyObject *args)
391
if (!PyArg_ParseTuple(args, "s", &pstr))
395
return GetPyObject(GetApplication().GetParameterGroupByPath(pstr));
399
PyObject* Application::sSaveParameter(PyObject * /*self*/, PyObject *args)
401
const char *pstr = "User parameter";
402
if (!PyArg_ParseTuple(args, "|s", &pstr))
406
ParameterManager* param = App::GetApplication().GetParameterSet(pstr);
408
std::stringstream str;
409
str << "No parameter set found with name: " << pstr;
410
PyErr_SetString(PyExc_ValueError, str.str().c_str());
413
else if (!param->HasSerializer()) {
414
std::stringstream str;
415
str << "Parameter set cannot be serialized: " << pstr;
416
PyErr_SetString(PyExc_RuntimeError, str.str().c_str());
420
param->SaveDocument();
427
PyObject* Application::sGetConfig(PyObject * /*self*/, PyObject *args)
431
if (!PyArg_ParseTuple(args, "s", &pstr))
433
const std::map<std::string, std::string>& Map = GetApplication().Config();
435
std::map<std::string, std::string>::const_iterator it = Map.find(pstr);
436
if (it != Map.end()) {
437
return Py_BuildValue("s", it->second.c_str());
440
// do not set an error because this may break existing python code
441
return PyUnicode_FromString("");
445
PyObject* Application::sDumpConfig(PyObject * /*self*/, PyObject *args)
447
if (!PyArg_ParseTuple(args, ""))
450
PyObject *dict = PyDict_New();
451
for (const auto & It : GetApplication()._mConfig) {
452
PyDict_SetItemString(dict, It.first.c_str(), PyUnicode_FromString(It.second.c_str()));
457
PyObject* Application::sSetConfig(PyObject * /*self*/, PyObject *args)
461
if (!PyArg_ParseTuple(args, "ss", &pstr, &pstr2))
464
GetApplication()._mConfig[pstr] = pstr2;
470
PyObject* Application::sGetVersion(PyObject * /*self*/, PyObject *args)
472
if (!PyArg_ParseTuple(args, ""))
476
const std::map<std::string, std::string>& cfg = Application::Config();
477
std::map<std::string, std::string>::const_iterator it;
479
it = cfg.find("BuildVersionMajor");
480
list.append(Py::String(it != cfg.end() ? it->second : ""));
482
it = cfg.find("BuildVersionMinor");
483
list.append(Py::String(it != cfg.end() ? it->second : ""));
485
it = cfg.find("BuildVersionPoint");
486
list.append(Py::String(it != cfg.end() ? it->second : ""));
488
it = cfg.find("BuildRevision");
489
list.append(Py::String(it != cfg.end() ? it->second : ""));
491
it = cfg.find("BuildRepositoryURL");
492
list.append(Py::String(it != cfg.end() ? it->second : ""));
494
it = cfg.find("BuildRevisionDate");
495
list.append(Py::String(it != cfg.end() ? it->second : ""));
497
it = cfg.find("BuildRevisionBranch");
499
list.append(Py::String(it->second));
501
it = cfg.find("BuildRevisionHash");
503
list.append(Py::String(it->second));
505
return Py::new_reference_to(list);
508
PyObject* Application::sAddImportType(PyObject * /*self*/, PyObject *args)
512
if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod))
515
GetApplication().addImportType(psKey,psMod);
520
PyObject* Application::sChangeImportModule(PyObject * /*self*/, PyObject *args)
522
char *key,*oldMod,*newMod;
524
if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod))
527
GetApplication().changeImportModule(key,oldMod,newMod);
532
PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args)
536
if (!PyArg_ParseTuple(args, "|s", &psKey))
541
std::vector<std::string> modules = GetApplication().getImportModules(psKey);
542
for (const auto & it : modules) {
543
list.append(Py::String(it));
546
return Py::new_reference_to(list);
550
std::vector<std::string> types = GetApplication().getImportTypes();
551
for (const auto & it : types) {
552
std::vector<std::string> modules = GetApplication().getImportModules(it.c_str());
553
if (modules.empty()) {
554
dict.setItem(it.c_str(), Py::None());
556
else if (modules.size() == 1) {
557
dict.setItem(it.c_str(), Py::String(modules.front()));
561
for (const auto & jt : modules) {
562
list.append(Py::String(jt));
564
dict.setItem(it.c_str(), list);
568
return Py::new_reference_to(dict);
572
PyObject* Application::sAddExportType(PyObject * /*self*/, PyObject *args)
576
if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod))
579
GetApplication().addExportType(psKey,psMod);
584
PyObject* Application::sChangeExportModule(PyObject * /*self*/, PyObject *args)
586
char *key,*oldMod,*newMod;
588
if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod))
591
GetApplication().changeExportModule(key,oldMod,newMod);
596
PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args)
600
if (!PyArg_ParseTuple(args, "|s", &psKey))
605
std::vector<std::string> modules = GetApplication().getExportModules(psKey);
606
for (const auto & it : modules) {
607
list.append(Py::String(it));
610
return Py::new_reference_to(list);
614
std::vector<std::string> types = GetApplication().getExportTypes();
615
for (const auto & it : types) {
616
std::vector<std::string> modules = GetApplication().getExportModules(it.c_str());
617
if (modules.empty()) {
618
dict.setItem(it.c_str(), Py::None());
620
else if (modules.size() == 1) {
621
dict.setItem(it.c_str(), Py::String(modules.front()));
625
for (const auto & jt : modules) {
626
list.append(Py::String(jt));
628
dict.setItem(it.c_str(), list);
632
return Py::new_reference_to(dict);
636
PyObject* Application::sGetResourcePath(PyObject * /*self*/, PyObject *args)
638
if (!PyArg_ParseTuple(args, ""))
641
Py::String datadir(Application::getResourceDir(),"utf-8");
642
return Py::new_reference_to(datadir);
645
PyObject* Application::sGetLibraryPath(PyObject * /*self*/, PyObject *args)
647
if (!PyArg_ParseTuple(args, ""))
650
Py::String datadir(Application::getLibraryDir(),"utf-8");
651
return Py::new_reference_to(datadir);
654
PyObject* Application::sGetTempPath(PyObject * /*self*/, PyObject *args)
656
if (!PyArg_ParseTuple(args, ""))
659
Py::String datadir(Application::getTempPath(),"utf-8");
660
return Py::new_reference_to(datadir);
663
PyObject* Application::sGetUserCachePath(PyObject * /*self*/, PyObject *args)
665
if (!PyArg_ParseTuple(args, ""))
668
Py::String datadir(Application::getUserCachePath(),"utf-8");
669
return Py::new_reference_to(datadir);
672
PyObject* Application::sGetUserConfigPath(PyObject * /*self*/, PyObject *args)
674
if (!PyArg_ParseTuple(args, ""))
677
Py::String datadir(Application::getUserConfigPath(),"utf-8");
678
return Py::new_reference_to(datadir);
681
PyObject* Application::sGetUserAppDataPath(PyObject * /*self*/, PyObject *args)
683
if (!PyArg_ParseTuple(args, ""))
686
Py::String user_data_dir(Application::getUserAppDataDir(),"utf-8");
687
return Py::new_reference_to(user_data_dir);
690
PyObject* Application::sGetUserMacroPath(PyObject * /*self*/, PyObject *args)
692
PyObject *actual = Py_False;
693
if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &actual))
696
std::string macroDir = Application::getUserMacroDir();
697
if (Base::asBoolean(actual)) {
698
macroDir = App::GetApplication().
699
GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro")
700
->GetASCII("MacroPath", macroDir.c_str());
701
std::replace(macroDir.begin(), macroDir.end(), '/', PATHSEP);
704
Py::String user_macro_dir(macroDir,"utf-8");
705
return Py::new_reference_to(user_macro_dir);
708
PyObject* Application::sGetHelpPath(PyObject * /*self*/, PyObject *args)
710
if (!PyArg_ParseTuple(args, ""))
713
Py::String user_macro_dir(Application::getHelpDir(),"utf-8");
714
return Py::new_reference_to(user_macro_dir);
717
PyObject* Application::sGetHomePath(PyObject * /*self*/, PyObject *args)
719
if (!PyArg_ParseTuple(args, ""))
722
Py::String homedir(Application::getHomePath(),"utf-8");
723
return Py::new_reference_to(homedir);
726
PyObject* Application::sListDocuments(PyObject * /*self*/, PyObject *args)
728
PyObject *sort = Py_False;
729
if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort))
732
PyObject *pDict = PyDict_New();
734
Base::PyObjectBase* pValue;
736
std::vector<Document*> docs = GetApplication().getDocuments();;
737
if (Base::asBoolean(sort))
738
docs = Document::getDependentDocuments(docs,true);
740
for (auto doc : docs) {
741
pKey = PyUnicode_FromString(doc->getName());
742
// GetPyObject() increments
743
pValue = static_cast<Base::PyObjectBase*>(doc->getPyObject());
744
PyDict_SetItem(pDict, pKey, pValue);
745
// now we can decrement again as PyDict_SetItem also has incremented
753
PyObject* Application::sAddDocObserver(PyObject * /*self*/, PyObject *args)
756
if (!PyArg_ParseTuple(args, "O",&o))
759
DocumentObserverPython::addObserver(Py::Object(o));
764
PyObject* Application::sRemoveDocObserver(PyObject * /*self*/, PyObject *args)
767
if (!PyArg_ParseTuple(args, "O",&o))
770
DocumentObserverPython::removeObserver(Py::Object(o));
775
PyObject *Application::sSetLogLevel(PyObject * /*self*/, PyObject *args)
779
if (!PyArg_ParseTuple(args, "sO", &tag, &pcObj))
783
if (PyUnicode_Check(pcObj)) {
784
const char *pstr = PyUnicode_AsUTF8(pcObj);
785
if(strcmp(pstr,"Log") == 0)
787
else if(strcmp(pstr,"Warning") == 0)
788
l = FC_LOGLEVEL_WARN;
789
else if(strcmp(pstr,"Message") == 0)
791
else if(strcmp(pstr,"Error") == 0)
793
else if(strcmp(pstr,"Trace") == 0)
794
l = FC_LOGLEVEL_TRACE;
795
else if(strcmp(pstr,"Default") == 0)
796
l = FC_LOGLEVEL_DEFAULT;
798
Py_Error(PyExc_ValueError,
799
"Unknown Log Level (use 'Default', 'Error', 'Warning', 'Message', 'Log', 'Trace' or an integer)");
803
l = PyLong_AsLong(pcObj);
804
GetApplication().GetParameterGroupByPath("User parameter:BaseApp/LogLevels")->SetInt(tag,l);
805
if(strcmp(tag,"Default") == 0) {
807
if(l>=0) Base::Console().SetDefaultLogLevel(l);
809
}else if(strcmp(tag,"DebugDefault") == 0) {
811
if(l>=0) Base::Console().SetDefaultLogLevel(l);
814
*Base::Console().GetLogLevel(tag) = l;
820
PyObject *Application::sGetLogLevel(PyObject * /*self*/, PyObject *args)
823
if (!PyArg_ParseTuple(args, "s", &tag))
828
if(strcmp(tag,"Default")==0) {
830
l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag,-1);
832
}else if(strcmp(tag,"DebugDefault")==0) {
834
l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag,-1);
837
int *pl = Base::Console().GetLogLevel(tag,false);
840
// For performance reason, we only output integer value
841
return Py_BuildValue("i",Base::Console().LogLevel(l));
845
PyObject *Application::sCheckLinkDepth(PyObject * /*self*/, PyObject *args)
848
if (!PyArg_ParseTuple(args, "h", &depth))
852
return Py::new_reference_to(Py::Int(GetApplication().checkLinkDepth(depth, MessageOption::Throw)));
856
PyObject *Application::sGetLinksTo(PyObject * /*self*/, PyObject *args)
858
PyObject *pyobj = Py_None;
861
if (!PyArg_ParseTuple(args, "|Oih",&pyobj,&options, &count))
865
Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type App.DocumentObject or None");
866
DocumentObject *obj = nullptr;
868
obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
870
auto links = GetApplication().getLinksTo(obj,options,count);
871
Py::Tuple ret(links.size());
874
ret.setItem(i++,Py::Object(o->getPyObject(),true));
876
return Py::new_reference_to(ret);
881
PyObject *Application::sGetDependentObjects(PyObject * /*self*/, PyObject *args)
885
if (!PyArg_ParseTuple(args, "O|i", &obj,&options))
888
std::vector<App::DocumentObject*> objs;
889
if (PySequence_Check(obj)) {
890
Py::Sequence seq(obj);
891
for (Py_ssize_t i=0;i<seq.size();++i) {
892
if(!PyObject_TypeCheck(seq[i].ptr(),&DocumentObjectPy::Type)) {
893
PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
896
objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
899
else if(!PyObject_TypeCheck(obj,&DocumentObjectPy::Type)) {
900
PyErr_SetString(PyExc_TypeError,
901
"Expect first argument to be either a document object or sequence of document objects");
905
objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
909
auto ret = App::Document::getDependencyList(objs,options);
911
Py::Tuple tuple(ret.size());
912
for(size_t i=0;i<ret.size();++i)
913
tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
914
return Py::new_reference_to(tuple);
919
PyObject *Application::sSetActiveTransaction(PyObject * /*self*/, PyObject *args)
922
PyObject *persist = Py_False;
923
if (!PyArg_ParseTuple(args, "s|O!", &name, &PyBool_Type, &persist))
927
Py::Int ret(GetApplication().setActiveTransaction(name, Base::asBoolean(persist)));
928
return Py::new_reference_to(ret);
932
PyObject *Application::sGetActiveTransaction(PyObject * /*self*/, PyObject *args)
934
if (!PyArg_ParseTuple(args, ""))
939
const char *name = GetApplication().getActiveTransaction(&id);
943
ret.setItem(0,Py::String(name));
944
ret.setItem(1,Py::Int(id));
945
return Py::new_reference_to(ret);
949
PyObject *Application::sCloseActiveTransaction(PyObject * /*self*/, PyObject *args)
951
PyObject *abort = Py_False;
953
if (!PyArg_ParseTuple(args, "|O!i", &PyBool_Type, &abort,&id))
957
GetApplication().closeActiveTransaction(Base::asBoolean(abort), id);
962
PyObject *Application::sCheckAbort(PyObject * /*self*/, PyObject *args)
964
if (!PyArg_ParseTuple(args, ""))
968
Base::Sequencer().checkAbort();