FreeCAD

Форк
0
/
ApplicationPy.cpp 
971 строка · 35.2 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de>              *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
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.                                 *
11
 *                                                                         *
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.                  *
16
 *                                                                         *
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  *
20
 *   USA                                                                   *
21
 *                                                                         *
22
 ***************************************************************************/
23

24

25
#include "PreCompiled.h"
26

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>
34

35
#include "Application.h"
36
#include "DocumentPy.h"
37
#include "DocumentObserverPython.h"
38
#include "DocumentObjectPy.h"
39

40

41
//using Base::GetConsole;
42
using namespace Base;
43
using namespace App;
44

45

46
//**************************************************************************
47
// Python stuff
48

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"},
97

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 */
184
};
185

186

187
PyObject* Application::sLoadFile(PyObject * /*self*/, PyObject *args)
188
{
189
    const char *path;
190
    const char *doc="";
191
    const char *mod="";
192
    if (!PyArg_ParseTuple(args, "s|ss", &path, &doc, &mod))
193
        return nullptr;
194
    try {
195
        Base::FileInfo fi(path);
196
        if (!fi.isFile() || !fi.exists()) {
197
            PyErr_Format(PyExc_IOError, "File %s doesn't exist.", path);
198
            return nullptr;
199
        }
200

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());
207
                return nullptr;
208
            }
209
            else {
210
                module = modules.front();
211
            }
212
        }
213

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);
219

220
        std::stringstream str;
221
        str << "import " << module << std::endl;
222
        if (fi.hasExtension("FCStd"))
223
            str << module << ".openDocument(" << pathRepr << ")" << std::endl;
224
        else
225
            str << module << ".insert(" << pathRepr << ",'" << doc << "')" << std::endl;
226

227
        Py_DECREF(pathObj);
228
        Py_DECREF(pathReprObj);
229

230
        Base::Interpreter().runString(str.str().c_str());
231
        Py_Return;
232
    }
233
    catch (const Base::Exception& e) {
234
        e.setPyException();
235
        return nullptr;
236
    }
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());
240
        return nullptr;
241
    }
242
}
243

244
PyObject* Application::sIsRestoring(PyObject * /*self*/, PyObject *args) {
245
    if (!PyArg_ParseTuple(args, ""))
246
        return nullptr;
247
    return Py::new_reference_to(Py::Boolean(GetApplication().isRestoring()));
248
}
249

250
PyObject* Application::sOpenDocument(PyObject * /*self*/, PyObject *args, PyObject *kwd)
251
{
252
    char* Name;
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)) {
257
        return nullptr;
258
    }
259
    std::string EncodedName = std::string(Name);
260
    PyMem_Free(Name);
261
    try {
262
        // return new document
263
        return (GetApplication().openDocument(EncodedName.c_str(), !Base::asBoolean(hidden))->getPyObject());
264
    }
265
    catch (const Base::Exception& e) {
266
        PyErr_SetString(PyExc_IOError, e.what());
267
        return nullptr;
268
    }
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());
272
        return nullptr;
273
    }
274
}
275

276
PyObject* Application::sNewDocument(PyObject * /*self*/, PyObject *args, PyObject *kwd)
277
{
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)) {
285
        return nullptr;
286
    }
287

288
    PY_TRY {
289
        App::Document* doc = GetApplication().newDocument(docName, usrName, !Base::asBoolean(hidden), Base::asBoolean(temp));
290
        PyMem_Free(docName);
291
        PyMem_Free(usrName);
292
        return doc->getPyObject();
293
    }PY_CATCH;
294
}
295

296
PyObject* Application::sSetActiveDocument(PyObject * /*self*/, PyObject *args)
297
{
298
    char *pstr = nullptr;
299
    if (!PyArg_ParseTuple(args, "s", &pstr))
300
        return nullptr;
301

302
    try {
303
        GetApplication().setActiveDocument(pstr);
304
    }
305
    catch (const Base::Exception& e) {
306
        e.setPyException();
307
        return nullptr;
308
    }
309

310
    Py_Return;
311
}
312

313
PyObject* Application::sCloseDocument(PyObject * /*self*/, PyObject *args)
314
{
315
    char *pstr = nullptr;
316
    if (!PyArg_ParseTuple(args, "s", &pstr))
317
        return nullptr;
318

319
    Document* doc = GetApplication().getDocument(pstr);
320
    if (!doc) {
321
        PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
322
        return nullptr;
323
    }
324
    if (!doc->isClosable()) {
325
        PyErr_Format(PyExc_RuntimeError, "The document '%s' is not closable for the moment", pstr);
326
        return nullptr;
327
    }
328

329
    if (!GetApplication().closeDocument(pstr)) {
330
        PyErr_Format(PyExc_RuntimeError, "Closing the document '%s' failed", pstr);
331
        return nullptr;
332
    }
333

334
    Py_Return;
335
}
336

337
PyObject* Application::sSaveDocument(PyObject * /*self*/, PyObject *args)
338
{
339
    char *pDoc;
340
    if (!PyArg_ParseTuple(args, "s", &pDoc))
341
        return nullptr;
342

343
    Document* doc = GetApplication().getDocument(pDoc);
344
    if ( doc ) {
345
        if (!doc->save()) {
346
            PyErr_Format(Base::PyExc_FC_GeneralError, "Cannot save document '%s'", pDoc);
347
            return nullptr;
348
        }
349
    }
350
    else {
351
        PyErr_Format(PyExc_NameError, "Unknown document '%s'", pDoc);
352
        return nullptr;
353
    }
354

355
    Py_Return;
356
}
357

358
PyObject* Application::sActiveDocument(PyObject * /*self*/, PyObject *args)
359
{
360
    if (!PyArg_ParseTuple(args, ""))
361
        return nullptr;
362

363
    Document* doc = GetApplication().getActiveDocument();
364
    if (doc) {
365
        return doc->getPyObject();
366
    }
367
    else {
368
        Py_INCREF(Py_None);
369
        return Py_None;
370
    }
371
}
372

373
PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args)
374
{
375
    char *pstr=nullptr;
376
    if (!PyArg_ParseTuple(args, "s", &pstr))
377
        return nullptr;
378

379
    Document* doc = GetApplication().getDocument(pstr);
380
    if ( !doc ) {
381
        PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
382
        return nullptr;
383
    }
384

385
    return doc->getPyObject();
386
}
387

388
PyObject* Application::sGetParam(PyObject * /*self*/, PyObject *args)
389
{
390
    char *pstr=nullptr;
391
    if (!PyArg_ParseTuple(args, "s", &pstr))
392
        return nullptr;
393

394
    PY_TRY {
395
        return GetPyObject(GetApplication().GetParameterGroupByPath(pstr));
396
    }PY_CATCH;
397
}
398

399
PyObject* Application::sSaveParameter(PyObject * /*self*/, PyObject *args)
400
{
401
    const char *pstr = "User parameter";
402
    if (!PyArg_ParseTuple(args, "|s", &pstr))
403
        return nullptr;
404

405
    PY_TRY {
406
        ParameterManager* param = App::GetApplication().GetParameterSet(pstr);
407
        if (!param) {
408
            std::stringstream str;
409
            str << "No parameter set found with name: " << pstr;
410
            PyErr_SetString(PyExc_ValueError, str.str().c_str());
411
            return nullptr;
412
        }
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());
417
            return nullptr;
418
        }
419

420
        param->SaveDocument();
421
        Py_INCREF(Py_None);
422
        return Py_None;
423
    }PY_CATCH;
424
}
425

426

427
PyObject* Application::sGetConfig(PyObject * /*self*/, PyObject *args)
428
{
429
    char *pstr;
430

431
    if (!PyArg_ParseTuple(args, "s", &pstr))
432
        return nullptr;
433
    const std::map<std::string, std::string>& Map = GetApplication().Config();
434

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());
438
    }
439
    else {
440
        // do not set an error because this may break existing python code
441
        return PyUnicode_FromString("");
442
    }
443
}
444

445
PyObject* Application::sDumpConfig(PyObject * /*self*/, PyObject *args)
446
{
447
    if (!PyArg_ParseTuple(args, ""))
448
        return nullptr;
449

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()));
453
    }
454
    return dict;
455
}
456

457
PyObject* Application::sSetConfig(PyObject * /*self*/, PyObject *args)
458
{
459
    char *pstr, *pstr2;
460

461
    if (!PyArg_ParseTuple(args, "ss", &pstr, &pstr2))
462
        return nullptr;
463

464
    GetApplication()._mConfig[pstr] = pstr2;
465

466
    Py_INCREF(Py_None);
467
    return Py_None;
468
}
469

470
PyObject* Application::sGetVersion(PyObject * /*self*/, PyObject *args)
471
{
472
    if (!PyArg_ParseTuple(args, ""))
473
        return nullptr;
474

475
    Py::List list;
476
    const std::map<std::string, std::string>& cfg = Application::Config();
477
    std::map<std::string, std::string>::const_iterator it;
478

479
    it = cfg.find("BuildVersionMajor");
480
    list.append(Py::String(it != cfg.end() ? it->second : ""));
481

482
    it = cfg.find("BuildVersionMinor");
483
    list.append(Py::String(it != cfg.end() ? it->second : ""));
484

485
    it = cfg.find("BuildVersionPoint");
486
    list.append(Py::String(it != cfg.end() ? it->second : ""));
487

488
    it = cfg.find("BuildRevision");
489
    list.append(Py::String(it != cfg.end() ? it->second : ""));
490

491
    it = cfg.find("BuildRepositoryURL");
492
    list.append(Py::String(it != cfg.end() ? it->second : ""));
493

494
    it = cfg.find("BuildRevisionDate");
495
    list.append(Py::String(it != cfg.end() ? it->second : ""));
496

497
    it = cfg.find("BuildRevisionBranch");
498
    if (it != cfg.end())
499
        list.append(Py::String(it->second));
500

501
    it = cfg.find("BuildRevisionHash");
502
    if (it != cfg.end())
503
        list.append(Py::String(it->second));
504

505
    return Py::new_reference_to(list);
506
}
507

508
PyObject* Application::sAddImportType(PyObject * /*self*/, PyObject *args)
509
{
510
    char *psKey,*psMod;
511

512
    if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod))
513
        return nullptr;
514

515
    GetApplication().addImportType(psKey,psMod);
516

517
    Py_Return;
518
}
519

520
PyObject* Application::sChangeImportModule(PyObject * /*self*/, PyObject *args)
521
{
522
    char *key,*oldMod,*newMod;
523

524
    if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod))
525
        return nullptr;
526

527
    GetApplication().changeImportModule(key,oldMod,newMod);
528

529
    Py_Return;
530
}
531

532
PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args)
533
{
534
    char*       psKey=nullptr;
535

536
    if (!PyArg_ParseTuple(args, "|s", &psKey))
537
        return nullptr;
538

539
    if (psKey) {
540
        Py::List list;
541
        std::vector<std::string> modules = GetApplication().getImportModules(psKey);
542
        for (const auto & it : modules) {
543
            list.append(Py::String(it));
544
        }
545

546
        return Py::new_reference_to(list);
547
    }
548
    else {
549
        Py::Dict dict;
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());
555
            }
556
            else if (modules.size() == 1) {
557
                dict.setItem(it.c_str(), Py::String(modules.front()));
558
            }
559
            else {
560
                Py::List list;
561
                for (const auto & jt : modules) {
562
                    list.append(Py::String(jt));
563
                }
564
                dict.setItem(it.c_str(), list);
565
            }
566
        }
567

568
        return Py::new_reference_to(dict);
569
    }
570
}
571

572
PyObject* Application::sAddExportType(PyObject * /*self*/, PyObject *args)
573
{
574
    char *psKey,*psMod;
575

576
    if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod))
577
        return nullptr;
578

579
    GetApplication().addExportType(psKey,psMod);
580

581
    Py_Return;
582
}
583

584
PyObject* Application::sChangeExportModule(PyObject * /*self*/, PyObject *args)
585
{
586
    char *key,*oldMod,*newMod;
587

588
    if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod))
589
        return nullptr;
590

591
    GetApplication().changeExportModule(key,oldMod,newMod);
592

593
    Py_Return;
594
}
595

596
PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args)
597
{
598
    char*       psKey=nullptr;
599

600
    if (!PyArg_ParseTuple(args, "|s", &psKey))
601
        return nullptr;
602

603
    if (psKey) {
604
        Py::List list;
605
        std::vector<std::string> modules = GetApplication().getExportModules(psKey);
606
        for (const auto & it : modules) {
607
            list.append(Py::String(it));
608
        }
609

610
        return Py::new_reference_to(list);
611
    }
612
    else {
613
        Py::Dict dict;
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());
619
            }
620
            else if (modules.size() == 1) {
621
                dict.setItem(it.c_str(), Py::String(modules.front()));
622
            }
623
            else {
624
                Py::List list;
625
                for (const auto & jt : modules) {
626
                    list.append(Py::String(jt));
627
                }
628
                dict.setItem(it.c_str(), list);
629
            }
630
        }
631

632
        return Py::new_reference_to(dict);
633
    }
634
}
635

636
PyObject* Application::sGetResourcePath(PyObject * /*self*/, PyObject *args)
637
{
638
    if (!PyArg_ParseTuple(args, ""))
639
        return nullptr;
640

641
    Py::String datadir(Application::getResourceDir(),"utf-8");
642
    return Py::new_reference_to(datadir);
643
}
644

645
PyObject* Application::sGetLibraryPath(PyObject * /*self*/, PyObject *args)
646
{
647
    if (!PyArg_ParseTuple(args, ""))
648
        return nullptr;
649

650
    Py::String datadir(Application::getLibraryDir(),"utf-8");
651
    return Py::new_reference_to(datadir);
652
}
653

654
PyObject* Application::sGetTempPath(PyObject * /*self*/, PyObject *args)
655
{
656
    if (!PyArg_ParseTuple(args, ""))
657
        return nullptr;
658

659
    Py::String datadir(Application::getTempPath(),"utf-8");
660
    return Py::new_reference_to(datadir);
661
}
662

663
PyObject* Application::sGetUserCachePath(PyObject * /*self*/, PyObject *args)
664
{
665
    if (!PyArg_ParseTuple(args, ""))
666
        return nullptr;
667

668
    Py::String datadir(Application::getUserCachePath(),"utf-8");
669
    return Py::new_reference_to(datadir);
670
}
671

672
PyObject* Application::sGetUserConfigPath(PyObject * /*self*/, PyObject *args)
673
{
674
    if (!PyArg_ParseTuple(args, ""))
675
        return nullptr;
676

677
    Py::String datadir(Application::getUserConfigPath(),"utf-8");
678
    return Py::new_reference_to(datadir);
679
}
680

681
PyObject* Application::sGetUserAppDataPath(PyObject * /*self*/, PyObject *args)
682
{
683
    if (!PyArg_ParseTuple(args, ""))
684
        return nullptr;
685

686
    Py::String user_data_dir(Application::getUserAppDataDir(),"utf-8");
687
    return Py::new_reference_to(user_data_dir);
688
}
689

690
PyObject* Application::sGetUserMacroPath(PyObject * /*self*/, PyObject *args)
691
{
692
    PyObject *actual = Py_False;
693
    if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &actual))
694
        return nullptr;
695

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);
702
    }
703

704
    Py::String user_macro_dir(macroDir,"utf-8");
705
    return Py::new_reference_to(user_macro_dir);
706
}
707

708
PyObject* Application::sGetHelpPath(PyObject * /*self*/, PyObject *args)
709
{
710
    if (!PyArg_ParseTuple(args, ""))
711
        return nullptr;
712

713
    Py::String user_macro_dir(Application::getHelpDir(),"utf-8");
714
    return Py::new_reference_to(user_macro_dir);
715
}
716

717
PyObject* Application::sGetHomePath(PyObject * /*self*/, PyObject *args)
718
{
719
    if (!PyArg_ParseTuple(args, ""))
720
        return nullptr;
721

722
    Py::String homedir(Application::getHomePath(),"utf-8");
723
    return Py::new_reference_to(homedir);
724
}
725

726
PyObject* Application::sListDocuments(PyObject * /*self*/, PyObject *args)
727
{
728
    PyObject *sort = Py_False;
729
    if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort))
730
        return nullptr;
731
    PY_TRY {
732
        PyObject *pDict = PyDict_New();
733
        PyObject *pKey;
734
        Base::PyObjectBase* pValue;
735

736
        std::vector<Document*> docs = GetApplication().getDocuments();;
737
        if (Base::asBoolean(sort))
738
            docs = Document::getDependentDocuments(docs,true);
739

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
746
            pValue->DecRef();
747
        }
748

749
        return pDict;
750
    } PY_CATCH;
751
}
752

753
PyObject* Application::sAddDocObserver(PyObject * /*self*/, PyObject *args)
754
{
755
    PyObject* o;
756
    if (!PyArg_ParseTuple(args, "O",&o))
757
        return nullptr;
758
    PY_TRY {
759
        DocumentObserverPython::addObserver(Py::Object(o));
760
        Py_Return;
761
    } PY_CATCH;
762
}
763

764
PyObject* Application::sRemoveDocObserver(PyObject * /*self*/, PyObject *args)
765
{
766
    PyObject* o;
767
    if (!PyArg_ParseTuple(args, "O",&o))
768
        return nullptr;
769
    PY_TRY {
770
        DocumentObserverPython::removeObserver(Py::Object(o));
771
        Py_Return;
772
    } PY_CATCH;
773
}
774

775
PyObject *Application::sSetLogLevel(PyObject * /*self*/, PyObject *args)
776
{
777
    char *tag;
778
    PyObject *pcObj;
779
    if (!PyArg_ParseTuple(args, "sO", &tag, &pcObj))
780
        return nullptr;
781
    PY_TRY{
782
        int l;
783
        if (PyUnicode_Check(pcObj)) {
784
            const char *pstr = PyUnicode_AsUTF8(pcObj);
785
            if(strcmp(pstr,"Log") == 0)
786
                l = FC_LOGLEVEL_LOG;
787
            else if(strcmp(pstr,"Warning") == 0)
788
                l = FC_LOGLEVEL_WARN;
789
            else if(strcmp(pstr,"Message") == 0)
790
                l = FC_LOGLEVEL_MSG;
791
            else if(strcmp(pstr,"Error") == 0)
792
                l = FC_LOGLEVEL_ERR;
793
            else if(strcmp(pstr,"Trace") == 0)
794
                l = FC_LOGLEVEL_TRACE;
795
            else if(strcmp(pstr,"Default") == 0)
796
                l = FC_LOGLEVEL_DEFAULT;
797
            else {
798
                Py_Error(PyExc_ValueError,
799
                        "Unknown Log Level (use 'Default', 'Error', 'Warning', 'Message', 'Log', 'Trace' or an integer)");
800
                return nullptr;
801
            }
802
        }else
803
            l = PyLong_AsLong(pcObj);
804
        GetApplication().GetParameterGroupByPath("User parameter:BaseApp/LogLevels")->SetInt(tag,l);
805
        if(strcmp(tag,"Default") == 0) {
806
#ifndef FC_DEBUG
807
            if(l>=0) Base::Console().SetDefaultLogLevel(l);
808
#endif
809
        }else if(strcmp(tag,"DebugDefault") == 0) {
810
#ifdef FC_DEBUG
811
            if(l>=0) Base::Console().SetDefaultLogLevel(l);
812
#endif
813
        }else
814
            *Base::Console().GetLogLevel(tag) = l;
815
        Py_INCREF(Py_None);
816
        return Py_None;
817
    }PY_CATCH;
818
}
819

820
PyObject *Application::sGetLogLevel(PyObject * /*self*/, PyObject *args)
821
{
822
    char *tag;
823
    if (!PyArg_ParseTuple(args, "s", &tag))
824
        return nullptr;
825

826
    PY_TRY{
827
        int l = -1;
828
        if(strcmp(tag,"Default")==0) {
829
#ifdef FC_DEBUG
830
            l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag,-1);
831
#endif
832
        }else if(strcmp(tag,"DebugDefault")==0) {
833
#ifndef FC_DEBUG
834
            l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag,-1);
835
#endif
836
        }else{
837
            int *pl = Base::Console().GetLogLevel(tag,false);
838
            l = pl?*pl:-1;
839
        }
840
        // For performance reason, we only output integer value
841
        return Py_BuildValue("i",Base::Console().LogLevel(l));
842
    } PY_CATCH;
843
}
844

845
PyObject *Application::sCheckLinkDepth(PyObject * /*self*/, PyObject *args)
846
{
847
    short depth = 0;
848
    if (!PyArg_ParseTuple(args, "h", &depth))
849
        return nullptr;
850

851
    PY_TRY {
852
        return Py::new_reference_to(Py::Int(GetApplication().checkLinkDepth(depth, MessageOption::Throw)));
853
    }PY_CATCH;
854
}
855

856
PyObject *Application::sGetLinksTo(PyObject * /*self*/, PyObject *args)
857
{
858
    PyObject *pyobj = Py_None;
859
    int options = 0;
860
    short count = 0;
861
    if (!PyArg_ParseTuple(args, "|Oih",&pyobj,&options, &count))
862
        return nullptr;
863

864
    PY_TRY {
865
        Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type App.DocumentObject or None");
866
        DocumentObject *obj = nullptr;
867
        if (pyobj)
868
            obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
869

870
        auto links = GetApplication().getLinksTo(obj,options,count);
871
        Py::Tuple ret(links.size());
872
        int i=0;
873
        for(auto o : links)
874
            ret.setItem(i++,Py::Object(o->getPyObject(),true));
875

876
        return Py::new_reference_to(ret);
877
    }
878
    PY_CATCH;
879
}
880

881
PyObject *Application::sGetDependentObjects(PyObject * /*self*/, PyObject *args)
882
{
883
    PyObject *obj;
884
    int options = 0;
885
    if (!PyArg_ParseTuple(args, "O|i", &obj,&options))
886
        return nullptr;
887

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");
894
                return nullptr;
895
            }
896
            objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
897
        }
898
    }
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");
902
        return nullptr;
903
    }
904
    else {
905
        objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
906
    }
907

908
    PY_TRY {
909
        auto ret = App::Document::getDependencyList(objs,options);
910

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);
915
    } PY_CATCH;
916
}
917

918

919
PyObject *Application::sSetActiveTransaction(PyObject * /*self*/, PyObject *args)
920
{
921
    char *name;
922
    PyObject *persist = Py_False;
923
    if (!PyArg_ParseTuple(args, "s|O!", &name, &PyBool_Type, &persist))
924
        return nullptr;
925

926
    PY_TRY {
927
        Py::Int ret(GetApplication().setActiveTransaction(name, Base::asBoolean(persist)));
928
        return Py::new_reference_to(ret);
929
    }PY_CATCH;
930
}
931

932
PyObject *Application::sGetActiveTransaction(PyObject * /*self*/, PyObject *args)
933
{
934
    if (!PyArg_ParseTuple(args, ""))
935
        return nullptr;
936

937
    PY_TRY {
938
        int id = 0;
939
        const char *name = GetApplication().getActiveTransaction(&id);
940
        if(!name || id<=0)
941
            Py_Return;
942
        Py::Tuple ret(2);
943
        ret.setItem(0,Py::String(name));
944
        ret.setItem(1,Py::Int(id));
945
        return Py::new_reference_to(ret);
946
    }PY_CATCH;
947
}
948

949
PyObject *Application::sCloseActiveTransaction(PyObject * /*self*/, PyObject *args)
950
{
951
    PyObject *abort = Py_False;
952
    int id = 0;
953
    if (!PyArg_ParseTuple(args, "|O!i", &PyBool_Type, &abort,&id))
954
        return nullptr;
955

956
    PY_TRY {
957
        GetApplication().closeActiveTransaction(Base::asBoolean(abort), id);
958
        Py_Return;
959
    } PY_CATCH;
960
}
961

962
PyObject *Application::sCheckAbort(PyObject * /*self*/, PyObject *args)
963
{
964
    if (!PyArg_ParseTuple(args, ""))
965
        return nullptr;
966

967
    PY_TRY {
968
        Base::Sequencer().checkAbort();
969
        Py_Return;
970
    }PY_CATCH
971
}
972

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.