FreeCAD

Форк
0
/
DocumentPyImp.cpp 
1006 строк · 30.7 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2007 Jürgen Riegel <juergen.riegel@web.de>              *
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

24
#include "PreCompiled.h"
25

26
#include <Base/FileInfo.h>
27
#include <Base/Interpreter.h>
28
#include <Base/Stream.h>
29

30
#include "Document.h"
31
#include "DocumentObject.h"
32
#include "DocumentObjectPy.h"
33
#include "MergeDocuments.h"
34

35
// inclusion of the generated files (generated By DocumentPy.xml)
36
#include "DocumentPy.h"
37
#include "DocumentPy.cpp"
38
#include <boost/regex.hpp>
39
#include <Base/PyWrapParseTupleAndKeywords.h>
40

41
using namespace App;
42

43

44
PyObject*  DocumentPy::addProperty(PyObject *args, PyObject *kwd)
45
{
46
    char *sType {nullptr};
47
    char *sName {nullptr};
48
    char *sGroup {nullptr};
49
    char *sDoc {nullptr};
50
    short attr=0;
51
    std::string sDocStr;
52
    PyObject *ro = Py_False, *hd = Py_False;
53
    PyObject* enumVals = nullptr;
54
    static const std::array<const char *, 9> kwlist{"type", "name", "group", "doc", "attr",
55
                                                    "read_only", "hidden", "enum_vals", nullptr};
56
    if (!Base::Wrapped_ParseTupleAndKeywords(
57
            args, kwd, "ss|sethO!O!O", kwlist, &sType, &sName, &sGroup, "utf-8",
58
            &sDoc, &attr, &PyBool_Type, &ro, &PyBool_Type, &hd, &enumVals)) {
59
        return nullptr;
60
    }
61

62
    if (sDoc) {
63
        sDocStr = sDoc;
64
        PyMem_Free(sDoc);
65
    }
66

67
    Property *prop = getDocumentPtr()->
68
        addDynamicProperty(sType,sName,sGroup,sDocStr.c_str(),attr,
69
                           Base::asBoolean(ro), Base::asBoolean(hd));
70

71
    // enum support
72
    auto* propEnum = dynamic_cast<App::PropertyEnumeration*>(prop);
73
    if (propEnum && enumVals) {
74
        propEnum->setPyObject(enumVals);
75
    }
76

77
    return Py::new_reference_to(this);
78
}
79

80
PyObject*  DocumentPy::removeProperty(PyObject *args)
81
{
82
    char *sName;
83
    if (!PyArg_ParseTuple(args, "s", &sName))
84
        return nullptr;
85

86
    bool ok = getDocumentPtr()->removeDynamicProperty(sName);
87
    return Py_BuildValue("O", (ok ? Py_True : Py_False));
88
}
89

90
// returns a string which represent the object e.g. when printed in python
91
std::string DocumentPy::representation() const
92
{
93
    std::stringstream str;
94
    str << "<Document object at " << getDocumentPtr() << ">";
95

96
    return str.str();
97
}
98

99
PyObject*  DocumentPy::save(PyObject * args)
100
{
101
    if (!PyArg_ParseTuple(args, ""))
102
        return nullptr;
103

104
    PY_TRY {
105
        if (!getDocumentPtr()->save()) {
106
            PyErr_SetString(PyExc_ValueError, "Object attribute 'FileName' is not set");
107
            return nullptr;
108
        }
109
    } PY_CATCH;
110

111
    const char* filename = getDocumentPtr()->FileName.getValue();
112
    Base::FileInfo fi(filename);
113
    if (!fi.isReadable()) {
114
        PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
115
        return nullptr;
116
    }
117

118
    Py_Return;
119
}
120

121
PyObject*  DocumentPy::saveAs(PyObject * args)
122
{
123
    char* fn;
124
    if (!PyArg_ParseTuple(args, "et", "utf-8", &fn))
125
        return nullptr;
126

127
    std::string utf8Name = fn;
128
    PyMem_Free(fn);
129

130
    PY_TRY {
131
        getDocumentPtr()->saveAs(utf8Name.c_str());
132
        Py_Return;
133
    }PY_CATCH
134
}
135

136
PyObject*  DocumentPy::saveCopy(PyObject * args)
137
{
138
    char* fn;
139
    if (!PyArg_ParseTuple(args, "s", &fn))
140
        return nullptr;
141

142
    PY_TRY {
143
        getDocumentPtr()->saveCopy(fn);
144
        Py_Return;
145
    }PY_CATCH
146
}
147

148
PyObject*  DocumentPy::load(PyObject * args)
149
{
150
    char* filename=nullptr;
151
    if (!PyArg_ParseTuple(args, "s", &filename))
152
        return nullptr;
153
    if (!filename || *filename == '\0') {
154
        PyErr_Format(PyExc_ValueError, "Path is empty");
155
        return nullptr;
156
    }
157

158
    getDocumentPtr()->FileName.setValue(filename);
159
    Base::FileInfo fi(filename);
160
    if (!fi.isReadable()) {
161
        PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
162
        return nullptr;
163
    }
164
    try {
165
        getDocumentPtr()->restore();
166
    } catch (...) {
167
        PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename);
168
        return nullptr;
169
    }
170
    Py_Return;
171
}
172

173
PyObject*  DocumentPy::restore(PyObject * args)
174
{
175
    if (!PyArg_ParseTuple(args, ""))
176
        return nullptr;
177
    const char* filename = getDocumentPtr()->FileName.getValue();
178
    if (!filename || *filename == '\0') {
179
        PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set");
180
        return nullptr;
181
    }
182
    Base::FileInfo fi(filename);
183
    if (!fi.isReadable()) {
184
        PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
185
        return nullptr;
186
    }
187
    try {
188
        getDocumentPtr()->restore();
189
    } catch (...) {
190
        PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename);
191
        return nullptr;
192
    }
193
    Py_Return;
194
}
195

196
PyObject* DocumentPy::isSaved(PyObject* args)
197
{
198
    if (!PyArg_ParseTuple(args, ""))
199
        return nullptr;
200
    bool ok = getDocumentPtr()->isSaved();
201
    return Py::new_reference_to(Py::Boolean(ok));
202
}
203

204
PyObject* DocumentPy::getProgramVersion(PyObject* args)
205
{
206
    if (!PyArg_ParseTuple(args, ""))
207
        return nullptr;
208
    const char* version = getDocumentPtr()->getProgramVersion();
209
    return Py::new_reference_to(Py::String(version));
210
}
211

212
PyObject* DocumentPy::getFileName(PyObject* args)
213
{
214
    if (!PyArg_ParseTuple(args, ""))
215
        return nullptr;
216
    const char* fn = getDocumentPtr()->getFileName();
217
    return Py::new_reference_to(Py::String(fn));
218
}
219

220
PyObject*  DocumentPy::mergeProject(PyObject * args)
221
{
222
    char* filename;
223
    if (!PyArg_ParseTuple(args, "s", &filename))
224
        return nullptr;
225

226
    PY_TRY {
227
        Base::FileInfo fi(filename);
228
        Base::ifstream str(fi, std::ios::in | std::ios::binary);
229
        App::Document* doc = getDocumentPtr();
230
        MergeDocuments md(doc);
231
        md.importObjects(str);
232
        Py_Return;
233
    } PY_CATCH;
234
}
235

236
PyObject*  DocumentPy::exportGraphviz(PyObject * args)
237
{
238
    char* fn=nullptr;
239
    if (!PyArg_ParseTuple(args, "|s",&fn))
240
        return nullptr;
241
    if (fn) {
242
        Base::FileInfo fi(fn);
243
        Base::ofstream str(fi);
244
        getDocumentPtr()->exportGraphviz(str);
245
        str.close();
246
        Py_Return;
247
    }
248
    else {
249
        std::stringstream str;
250
        getDocumentPtr()->exportGraphviz(str);
251
        return PyUnicode_FromString(str.str().c_str());
252
    }
253
}
254

255
PyObject*  DocumentPy::addObject(PyObject *args, PyObject *kwd)
256
{
257
    char *sType, *sName = nullptr, *sViewType = nullptr;
258
    PyObject *obj = nullptr;
259
    PyObject *view = nullptr;
260
    PyObject *attach = Py_False;
261
    static const std::array<const char *, 7> kwlist{"type", "name", "objProxy", "viewProxy", "attach", "viewType",
262
                                                    nullptr};
263
    if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "s|sOOO!s",
264
                                             kwlist, &sType, &sName, &obj, &view, &PyBool_Type, &attach, &sViewType)) {
265
        return nullptr;
266
    }
267

268
    DocumentObject *pcFtr = nullptr;
269

270
    if (!obj || !Base::asBoolean(attach)) {
271
        pcFtr = getDocumentPtr()->addObject(sType,sName,true,sViewType);
272
    }
273
    else {
274
        Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, DocumentObject::getClassTypeId(), true);
275
        if (type.isBad()) {
276
            std::stringstream str;
277
            str << "'" << sType << "' is not a document object type";
278
            throw Base::TypeError(str.str());
279
        }
280
        pcFtr = static_cast<DocumentObject*>(type.createInstance());
281
    }
282
    // the type instance could be a null pointer
283
    if (!pcFtr) {
284
        std::stringstream str;
285
        str << "No document object found of type '" << sType << "'" << std::ends;
286
        throw Py::TypeError(str.str());
287
    }
288
    // Allows to hide the handling with Proxy in client python code
289
    if (obj) {
290
        try {
291
            // the python binding class to the document object
292
            Py::Object pyftr = Py::asObject(pcFtr->getPyObject());
293
            // 'pyobj' is the python class with the implementation for DocumentObject
294
            Py::Object pyobj(obj);
295
            if (pyobj.hasAttr("__object__")) {
296
                pyobj.setAttr("__object__", pyftr);
297
            }
298
            pyftr.setAttr("Proxy", pyobj);
299

300
            if (Base::asBoolean(attach)) {
301
                getDocumentPtr()->addObject(pcFtr,sName);
302

303
                try {
304
                    Py::Callable method(pyobj.getAttr("attach"));
305
                    if (!method.isNone()) {
306
                        Py::TupleN arg(pyftr);
307
                        method.apply(arg);
308
                    }
309
                }
310
                catch (Py::Exception&) {
311
                    Base::PyException e;
312
                    e.ReportException();
313
                }
314
            }
315

316
            // if a document class is set we also need a view provider defined which must be
317
            // something different to None
318
            Py::Object pyvp;
319
            if (view)
320
                pyvp = Py::Object(view);
321
            if (pyvp.isNone())
322
                pyvp = Py::Int(1);
323
            // 'pyvp' is the python class with the implementation for ViewProvider
324
            if (pyvp.hasAttr("__vobject__")) {
325
                pyvp.setAttr("__vobject__", pyftr.getAttr("ViewObject"));
326
            }
327

328
            Py::Object pyprx(pyftr.getAttr("ViewObject"));
329
            pyprx.setAttr("Proxy", pyvp);
330
            return Py::new_reference_to(pyftr);
331
        }
332
        catch (Py::Exception& e) {
333
            e.clear();
334
        }
335
    }
336
    return pcFtr->getPyObject();
337
}
338

339
PyObject*  DocumentPy::removeObject(PyObject *args)
340
{
341
    char *sName;
342
    if (!PyArg_ParseTuple(args, "s",&sName))
343
        return nullptr;
344

345

346
    DocumentObject *pcFtr = getDocumentPtr()->getObject(sName);
347
    if (pcFtr) {
348
        getDocumentPtr()->removeObject( sName );
349
        Py_Return;
350
    }
351
    else {
352
        std::stringstream str;
353
        str << "No document object found with name '" << sName << "'" << std::ends;
354
        throw Py::ValueError(str.str());
355
    }
356
}
357

358
PyObject*  DocumentPy::copyObject(PyObject *args)
359
{
360
    PyObject *obj, *rec=Py_False, *retAll=Py_False;
361
    if (!PyArg_ParseTuple(args, "O|O!O!",&obj,&PyBool_Type,&rec,&PyBool_Type,&retAll))
362
        return nullptr;
363

364
    std::vector<App::DocumentObject*> objs;
365
    bool single = false;
366
    if (PySequence_Check(obj)) {
367
        Py::Sequence seq(obj);
368
        for (Py_ssize_t i=0;i<seq.size();++i) {
369
            if (!PyObject_TypeCheck(seq[i].ptr(),&DocumentObjectPy::Type)) {
370
                PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
371
                return nullptr;
372
            }
373
            objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
374
        }
375
    }
376
    else if (!PyObject_TypeCheck(obj,&DocumentObjectPy::Type)) {
377
        PyErr_SetString(PyExc_TypeError,
378
            "Expect first argument to be either a document object or sequence of document objects");
379
        return nullptr;
380
    }
381
    else {
382
        objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
383
        single = true;
384
    }
385

386
    PY_TRY {
387
        auto ret = getDocumentPtr()->copyObject(objs, Base::asBoolean(rec), Base::asBoolean(retAll));
388
        if (ret.size()==1 && single)
389
            return ret[0]->getPyObject();
390

391
        Py::Tuple tuple(ret.size());
392
        for (size_t i=0;i<ret.size();++i)
393
            tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
394
        return Py::new_reference_to(tuple);
395
    } PY_CATCH
396
}
397

398
PyObject*  DocumentPy::importLinks(PyObject *args)
399
{
400
    PyObject *obj = Py_None;
401
    if (!PyArg_ParseTuple(args, "|O",&obj))
402
        return nullptr;
403

404
    std::vector<App::DocumentObject*> objs;
405
    if (PySequence_Check(obj)) {
406
        Py::Sequence seq(obj);
407
        for (Py_ssize_t i=0;i<seq.size();++i) {
408
            if (!PyObject_TypeCheck(seq[i].ptr(),&DocumentObjectPy::Type)) {
409
                PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
410
                return nullptr;
411
            }
412
            objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
413
        }
414
    }
415
    else {
416
        Base::PyTypeCheck(&obj, &DocumentObjectPy::Type,
417
            "Expect first argument to be either a document object, sequence of document objects or None");
418
        if (obj)
419
            objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
420
    }
421

422
    if (objs.empty())
423
        objs = getDocumentPtr()->getObjects();
424

425
    PY_TRY {
426
        auto ret = getDocumentPtr()->importLinks(objs);
427

428
        Py::Tuple tuple(ret.size());
429
        for (size_t i=0;i<ret.size();++i)
430
            tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
431
        return Py::new_reference_to(tuple);
432
    }
433
    PY_CATCH
434
}
435

436
PyObject*  DocumentPy::moveObject(PyObject *args)
437
{
438
    PyObject *obj, *rec=Py_False;
439
    if (!PyArg_ParseTuple(args, "O!|O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec))
440
        return nullptr;
441

442
    DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(obj);
443
    DocumentObject* move = getDocumentPtr()->moveObject(docObj->getDocumentObjectPtr(), Base::asBoolean(rec));
444
    if (move) {
445
        return move->getPyObject();
446
    }
447
    else {
448
        std::string str("Failed to move the object");
449
        throw Py::ValueError(str);
450
    }
451
}
452

453
PyObject*  DocumentPy::openTransaction(PyObject *args)
454
{
455
    PyObject *value = nullptr;
456
    if (!PyArg_ParseTuple(args, "|O",&value))
457
        return nullptr;
458
    std::string cmd;
459

460

461
    if (!value) {
462
        cmd = "<empty>";
463
    }
464
    else if (PyUnicode_Check(value)) {
465
        cmd = PyUnicode_AsUTF8(value);
466
    }
467
    else {
468
        PyErr_SetString(PyExc_TypeError, "string or unicode expected");
469
        return nullptr;
470
    }
471

472
    getDocumentPtr()->openTransaction(cmd.c_str());
473
    Py_Return;
474
}
475

476
PyObject*  DocumentPy::abortTransaction(PyObject * args)
477
{
478
    if (!PyArg_ParseTuple(args, ""))
479
        return nullptr;
480
    getDocumentPtr()->abortTransaction();
481
    Py_Return;
482
}
483

484
PyObject*  DocumentPy::commitTransaction(PyObject * args)
485
{
486
    if (!PyArg_ParseTuple(args, ""))
487
        return nullptr;
488
    getDocumentPtr()->commitTransaction();
489
    Py_Return;
490
}
491

492
Py::Boolean DocumentPy::getHasPendingTransaction() const {
493
    return {getDocumentPtr()->hasPendingTransaction()};
494
}
495

496
PyObject*  DocumentPy::undo(PyObject * args)
497
{
498
    if (!PyArg_ParseTuple(args, ""))
499
        return nullptr;
500
    if (getDocumentPtr()->getAvailableUndos())
501
        getDocumentPtr()->undo();
502
    Py_Return;
503
}
504

505
PyObject*  DocumentPy::redo(PyObject * args)
506
{
507
    if (!PyArg_ParseTuple(args, ""))
508
        return nullptr;
509
    if (getDocumentPtr()->getAvailableRedos())
510
        getDocumentPtr()->redo();
511
    Py_Return;
512
}
513

514
PyObject* DocumentPy::clearUndos(PyObject * args)
515
{
516
    if (!PyArg_ParseTuple(args, ""))
517
        return nullptr;
518
    getDocumentPtr()->clearUndos();
519
    Py_Return;
520
}
521

522
PyObject* DocumentPy::clearDocument(PyObject * args)
523
{
524
    if (!PyArg_ParseTuple(args, ""))
525
        return nullptr;
526
    getDocumentPtr()->clearDocument();
527
    Py_Return;
528
}
529

530
PyObject* DocumentPy::setClosable(PyObject* args)
531
{
532
    PyObject* close;
533
    if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &close))
534
        return nullptr;
535
    getDocumentPtr()->setClosable(Base::asBoolean(close));
536
    Py_Return;
537
}
538

539
PyObject* DocumentPy::isClosable(PyObject* args)
540
{
541
    if (!PyArg_ParseTuple(args, ""))
542
        return nullptr;
543
    bool ok = getDocumentPtr()->isClosable();
544
    return Py::new_reference_to(Py::Boolean(ok));
545
}
546

547
PyObject*  DocumentPy::recompute(PyObject * args)
548
{
549
    PyObject *pyobjs = Py_None;
550
    PyObject *force = Py_False;
551
    PyObject *checkCycle = Py_False;
552
    if (!PyArg_ParseTuple(args, "|OO!O!",&pyobjs,
553
                &PyBool_Type,&force,&PyBool_Type,&checkCycle))
554
        return nullptr;
555

556
    PY_TRY {
557
        std::vector<App::DocumentObject *> objs;
558
        if (pyobjs!=Py_None) {
559
            if (!PySequence_Check(pyobjs)) {
560
                PyErr_SetString(PyExc_TypeError, "expect input of sequence of document objects");
561
                return nullptr;
562
            }
563

564
            Py::Sequence seq(pyobjs);
565
            for (Py_ssize_t i=0;i<seq.size();++i) {
566
                if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
567
                    PyErr_SetString(PyExc_TypeError, "Expect element in sequence to be of type document object");
568
                    return nullptr;
569
                }
570
                objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
571
            }
572
        }
573

574
        int options = 0;
575
        if (Base::asBoolean(checkCycle))
576
            options = Document::DepNoCycle;
577

578
        int objectCount = getDocumentPtr()->recompute(objs, Base::asBoolean(force), nullptr, options);
579

580
        // Document::recompute() hides possibly raised Python exceptions by its features
581
        // So, check if an error is set and return null if yes
582
        if (PyErr_Occurred()) {
583
            return nullptr;
584
        }
585

586
        return Py::new_reference_to(Py::Int(objectCount));
587
    } PY_CATCH;
588
}
589

590
PyObject* DocumentPy::mustExecute(PyObject* args)
591
{
592
    if (!PyArg_ParseTuple(args, ""))
593
        return nullptr;
594
    bool ok = getDocumentPtr()->mustExecute();
595
    return Py::new_reference_to(Py::Boolean(ok));
596
}
597

598
PyObject* DocumentPy::isTouched(PyObject* args)
599
{
600
    if (!PyArg_ParseTuple(args, ""))
601
        return nullptr;
602
    bool ok = getDocumentPtr()->isTouched();
603
    return Py::new_reference_to(Py::Boolean(ok));
604
}
605

606
PyObject* DocumentPy::purgeTouched(PyObject* args)
607
{
608
    if (!PyArg_ParseTuple(args, ""))
609
        return nullptr;
610
    getDocumentPtr()->purgeTouched();
611
    Py_Return;
612
}
613

614
PyObject* DocumentPy::getObject(PyObject *args)
615
{
616
    DocumentObject* obj = nullptr;
617

618
    do {
619
        char* name = nullptr;
620
        if (PyArg_ParseTuple(args, "s", &name))  {
621
            obj = getDocumentPtr()->getObject(name);
622
            break;
623
        }
624

625
        PyErr_Clear();
626
        long id = -1;
627
        if (PyArg_ParseTuple(args, "l", &id)) {
628
            obj = getDocumentPtr()->getObjectByID(id);
629
            break;
630
        }
631

632
        PyErr_SetString(PyExc_TypeError, "a string or integer is required");
633
        return nullptr;
634
    }
635
    while (false);
636

637
    if (obj)
638
        return obj->getPyObject();
639

640
    Py_Return;
641
}
642

643
PyObject*  DocumentPy::getObjectsByLabel(PyObject *args)
644
{
645
    char *sName;
646
    if (!PyArg_ParseTuple(args, "s",&sName))
647
        return nullptr;
648

649
    Py::List list;
650
    std::string name = sName;
651
    std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
652
    for (auto obj : objs) {
653
        if (name == obj->Label.getValue())
654
            list.append(Py::asObject(obj->getPyObject()));
655
    }
656

657
    return Py::new_reference_to(list);
658
}
659

660
PyObject*  DocumentPy::findObjects(PyObject *args, PyObject *kwds)
661
{
662
    const char *sType = "App::DocumentObject", *sName = nullptr, *sLabel = nullptr;
663
    static const std::array<const char *, 4> kwlist{"Type", "Name", "Label", nullptr};
664
    if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "|sss", kwlist, &sType, &sName, &sLabel)) {
665
        return nullptr;
666
    }
667

668
    Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true);
669
    if (type.isBad()) {
670
        std::stringstream str;
671
        str << "'" << sType << "' is not a document object type";
672
        throw Base::TypeError(str.str());
673
    }
674

675
    std::vector<DocumentObject*> res;
676

677
    try {
678
        res = getDocumentPtr()->findObjects(type, sName, sLabel);
679
    }
680
    catch (const boost::regex_error& e) {
681
        PyErr_SetString(PyExc_RuntimeError, e.what());
682
        return nullptr;
683
    }
684

685
    Py_ssize_t index=0;
686
    PyObject* list = PyList_New((Py_ssize_t)res.size());
687
    for (std::vector<DocumentObject*>::const_iterator It = res.begin();It != res.end();++It, index++)
688
        PyList_SetItem(list, index, (*It)->getPyObject());
689
    return list;
690
}
691

692
Py::Object DocumentPy::getActiveObject() const
693
{
694
    DocumentObject *pcFtr = getDocumentPtr()->getActiveObject();
695
    if (pcFtr)
696
        return Py::Object(pcFtr->getPyObject(), true);
697
    return Py::None();
698
}
699

700
PyObject*  DocumentPy::supportedTypes(PyObject *args)
701
{
702
    if (!PyArg_ParseTuple(args, ""))
703
        return nullptr;
704

705
    std::vector<Base::Type> ary;
706
    Base::Type::getAllDerivedFrom(App::DocumentObject::getClassTypeId(), ary);
707
    Py::List res;
708
    for (const auto & it : ary)
709
        res.append(Py::String(it.getName()));
710
    return Py::new_reference_to(res);
711
}
712

713
Py::List DocumentPy::getObjects() const
714
{
715
    std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
716
    Py::List res;
717

718
    for (auto obj : objs)
719
        //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter
720
        res.append(Py::Object(obj->getPyObject(), true));
721

722
    return res;
723
}
724

725
Py::List DocumentPy::getTopologicalSortedObjects() const
726
{
727
    std::vector<DocumentObject*> objs = getDocumentPtr()->topologicalSort();
728
    Py::List res;
729

730
    for (auto obj : objs)
731
        //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter
732
        res.append(Py::Object(obj->getPyObject(), true));
733

734
    return res;
735
}
736

737
Py::List DocumentPy::getRootObjects() const
738
{
739
    std::vector<DocumentObject*> objs = getDocumentPtr()->getRootObjects();
740
    Py::List res;
741

742
    for (auto obj : objs)
743
        //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter
744
        res.append(Py::Object(obj->getPyObject(), true));
745

746
    return res;
747
}
748

749
Py::List DocumentPy::getRootObjectsIgnoreLinks() const
750
{
751
    std::vector<App::DocumentObject*> objs = getDocumentPtr()->getRootObjectsIgnoreLinks();
752
    Py::List res;
753

754
    for (auto obj : objs)
755
        //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter
756
        res.append(Py::Object(obj->getPyObject(), true));
757

758
    return res;
759
}
760

761
Py::Int DocumentPy::getUndoMode() const
762
{
763
    return Py::Int(getDocumentPtr()->getUndoMode());
764
}
765

766
void  DocumentPy::setUndoMode(Py::Int arg)
767
{
768
    getDocumentPtr()->setUndoMode(arg);
769
}
770

771

772
Py::Int DocumentPy::getUndoRedoMemSize() const
773
{
774
    return Py::Int((long)getDocumentPtr()->getUndoMemSize());
775
}
776

777
Py::Int DocumentPy::getUndoCount() const
778
{
779
    return Py::Int((long)getDocumentPtr()->getAvailableUndos());
780
}
781

782
Py::Int DocumentPy::getRedoCount() const
783
{
784
    return Py::Int((long)getDocumentPtr()->getAvailableRedos());
785
}
786

787
Py::List DocumentPy::getUndoNames() const
788
{
789
    std::vector<std::string> vList = getDocumentPtr()->getAvailableUndoNames();
790
    Py::List res;
791

792
    for (const auto & It : vList)
793
        res.append(Py::String(It));
794

795
    return res;
796
}
797

798
Py::List DocumentPy::getRedoNames() const
799
{
800
    std::vector<std::string> vList = getDocumentPtr()->getAvailableRedoNames();
801
    Py::List res;
802

803
    for (const auto & It : vList)
804
        res.append(Py::String(It));
805

806
    return res;
807
}
808

809
Py::String  DocumentPy::getDependencyGraph() const
810
{
811
    std::stringstream out;
812
    getDocumentPtr()->exportGraphviz(out);
813
    return {out.str()};
814
}
815

816
Py::String DocumentPy::getName() const
817
{
818
    return {getDocumentPtr()->getName()};
819
}
820

821
Py::Boolean DocumentPy::getRecomputesFrozen() const
822
{
823
    return {getDocumentPtr()->testStatus(Document::Status::SkipRecompute)};
824
}
825

826
void DocumentPy::setRecomputesFrozen(Py::Boolean arg)
827
{
828
    getDocumentPtr()->setStatus(Document::Status::SkipRecompute, arg.isTrue());
829
}
830

831
PyObject* DocumentPy::getTempFileName(PyObject *args)
832
{
833
    PyObject *value;
834
    if (!PyArg_ParseTuple(args, "O",&value))
835
        return nullptr;
836

837
    std::string string;
838
    if (PyUnicode_Check(value)) {
839
        string = PyUnicode_AsUTF8(value);
840
    }
841
    else {
842
        std::string error = std::string("type must be a string!");
843
        error += value->ob_type->tp_name;
844
        throw Py::TypeError(error);
845
    }
846

847
    // search for a temp file name in the document transient directory
848
    Base::FileInfo fileName(Base::FileInfo::getTempFileName
849
        (string.c_str(),getDocumentPtr()->TransientDir.getValue()));
850
    // delete the created file, we need only the name...
851
    fileName.deleteFile();
852

853
    PyObject *p = PyUnicode_DecodeUTF8(fileName.filePath().c_str(),fileName.filePath().size(),nullptr);
854
    if (!p) {
855
        throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()");
856
    }
857
    return p;
858
}
859

860
PyObject *DocumentPy::getCustomAttributes(const char* attr) const
861
{
862
    // Note: Here we want to return only a document object if its
863
    // name matches 'attr'. However, it is possible to have an object
864
    // with the same name as an attribute. If so, we return 0 as other-
865
    // wise it wouldn't be possible to address this attribute any more.
866
    // The object must then be addressed by the getObject() method directly.
867
    App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
868
    if (prop)
869
        return nullptr;
870
    if (!this->ob_type->tp_dict) {
871
        if (PyType_Ready(this->ob_type) < 0)
872
            return nullptr;
873
    }
874
    PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
875
    if (item)
876
        return nullptr;
877
    // search for an object with this name
878
    DocumentObject* obj = getDocumentPtr()->getObject(attr);
879
    return (obj ? obj->getPyObject() : nullptr);
880
}
881

882
int DocumentPy::setCustomAttributes(const char* attr, PyObject *)
883
{
884
    // Note: Here we want to return only a document object if its
885
    // name matches 'attr'. However, it is possible to have an object
886
    // with the same name as an attribute. If so, we return 0 as other-
887
    // wise it wouldn't be possible to address this attribute any more.
888
    // The object must then be addressed by the getObject() method directly.
889
    App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
890
    if (prop)
891
        return 0;
892
    if (!this->ob_type->tp_dict) {
893
        if (PyType_Ready(this->ob_type) < 0)
894
            return 0;
895
    }
896
    PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
897
    if (item)
898
        return 0;
899
    DocumentObject* obj = getDocumentPtr()->getObject(attr);
900
    if (obj)
901
    {
902
        std::stringstream str;
903
        str << "'Document' object attribute '" << attr
904
            << "' must not be set this way" << std::ends;
905
        PyErr_SetString(PyExc_RuntimeError, str.str().c_str());
906
        return -1;
907
    }
908

909
    return 0;
910
}
911

912
PyObject* DocumentPy::getLinksTo(PyObject *args)
913
{
914
    PyObject *pyobj = Py_None;
915
    int options = 0;
916
    short count = 0;
917
    if (!PyArg_ParseTuple(args, "|Oih", &pyobj,&options, &count))
918
        return nullptr;
919

920
    PY_TRY {
921
        Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type document object");
922
        DocumentObject *obj = nullptr;
923
        if (pyobj)
924
            obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
925

926
        std::set<DocumentObject *> links;
927
        getDocumentPtr()->getLinksTo(links,obj,options,count);
928
        Py::Tuple ret(links.size());
929
        int i=0;
930
        for (auto o : links)
931
            ret.setItem(i++,Py::Object(o->getPyObject(),true));
932

933
        return Py::new_reference_to(ret);
934
    }
935
    PY_CATCH
936
}
937

938
Py::List DocumentPy::getInList() const
939
{
940
    Py::List ret;
941
    auto lists = PropertyXLink::getDocumentInList(getDocumentPtr());
942
    if (lists.size()==1) {
943
        for (auto doc : lists.begin()->second)
944
            ret.append(Py::Object(doc->getPyObject(), true));
945
    }
946
    return ret;
947
}
948

949
Py::List DocumentPy::getOutList() const
950
{
951
    Py::List ret;
952
    auto lists = PropertyXLink::getDocumentOutList(getDocumentPtr());
953
    if (lists.size()==1) {
954
        for (auto doc : lists.begin()->second)
955
            ret.append(Py::Object(doc->getPyObject(), true));
956
    }
957
    return ret;
958
}
959

960
PyObject *DocumentPy::getDependentDocuments(PyObject *args) {
961
    PyObject *sort = Py_True;
962
    if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort))
963
        return nullptr;
964
    PY_TRY {
965
        auto docs = getDocumentPtr()->getDependentDocuments(Base::asBoolean(sort));
966
        Py::List ret;
967
        for (auto doc : docs)
968
            ret.append(Py::Object(doc->getPyObject(), true));
969
        return Py::new_reference_to(ret);
970
    } PY_CATCH;
971
}
972

973
Py::Boolean DocumentPy::getRestoring() const
974
{
975
    return {getDocumentPtr()->testStatus(Document::Status::Restoring)};
976
}
977

978
Py::Boolean DocumentPy::getPartial() const
979
{
980
    return {getDocumentPtr()->testStatus(Document::Status::PartialDoc)};
981
}
982

983
Py::Boolean DocumentPy::getImporting() const
984
{
985
    return {getDocumentPtr()->testStatus(Document::Status::Importing)};
986
}
987

988
Py::Boolean DocumentPy::getRecomputing() const
989
{
990
    return {getDocumentPtr()->testStatus(Document::Status::Recomputing)};
991
}
992

993
Py::Boolean DocumentPy::getTransacting() const
994
{
995
    return {getDocumentPtr()->isPerformingTransaction()};
996
}
997

998
Py::String DocumentPy::getOldLabel() const
999
{
1000
    return {getDocumentPtr()->getOldLabel()};
1001
}
1002

1003
Py::Boolean DocumentPy::getTemporary() const
1004
{
1005
    return {getDocumentPtr()->testStatus(Document::TempDoc)};
1006
}
1007

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

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

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

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