00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <assert.h>
00028 # include <string>
00029 # include <boost/signals.hpp>
00030 # include <boost/bind.hpp>
00031 # include <QApplication>
00032 # include <QString>
00033 # include <QStatusBar>
00034 #endif
00035
00037 #include "Application.h"
00038 #include "Document.h"
00039 #include "Selection.h"
00040 #include "SelectionFilter.h"
00041 #include "SelectionObjectPy.h"
00042 #include "View3DInventor.h"
00043 #include <Base/Exception.h>
00044 #include <Base/Console.h>
00045 #include <Base/Interpreter.h>
00046 #include <App/Application.h>
00047 #include <App/Document.h>
00048 #include <App/DocumentObject.h>
00049 #include <App/DocumentObjectPy.h>
00050 #include "MainWindow.h"
00051
00052
00053
00054 using namespace Gui;
00055 using namespace std;
00056
00057 SelectionObserver::SelectionObserver()
00058 {
00059 attachSelection();
00060 }
00061
00062 SelectionObserver::~SelectionObserver()
00063 {
00064 detachSelection();
00065 }
00066
00067 bool SelectionObserver::blockConnection(bool block)
00068 {
00069 bool ok = connectSelection.blocked();
00070 if (block)
00071 connectSelection.block();
00072 else
00073 connectSelection.unblock();
00074 return ok;
00075 }
00076
00077 bool SelectionObserver::isConnectionBlocked() const
00078 {
00079 return connectSelection.blocked();
00080 }
00081
00082 void SelectionObserver::attachSelection()
00083 {
00084 if (!connectSelection.connected()) {
00085 connectSelection = Selection().signalSelectionChanged.connect(boost::bind
00086 (&SelectionObserver::onSelectionChanged, this, _1));
00087 }
00088 }
00089
00090 void SelectionObserver::detachSelection()
00091 {
00092 if (connectSelection.connected()) {
00093 connectSelection.disconnect();
00094 }
00095 }
00096
00097
00098
00099 std::vector<SelectionObserverPython*> SelectionObserverPython::_instances;
00100
00101 SelectionObserverPython::SelectionObserverPython(const Py::Object& obj) : inst(obj)
00102 {
00103 }
00104
00105 SelectionObserverPython::~SelectionObserverPython()
00106 {
00107 }
00108
00109 void SelectionObserverPython::addObserver(const Py::Object& obj)
00110 {
00111 _instances.push_back(new SelectionObserverPython(obj));
00112 }
00113
00114 void SelectionObserverPython::removeObserver(const Py::Object& obj)
00115 {
00116 SelectionObserverPython* obs=0;
00117 for (std::vector<SelectionObserverPython*>::iterator it =
00118 _instances.begin(); it != _instances.end(); ++it) {
00119 if ((*it)->inst == obj) {
00120 obs = *it;
00121 _instances.erase(it);
00122 break;
00123 }
00124 }
00125
00126 delete obs;
00127 }
00128
00129 void SelectionObserverPython::onSelectionChanged(const SelectionChanges& msg)
00130 {
00131 switch (msg.Type)
00132 {
00133 case SelectionChanges::AddSelection:
00134 addSelection(msg);
00135 break;
00136 case SelectionChanges::RmvSelection:
00137 removeSelection(msg);
00138 break;
00139 case SelectionChanges::SetSelection:
00140 setSelection(msg);
00141 break;
00142 case SelectionChanges::ClrSelection:
00143 clearSelection(msg);
00144 break;
00145 case SelectionChanges::SetPreselect:
00146 setPreselection(msg);
00147 break;
00148 case SelectionChanges::RmvPreselect:
00149 removePreselection(msg);
00150 break;
00151 default:
00152 break;
00153 }
00154 }
00155
00156 void SelectionObserverPython::addSelection(const SelectionChanges& msg)
00157 {
00158 Base::PyGILStateLocker lock;
00159 try {
00160 if (this->inst.hasAttr(std::string("addSelection"))) {
00161 Py::Callable method(this->inst.getAttr(std::string("addSelection")));
00162 Py::Tuple args(4);
00163 args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
00164 args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
00165 args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
00166 Py::Tuple tuple(3);
00167 tuple[0] = Py::Float(msg.x);
00168 tuple[1] = Py::Float(msg.y);
00169 tuple[2] = Py::Float(msg.z);
00170 args.setItem(3, tuple);
00171 method.apply(args);
00172 }
00173 }
00174 catch (Py::Exception&) {
00175 Base::PyException e;
00176 Base::Console().Error("%s\n", e.what());
00177 }
00178 }
00179
00180 void SelectionObserverPython::removeSelection(const SelectionChanges& msg)
00181 {
00182 Base::PyGILStateLocker lock;
00183 try {
00184 if (this->inst.hasAttr(std::string("removeSelection"))) {
00185 Py::Callable method(this->inst.getAttr(std::string("removeSelection")));
00186 Py::Tuple args(3);
00187 args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
00188 args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
00189 args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
00190 method.apply(args);
00191 }
00192 }
00193 catch (Py::Exception&) {
00194 Base::PyException e;
00195 Base::Console().Error("%s\n", e.what());
00196 }
00197 }
00198
00199 void SelectionObserverPython::setSelection(const SelectionChanges& msg)
00200 {
00201 Base::PyGILStateLocker lock;
00202 try {
00203 if (this->inst.hasAttr(std::string("setSelection"))) {
00204 Py::Callable method(this->inst.getAttr(std::string("setSelection")));
00205 Py::Tuple args(1);
00206 args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
00207 method.apply(args);
00208 }
00209 }
00210 catch (Py::Exception&) {
00211 Base::PyException e;
00212 Base::Console().Error("%s\n", e.what());
00213 }
00214 }
00215
00216 void SelectionObserverPython::clearSelection(const SelectionChanges& msg)
00217 {
00218 Base::PyGILStateLocker lock;
00219 try {
00220 if (this->inst.hasAttr(std::string("clearSelection"))) {
00221 Py::Callable method(this->inst.getAttr(std::string("clearSelection")));
00222 Py::Tuple args(1);
00223 args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
00224 method.apply(args);
00225 }
00226 }
00227 catch (Py::Exception&) {
00228 Base::PyException e;
00229 Base::Console().Error("%s\n", e.what());
00230 }
00231 }
00232
00233 void SelectionObserverPython::setPreselection(const SelectionChanges& msg)
00234 {
00235 Base::PyGILStateLocker lock;
00236 try {
00237 if (this->inst.hasAttr(std::string("setPreselection"))) {
00238 Py::Callable method(this->inst.getAttr(std::string("setPreselection")));
00239 Py::Tuple args(3);
00240 args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
00241 args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
00242 args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
00243 method.apply(args);
00244 }
00245 }
00246 catch (Py::Exception&) {
00247 Base::PyException e;
00248 Base::Console().Error("%s\n", e.what());
00249 }
00250 }
00251
00252 void SelectionObserverPython::removePreselection(const SelectionChanges& msg)
00253 {
00254 Base::PyGILStateLocker lock;
00255 try {
00256 if (this->inst.hasAttr(std::string("removePreselection"))) {
00257 Py::Callable method(this->inst.getAttr(std::string("removePreselection")));
00258 Py::Tuple args(3);
00259 args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
00260 args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
00261 args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
00262 method.apply(args);
00263 }
00264 }
00265 catch (Py::Exception&) {
00266 Base::PyException e;
00267 Base::Console().Error("%s\n", e.what());
00268 }
00269 }
00270
00271
00272
00273 bool SelectionSingleton::hasSelection() const
00274 {
00275 return !_SelList.empty();
00276 }
00277
00278 std::vector<SelectionSingleton::SelObj> SelectionSingleton::getCompleteSelection() const
00279 {
00280 std::vector<SelObj> temp;
00281 SelObj tempSelObj;
00282
00283 for(std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
00284 tempSelObj.DocName = It->DocName.c_str();
00285 tempSelObj.FeatName = It->FeatName.c_str();
00286 tempSelObj.SubName = It->SubName.c_str();
00287 tempSelObj.TypeName = It->TypeName.c_str();
00288 tempSelObj.pObject = It->pObject;
00289 tempSelObj.pDoc = It->pDoc;
00290 temp.push_back(tempSelObj);
00291 }
00292
00293 return temp;
00294 }
00295
00296 std::vector<SelectionSingleton::SelObj> SelectionSingleton::getSelection(const char* pDocName) const
00297 {
00298 std::vector<SelObj> temp;
00299 SelObj tempSelObj;
00300
00301 App::Document *pcDoc;
00302 pcDoc = getDocument(pDocName);
00303
00304 if (!pcDoc)
00305 return temp;
00306
00307 for(std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
00308 if (It->pDoc == pcDoc) {
00309 tempSelObj.DocName = It->DocName.c_str();
00310 tempSelObj.FeatName = It->FeatName.c_str();
00311 tempSelObj.SubName = It->SubName.c_str();
00312 tempSelObj.TypeName = It->TypeName.c_str();
00313 tempSelObj.pObject = It->pObject;
00314 tempSelObj.pDoc = It->pDoc;
00315 tempSelObj.x = It->x;
00316 tempSelObj.y = It->y;
00317 tempSelObj.z = It->z;
00318 temp.push_back(tempSelObj);
00319 }
00320 }
00321
00322 return temp;
00323 }
00324
00325 bool SelectionSingleton::hasSelection(const char* doc) const
00326 {
00327 App::Document *pcDoc;
00328 pcDoc = getDocument(doc);
00329 if (!pcDoc)
00330 return false;
00331 for(std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
00332 if (It->pDoc == pcDoc) {
00333 return true;
00334 }
00335 }
00336
00337 return false;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 std::vector<SelectionObject> SelectionSingleton::getSelectionEx(const char* pDocName,Base::Type typeId) const
00356 {
00357 std::vector<SelectionObject> temp;
00358
00359 std::map<App::DocumentObject*,SelectionObject> SortMap;
00360
00361
00362 if (typeId == Base::Type::badType())
00363 return temp;
00364
00365 App::Document *pcDoc;
00366 string DocName;
00367
00368 pcDoc = getDocument(pDocName);
00369
00370 if (!pcDoc)
00371 return temp;
00372
00373 for (std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
00374 if (It->pDoc == pcDoc) {
00375
00376 if(It->pObject->getTypeId().isDerivedFrom(typeId)){
00377
00378 if (SortMap.find(It->pObject) != SortMap.end()){
00379
00380 SortMap[It->pObject].SubNames.push_back(It->SubName);
00381 SortMap[It->pObject].SelPoses.push_back(Base::Vector3d(It->x,It->y,It->z));
00382 }
00383 else{
00384
00385 SelectionObject tempSelObj;
00386 tempSelObj.DocName = It->DocName;
00387 tempSelObj.FeatName = It->FeatName;
00388 tempSelObj.SubNames.push_back(It->SubName);
00389 tempSelObj.TypeName = It->TypeName.c_str();
00390 tempSelObj.SelPoses.push_back(Base::Vector3d(It->x,It->y,It->z));
00391 SortMap.insert(std::pair<App::DocumentObject*,SelectionObject>(It->pObject,tempSelObj));
00392 }
00393 }
00394 }
00395 }
00396 for (std::map<App::DocumentObject*,SelectionObject>::const_iterator It = SortMap.begin();It != SortMap.end();++It)
00397 temp.push_back(It->second);
00398
00399 return temp;
00400 }
00401
00402 vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Type& typeId, const char* pDocName) const
00403 {
00404 std::vector<App::DocumentObject*> temp;
00405 App::Document *pcDoc;
00406
00407 pcDoc = getDocument(pDocName);
00408
00409 if (!pcDoc)
00410 return temp;
00411
00412 for (std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
00413 if (It->pDoc == pcDoc && It->pObject && It->pObject->getTypeId().isDerivedFrom(typeId)) {
00414 temp.push_back(It->pObject);
00415 }
00416 }
00417
00418 return temp;
00419 }
00420
00421 std::vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const char* typeName, const char* pDocName) const
00422 {
00423 Base::Type typeId = Base::Type::fromName(typeName);
00424 if (typeId == Base::Type::badType())
00425 return std::vector<App::DocumentObject*>();
00426 return getObjectsOfType(typeId, pDocName);
00427 }
00428
00429 unsigned int SelectionSingleton::countObjectsOfType(const Base::Type& typeId, const char* pDocName) const
00430 {
00431 unsigned int iNbr=0;
00432 App::Document *pcDoc;
00433
00434 pcDoc = getDocument(pDocName);
00435
00436 if (!pcDoc)
00437 return 0;
00438
00439 for (std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
00440 if (It->pDoc == pcDoc && It->pObject && It->pObject->getTypeId().isDerivedFrom(typeId)) {
00441 iNbr++;
00442 }
00443 }
00444
00445 return iNbr;
00446 }
00447
00448 unsigned int SelectionSingleton::countObjectsOfType(const char* typeName, const char* pDocName) const
00449 {
00450 Base::Type typeId = Base::Type::fromName(typeName);
00451 if (typeId == Base::Type::badType())
00452 return 0;
00453 return countObjectsOfType(typeId, pDocName);
00454 }
00455
00456 bool SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectName, const char* pSubName, float x, float y, float z)
00457 {
00458 static char buf[513];
00459
00460 if (DocName != "")
00461 rmvPreselect();
00462
00463 if(ActiveGate)
00464 {
00465 App::Document* pDoc = getDocument(pDocName);
00466
00467 if (pDoc) {
00468 if(pObjectName){
00469 App::DocumentObject* pObject = pDoc->getObject(pObjectName);
00470 if(! ActiveGate->allow(pDoc,pObject,pSubName)){
00471 snprintf(buf,512,"Not allowed: %s.%s.%s ",pDocName
00472 ,pObjectName
00473 ,pSubName
00474 );
00475
00476 if (getMainWindow()){
00477 getMainWindow()->showMessage(QString::fromAscii(buf),3000);
00478 Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
00479 if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
00480 static_cast<View3DInventor*>(mdi)->setCursor(Qt::ForbiddenCursor);
00481 }
00482 }
00483 return false;
00484 }
00485
00486 }else
00487 return ActiveGate->allow(pDoc,0,0);
00488 }else
00489 return false;
00490
00491 }
00492
00493 DocName = pDocName;
00494 FeatName= pObjectName;
00495 SubName = pSubName;
00496 hx = x;
00497 hy = y;
00498 hz = z;
00499
00500
00501 SelectionChanges Chng;
00502 Chng.pDocName = DocName.c_str();
00503 Chng.pObjectName = FeatName.c_str();
00504 Chng.pSubName = SubName.c_str();
00505 Chng.x = x;
00506 Chng.y = y;
00507 Chng.z = z;
00508 Chng.Type = SelectionChanges::SetPreselect;
00509
00510
00511 CurrentPreselection = Chng;
00512
00513 snprintf(buf,512,"Preselected: %s.%s.%s (%f,%f,%f)",Chng.pDocName
00514 ,Chng.pObjectName
00515 ,Chng.pSubName
00516 ,x,y,z);
00517
00518 if (getMainWindow()){
00519 getMainWindow()->showMessage(QString::fromAscii(buf),3000);
00520 Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
00521 if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
00522 static_cast<View3DInventor*>(mdi)->setCursor(Qt::ArrowCursor);
00523 }
00524 }
00525
00526 Notify(Chng);
00527 signalSelectionChanged(Chng);
00528
00529
00530
00531
00532 return true;
00533 }
00534
00535 void SelectionSingleton::setPreselectCoord( float x, float y, float z)
00536 {
00537 static char buf[513];
00538
00539
00540 if(!CurrentPreselection.pObjectName) return;
00541
00542 CurrentPreselection.x = x;
00543 CurrentPreselection.y = y;
00544 CurrentPreselection.z = z;
00545
00546 snprintf(buf,512,"Preselected: %s.%s.%s (%f,%f,%f)",CurrentPreselection.pDocName
00547 ,CurrentPreselection.pObjectName
00548 ,CurrentPreselection.pSubName
00549 ,x,y,z);
00550
00551 if (getMainWindow())
00552 getMainWindow()->showMessage(QString::fromAscii(buf),3000);
00553 }
00554
00555 void SelectionSingleton::rmvPreselect()
00556 {
00557 if (DocName == "")
00558 return;
00559
00560 SelectionChanges Chng;
00561 Chng.pDocName = DocName.c_str();
00562 Chng.pObjectName = FeatName.c_str();
00563 Chng.pSubName = SubName.c_str();
00564 Chng.Type = SelectionChanges::RmvPreselect;
00565
00566
00567 CurrentPreselection.pDocName =0;
00568 CurrentPreselection.pObjectName = 0;
00569 CurrentPreselection.pSubName = 0;
00570 CurrentPreselection.x = 0.0;
00571 CurrentPreselection.y = 0.0;
00572 CurrentPreselection.z = 0.0;
00573
00574
00575 Notify(Chng);
00576 signalSelectionChanged(Chng);
00577
00578 DocName = "";
00579 FeatName= "";
00580 SubName = "";
00581 hx = 0;
00582 hy = 0;
00583 hz = 0;
00584
00585 if (getMainWindow()){
00586 Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
00587 if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
00588 static_cast<View3DInventor*>(mdi)->setCursor(Qt::ArrowCursor);
00589 }
00590 }
00591
00592
00593 }
00594
00595 const SelectionChanges &SelectionSingleton::getPreselection(void) const
00596 {
00597 return CurrentPreselection;
00598 }
00599
00600
00601 void SelectionSingleton::addSelectionGate(Gui::SelectionGate *gate)
00602 {
00603 if(ActiveGate)
00604 rmvSelectionGate();
00605
00606 ActiveGate = gate;
00607
00608 }
00609
00610
00611 void SelectionSingleton::rmvSelectionGate(void)
00612 {
00613 if (ActiveGate)
00614 delete ActiveGate;
00615 ActiveGate=0;
00616 }
00617
00618
00619 App::Document* SelectionSingleton::getDocument(const char* pDocName) const
00620 {
00621 if (pDocName)
00622 return App::GetApplication().getDocument(pDocName);
00623 else
00624 return App::GetApplication().getActiveDocument();
00625 }
00626
00627 bool SelectionSingleton::addSelection(const char* pDocName, const char* pObjectName, const char* pSubName, float x, float y, float z)
00628 {
00629
00630 if (isSelected(pDocName, pObjectName, pSubName))
00631 return true;
00632
00633 _SelObj temp;
00634
00635 temp.pDoc = getDocument(pDocName);
00636
00637 if (temp.pDoc) {
00638 if(pObjectName)
00639 temp.pObject = temp.pDoc->getObject(pObjectName);
00640 else
00641 temp.pObject = 0;
00642
00643
00644 if(ActiveGate)
00645 {
00646 if(! ActiveGate->allow(temp.pDoc,temp.pObject,pSubName)){
00647 if (getMainWindow()){
00648 getMainWindow()->showMessage(QString::fromAscii("Selection not allowed by filter"),5000);
00649 Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
00650 if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
00651 static_cast<View3DInventor*>(mdi)->setCursor(Qt::ForbiddenCursor);
00652 }
00653 }
00654 QApplication::beep();
00655 return false;
00656 }
00657 }
00658
00659 temp.DocName = pDocName;
00660 temp.FeatName = pObjectName ? pObjectName : "";
00661 temp.SubName = pSubName ? pSubName : "";
00662 temp.x = x;
00663 temp.y = y;
00664 temp.z = z;
00665
00666 if (temp.pObject)
00667 temp.TypeName = temp.pObject->getTypeId().getName();
00668
00669 _SelList.push_back(temp);
00670
00671 SelectionChanges Chng;
00672
00673 Chng.pDocName = pDocName;
00674 Chng.pObjectName = pObjectName ? pObjectName : "";
00675 Chng.pSubName = pSubName ? pSubName : "";
00676 Chng.x = x;
00677 Chng.y = y;
00678 Chng.z = z;
00679 Chng.Type = SelectionChanges::AddSelection;
00680
00681
00682 Notify(Chng);
00683 signalSelectionChanged(Chng);
00684
00685 Base::Console().Log("Sel : Add Selection \"%s.%s.%s(%f,%f,%f)\"\n",pDocName,pObjectName,pSubName,x,y,z);
00686
00687
00688 return true;
00689 }
00690 else {
00691
00692
00693 Base::Console().Error("Cannot add to selection: no document '%s' found.\n", pDocName);
00694 return false;
00695 }
00696 }
00697
00698 void SelectionSingleton::rmvSelection(const char* pDocName, const char* pObjectName, const char* pSubName)
00699 {
00700 std::vector<SelectionChanges> rmvList;
00701
00702 for (std::list<_SelObj>::iterator It = _SelList.begin();It != _SelList.end();) {
00703 if ((It->DocName == pDocName && !pObjectName) ||
00704 (It->DocName == pDocName && pObjectName && It->FeatName == pObjectName && !pSubName) ||
00705 (It->DocName == pDocName && pObjectName && It->FeatName == pObjectName && pSubName && It->SubName == pSubName))
00706 {
00707
00708 std::string tmpDocName = It->DocName;
00709 std::string tmpFeaName = It->FeatName;
00710 std::string tmpSubName = It->SubName;
00711
00712
00713 It = _SelList.erase(It);
00714
00715 SelectionChanges Chng;
00716 Chng.pDocName = tmpDocName.c_str();
00717 Chng.pObjectName = tmpFeaName.c_str();
00718 Chng.pSubName = tmpSubName.c_str();
00719 Chng.Type = SelectionChanges::RmvSelection;
00720
00721 Notify(Chng);
00722 signalSelectionChanged(Chng);
00723
00724 rmvList.push_back(Chng);
00725 Base::Console().Log("Sel : Rmv Selection \"%s.%s.%s\"\n",pDocName,pObjectName,pSubName);
00726 }
00727 else {
00728 ++It;
00729 }
00730 }
00731 }
00732
00733 void SelectionSingleton::setSelection(const char* pDocName, const std::vector<App::DocumentObject*>& sel)
00734 {
00735 App::Document *pcDoc;
00736 pcDoc = getDocument(pDocName);
00737 if (!pcDoc)
00738 return;
00739
00740 std::set<App::DocumentObject*> cur_sel, new_sel;
00741 new_sel.insert(sel.begin(), sel.end());
00742
00743
00744 std::list<_SelObj> temp;
00745 for (std::list<_SelObj>::const_iterator it = _SelList.begin(); it != _SelList.end(); ++it) {
00746 if (it->pDoc != pcDoc)
00747 temp.push_back(*it);
00748 else {
00749 cur_sel.insert(it->pObject);
00750 if (new_sel.find(it->pObject) != new_sel.end())
00751 temp.push_back(*it);
00752 }
00753 }
00754
00755
00756 std::vector<App::DocumentObject*> diff_new_cur;
00757 std::back_insert_iterator< std::vector<App::DocumentObject*> > biit(diff_new_cur);
00758 std::set_difference(new_sel.begin(), new_sel.end(), cur_sel.begin(), cur_sel.end(), biit);
00759
00760 _SelObj obj;
00761 for (std::vector<App::DocumentObject*>::const_iterator it = diff_new_cur.begin(); it != diff_new_cur.end(); ++it) {
00762 obj.pDoc = pcDoc;
00763 obj.pObject = *it;
00764 obj.DocName = pDocName;
00765 obj.FeatName = (*it)->getNameInDocument();
00766 obj.SubName = "";
00767 obj.TypeName = (*it)->getTypeId().getName();
00768 obj.x = 0.0f;
00769 obj.y = 0.0f;
00770 obj.z = 0.0f;
00771 temp.push_back(obj);
00772 }
00773
00774 if (cur_sel == new_sel)
00775 return;
00776
00777 _SelList = temp;
00778
00779 SelectionChanges Chng;
00780 Chng.Type = SelectionChanges::SetSelection;
00781 Chng.pDocName = pDocName;
00782 Chng.pObjectName = "";
00783 Chng.pSubName = "";
00784
00785 Notify(Chng);
00786 signalSelectionChanged(Chng);
00787 }
00788
00789 void SelectionSingleton::clearSelection(const char* pDocName)
00790 {
00791 App::Document* pDoc;
00792 pDoc = getDocument(pDocName);
00793
00794
00795 if (!pDoc && !pDocName) {
00796 clearCompleteSelection();
00797 }
00798 else {
00799 std::string docName;
00800 if (pDocName)
00801 docName = pDocName;
00802 else
00803 docName = pDoc->getName();
00804 std::list<_SelObj> selList;
00805 for (std::list<_SelObj>::iterator it = _SelList.begin(); it != _SelList.end(); ++it) {
00806 if (it->DocName != docName)
00807 selList.push_back(*it);
00808 }
00809
00810 _SelList = selList;
00811
00812 SelectionChanges Chng;
00813 Chng.Type = SelectionChanges::ClrSelection;
00814 Chng.pDocName = docName.c_str();
00815 Chng.pObjectName = "";
00816 Chng.pSubName = "";
00817
00818 Notify(Chng);
00819 signalSelectionChanged(Chng);
00820
00821 Base::Console().Log("Sel : Clear selection\n");
00822 }
00823 }
00824
00825 void SelectionSingleton::clearCompleteSelection()
00826 {
00827 _SelList.clear();
00828
00829 SelectionChanges Chng;
00830 Chng.Type = SelectionChanges::ClrSelection;
00831 Chng.pDocName = "";
00832 Chng.pObjectName = "";
00833 Chng.pSubName = "";
00834
00835
00836 Notify(Chng);
00837 signalSelectionChanged(Chng);
00838
00839 Base::Console().Log("Sel : Clear selection\n");
00840 }
00841
00842 bool SelectionSingleton::isSelected(const char* pDocName, const char* pObjectName, const char* pSubName) const
00843 {
00844 const char* tmpDocName = pDocName ? pDocName : "";
00845 const char* tmpFeaName = pObjectName ? pObjectName : "";
00846 const char* tmpSubName = pSubName ? pSubName : "";
00847 for (std::list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It)
00848 if (It->DocName == tmpDocName && It->FeatName == tmpFeaName && It->SubName == tmpSubName)
00849 return true;
00850 return false;
00851 }
00852
00853 bool SelectionSingleton::isSelected(App::DocumentObject* obj, const char* pSubName) const
00854 {
00855 if (!obj) return false;
00856
00857 for(list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
00858 if (It->pObject == obj) {
00859 if (pSubName) {
00860 if (It->SubName == pSubName)
00861 return true;
00862 }
00863 else {
00864 return true;
00865 }
00866 }
00867 }
00868
00869 return false;
00870 }
00871
00872 void SelectionSingleton::slotDeletedObject(const App::DocumentObject& Obj)
00873 {
00874
00875 Selection().rmvSelection( Obj.getDocument()->getName(), Obj.getNameInDocument() );
00876 }
00877
00878 void SelectionSingleton::slotRenamedObject(const App::DocumentObject& Obj)
00879 {
00880
00881 App::Document* pDoc = Obj.getDocument();
00882 for (std::list<_SelObj>::iterator it = _SelList.begin(); it != _SelList.end(); ++it) {
00883 if (it->pDoc == pDoc) {
00884 it->DocName = pDoc->getName();
00885 }
00886 }
00887 }
00888
00889
00890
00891
00892
00897 SelectionSingleton::SelectionSingleton()
00898 {
00899 ActiveGate = 0;
00900 App::GetApplication().signalDeletedObject.connect(boost::bind(&Gui::SelectionSingleton::slotDeletedObject, this, _1));
00901 App::GetApplication().signalRenamedObject.connect(boost::bind(&Gui::SelectionSingleton::slotRenamedObject, this, _1));
00902 CurrentPreselection.pDocName = 0;
00903 CurrentPreselection.pObjectName = 0;
00904 CurrentPreselection.pSubName = 0;
00905
00906 }
00907
00912 SelectionSingleton::~SelectionSingleton()
00913 {
00914 }
00915
00916
00917 SelectionSingleton* SelectionSingleton::_pcSingleton = NULL;
00918
00919 SelectionSingleton& SelectionSingleton::instance(void)
00920 {
00921 if (_pcSingleton == NULL)
00922 _pcSingleton = new SelectionSingleton;
00923 return *_pcSingleton;
00924 }
00925
00926 void SelectionSingleton::destruct (void)
00927 {
00928 if (_pcSingleton != NULL)
00929 delete _pcSingleton;
00930 _pcSingleton = 0;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 PyMethodDef SelectionSingleton::Methods[] = {
00953 {"addSelection", (PyCFunction) SelectionSingleton::sAddSelection, 1,
00954 "addSelection(object) -- Add an object to the selection"},
00955 {"removeSelection", (PyCFunction) SelectionSingleton::sRemoveSelection, 1,
00956 "removeSelection(object) -- Remove an object from the selection"},
00957 {"clearSelection" , (PyCFunction) SelectionSingleton::sClearSelection, 1,
00958 "clearSelection([string]) -- Clear the selection\n"
00959 "Clear the selection to the given document name. If no document is\n"
00960 "given the complete selection is cleared."},
00961 {"isSelected", (PyCFunction) SelectionSingleton::sIsSelected, 1,
00962 "isSelected(object) -- Check if a given object is selected"},
00963 {"getSelection", (PyCFunction) SelectionSingleton::sGetSelection, 1,
00964 "getSelection([string]) -- Return a list of selected objets\n"
00965 "Return a list of selected objects for a given document name. If no\n"
00966 "document is given the complete selection is returned."},
00967 {"getSelectionEx", (PyCFunction) SelectionSingleton::sGetSelectionEx, 1,
00968 "getSelectionEx([string]) -- Return a list of SelectionObjects\n"
00969 "Return a list of SelectionObjects for a given document name. If no\n"
00970 "document is given the selection of the active document is returned.\n"
00971 "The SelectionObjects contain a variety of information about the selection,\n"
00972 "e.g. sub-element names."},
00973 {"addObserver", (PyCFunction) SelectionSingleton::sAddSelObserver, 1,
00974 "addObserver(Object) -- Install an observer\n"},
00975 {"removeObserver", (PyCFunction) SelectionSingleton::sRemSelObserver, 1,
00976 "removeObserver(Object) -- Uninstall an observer\n"},
00977 {"addSelectionGate", (PyCFunction) SelectionSingleton::saddSelectionGate, 1,
00978 "addSelectionGate(String) -- activate the selection gate.\n"
00979 "The selection gate will prohibit all selections which do not match the\n"
00980 "the given selection filter string. Examples strings are:\n"
00981 "'SELECT Part::Feature SUB Edge',\n"
00982 "'SELECT Robot::RobotObject'\n"},
00983 {"removeSelectionGate", (PyCFunction) SelectionSingleton::sremoveSelectionGate, 1,
00984 "removeSelectionGate() -- remove the active slection gate\n"},
00985 {NULL, NULL, 0, NULL}
00986 };
00987
00988 PyObject *SelectionSingleton::sAddSelection(PyObject * , PyObject *args, PyObject * )
00989 {
00990 PyObject *object;
00991 char* subname=0;
00992 float x=0,y=0,z=0;
00993 if (!PyArg_ParseTuple(args, "O!|sfff", &(App::DocumentObjectPy::Type),&object,&subname,&x,&y,&z))
00994 return NULL;
00995
00996 App::DocumentObjectPy* docObjPy = static_cast<App::DocumentObjectPy*>(object);
00997 App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
00998 if (!docObj || !docObj->getNameInDocument()) {
00999 PyErr_SetString(PyExc_Exception, "Cannot check invalid object");
01000 return NULL;
01001 }
01002
01003 Selection().addSelection(docObj->getDocument()->getName(),
01004 docObj->getNameInDocument(),
01005 subname,x,y,z);
01006
01007 Py_Return;
01008 }
01009
01010 PyObject *SelectionSingleton::sRemoveSelection(PyObject * , PyObject *args, PyObject * )
01011 {
01012 PyObject *object;
01013 char* subname=0;
01014 if (!PyArg_ParseTuple(args, "O!|s", &(App::DocumentObjectPy::Type),&object,&subname))
01015 return NULL;
01016
01017 App::DocumentObjectPy* docObjPy = static_cast<App::DocumentObjectPy*>(object);
01018 App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
01019 if (!docObj || !docObj->getNameInDocument()) {
01020 PyErr_SetString(PyExc_Exception, "Cannot check invalid object");
01021 return NULL;
01022 }
01023
01024 Selection().rmvSelection(docObj->getDocument()->getName(),
01025 docObj->getNameInDocument(),
01026 subname);
01027
01028 Py_Return;
01029 }
01030
01031 PyObject *SelectionSingleton::sClearSelection(PyObject * , PyObject *args, PyObject * )
01032 {
01033 char *documentName=0;
01034 if (!PyArg_ParseTuple(args, "|s", &documentName))
01035 return NULL;
01036 documentName ? Selection().clearSelection(documentName) : Selection().clearCompleteSelection();
01037 Py_Return;
01038 }
01039
01040 PyObject *SelectionSingleton::sIsSelected(PyObject * , PyObject *args, PyObject * )
01041 {
01042 PyObject *object;
01043 char* subname=0;
01044 if (!PyArg_ParseTuple(args, "O!|s", &(App::DocumentObjectPy::Type), &object, &subname))
01045 return NULL;
01046
01047 App::DocumentObjectPy* docObj = static_cast<App::DocumentObjectPy*>(object);
01048 bool ok = Selection().isSelected(docObj->getDocumentObjectPtr(), subname);
01049 return Py_BuildValue("O", (ok ? Py_True : Py_False));
01050 }
01051
01052 PyObject *SelectionSingleton::sGetSelection(PyObject * , PyObject *args, PyObject * )
01053 {
01054 char *documentName=0;
01055 if (!PyArg_ParseTuple(args, "|s", &documentName))
01056 return NULL;
01057
01058 std::vector<SelectionSingleton::SelObj> sel;
01059 if (documentName)
01060 sel = Selection().getSelection(documentName);
01061 else
01062 sel = Selection().getCompleteSelection();
01063
01064 try {
01065 Py::List list;
01066 for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
01067 list.append(Py::asObject(it->pObject->getPyObject()));
01068 }
01069 return Py::new_reference_to(list);
01070 }
01071 catch (Py::Exception&) {
01072 return 0;
01073 }
01074 }
01075
01076 PyObject *SelectionSingleton::sGetSelectionEx(PyObject * , PyObject *args, PyObject * )
01077 {
01078 char *documentName=0;
01079 if (!PyArg_ParseTuple(args, "|s", &documentName))
01080 return NULL;
01081
01082 std::vector<SelectionObject> sel;
01083 sel = Selection().getSelectionEx(documentName);
01084
01085 try {
01086 Py::List list;
01087 for (std::vector<SelectionObject>::iterator it = sel.begin(); it != sel.end(); ++it) {
01088 list.append(Py::asObject(it->getPyObject()));
01089 }
01090 return Py::new_reference_to(list);
01091 }
01092 catch (Py::Exception&) {
01093 return 0;
01094 }
01095 }
01096
01097 PyObject *SelectionSingleton::sAddSelObserver(PyObject * , PyObject *args, PyObject * )
01098 {
01099 PyObject* o;
01100 if (!PyArg_ParseTuple(args, "O",&o))
01101 return NULL;
01102 PY_TRY {
01103 SelectionObserverPython::addObserver(Py::Object(o));
01104 Py_Return;
01105 } PY_CATCH;
01106 }
01107
01108 PyObject *SelectionSingleton::sRemSelObserver(PyObject * , PyObject *args, PyObject * )
01109 {
01110 PyObject* o;
01111 if (!PyArg_ParseTuple(args, "O",&o))
01112 return NULL;
01113 PY_TRY {
01114 SelectionObserverPython::removeObserver(Py::Object(o));
01115 Py_Return;
01116 } PY_CATCH;
01117 }
01118
01119 PyObject *SelectionSingleton::saddSelectionGate(PyObject * , PyObject *args, PyObject * )
01120 {
01121 char* filter;
01122 if (!PyArg_ParseTuple(args, "s",&filter))
01123 return NULL;
01124
01125 PY_TRY {
01126 Selection().addSelectionGate(new SelectionFilterGate(filter));
01127 } PY_CATCH;
01128
01129 Py_Return;
01130 }
01131
01132 PyObject *SelectionSingleton::sremoveSelectionGate(PyObject * , PyObject *args, PyObject * )
01133 {
01134 if (!PyArg_ParseTuple(args, ""))
01135 return NULL;
01136
01137 PY_TRY {
01138 Selection().rmvSelectionGate();
01139 } PY_CATCH;
01140
01141 Py_Return;
01142 }