1
/***************************************************************************
2
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
3
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
5
* This file is part of the FreeCAD CAx development system. *
7
* This library is free software; you can redistribute it and/or *
8
* modify it under the terms of the GNU Library General Public *
9
* License as published by the Free Software Foundation; either *
10
* version 2 of the License, or (at your option) any later version. *
12
* This library is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU Library General Public License for more details. *
17
* You should have received a copy of the GNU Library General Public *
18
* License along with this library; see the file COPYING.LIB. If not, *
19
* write to the Free Software Foundation, Inc., 59 Temple Place, *
20
* Suite 330, Boston, MA 02111-1307, USA *
22
***************************************************************************/
24
#include "PreCompiled.h"
28
# include <boost/algorithm/string/predicate.hpp>
29
# include <QApplication>
32
#include <App/Application.h>
33
#include <App/Document.h>
34
#include <App/DocumentObject.h>
35
#include <App/DocumentObjectPy.h>
36
#include <App/GeoFeature.h>
37
#include <Base/Console.h>
38
#include <Base/Exception.h>
39
#include <Base/Interpreter.h>
40
#include <Base/Tools.h>
41
#include <Base/PyWrapParseTupleAndKeywords.h>
42
#include <Base/UnitsApi.h>
45
#include "SelectionObject.h"
46
#include "Application.h"
49
#include "MainWindow.h"
51
#include "SelectionFilter.h"
52
#include "SelectionFilterPy.h"
53
#include "SelectionObserverPython.h"
55
#include "ViewProviderDocumentObject.h"
58
FC_LOG_LEVEL_INIT("Selection",false,true,true)
62
namespace sp = std::placeholders;
64
SelectionGateFilterExternal::SelectionGateFilterExternal(const char *docName, const char *objName) {
72
bool SelectionGateFilterExternal::allow(App::Document *doc ,App::DocumentObject *obj, const char*) {
75
if(!DocName.empty() && doc->getName()!=DocName)
76
notAllowedReason = "Cannot select external object";
77
else if(!ObjName.empty() && ObjName==obj->getNameInDocument())
78
notAllowedReason = "Cannot select self";
84
//////////////////////////////////////////////////////////////////////////////////////////
86
SelectionObserver::SelectionObserver(bool attach, ResolveMode resolve)
88
, blockedSelection(false)
94
SelectionObserver::SelectionObserver(const ViewProviderDocumentObject *vp, bool attach, ResolveMode resolve)
96
, blockedSelection(false)
98
if (vp && vp->getObject() && vp->getObject()->getDocument()) {
99
filterDocName = vp->getObject()->getDocument()->getName();
100
filterObjName = vp->getObject()->getNameInDocument();
107
SelectionObserver::~SelectionObserver()
112
bool SelectionObserver::blockSelection(bool block)
114
bool ok = blockedSelection;
115
blockedSelection = block;
119
bool SelectionObserver::isSelectionBlocked() const
121
return blockedSelection;
124
bool SelectionObserver::isSelectionAttached() const
126
return connectSelection.connected();
129
void SelectionObserver::attachSelection()
131
if (!connectSelection.connected()) {
132
bool newStyle = (resolve >= ResolveMode::NewStyleElement);
133
bool oldStyle = (resolve == ResolveMode::OldStyleElement);
134
auto &signal = newStyle ? Selection().signalSelectionChanged3 :
135
oldStyle ? Selection().signalSelectionChanged2 :
136
Selection().signalSelectionChanged ;
138
connectSelection = signal.connect(std::bind
139
(&SelectionObserver::_onSelectionChanged, this, sp::_1));
142
if (!filterDocName.empty()) {
143
Selection().addSelectionGate(
144
new SelectionGateFilterExternal(filterDocName.c_str(),filterObjName.c_str()));
149
void SelectionObserver::_onSelectionChanged(const SelectionChanges& msg) {
151
if (blockedSelection)
153
onSelectionChanged(msg);
154
} catch (Base::Exception &e) {
156
FC_ERR("Unhandled Base::Exception caught in selection observer: ");
157
} catch (std::exception &e) {
158
FC_ERR("Unhandled std::exception caught in selection observer: " << e.what());
160
FC_ERR("Unhandled unknown exception caught in selection observer");
164
void SelectionObserver::detachSelection()
166
if (connectSelection.connected()) {
167
connectSelection.disconnect();
168
if (!filterDocName.empty())
169
Selection().rmvSelectionGate();
173
// -------------------------------------------
175
bool SelectionSingleton::hasSelection() const
177
return !_SelList.empty();
180
bool SelectionSingleton::hasPreselection() const {
181
return !CurrentPreselection.Object.getObjectName().empty();
184
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getCompleteSelection(ResolveMode resolve) const
186
return getSelection("*", resolve);
189
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getSelection(const char* pDocName, ResolveMode resolve, bool single) const
191
std::vector<SelObj> temp;
196
App::Document *pcDoc = nullptr;
197
if(!pDocName || strcmp(pDocName,"*") != 0) {
198
pcDoc = getDocument(pDocName);
203
std::map<App::DocumentObject*,std::set<std::string> > objMap;
205
for(auto &sel : _SelList) {
208
const char *subelement = nullptr;
209
auto obj = getObjectOfType(sel, App::DocumentObject::getClassTypeId(), resolve, &subelement);
210
if (!obj || (pcDoc && sel.pObject->getDocument() != pcDoc))
213
// In case we are resolving objects, make sure no duplicates
214
if (resolve != ResolveMode::NoResolve && !objMap[obj].insert(std::string(subelement ? subelement : "")).second)
217
if (single && !temp.empty()) {
222
tempSelObj.DocName = obj->getDocument()->getName();
223
tempSelObj.FeatName = obj->getNameInDocument();
224
tempSelObj.SubName = subelement;
225
tempSelObj.TypeName = obj->getTypeId().getName();
226
tempSelObj.pObject = obj;
227
tempSelObj.pResolvedObject = sel.pResolvedObject;
228
tempSelObj.pDoc = obj->getDocument();
229
tempSelObj.x = sel.x;
230
tempSelObj.y = sel.y;
231
tempSelObj.z = sel.z;
233
temp.push_back(tempSelObj);
239
bool SelectionSingleton::hasSelection(const char* doc, ResolveMode resolve) const
241
App::Document *pcDoc = nullptr;
242
if (!doc || strcmp(doc,"*") != 0) {
243
pcDoc = getDocument(doc);
247
for(auto &sel : _SelList) {
250
auto obj = getObjectOfType(sel, App::DocumentObject::getClassTypeId(), resolve);
251
if (obj && (!pcDoc || sel.pObject->getDocument()==pcDoc)) {
259
bool SelectionSingleton::hasSubSelection(const char* doc, bool subElement) const
261
App::Document *pcDoc = nullptr;
262
if(!doc || strcmp(doc,"*")!=0) {
263
pcDoc = getDocument(doc);
267
for(auto &sel : _SelList) {
268
if(pcDoc && pcDoc != sel.pDoc)
270
if(sel.SubName.empty())
272
if(subElement && sel.SubName.back()!='.')
274
if(sel.pObject != sel.pResolvedObject)
281
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getPickedList(const char* pDocName) const
283
std::vector<SelObj> temp;
286
App::Document *pcDoc = nullptr;
287
if(!pDocName || strcmp(pDocName,"*") != 0) {
288
pcDoc = getDocument(pDocName);
293
for(std::list<_SelObj>::const_iterator It = _PickedList.begin();It != _PickedList.end();++It) {
294
if (!pcDoc || It->pDoc == pcDoc) {
295
tempSelObj.DocName = It->DocName.c_str();
296
tempSelObj.FeatName = It->FeatName.c_str();
297
tempSelObj.SubName = It->SubName.c_str();
298
tempSelObj.TypeName = It->TypeName.c_str();
299
tempSelObj.pObject = It->pObject;
300
tempSelObj.pResolvedObject = It->pResolvedObject;
301
tempSelObj.pDoc = It->pDoc;
302
tempSelObj.x = It->x;
303
tempSelObj.y = It->y;
304
tempSelObj.z = It->z;
305
temp.push_back(tempSelObj);
312
std::vector<SelectionObject> SelectionSingleton::getSelectionEx(const char* pDocName, Base::Type typeId,
313
ResolveMode resolve, bool single) const
315
return getObjectList(pDocName, typeId, _SelList, resolve, single);
318
std::vector<SelectionObject> SelectionSingleton::getPickedListEx(const char* pDocName, Base::Type typeId) const
320
return getObjectList(pDocName, typeId, _PickedList, ResolveMode::NoResolve);
323
std::vector<SelectionObject> SelectionSingleton::getObjectList(const char* pDocName, Base::Type typeId,
324
std::list<_SelObj> &objList,
325
ResolveMode resolve, bool single) const
327
std::vector<SelectionObject> temp;
330
std::map<App::DocumentObject*,size_t> SortMap;
333
if (typeId == Base::Type::badType())
336
App::Document *pcDoc = nullptr;
337
if (!pDocName || strcmp(pDocName,"*") != 0) {
338
pcDoc = getDocument(pDocName);
343
for (auto &sel : objList) {
346
const char *subelement = nullptr;
347
auto obj = getObjectOfType(sel,typeId,resolve,&subelement);
348
if (!obj || (pcDoc && sel.pObject->getDocument() != pcDoc))
350
auto it = SortMap.find(obj);
351
if(it!=SortMap.end()) {
352
// only add sub-element
353
if (subelement && *subelement) {
354
if (resolve != ResolveMode::NoResolve && !temp[it->second]._SubNameSet.insert(subelement).second)
356
temp[it->second].SubNames.emplace_back(subelement);
357
temp[it->second].SelPoses.emplace_back(sel.x,sel.y,sel.z);
361
if (single && !temp.empty()) {
365
// create a new entry
366
temp.emplace_back(obj);
367
if (subelement && *subelement) {
368
temp.back().SubNames.emplace_back(subelement);
369
temp.back().SelPoses.emplace_back(sel.x,sel.y,sel.z);
370
if (resolve != ResolveMode::NoResolve)
371
temp.back()._SubNameSet.insert(subelement);
373
SortMap.insert(std::make_pair(obj,temp.size()-1));
380
bool SelectionSingleton::needPickedList() const
382
return _needPickedList;
385
void SelectionSingleton::enablePickedList(bool enable)
387
if(enable != _needPickedList) {
388
_needPickedList = enable;
390
notify(SelectionChanges(SelectionChanges::PickedListChanged));
394
void SelectionSingleton::notify(SelectionChanges &&Chng)
397
NotificationQueue.push_back(std::move(Chng));
400
Base::FlagToggler<bool> flag(Notifying);
401
NotificationQueue.push_back(std::move(Chng));
402
while(!NotificationQueue.empty()) {
403
const auto &msg = NotificationQueue.front();
406
case SelectionChanges::AddSelection:
407
notify = isSelected(msg.pDocName, msg.pObjectName, msg.pSubName, ResolveMode::NoResolve);
409
case SelectionChanges::RmvSelection:
410
notify = !isSelected(msg.pDocName, msg.pObjectName, msg.pSubName, ResolveMode::NoResolve);
412
case SelectionChanges::SetPreselect:
413
notify = CurrentPreselection.Type==SelectionChanges::SetPreselect
414
&& CurrentPreselection.Object == msg.Object;
416
case SelectionChanges::RmvPreselect:
417
notify = CurrentPreselection.Type==SelectionChanges::ClrSelection;
425
signalSelectionChanged(msg);
427
catch (const boost::exception&) {
428
// reported by code analyzers
429
Base::Console().Warning("notify: Unexpected boost exception\n");
432
NotificationQueue.pop_front();
436
bool SelectionSingleton::hasPickedList() const
438
return !_PickedList.empty();
441
int SelectionSingleton::getAsPropertyLinkSubList(App::PropertyLinkSubList &prop) const
443
std::vector<Gui::SelectionObject> sel = this->getSelectionEx();
444
std::vector<App::DocumentObject*> objs; objs.reserve(sel.size() * 2);
445
std::vector<std::string> subs; subs.reserve(sel.size()*2);
446
for (auto & selitem : sel) {
447
App::DocumentObject* obj = selitem.getObject();
448
const std::vector<std::string> &subnames = selitem.getSubNames();
450
//whole object is selected
451
if (subnames.empty()){
456
for (const auto & subname : subnames) {
458
subs.push_back(subname);
462
assert(objs.size()==subs.size());
463
prop.setValues(objs, subs);
467
App::DocumentObject *SelectionSingleton::getObjectOfType(_SelObj &sel, Base::Type typeId,
468
ResolveMode resolve, const char **subelement)
470
auto obj = sel.pObject;
471
if(!obj || !obj->isAttachedToDocument())
473
const char *subname = sel.SubName.c_str();
474
if (resolve != ResolveMode::NoResolve) {
475
obj = sel.pResolvedObject;
476
if (resolve == ResolveMode::NewStyleElement && !sel.elementName.newName.empty())
477
subname = sel.elementName.newName.c_str();
479
subname = sel.elementName.oldName.c_str();
485
if (!obj->isDerivedFrom(typeId) && (resolve != ResolveMode::FollowLink || !obj->getLinkedObject(true)->isDerivedFrom(typeId)))
489
*subelement = subname;
494
vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Type& typeId, const char* pDocName, ResolveMode resolve) const
496
std::vector<App::DocumentObject*> temp;
498
App::Document *pcDoc = nullptr;
499
if (!pDocName || strcmp(pDocName,"*") != 0) {
500
pcDoc = getDocument(pDocName);
505
std::set<App::DocumentObject*> objs;
506
for(auto &sel : _SelList) {
507
if(pcDoc && pcDoc!=sel.pDoc) continue;
508
App::DocumentObject *pObject = getObjectOfType(sel, typeId, resolve);
510
auto ret = objs.insert(pObject);
512
temp.push_back(pObject);
519
std::vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const char* typeName, const char* pDocName, ResolveMode resolve) const
521
Base::Type typeId = Base::Type::fromName(typeName);
522
if (typeId == Base::Type::badType())
524
return getObjectsOfType(typeId, pDocName, resolve);
527
unsigned int SelectionSingleton::countObjectsOfType(const Base::Type& typeId, const char* pDocName, ResolveMode resolve) const
530
App::Document *pcDoc = nullptr;
531
if(!pDocName || strcmp(pDocName,"*") != 0) {
532
pcDoc = getDocument(pDocName);
537
for (auto &sel : _SelList) {
538
if((!pcDoc||pcDoc==sel.pDoc) && getObjectOfType(sel, typeId, resolve))
545
unsigned int SelectionSingleton::countObjectsOfType(const char* typeName, const char* pDocName, ResolveMode resolve) const
547
Base::Type typeId = Base::Type::fromName(typeName);
548
if (typeId == Base::Type::badType())
550
return countObjectsOfType(typeId, pDocName, resolve);
554
void SelectionSingleton::slotSelectionChanged(const SelectionChanges& msg)
556
if(msg.Type == SelectionChanges::SetPreselectSignal ||
557
msg.Type == SelectionChanges::ShowSelection ||
558
msg.Type == SelectionChanges::HideSelection)
561
if(!msg.Object.getSubName().empty()) {
562
auto pParent = msg.Object.getObject();
565
App::ElementNamePair elementName;
566
auto &newElementName = elementName.newName;
567
auto &oldElementName = elementName.oldName;
568
auto pObject = App::GeoFeature::resolveElement(pParent,msg.pSubName,elementName);
571
SelectionChanges msg2(msg.Type,pObject->getDocument()->getName(),
572
pObject->getNameInDocument(),
573
!newElementName.empty()?newElementName.c_str():oldElementName.c_str(),
574
pObject->getTypeId().getName(), msg.x,msg.y,msg.z);
577
msg2.pOriginalMsg = &msg;
578
signalSelectionChanged3(msg2);
580
msg2.Object.setSubName(oldElementName.c_str());
581
msg2.pSubName = msg2.Object.getSubName().c_str();
582
signalSelectionChanged2(msg2);
584
catch (const boost::exception&) {
585
// reported by code analyzers
586
Base::Console().Warning("slotSelectionChanged: Unexpected boost exception\n");
591
signalSelectionChanged3(msg);
592
signalSelectionChanged2(msg);
594
catch (const boost::exception&) {
595
// reported by code analyzers
596
Base::Console().Warning("slotSelectionChanged: Unexpected boost exception\n");
601
int SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectName, const char* pSubName,
602
float x, float y, float z, SelectionChanges::MsgSource signal)
604
if (!pDocName || !pObjectName) {
608
if (!pSubName) pSubName = "";
610
if (DocName==pDocName && FeatName==pObjectName && SubName==pSubName) {
616
if (ActiveGate && signal != SelectionChanges::MsgSource::Internal) {
617
App::Document* pDoc = getDocument(pDocName);
618
if (!pDoc || !pObjectName)
620
App::ElementNamePair elementName;
621
auto pObject = pDoc->getObject(pObjectName);
625
const char *subelement = pSubName;
626
if (gateResolve != ResolveMode::NoResolve) {
627
auto &newElementName = elementName.newName;
628
auto &oldElementName = elementName.oldName;
629
pObject = App::GeoFeature::resolveElement(pObject,pSubName,elementName);
632
if (gateResolve > ResolveMode::OldStyleElement)
633
subelement = !newElementName.empty() ? newElementName.c_str() : oldElementName.c_str();
635
subelement = oldElementName.c_str();
637
if (!ActiveGate->allow(pObject->getDocument(), pObject, subelement)) {
639
if (ActiveGate->notAllowedReason.length() > 0){
640
msg = QObject::tr(ActiveGate->notAllowedReason.c_str());
642
msg = QCoreApplication::translate("SelectionFilter","Not allowed:");
644
msg.append(QString::fromLatin1(" %1.%2.%3 ")
645
.arg(QString::fromLatin1(pDocName),
646
QString::fromLatin1(pObjectName),
647
QString::fromLatin1(pSubName)));
649
if (getMainWindow()) {
650
getMainWindow()->showMessage(msg);
651
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
652
mdi->setOverrideCursor(QCursor(Qt::ForbiddenCursor));
656
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
657
mdi->restoreOverrideCursor();
661
FeatName= pObjectName;
667
// set up the change object
668
SelectionChanges Chng(signal == SelectionChanges::MsgSource::Internal
669
? SelectionChanges::SetPreselectSignal
670
: SelectionChanges::SetPreselect,
671
DocName,FeatName,SubName,std::string(),x,y,z,signal);
673
if (Chng.Type==SelectionChanges::SetPreselect) {
674
CurrentPreselection = Chng;
675
FC_TRACE("preselect "<<DocName<<'#'<<FeatName<<'.'<<SubName);
678
FC_TRACE("preselect signal "<<DocName<<'#'<<FeatName<<'.'<<SubName);
683
if (signal == SelectionChanges::MsgSource::Internal && !DocName.empty()) {
684
FC_TRACE("preselect "<<DocName<<'#'<<FeatName<<'.'<<SubName);
685
Chng.Type = SelectionChanges::SetPreselect;
686
CurrentPreselection = Chng;
687
notify(std::move(Chng));
690
// It is possible the preselect is removed during notification
691
return DocName.empty()?0:1;
695
std::array<std::pair<double, std::string>, 3> schemaTranslatePoint(double x, double y, double z, double precision)
697
Base::Quantity mmx(Base::Quantity::MilliMetre);
698
mmx.setValue(fabs(x) > precision ? x : 0.0);
699
Base::Quantity mmy(Base::Quantity::MilliMetre);
700
mmy.setValue(fabs(y) > precision ? y : 0.0);
701
Base::Quantity mmz(Base::Quantity::MilliMetre);
702
mmz.setValue(fabs(z) > precision ? z : 0.0);
704
double xfactor, yfactor, zfactor;
705
QString xunit, yunit, zunit;
707
Base::UnitsApi::schemaTranslate(mmx, xfactor, xunit);
708
Base::UnitsApi::schemaTranslate(mmy, yfactor, yunit);
709
Base::UnitsApi::schemaTranslate(mmz, zfactor, zunit);
711
double xuser = fabs(x) > precision ? x / xfactor : 0.0;
712
double yuser = fabs(y) > precision ? y / yfactor : 0.0;
713
double zuser = fabs(z) > precision ? z / zfactor : 0.0;
715
std::array<std::pair<double, std::string>, 3> ret = {std::make_pair(xuser, xunit.toUtf8().constBegin()),
716
std::make_pair(yuser, yunit.toUtf8().constBegin()),
717
std::make_pair(zuser, zunit.toUtf8().constBegin())};
721
QString getPreselectionInfo(const char* documentName,
722
const char* objectName,
723
const char* subElementName,
724
float x, float y, float z,
727
auto pts = schemaTranslatePoint(x, y, z, precision);
729
int numberDecimals = std::min(6, Base::UnitsApi::getDecimals());
731
QString message = QStringLiteral("Preselected: %1.%2.%3 (%4 %5, %6 %7, %8 %9)")
732
.arg(QString::fromUtf8(documentName))
733
.arg(QString::fromUtf8(objectName))
734
.arg(QString::fromUtf8(subElementName))
735
.arg(QString::number(pts[0].first, 'f', numberDecimals))
736
.arg(QString::fromStdString(pts[0].second))
737
.arg(QString::number(pts[1].first, 'f', numberDecimals))
738
.arg(QString::fromStdString(pts[1].second))
739
.arg(QString::number(pts[2].first, 'f', numberDecimals))
740
.arg(QString::fromStdString(pts[2].second));
744
void printPreselectionInfo(const char* documentName,
745
const char* objectName,
746
const char* subElementName,
747
float x, float y, float z,
750
if (getMainWindow()) {
751
QString message = getPreselectionInfo(documentName,
755
getMainWindow()->showMessage(message);
760
void SelectionSingleton::setPreselectCoord( float x, float y, float z)
762
// if nothing is in preselect ignore
763
if(CurrentPreselection.Object.getObjectName().empty())
766
CurrentPreselection.x = x;
767
CurrentPreselection.y = y;
768
CurrentPreselection.z = z;
770
printPreselectionInfo(CurrentPreselection.pDocName,
771
CurrentPreselection.pObjectName,
772
CurrentPreselection.pSubName,
776
void SelectionSingleton::rmvPreselect(bool signal)
782
SelectionChanges Chng(SelectionChanges::RmvPreselectSignal,DocName,FeatName,SubName);
783
notify(std::move(Chng));
787
SelectionChanges Chng(SelectionChanges::RmvPreselect,DocName,FeatName,SubName);
789
// reset the current preselection
790
CurrentPreselection = SelectionChanges();
799
if (ActiveGate && getMainWindow()) {
800
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
801
mdi->restoreOverrideCursor();
804
FC_TRACE("rmv preselect");
806
// notify observing objects
807
notify(std::move(Chng));
810
const SelectionChanges &SelectionSingleton::getPreselection() const
812
return CurrentPreselection;
815
// add a SelectionGate to control what is selectable
816
void SelectionSingleton::addSelectionGate(Gui::SelectionGate *gate, ResolveMode resolve)
822
gateResolve = resolve;
825
// remove the active SelectionGate
826
void SelectionSingleton::rmvSelectionGate()
830
ActiveGate = nullptr;
832
Gui::Document* doc = Gui::Application::Instance->activeDocument();
834
// if a document is about to be closed it has no MDI view any more
835
Gui::MDIView* mdi = doc->getActiveView();
837
mdi->restoreOverrideCursor();
843
App::Document* SelectionSingleton::getDocument(const char* pDocName) const
845
if (pDocName && pDocName[0])
846
return App::GetApplication().getDocument(pDocName);
848
return App::GetApplication().getActiveDocument();
851
int SelectionSingleton::disableCommandLog() {
853
logHasSelection = hasSelection();
854
return ++logDisabled;
857
int SelectionSingleton::enableCommandLog(bool silent) {
859
if(!logDisabled && !silent) {
860
auto manager = Application::Instance->macroManager();
861
if(!hasSelection()) {
863
manager->addLine(MacroManager::Cmt, "Gui.Selection.clearSelection()");
865
for(auto &sel : _SelList)
872
void SelectionSingleton::_SelObj::log(bool remove, bool clearPreselect) {
873
if(logged && !remove)
876
std::ostringstream ss;
877
ss << "Gui.Selection." << (remove?"removeSelection":"addSelection")
878
<< "('" << DocName << "','" << FeatName << "'";
879
if(!SubName.empty()) {
880
if(!elementName.oldName.empty() && !elementName.newName.empty())
881
ss << ",'" << SubName.substr(0,SubName.size()-elementName.newName.size())
882
<< elementName.oldName << "'";
884
ss << ",'" << SubName << "'";
886
if(!remove && (x || y || z || !clearPreselect)) {
889
ss << ',' << x << ',' << y << ',' << z;
894
Application::Instance->macroManager()->addLine(MacroManager::Cmt, ss.str().c_str());
897
bool SelectionSingleton::addSelection(const char* pDocName, const char* pObjectName,
898
const char* pSubName, float x, float y, float z,
899
const std::vector<SelObj> *pickedList, bool clearPreselect)
903
for(const auto &sel : *pickedList) {
904
_PickedList.emplace_back();
905
auto &s = _PickedList.back();
906
s.DocName = sel.DocName;
907
s.FeatName = sel.FeatName;
908
s.SubName = sel.SubName;
909
s.TypeName = sel.TypeName;
910
s.pObject = sel.pObject;
916
notify(SelectionChanges(SelectionChanges::PickedListChanged));
920
int ret = checkSelection(pDocName, pObjectName, pSubName, ResolveMode::NoResolve, temp);
928
// check for a Selection Gate
930
const char *subelement = nullptr;
931
auto pObject = getObjectOfType(temp,App::DocumentObject::getClassTypeId(),gateResolve,&subelement);
932
if (!ActiveGate->allow(pObject?pObject->getDocument():temp.pDoc,pObject,subelement)) {
933
if (getMainWindow()) {
935
if (ActiveGate->notAllowedReason.length() > 0) {
936
msg = QObject::tr(ActiveGate->notAllowedReason.c_str());
938
msg = QCoreApplication::translate("SelectionFilter","Selection not allowed by filter");
940
getMainWindow()->showMessage(msg);
941
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
942
mdi->setOverrideCursor(Qt::ForbiddenCursor);
944
ActiveGate->notAllowedReason.clear();
945
QApplication::beep();
951
temp.log(false,clearPreselect);
953
_SelList.push_back(temp);
954
_SelStackForward.clear();
959
SelectionChanges Chng(SelectionChanges::AddSelection,
960
temp.DocName,temp.FeatName,temp.SubName,temp.TypeName, x,y,z);
962
FC_LOG("Add Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName
963
<< " (" << x << ", " << y << ", " << z << ')');
965
notify(std::move(Chng));
967
getMainWindow()->updateActions();
971
// There is a possibility that some observer removes or clears selection
972
// inside signal handler, hence the check here
973
return isSelected(temp.DocName.c_str(),temp.FeatName.c_str(), temp.SubName.c_str());
976
void SelectionSingleton::selStackPush(bool clearForward, bool overwrite) {
977
static int stackSize;
979
stackSize = App::GetApplication().GetParameterGroupByPath
980
("User parameter:BaseApp/Preferences/View")->GetInt("SelectionStackSize",100);
983
_SelStackForward.clear();
986
if((int)_SelStackBack.size() >= stackSize)
987
_SelStackBack.pop_front();
989
for(auto &sel : _SelList)
990
item.emplace(sel.DocName.c_str(),sel.FeatName.c_str(),sel.SubName.c_str());
991
if(!_SelStackBack.empty() && _SelStackBack.back()==item)
993
if(!overwrite || _SelStackBack.empty())
994
_SelStackBack.emplace_back();
995
_SelStackBack.back() = std::move(item);
998
void SelectionSingleton::selStackGoBack(int count) {
999
if((int)_SelStackBack.size()<count)
1000
count = _SelStackBack.size();
1003
if(!_SelList.empty()) {
1004
selStackPush(false,true);
1005
clearCompleteSelection();
1008
for(int i=0;i<count;++i) {
1009
_SelStackForward.push_front(std::move(_SelStackBack.back()));
1010
_SelStackBack.pop_back();
1012
std::deque<SelStackItem> tmpStack;
1013
_SelStackForward.swap(tmpStack);
1014
while(!_SelStackBack.empty()) {
1016
for(auto &sobjT : _SelStackBack.back()) {
1017
if(sobjT.getSubObject()) {
1018
addSelection(sobjT.getDocumentName().c_str(),
1019
sobjT.getObjectName().c_str(),
1020
sobjT.getSubName().c_str());
1026
tmpStack.push_front(std::move(_SelStackBack.back()));
1027
_SelStackBack.pop_back();
1029
_SelStackForward = std::move(tmpStack);
1030
getMainWindow()->updateActions();
1033
void SelectionSingleton::selStackGoForward(int count) {
1034
if((int)_SelStackForward.size()<count)
1035
count = _SelStackForward.size();
1038
if(!_SelList.empty()) {
1039
selStackPush(false,true);
1040
clearCompleteSelection();
1042
for(int i=0;i<count;++i) {
1043
_SelStackBack.push_back(_SelStackForward.front());
1044
_SelStackForward.pop_front();
1046
std::deque<SelStackItem> tmpStack;
1047
_SelStackForward.swap(tmpStack);
1050
for(auto &sobjT : _SelStackBack.back()) {
1051
if(sobjT.getSubObject()) {
1052
addSelection(sobjT.getDocumentName().c_str(),
1053
sobjT.getObjectName().c_str(),
1054
sobjT.getSubName().c_str());
1058
if(found || tmpStack.empty())
1060
_SelStackBack.push_back(tmpStack.front());
1061
tmpStack.pop_front();
1063
_SelStackForward = std::move(tmpStack);
1064
getMainWindow()->updateActions();
1067
std::vector<SelectionObject> SelectionSingleton::selStackGet(const char* pDocName, ResolveMode resolve, int index) const
1069
const SelStackItem *item = nullptr;
1071
if(index >= (int)_SelStackBack.size())
1073
item = &_SelStackBack[_SelStackBack.size()-1-index];
1077
if(index>=(int)_SelStackForward.size())
1079
item = &_SelStackBack[_SelStackForward.size()-1-index];
1082
std::list<_SelObj> selList;
1083
for(auto &sobjT : *item) {
1085
if(checkSelection(sobjT.getDocumentName().c_str(),
1086
sobjT.getObjectName().c_str(),
1087
sobjT.getSubName().c_str(),
1088
ResolveMode::NoResolve,
1092
selList.push_back(sel);
1096
return getObjectList(pDocName,App::DocumentObject::getClassTypeId(), selList, resolve);
1099
bool SelectionSingleton::addSelections(const char* pDocName, const char* pObjectName, const std::vector<std::string>& pSubNames)
1101
if(!_PickedList.empty()) {
1102
_PickedList.clear();
1103
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1106
bool update = false;
1107
for(const auto & pSubName : pSubNames) {
1109
int ret = checkSelection(pDocName, pObjectName, pSubName.c_str(), ResolveMode::NoResolve, temp);
1117
_SelList.push_back(temp);
1118
_SelStackForward.clear();
1120
SelectionChanges Chng(SelectionChanges::AddSelection,
1121
temp.DocName,temp.FeatName,temp.SubName,temp.TypeName);
1123
FC_LOG("Add Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName);
1125
notify(std::move(Chng));
1130
getMainWindow()->updateActions();
1134
bool SelectionSingleton::updateSelection(bool show, const char* pDocName,
1135
const char* pObjectName, const char* pSubName)
1137
if(!pDocName || !pObjectName)
1141
if(DocName==pDocName && FeatName==pObjectName && SubName==pSubName) {
1143
FC_TRACE("preselect signal");
1144
notify(SelectionChanges(SelectionChanges::SetPreselectSignal,DocName,FeatName,SubName));
1148
auto pDoc = getDocument(pDocName);
1151
auto pObject = pDoc->getObject(pObjectName);
1154
if (!isSelected(pObject, pSubName, ResolveMode::NoResolve))
1157
SelectionChanges Chng(show?SelectionChanges::ShowSelection:SelectionChanges::HideSelection,
1158
pDocName,pObjectName,pSubName,pObject->getTypeId().getName());
1160
FC_LOG("Update Selection "<<Chng.pDocName << '#' << Chng.pObjectName << '.' <<Chng.pSubName);
1162
notify(std::move(Chng));
1167
bool SelectionSingleton::addSelection(const SelectionObject& obj, bool clearPreselect)
1169
const std::vector<std::string>& subNames = obj.getSubNames();
1170
const std::vector<Base::Vector3d> points = obj.getPickedPoints();
1171
if (!subNames.empty() && subNames.size() == points.size()) {
1173
for (std::size_t i=0; i<subNames.size(); i++) {
1174
const std::string& name = subNames[i];
1175
const Base::Vector3d& pnt = points[i];
1176
ok &= addSelection(obj.getDocName(), obj.getFeatName(), name.c_str(),
1177
static_cast<float>(pnt.x),
1178
static_cast<float>(pnt.y),
1179
static_cast<float>(pnt.z),nullptr,clearPreselect);
1183
else if (!subNames.empty()) {
1185
for (const std::string& name : subNames) {
1186
ok &= addSelection(obj.getDocName(), obj.getFeatName(), name.c_str());
1191
return addSelection(obj.getDocName(), obj.getFeatName());
1196
void SelectionSingleton::rmvSelection(const char* pDocName, const char* pObjectName, const char* pSubName,
1197
const std::vector<SelObj> *pickedList)
1200
_PickedList.clear();
1201
for(const auto &sel : *pickedList) {
1202
_PickedList.emplace_back();
1203
auto &s = _PickedList.back();
1204
s.DocName = sel.DocName;
1205
s.FeatName = sel.FeatName;
1206
s.SubName = sel.SubName;
1207
s.TypeName = sel.TypeName;
1208
s.pObject = sel.pObject;
1214
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1221
int ret = checkSelection(pDocName, pObjectName, pSubName, ResolveMode::NoResolve, temp);
1225
std::vector<SelectionChanges> changes;
1226
for(auto It=_SelList.begin(),ItNext=It;It!=_SelList.end();It=ItNext) {
1228
if(It->DocName!=temp.DocName || It->FeatName!=temp.FeatName)
1230
// if no subname is specified, remove all subobjects of the matching object
1231
if(!temp.SubName.empty()) {
1232
// otherwise, match subojects with common prefix, separated by '.'
1233
if(!boost::starts_with(It->SubName,temp.SubName) ||
1234
(It->SubName.length()!=temp.SubName.length() && It->SubName[temp.SubName.length()-1]!='.'))
1240
changes.emplace_back(SelectionChanges::RmvSelection,
1241
It->DocName,It->FeatName,It->SubName,It->TypeName);
1243
// destroy the _SelObj item
1247
// NOTE: It can happen that there are nested calls of rmvSelection()
1248
// so that it's not safe to invoke the notifications inside the loop
1249
// as this can invalidate the iterators and thus leads to undefined
1251
// So, the notification is done after the loop, see also #0003469
1252
if(!changes.empty()) {
1253
for(auto &Chng : changes) {
1254
FC_LOG("Rmv Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName);
1255
notify(std::move(Chng));
1257
getMainWindow()->updateActions();
1262
std::string DocName;
1263
std::string FeatName;
1264
std::string SubName;
1265
SelInfo(const std::string &docName,
1266
const std::string &featName,
1267
const std::string &subName)
1274
void SelectionSingleton::setVisible(VisibleState vis) {
1275
std::set<std::pair<App::DocumentObject*,App::DocumentObject*> > filter;
1288
// Copy the selection in case it changes during this function
1289
std::vector<SelInfo> sels;
1290
sels.reserve(_SelList.size());
1291
for(auto &sel : _SelList) {
1292
if(sel.DocName.empty() || sel.FeatName.empty() || !sel.pObject)
1294
sels.emplace_back(sel.DocName,sel.FeatName,sel.SubName);
1297
for(auto &sel : sels) {
1298
App::Document *doc = App::GetApplication().getDocument(sel.DocName.c_str());
1300
App::DocumentObject *obj = doc->getObject(sel.FeatName.c_str());
1303
// get parent object
1304
App::DocumentObject *parent = nullptr;
1305
std::string elementName;
1306
obj = obj->resolve(sel.SubName.c_str(),&parent,&elementName);
1307
if (!obj || !obj->isAttachedToDocument() || (parent && !parent->isAttachedToDocument()))
1309
// try call parent object's setElementVisible
1311
// prevent setting the same object visibility more than once
1312
if (!filter.insert(std::make_pair(obj,parent)).second)
1314
int visElement = parent->isElementVisible(elementName.c_str());
1315
if (visElement >= 0) {
1319
if (visElement == visible)
1321
visElement = visible;
1324
visElement = !visElement;
1328
updateSelection(false,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1329
parent->setElementVisible(elementName.c_str(), visElement ? true : false);
1331
updateSelection(true,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1335
// Fall back to direct object visibility setting
1337
if(!filter.insert(std::make_pair(obj,static_cast<App::DocumentObject*>(nullptr))).second){
1341
auto vp = Application::Instance->getViewProvider(obj);
1346
visObject = visible ? true : false;
1348
visObject = !vp->isShow();
1352
updateSelection(visObject,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1354
updateSelection(visObject,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1361
void SelectionSingleton::setSelection(const char* pDocName, const std::vector<App::DocumentObject*>& sel)
1363
App::Document *pcDoc;
1364
pcDoc = getDocument(pDocName);
1368
if(!_PickedList.empty()) {
1369
_PickedList.clear();
1370
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1373
bool touched = false;
1374
for(auto obj : sel) {
1375
if(!obj || !obj->isAttachedToDocument())
1378
int ret = checkSelection(pDocName,obj->getNameInDocument(), nullptr, ResolveMode::NoResolve, temp);
1382
_SelList.push_back(temp);
1386
_SelStackForward.clear();
1387
notify(SelectionChanges(SelectionChanges::SetSelection, pDocName));
1388
getMainWindow()->updateActions();
1392
void SelectionSingleton::clearSelection(const char* pDocName, bool clearPreSelect)
1394
// Because the introduction of external editing, it is best to make
1395
// clearSelection(0) behave as clearCompleteSelection(), which is the same
1396
// behavior of python Selection.clearSelection(None)
1397
if (!pDocName || !pDocName[0] || strcmp(pDocName,"*")==0) {
1398
clearCompleteSelection(clearPreSelect);
1402
if (!_PickedList.empty()) {
1403
_PickedList.clear();
1404
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1407
App::Document* pDoc;
1408
pDoc = getDocument(pDocName);
1410
std::string docName = pDocName;
1411
if (clearPreSelect && DocName == docName)
1414
bool touched = false;
1415
for (auto it=_SelList.begin();it!=_SelList.end();) {
1416
if (it->DocName == docName) {
1418
it = _SelList.erase(it);
1429
std::ostringstream ss;
1430
ss << "Gui.Selection.clearSelection('" << docName << "'";
1431
if (!clearPreSelect)
1434
Application::Instance->macroManager()->addLine(MacroManager::Cmt,ss.str().c_str());
1437
notify(SelectionChanges(SelectionChanges::ClrSelection,docName.c_str()));
1439
getMainWindow()->updateActions();
1443
void SelectionSingleton::clearCompleteSelection(bool clearPreSelect)
1445
if(!_PickedList.empty()) {
1446
_PickedList.clear();
1447
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1453
if(_SelList.empty())
1457
Application::Instance->macroManager()->addLine(MacroManager::Cmt,
1458
clearPreSelect?"Gui.Selection.clearSelection()"
1459
:"Gui.Selection.clearSelection(False)");
1463
SelectionChanges Chng(SelectionChanges::ClrSelection);
1465
FC_LOG("Clear selection");
1467
notify(std::move(Chng));
1468
getMainWindow()->updateActions();
1471
bool SelectionSingleton::isSelected(const char* pDocName, const char* pObjectName,
1472
const char* pSubName, ResolveMode resolve) const
1475
return checkSelection(pDocName, pObjectName, pSubName, resolve, sel, &_SelList) > 0;
1478
bool SelectionSingleton::isSelected(App::DocumentObject* pObject, const char* pSubName, ResolveMode resolve) const
1480
if (!pObject || !pObject->isAttachedToDocument() || !pObject->getDocument())
1483
return checkSelection(pObject->getDocument()->getName(),
1484
pObject->getNameInDocument(), pSubName, resolve, sel, &_SelList) > 0;
1487
int SelectionSingleton::checkSelection(const char *pDocName, const char *pObjectName, const char *pSubName,
1488
ResolveMode resolve, _SelObj &sel, const std::list<_SelObj> *selList) const
1490
sel.pDoc = getDocument(pDocName);
1493
FC_ERR("Cannot find document");
1496
pDocName = sel.pDoc->getName();
1497
sel.DocName = pDocName;
1500
sel.pObject = sel.pDoc->getObject(pObjectName);
1502
sel.pObject = nullptr;
1505
FC_ERR("Object not found");
1508
if (sel.pObject->testStatus(App::ObjectStatus::Remove))
1511
sel.SubName = pSubName;
1512
if (resolve == ResolveMode::NoResolve)
1513
TreeWidget::checkTopParent(sel.pObject,sel.SubName);
1514
pSubName = !sel.SubName.empty()?sel.SubName.c_str():nullptr;
1515
sel.FeatName = sel.pObject->getNameInDocument();
1516
sel.TypeName = sel.pObject->getTypeId().getName();
1517
const char *element = nullptr;
1518
sel.pResolvedObject = App::GeoFeature::resolveElement(sel.pObject,
1519
pSubName,sel.elementName,false,App::GeoFeature::Normal,nullptr,&element);
1520
if(!sel.pResolvedObject) {
1522
FC_ERR("Sub-object " << sel.DocName << '#' << sel.FeatName << '.' << sel.SubName << " not found");
1525
if(sel.pResolvedObject->testStatus(App::ObjectStatus::Remove))
1527
std::string subname;
1529
if(pSubName && element) {
1530
prefix = std::string(pSubName, element-pSubName);
1531
if(!sel.elementName.newName.empty()) {
1532
// make sure the selected sub name is a new style if available
1533
subname = prefix + sel.elementName.newName;
1534
pSubName = subname.c_str();
1535
sel.SubName = subname;
1539
selList = &_SelList;
1544
for (auto &s : *selList) {
1545
if (s.DocName==pDocName && s.FeatName==sel.FeatName) {
1546
if(s.SubName==pSubName)
1548
if (resolve > ResolveMode::OldStyleElement && boost::starts_with(s.SubName,prefix))
1552
if (resolve == ResolveMode::OldStyleElement) {
1553
for(auto &s : *selList) {
1554
if(s.pResolvedObject != sel.pResolvedObject)
1558
if (!s.elementName.newName.empty()) {
1559
if (s.elementName.newName == sel.elementName.newName)
1562
else if(s.SubName == sel.elementName.oldName)
1569
const char *SelectionSingleton::getSelectedElement(App::DocumentObject *obj, const char* pSubName) const
1574
for(list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
1575
if (It->pObject == obj) {
1576
auto len = It->SubName.length();
1579
if (pSubName && strncmp(pSubName,It->SubName.c_str(),It->SubName.length())==0){
1580
if(pSubName[len]==0 || pSubName[len-1] == '.')
1581
return It->SubName.c_str();
1588
void SelectionSingleton::slotDeletedObject(const App::DocumentObject& Obj)
1590
if(!Obj.isAttachedToDocument())
1593
// For safety reason, don't bother checking
1596
// Remove also from the selection, if selected
1597
// We don't walk down the hierarchy for each selection, so there may be stray selection
1598
std::vector<SelectionChanges> changes;
1599
for(auto it=_SelList.begin(),itNext=it;it!=_SelList.end();it=itNext) {
1601
if(it->pResolvedObject == &Obj || it->pObject==&Obj) {
1602
changes.emplace_back(SelectionChanges::RmvSelection,
1603
it->DocName,it->FeatName,it->SubName,it->TypeName);
1607
if(!changes.empty()) {
1608
for(auto &Chng : changes) {
1609
FC_LOG("Rmv Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName);
1610
notify(std::move(Chng));
1612
getMainWindow()->updateActions();
1615
if(!_PickedList.empty()) {
1616
bool changed = false;
1617
for(auto it=_PickedList.begin(),itNext=it;it!=_PickedList.end();it=itNext) {
1620
if(sel.DocName == Obj.getDocument()->getName() &&
1621
sel.FeatName == Obj.getNameInDocument())
1624
_PickedList.erase(it);
1628
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1632
void SelectionSingleton::setSelectionStyle(SelectionStyle selStyle)
1634
selectionStyle = selStyle;
1637
SelectionSingleton::SelectionStyle SelectionSingleton::getSelectionStyle()
1639
return selectionStyle;
1642
//**************************************************************************
1643
// Construction/Destruction
1647
* A more elaborate description of the constructor.
1649
SelectionSingleton::SelectionSingleton() :
1650
CurrentPreselection(SelectionChanges::ClrSelection),
1651
selectionStyle(SelectionStyle::NormalSelection)
1656
ActiveGate = nullptr;
1657
gateResolve = ResolveMode::OldStyleElement;
1659
App::GetApplication().signalDeletedObject.connect(std::bind(&Gui::SelectionSingleton::slotDeletedObject, this, sp::_1));
1660
signalSelectionChanged.connect(std::bind(&Gui::SelectionSingleton::slotSelectionChanged, this, sp::_1));
1666
* A more elaborate description of the destructor.
1668
SelectionSingleton::~SelectionSingleton() = default;
1670
SelectionSingleton* SelectionSingleton::_pcSingleton = nullptr;
1672
SelectionSingleton& SelectionSingleton::instance()
1675
_pcSingleton = new SelectionSingleton;
1676
return *_pcSingleton;
1679
void SelectionSingleton::destruct ()
1682
delete _pcSingleton;
1683
_pcSingleton = nullptr;
1686
//**************************************************************************
1689
// SelectionSingleton Methods // Methods structure
1690
PyMethodDef SelectionSingleton::Methods[] = {
1691
{"addSelection", (PyCFunction) SelectionSingleton::sAddSelection, METH_VARARGS,
1692
"addSelection(docName, objName, subName, x=0, y=0, z=0, clear=True) -> None\n"
1693
"addSelection(obj, subName, x=0, y=0, z=0, clear=True) -> None\n"
1694
"addSelection(obj, subNames, clear=True) -> None\n"
1696
"Add an object to the selection.\n"
1698
"docName : str\n Name of the `App.Document`.\n"
1699
"objName : str\n Name of the `App.DocumentObject` to add.\n"
1700
"obj : App.DocumentObject\n Object to add.\n"
1701
"subName : str\n Subelement name.\n"
1702
"x : float\n Coordinate `x` of the point to pick.\n"
1703
"y : float\n Coordinate `y` of the point to pick.\n"
1704
"z : float\n Coordinate `z` of the point to pick.\n"
1705
"subNames : list of str\n List of subelement names.\n"
1706
"clear : bool\n Clear preselection."},
1707
{"updateSelection", (PyCFunction) SelectionSingleton::sUpdateSelection, METH_VARARGS,
1708
"updateSelection(show, obj, subName) -> None\n"
1710
"Update an object in the selection.\n"
1712
"show : bool\n Show or hide the selection.\n"
1713
"obj : App.DocumentObject\n Object to update.\n"
1714
"subName : str\n Name of the subelement to update."},
1715
{"removeSelection", (PyCFunction) SelectionSingleton::sRemoveSelection, METH_VARARGS,
1716
"removeSelection(obj, subName) -> None\n"
1717
"removeSelection(docName, objName, subName) -> None\n"
1719
"Remove an object from the selection.\n"
1721
"docName : str\n Name of the `App.Document`.\n"
1722
"objName : str\n Name of the `App.DocumentObject` to remove.\n"
1723
"obj : App.DocumentObject\n Object to remove.\n"
1724
"subName : str\n Name of the subelement to remove."},
1725
{"clearSelection" , (PyCFunction) SelectionSingleton::sClearSelection, METH_VARARGS,
1726
"clearSelection(docName, clearPreSelect=True) -> None\n"
1727
"clearSelection(clearPreSelect=True) -> None\n"
1729
"Clear the selection in the given document. If no document is\n"
1730
"given the complete selection is cleared.\n"
1732
"docName : str\n Name of the `App.Document`.\n"
1733
"clearPreSelect : bool\n Clear preselection."},
1734
{"isSelected", (PyCFunction) SelectionSingleton::sIsSelected, METH_VARARGS,
1735
"isSelected(obj, subName, resolve=ResolveMode.OldStyleElement) -> bool\n"
1737
"Check if a given object is selected.\n"
1739
"obj : App.DocumentObject\n Object to check.\n"
1740
"subName : str\n Name of the subelement.\n"
1741
"resolve : int\n Resolve subelement reference."},
1742
{"setPreselection", reinterpret_cast<PyCFunction>(reinterpret_cast<void (*) ()>( SelectionSingleton::sSetPreselection )), METH_VARARGS|METH_KEYWORDS,
1743
"setPreselection(obj, subName, x=0, y=0, z=0, type=1) -> None\n"
1745
"Set preselected object.\n"
1747
"obj : App.DocumentObject\n Object to preselect.\n"
1748
"subName : str\n Subelement name.\n"
1749
"x : float\n Coordinate `x` of the point to preselect.\n"
1750
"y : float\n Coordinate `y` of the point to preselect.\n"
1751
"z : float\n Coordinate `z` of the point to preselect.\n"
1753
{"getPreselection", (PyCFunction) SelectionSingleton::sGetPreselection, METH_VARARGS,
1754
"getPreselection() -> Gui.SelectionObject\n"
1756
"Get preselected object."},
1757
{"clearPreselection", (PyCFunction) SelectionSingleton::sRemPreselection, METH_VARARGS,
1758
"clearPreselection() -> None\n"
1760
"Clear the preselection."},
1761
{"countObjectsOfType", (PyCFunction) SelectionSingleton::sCountObjectsOfType, METH_VARARGS,
1762
"countObjectsOfType(type, docName, resolve=ResolveMode.OldStyleElement) -> int\n"
1764
"Get the number of selected objects. If no document name is given the\n"
1765
"active document is used and '*' means all documents.\n"
1767
"type : str\n Object type id name.\n"
1768
"docName : str\n Name of the `App.Document`.\n"
1770
{"getSelection", (PyCFunction) SelectionSingleton::sGetSelection, METH_VARARGS,
1771
"getSelection(docName, resolve=ResolveMode.OldStyleElement, single=False) -> list\n"
1773
"Return a list of selected objects. If no document name is given\n"
1774
"the active document is used and '*' means all documents.\n"
1776
"docName : str\n Name of the `App.Document`.\n"
1777
"resolve : int\n Resolve the subname references.\n"
1778
" 0: do not resolve, 1: resolve, 2: resolve with element map.\n"
1779
"single : bool\n Only return if there is only one selection."},
1780
{"getPickedList", (PyCFunction) SelectionSingleton::sGetPickedList, 1,
1781
"getPickedList(docName) -> list of Gui.SelectionObject\n"
1783
"Return a list of SelectionObjects generated by the last mouse click.\n"
1784
"If no document name is given the active document is used and '*'\n"
1785
"means all documents.\n"
1787
"docName : str\n Name of the `App.Document`."},
1788
{"enablePickedList", (PyCFunction) SelectionSingleton::sEnablePickedList, METH_VARARGS,
1789
"enablePickedList(enable=True) -> None\n"
1791
"Enable/disable pick list.\n"
1794
{"getCompleteSelection", (PyCFunction) SelectionSingleton::sGetCompleteSelection, METH_VARARGS,
1795
"getCompleteSelection(resolve=ResolveMode.OldStyleElement) -> list\n"
1797
"Return a list of selected objects across all documents.\n"
1800
{"getSelectionEx", (PyCFunction) SelectionSingleton::sGetSelectionEx, METH_VARARGS,
1801
"getSelectionEx(docName, resolve=ResolveMode.OldStyleElement, single=False) -> list of Gui.SelectionObject\n"
1803
"Return a list of SelectionObjects. If no document name is given the\n"
1804
"active document is used and '*' means all documents.\n"
1805
"The SelectionObjects contain a variety of information about the selection,\n"
1806
"e.g. subelement names.\n"
1808
"docName : str\n Name of the `App.Document`.\n"
1809
"resolve : int\n Resolve the subname references.\n"
1810
" 0: do not resolve, 1: resolve, 2: resolve with element map.\n"
1811
"single : bool\n Only return if there is only one selection."},
1812
{"getSelectionObject", (PyCFunction) SelectionSingleton::sGetSelectionObject, METH_VARARGS,
1813
"getSelectionObject(docName, objName, subName, point) -> Gui.SelectionObject\n"
1815
"Return a SelectionObject.\n"
1817
"docName : str\n Name of the `App.Document`.\n"
1818
"objName : str\n Name of the `App.DocumentObject` to select.\n"
1819
"subName : str\n Subelement name.\n"
1820
"point : tuple\n Coordinates of the point to pick."},
1821
{"setSelectionStyle", (PyCFunction) SelectionSingleton::sSetSelectionStyle, METH_VARARGS,
1822
"setSelectionStyle(selectionStyle) -> None\n"
1824
"Change the selection style. 0 for normal selection, 1 for greedy selection\n"
1826
"selectionStyle : int"},
1827
{"addObserver", (PyCFunction) SelectionSingleton::sAddSelObserver, METH_VARARGS,
1828
"addObserver(object, resolve=ResolveMode.OldStyleElement) -> None\n"
1830
"Install an observer.\n"
1832
"object : object\n Python object instance.\n"
1834
{"removeObserver", (PyCFunction) SelectionSingleton::sRemSelObserver, METH_VARARGS,
1835
"removeObserver(object) -> None\n"
1837
"Uninstall an observer.\n"
1839
"object : object\n Python object instance."},
1840
{"addSelectionGate", (PyCFunction) SelectionSingleton::sAddSelectionGate, METH_VARARGS,
1841
"addSelectionGate(filter, resolve=ResolveMode.OldStyleElement) -> None\n"
1843
"Activate the selection gate.\n"
1844
"The selection gate will prohibit all selections that do not match\n"
1845
"the given selection criteria.\n"
1847
"filter : str, SelectionFilter, object\n"
1850
"Examples strings are:\n"
1851
"Gui.Selection.addSelectionGate('SELECT Part::Feature SUBELEMENT Edge')\n"
1852
"Gui.Selection.addSelectionGate('SELECT Robot::RobotObject')\n"
1854
"An instance of SelectionFilter can also be set:\n"
1855
"filter = Gui.Selection.Filter('SELECT Part::Feature SUBELEMENT Edge')\n"
1856
"Gui.Selection.addSelectionGate(filter)\n"
1858
"The most flexible approach is to write a selection gate class that\n"
1859
"implements the method 'allow':\n"
1861
" def allow(self,doc,obj,sub):\n"
1862
" return (sub[0:4] == 'Face')\n"
1863
"Gui.Selection.addSelectionGate(Gate())"},
1864
{"removeSelectionGate", (PyCFunction) SelectionSingleton::sRemoveSelectionGate, METH_VARARGS,
1865
"removeSelectionGate() -> None\n"
1867
"Remove the active selection gate."},
1868
{"setVisible", (PyCFunction) SelectionSingleton::sSetVisible, METH_VARARGS,
1869
"setVisible(visible=None) -> None\n"
1871
"Set visibility of all selection items.\n"
1873
"visible : bool, None\n If None, then toggle visibility."},
1874
{"pushSelStack", (PyCFunction) SelectionSingleton::sPushSelStack, METH_VARARGS,
1875
"pushSelStack(clearForward=True, overwrite=False) -> None\n"
1877
"Push current selection to stack.\n"
1879
"clearForward : bool\n Clear the forward selection stack.\n"
1880
"overwrite : bool\n Overwrite the top back selection stack with current selection."},
1881
{"hasSelection", (PyCFunction) SelectionSingleton::sHasSelection, METH_VARARGS,
1882
"hasSelection(docName, resolve=ResolveMode.NoResolve) -> bool\n"
1884
"Check if there is any selection. If no document name is given,\n"
1885
"checks selections in all documents.\n"
1887
"docName : str\n Name of the `App.Document`.\n"
1889
{"hasSubSelection", (PyCFunction) SelectionSingleton::sHasSubSelection, METH_VARARGS,
1890
"hasSubSelection(docName, subElement=False) -> bool\n"
1892
"Check if there is any selection with subname. If no document name\n"
1893
"is given the active document is used and '*' means all documents.\n"
1895
"docName : str\n Name of the `App.Document`.\n"
1896
"subElement : bool"},
1897
{"getSelectionFromStack",(PyCFunction) SelectionSingleton::sGetSelectionFromStack, METH_VARARGS,
1898
"getSelectionFromStack(docName, resolve=ResolveMode.OldStyleElement, index=0) -> list of Gui.SelectionObject\n"
1900
"Return SelectionObjects from selection stack. If no document name is given\n"
1901
"the active document is used and '*' means all documents.\n"
1903
"docName : str\n Name of the `App.Document`.\n"
1904
"resolve : int\n Resolve the subname references.\n"
1905
" 0: do not resolve, 1: resolve, 2: resolve with element map.\n"
1906
"index : int\n Select stack index.\n"
1907
" 0: last pushed selection, > 0: trace back, < 0: trace forward."},
1908
{nullptr, nullptr, 0, nullptr} /* Sentinel */
1911
PyObject *SelectionSingleton::sAddSelection(PyObject * /*self*/, PyObject *args)
1913
SelectionLogDisabler disabler(true);
1914
PyObject *clearPreselect = Py_True;
1917
char* subname = nullptr;
1918
float x = 0, y = 0, z = 0;
1919
if (PyArg_ParseTuple(args, "ss|sfffO!", &docname, &objname ,
1920
&subname,&x,&y,&z,&PyBool_Type,&clearPreselect)) {
1921
Selection().addSelection(docname, objname, subname, x, y, z, nullptr, Base::asBoolean(clearPreselect));
1928
x = 0, y = 0, z = 0;
1929
if (PyArg_ParseTuple(args, "O!|sfffO!", &(App::DocumentObjectPy::Type),&object,
1930
&subname,&x,&y,&z,&PyBool_Type,&clearPreselect)) {
1931
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
1932
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
1933
if (!docObj || !docObj->isAttachedToDocument()) {
1934
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
1938
Selection().addSelection(docObj->getDocument()->getName(),
1939
docObj->getNameInDocument(),
1940
subname, x, y, z, nullptr, Base::asBoolean(clearPreselect));
1946
if (PyArg_ParseTuple(args, "O!O|O!", &(App::DocumentObjectPy::Type),&object,
1947
&sequence,&PyBool_Type,&clearPreselect))
1949
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
1950
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
1951
if (!docObj || !docObj->isAttachedToDocument()) {
1952
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
1957
if (PyTuple_Check(sequence) || PyList_Check(sequence)) {
1958
Py::Sequence list(sequence);
1959
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1960
std::string subname = static_cast<std::string>(Py::String(*it));
1961
Selection().addSelection(docObj->getDocument()->getName(),
1962
docObj->getNameInDocument(),
1963
subname.c_str(), 0, 0, 0, nullptr, Base::asBoolean(clearPreselect));
1968
catch (const Py::Exception&) {
1973
PyErr_SetString(PyExc_ValueError, "type must be 'DocumentObject[,subname[,x,y,z]]' or 'DocumentObject, list or tuple of subnames'");
1978
PyObject *SelectionSingleton::sUpdateSelection(PyObject * /*self*/, PyObject *args)
1982
char* subname=nullptr;
1983
if(!PyArg_ParseTuple(args, "O!O!|s", &PyBool_Type, &show, &(App::DocumentObjectPy::Type),
1987
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
1988
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
1989
if (!docObj || !docObj->isAttachedToDocument()) {
1990
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
1994
Selection().updateSelection(Base::asBoolean(show),
1995
docObj->getDocument()->getName(), docObj->getNameInDocument(), subname);
2001
PyObject *SelectionSingleton::sRemoveSelection(PyObject * /*self*/, PyObject *args)
2003
SelectionLogDisabler disabler(true);
2004
char *docname, *objname;
2005
char* subname = nullptr;
2006
if(PyArg_ParseTuple(args, "ss|s", &docname,&objname,&subname)) {
2007
Selection().rmvSelection(docname,objname,subname);
2014
if (!PyArg_ParseTuple(args, "O!|s", &(App::DocumentObjectPy::Type),&object,&subname))
2017
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
2018
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
2019
if (!docObj || !docObj->isAttachedToDocument()) {
2020
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
2024
Selection().rmvSelection(docObj->getDocument()->getName(),
2025
docObj->getNameInDocument(),
2031
PyObject *SelectionSingleton::sClearSelection(PyObject * /*self*/, PyObject *args)
2033
SelectionLogDisabler disabler(true);
2034
PyObject *clearPreSelect = Py_True;
2035
char *documentName = nullptr;
2036
if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &clearPreSelect)) {
2038
if (!PyArg_ParseTuple(args, "|sO!", &documentName, &PyBool_Type, &clearPreSelect))
2041
Selection().clearSelection(documentName, Base::asBoolean(clearPreSelect));
2047
ResolveMode toEnum(int value) {
2050
return ResolveMode::NoResolve;
2052
return ResolveMode::OldStyleElement;
2054
return ResolveMode::NewStyleElement;
2056
return ResolveMode::FollowLink;
2058
throw Base::ValueError("Wrong enum value");
2063
PyObject *SelectionSingleton::sIsSelected(PyObject * /*self*/, PyObject *args)
2066
char* subname = nullptr;
2068
if (!PyArg_ParseTuple(args, "O!|si", &(App::DocumentObjectPy::Type), &object, &subname, &resolve))
2072
auto docObj = static_cast<App::DocumentObjectPy*>(object);
2073
bool ok = Selection().isSelected(docObj->getDocumentObjectPtr(), subname, toEnum(resolve));
2075
return Py_BuildValue("O", (ok ? Py_True : Py_False));
2077
catch (const Base::Exception& e) {
2083
PyObject *SelectionSingleton::sCountObjectsOfType(PyObject * /*self*/, PyObject *args)
2086
char* document = nullptr;
2088
if (!PyArg_ParseTuple(args, "s|si", &objecttype, &document,&resolve))
2092
unsigned int count = Selection().countObjectsOfType(objecttype, document, toEnum(resolve));
2093
return PyLong_FromLong(count);
2095
catch (const Base::Exception& e) {
2101
PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args)
2103
char *documentName = nullptr;
2105
PyObject *single = Py_False;
2106
if (!PyArg_ParseTuple(args, "|siO!", &documentName, &resolve, &PyBool_Type, &single))
2110
std::vector<SelectionSingleton::SelObj> sel;
2111
sel = Selection().getSelection(documentName, toEnum(resolve), Base::asBoolean(single));
2113
std::set<App::DocumentObject*> noduplicates;
2114
std::vector<App::DocumentObject*> selectedObjects; // keep the order of selection
2116
for (const auto & it : sel) {
2117
if (noduplicates.insert(it.pObject).second) {
2118
selectedObjects.push_back(it.pObject);
2121
for (const auto & selectedObject : selectedObjects) {
2122
list.append(Py::asObject(selectedObject->getPyObject()));
2124
return Py::new_reference_to(list);
2126
catch (const Base::Exception& e) {
2130
catch (Py::Exception&) {
2135
PyObject *SelectionSingleton::sEnablePickedList(PyObject * /*self*/, PyObject *args)
2137
PyObject *enable = Py_True;
2138
if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &enable))
2141
Selection().enablePickedList(Base::asBoolean(enable));
2146
PyObject *SelectionSingleton::sSetPreselection(PyObject * /*self*/, PyObject *args, PyObject *kwd)
2149
const char* subname = nullptr;
2150
float x = 0, y = 0, z = 0;
2152
static const std::array<const char *, 7> kwlist{"obj", "subname", "x", "y", "z", "tp", nullptr};
2153
if (Base::Wrapped_ParseTupleAndKeywords(args, kwd, "O!|sfffi", kwlist, &(App::DocumentObjectPy::Type), &object,
2154
&subname, &x, &y, &z, &type)) {
2155
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
2156
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
2157
if (!docObj || !docObj->isAttachedToDocument()) {
2158
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
2162
Selection().setPreselect(docObj->getDocument()->getName(),
2163
docObj->getNameInDocument(),
2164
subname,x,y,z, static_cast<SelectionChanges::MsgSource>(type));
2168
PyErr_SetString(PyExc_ValueError, "type must be 'DocumentObject[,subname[,x,y,z]]'");
2173
PyObject *SelectionSingleton::sGetPreselection(PyObject * /*self*/, PyObject *args)
2175
if (!PyArg_ParseTuple(args, ""))
2178
const SelectionChanges& sel = Selection().getPreselection();
2179
SelectionObject obj(sel);
2181
return obj.getPyObject();
2184
PyObject *SelectionSingleton::sRemPreselection(PyObject * /*self*/, PyObject *args)
2186
if (!PyArg_ParseTuple(args, ""))
2189
Selection().rmvPreselect();
2194
PyObject *SelectionSingleton::sGetCompleteSelection(PyObject * /*self*/, PyObject *args)
2197
if (!PyArg_ParseTuple(args, "|i",&resolve))
2201
std::vector<SelectionSingleton::SelObj> sel;
2202
sel = Selection().getCompleteSelection(toEnum(resolve));
2205
for (const auto & it : sel) {
2206
SelectionObject obj(SelectionChanges(SelectionChanges::AddSelection,
2212
list.append(Py::asObject(obj.getPyObject()));
2214
return Py::new_reference_to(list);
2216
catch (const Base::Exception& e) {
2220
catch (Py::Exception&) {
2225
PyObject *SelectionSingleton::sGetSelectionEx(PyObject * /*self*/, PyObject *args)
2227
char *documentName = nullptr;
2229
PyObject *single = Py_False;
2230
if (!PyArg_ParseTuple(args, "|siO!", &documentName, &resolve, &PyBool_Type, &single))
2234
std::vector<SelectionObject> sel;
2235
sel = Selection().getSelectionEx(documentName,
2236
App::DocumentObject::getClassTypeId(), toEnum(resolve), Base::asBoolean(single));
2239
for (auto & it : sel) {
2240
list.append(Py::asObject(it.getPyObject()));
2242
return Py::new_reference_to(list);
2244
catch (const Base::Exception& e) {
2248
catch (Py::Exception&) {
2253
PyObject *SelectionSingleton::sGetPickedList(PyObject * /*self*/, PyObject *args)
2255
char *documentName = nullptr;
2256
if (!PyArg_ParseTuple(args, "|s", &documentName))
2259
std::vector<SelectionObject> sel;
2260
sel = Selection().getPickedListEx(documentName);
2264
for (auto & it : sel) {
2265
list.append(Py::asObject(it.getPyObject()));
2267
return Py::new_reference_to(list);
2269
catch (Py::Exception&) {
2274
PyObject *SelectionSingleton::sGetSelectionObject(PyObject * /*self*/, PyObject *args)
2276
char *docName, *objName, *subName;
2277
PyObject* tuple = nullptr;
2278
if (!PyArg_ParseTuple(args, "sss|O!", &docName, &objName, &subName, &PyTuple_Type, &tuple))
2282
SelectionObject selObj;
2283
selObj.DocName = docName;
2284
selObj.FeatName = objName;
2285
std::string sub = subName;
2287
selObj.SubNames.push_back(sub);
2290
double x = (double)Py::Float(t.getItem(0));
2291
double y = (double)Py::Float(t.getItem(1));
2292
double z = (double)Py::Float(t.getItem(2));
2293
selObj.SelPoses.emplace_back(x,y,z);
2297
return selObj.getPyObject();
2299
catch (const Py::Exception&) {
2302
catch (const Base::Exception& e) {
2308
PyObject *SelectionSingleton::sSetSelectionStyle(PyObject * /*self*/, PyObject *args)
2311
if (!PyArg_ParseTuple(args, "i", &selStyle))
2315
Selection().setSelectionStyle(selStyle == 0 ? SelectionStyle::NormalSelection : SelectionStyle::GreedySelection);
2321
PyObject *SelectionSingleton::sAddSelObserver(PyObject * /*self*/, PyObject *args)
2325
if (!PyArg_ParseTuple(args, "O|i", &o, &resolve))
2329
SelectionObserverPython::addObserver(Py::Object(o), toEnum(resolve));
2335
PyObject *SelectionSingleton::sRemSelObserver(PyObject * /*self*/, PyObject *args)
2338
if (!PyArg_ParseTuple(args, "O", &o))
2342
SelectionObserverPython::removeObserver(Py::Object(o));
2348
PyObject *SelectionSingleton::sAddSelectionGate(PyObject * /*self*/, PyObject *args)
2352
if (PyArg_ParseTuple(args, "s|i", &filter, &resolve)) {
2354
Selection().addSelectionGate(new SelectionFilterGate(filter), toEnum(resolve));
2362
if (PyArg_ParseTuple(args, "O!|i",SelectionFilterPy::type_object(),&filterPy,resolve)) {
2364
Selection().addSelectionGate(new SelectionFilterGatePython(
2365
SelectionFilterPy::cast(filterPy)), toEnum(resolve));
2373
if (PyArg_ParseTuple(args, "O|i",&gate,&resolve)) {
2375
Selection().addSelectionGate(new SelectionGatePython(Py::Object(gate, false)), toEnum(resolve));
2381
PyErr_SetString(PyExc_ValueError, "Argument is neither string nor SelectionFiler nor SelectionGate");
2386
PyObject *SelectionSingleton::sRemoveSelectionGate(PyObject * /*self*/, PyObject *args)
2388
if (!PyArg_ParseTuple(args, ""))
2392
Selection().rmvSelectionGate();
2398
PyObject *SelectionSingleton::sSetVisible(PyObject * /*self*/, PyObject *args)
2400
PyObject *visible = Py_None;
2401
if (!PyArg_ParseTuple(args, "|O", &visible))
2405
VisibleState vis = VisToggle;
2406
Base::PyTypeCheck(&visible, &PyBool_Type);
2408
vis = PyObject_IsTrue(visible) ? VisShow : VisHide;
2410
Selection().setVisible(vis);
2416
PyObject *SelectionSingleton::sPushSelStack(PyObject * /*self*/, PyObject *args)
2418
PyObject *clear = Py_True;
2419
PyObject *overwrite = Py_False;
2420
if (!PyArg_ParseTuple(args, "|O!O!", &PyBool_Type, &clear, &PyBool_Type, &overwrite))
2423
Selection().selStackPush(Base::asBoolean(clear), Base::asBoolean(overwrite));
2428
PyObject *SelectionSingleton::sHasSelection(PyObject * /*self*/, PyObject *args)
2430
const char *doc = nullptr;
2432
if (!PyArg_ParseTuple(args, "|si", &doc, &resolve))
2437
if (doc || resolve > 0)
2438
ret = Selection().hasSelection(doc, toEnum(resolve));
2440
ret = Selection().hasSelection();
2442
return Py::new_reference_to(Py::Boolean(ret));
2447
PyObject *SelectionSingleton::sHasSubSelection(PyObject * /*self*/, PyObject *args)
2449
const char *doc = nullptr;
2450
PyObject *subElement = Py_False;
2451
if (!PyArg_ParseTuple(args, "|sO!",&doc,&PyBool_Type,&subElement))
2455
return Py::new_reference_to(
2456
Py::Boolean(Selection().hasSubSelection(doc, Base::asBoolean(subElement))));
2461
PyObject *SelectionSingleton::sGetSelectionFromStack(PyObject * /*self*/, PyObject *args)
2463
char *documentName = nullptr;
2466
if (!PyArg_ParseTuple(args, "|sii", &documentName, &resolve, &index))
2471
for(auto &sel : Selection().selStackGet(documentName, toEnum(resolve), index))
2472
list.append(Py::asObject(sel.getPyObject()));
2473
return Py::new_reference_to(list);