~ubuntu-branches/ubuntu/maverick/freecad/maverick

« back to all changes in this revision

Viewing changes to src/Gui/Selection.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam C. Powell, IV
  • Date: 2010-01-11 08:48:33 UTC
  • mfrom: (3.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20100111084833-4g9vgdqbkw8u34zb
Tags: 0.9.2646.5-1
* New upstream version (closes: #561696).
* Added swig to Build-Depends (closes: #563523, #563772).
* Removed python-opencv from Build-Depends and Recommends (closes: #560768).

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
33
33
/// Here the FreeCAD includes sorted by Base,App,Gui......
34
34
#include "Selection.h"
 
35
#include "SelectionObjectPy.h"
35
36
#include <Base/Exception.h>
36
37
#include <Base/Console.h>
 
38
#include <Base/Interpreter.h>
37
39
#include <App/Application.h>
38
40
#include <App/Document.h>
39
41
#include <App/DocumentObject.h>
43
45
using namespace Gui;
44
46
using namespace std;
45
47
 
 
48
SelectionObserver::SelectionObserver()
 
49
{
 
50
    attachSelection();
 
51
}
 
52
 
 
53
SelectionObserver::~SelectionObserver()
 
54
{
 
55
    detachSelection();
 
56
}
 
57
 
 
58
bool SelectionObserver::blockConnection(bool block)
 
59
{
 
60
    bool ok = connectSelection.blocked();
 
61
    if (block)
 
62
        connectSelection.block();
 
63
    else
 
64
        connectSelection.unblock();
 
65
    return ok;
 
66
}
 
67
 
 
68
bool SelectionObserver::isConnectionBlocked() const
 
69
{
 
70
    return connectSelection.blocked();
 
71
}
 
72
 
 
73
void SelectionObserver::attachSelection()
 
74
{
 
75
    if (!connectSelection.connected()) {
 
76
        connectSelection = Selection().signalSelectionChanged.connect(boost::bind
 
77
            (&SelectionObserver::onSelectionChanged, this, _1));
 
78
    }
 
79
}
 
80
 
 
81
void SelectionObserver::detachSelection()
 
82
{
 
83
    if (connectSelection.connected()) {
 
84
        connectSelection.disconnect();
 
85
    }
 
86
}
 
87
 
 
88
// -------------------------------------------
 
89
 
 
90
std::vector<SelectionObserverPython*> SelectionObserverPython::_instances;
 
91
 
 
92
SelectionObserverPython::SelectionObserverPython(const Py::Object& obj) : inst(obj)
 
93
{
 
94
}
 
95
 
 
96
SelectionObserverPython::~SelectionObserverPython()
 
97
{
 
98
}
 
99
 
 
100
void SelectionObserverPython::addObserver(const Py::Object& obj)
 
101
{
 
102
    _instances.push_back(new SelectionObserverPython(obj));
 
103
}
 
104
 
 
105
void SelectionObserverPython::removeObserver(const Py::Object& obj)
 
106
{
 
107
    SelectionObserverPython* obs=0;
 
108
    for (std::vector<SelectionObserverPython*>::iterator it =
 
109
        _instances.begin(); it != _instances.end(); ++it) {
 
110
        if ((*it)->inst == obj) {
 
111
            obs = *it;
 
112
            _instances.erase(it);
 
113
            break;
 
114
        }
 
115
    }
 
116
 
 
117
    delete obs;
 
118
}
 
119
 
 
120
void SelectionObserverPython::onSelectionChanged(const SelectionChanges& msg)
 
121
{
 
122
    switch (msg.Type)
 
123
    {
 
124
    case SelectionChanges::AddSelection:
 
125
        addSelection(msg);
 
126
        break;
 
127
    case SelectionChanges::RmvSelection:
 
128
        removeSelection(msg);
 
129
        break;
 
130
    case SelectionChanges::SetSelection:
 
131
        setSelection(msg);
 
132
        break;
 
133
    case SelectionChanges::ClrSelection:
 
134
        clearSelection(msg);
 
135
        break;
 
136
    case SelectionChanges::SetPreselect:
 
137
        setPreselection(msg);
 
138
        break;
 
139
    case SelectionChanges::RmvPreselect:
 
140
        removePreselection(msg);
 
141
        break;
 
142
    default:
 
143
        break;
 
144
    }
 
145
}
 
146
 
 
147
void SelectionObserverPython::addSelection(const SelectionChanges& msg)
 
148
{
 
149
    Base::PyGILStateLocker lock;
 
150
    try {
 
151
        if (this->inst.hasAttr(std::string("addSelection"))) {
 
152
            Py::Callable method(this->inst.getAttr(std::string("addSelection")));
 
153
            Py::Tuple args(4);
 
154
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
 
155
            args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
 
156
            args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
 
157
            Py::Tuple tuple(3);
 
158
            tuple[0] = Py::Float(msg.x);
 
159
            tuple[1] = Py::Float(msg.y);
 
160
            tuple[2] = Py::Float(msg.z);
 
161
            args.setItem(3, tuple);
 
162
            method.apply(args);
 
163
        }
 
164
    }
 
165
    catch (Py::Exception&) {
 
166
        Base::PyException e; // extract the Python error text
 
167
        Base::Console().Error("%s\n", e.what());
 
168
    }
 
169
}
 
170
 
 
171
void SelectionObserverPython::removeSelection(const SelectionChanges& msg)
 
172
{
 
173
    Base::PyGILStateLocker lock;
 
174
    try {
 
175
        if (this->inst.hasAttr(std::string("removeSelection"))) {
 
176
            Py::Callable method(this->inst.getAttr(std::string("removeSelection")));
 
177
            Py::Tuple args(3);
 
178
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
 
179
            args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
 
180
            args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
 
181
            method.apply(args);
 
182
        }
 
183
    }
 
184
    catch (Py::Exception&) {
 
185
        Base::PyException e; // extract the Python error text
 
186
        Base::Console().Error("%s\n", e.what());
 
187
    }
 
188
}
 
189
 
 
190
void SelectionObserverPython::setSelection(const SelectionChanges& msg)
 
191
{
 
192
    Base::PyGILStateLocker lock;
 
193
    try {
 
194
        if (this->inst.hasAttr(std::string("setSelection"))) {
 
195
            Py::Callable method(this->inst.getAttr(std::string("setSelection")));
 
196
            Py::Tuple args(1);
 
197
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
 
198
            method.apply(args);
 
199
        }
 
200
    }
 
201
    catch (Py::Exception&) {
 
202
        Base::PyException e; // extract the Python error text
 
203
        Base::Console().Error("%s\n", e.what());
 
204
    }
 
205
}
 
206
 
 
207
void SelectionObserverPython::clearSelection(const SelectionChanges& msg)
 
208
{
 
209
    Base::PyGILStateLocker lock;
 
210
    try {
 
211
        if (this->inst.hasAttr(std::string("clearSelection"))) {
 
212
            Py::Callable method(this->inst.getAttr(std::string("clearSelection")));
 
213
            Py::Tuple args(1);
 
214
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
 
215
            method.apply(args);
 
216
        }
 
217
    }
 
218
    catch (Py::Exception&) {
 
219
        Base::PyException e; // extract the Python error text
 
220
        Base::Console().Error("%s\n", e.what());
 
221
    }
 
222
}
 
223
 
 
224
void SelectionObserverPython::setPreselection(const SelectionChanges& msg)
 
225
{
 
226
    Base::PyGILStateLocker lock;
 
227
    try {
 
228
        if (this->inst.hasAttr(std::string("setPreselection"))) {
 
229
            Py::Callable method(this->inst.getAttr(std::string("setPreselection")));
 
230
            Py::Tuple args(3);
 
231
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
 
232
            args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
 
233
            args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
 
234
            method.apply(args);
 
235
        }
 
236
    }
 
237
    catch (Py::Exception&) {
 
238
        Base::PyException e; // extract the Python error text
 
239
        Base::Console().Error("%s\n", e.what());
 
240
    }
 
241
}
 
242
 
 
243
void SelectionObserverPython::removePreselection(const SelectionChanges& msg)
 
244
{
 
245
    Base::PyGILStateLocker lock;
 
246
    try {
 
247
        if (this->inst.hasAttr(std::string("removePreselection"))) {
 
248
            Py::Callable method(this->inst.getAttr(std::string("removePreselection")));
 
249
            Py::Tuple args(3);
 
250
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
 
251
            args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
 
252
            args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
 
253
            method.apply(args);
 
254
        }
 
255
    }
 
256
    catch (Py::Exception&) {
 
257
        Base::PyException e; // extract the Python error text
 
258
        Base::Console().Error("%s\n", e.what());
 
259
    }
 
260
}
 
261
 
 
262
// -------------------------------------------
 
263
 
46
264
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getCompleteSelection() const
47
265
{
48
266
    std::vector<SelObj> temp;
49
267
    SelObj tempSelObj;
50
268
 
51
 
    for( list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
 
269
    for(std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
52
270
        tempSelObj.DocName  = It->DocName.c_str();
53
271
        tempSelObj.FeatName = It->FeatName.c_str();
54
272
        tempSelObj.SubName  = It->SubName.c_str();
71
289
 
72
290
    pcDoc = getDocument(pDocName);
73
291
 
74
 
    //FIXME: We should abandon all the 'active' document stuff because this make quite a lot of troubles.
75
 
    //Thus it should only be able to access (an existing) document stuff by its name. For Python there might
76
 
    //be an active document but not for internal stuff. (Werner 20060517)
77
 
    if(!pcDoc)
 
292
    if (!pcDoc)
78
293
        return temp;
79
294
 
80
295
    for(std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
83
298
            tempSelObj.FeatName = It->FeatName.c_str();
84
299
            tempSelObj.SubName  = It->SubName.c_str();
85
300
            tempSelObj.TypeName = It->TypeName.c_str();
86
 
            tempSelObj.pObject    = It->pObject;
 
301
            tempSelObj.pObject  = It->pObject;
87
302
            tempSelObj.pDoc     = It->pDoc;
 
303
            tempSelObj.x        = It->x;
 
304
            tempSelObj.y        = It->y;
 
305
            tempSelObj.z        = It->z;
88
306
            temp.push_back(tempSelObj);
89
307
        }
90
308
    }
92
310
    return temp;
93
311
}
94
312
 
 
313
std::vector<SelectionObject> SelectionSingleton::getSelectionEx(const char* pDocName) const
 
314
{
 
315
    std::vector<SelectionObject> temp;
 
316
    
 
317
    std::map<App::DocumentObject*,SelectionObject> SortMap;
 
318
 
 
319
    App::Document *pcDoc;
 
320
    string DocName;
 
321
 
 
322
    pcDoc = getDocument(pDocName);
 
323
 
 
324
    if (!pcDoc)
 
325
        return temp;
 
326
 
 
327
    for (std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
 
328
        if (It->pDoc == pcDoc) {
 
329
            // if the object has already an entry
 
330
            if (SortMap.find(It->pObject) != SortMap.end()){
 
331
                // only add sub-element
 
332
                SortMap[It->pObject].SubNames.push_back(It->SubName);
 
333
                SortMap[It->pObject].SelPoses.push_back(Base::Vector3d(It->x,It->y,It->z));
 
334
            }
 
335
            else{
 
336
                // create a new entry
 
337
                SelectionObject tempSelObj;
 
338
                tempSelObj.DocName  = It->DocName;
 
339
                tempSelObj.FeatName = It->FeatName;
 
340
                tempSelObj.SubNames.push_back(It->SubName);
 
341
                tempSelObj.TypeName = It->TypeName.c_str();
 
342
                tempSelObj.SelPoses.push_back(Base::Vector3d(It->x,It->y,It->z));
 
343
                SortMap.insert(std::pair<App::DocumentObject*,SelectionObject>(It->pObject,tempSelObj));
 
344
            }
 
345
        }
 
346
    }
 
347
    for (std::map<App::DocumentObject*,SelectionObject>::const_iterator It = SortMap.begin();It != SortMap.end();++It) 
 
348
        temp.push_back(It->second);
 
349
 
 
350
    return temp;
 
351
}
 
352
 
95
353
vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Type& typeId, const char* pDocName) const
96
354
{
97
355
    std::vector<App::DocumentObject*> temp;
99
357
 
100
358
    pcDoc = getDocument(pDocName);
101
359
 
102
 
    //FIXME: We should abandon all the 'active' document stuff because this make quite a lot of troubles.
103
 
    //Thus it should only be able to access (an existing) document stuff by its name. For Python there might
104
 
    //be an active document but not for internal stuff. (Werner 20060517)
105
360
    if (!pcDoc)
106
361
        return temp;
107
362
 
129
384
 
130
385
    pcDoc = getDocument(pDocName);
131
386
 
132
 
    //FIXME: We should abandon all the 'active' document stuff because this make quite a lot of troubles.
133
 
    //Thus it should only be able to access (an existing) document stuff by its name. For Python there might
134
 
    //be an active document but not for internal stuff. (Werner 20060517)
135
387
    if (!pcDoc)
136
388
        return 0;
137
389
 
176
428
 
177
429
 
178
430
    Notify(Chng);
 
431
    signalSelectionChanged(Chng);
179
432
 
180
433
    //Base::Console().Log("Sel : Add preselect %s \n",pObjectName);
181
434
 
195
448
    Chng.Type = SelectionChanges::RmvPreselect;
196
449
 
197
450
    Notify(Chng);
 
451
    signalSelectionChanged(Chng);
198
452
 
199
453
    DocName = "";
200
454
    FeatName= "";
254
508
 
255
509
 
256
510
        Notify(Chng);
 
511
        signalSelectionChanged(Chng);
257
512
 
258
513
        Base::Console().Log("Sel : Add Selection \"%s.%s.%s(%f,%f,%f)\"\n",pDocName,pObjectName,pSubName,x,y,z);
259
514
 
292
547
            Chng.Type      = SelectionChanges::RmvSelection;
293
548
 
294
549
            Notify(Chng);
 
550
            signalSelectionChanged(Chng);
295
551
      
296
552
            rmvList.push_back(Chng);
297
553
            Base::Console().Log("Sel : Rmv Selection \"%s.%s.%s\"\n",pDocName,pObjectName,pSubName);
302
558
    }
303
559
}
304
560
 
 
561
void SelectionSingleton::setSelection(const char* pDocName, const std::vector<App::DocumentObject*>& sel)
 
562
{
 
563
    App::Document *pcDoc;
 
564
    pcDoc = getDocument(pDocName);
 
565
    if (!pcDoc)
 
566
        return;
 
567
 
 
568
    std::list<_SelObj> temp;
 
569
    std::vector<App::DocumentObject*> prev_sel;
 
570
    for (std::list<_SelObj>::const_iterator it = _SelList.begin(); it != _SelList.end(); ++it) {
 
571
        if (it->pDoc != pcDoc)
 
572
            temp.push_back(*it);
 
573
        else
 
574
            prev_sel.push_back(it->pObject);
 
575
    }
 
576
 
 
577
    _SelObj obj;
 
578
    for (std::vector<App::DocumentObject*>::const_iterator it = sel.begin(); it != sel.end(); ++it) {
 
579
        obj.pDoc = pcDoc;
 
580
        obj.pObject = *it;
 
581
        obj.DocName = pDocName;
 
582
        obj.FeatName = (*it)->getNameInDocument();
 
583
        obj.SubName = "";
 
584
        obj.TypeName = (*it)->getTypeId().getName();
 
585
        obj.x = 0.0f;
 
586
        obj.y = 0.0f;
 
587
        obj.z = 0.0f;
 
588
        temp.push_back(obj);
 
589
    }
 
590
 
 
591
    std::vector<App::DocumentObject*> curr_sel = sel;
 
592
    std::sort(curr_sel.begin(), curr_sel.end());
 
593
    std::sort(prev_sel.begin(), prev_sel.end());
 
594
    if (curr_sel == prev_sel) // nothing has changed
 
595
        return;
 
596
 
 
597
    _SelList = temp;
 
598
 
 
599
    SelectionChanges Chng;
 
600
    Chng.Type = SelectionChanges::SetSelection;
 
601
    Chng.pDocName = pDocName;
 
602
    Chng.pObjectName = "";
 
603
    Chng.pSubName = "";
 
604
 
 
605
    Notify(Chng);
 
606
    signalSelectionChanged(Chng);
 
607
}
 
608
 
305
609
void SelectionSingleton::clearSelection(const char* pDocName)
306
610
{
307
611
    App::Document* pDoc;
328
632
        SelectionChanges Chng;
329
633
        Chng.Type = SelectionChanges::ClrSelection;
330
634
        Chng.pDocName = docName.c_str();
 
635
        Chng.pObjectName = "";
 
636
        Chng.pSubName = "";
331
637
 
332
638
        Notify(Chng);
 
639
        signalSelectionChanged(Chng);
333
640
 
334
641
        Base::Console().Log("Sel : Clear selection\n");
335
642
    }
342
649
    SelectionChanges Chng;
343
650
    Chng.Type = SelectionChanges::ClrSelection;
344
651
    Chng.pDocName = "";
 
652
    Chng.pObjectName = "";
 
653
    Chng.pSubName = "";
345
654
 
346
655
 
347
656
    Notify(Chng);
 
657
    signalSelectionChanged(Chng);
348
658
 
349
659
    Base::Console().Log("Sel : Clear selection\n");
350
660
}
371
681
 
372
682
    return false;
373
683
}
374
 
void SelectionSingleton::slotDeletedObject(App::DocumentObject& Obj)
 
684
 
 
685
void SelectionSingleton::slotDeletedObject(const App::DocumentObject& Obj)
375
686
{
376
687
    // remove also from the selection, if selected
377
688
    Selection().rmvSelection( Obj.getDocument()->getName(), Obj.getNameInDocument() );
378
689
}
379
690
 
380
 
void SelectionSingleton::slotRenamedObject(App::DocumentObject& Obj)
 
691
void SelectionSingleton::slotRenamedObject(const App::DocumentObject& Obj)
381
692
{
382
693
    // compare internals with the document and change them if needed
383
694
    App::Document* pDoc = Obj.getDocument();
461
772
     "getSelection([string]) -- Return a list of selected objets\n"
462
773
     "Return a list of selected objects for a given document name. If no\n"
463
774
     "document is given the complete selection is returned."},
 
775
    {"getSelectionEx",         (PyCFunction) SelectionSingleton::sGetSelectionEx, 1,
 
776
     "getSelectionEx([string]) -- Return a list of SelectionObjects\n"
 
777
     "Return a list of SelectionObjects for a given document name. If no\n"
 
778
     "document is given the selection of the active document is returned.\n"
 
779
     "The SelectionObjects contain a variety of information about the selection,\n"
 
780
     "e.g. sub-element names."},
 
781
    {"addObserver",         (PyCFunction) SelectionSingleton::sAddSelObserver, 1,
 
782
     "addObserver(Object) -- Install an observer\n"},
 
783
    {"removeObserver",      (PyCFunction) SelectionSingleton::sRemSelObserver, 1,
 
784
     "removeObserver(Object) -- Uninstall an observer\n"},
464
785
    {NULL, NULL, 0, NULL}               /* Sentinel */
465
786
};
466
787
 
543
864
        return 0;
544
865
    }
545
866
}
 
867
 
 
868
PyObject *SelectionSingleton::sGetSelectionEx(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
 
869
{
 
870
    char *documentName=0;
 
871
    if (!PyArg_ParseTuple(args, "|s", &documentName))     // convert args: Python->C 
 
872
        return NULL;                             // NULL triggers exception
 
873
 
 
874
    std::vector<SelectionObject> sel;
 
875
    sel = Selection().getSelectionEx(documentName);
 
876
 
 
877
    try {
 
878
        Py::List list;
 
879
        for (std::vector<SelectionObject>::iterator it = sel.begin(); it != sel.end(); ++it) {
 
880
            list.append(Py::Object(new SelectionObjectPy(new SelectionObject(*it)), true));
 
881
        }
 
882
        return Py::new_reference_to(list);
 
883
    }
 
884
    catch (Py::Exception&) {
 
885
        return 0;
 
886
    }
 
887
}
 
888
 
 
889
PyObject *SelectionSingleton::sAddSelObserver(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
 
890
{
 
891
    PyObject* o;
 
892
    if (!PyArg_ParseTuple(args, "O",&o))
 
893
        return NULL;
 
894
    PY_TRY {
 
895
        SelectionObserverPython::addObserver(Py::Object(o));
 
896
        Py_Return;
 
897
    } PY_CATCH;
 
898
}
 
899
 
 
900
PyObject *SelectionSingleton::sRemSelObserver(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
 
901
{
 
902
    PyObject* o;
 
903
    if (!PyArg_ParseTuple(args, "O",&o))
 
904
        return NULL;
 
905
    PY_TRY {
 
906
        SelectionObserverPython::removeObserver(Py::Object(o));
 
907
        Py_Return;
 
908
    } PY_CATCH;
 
909
}