FreeCAD

Форк
0
/
DocumentPyImp.cpp 
1000 строк · 30.6 Кб
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) {
74
        if (enumVals && PySequence_Check(enumVals)) {
75
            std::vector<std::string> enumValsAsVector;
76
            for (Py_ssize_t i = 0; i < PySequence_Length(enumVals); ++i) {
77
                enumValsAsVector.emplace_back(PyUnicode_AsUTF8(PySequence_GetItem(enumVals,i)));
78
            }
79
            propEnum->setEnums(enumValsAsVector);
80
        }
81
    }
82

83
    return Py::new_reference_to(this);
84
}
85

86
PyObject*  DocumentPy::removeProperty(PyObject *args)
87
{
88
    char *sName;
89
    if (!PyArg_ParseTuple(args, "s", &sName))
90
        return nullptr;
91

92
    bool ok = getDocumentPtr()->removeDynamicProperty(sName);
93
    return Py_BuildValue("O", (ok ? Py_True : Py_False));
94
}
95

96
// returns a string which represent the object e.g. when printed in python
97
std::string DocumentPy::representation() const
98
{
99
    std::stringstream str;
100
    str << "<Document object at " << getDocumentPtr() << ">";
101

102
    return str.str();
103
}
104

105
PyObject*  DocumentPy::save(PyObject * args)
106
{
107
    if (!PyArg_ParseTuple(args, ""))
108
        return nullptr;
109

110
    PY_TRY {
111
        if (!getDocumentPtr()->save()) {
112
            PyErr_SetString(PyExc_ValueError, "Object attribute 'FileName' is not set");
113
            return nullptr;
114
        }
115
    } PY_CATCH;
116

117
    const char* filename = getDocumentPtr()->FileName.getValue();
118
    Base::FileInfo fi(filename);
119
    if (!fi.isReadable()) {
120
        PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
121
        return nullptr;
122
    }
123

124
    Py_Return;
125
}
126

127
PyObject*  DocumentPy::saveAs(PyObject * args)
128
{
129
    char* fn;
130
    if (!PyArg_ParseTuple(args, "et", "utf-8", &fn))
131
        return nullptr;
132

133
    std::string utf8Name = fn;
134
    PyMem_Free(fn);
135

136
    PY_TRY {
137
        getDocumentPtr()->saveAs(utf8Name.c_str());
138
        Py_Return;
139
    }PY_CATCH
140
}
141

142
PyObject*  DocumentPy::saveCopy(PyObject * args)
143
{
144
    char* fn;
145
    if (!PyArg_ParseTuple(args, "s", &fn))
146
        return nullptr;
147

148
    PY_TRY {
149
        getDocumentPtr()->saveCopy(fn);
150
        Py_Return;
151
    }PY_CATCH
152
}
153

154
PyObject*  DocumentPy::load(PyObject * args)
155
{
156
    char* filename=nullptr;
157
    if (!PyArg_ParseTuple(args, "s", &filename))
158
        return nullptr;
159
    if (!filename || *filename == '\0') {
160
        PyErr_Format(PyExc_ValueError, "Path is empty");
161
        return nullptr;
162
    }
163

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

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

202
PyObject* DocumentPy::isSaved(PyObject* args)
203
{
204
    if (!PyArg_ParseTuple(args, ""))
205
        return nullptr;
206
    bool ok = getDocumentPtr()->isSaved();
207
    return Py::new_reference_to(Py::Boolean(ok));
208
}
209

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

218
PyObject* DocumentPy::getFileName(PyObject* args)
219
{
220
    if (!PyArg_ParseTuple(args, ""))
221
        return nullptr;
222
    const char* fn = getDocumentPtr()->getFileName();
223
    return Py::new_reference_to(Py::String(fn));
224
}
225

226
PyObject*  DocumentPy::mergeProject(PyObject * args)
227
{
228
    char* filename;
229
    if (!PyArg_ParseTuple(args, "s", &filename))
230
        return nullptr;
231

232
    PY_TRY {
233
        Base::FileInfo fi(filename);
234
        Base::ifstream str(fi, std::ios::in | std::ios::binary);
235
        App::Document* doc = getDocumentPtr();
236
        MergeDocuments md(doc);
237
        md.importObjects(str);
238
        Py_Return;
239
    } PY_CATCH;
240
}
241

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

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

274
    DocumentObject *pcFtr = nullptr;
275

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

306
            if (Base::asBoolean(attach)) {
307
                getDocumentPtr()->addObject(pcFtr,sName);
308

309
                try {
310
                    Py::Callable method(pyobj.getAttr("attach"));
311
                    if (!method.isNone()) {
312
                        Py::TupleN arg(pyftr);
313
                        method.apply(arg);
314
                    }
315
                }
316
                catch (Py::Exception&) {
317
                    Base::PyException e;
318
                    e.ReportException();
319
                }
320
            }
321

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

334
            Py::Object pyprx(pyftr.getAttr("ViewObject"));
335
            pyprx.setAttr("Proxy", pyvp);
336
            return Py::new_reference_to(pyftr);
337
        }
338
        catch (Py::Exception& e) {
339
            e.clear();
340
        }
341
    }
342
    return pcFtr->getPyObject();
343
}
344

345
PyObject*  DocumentPy::removeObject(PyObject *args)
346
{
347
    char *sName;
348
    if (!PyArg_ParseTuple(args, "s",&sName))
349
        return nullptr;
350

351

352
    DocumentObject *pcFtr = getDocumentPtr()->getObject(sName);
353
    if (pcFtr) {
354
        getDocumentPtr()->removeObject( sName );
355
        Py_Return;
356
    }
357
    else {
358
        std::stringstream str;
359
        str << "No document object found with name '" << sName << "'" << std::ends;
360
        throw Py::ValueError(str.str());
361
    }
362
}
363

364
PyObject*  DocumentPy::copyObject(PyObject *args)
365
{
366
    PyObject *obj, *rec=Py_False, *retAll=Py_False;
367
    if (!PyArg_ParseTuple(args, "O|O!O!",&obj,&PyBool_Type,&rec,&PyBool_Type,&retAll))
368
        return nullptr;
369

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

392
    PY_TRY {
393
        auto ret = getDocumentPtr()->copyObject(objs, Base::asBoolean(rec), Base::asBoolean(retAll));
394
        if (ret.size()==1 && single)
395
            return ret[0]->getPyObject();
396

397
        Py::Tuple tuple(ret.size());
398
        for (size_t i=0;i<ret.size();++i)
399
            tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
400
        return Py::new_reference_to(tuple);
401
    } PY_CATCH
402
}
403

404
PyObject*  DocumentPy::importLinks(PyObject *args)
405
{
406
    PyObject *obj = Py_None;
407
    if (!PyArg_ParseTuple(args, "|O",&obj))
408
        return nullptr;
409

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

428
    if (objs.empty())
429
        objs = getDocumentPtr()->getObjects();
430

431
    PY_TRY {
432
        auto ret = getDocumentPtr()->importLinks(objs);
433

434
        Py::Tuple tuple(ret.size());
435
        for (size_t i=0;i<ret.size();++i)
436
            tuple.setItem(i,Py::Object(ret[i]->getPyObject(),true));
437
        return Py::new_reference_to(tuple);
438
    }
439
    PY_CATCH
440
}
441

442
PyObject*  DocumentPy::moveObject(PyObject *args)
443
{
444
    PyObject *obj, *rec=Py_False;
445
    if (!PyArg_ParseTuple(args, "O!|O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec))
446
        return nullptr;
447

448
    DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(obj);
449
    DocumentObject* move = getDocumentPtr()->moveObject(docObj->getDocumentObjectPtr(), Base::asBoolean(rec));
450
    if (move) {
451
        return move->getPyObject();
452
    }
453
    else {
454
        std::string str("Failed to move the object");
455
        throw Py::ValueError(str);
456
    }
457
}
458

459
PyObject*  DocumentPy::openTransaction(PyObject *args)
460
{
461
    PyObject *value = nullptr;
462
    if (!PyArg_ParseTuple(args, "|O",&value))
463
        return nullptr;
464
    std::string cmd;
465

466

467
    if (!value) {
468
        cmd = "<empty>";
469
    }
470
    else if (PyUnicode_Check(value)) {
471
        cmd = PyUnicode_AsUTF8(value);
472
    }
473
    else {
474
        PyErr_SetString(PyExc_TypeError, "string or unicode expected");
475
        return nullptr;
476
    }
477

478
    getDocumentPtr()->openTransaction(cmd.c_str());
479
    Py_Return;
480
}
481

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

490
PyObject*  DocumentPy::commitTransaction(PyObject * args)
491
{
492
    if (!PyArg_ParseTuple(args, ""))
493
        return nullptr;
494
    getDocumentPtr()->commitTransaction();
495
    Py_Return;
496
}
497

498
Py::Boolean DocumentPy::getHasPendingTransaction() const {
499
    return {getDocumentPtr()->hasPendingTransaction()};
500
}
501

502
PyObject*  DocumentPy::undo(PyObject * args)
503
{
504
    if (!PyArg_ParseTuple(args, ""))
505
        return nullptr;
506
    if (getDocumentPtr()->getAvailableUndos())
507
        getDocumentPtr()->undo();
508
    Py_Return;
509
}
510

511
PyObject*  DocumentPy::redo(PyObject * args)
512
{
513
    if (!PyArg_ParseTuple(args, ""))
514
        return nullptr;
515
    if (getDocumentPtr()->getAvailableRedos())
516
        getDocumentPtr()->redo();
517
    Py_Return;
518
}
519

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

528
PyObject* DocumentPy::clearDocument(PyObject * args)
529
{
530
    if (!PyArg_ParseTuple(args, ""))
531
        return nullptr;
532
    getDocumentPtr()->clearDocument();
533
    Py_Return;
534
}
535

536
PyObject* DocumentPy::setClosable(PyObject* args)
537
{
538
    PyObject* close;
539
    if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &close))
540
        return nullptr;
541
    getDocumentPtr()->setClosable(Base::asBoolean(close));
542
    Py_Return;
543
}
544

545
PyObject* DocumentPy::isClosable(PyObject* args)
546
{
547
    if (!PyArg_ParseTuple(args, ""))
548
        return nullptr;
549
    bool ok = getDocumentPtr()->isClosable();
550
    return Py::new_reference_to(Py::Boolean(ok));
551
}
552

553
PyObject*  DocumentPy::recompute(PyObject * args)
554
{
555
    PyObject *pyobjs = Py_None;
556
    PyObject *force = Py_False;
557
    PyObject *checkCycle = Py_False;
558
    if (!PyArg_ParseTuple(args, "|OO!O!",&pyobjs,
559
                &PyBool_Type,&force,&PyBool_Type,&checkCycle))
560
        return nullptr;
561

562
    PY_TRY {
563
        std::vector<App::DocumentObject *> objs;
564
        if (pyobjs!=Py_None) {
565
            if (!PySequence_Check(pyobjs)) {
566
                PyErr_SetString(PyExc_TypeError, "expect input of sequence of document objects");
567
                return nullptr;
568
            }
569

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

580
        int options = 0;
581
        if (Base::asBoolean(checkCycle))
582
            options = Document::DepNoCycle;
583

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

586
        // Document::recompute() hides possibly raised Python exceptions by its features
587
        // So, check if an error is set and return null if yes
588
        if (PyErr_Occurred()) {
589
            return nullptr;
590
        }
591

592
        return Py::new_reference_to(Py::Int(objectCount));
593
    } PY_CATCH;
594
}
595

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

604
PyObject* DocumentPy::isTouched(PyObject* args)
605
{
606
    if (!PyArg_ParseTuple(args, ""))
607
        return nullptr;
608
    bool ok = getDocumentPtr()->isTouched();
609
    return Py::new_reference_to(Py::Boolean(ok));
610
}
611

612
PyObject* DocumentPy::purgeTouched(PyObject* args)
613
{
614
    if (!PyArg_ParseTuple(args, ""))
615
        return nullptr;
616
    getDocumentPtr()->purgeTouched();
617
    Py_Return;
618
}
619

620
PyObject* DocumentPy::getObject(PyObject *args)
621
{
622
    DocumentObject* obj = nullptr;
623

624
    do {
625
        char* name = nullptr;
626
        if (PyArg_ParseTuple(args, "s", &name))  {
627
            obj = getDocumentPtr()->getObject(name);
628
            break;
629
        }
630

631
        PyErr_Clear();
632
        long id = -1;
633
        if (PyArg_ParseTuple(args, "l", &id)) {
634
            obj = getDocumentPtr()->getObjectByID(id);
635
            break;
636
        }
637

638
        PyErr_SetString(PyExc_TypeError, "a string or integer is required");
639
        return nullptr;
640
    }
641
    while (false);
642

643
    if (obj)
644
        return obj->getPyObject();
645

646
    Py_Return;
647
}
648

649
PyObject*  DocumentPy::getObjectsByLabel(PyObject *args)
650
{
651
    char *sName;
652
    if (!PyArg_ParseTuple(args, "s",&sName))
653
        return nullptr;
654

655
    Py::List list;
656
    std::string name = sName;
657
    std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
658
    for (auto obj : objs) {
659
        if (name == obj->Label.getValue())
660
            list.append(Py::asObject(obj->getPyObject()));
661
    }
662

663
    return Py::new_reference_to(list);
664
}
665

666
PyObject*  DocumentPy::findObjects(PyObject *args, PyObject *kwds)
667
{
668
    const char *sType = "App::DocumentObject", *sName = nullptr, *sLabel = nullptr;
669
    static const std::array<const char *, 4> kwlist{"Type", "Name", "Label", nullptr};
670
    if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "|sss", kwlist, &sType, &sName, &sLabel)) {
671
        return nullptr;
672
    }
673

674
    Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true);
675
    if (type.isBad()) {
676
        std::stringstream str;
677
        str << "'" << sType << "' is not a document object type";
678
        throw Base::TypeError(str.str());
679
    }
680

681
    std::vector<DocumentObject*> res;
682

683
    try {
684
        res = getDocumentPtr()->findObjects(type, sName, sLabel);
685
    }
686
    catch (const boost::regex_error& e) {
687
        PyErr_SetString(PyExc_RuntimeError, e.what());
688
        return nullptr;
689
    }
690

691
    Py_ssize_t index=0;
692
    PyObject* list = PyList_New((Py_ssize_t)res.size());
693
    for (std::vector<DocumentObject*>::const_iterator It = res.begin();It != res.end();++It, index++)
694
        PyList_SetItem(list, index, (*It)->getPyObject());
695
    return list;
696
}
697

698
Py::Object DocumentPy::getActiveObject() const
699
{
700
    DocumentObject *pcFtr = getDocumentPtr()->getActiveObject();
701
    if (pcFtr)
702
        return Py::Object(pcFtr->getPyObject(), true);
703
    return Py::None();
704
}
705

706
PyObject*  DocumentPy::supportedTypes(PyObject *args)
707
{
708
    if (!PyArg_ParseTuple(args, ""))
709
        return nullptr;
710

711
    std::vector<Base::Type> ary;
712
    Base::Type::getAllDerivedFrom(App::DocumentObject::getClassTypeId(), ary);
713
    Py::List res;
714
    for (const auto & it : ary)
715
        res.append(Py::String(it.getName()));
716
    return Py::new_reference_to(res);
717
}
718

719
Py::List DocumentPy::getObjects() const
720
{
721
    std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
722
    Py::List res;
723

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

728
    return res;
729
}
730

731
Py::List DocumentPy::getTopologicalSortedObjects() const
732
{
733
    std::vector<DocumentObject*> objs = getDocumentPtr()->topologicalSort();
734
    Py::List res;
735

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

740
    return res;
741
}
742

743
Py::List DocumentPy::getRootObjects() const
744
{
745
    std::vector<DocumentObject*> objs = getDocumentPtr()->getRootObjects();
746
    Py::List res;
747

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

752
    return res;
753
}
754

755
Py::Int DocumentPy::getUndoMode() const
756
{
757
    return Py::Int(getDocumentPtr()->getUndoMode());
758
}
759

760
void  DocumentPy::setUndoMode(Py::Int arg)
761
{
762
    getDocumentPtr()->setUndoMode(arg);
763
}
764

765

766
Py::Int DocumentPy::getUndoRedoMemSize() const
767
{
768
    return Py::Int((long)getDocumentPtr()->getUndoMemSize());
769
}
770

771
Py::Int DocumentPy::getUndoCount() const
772
{
773
    return Py::Int((long)getDocumentPtr()->getAvailableUndos());
774
}
775

776
Py::Int DocumentPy::getRedoCount() const
777
{
778
    return Py::Int((long)getDocumentPtr()->getAvailableRedos());
779
}
780

781
Py::List DocumentPy::getUndoNames() const
782
{
783
    std::vector<std::string> vList = getDocumentPtr()->getAvailableUndoNames();
784
    Py::List res;
785

786
    for (const auto & It : vList)
787
        res.append(Py::String(It));
788

789
    return res;
790
}
791

792
Py::List DocumentPy::getRedoNames() const
793
{
794
    std::vector<std::string> vList = getDocumentPtr()->getAvailableRedoNames();
795
    Py::List res;
796

797
    for (const auto & It : vList)
798
        res.append(Py::String(It));
799

800
    return res;
801
}
802

803
Py::String  DocumentPy::getDependencyGraph() const
804
{
805
    std::stringstream out;
806
    getDocumentPtr()->exportGraphviz(out);
807
    return {out.str()};
808
}
809

810
Py::String DocumentPy::getName() const
811
{
812
    return {getDocumentPtr()->getName()};
813
}
814

815
Py::Boolean DocumentPy::getRecomputesFrozen() const
816
{
817
    return {getDocumentPtr()->testStatus(Document::Status::SkipRecompute)};
818
}
819

820
void DocumentPy::setRecomputesFrozen(Py::Boolean arg)
821
{
822
    getDocumentPtr()->setStatus(Document::Status::SkipRecompute, arg.isTrue());
823
}
824

825
PyObject* DocumentPy::getTempFileName(PyObject *args)
826
{
827
    PyObject *value;
828
    if (!PyArg_ParseTuple(args, "O",&value))
829
        return nullptr;
830

831
    std::string string;
832
    if (PyUnicode_Check(value)) {
833
        string = PyUnicode_AsUTF8(value);
834
    }
835
    else {
836
        std::string error = std::string("type must be a string!");
837
        error += value->ob_type->tp_name;
838
        throw Py::TypeError(error);
839
    }
840

841
    // search for a temp file name in the document transient directory
842
    Base::FileInfo fileName(Base::FileInfo::getTempFileName
843
        (string.c_str(),getDocumentPtr()->TransientDir.getValue()));
844
    // delete the created file, we need only the name...
845
    fileName.deleteFile();
846

847
    PyObject *p = PyUnicode_DecodeUTF8(fileName.filePath().c_str(),fileName.filePath().size(),nullptr);
848
    if (!p) {
849
        throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()");
850
    }
851
    return p;
852
}
853

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

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

903
    return 0;
904
}
905

906
PyObject* DocumentPy::getLinksTo(PyObject *args)
907
{
908
    PyObject *pyobj = Py_None;
909
    int options = 0;
910
    short count = 0;
911
    if (!PyArg_ParseTuple(args, "|Oih", &pyobj,&options, &count))
912
        return nullptr;
913

914
    PY_TRY {
915
        Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type document object");
916
        DocumentObject *obj = nullptr;
917
        if (pyobj)
918
            obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
919

920
        std::set<DocumentObject *> links;
921
        getDocumentPtr()->getLinksTo(links,obj,options,count);
922
        Py::Tuple ret(links.size());
923
        int i=0;
924
        for (auto o : links)
925
            ret.setItem(i++,Py::Object(o->getPyObject(),true));
926

927
        return Py::new_reference_to(ret);
928
    }
929
    PY_CATCH
930
}
931

932
Py::List DocumentPy::getInList() const
933
{
934
    Py::List ret;
935
    auto lists = PropertyXLink::getDocumentInList(getDocumentPtr());
936
    if (lists.size()==1) {
937
        for (auto doc : lists.begin()->second)
938
            ret.append(Py::Object(doc->getPyObject(), true));
939
    }
940
    return ret;
941
}
942

943
Py::List DocumentPy::getOutList() const
944
{
945
    Py::List ret;
946
    auto lists = PropertyXLink::getDocumentOutList(getDocumentPtr());
947
    if (lists.size()==1) {
948
        for (auto doc : lists.begin()->second)
949
            ret.append(Py::Object(doc->getPyObject(), true));
950
    }
951
    return ret;
952
}
953

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

967
Py::Boolean DocumentPy::getRestoring() const
968
{
969
    return {getDocumentPtr()->testStatus(Document::Status::Restoring)};
970
}
971

972
Py::Boolean DocumentPy::getPartial() const
973
{
974
    return {getDocumentPtr()->testStatus(Document::Status::PartialDoc)};
975
}
976

977
Py::Boolean DocumentPy::getImporting() const
978
{
979
    return {getDocumentPtr()->testStatus(Document::Status::Importing)};
980
}
981

982
Py::Boolean DocumentPy::getRecomputing() const
983
{
984
    return {getDocumentPtr()->testStatus(Document::Status::Recomputing)};
985
}
986

987
Py::Boolean DocumentPy::getTransacting() const
988
{
989
    return {getDocumentPtr()->isPerformingTransaction()};
990
}
991

992
Py::String DocumentPy::getOldLabel() const
993
{
994
    return {getDocumentPtr()->getOldLabel()};
995
}
996

997
Py::Boolean DocumentPy::getTemporary() const
998
{
999
    return {getDocumentPtr()->testStatus(Document::TempDoc)};
1000
}
1001

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

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

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

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