FreeCAD

Форк
0
/
ApplicationPy.cpp 
1616 строк · 52.1 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# include <QApplication>
27
# include <QDir>
28
# include <QPrinter>
29
# include <QFileInfo>
30
# include <Inventor/SoInput.h>
31
# include <Inventor/actions/SoGetPrimitiveCountAction.h>
32
# include <Inventor/nodes/SoSeparator.h>
33
# include <xercesc/util/TranscodingException.hpp>
34
# include <xercesc/util/XMLString.hpp>
35
#endif
36

37
#include <boost/regex.hpp>
38

39
#include <App/DocumentObjectPy.h>
40
#include <App/DocumentPy.h>
41
#include <App/PropertyFile.h>
42
#include <Base/Interpreter.h>
43
#include <Base/Console.h>
44
#include <Base/PyWrapParseTupleAndKeywords.h>
45
#include <CXX/Objects.hxx>
46

47
#include "Application.h"
48
#include "BitmapFactory.h"
49
#include "Command.h"
50
#include "DlgPreferencesImp.h"
51
#include "Document.h"
52
#include "DocumentObserverPython.h"
53
#include "DownloadManager.h"
54
#include "EditorView.h"
55
#include "FileHandler.h"
56
#include "Macro.h"
57
#include "MainWindow.h"
58
#include "MainWindowPy.h"
59
#include "PythonEditor.h"
60
#include "PythonWrapper.h"
61
#include "SoFCDB.h"
62
#include "SplitView3DInventor.h"
63
#include "View3DInventor.h"
64
#include "ViewProvider.h"
65
#include "WaitCursor.h"
66
#include "WidgetFactory.h"
67
#include "Workbench.h"
68
#include "WorkbenchManager.h"
69
#include "WorkbenchManipulatorPython.h"
70
#include "Inventor/MarkerBitmaps.h"
71
#include "Language/Translator.h"
72

73

74
using namespace Gui;
75

76
// Application methods structure
77
PyMethodDef Application::Methods[] = {
78
  {"activateWorkbench",(PyCFunction) Application::sActivateWorkbenchHandler, METH_VARARGS,
79
   "activateWorkbench(name) -> bool\n"
80
    "\n"
81
   "Activate workbench by its name. Return False if the workbench is\n"
82
   "already active.\n"
83
    "\n"
84
    "name : str\n    Name of the workbench to activate."},
85
  {"addWorkbench",     (PyCFunction) Application::sAddWorkbenchHandler, METH_VARARGS,
86
   "addWorkbench(workbench) -> None\n"
87
    "\n"
88
   "Add a workbench.\n"
89
    "\n"
90
    "workbench : Workbench, Workbench type\n"
91
    "    Instance of a Workbench subclass or subclass of the\n"
92
    "    Workbench class."},
93
  {"removeWorkbench",  (PyCFunction) Application::sRemoveWorkbenchHandler, METH_VARARGS,
94
   "removeWorkbench(name) -> None\n"
95
   "\n"
96
   "Remove a workbench.\n"
97
   "\n"
98
   "name : str\n    Name of the workbench to remove."},
99
  {"getWorkbench",     (PyCFunction) Application::sGetWorkbenchHandler, METH_VARARGS,
100
   "getWorkbench(name) -> Workbench\n"
101
   "\n"
102
   "Get the workbench by its name.\n"
103
   "\n"
104
   "name : str\n    Name of the workbench to return."},
105
  {"listWorkbenches",   (PyCFunction) Application::sListWorkbenchHandlers, METH_VARARGS,
106
   "listWorkbenches() -> dict\n"
107
   "\n"
108
   "Get a dictionary with all workbenches."},
109
  {"activeWorkbench", (PyCFunction) Application::sActiveWorkbenchHandler, METH_VARARGS,
110
   "activeWorkbench() -> Workbench\n"
111
   "\n"
112
   "Return the active workbench object."},
113
  {"addResourcePath",             (PyCFunction) Application::sAddResPath, METH_VARARGS,
114
   "addResourcePath(path) -> None\n"
115
   "\n"
116
   "Add a new path to the system where to find resource files\n"
117
   "like icons or localization files.\n"
118
   "\n"
119
   "path : str, bytes, bytearray\n    Path to resource files."},
120
  {"addLanguagePath",             (PyCFunction) Application::sAddLangPath, METH_VARARGS,
121
   "addLanguagePath(path) -> None\n"
122
   "\n"
123
   "Add a new path to the system where to find language files.\n"
124
   "\n"
125
   "path : str, bytes, bytearray\n    Path to language files."},
126
  {"addIconPath",             (PyCFunction) Application::sAddIconPath, METH_VARARGS,
127
   "addIconPath(path) -> None\n"
128
   "\n"
129
   "Add a new path to the system where to find icon files.\n"
130
   "\n"
131
   "path : str, bytes, bytearray\n    Path to icon files."},
132
  {"addIcon",                 (PyCFunction) Application::sAddIcon, METH_VARARGS,
133
   "addIcon(name, content, format='XPM') -> None\n"
134
   "\n"
135
   "Add an icon to the system.\n"
136
   "\n"
137
   "name : str\n    Name of the icon.\n"
138
   "content : str, bytes-like\n    Content of the icon.\n"
139
   "format : str\n    Format of the icon."},
140
  {"getIcon",                 (PyCFunction) Application::sGetIcon, METH_VARARGS,
141
   "getIcon(name) -> QIcon or None\n"
142
   "\n"
143
   "Get an icon in the system. If the pixmap is null, return None.\n"
144
   "\n"
145
   "name : str\n    Name of the icon."},
146
  {"isIconCached",           (PyCFunction) Application::sIsIconCached, METH_VARARGS,
147
   "isIconCached(name) -> Bool\n"
148
   "\n"
149
   "Check if an icon with the given name is cached.\n"
150
   "\n"
151
   "name : str\n    Name of the icon."},
152
  {"getMainWindow",           (PyCFunction) Application::sGetMainWindow, METH_VARARGS,
153
   "getMainWindow() -> QMainWindow\n"
154
   "\n"
155
   "Return the main window instance."},
156
  {"updateGui",               (PyCFunction) Application::sUpdateGui, METH_VARARGS,
157
   "updateGui() -> None\n"
158
   "\n"
159
   "Update the main window and all its windows."},
160
  {"updateLocale",            (PyCFunction) Application::sUpdateLocale, METH_VARARGS,
161
   "updateLocale() -> None\n"
162
   "\n"
163
   "Update the localization."},
164
  {"getLocale",            (PyCFunction) Application::sGetLocale, METH_VARARGS,
165
   "getLocale() -> str\n"
166
   "\n"
167
   "Returns the locale currently used by FreeCAD."},
168
  {"setLocale",            (PyCFunction) Application::sSetLocale, METH_VARARGS,
169
   "setLocale(name) -> None\n"
170
   "\n"
171
   "Sets the locale used by FreeCAD. Can be set by top-level\n"
172
   "domain (e.g. \"de\") or the language name (e.g. \"German\").\n"
173
   "\n"
174
   "name : str\n    Locale name."},
175
  {"supportedLocales", (PyCFunction) Application::sSupportedLocales, METH_VARARGS,
176
   "supportedLocales() -> dict\n"
177
   "\n"
178
   "Returns a dict of all supported locales. The keys are the language\n"
179
   "names and the values the top-level domains."},
180
  {"createDialog",            (PyCFunction) Application::sCreateDialog, METH_VARARGS,
181
   "createDialog(path) -> PyResource\n"
182
   "\n"
183
   "Open a UI file.\n"
184
   "\n"
185
   "path : str\n    UI file path."},
186
  {"addPreferencePage",       (PyCFunction) Application::sAddPreferencePage, METH_VARARGS,
187
   "addPreferencePage(path, group) -> None\n"
188
   "addPreferencePage(dialog, group) -> None\n"
189
   "\n"
190
   "Add a UI form to the preferences dialog in the specified group.\n"
191
   "\n"
192
   "path : str\n    UI file path.\n"
193
   "group : str\n    Group name.\n"
194
   "dialog : type\n    Preference page."},
195
  {"addCommand",              (PyCFunction) Application::sAddCommand, METH_VARARGS,
196
   "addCommand(name, cmd, activation) -> None\n"
197
   "\n"
198
   "Add a command object.\n"
199
   "\n"
200
   "name : str\n    Name of the command.\n"
201
   "cmd : object\n    Command instance.\n"
202
   "activation : str\n    Activation sequence. Optional."},
203
  {"runCommand",              (PyCFunction) Application::sRunCommand, METH_VARARGS,
204
   "runCommand(name, index=0) -> None\n"
205
   "\n"
206
   "Run command by its name.\n"
207
   "\n"
208
   "name : str\n    Name of the command.\n"
209
   "index : int\n    Index of the child command."},
210
  {"SendMsgToActiveView",     (PyCFunction) Application::sSendActiveView, METH_VARARGS,
211
   "SendMsgToActiveView(name, suppress=False) -> str or None\n"
212
   "\n"
213
   "Send message to the active view. Deprecated, use class View.\n"
214
   "\n"
215
   "name : str\n    Name of the view command.\n"
216
   "suppress : bool\n    If the sent message fail, suppress warning message."},
217
  {"sendMsgToFocusView",     (PyCFunction) Application::sSendFocusView, METH_VARARGS,
218
   "sendMsgToFocusView(name, suppress=False) -> str or None\n"
219
   "\n"
220
   "Send message to the focused view.\n"
221
   "\n"
222
   "name : str\n    Name of the view command.\n"
223
   "suppress : bool\n    If send message fail, suppress warning message."},
224
  {"hide",                    (PyCFunction) Application::sHide, METH_VARARGS,
225
   "hide(name) -> None\n"
226
   "\n"
227
   "Hide the given feature. Deprecated.\n"
228
   "\n"
229
   "name : str\n    Feature name."},
230
  {"show",                    (PyCFunction) Application::sShow, METH_VARARGS,
231
   "show(name) -> None\n"
232
   "\n"
233
   "Show the given feature. Deprecated.\n"
234
   "\n"
235
   "name : str\n    Feature name."},
236
  {"hideObject",              (PyCFunction) Application::sHideObject, METH_VARARGS,
237
   "hideObject(obj) -> None\n"
238
   "\n"
239
   "Hide the view provider of the given object.\n"
240
   "\n"
241
   "obj : App.DocumentObject"},
242
  {"showObject",              (PyCFunction) Application::sShowObject, METH_VARARGS,
243
   "showObject(obj) -> None\n"
244
   "\n"
245
   "Show the view provider of the given object.\n"
246
   "\n"
247
   "obj : App.DocumentObject"},
248
  {"open",                    (PyCFunction) Application::sOpen, METH_VARARGS,
249
   "open(fileName) -> None\n"
250
   "\n"
251
   "Open a macro, Inventor or VRML file.\n"
252
   "\n"
253
   "fileName : str, bytes, bytearray\n    File name."},
254
  {"insert",                  (PyCFunction) Application::sInsert, METH_VARARGS,
255
   "insert(fileName, docName) -> None\n"
256
   "\n"
257
   "Insert a macro, Inventor or VRML file. If no document name\n"
258
   "is given the active document is used.\n"
259
   "\n"
260
   "fileName : str, bytes, bytearray\n    File name.\n"
261
   "docName : str\n    Document name."},
262
  {"export",                  (PyCFunction) Application::sExport, METH_VARARGS,
263
   "export(objs, fileName) -> None\n"
264
   "\n"
265
   "Save scene to Inventor or VRML file.\n"
266
   "\n"
267
   "objs : sequence of App.DocumentObject\n    Sequence of objects to save.\n"
268
   "fileName : str, bytes, bytearray\n    File name."},
269
  {"activeDocument",          (PyCFunction) Application::sActiveDocument, METH_VARARGS,
270
   "activeDocument() -> Gui.Document or None\n"
271
   "\n"
272
   "Return the active document. If no one exists, return None."},
273
  {"setActiveDocument",       (PyCFunction) Application::sSetActiveDocument, METH_VARARGS,
274
   "setActiveDocument(doc) -> None\n"
275
   "\n"
276
   "Activate the specified document.\n"
277
   "\n"
278
   "doc : str, App.Document\n    Document to activate."},
279
  {"activeView", (PyCFunction)Application::sActiveView, METH_VARARGS,
280
   "activeView(typeName) -> object or None\n"
281
   "\n"
282
   "Return the active view of the active document. If no one\n"
283
   "exists, return None.\n"
284
   "\n"
285
   "typeName : str\n    Type name."},
286
  {"activateView", (PyCFunction)Application::sActivateView, METH_VARARGS,
287
   "activateView(typeName, create=False) -> None\n"
288
   "\n"
289
   "Activate a view of the given type in the active document.\n"
290
   "If a view of this type doesn't exist and create is True, a\n"
291
   "new view of this type is created.\n"
292
   "\n"
293
   "type : str\n    Type name.\n"
294
   "create : bool"},
295
  {"editDocument", (PyCFunction)Application::sEditDocument, METH_VARARGS,
296
   "editDocument() -> Gui.Document or None\n"
297
   "\n"
298
   "Return the current editing document. If no one exists,\n"
299
   "return None."},
300
  {"getDocument",             (PyCFunction) Application::sGetDocument, METH_VARARGS,
301
   "getDocument(doc) -> Gui.Document\n"
302
   "\n"
303
   "Get a document.\n"
304
   "\n"
305
   "doc : str, App.Document\n    `App.Document` name or `App.Document` object."},
306
  {"doCommand",               (PyCFunction) Application::sDoCommand, METH_VARARGS,
307
   "doCommand(cmd) -> None\n"
308
   "\n"
309
   "Prints the given string in the python console and runs it.\n"
310
   "\n"
311
   "cmd : str"},
312
  {"doCommandGui",               (PyCFunction) Application::sDoCommandGui, METH_VARARGS,
313
   "doCommandGui(cmd) -> None\n"
314
   "\n"
315
   "Prints the given string in the python console and runs it\n"
316
   "but doesn't record it in macros.\n"
317
   "\n"
318
   "cmd : str"},
319
  {"addModule",               (PyCFunction) Application::sAddModule, METH_VARARGS,
320
   "addModule(mod) -> None\n"
321
   "\n"
322
   "Prints the given module import only once in the macro recording.\n"
323
   "\n"
324
   "mod : str"},
325
  {"showDownloads",               (PyCFunction) Application::sShowDownloads, METH_VARARGS,
326
   "showDownloads() -> None\n\n"
327
   "Show the downloads manager window."},
328
  {"showPreferences",               (PyCFunction) Application::sShowPreferences, METH_VARARGS,
329
   "showPreferences(grp, index=0) -> None\n"
330
   "\n"
331
   "Show the preferences window.\n"
332
   "\n"
333
   "grp: str\n    Group to show.\n"
334
   "index : int\n    Page index."},
335
  {"createViewer",               (PyCFunction) Application::sCreateViewer, METH_VARARGS,
336
   "createViewer(views=1, name) -> View3DInventorPy or AbstractSplitViewPy\n"
337
   "\n"
338
   "Show and returns a viewer.\n"
339
   "\n"
340
   "views : int\n    If > 1 a `AbstractSplitViewPy` object is returned.\n"
341
   "name : str\n    Viewer title."},
342
  {"getMarkerIndex", (PyCFunction) Application::sGetMarkerIndex, METH_VARARGS,
343
   "getMarkerIndex(marker, size=9) -> int\n"
344
   "\n"
345
   "Get marker index according to marker name and size.\n"
346
   "\n"
347
   "marker : str\n    Marker style name.\n"
348
   "size : int\n    Marker size."},
349
  {"addDocumentObserver",  (PyCFunction) Application::sAddDocObserver, METH_VARARGS,
350
   "addDocumentObserver(obj) -> None\n"
351
   "\n"
352
   "Add an observer to get notifications about changes on documents.\n"
353
   "\n"
354
   "obj : object"},
355
  {"removeDocumentObserver",  (PyCFunction) Application::sRemoveDocObserver, METH_VARARGS,
356
   "removeDocumentObserver(obj) -> None\n"
357
   "\n"
358
   "Remove an added document observer.\n"
359
   "\n"
360
   "obj : object"},
361
  {"addWorkbenchManipulator",  (PyCFunction) Application::sAddWbManipulator, METH_VARARGS,
362
   "addWorkbenchManipulator(obj) -> None\n"
363
   "\n"
364
   "Add a workbench manipulator to modify a workbench when it is activated.\n"
365
   "\n"
366
   "obj : object"},
367
  {"removeWorkbenchManipulator",  (PyCFunction) Application::sRemoveWbManipulator, METH_VARARGS,
368
   "removeWorkbenchManipulator(obj) -> None\n"
369
   "\n"
370
   "Remove an added workbench manipulator.\n"
371
   "\n"
372
   "obj : object"},
373
  {"listUserEditModes", (PyCFunction) Application::sListUserEditModes, METH_VARARGS,
374
   "listUserEditModes() -> list\n"
375
   "\n"
376
   "List available user edit modes."},
377
  {"getUserEditMode", (PyCFunction) Application::sGetUserEditMode, METH_VARARGS,
378
   "getUserEditMode() -> str\n"
379
   "\n"
380
   "Get current user edit mode."},
381
  {"setUserEditMode", (PyCFunction) Application::sSetUserEditMode, METH_VARARGS,
382
   "setUserEditMode(mode) -> bool\n"
383
   "\n"
384
   "Set user edit mode. Returns True if exists, False otherwise.\n"
385
   "\n"
386
   "mode : str"},
387
  {"reload",                    (PyCFunction) Application::sReload, METH_VARARGS,
388
   "reload(name) -> App.Document or None\n"
389
   "\n"
390
   "Reload a partial opened document. If the document is not open,\n"
391
   "return None.\n"
392
   "\n"
393
   "name : str\n    `App.Document` name."},
394
  {"loadFile",       (PyCFunction) Application::sLoadFile, METH_VARARGS,
395
   "loadFile(fileName, module) -> None\n"
396
   "\n"
397
   "Loads an arbitrary file by delegating to the given Python module.\n"
398
   "If no module is given it will be determined by the file extension.\n"
399
   "If more than one module can load a file the first one will be taken.\n"
400
   "If no module exists to load the file an exception will be raised.\n"
401
   "\n"
402
   "fileName : str\n"
403
   "module : str"},
404
  {"coinRemoveAllChildren",     (PyCFunction) Application::sCoinRemoveAllChildren, METH_VARARGS,
405
   "coinRemoveAllChildren(node) -> None\n"
406
   "\n"
407
   "Remove all children from a group node.\n"
408
   "\n"
409
   "node : object"},
410
  {nullptr, nullptr, 0, nullptr}    /* Sentinel */
411
};
412

413
PyObject* Gui::Application::sEditDocument(PyObject * /*self*/, PyObject *args)
414
{
415
    if (!PyArg_ParseTuple(args, ""))
416
        return nullptr;
417

418
    Document *pcDoc = Instance->editDocument();
419
    if (pcDoc)
420
        return pcDoc->getPyObject();
421
    else
422
        Py_Return;
423
}
424

425
PyObject* Gui::Application::sActiveDocument(PyObject * /*self*/, PyObject *args)
426
{
427
    if (!PyArg_ParseTuple(args, ""))
428
        return nullptr;
429

430
    Document *pcDoc = Instance->activeDocument();
431
    if (pcDoc)
432
        return pcDoc->getPyObject();
433
    else
434
        Py_Return;
435
}
436

437
PyObject* Gui::Application::sActiveView(PyObject * /*self*/, PyObject *args)
438
{
439
    const char *typeName = nullptr;
440
    if (!PyArg_ParseTuple(args, "|s", &typeName))
441
        return nullptr;
442

443
    PY_TRY {
444
        Base::Type type;
445
        if(typeName) {
446
            type = Base::Type::fromName(typeName);
447
            if(type.isBad()) {
448
                PyErr_Format(PyExc_TypeError, "Invalid type '%s'", typeName);
449
                return nullptr;
450
            }
451
        }
452

453
        Gui::MDIView* mdiView = Instance->activeView();
454
        if (mdiView && (type.isBad() || mdiView->isDerivedFrom(type))) {
455
            auto res = Py::asObject(mdiView->getPyObject());
456
            if(!res.isNone() || !type.isBad())
457
                return Py::new_reference_to(res);
458
        }
459

460
        if(type.isBad())
461
            type = Gui::View3DInventor::getClassTypeId();
462
        Instance->activateView(type, true);
463
        mdiView = Instance->activeView();
464
        if (mdiView)
465
            return mdiView->getPyObject();
466

467
        Py_Return;
468

469
    }
470
    PY_CATCH
471
}
472

473
PyObject* Gui::Application::sActivateView(PyObject * /*self*/, PyObject *args)
474
{
475
    char* typeStr;
476
    PyObject *create = Py_False;
477
    if (!PyArg_ParseTuple(args, "sO!", &typeStr, &PyBool_Type, &create))
478
        return nullptr;
479

480
    Base::Type type = Base::Type::fromName(typeStr);
481
    Instance->activateView(type, Base::asBoolean(create));
482

483
    Py_Return;
484
}
485

486
PyObject* Gui::Application::sSetActiveDocument(PyObject * /*self*/, PyObject *args)
487
{
488
    Document *pcDoc = nullptr;
489

490
    do {
491
        char *pstr = nullptr;
492
        if (PyArg_ParseTuple(args, "s", &pstr)) {
493
            pcDoc = Instance->getDocument(pstr);
494
            if (!pcDoc) {
495
                PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
496
                return nullptr;
497
            }
498
            break;
499
        }
500

501
        PyErr_Clear();
502
        PyObject* doc;
503
        if (PyArg_ParseTuple(args, "O!", &(App::DocumentPy::Type), &doc)) {
504
            pcDoc = Instance->getDocument(static_cast<App::DocumentPy*>(doc)->getDocumentPtr());
505
            if (!pcDoc) {
506
                PyErr_Format(PyExc_KeyError, "Unknown document instance");
507
                return nullptr;
508
            }
509
            break;
510
        }
511
    }
512
    while(false);
513

514
    if (!pcDoc) {
515
        PyErr_SetString(PyExc_TypeError, "Either string or App.Document expected");
516
        return nullptr;
517
    }
518

519
    if (Instance->activeDocument() != pcDoc) {
520
        Gui::MDIView* view = pcDoc->getActiveView();
521
        getMainWindow()->setActiveWindow(view);
522
    }
523

524
    Py_Return;
525
}
526

527
PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args)
528
{
529
    char *pstr = nullptr;
530
    if (PyArg_ParseTuple(args, "s", &pstr)) {
531
        Document *pcDoc = Instance->getDocument(pstr);
532
        if (!pcDoc) {
533
            PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr);
534
            return nullptr;
535
        }
536
        return pcDoc->getPyObject();
537
    }
538

539
    PyErr_Clear();
540
    PyObject* doc;
541
    if (PyArg_ParseTuple(args, "O!", &(App::DocumentPy::Type), &doc)) {
542
        Document *pcDoc = Instance->getDocument(static_cast<App::DocumentPy*>(doc)->getDocumentPtr());
543
        if (!pcDoc) {
544
            PyErr_Format(PyExc_KeyError, "Unknown document instance");
545
            return nullptr;
546
        }
547
        return pcDoc->getPyObject();
548
    }
549

550
    PyErr_SetString(PyExc_TypeError, "Either string or App.Document expected");
551
    return nullptr;
552
}
553

554
PyObject* Application::sHide(PyObject * /*self*/, PyObject *args)
555
{
556
    char *psFeatStr;
557
    if (!PyArg_ParseTuple(args, "s;Name of the object to hide has to be given!",&psFeatStr))
558
        return nullptr;
559

560
    Document *pcDoc = Instance->activeDocument();
561

562
    if (pcDoc)
563
        pcDoc->setHide(psFeatStr);
564

565
    Py_Return;
566
}
567

568
PyObject* Application::sShow(PyObject * /*self*/, PyObject *args)
569
{
570
    char *psFeatStr;
571
    if (!PyArg_ParseTuple(args, "s;Name of the object to show has to be given!",&psFeatStr))
572
        return nullptr;
573

574
    Document *pcDoc = Instance->activeDocument();
575

576
    if (pcDoc)
577
        pcDoc->setShow(psFeatStr);
578

579
    Py_Return;
580
}
581

582
PyObject* Application::sHideObject(PyObject * /*self*/, PyObject *args)
583
{
584
    PyObject *object;
585
    if (!PyArg_ParseTuple(args, "O!",&(App::DocumentObjectPy::Type),&object))
586
        return nullptr;
587

588
    App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(object)->getDocumentObjectPtr();
589
    Instance->hideViewProvider(obj);
590

591
    Py_Return;
592
}
593

594
PyObject* Application::sShowObject(PyObject * /*self*/, PyObject *args)
595
{
596
    PyObject *object;
597
    if (!PyArg_ParseTuple(args, "O!",&(App::DocumentObjectPy::Type),&object))
598
        return nullptr;
599

600
    App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(object)->getDocumentObjectPtr();
601
    Instance->showViewProvider(obj);
602

603
    Py_Return;
604
}
605

606
PyObject* Application::sOpen(PyObject * /*self*/, PyObject *args)
607
{
608
    // only used to open Python files
609
    char* Name;
610
    if (!PyArg_ParseTuple(args, "et","utf-8",&Name))
611
        return nullptr;
612

613
    std::string Utf8Name = std::string(Name);
614
    PyMem_Free(Name);
615
    PY_TRY {
616
        QString fileName = QString::fromUtf8(Utf8Name.c_str());
617
        FileHandler handler(fileName);
618
        if (!handler.openFile()) {
619
            QString ext = handler.extension();
620
            Base::Console().Error("File type '%s' not supported\n", ext.toLatin1().constData());
621
        }
622
    }
623
    PY_CATCH;
624

625
    Py_Return;
626
}
627

628
PyObject* Application::sInsert(PyObject * /*self*/, PyObject *args)
629
{
630
    char* Name;
631
    char* DocName = nullptr;
632
    if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&DocName))
633
        return nullptr;
634

635
    std::string Utf8Name = std::string(Name);
636
    PyMem_Free(Name);
637

638
    PY_TRY {
639
        QString fileName = QString::fromUtf8(Utf8Name.c_str());
640
        FileHandler handler(fileName);
641
        if (!handler.importFile(std::string(DocName ? DocName : ""))) {
642
            QString ext = handler.extension();
643
            Base::Console().Error("File type '%s' not supported\n", ext.toLatin1().constData());
644
        }
645
    } PY_CATCH;
646

647
    Py_Return;
648
}
649

650
PyObject* Application::sExport(PyObject * /*self*/, PyObject *args)
651
{
652
    PyObject* object;
653
    char* Name;
654
    if (!PyArg_ParseTuple(args, "Oet",&object,"utf-8",&Name))
655
        return nullptr;
656

657
    std::string Utf8Name = std::string(Name);
658
    PyMem_Free(Name);
659

660
    PY_TRY {
661
        App::Document* doc = nullptr;
662
        Py::Sequence list(object);
663
        for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
664
            PyObject* item = (*it).ptr();
665
            if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
666
                App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
667
                doc = obj->getDocument();
668
                break;
669
            }
670
        }
671

672
        QString fileName = QString::fromUtf8(Utf8Name.c_str());
673
        QFileInfo fi;
674
        fi.setFile(fileName);
675
        QString ext = fi.suffix().toLower();
676
        if (ext == QLatin1String("iv") ||
677
            ext == QLatin1String("wrl") ||
678
            ext == QLatin1String("vrml") ||
679
            ext == QLatin1String("wrz") ||
680
            ext == QLatin1String("x3d") ||
681
            ext == QLatin1String("x3dz") ||
682
            ext == QLatin1String("xhtml")) {
683

684
            // build up the graph
685
            auto sep = new SoSeparator();
686
            sep->ref();
687

688
            for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
689
                PyObject* item = (*it).ptr();
690
                if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
691
                    App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
692

693
                    Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(obj);
694
                    if (vp) {
695
                        sep->addChild(vp->getRoot());
696
                    }
697
                }
698
            }
699

700

701
            SoGetPrimitiveCountAction action;
702
            action.setCanApproximate(true);
703
            action.apply(sep);
704

705
            bool binary = false;
706
            if (action.getTriangleCount() > 100000 ||
707
                action.getPointCount() > 30000 ||
708
                action.getLineCount() > 10000)
709
                binary = true;
710

711
            SoFCDB::writeToFile(sep, Utf8Name.c_str(), binary);
712
            sep->unref();
713
        }
714
        else if (ext == QLatin1String("pdf")) {
715
            // get the view that belongs to the found document
716
            Gui::Document* gui_doc = Application::Instance->getDocument(doc);
717
            if (gui_doc) {
718
                Gui::MDIView* view = gui_doc->getActiveView();
719
                if (view) {
720
                    auto view3d = qobject_cast<View3DInventor*>(view);
721
                    if (view3d)
722
                        view3d->viewAll();
723
                    QPrinter printer(QPrinter::ScreenResolution);
724
                    // setPdfVersion sets the printied PDF Version to comply with PDF/A-1b, more details under: https://www.kdab.com/creating-pdfa-documents-qt/
725
                    printer.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b);
726
                    printer.setOutputFormat(QPrinter::PdfFormat);
727
                    printer.setOutputFileName(fileName);
728
                    view->print(&printer);
729
                }
730
            }
731
        }
732
        else {
733
            Base::Console().Error("File type '%s' not supported\n", ext.toLatin1().constData());
734
        }
735
    } PY_CATCH;
736

737
    Py_Return;
738
}
739

740
PyObject* Application::sSendActiveView(PyObject * /*self*/, PyObject *args)
741
{
742
    char *psCommandStr;
743
    PyObject *suppress=Py_False;
744
    if (!PyArg_ParseTuple(args, "s|O!",&psCommandStr,&PyBool_Type,&suppress))
745
        return nullptr;
746

747
    const char* ppReturn = nullptr;
748
    if (!Instance->sendMsgToActiveView(psCommandStr,&ppReturn)) {
749
        if (!Base::asBoolean(suppress))
750
            Base::Console().Warning("Unknown view command: %s\n",psCommandStr);
751
    }
752

753
    // Print the return value to the output
754
    if (ppReturn) {
755
        return Py_BuildValue("s",ppReturn);
756
    }
757

758
    Py_Return;
759
}
760

761
PyObject* Application::sSendFocusView(PyObject * /*self*/, PyObject *args)
762
{
763
    char *psCommandStr;
764
    PyObject *suppress=Py_False;
765
    if (!PyArg_ParseTuple(args, "s|O!",&psCommandStr,&PyBool_Type,&suppress))
766
        return nullptr;
767

768
    const char* ppReturn = nullptr;
769
    if (!Instance->sendMsgToFocusView(psCommandStr,&ppReturn)) {
770
        if (!Base::asBoolean(suppress))
771
            Base::Console().Warning("Unknown view command: %s\n",psCommandStr);
772
    }
773

774
    // Print the return value to the output
775
    if (ppReturn) {
776
        return Py_BuildValue("s",ppReturn);
777
    }
778

779
    Py_Return;
780
}
781

782
PyObject* Application::sGetMainWindow(PyObject * /*self*/, PyObject *args)
783
{
784
    if (!PyArg_ParseTuple(args, ""))
785
        return nullptr;
786

787
    try {
788
        return Py::new_reference_to(MainWindowPy::createWrapper(Gui::getMainWindow()));
789
    }
790
    catch (const Py::Exception&) {
791
        return nullptr;
792
    }
793
}
794

795
PyObject* Application::sUpdateGui(PyObject * /*self*/, PyObject *args)
796
{
797
    if (!PyArg_ParseTuple(args, ""))
798
        return nullptr;
799

800
    qApp->processEvents();
801

802
    Py_Return;
803
}
804

805
PyObject* Application::sUpdateLocale(PyObject * /*self*/, PyObject *args)
806
{
807
    if (!PyArg_ParseTuple(args, ""))
808
        return nullptr;
809

810
    Translator::instance()->refresh();
811

812
    Py_Return;
813
}
814

815
PyObject* Application::sGetLocale(PyObject * /*self*/, PyObject *args)
816
{
817
    if (!PyArg_ParseTuple(args, ""))
818
        return nullptr;
819

820
    std::string locale = Translator::instance()->activeLanguage();
821
    return PyUnicode_FromString(locale.c_str());
822
}
823

824
PyObject* Application::sSetLocale(PyObject * /*self*/, PyObject *args)
825
{
826
    char* name;
827
    if (!PyArg_ParseTuple(args, "s", &name))
828
        return nullptr;
829

830
    std::string cname(name);
831
    TStringMap map = Translator::instance()->supportedLocales();
832
    map["English"] = "en";
833
    for (const auto& it : map) {
834
        if (it.first == cname || it.second == cname) {
835
            Translator::instance()->activateLanguage(it.first.c_str());
836
            break;
837
        }
838
    }
839

840
    Py_Return;
841
}
842

843
PyObject* Application::sSupportedLocales(PyObject * /*self*/, PyObject *args)
844
{
845
    if (!PyArg_ParseTuple(args, ""))
846
        return nullptr;
847

848
    TStringMap map = Translator::instance()->supportedLocales();
849
    Py::Dict dict;
850
    dict.setItem(Py::String("English"), Py::String("en"));
851
    for (const auto& it : map) {
852
        Py::String key(it.first);
853
        Py::String val(it.second);
854
        dict.setItem(key, val);
855
    }
856
    return Py::new_reference_to(dict);
857
}
858

859
PyObject* Application::sCreateDialog(PyObject * /*self*/, PyObject *args)
860
{
861
    char* fn = nullptr;
862
    if (!PyArg_ParseTuple(args, "s", &fn))
863
        return nullptr;
864

865
    PyObject* pPyResource = nullptr;
866
    try{
867
        pPyResource = new PyResource();
868
        static_cast<PyResource*>(pPyResource)->load(fn);
869
    }
870
    catch (const Base::Exception& e) {
871
        PyErr_SetString(PyExc_AssertionError, e.what());
872
        return nullptr;
873
    }
874

875
    return pPyResource;
876
}
877

878
PyObject* Application::sAddPreferencePage(PyObject * /*self*/, PyObject *args)
879
{
880
    char *fn, *grp;
881
    if (PyArg_ParseTuple(args, "ss", &fn,&grp)) {
882
        QFileInfo fi(QString::fromUtf8(fn));
883
        if (!fi.exists()) {
884
            PyErr_SetString(PyExc_RuntimeError, "UI file does not exist");
885
            return nullptr;
886
        }
887

888
        // add to the preferences dialog
889
        new PrefPageUiProducer(fn, grp);
890
        Py_Return;
891
    }
892

893
    PyErr_Clear();
894
    PyObject* dlg;
895
    // new style classes
896
    if (PyArg_ParseTuple(args, "O!s", &PyType_Type, &dlg, &grp)) {
897
        // add to the preferences dialog
898
        new PrefPagePyProducer(Py::Object(dlg), grp);
899
        Py_Return;
900
    }
901

902
    return nullptr;
903
}
904

905
PyObject* Application::sActivateWorkbenchHandler(PyObject * /*self*/, PyObject *args)
906
{
907
    char* psKey;
908
    if (!PyArg_ParseTuple(args, "s", &psKey))
909
        return nullptr;
910

911
    // search for workbench handler from the dictionary
912
    PyObject* pcWorkbench = PyDict_GetItemString(Instance->_pcWorkbenchDictionary, psKey);
913
    if (!pcWorkbench) {
914
        PyErr_Format(PyExc_KeyError, "No such workbench '%s'", psKey);
915
        return nullptr;
916
    }
917

918
    try {
919
        bool ok = Instance->activateWorkbench(psKey);
920
        return Py::new_reference_to(Py::Boolean(ok));
921
    }
922
    catch (const Base::Exception& e) {
923
        std::stringstream err;
924
        err << psKey << ": " << e.what();
925
        PyErr_SetString(e.getPyExceptionType(), err.str().c_str());
926
        return nullptr;
927
    }
928
    catch (const XERCES_CPP_NAMESPACE_QUALIFIER TranscodingException& e) {
929
        std::stringstream err;
930
        char *pMsg = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(e.getMessage());
931
        err << "Transcoding exception in Xerces-c:\n\n"
932
            << "Transcoding exception raised in activateWorkbench.\n"
933
            << "Check if your user configuration file is valid.\n"
934
            << "  Exception message:"
935
            << pMsg;
936
        XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&pMsg);
937
        PyErr_SetString(PyExc_RuntimeError, err.str().c_str());
938
        return nullptr;
939
    }
940
    catch (...) {
941
        std::stringstream err;
942
        err << "Unknown C++ exception raised in activateWorkbench('" << psKey << "')";
943
        PyErr_SetString(Base::PyExc_FC_GeneralError, err.str().c_str());
944
        return nullptr;
945
    }
946
}
947

948
PyObject* Application::sAddWorkbenchHandler(PyObject * /*self*/, PyObject *args)
949
{
950
    PyObject* pcObject;
951
    if (!PyArg_ParseTuple(args, "O", &pcObject))
952
        return nullptr;
953

954
    try {
955
        // get the class object 'Workbench' from the main module that is expected
956
        // to be base class for all workbench classes
957
        Py::Module module("__main__");
958
        Py::Object baseclass(module.getAttr(std::string("Workbench")));
959

960
        // check whether it is an instance or class object
961
        Py::Object object(pcObject);
962
        Py::String name;
963

964
        if (PyObject_IsSubclass(object.ptr(), baseclass.ptr()) == 1) {
965
            // create an instance of this class
966
            name = object.getAttr(std::string("__name__"));
967
            Py::Tuple arg;
968
            Py::Callable creation(object);
969
            object = creation.apply(arg);
970
        }
971
        else if (PyObject_IsInstance(object.ptr(), baseclass.ptr()) == 1) {
972
            // extract the class name of the instance
973
            PyErr_Clear(); // PyObject_IsSubclass set an exception
974
            Py::Object classobj = object.getAttr(std::string("__class__"));
975
            name = classobj.getAttr(std::string("__name__"));
976
        }
977
        else {
978
            PyErr_SetString(PyExc_TypeError, "arg must be a subclass or an instance of "
979
                                             "a subclass of 'Workbench'");
980
            return nullptr;
981
        }
982

983
        // Search for some methods and members without invoking them
984
        Py::Callable(object.getAttr(std::string("Initialize")));
985
        Py::Callable(object.getAttr(std::string("GetClassName")));
986
        std::string item = name.as_std_string("ascii");
987

988
        PyObject* wb = PyDict_GetItemString(Instance->_pcWorkbenchDictionary,item.c_str());
989
        if (wb) {
990
            PyErr_Format(PyExc_KeyError, "'%s' already exists.", item.c_str());
991
            return nullptr;
992
        }
993

994
        PyDict_SetItemString(Instance->_pcWorkbenchDictionary,item.c_str(),object.ptr());
995
        Instance->signalRefreshWorkbenches();
996
    }
997
    catch (const Py::Exception&) {
998
        return nullptr;
999
    }
1000

1001
    Py_Return;
1002
}
1003

1004
PyObject* Application::sRemoveWorkbenchHandler(PyObject * /*self*/, PyObject *args)
1005
{
1006
    char* psKey;
1007
    if (!PyArg_ParseTuple(args, "s", &psKey))
1008
        return nullptr;
1009

1010
    PyObject* wb = PyDict_GetItemString(Instance->_pcWorkbenchDictionary,psKey);
1011
    if (!wb) {
1012
        PyErr_Format(PyExc_KeyError, "No such workbench '%s'", psKey);
1013
        return nullptr;
1014
    }
1015

1016
    WorkbenchManager::instance()->removeWorkbench(psKey);
1017
    PyDict_DelItemString(Instance->_pcWorkbenchDictionary,psKey);
1018
    Instance->signalRefreshWorkbenches();
1019

1020
    Py_Return;
1021
}
1022

1023
PyObject* Application::sGetWorkbenchHandler(PyObject * /*self*/, PyObject *args)
1024
{
1025
    char* psKey;
1026
    if (!PyArg_ParseTuple(args, "s", &psKey))
1027
        return nullptr;
1028

1029
    // get the python workbench object from the dictionary
1030
    PyObject* pcWorkbench = PyDict_GetItemString(Instance->_pcWorkbenchDictionary, psKey);
1031
    if (!pcWorkbench) {
1032
        PyErr_Format(PyExc_KeyError, "No such workbench '%s'", psKey);
1033
        return nullptr;
1034
    }
1035

1036
    Py_INCREF(pcWorkbench);
1037
    return pcWorkbench;
1038
}
1039

1040
PyObject* Application::sListWorkbenchHandlers(PyObject * /*self*/, PyObject *args)
1041
{
1042
    if (!PyArg_ParseTuple(args, ""))
1043
        return nullptr;
1044

1045
    Py_INCREF(Instance->_pcWorkbenchDictionary);
1046
    return Instance->_pcWorkbenchDictionary;
1047
}
1048

1049
PyObject* Application::sActiveWorkbenchHandler(PyObject * /*self*/, PyObject *args)
1050
{
1051
    if (!PyArg_ParseTuple(args, ""))
1052
        return nullptr;
1053

1054
    Workbench* actWb = WorkbenchManager::instance()->active();
1055
    if (!actWb) {
1056
        PyErr_SetString(PyExc_AssertionError, "No active workbench\n");
1057
        return nullptr;
1058
    }
1059

1060
    // get the python workbench object from the dictionary
1061
    std::string key = actWb->name();
1062
    PyObject* pcWorkbench = PyDict_GetItemString(Instance->_pcWorkbenchDictionary, key.c_str());
1063
    if (!pcWorkbench) {
1064
        PyErr_Format(PyExc_KeyError, "No such workbench '%s'", key.c_str());
1065
        return nullptr;
1066
    }
1067

1068
    // object get incremented
1069
    Py_INCREF(pcWorkbench);
1070
    return pcWorkbench;
1071
}
1072

1073
PyObject* Application::sAddResPath(PyObject * /*self*/, PyObject *args)
1074
{
1075
    char* filePath;
1076
    if (!PyArg_ParseTuple(args, "et", "utf-8", &filePath))
1077
        return nullptr;
1078

1079
    QString path = QString::fromUtf8(filePath);
1080
    PyMem_Free(filePath);
1081
    if (QDir::isRelativePath(path)) {
1082
        // Home path ends with '/'
1083
        QString home = QString::fromStdString(App::Application::getHomePath());
1084
        path = home + path;
1085
    }
1086

1087
    BitmapFactory().addPath(path);
1088
    Translator::instance()->addPath(path);
1089

1090
    Py_Return;
1091
}
1092

1093
PyObject* Application::sAddLangPath(PyObject * /*self*/, PyObject *args)
1094
{
1095
    char* filePath;
1096
    if (!PyArg_ParseTuple(args, "et", "utf-8", &filePath))
1097
        return nullptr;
1098

1099
    QString path = QString::fromUtf8(filePath);
1100
    PyMem_Free(filePath);
1101
    if (QDir::isRelativePath(path)) {
1102
        // Home path ends with '/'
1103
        QString home = QString::fromStdString(App::Application::getHomePath());
1104
        path = home + path;
1105
    }
1106

1107
    Translator::instance()->addPath(path);
1108

1109
    Py_Return;
1110
}
1111

1112
PyObject* Application::sAddIconPath(PyObject * /*self*/, PyObject *args)
1113
{
1114
    char* filePath;
1115
    if (!PyArg_ParseTuple(args, "et", "utf-8", &filePath))
1116
        return nullptr;
1117

1118
    QString path = QString::fromUtf8(filePath);
1119
    PyMem_Free(filePath);
1120
    if (QDir::isRelativePath(path)) {
1121
        // Home path ends with '/'
1122
        QString home = QString::fromStdString(App::Application::getHomePath());
1123
        path = home + path;
1124
    }
1125

1126
    BitmapFactory().addPath(path);
1127

1128
    Py_Return;
1129
}
1130

1131
PyObject* Application::sAddIcon(PyObject * /*self*/, PyObject *args)
1132
{
1133
    const char *iconName;
1134
    Py_buffer content;
1135
    const char *format = "XPM";
1136
    if (!PyArg_ParseTuple(args, "ss*|s", &iconName, &content, &format))
1137
        return nullptr;
1138

1139
    QPixmap icon;
1140
    if (BitmapFactory().findPixmapInCache(iconName, icon)) {
1141
        PyErr_SetString(PyExc_AssertionError, "Icon with this name already registered");
1142
        PyBuffer_Release(&content);
1143
        return nullptr;
1144
    }
1145

1146
    const char* contentStr = static_cast<const char*>(content.buf);
1147
    QByteArray ary(contentStr, content.len);
1148
    icon.loadFromData(ary, format);
1149

1150
    if (icon.isNull()){
1151
        QString file = QString::fromUtf8(contentStr, content.len);
1152
        icon.load(file);
1153
    }
1154

1155
    PyBuffer_Release(&content);
1156

1157
    if (icon.isNull()) {
1158
        PyErr_SetString(Base::PyExc_FC_GeneralError, "Invalid icon added to application");
1159
        return nullptr;
1160
    }
1161

1162
    BitmapFactory().addPixmapToCache(iconName, icon);
1163

1164
    Py_Return;
1165
}
1166

1167
PyObject* Application::sGetIcon(PyObject * /*self*/, PyObject *args)
1168
{
1169
    char *iconName;
1170
    if (!PyArg_ParseTuple(args, "s", &iconName))
1171
        return nullptr;
1172

1173
    PythonWrapper wrap;
1174
    wrap.loadGuiModule();
1175
    wrap.loadWidgetsModule();
1176
    auto pixmap = BitmapFactory().pixmap(iconName);
1177
    if(!pixmap.isNull())
1178
        return Py::new_reference_to(wrap.fromQIcon(new QIcon(pixmap)));
1179

1180
    Py_Return;
1181
}
1182

1183
PyObject* Application::sIsIconCached(PyObject * /*self*/, PyObject *args)
1184
{
1185
    char *iconName;
1186
    if (!PyArg_ParseTuple(args, "s", &iconName))
1187
        return nullptr;
1188

1189
    QPixmap icon;
1190

1191
    return Py::new_reference_to(Py::Boolean(BitmapFactory().findPixmapInCache(iconName, icon)));
1192
}
1193

1194
PyObject* Application::sAddCommand(PyObject * /*self*/, PyObject *args)
1195
{
1196
    char* pName;
1197
    char* pSource = nullptr;
1198
    PyObject* pcCmdObj;
1199
    if (!PyArg_ParseTuple(args, "sO|s", &pName,&pcCmdObj,&pSource))
1200
        return nullptr;
1201

1202
    // get the call stack to find the Python module name
1203
    //
1204
    std::string module, group;
1205
    try {
1206
        Base::PyGILStateLocker lock;
1207
        Py::Module mod(PyImport_ImportModule("inspect"), true);
1208
        if (mod.isNull()) {
1209
            PyErr_SetString(PyExc_ImportError, "Cannot load inspect module");
1210
            return nullptr;
1211
        }
1212
        Py::Callable inspect(mod.getAttr("stack"));
1213
        Py::List list(inspect.apply());
1214

1215
        std::string file;
1216
        // usually this is the file name of the calling script
1217
        Py::Object info = list.getItem(0);
1218
        PyObject *pyfile = PyStructSequence_GET_ITEM(*info,1);
1219
        if(!pyfile)
1220
            throw Py::Exception();
1221

1222
        file = Py::Object(pyfile).as_string();
1223
        Base::FileInfo fi(file);
1224
        // convert backslashes to slashes
1225
        file = fi.filePath();
1226
        module = fi.fileNamePure();
1227

1228
        // for the group name get the directory name after 'Mod'
1229
        boost::regex rx("/Mod/(\\w+)/");
1230
        boost::smatch what;
1231
        if (boost::regex_search(file, what, rx)) {
1232
            group = what[1];
1233
        }
1234
        else {
1235
            boost::regex rx("/Ext/freecad/(\\w+)/");
1236
            if (boost::regex_search(file, what, rx))
1237
                group = what[1];
1238
            else
1239
                group = module;
1240
        }
1241
    }
1242
    catch (Py::Exception& e) {
1243
        e.clear();
1244
    }
1245
    try {
1246
        Base::PyGILStateLocker lock;
1247

1248
        Py::Object cmd(pcCmdObj);
1249
        if (cmd.hasAttr("GetCommands")) {
1250
            Command* cmd = new PythonGroupCommand(pName, pcCmdObj);
1251
            if (!module.empty()) {
1252
                cmd->setAppModuleName(module.c_str());
1253
            }
1254
            if (!group.empty()) {
1255
                cmd->setGroupName(group.c_str());
1256
            }
1257
            Application::Instance->commandManager().addCommand(cmd);
1258
        }
1259
        else {
1260
            Command* cmd = new PythonCommand(pName, pcCmdObj, pSource);
1261
            if (!module.empty()) {
1262
                cmd->setAppModuleName(module.c_str());
1263
            }
1264
            if (!group.empty()) {
1265
                cmd->setGroupName(group.c_str());
1266
            }
1267
            Application::Instance->commandManager().addCommand(cmd);
1268
        }
1269
    }
1270
    catch (const Base::Exception& e) {
1271
        e.setPyException();
1272
        return nullptr;
1273
    }
1274
    catch (...) {
1275
        PyErr_SetString(Base::PyExc_FC_GeneralError, "Unknown C++ exception raised in Application::sAddCommand()");
1276
        return nullptr;
1277
    }
1278

1279
    Py_Return;
1280
}
1281

1282
PyObject* Application::sRunCommand(PyObject * /*self*/, PyObject *args)
1283
{
1284
    char* pName;
1285
    int item = 0;
1286
    if (!PyArg_ParseTuple(args, "s|i", &pName, &item))
1287
        return nullptr;
1288

1289
    Gui::Command::LogDisabler d1;
1290
    Gui::SelectionLogDisabler d2;
1291

1292
    Command* cmd = Application::Instance->commandManager().getCommandByName(pName);
1293
    if (cmd) {
1294
        cmd->invoke(item);
1295
        Py_Return;
1296
    }
1297
    else {
1298
        PyErr_Format(Base::PyExc_FC_GeneralError, "No such command '%s'", pName);
1299
        return nullptr;
1300
    }
1301
}
1302

1303
PyObject* Application::sDoCommand(PyObject * /*self*/, PyObject *args)
1304
{
1305
    char *sCmd = nullptr;
1306
    if (!PyArg_ParseTuple(args, "s", &sCmd))
1307
        return nullptr;
1308

1309
    Gui::Command::LogDisabler d1;
1310
    Gui::SelectionLogDisabler d2;
1311

1312
    Gui::Command::printPyCaller();
1313
    Gui::Application::Instance->macroManager()->addLine(MacroManager::App, sCmd);
1314

1315
    PyObject *module, *dict;
1316

1317
    Base::PyGILStateLocker locker;
1318
    module = PyImport_AddModule("__main__");
1319
    if (!module)
1320
        return nullptr;
1321

1322
    dict = PyModule_GetDict(module);
1323
    if (!dict)
1324
        return nullptr;
1325

1326
    return PyRun_String(sCmd, Py_file_input, dict, dict);
1327
}
1328

1329
PyObject* Application::sDoCommandGui(PyObject * /*self*/, PyObject *args)
1330
{
1331
    char *sCmd = nullptr;
1332
    if (!PyArg_ParseTuple(args, "s", &sCmd))
1333
        return nullptr;
1334

1335
    Gui::Command::LogDisabler d1;
1336
    Gui::SelectionLogDisabler d2;
1337

1338
    Gui::Command::printPyCaller();
1339
    Gui::Application::Instance->macroManager()->addLine(MacroManager::Gui, sCmd);
1340

1341
    PyObject *module, *dict;
1342

1343
    Base::PyGILStateLocker locker;
1344
    module = PyImport_AddModule("__main__");
1345
    if (!module)
1346
        return nullptr;
1347

1348
    dict = PyModule_GetDict(module);
1349
    if (!dict)
1350
        return nullptr;
1351

1352
    return PyRun_String(sCmd, Py_file_input, dict, dict);
1353
}
1354

1355
PyObject* Application::sAddModule(PyObject * /*self*/, PyObject *args)
1356
{
1357
    char *pstr;
1358
    if (!PyArg_ParseTuple(args, "s", &pstr))
1359
        return nullptr;
1360

1361
    try {
1362
        Command::addModule(Command::Doc,pstr);
1363
        Py_Return;
1364
    }
1365
    catch (const Base::Exception& e) {
1366
        PyErr_SetString(PyExc_ImportError, e.what());
1367
        return nullptr;
1368
    }
1369
}
1370

1371
PyObject* Application::sShowDownloads(PyObject * /*self*/, PyObject *args)
1372
{
1373
    if (!PyArg_ParseTuple(args, ""))
1374
        return nullptr;
1375

1376
    Gui::Dialog::DownloadManager::getInstance();
1377

1378
    Py_Return;
1379
}
1380

1381
PyObject* Application::sShowPreferences(PyObject * /*self*/, PyObject *args)
1382
{
1383
    char *pstr = nullptr;
1384
    int idx=0;
1385
    if (!PyArg_ParseTuple(args, "|si", &pstr, &idx))
1386
        return nullptr;
1387

1388
    Gui::Dialog::DlgPreferencesImp cDlg(getMainWindow());
1389
    if (pstr)
1390
        cDlg.activateGroupPage(QString::fromUtf8(pstr),idx);
1391

1392
    WaitCursor wc;
1393
    wc.restoreCursor();
1394
    cDlg.exec();
1395
    wc.setWaitCursor();
1396

1397
    Py_Return;
1398
}
1399

1400
PyObject* Application::sCreateViewer(PyObject * /*self*/, PyObject *args)
1401
{
1402
    int num_of_views = 1;
1403
    char* title = nullptr;
1404
    // if one argument (int) is given
1405
    if (!PyArg_ParseTuple(args, "|is", &num_of_views, &title))
1406
        return nullptr;
1407

1408
    if (num_of_views <= 0) {
1409
        PyErr_Format(PyExc_ValueError, "views must be > 0");
1410
        return nullptr;
1411
    }
1412
    else if (num_of_views == 1) {
1413
        auto viewer = new View3DInventor(nullptr, nullptr);
1414
        if (title)
1415
            viewer->setWindowTitle(QString::fromUtf8(title));
1416
        Gui::getMainWindow()->addWindow(viewer);
1417
        return viewer->getPyObject();
1418
    }
1419
    else {
1420
        auto viewer = new SplitView3DInventor(num_of_views, nullptr, nullptr);
1421
        if (title)
1422
            viewer->setWindowTitle(QString::fromUtf8(title));
1423
        Gui::getMainWindow()->addWindow(viewer);
1424
        return viewer->getPyObject();
1425
    }
1426
}
1427

1428
PyObject* Application::sGetMarkerIndex(PyObject * /*self*/, PyObject *args)
1429
{
1430
    char *pstr {};
1431
    int  defSize = 9;
1432
    if (!PyArg_ParseTuple(args, "s|i", &pstr, &defSize))
1433
        return nullptr;
1434

1435
    PY_TRY {
1436
        ParameterGrp::handle const hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
1437

1438
        //find the appropriate marker style string token
1439
        std::string marker_arg = pstr;
1440

1441
        std::list<std::pair<std::string, std::string> > markerList = {
1442
            {"square", "DIAMOND_FILLED"},
1443
            {"cross", "CROSS"},
1444
            {"hourglass", "HOURGLASS_FILLED"},
1445
            {"plus", "PLUS"},
1446
            {"empty", "SQUARE_LINE"},
1447
            {"quad", "SQUARE_FILLED"},
1448
            {"circle", "CIRCLE_LINE"},
1449
            {"default", "CIRCLE_FILLED"}
1450
        };
1451

1452
        auto findIt = std::find_if(markerList.begin(), markerList.end(), [&marker_arg](const auto& it) {
1453
            return marker_arg == it.first || marker_arg == it.second;
1454
        });
1455

1456
        marker_arg = (findIt != markerList.end() ? findIt->second : "CIRCLE_FILLED");
1457

1458

1459
        //get the marker size
1460
        auto sizeList = Gui::Inventor::MarkerBitmaps::getSupportedSizes(marker_arg);
1461

1462
        if (std::find(std::begin(sizeList), std::end(sizeList), defSize) == std::end(sizeList))
1463
            defSize = 9;
1464

1465
        return Py_BuildValue("i", Gui::Inventor::MarkerBitmaps::getMarkerIndex(marker_arg, defSize));
1466
    }
1467
    PY_CATCH;
1468
}
1469

1470
PyObject* Application::sReload(PyObject * /*self*/, PyObject *args)
1471
{
1472
    const char *name;
1473
    if (!PyArg_ParseTuple(args, "s", &name))
1474
        return nullptr;
1475

1476
    PY_TRY {
1477
        auto doc = Application::Instance->reopen(App::GetApplication().getDocument(name));
1478
        if(doc)
1479
            return doc->getPyObject();
1480
        Py_Return;
1481
    }
1482
    PY_CATCH;
1483
}
1484

1485
PyObject* Application::sLoadFile(PyObject * /*self*/, PyObject *args)
1486
{
1487
    const char *path = "";
1488
    const char *mod = "";
1489
    if (!PyArg_ParseTuple(args, "s|s", &path, &mod))
1490
        return nullptr;
1491

1492
    PY_TRY {
1493
        Base::FileInfo fi(path);
1494
        if (!fi.isFile() || !fi.exists()) {
1495
            PyErr_Format(PyExc_IOError, "File %s doesn't exist.", path);
1496
            return nullptr;
1497
        }
1498

1499
        std::string module = mod;
1500
        if (module.empty()) {
1501
            std::string ext = fi.extension();
1502
            std::vector<std::string> modules = App::GetApplication().getImportModules(ext.c_str());
1503
            if (modules.empty()) {
1504
                PyErr_Format(PyExc_IOError, "Filetype %s is not supported.", ext.c_str());
1505
                return nullptr;
1506
            }
1507
            else {
1508
                module = modules.front();
1509
            }
1510
        }
1511

1512
        Application::Instance->open(path,module.c_str());
1513

1514
        Py_Return;
1515
    }
1516
    PY_CATCH
1517
}
1518

1519
PyObject* Application::sAddDocObserver(PyObject * /*self*/, PyObject *args)
1520
{
1521
    PyObject* o;
1522
    if (!PyArg_ParseTuple(args, "O",&o))
1523
        return nullptr;
1524

1525
    PY_TRY {
1526
        DocumentObserverPython::addObserver(Py::Object(o));
1527
        Py_Return;
1528
    }
1529
    PY_CATCH;
1530
}
1531

1532
PyObject* Application::sRemoveDocObserver(PyObject * /*self*/, PyObject *args)
1533
{
1534
    PyObject* o;
1535
    if (!PyArg_ParseTuple(args, "O",&o))
1536
        return nullptr;
1537

1538
    PY_TRY {
1539
        DocumentObserverPython::removeObserver(Py::Object(o));
1540
        Py_Return;
1541
    }
1542
    PY_CATCH;
1543
}
1544

1545
PyObject* Application::sAddWbManipulator(PyObject * /*self*/, PyObject *args)
1546
{
1547
    PyObject* o;
1548
    if (!PyArg_ParseTuple(args, "O",&o))
1549
        return nullptr;
1550

1551
    PY_TRY {
1552
        WorkbenchManipulatorPython::installManipulator(Py::Object(o));
1553
        Py_Return;
1554
    }
1555
    PY_CATCH;
1556
}
1557

1558
PyObject* Application::sRemoveWbManipulator(PyObject * /*self*/, PyObject *args)
1559
{
1560
    PyObject* o;
1561
    if (!PyArg_ParseTuple(args, "O",&o))
1562
        return nullptr;
1563

1564
    PY_TRY {
1565
        WorkbenchManipulatorPython::removeManipulator(Py::Object(o));
1566
        Py_Return;
1567
    }
1568
    PY_CATCH;
1569
}
1570

1571
PyObject* Application::sCoinRemoveAllChildren(PyObject * /*self*/, PyObject *args)
1572
{
1573
    PyObject *pynode;
1574
    if (!PyArg_ParseTuple(args, "O", &pynode))
1575
        return nullptr;
1576

1577
    PY_TRY {
1578
        void* ptr = nullptr;
1579
        Base::Interpreter().convertSWIGPointerObj("pivy.coin","_p_SoGroup", pynode, &ptr, 0);
1580
        coinRemoveAllChildren(static_cast<SoGroup*>(ptr));
1581
        Py_Return;
1582
    }
1583
    PY_CATCH;
1584
}
1585

1586
PyObject* Application::sListUserEditModes(PyObject * /*self*/, PyObject *args)
1587
{
1588
    Py::List ret;
1589
    if (!PyArg_ParseTuple(args, ""))
1590
        return nullptr;
1591

1592
    for (auto const &uem : Instance->listUserEditModes()) {
1593
        ret.append(Py::String(uem.second.first));
1594
    }
1595

1596
    return Py::new_reference_to(ret);
1597
}
1598

1599
PyObject* Application::sGetUserEditMode(PyObject * /*self*/, PyObject *args)
1600
{
1601
    if (!PyArg_ParseTuple(args, ""))
1602
        return nullptr;
1603

1604
    return Py::new_reference_to(Py::String(Instance->getUserEditModeUIStrings().first));
1605
}
1606

1607
PyObject* Application::sSetUserEditMode(PyObject * /*self*/, PyObject *args)
1608
{
1609
    const char *mode = "";
1610
    if (!PyArg_ParseTuple(args, "s", &mode))
1611
        return nullptr;
1612

1613
    bool ok = Instance->setUserEditMode(std::string(mode));
1614

1615
    return Py::new_reference_to(Py::Boolean(ok));
1616
}
1617

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

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

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

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