FreeCAD

Форк
0
/
DocumentObserverPython.cpp 
577 строк · 20.5 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2009 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

24
#include "PreCompiled.h"
25
#ifndef _PreComp_
26
#include <functional>
27
#endif
28

29
#include <CXX/Objects.hxx>
30
#include "Application.h"
31
#include "Document.h"
32
#include "DocumentObject.h"
33
#include "DocumentObserverPython.h"
34
#include <Base/Interpreter.h>
35

36

37
using namespace App;
38
namespace sp = std::placeholders;
39

40
std::vector<DocumentObserverPython*> DocumentObserverPython::_instances;
41

42
void DocumentObserverPython::addObserver(const Py::Object& obj)
43
{
44
    _instances.push_back(new DocumentObserverPython(obj));
45
}
46

47
void DocumentObserverPython::removeObserver(const Py::Object& obj)
48
{
49
    DocumentObserverPython* obs=nullptr;
50
    for (std::vector<DocumentObserverPython*>::iterator it =
51
        _instances.begin(); it != _instances.end(); ++it) {
52
        if ((*it)->inst == obj) {
53
            obs = *it;
54
            _instances.erase(it);
55
            break;
56
        }
57
    }
58

59
    delete obs;
60
}
61

62
DocumentObserverPython::DocumentObserverPython(const Py::Object& obj) : inst(obj)
63
{
64
#define FC_PY_ELEMENT_ARG0(_name1, _name2) do {\
65
        FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py);\
66
        if (!py##_name1.py.isNone())\
67
            py##_name1.slot = App::GetApplication().signal##_name2.connect(\
68
                    std::bind(&DocumentObserverPython::slot##_name1, this));\
69
    }\
70
    while(0);
71

72

73
#define FC_PY_ELEMENT_ARG1(_name1, _name2) do {\
74
        FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py);\
75
        if (!py##_name1.py.isNone())\
76
            py##_name1.slot = App::GetApplication().signal##_name2.connect(\
77
                    std::bind(&DocumentObserverPython::slot##_name1, this, sp::_1));\
78
    }\
79
    while(0);
80

81
    //NOLINTBEGIN
82
#define FC_PY_ELEMENT_ARG2(_name1, _name2) do {\
83
        FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py);\
84
        if (!py##_name1.py.isNone())\
85
            py##_name1.slot = App::GetApplication().signal##_name2.connect(\
86
                    std::bind(&DocumentObserverPython::slot##_name1, this, sp::_1, sp::_2));\
87
    }\
88
    while(0);
89

90
    FC_PY_ELEMENT_ARG1(CreatedDocument, NewDocument)
91
    FC_PY_ELEMENT_ARG1(DeletedDocument, DeleteDocument)
92
    FC_PY_ELEMENT_ARG1(RelabelDocument, RelabelDocument)
93
    FC_PY_ELEMENT_ARG1(ActivateDocument, ActiveDocument)
94
    FC_PY_ELEMENT_ARG1(UndoDocument, UndoDocument)
95
    FC_PY_ELEMENT_ARG1(RedoDocument, RedoDocument)
96
    FC_PY_ELEMENT_ARG2(BeforeChangeDocument, BeforeChangeDocument)
97
    FC_PY_ELEMENT_ARG2(ChangedDocument, ChangedDocument)
98
    FC_PY_ELEMENT_ARG1(CreatedObject, NewObject)
99
    FC_PY_ELEMENT_ARG1(DeletedObject, DeletedObject)
100
    FC_PY_ELEMENT_ARG2(BeforeChangeObject, BeforeChangeObject)
101
    FC_PY_ELEMENT_ARG2(ChangedObject, ChangedObject)
102
    FC_PY_ELEMENT_ARG1(RecomputedObject, ObjectRecomputed)
103
    FC_PY_ELEMENT_ARG1(BeforeRecomputeDocument, BeforeRecomputeDocument)
104
    FC_PY_ELEMENT_ARG1(RecomputedDocument, Recomputed)
105
    FC_PY_ELEMENT_ARG2(OpenTransaction, OpenTransaction)
106
    FC_PY_ELEMENT_ARG1(CommitTransaction, CommitTransaction)
107
    FC_PY_ELEMENT_ARG1(AbortTransaction, AbortTransaction)
108
    FC_PY_ELEMENT_ARG0(Undo, Undo)
109
    FC_PY_ELEMENT_ARG0(Redo, Redo)
110
    FC_PY_ELEMENT_ARG1(BeforeCloseTransaction, BeforeCloseTransaction)
111
    FC_PY_ELEMENT_ARG1(CloseTransaction, CloseTransaction)
112
    FC_PY_ELEMENT_ARG2(StartSaveDocument, StartSaveDocument)
113
    FC_PY_ELEMENT_ARG2(FinishSaveDocument, FinishSaveDocument)
114
    FC_PY_ELEMENT_ARG1(AppendDynamicProperty, AppendDynamicProperty)
115
    FC_PY_ELEMENT_ARG1(RemoveDynamicProperty, RemoveDynamicProperty)
116
    FC_PY_ELEMENT_ARG2(ChangePropertyEditor, ChangePropertyEditor)
117
    FC_PY_ELEMENT_ARG2(BeforeAddingDynamicExtension, BeforeAddingDynamicExtension)
118
    FC_PY_ELEMENT_ARG2(AddedDynamicExtension, AddedDynamicExtension)
119
    //NOLINTEND
120
}
121

122
DocumentObserverPython::~DocumentObserverPython() = default;
123

124
void DocumentObserverPython::slotCreatedDocument(const App::Document& Doc)
125
{
126
    Base::PyGILStateLocker lock;
127
    try {
128
        Py::Tuple args(1);
129
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
130
        Base::pyCall(pyCreatedDocument.ptr(),args.ptr());
131
    }
132
    catch (Py::Exception&) {
133
        Base::PyException e; // extract the Python error text
134
        e.ReportException();
135
    }
136
}
137

138
void DocumentObserverPython::slotDeletedDocument(const App::Document& Doc)
139
{
140
    Base::PyGILStateLocker lock;
141
    try {
142
        Py::Tuple args(1);
143
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
144
        Base::pyCall(pyDeletedDocument.ptr(),args.ptr());
145
    }
146
    catch (Py::Exception&) {
147
        Base::PyException e; // extract the Python error text
148
        e.ReportException();
149
    }
150
}
151

152
void DocumentObserverPython::slotRelabelDocument(const App::Document& Doc)
153
{
154
    Base::PyGILStateLocker lock;
155
    try {
156
        Py::Tuple args(1);
157
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
158
        Base::pyCall(pyRelabelDocument.ptr(),args.ptr());
159
    }
160
    catch (Py::Exception&) {
161
        Base::PyException e; // extract the Python error text
162
        e.ReportException();
163
    }
164
}
165

166
void DocumentObserverPython::slotActivateDocument(const App::Document& Doc)
167
{
168
    Base::PyGILStateLocker lock;
169
    try {
170
        Py::Tuple args(1);
171
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
172
        Base::pyCall(pyActivateDocument.ptr(),args.ptr());
173
    }
174
    catch (Py::Exception&) {
175
        Base::PyException e; // extract the Python error text
176
        e.ReportException();
177
    }
178
}
179

180
void DocumentObserverPython::slotUndoDocument(const App::Document& Doc)
181
{
182
    Base::PyGILStateLocker lock;
183
    try {
184
        Py::Tuple args(1);
185
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
186
        Base::pyCall(pyUndoDocument.ptr(),args.ptr());
187
    }
188
    catch (Py::Exception&) {
189
        Base::PyException e; // extract the Python error text
190
        e.ReportException();
191
    }
192
}
193

194

195
void DocumentObserverPython::slotRedoDocument(const App::Document& Doc)
196
{
197
    Base::PyGILStateLocker lock;
198
    try {
199
        Py::Tuple args(1);
200
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
201
        Base::pyCall(pyRedoDocument.ptr(),args.ptr());
202
    }
203
    catch (Py::Exception&) {
204
        Base::PyException e; // extract the Python error text
205
        e.ReportException();
206
    }
207
}
208

209
void DocumentObserverPython::slotUndo()
210
{
211
    Base::PyGILStateLocker lock;
212
    try {
213
        Base::pyCall(pyUndo.ptr());
214
    }
215
    catch (Py::Exception&) {
216
        Base::PyException e; // extract the Python error text
217
        e.ReportException();
218
    }
219
}
220

221
void DocumentObserverPython::slotRedo()
222
{
223
    Base::PyGILStateLocker lock;
224
    try {
225
        Base::pyCall(pyRedo.ptr());
226
    }
227
    catch (Py::Exception&) {
228
        Base::PyException e; // extract the Python error text
229
        e.ReportException();
230
    }
231
}
232

233
void DocumentObserverPython::slotBeforeCloseTransaction(bool abort)
234
{
235
    Base::PyGILStateLocker lock;
236
    try {
237
        Py::Tuple args(1);
238
        args.setItem(0, Py::Boolean(abort));
239
        Base::pyCall(pyBeforeCloseTransaction.ptr(),args.ptr());
240
    }
241
    catch (Py::Exception&) {
242
        Base::PyException e; // extract the Python error text
243
        e.ReportException();
244
    }
245
}
246

247
void DocumentObserverPython::slotCloseTransaction(bool abort)
248
{
249
    Base::PyGILStateLocker lock;
250
    try {
251
        Py::Tuple args(1);
252
        args.setItem(0, Py::Boolean(abort));
253
        Base::pyCall(pyCloseTransaction.ptr(),args.ptr());
254
    }
255
    catch (Py::Exception&) {
256
        Base::PyException e; // extract the Python error text
257
        e.ReportException();
258
    }
259
}
260

261
void DocumentObserverPython::slotBeforeChangeDocument(const App::Document& Doc, const App::Property& Prop)
262
{
263
    Base::PyGILStateLocker lock;
264
    try {
265
        Py::Tuple args(2);
266
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
267
        // If a property is touched but not part of a document object then its name is null.
268
        // In this case the slot function must not be called.
269
        const char* prop_name = Doc.getPropertyName(&Prop);
270
        if (prop_name) {
271
            args.setItem(1, Py::String(prop_name));
272
            Base::pyCall(pyBeforeChangeDocument.ptr(),args.ptr());
273
        }
274
    }
275
    catch (Py::Exception&) {
276
        Base::PyException e; // extract the Python error text
277
        e.ReportException();
278
    }
279
}
280

281
void DocumentObserverPython::slotChangedDocument(const App::Document& Doc, const App::Property& Prop)
282
{
283
    Base::PyGILStateLocker lock;
284
    try {
285
        Py::Tuple args(2);
286
        args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
287
        // If a property is touched but not part of a document object then its name is null.
288
        // In this case the slot function must not be called.
289
        const char* prop_name = Doc.getPropertyName(&Prop);
290
        if (prop_name) {
291
            args.setItem(1, Py::String(prop_name));
292
            Base::pyCall(pyChangedDocument.ptr(),args.ptr());
293
        }
294
    }
295
    catch (Py::Exception&) {
296
        Base::PyException e; // extract the Python error text
297
        e.ReportException();
298
    }
299
}
300

301
void DocumentObserverPython::slotCreatedObject(const App::DocumentObject& Obj)
302
{
303
    Base::PyGILStateLocker lock;
304
    try {
305
        Py::Tuple args(1);
306
        args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
307
        Base::pyCall(pyCreatedObject.ptr(),args.ptr());
308
    }
309
    catch (Py::Exception&) {
310
        Base::PyException e; // extract the Python error text
311
        e.ReportException();
312
    }
313
}
314

315
void DocumentObserverPython::slotDeletedObject(const App::DocumentObject& Obj)
316
{
317
    Base::PyGILStateLocker lock;
318
    try {
319
        Py::Tuple args(1);
320
        args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
321
        Base::pyCall(pyDeletedObject.ptr(),args.ptr());
322
    }
323
    catch (Py::Exception&) {
324
        Base::PyException e; // extract the Python error text
325
        e.ReportException();
326
    }
327
}
328

329
void DocumentObserverPython::slotBeforeChangeObject(const App::DocumentObject& Obj,
330
                                               const App::Property& Prop)
331
{
332
    Base::PyGILStateLocker lock;
333
    try {
334
        Py::Tuple args(2);
335
        args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
336
        // If a property is touched but not part of a document object then its name is null.
337
        // In this case the slot function must not be called.
338
        const char* prop_name = Obj.getPropertyName(&Prop);
339
        if (prop_name) {
340
            args.setItem(1, Py::String(prop_name));
341
            Base::pyCall(pyBeforeChangeObject.ptr(),args.ptr());
342
        }
343
    }
344
    catch (Py::Exception&) {
345
        Base::PyException e; // extract the Python error text
346
        e.ReportException();
347
    }
348
}
349

350
void DocumentObserverPython::slotChangedObject(const App::DocumentObject& Obj,
351
                                               const App::Property& Prop)
352
{
353
    Base::PyGILStateLocker lock;
354
    try {
355
        Py::Tuple args(2);
356
        args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
357
        // If a property is touched but not part of a document object then its name is null.
358
        // In this case the slot function must not be called.
359
        const char* prop_name = Obj.getPropertyName(&Prop);
360
        if (prop_name) {
361
            args.setItem(1, Py::String(prop_name));
362
            Base::pyCall(pyChangedObject.ptr(),args.ptr());
363
        }
364
    }
365
    catch (Py::Exception&) {
366
        Base::PyException e; // extract the Python error text
367
        e.ReportException();
368
    }
369
}
370

371
void DocumentObserverPython::slotRecomputedObject(const App::DocumentObject& Obj)
372
{
373
    Base::PyGILStateLocker lock;
374
    try {
375
        Py::Tuple args(1);
376
        args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
377
        Base::pyCall(pyRecomputedObject.ptr(),args.ptr());
378
    }
379
    catch (Py::Exception&) {
380
        Base::PyException e; // extract the Python error text
381
        e.ReportException();
382
    }
383
}
384

385
void DocumentObserverPython::slotRecomputedDocument(const App::Document& doc)
386
{
387
    Base::PyGILStateLocker lock;
388
    try {
389
        Py::Tuple args(1);
390
        args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
391
        Base::pyCall(pyRecomputedDocument.ptr(),args.ptr());
392
    }
393
    catch (Py::Exception&) {
394
        Base::PyException e; // extract the Python error text
395
        e.ReportException();
396
    }
397
}
398

399
void DocumentObserverPython::slotBeforeRecomputeDocument(const App::Document& doc)
400
{
401
    Base::PyGILStateLocker lock;
402
    try {
403
        Py::Tuple args(1);
404
        args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
405
        Base::pyCall(pyBeforeRecomputeDocument.ptr(),args.ptr());
406
    }
407
    catch (Py::Exception&) {
408
        Base::PyException e; // extract the Python error text
409
        e.ReportException();
410
    }
411
}
412

413
void DocumentObserverPython::slotOpenTransaction(const App::Document& doc, std::string str)
414
{
415
    Base::PyGILStateLocker lock;
416
    try {
417
        Py::Tuple args(2);
418
        args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
419
        args.setItem(1, Py::String(str));
420
        Base::pyCall(pyOpenTransaction.ptr(),args.ptr());
421
    }
422
    catch (Py::Exception&) {
423
        Base::PyException e; // extract the Python error text
424
        e.ReportException();
425
    }
426
}
427

428
void DocumentObserverPython::slotCommitTransaction(const App::Document& doc)
429
{
430
    Base::PyGILStateLocker lock;
431
    try {
432
        Py::Tuple args(1);
433
        args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
434
        Base::pyCall(pyCommitTransaction.ptr(),args.ptr());
435
    }
436
    catch (Py::Exception&) {
437
        Base::PyException e; // extract the Python error text
438
        e.ReportException();
439
    }
440
}
441

442
void DocumentObserverPython::slotAbortTransaction(const App::Document& doc)
443
{
444
    Base::PyGILStateLocker lock;
445
    try {
446
        Py::Tuple args(1);
447
        args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
448
        Base::pyCall(pyAbortTransaction.ptr(),args.ptr());
449
    }
450
    catch (Py::Exception&) {
451
        Base::PyException e; // extract the Python error text
452
        e.ReportException();
453
    }
454
}
455

456
void DocumentObserverPython::slotAppendDynamicProperty(const App::Property& Prop)
457
{
458
    Base::PyGILStateLocker lock;
459
    try {
460
        auto container = Prop.getContainer();
461
        Py::Tuple args(2);
462
        args.setItem(0, Py::asObject(container->getPyObject()));
463
        // If a property is touched but not part of a document object then its name is null.
464
        // In this case the slot function must not be called.
465
        const char* prop_name = container->getPropertyName(&Prop);
466
        if (prop_name) {
467
            args.setItem(1, Py::String(prop_name));
468
            Base::pyCall(pyAppendDynamicProperty.ptr(),args.ptr());
469
        }
470
    }
471
    catch (Py::Exception&) {
472
        Base::PyException e; // extract the Python error text
473
        e.ReportException();
474
    }
475
}
476

477
void DocumentObserverPython::slotRemoveDynamicProperty(const App::Property& Prop)
478
{
479
    Base::PyGILStateLocker lock;
480
    try {
481
        auto container = Prop.getContainer();
482
        Py::Tuple args(2);
483
        args.setItem(0, Py::asObject(container->getPyObject()));
484
        // If a property is touched but not part of a document object then its name is null.
485
        // In this case the slot function must not be called.
486
        const char* prop_name = container->getPropertyName(&Prop);
487
        if (prop_name) {
488
            args.setItem(1, Py::String(prop_name));
489
            Base::pyCall(pyRemoveDynamicProperty.ptr(),args.ptr());
490
        }
491
    }
492
    catch (Py::Exception&) {
493
        Base::PyException e; // extract the Python error text
494
        e.ReportException();
495
    }
496
}
497

498
void DocumentObserverPython::slotChangePropertyEditor(const App::Document &, const App::Property& Prop)
499
{
500
    Base::PyGILStateLocker lock;
501
    try {
502
        auto container = Prop.getContainer();
503
        Py::Tuple args(2);
504
        args.setItem(0, Py::asObject(container->getPyObject()));
505
        // If a property is touched but not part of a document object then its name is null.
506
        // In this case the slot function must not be called.
507
        const char* prop_name = container->getPropertyName(&Prop);
508
        if (prop_name) {
509
            args.setItem(1, Py::String(prop_name));
510
            Base::pyCall(pyChangePropertyEditor.ptr(),args.ptr());
511
        }
512
    }
513
    catch (Py::Exception&) {
514
        Base::PyException e; // extract the Python error text
515
        e.ReportException();
516
    }
517
}
518

519
void DocumentObserverPython::slotStartSaveDocument(const App::Document& doc, const std::string& file)
520
{
521
    Base::PyGILStateLocker lock;
522
    try {
523
        Py::Tuple args(2);
524
        args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
525
        args.setItem(1, Py::String(file));
526
        Base::pyCall(pyStartSaveDocument.ptr(),args.ptr());
527
    }
528
    catch (Py::Exception&) {
529
        Base::PyException e; // extract the Python error text
530
        e.ReportException();
531
    }
532
}
533

534
void DocumentObserverPython::slotFinishSaveDocument(const App::Document& doc, const std::string& file)
535
{
536
    Base::PyGILStateLocker lock;
537
    try {
538
        Py::Tuple args(2);
539
        args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
540
        args.setItem(1, Py::String(file));
541
        Base::pyCall(pyFinishSaveDocument.ptr(),args.ptr());
542
    }
543
    catch (Py::Exception&) {
544
        Base::PyException e; // extract the Python error text
545
        e.ReportException();
546
    }
547
}
548

549
void DocumentObserverPython::slotBeforeAddingDynamicExtension(const App::ExtensionContainer& extcont, std::string extension)
550
{
551
    Base::PyGILStateLocker lock;
552
    try {
553
        Py::Tuple args(2);
554
        args.setItem(0, Py::asObject(const_cast<App::ExtensionContainer&>(extcont).getPyObject()));
555
        args.setItem(1, Py::String(extension));
556
        Base::pyCall(pyBeforeAddingDynamicExtension.ptr(),args.ptr());
557
    }
558
    catch (Py::Exception&) {
559
        Base::PyException e; // extract the Python error text
560
        e.ReportException();
561
    }
562
}
563

564
void DocumentObserverPython::slotAddedDynamicExtension(const App::ExtensionContainer& extcont, std::string extension)
565
{
566
    Base::PyGILStateLocker lock;
567
    try {
568
        Py::Tuple args(2);
569
        args.setItem(0, Py::asObject(const_cast<App::ExtensionContainer&>(extcont).getPyObject()));
570
        args.setItem(1, Py::String(extension));
571
        Base::pyCall(pyAddedDynamicExtension.ptr(),args.ptr());
572
    }
573
    catch (Py::Exception&) {
574
        Base::PyException e; // extract the Python error text
575
        e.ReportException();
576
    }
577
}
578

579

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

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

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

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