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"
27
# include <boost/algorithm/string/predicate.hpp>
28
# include <QApplication>
31
#include <App/Application.h>
32
#include <App/Document.h>
33
#include <App/DocumentObject.h>
34
#include <App/DocumentObjectPy.h>
35
#include <App/GeoFeature.h>
36
#include <Base/Console.h>
37
#include <Base/Exception.h>
38
#include <Base/Interpreter.h>
39
#include <Base/Tools.h>
40
#include <Base/PyWrapParseTupleAndKeywords.h>
41
#include <Base/UnitsApi.h>
44
#include "SelectionObject.h"
45
#include "Application.h"
48
#include "MainWindow.h"
50
#include "SelectionFilter.h"
51
#include "SelectionFilterPy.h"
52
#include "SelectionObserverPython.h"
54
#include "ViewProviderDocumentObject.h"
57
FC_LOG_LEVEL_INIT("Selection",false,true,true)
61
namespace sp = std::placeholders;
63
SelectionGateFilterExternal::SelectionGateFilterExternal(const char *docName, const char *objName) {
71
bool SelectionGateFilterExternal::allow(App::Document *doc ,App::DocumentObject *obj, const char*) {
74
if(!DocName.empty() && doc->getName()!=DocName)
75
notAllowedReason = "Cannot select external object";
76
else if(!ObjName.empty() && ObjName==obj->getNameInDocument())
77
notAllowedReason = "Cannot select self";
83
//////////////////////////////////////////////////////////////////////////////////////////
85
SelectionObserver::SelectionObserver(bool attach, ResolveMode resolve)
87
, blockedSelection(false)
93
SelectionObserver::SelectionObserver(const ViewProviderDocumentObject *vp, bool attach, ResolveMode resolve)
95
, blockedSelection(false)
97
if (vp && vp->getObject() && vp->getObject()->getDocument()) {
98
filterDocName = vp->getObject()->getDocument()->getName();
99
filterObjName = vp->getObject()->getNameInDocument();
106
SelectionObserver::~SelectionObserver()
111
bool SelectionObserver::blockSelection(bool block)
113
bool ok = blockedSelection;
114
blockedSelection = block;
118
bool SelectionObserver::isSelectionBlocked() const
120
return blockedSelection;
123
bool SelectionObserver::isSelectionAttached() const
125
return connectSelection.connected();
128
void SelectionObserver::attachSelection()
130
if (!connectSelection.connected()) {
131
bool newStyle = (resolve >= ResolveMode::NewStyleElement);
132
bool oldStyle = (resolve == ResolveMode::OldStyleElement);
133
auto &signal = newStyle ? Selection().signalSelectionChanged3 :
134
oldStyle ? Selection().signalSelectionChanged2 :
135
Selection().signalSelectionChanged ;
137
connectSelection = signal.connect(std::bind
138
(&SelectionObserver::_onSelectionChanged, this, sp::_1));
141
if (!filterDocName.empty()) {
142
Selection().addSelectionGate(
143
new SelectionGateFilterExternal(filterDocName.c_str(),filterObjName.c_str()));
148
void SelectionObserver::_onSelectionChanged(const SelectionChanges& msg) {
150
if (blockedSelection)
152
onSelectionChanged(msg);
153
} catch (Base::Exception &e) {
155
FC_ERR("Unhandled Base::Exception caught in selection observer: ");
156
} catch (std::exception &e) {
157
FC_ERR("Unhandled std::exception caught in selection observer: " << e.what());
159
FC_ERR("Unhandled unknown exception caught in selection observer");
163
void SelectionObserver::detachSelection()
165
if (connectSelection.connected()) {
166
connectSelection.disconnect();
167
if (!filterDocName.empty())
168
Selection().rmvSelectionGate();
172
// -------------------------------------------
174
bool SelectionSingleton::hasSelection() const
176
return !_SelList.empty();
179
bool SelectionSingleton::hasPreselection() const {
180
return !CurrentPreselection.Object.getObjectName().empty();
183
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getCompleteSelection(ResolveMode resolve) const
185
return getSelection("*", resolve);
188
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getSelection(const char* pDocName, ResolveMode resolve, bool single) const
190
std::vector<SelObj> temp;
195
App::Document *pcDoc = nullptr;
196
if(!pDocName || strcmp(pDocName,"*") != 0) {
197
pcDoc = getDocument(pDocName);
202
std::map<App::DocumentObject*,std::set<std::string> > objMap;
204
for(auto &sel : _SelList) {
207
const char *subelement = nullptr;
208
auto obj = getObjectOfType(sel, App::DocumentObject::getClassTypeId(), resolve, &subelement);
209
if (!obj || (pcDoc && sel.pObject->getDocument() != pcDoc))
212
// In case we are resolving objects, make sure no duplicates
213
if (resolve != ResolveMode::NoResolve && !objMap[obj].insert(std::string(subelement ? subelement : "")).second)
216
if (single && !temp.empty()) {
221
tempSelObj.DocName = obj->getDocument()->getName();
222
tempSelObj.FeatName = obj->getNameInDocument();
223
tempSelObj.SubName = subelement;
224
tempSelObj.TypeName = obj->getTypeId().getName();
225
tempSelObj.pObject = obj;
226
tempSelObj.pResolvedObject = sel.pResolvedObject;
227
tempSelObj.pDoc = obj->getDocument();
228
tempSelObj.x = sel.x;
229
tempSelObj.y = sel.y;
230
tempSelObj.z = sel.z;
232
temp.push_back(tempSelObj);
238
bool SelectionSingleton::hasSelection(const char* doc, ResolveMode resolve) const
240
App::Document *pcDoc = nullptr;
241
if (!doc || strcmp(doc,"*") != 0) {
242
pcDoc = getDocument(doc);
246
for(auto &sel : _SelList) {
249
auto obj = getObjectOfType(sel, App::DocumentObject::getClassTypeId(), resolve);
250
if (obj && (!pcDoc || sel.pObject->getDocument()==pcDoc)) {
258
bool SelectionSingleton::hasSubSelection(const char* doc, bool subElement) const
260
App::Document *pcDoc = nullptr;
261
if(!doc || strcmp(doc,"*")!=0) {
262
pcDoc = getDocument(doc);
266
for(auto &sel : _SelList) {
267
if(pcDoc && pcDoc != sel.pDoc)
269
if(sel.SubName.empty())
271
if(subElement && sel.SubName.back()!='.')
273
if(sel.pObject != sel.pResolvedObject)
280
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getPickedList(const char* pDocName) const
282
std::vector<SelObj> temp;
285
App::Document *pcDoc = nullptr;
286
if(!pDocName || strcmp(pDocName,"*") != 0) {
287
pcDoc = getDocument(pDocName);
292
for(std::list<_SelObj>::const_iterator It = _PickedList.begin();It != _PickedList.end();++It) {
293
if (!pcDoc || It->pDoc == pcDoc) {
294
tempSelObj.DocName = It->DocName.c_str();
295
tempSelObj.FeatName = It->FeatName.c_str();
296
tempSelObj.SubName = It->SubName.c_str();
297
tempSelObj.TypeName = It->TypeName.c_str();
298
tempSelObj.pObject = It->pObject;
299
tempSelObj.pResolvedObject = It->pResolvedObject;
300
tempSelObj.pDoc = It->pDoc;
301
tempSelObj.x = It->x;
302
tempSelObj.y = It->y;
303
tempSelObj.z = It->z;
304
temp.push_back(tempSelObj);
311
std::vector<SelectionObject> SelectionSingleton::getSelectionEx(const char* pDocName, Base::Type typeId,
312
ResolveMode resolve, bool single) const
314
return getObjectList(pDocName, typeId, _SelList, resolve, single);
317
std::vector<SelectionObject> SelectionSingleton::getPickedListEx(const char* pDocName, Base::Type typeId) const
319
return getObjectList(pDocName, typeId, _PickedList, ResolveMode::NoResolve);
322
std::vector<SelectionObject> SelectionSingleton::getObjectList(const char* pDocName, Base::Type typeId,
323
std::list<_SelObj> &objList,
324
ResolveMode resolve, bool single) const
326
std::vector<SelectionObject> temp;
329
std::map<App::DocumentObject*,size_t> SortMap;
332
if (typeId == Base::Type::badType())
335
App::Document *pcDoc = nullptr;
336
if (!pDocName || strcmp(pDocName,"*") != 0) {
337
pcDoc = getDocument(pDocName);
342
for (auto &sel : objList) {
345
const char *subelement = nullptr;
346
auto obj = getObjectOfType(sel,typeId,resolve,&subelement);
347
if (!obj || (pcDoc && sel.pObject->getDocument() != pcDoc))
349
auto it = SortMap.find(obj);
350
if(it!=SortMap.end()) {
351
// only add sub-element
352
if (subelement && *subelement) {
353
if (resolve != ResolveMode::NoResolve && !temp[it->second]._SubNameSet.insert(subelement).second)
355
temp[it->second].SubNames.emplace_back(subelement);
356
temp[it->second].SelPoses.emplace_back(sel.x,sel.y,sel.z);
360
if (single && !temp.empty()) {
364
// create a new entry
365
temp.emplace_back(obj);
366
if (subelement && *subelement) {
367
temp.back().SubNames.emplace_back(subelement);
368
temp.back().SelPoses.emplace_back(sel.x,sel.y,sel.z);
369
if (resolve != ResolveMode::NoResolve)
370
temp.back()._SubNameSet.insert(subelement);
372
SortMap.insert(std::make_pair(obj,temp.size()-1));
379
bool SelectionSingleton::needPickedList() const
381
return _needPickedList;
384
void SelectionSingleton::enablePickedList(bool enable)
386
if(enable != _needPickedList) {
387
_needPickedList = enable;
389
notify(SelectionChanges(SelectionChanges::PickedListChanged));
393
void SelectionSingleton::notify(SelectionChanges &&Chng)
396
NotificationQueue.push_back(std::move(Chng));
399
Base::FlagToggler<bool> flag(Notifying);
400
NotificationQueue.push_back(std::move(Chng));
401
while(!NotificationQueue.empty()) {
402
const auto &msg = NotificationQueue.front();
405
case SelectionChanges::AddSelection:
406
notify = isSelected(msg.pDocName, msg.pObjectName, msg.pSubName, ResolveMode::NoResolve);
408
case SelectionChanges::RmvSelection:
409
notify = !isSelected(msg.pDocName, msg.pObjectName, msg.pSubName, ResolveMode::NoResolve);
411
case SelectionChanges::SetPreselect:
412
notify = CurrentPreselection.Type==SelectionChanges::SetPreselect
413
&& CurrentPreselection.Object == msg.Object;
415
case SelectionChanges::RmvPreselect:
416
notify = CurrentPreselection.Type==SelectionChanges::ClrSelection;
424
signalSelectionChanged(msg);
426
catch (const boost::exception&) {
427
// reported by code analyzers
428
Base::Console().Warning("notify: Unexpected boost exception\n");
431
NotificationQueue.pop_front();
435
bool SelectionSingleton::hasPickedList() const
437
return !_PickedList.empty();
440
int SelectionSingleton::getAsPropertyLinkSubList(App::PropertyLinkSubList &prop) const
442
std::vector<Gui::SelectionObject> sel = this->getSelectionEx();
443
std::vector<App::DocumentObject*> objs; objs.reserve(sel.size() * 2);
444
std::vector<std::string> subs; subs.reserve(sel.size()*2);
445
for (auto & selitem : sel) {
446
App::DocumentObject* obj = selitem.getObject();
447
const std::vector<std::string> &subnames = selitem.getSubNames();
449
//whole object is selected
450
if (subnames.empty()){
455
for (const auto & subname : subnames) {
457
subs.push_back(subname);
461
assert(objs.size()==subs.size());
462
prop.setValues(objs, subs);
466
App::DocumentObject *SelectionSingleton::getObjectOfType(_SelObj &sel, Base::Type typeId,
467
ResolveMode resolve, const char **subelement)
469
auto obj = sel.pObject;
470
if(!obj || !obj->isAttachedToDocument())
472
const char *subname = sel.SubName.c_str();
473
if (resolve != ResolveMode::NoResolve) {
474
obj = sel.pResolvedObject;
475
if (resolve == ResolveMode::NewStyleElement && !sel.elementName.first.empty())
476
subname = sel.elementName.first.c_str();
478
subname = sel.elementName.second.c_str();
484
if (!obj->isDerivedFrom(typeId) && (resolve != ResolveMode::FollowLink || !obj->getLinkedObject(true)->isDerivedFrom(typeId)))
488
*subelement = subname;
493
vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Type& typeId, const char* pDocName, ResolveMode resolve) const
495
std::vector<App::DocumentObject*> temp;
497
App::Document *pcDoc = nullptr;
498
if (!pDocName || strcmp(pDocName,"*") != 0) {
499
pcDoc = getDocument(pDocName);
504
std::set<App::DocumentObject*> objs;
505
for(auto &sel : _SelList) {
506
if(pcDoc && pcDoc!=sel.pDoc) continue;
507
App::DocumentObject *pObject = getObjectOfType(sel, typeId, resolve);
509
auto ret = objs.insert(pObject);
511
temp.push_back(pObject);
518
std::vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const char* typeName, const char* pDocName, ResolveMode resolve) const
520
Base::Type typeId = Base::Type::fromName(typeName);
521
if (typeId == Base::Type::badType())
523
return getObjectsOfType(typeId, pDocName, resolve);
526
unsigned int SelectionSingleton::countObjectsOfType(const Base::Type& typeId, const char* pDocName, ResolveMode resolve) const
529
App::Document *pcDoc = nullptr;
530
if(!pDocName || strcmp(pDocName,"*") != 0) {
531
pcDoc = getDocument(pDocName);
536
for (auto &sel : _SelList) {
537
if((!pcDoc||pcDoc==sel.pDoc) && getObjectOfType(sel, typeId, resolve))
544
unsigned int SelectionSingleton::countObjectsOfType(const char* typeName, const char* pDocName, ResolveMode resolve) const
546
Base::Type typeId = Base::Type::fromName(typeName);
547
if (typeId == Base::Type::badType())
549
return countObjectsOfType(typeId, pDocName, resolve);
553
void SelectionSingleton::slotSelectionChanged(const SelectionChanges& msg)
555
if(msg.Type == SelectionChanges::SetPreselectSignal ||
556
msg.Type == SelectionChanges::ShowSelection ||
557
msg.Type == SelectionChanges::HideSelection)
560
if(!msg.Object.getSubName().empty()) {
561
auto pParent = msg.Object.getObject();
564
std::pair<std::string,std::string> elementName;
565
auto &newElementName = elementName.first;
566
auto &oldElementName = elementName.second;
567
auto pObject = App::GeoFeature::resolveElement(pParent,msg.pSubName,elementName);
570
SelectionChanges msg2(msg.Type,pObject->getDocument()->getName(),
571
pObject->getNameInDocument(),
572
!newElementName.empty()?newElementName.c_str():oldElementName.c_str(),
573
pObject->getTypeId().getName(), msg.x,msg.y,msg.z);
576
msg2.pOriginalMsg = &msg;
577
signalSelectionChanged3(msg2);
579
msg2.Object.setSubName(oldElementName.c_str());
580
msg2.pSubName = msg2.Object.getSubName().c_str();
581
signalSelectionChanged2(msg2);
583
catch (const boost::exception&) {
584
// reported by code analyzers
585
Base::Console().Warning("slotSelectionChanged: Unexpected boost exception\n");
590
signalSelectionChanged3(msg);
591
signalSelectionChanged2(msg);
593
catch (const boost::exception&) {
594
// reported by code analyzers
595
Base::Console().Warning("slotSelectionChanged: Unexpected boost exception\n");
600
int SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectName, const char* pSubName,
601
float x, float y, float z, SelectionChanges::MsgSource signal)
603
if (!pDocName || !pObjectName) {
607
if (!pSubName) pSubName = "";
609
if (DocName==pDocName && FeatName==pObjectName && SubName==pSubName) {
615
if (ActiveGate && signal != SelectionChanges::MsgSource::Internal) {
616
App::Document* pDoc = getDocument(pDocName);
617
if (!pDoc || !pObjectName)
619
std::pair<std::string,std::string> elementName;
620
auto pObject = pDoc->getObject(pObjectName);
624
const char *subelement = pSubName;
625
if (gateResolve != ResolveMode::NoResolve) {
626
auto &newElementName = elementName.first;
627
auto &oldElementName = elementName.second;
628
pObject = App::GeoFeature::resolveElement(pObject,pSubName,elementName);
631
if (gateResolve > ResolveMode::OldStyleElement)
632
subelement = !newElementName.empty() ? newElementName.c_str() : oldElementName.c_str();
634
subelement = oldElementName.c_str();
636
if (!ActiveGate->allow(pObject->getDocument(), pObject, subelement)) {
638
if (ActiveGate->notAllowedReason.length() > 0){
639
msg = QObject::tr(ActiveGate->notAllowedReason.c_str());
641
msg = QCoreApplication::translate("SelectionFilter","Not allowed:");
643
msg.append(QString::fromLatin1(" %1.%2.%3 ")
644
.arg(QString::fromLatin1(pDocName),
645
QString::fromLatin1(pObjectName),
646
QString::fromLatin1(pSubName)));
648
if (getMainWindow()) {
649
getMainWindow()->showMessage(msg);
650
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
651
mdi->setOverrideCursor(QCursor(Qt::ForbiddenCursor));
655
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
656
mdi->restoreOverrideCursor();
660
FeatName= pObjectName;
666
// set up the change object
667
SelectionChanges Chng(signal == SelectionChanges::MsgSource::Internal
668
? SelectionChanges::SetPreselectSignal
669
: SelectionChanges::SetPreselect,
670
DocName,FeatName,SubName,std::string(),x,y,z,signal);
672
if (Chng.Type==SelectionChanges::SetPreselect) {
673
CurrentPreselection = Chng;
674
FC_TRACE("preselect "<<DocName<<'#'<<FeatName<<'.'<<SubName);
677
FC_TRACE("preselect signal "<<DocName<<'#'<<FeatName<<'.'<<SubName);
682
if (signal == SelectionChanges::MsgSource::Internal && !DocName.empty()) {
683
FC_TRACE("preselect "<<DocName<<'#'<<FeatName<<'.'<<SubName);
684
Chng.Type = SelectionChanges::SetPreselect;
685
CurrentPreselection = Chng;
686
notify(std::move(Chng));
689
// It is possible the preselect is removed during notification
690
return DocName.empty()?0:1;
694
std::array<std::pair<double, std::string>, 3> schemaTranslatePoint(double x, double y, double z, double precision)
696
Base::Quantity mmx(Base::Quantity::MilliMetre);
697
mmx.setValue(fabs(x) > precision ? x : 0.0);
698
Base::Quantity mmy(Base::Quantity::MilliMetre);
699
mmy.setValue(fabs(y) > precision ? y : 0.0);
700
Base::Quantity mmz(Base::Quantity::MilliMetre);
701
mmz.setValue(fabs(z) > precision ? z : 0.0);
703
double xfactor, yfactor, zfactor;
704
QString xunit, yunit, zunit;
706
Base::UnitsApi::schemaTranslate(mmx, xfactor, xunit);
707
Base::UnitsApi::schemaTranslate(mmy, yfactor, yunit);
708
Base::UnitsApi::schemaTranslate(mmz, zfactor, zunit);
710
double xuser = fabs(x) > precision ? x / xfactor : 0.0;
711
double yuser = fabs(y) > precision ? y / yfactor : 0.0;
712
double zuser = fabs(z) > precision ? z / zfactor : 0.0;
714
std::array<std::pair<double, std::string>, 3> ret = {std::make_pair(xuser, xunit.toUtf8().constBegin()),
715
std::make_pair(yuser, yunit.toUtf8().constBegin()),
716
std::make_pair(zuser, zunit.toUtf8().constBegin())};
720
QString getPreselectionInfo(const char* documentName,
721
const char* objectName,
722
const char* subElementName,
723
float x, float y, float z,
726
auto pts = schemaTranslatePoint(x, y, z, precision);
728
int numberDecimals = std::min(6, Base::UnitsApi::getDecimals());
730
QString message = QStringLiteral("Preselected: %1.%2.%3 (%4 %5, %6 %7, %8 %9)")
731
.arg(QString::fromUtf8(documentName))
732
.arg(QString::fromUtf8(objectName))
733
.arg(QString::fromUtf8(subElementName))
734
.arg(QString::number(pts[0].first, 'f', numberDecimals))
735
.arg(QString::fromStdString(pts[0].second))
736
.arg(QString::number(pts[1].first, 'f', numberDecimals))
737
.arg(QString::fromStdString(pts[1].second))
738
.arg(QString::number(pts[2].first, 'f', numberDecimals))
739
.arg(QString::fromStdString(pts[2].second));
743
void printPreselectionInfo(const char* documentName,
744
const char* objectName,
745
const char* subElementName,
746
float x, float y, float z,
749
if (getMainWindow()) {
750
QString message = getPreselectionInfo(documentName,
754
getMainWindow()->showMessage(message);
759
void SelectionSingleton::setPreselectCoord( float x, float y, float z)
761
// if nothing is in preselect ignore
762
if(CurrentPreselection.Object.getObjectName().empty())
765
CurrentPreselection.x = x;
766
CurrentPreselection.y = y;
767
CurrentPreselection.z = z;
769
printPreselectionInfo(CurrentPreselection.pDocName,
770
CurrentPreselection.pObjectName,
771
CurrentPreselection.pSubName,
775
void SelectionSingleton::rmvPreselect(bool signal)
781
SelectionChanges Chng(SelectionChanges::RmvPreselectSignal,DocName,FeatName,SubName);
782
notify(std::move(Chng));
786
SelectionChanges Chng(SelectionChanges::RmvPreselect,DocName,FeatName,SubName);
788
// reset the current preselection
789
CurrentPreselection = SelectionChanges();
798
if (ActiveGate && getMainWindow()) {
799
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
800
mdi->restoreOverrideCursor();
803
FC_TRACE("rmv preselect");
805
// notify observing objects
806
notify(std::move(Chng));
809
const SelectionChanges &SelectionSingleton::getPreselection() const
811
return CurrentPreselection;
814
// add a SelectionGate to control what is selectable
815
void SelectionSingleton::addSelectionGate(Gui::SelectionGate *gate, ResolveMode resolve)
821
gateResolve = resolve;
824
// remove the active SelectionGate
825
void SelectionSingleton::rmvSelectionGate()
829
ActiveGate = nullptr;
831
Gui::Document* doc = Gui::Application::Instance->activeDocument();
833
// if a document is about to be closed it has no MDI view any more
834
Gui::MDIView* mdi = doc->getActiveView();
836
mdi->restoreOverrideCursor();
842
App::Document* SelectionSingleton::getDocument(const char* pDocName) const
844
if (pDocName && pDocName[0])
845
return App::GetApplication().getDocument(pDocName);
847
return App::GetApplication().getActiveDocument();
850
int SelectionSingleton::disableCommandLog() {
852
logHasSelection = hasSelection();
853
return ++logDisabled;
856
int SelectionSingleton::enableCommandLog(bool silent) {
858
if(!logDisabled && !silent) {
859
auto manager = Application::Instance->macroManager();
860
if(!hasSelection()) {
862
manager->addLine(MacroManager::Cmt, "Gui.Selection.clearSelection()");
864
for(auto &sel : _SelList)
871
void SelectionSingleton::_SelObj::log(bool remove, bool clearPreselect) {
872
if(logged && !remove)
875
std::ostringstream ss;
876
ss << "Gui.Selection." << (remove?"removeSelection":"addSelection")
877
<< "('" << DocName << "','" << FeatName << "'";
878
if(!SubName.empty()) {
879
if(!elementName.second.empty() && !elementName.first.empty())
880
ss << ",'" << SubName.substr(0,SubName.size()-elementName.first.size())
881
<< elementName.second << "'";
883
ss << ",'" << SubName << "'";
885
if(!remove && (x || y || z || !clearPreselect)) {
888
ss << ',' << x << ',' << y << ',' << z;
893
Application::Instance->macroManager()->addLine(MacroManager::Cmt, ss.str().c_str());
896
bool SelectionSingleton::addSelection(const char* pDocName, const char* pObjectName,
897
const char* pSubName, float x, float y, float z,
898
const std::vector<SelObj> *pickedList, bool clearPreselect)
902
for(const auto &sel : *pickedList) {
903
_PickedList.emplace_back();
904
auto &s = _PickedList.back();
905
s.DocName = sel.DocName;
906
s.FeatName = sel.FeatName;
907
s.SubName = sel.SubName;
908
s.TypeName = sel.TypeName;
909
s.pObject = sel.pObject;
915
notify(SelectionChanges(SelectionChanges::PickedListChanged));
919
int ret = checkSelection(pDocName, pObjectName, pSubName, ResolveMode::NoResolve, temp);
927
// check for a Selection Gate
929
const char *subelement = nullptr;
930
auto pObject = getObjectOfType(temp,App::DocumentObject::getClassTypeId(),gateResolve,&subelement);
931
if (!ActiveGate->allow(pObject?pObject->getDocument():temp.pDoc,pObject,subelement)) {
932
if (getMainWindow()) {
934
if (ActiveGate->notAllowedReason.length() > 0) {
935
msg = QObject::tr(ActiveGate->notAllowedReason.c_str());
937
msg = QCoreApplication::translate("SelectionFilter","Selection not allowed by filter");
939
getMainWindow()->showMessage(msg);
940
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
941
mdi->setOverrideCursor(Qt::ForbiddenCursor);
943
ActiveGate->notAllowedReason.clear();
944
QApplication::beep();
950
temp.log(false,clearPreselect);
952
_SelList.push_back(temp);
953
_SelStackForward.clear();
958
SelectionChanges Chng(SelectionChanges::AddSelection,
959
temp.DocName,temp.FeatName,temp.SubName,temp.TypeName, x,y,z);
961
FC_LOG("Add Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName
962
<< " (" << x << ", " << y << ", " << z << ')');
964
notify(std::move(Chng));
966
getMainWindow()->updateActions();
970
// There is a possibility that some observer removes or clears selection
971
// inside signal handler, hence the check here
972
return isSelected(temp.DocName.c_str(),temp.FeatName.c_str(), temp.SubName.c_str());
975
void SelectionSingleton::selStackPush(bool clearForward, bool overwrite) {
976
static int stackSize;
978
stackSize = App::GetApplication().GetParameterGroupByPath
979
("User parameter:BaseApp/Preferences/View")->GetInt("SelectionStackSize",100);
982
_SelStackForward.clear();
985
if((int)_SelStackBack.size() >= stackSize)
986
_SelStackBack.pop_front();
988
for(auto &sel : _SelList)
989
item.emplace(sel.DocName.c_str(),sel.FeatName.c_str(),sel.SubName.c_str());
990
if(!_SelStackBack.empty() && _SelStackBack.back()==item)
992
if(!overwrite || _SelStackBack.empty())
993
_SelStackBack.emplace_back();
994
_SelStackBack.back() = std::move(item);
997
void SelectionSingleton::selStackGoBack(int count) {
998
if((int)_SelStackBack.size()<count)
999
count = _SelStackBack.size();
1002
if(!_SelList.empty()) {
1003
selStackPush(false,true);
1004
clearCompleteSelection();
1007
for(int i=0;i<count;++i) {
1008
_SelStackForward.push_front(std::move(_SelStackBack.back()));
1009
_SelStackBack.pop_back();
1011
std::deque<SelStackItem> tmpStack;
1012
_SelStackForward.swap(tmpStack);
1013
while(!_SelStackBack.empty()) {
1015
for(auto &sobjT : _SelStackBack.back()) {
1016
if(sobjT.getSubObject()) {
1017
addSelection(sobjT.getDocumentName().c_str(),
1018
sobjT.getObjectName().c_str(),
1019
sobjT.getSubName().c_str());
1025
tmpStack.push_front(std::move(_SelStackBack.back()));
1026
_SelStackBack.pop_back();
1028
_SelStackForward = std::move(tmpStack);
1029
getMainWindow()->updateActions();
1032
void SelectionSingleton::selStackGoForward(int count) {
1033
if((int)_SelStackForward.size()<count)
1034
count = _SelStackForward.size();
1037
if(!_SelList.empty()) {
1038
selStackPush(false,true);
1039
clearCompleteSelection();
1041
for(int i=0;i<count;++i) {
1042
_SelStackBack.push_back(_SelStackForward.front());
1043
_SelStackForward.pop_front();
1045
std::deque<SelStackItem> tmpStack;
1046
_SelStackForward.swap(tmpStack);
1049
for(auto &sobjT : _SelStackBack.back()) {
1050
if(sobjT.getSubObject()) {
1051
addSelection(sobjT.getDocumentName().c_str(),
1052
sobjT.getObjectName().c_str(),
1053
sobjT.getSubName().c_str());
1057
if(found || tmpStack.empty())
1059
_SelStackBack.push_back(tmpStack.front());
1060
tmpStack.pop_front();
1062
_SelStackForward = std::move(tmpStack);
1063
getMainWindow()->updateActions();
1066
std::vector<SelectionObject> SelectionSingleton::selStackGet(const char* pDocName, ResolveMode resolve, int index) const
1068
const SelStackItem *item = nullptr;
1070
if(index >= (int)_SelStackBack.size())
1072
item = &_SelStackBack[_SelStackBack.size()-1-index];
1076
if(index>=(int)_SelStackForward.size())
1078
item = &_SelStackBack[_SelStackForward.size()-1-index];
1081
std::list<_SelObj> selList;
1082
for(auto &sobjT : *item) {
1084
if(checkSelection(sobjT.getDocumentName().c_str(),
1085
sobjT.getObjectName().c_str(),
1086
sobjT.getSubName().c_str(),
1087
ResolveMode::NoResolve,
1091
selList.push_back(sel);
1095
return getObjectList(pDocName,App::DocumentObject::getClassTypeId(), selList, resolve);
1098
bool SelectionSingleton::addSelections(const char* pDocName, const char* pObjectName, const std::vector<std::string>& pSubNames)
1100
if(!_PickedList.empty()) {
1101
_PickedList.clear();
1102
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1105
bool update = false;
1106
for(const auto & pSubName : pSubNames) {
1108
int ret = checkSelection(pDocName, pObjectName, pSubName.c_str(), ResolveMode::NoResolve, temp);
1116
_SelList.push_back(temp);
1117
_SelStackForward.clear();
1119
SelectionChanges Chng(SelectionChanges::AddSelection,
1120
temp.DocName,temp.FeatName,temp.SubName,temp.TypeName);
1122
FC_LOG("Add Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName);
1124
notify(std::move(Chng));
1129
getMainWindow()->updateActions();
1133
bool SelectionSingleton::updateSelection(bool show, const char* pDocName,
1134
const char* pObjectName, const char* pSubName)
1136
if(!pDocName || !pObjectName)
1140
if(DocName==pDocName && FeatName==pObjectName && SubName==pSubName) {
1142
FC_TRACE("preselect signal");
1143
notify(SelectionChanges(SelectionChanges::SetPreselectSignal,DocName,FeatName,SubName));
1147
auto pDoc = getDocument(pDocName);
1150
auto pObject = pDoc->getObject(pObjectName);
1153
if (!isSelected(pObject, pSubName, ResolveMode::NoResolve))
1156
SelectionChanges Chng(show?SelectionChanges::ShowSelection:SelectionChanges::HideSelection,
1157
pDocName,pObjectName,pSubName,pObject->getTypeId().getName());
1159
FC_LOG("Update Selection "<<Chng.pDocName << '#' << Chng.pObjectName << '.' <<Chng.pSubName);
1161
notify(std::move(Chng));
1166
bool SelectionSingleton::addSelection(const SelectionObject& obj, bool clearPreselect)
1168
const std::vector<std::string>& subNames = obj.getSubNames();
1169
const std::vector<Base::Vector3d> points = obj.getPickedPoints();
1170
if (!subNames.empty() && subNames.size() == points.size()) {
1172
for (std::size_t i=0; i<subNames.size(); i++) {
1173
const std::string& name = subNames[i];
1174
const Base::Vector3d& pnt = points[i];
1175
ok &= addSelection(obj.getDocName(), obj.getFeatName(), name.c_str(),
1176
static_cast<float>(pnt.x),
1177
static_cast<float>(pnt.y),
1178
static_cast<float>(pnt.z),nullptr,clearPreselect);
1182
else if (!subNames.empty()) {
1184
for (const std::string& name : subNames) {
1185
ok &= addSelection(obj.getDocName(), obj.getFeatName(), name.c_str());
1190
return addSelection(obj.getDocName(), obj.getFeatName());
1195
void SelectionSingleton::rmvSelection(const char* pDocName, const char* pObjectName, const char* pSubName,
1196
const std::vector<SelObj> *pickedList)
1199
_PickedList.clear();
1200
for(const auto &sel : *pickedList) {
1201
_PickedList.emplace_back();
1202
auto &s = _PickedList.back();
1203
s.DocName = sel.DocName;
1204
s.FeatName = sel.FeatName;
1205
s.SubName = sel.SubName;
1206
s.TypeName = sel.TypeName;
1207
s.pObject = sel.pObject;
1213
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1220
int ret = checkSelection(pDocName, pObjectName, pSubName, ResolveMode::NoResolve, temp);
1224
std::vector<SelectionChanges> changes;
1225
for(auto It=_SelList.begin(),ItNext=It;It!=_SelList.end();It=ItNext) {
1227
if(It->DocName!=temp.DocName || It->FeatName!=temp.FeatName)
1229
// if no subname is specified, remove all subobjects of the matching object
1230
if(!temp.SubName.empty()) {
1231
// otherwise, match subojects with common prefix, separated by '.'
1232
if(!boost::starts_with(It->SubName,temp.SubName) ||
1233
(It->SubName.length()!=temp.SubName.length() && It->SubName[temp.SubName.length()-1]!='.'))
1239
changes.emplace_back(SelectionChanges::RmvSelection,
1240
It->DocName,It->FeatName,It->SubName,It->TypeName);
1242
// destroy the _SelObj item
1246
// NOTE: It can happen that there are nested calls of rmvSelection()
1247
// so that it's not safe to invoke the notifications inside the loop
1248
// as this can invalidate the iterators and thus leads to undefined
1250
// So, the notification is done after the loop, see also #0003469
1251
if(!changes.empty()) {
1252
for(auto &Chng : changes) {
1253
FC_LOG("Rmv Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName);
1254
notify(std::move(Chng));
1256
getMainWindow()->updateActions();
1261
std::string DocName;
1262
std::string FeatName;
1263
std::string SubName;
1264
SelInfo(const std::string &docName,
1265
const std::string &featName,
1266
const std::string &subName)
1273
void SelectionSingleton::setVisible(VisibleState vis) {
1274
std::set<std::pair<App::DocumentObject*,App::DocumentObject*> > filter;
1287
// Copy the selection in case it changes during this function
1288
std::vector<SelInfo> sels;
1289
sels.reserve(_SelList.size());
1290
for(auto &sel : _SelList) {
1291
if(sel.DocName.empty() || sel.FeatName.empty() || !sel.pObject)
1293
sels.emplace_back(sel.DocName,sel.FeatName,sel.SubName);
1296
for(auto &sel : sels) {
1297
App::Document *doc = App::GetApplication().getDocument(sel.DocName.c_str());
1299
App::DocumentObject *obj = doc->getObject(sel.FeatName.c_str());
1302
// get parent object
1303
App::DocumentObject *parent = nullptr;
1304
std::string elementName;
1305
obj = obj->resolve(sel.SubName.c_str(),&parent,&elementName);
1306
if (!obj || !obj->isAttachedToDocument() || (parent && !parent->isAttachedToDocument()))
1308
// try call parent object's setElementVisible
1310
// prevent setting the same object visibility more than once
1311
if (!filter.insert(std::make_pair(obj,parent)).second)
1313
int visElement = parent->isElementVisible(elementName.c_str());
1314
if (visElement >= 0) {
1318
if (visElement == visible)
1320
visElement = visible;
1323
visElement = !visElement;
1327
updateSelection(false,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1328
parent->setElementVisible(elementName.c_str(), visElement ? true : false);
1330
updateSelection(true,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1334
// Fall back to direct object visibility setting
1336
if(!filter.insert(std::make_pair(obj,static_cast<App::DocumentObject*>(nullptr))).second){
1340
auto vp = Application::Instance->getViewProvider(obj);
1345
visObject = visible ? true : false;
1347
visObject = !vp->isShow();
1351
updateSelection(visObject,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1353
updateSelection(visObject,sel.DocName.c_str(),sel.FeatName.c_str(), sel.SubName.c_str());
1360
void SelectionSingleton::setSelection(const char* pDocName, const std::vector<App::DocumentObject*>& sel)
1362
App::Document *pcDoc;
1363
pcDoc = getDocument(pDocName);
1367
if(!_PickedList.empty()) {
1368
_PickedList.clear();
1369
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1372
bool touched = false;
1373
for(auto obj : sel) {
1374
if(!obj || !obj->isAttachedToDocument())
1377
int ret = checkSelection(pDocName,obj->getNameInDocument(), nullptr, ResolveMode::NoResolve, temp);
1381
_SelList.push_back(temp);
1385
_SelStackForward.clear();
1386
notify(SelectionChanges(SelectionChanges::SetSelection, pDocName));
1387
getMainWindow()->updateActions();
1391
void SelectionSingleton::clearSelection(const char* pDocName, bool clearPreSelect)
1393
// Because the introduction of external editing, it is best to make
1394
// clearSelection(0) behave as clearCompleteSelection(), which is the same
1395
// behavior of python Selection.clearSelection(None)
1396
if (!pDocName || !pDocName[0] || strcmp(pDocName,"*")==0) {
1397
clearCompleteSelection(clearPreSelect);
1401
if (!_PickedList.empty()) {
1402
_PickedList.clear();
1403
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1406
App::Document* pDoc;
1407
pDoc = getDocument(pDocName);
1409
std::string docName = pDocName;
1410
if (clearPreSelect && DocName == docName)
1413
bool touched = false;
1414
for (auto it=_SelList.begin();it!=_SelList.end();) {
1415
if (it->DocName == docName) {
1417
it = _SelList.erase(it);
1428
std::ostringstream ss;
1429
ss << "Gui.Selection.clearSelection('" << docName << "'";
1430
if (!clearPreSelect)
1433
Application::Instance->macroManager()->addLine(MacroManager::Cmt,ss.str().c_str());
1436
notify(SelectionChanges(SelectionChanges::ClrSelection,docName.c_str()));
1438
getMainWindow()->updateActions();
1442
void SelectionSingleton::clearCompleteSelection(bool clearPreSelect)
1444
if(!_PickedList.empty()) {
1445
_PickedList.clear();
1446
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1452
if(_SelList.empty())
1456
Application::Instance->macroManager()->addLine(MacroManager::Cmt,
1457
clearPreSelect?"Gui.Selection.clearSelection()"
1458
:"Gui.Selection.clearSelection(False)");
1462
SelectionChanges Chng(SelectionChanges::ClrSelection);
1464
FC_LOG("Clear selection");
1466
notify(std::move(Chng));
1467
getMainWindow()->updateActions();
1470
bool SelectionSingleton::isSelected(const char* pDocName, const char* pObjectName,
1471
const char* pSubName, ResolveMode resolve) const
1474
return checkSelection(pDocName, pObjectName, pSubName, resolve, sel, &_SelList) > 0;
1477
bool SelectionSingleton::isSelected(App::DocumentObject* pObject, const char* pSubName, ResolveMode resolve) const
1479
if (!pObject || !pObject->isAttachedToDocument() || !pObject->getDocument())
1482
return checkSelection(pObject->getDocument()->getName(),
1483
pObject->getNameInDocument(), pSubName, resolve, sel, &_SelList) > 0;
1486
int SelectionSingleton::checkSelection(const char *pDocName, const char *pObjectName, const char *pSubName,
1487
ResolveMode resolve, _SelObj &sel, const std::list<_SelObj> *selList) const
1489
sel.pDoc = getDocument(pDocName);
1492
FC_ERR("Cannot find document");
1495
pDocName = sel.pDoc->getName();
1496
sel.DocName = pDocName;
1499
sel.pObject = sel.pDoc->getObject(pObjectName);
1501
sel.pObject = nullptr;
1504
FC_ERR("Object not found");
1507
if (sel.pObject->testStatus(App::ObjectStatus::Remove))
1510
sel.SubName = pSubName;
1511
if (resolve == ResolveMode::NoResolve)
1512
TreeWidget::checkTopParent(sel.pObject,sel.SubName);
1513
pSubName = !sel.SubName.empty()?sel.SubName.c_str():nullptr;
1514
sel.FeatName = sel.pObject->getNameInDocument();
1515
sel.TypeName = sel.pObject->getTypeId().getName();
1516
const char *element = nullptr;
1517
sel.pResolvedObject = App::GeoFeature::resolveElement(sel.pObject,
1518
pSubName,sel.elementName,false,App::GeoFeature::Normal,nullptr,&element);
1519
if(!sel.pResolvedObject) {
1521
FC_ERR("Sub-object " << sel.DocName << '#' << sel.FeatName << '.' << sel.SubName << " not found");
1524
if(sel.pResolvedObject->testStatus(App::ObjectStatus::Remove))
1526
std::string subname;
1528
if(pSubName && element) {
1529
prefix = std::string(pSubName, element-pSubName);
1530
if(!sel.elementName.first.empty()) {
1531
// make sure the selected sub name is a new style if available
1532
subname = prefix + sel.elementName.first;
1533
pSubName = subname.c_str();
1534
sel.SubName = subname;
1538
selList = &_SelList;
1543
for (auto &s : *selList) {
1544
if (s.DocName==pDocName && s.FeatName==sel.FeatName) {
1545
if(s.SubName==pSubName)
1547
if (resolve > ResolveMode::OldStyleElement && boost::starts_with(s.SubName,prefix))
1551
if (resolve == ResolveMode::OldStyleElement) {
1552
for(auto &s : *selList) {
1553
if(s.pResolvedObject != sel.pResolvedObject)
1557
if (!s.elementName.first.empty()) {
1558
if (s.elementName.first == sel.elementName.first)
1561
else if(s.SubName == sel.elementName.second)
1568
const char *SelectionSingleton::getSelectedElement(App::DocumentObject *obj, const char* pSubName) const
1573
for(list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
1574
if (It->pObject == obj) {
1575
auto len = It->SubName.length();
1578
if (pSubName && strncmp(pSubName,It->SubName.c_str(),It->SubName.length())==0){
1579
if(pSubName[len]==0 || pSubName[len-1] == '.')
1580
return It->SubName.c_str();
1587
void SelectionSingleton::slotDeletedObject(const App::DocumentObject& Obj)
1589
if(!Obj.isAttachedToDocument())
1592
// For safety reason, don't bother checking
1595
// Remove also from the selection, if selected
1596
// We don't walk down the hierarchy for each selection, so there may be stray selection
1597
std::vector<SelectionChanges> changes;
1598
for(auto it=_SelList.begin(),itNext=it;it!=_SelList.end();it=itNext) {
1600
if(it->pResolvedObject == &Obj || it->pObject==&Obj) {
1601
changes.emplace_back(SelectionChanges::RmvSelection,
1602
it->DocName,it->FeatName,it->SubName,it->TypeName);
1606
if(!changes.empty()) {
1607
for(auto &Chng : changes) {
1608
FC_LOG("Rmv Selection "<<Chng.pDocName<<'#'<<Chng.pObjectName<<'.'<<Chng.pSubName);
1609
notify(std::move(Chng));
1611
getMainWindow()->updateActions();
1614
if(!_PickedList.empty()) {
1615
bool changed = false;
1616
for(auto it=_PickedList.begin(),itNext=it;it!=_PickedList.end();it=itNext) {
1619
if(sel.DocName == Obj.getDocument()->getName() &&
1620
sel.FeatName == Obj.getNameInDocument())
1623
_PickedList.erase(it);
1627
notify(SelectionChanges(SelectionChanges::PickedListChanged));
1631
void SelectionSingleton::setSelectionStyle(SelectionStyle selStyle)
1633
selectionStyle = selStyle;
1636
SelectionSingleton::SelectionStyle SelectionSingleton::getSelectionStyle()
1638
return selectionStyle;
1641
//**************************************************************************
1642
// Construction/Destruction
1646
* A more elaborate description of the constructor.
1648
SelectionSingleton::SelectionSingleton() :
1649
CurrentPreselection(SelectionChanges::ClrSelection),
1650
selectionStyle(SelectionStyle::NormalSelection)
1655
ActiveGate = nullptr;
1656
gateResolve = ResolveMode::OldStyleElement;
1658
App::GetApplication().signalDeletedObject.connect(std::bind(&Gui::SelectionSingleton::slotDeletedObject, this, sp::_1));
1659
signalSelectionChanged.connect(std::bind(&Gui::SelectionSingleton::slotSelectionChanged, this, sp::_1));
1665
* A more elaborate description of the destructor.
1667
SelectionSingleton::~SelectionSingleton() = default;
1669
SelectionSingleton* SelectionSingleton::_pcSingleton = nullptr;
1671
SelectionSingleton& SelectionSingleton::instance()
1674
_pcSingleton = new SelectionSingleton;
1675
return *_pcSingleton;
1678
void SelectionSingleton::destruct ()
1681
delete _pcSingleton;
1682
_pcSingleton = nullptr;
1685
//**************************************************************************
1688
// SelectionSingleton Methods // Methods structure
1689
PyMethodDef SelectionSingleton::Methods[] = {
1690
{"addSelection", (PyCFunction) SelectionSingleton::sAddSelection, METH_VARARGS,
1691
"addSelection(docName, objName, subName, x=0, y=0, z=0, clear=True) -> None\n"
1692
"addSelection(obj, subName, x=0, y=0, z=0, clear=True) -> None\n"
1693
"addSelection(obj, subNames, clear=True) -> None\n"
1695
"Add an object to the selection.\n"
1697
"docName : str\n Name of the `App.Document`.\n"
1698
"objName : str\n Name of the `App.DocumentObject` to add.\n"
1699
"obj : App.DocumentObject\n Object to add.\n"
1700
"subName : str\n Subelement name.\n"
1701
"x : float\n Coordinate `x` of the point to pick.\n"
1702
"y : float\n Coordinate `y` of the point to pick.\n"
1703
"z : float\n Coordinate `z` of the point to pick.\n"
1704
"subNames : list of str\n List of subelement names.\n"
1705
"clear : bool\n Clear preselection."},
1706
{"updateSelection", (PyCFunction) SelectionSingleton::sUpdateSelection, METH_VARARGS,
1707
"updateSelection(show, obj, subName) -> None\n"
1709
"Update an object in the selection.\n"
1711
"show : bool\n Show or hide the selection.\n"
1712
"obj : App.DocumentObject\n Object to update.\n"
1713
"subName : str\n Name of the subelement to update."},
1714
{"removeSelection", (PyCFunction) SelectionSingleton::sRemoveSelection, METH_VARARGS,
1715
"removeSelection(obj, subName) -> None\n"
1716
"removeSelection(docName, objName, subName) -> None\n"
1718
"Remove an object from the selection.\n"
1720
"docName : str\n Name of the `App.Document`.\n"
1721
"objName : str\n Name of the `App.DocumentObject` to remove.\n"
1722
"obj : App.DocumentObject\n Object to remove.\n"
1723
"subName : str\n Name of the subelement to remove."},
1724
{"clearSelection" , (PyCFunction) SelectionSingleton::sClearSelection, METH_VARARGS,
1725
"clearSelection(docName, clearPreSelect=True) -> None\n"
1726
"clearSelection(clearPreSelect=True) -> None\n"
1728
"Clear the selection in the given document. If no document is\n"
1729
"given the complete selection is cleared.\n"
1731
"docName : str\n Name of the `App.Document`.\n"
1732
"clearPreSelect : bool\n Clear preselection."},
1733
{"isSelected", (PyCFunction) SelectionSingleton::sIsSelected, METH_VARARGS,
1734
"isSelected(obj, subName, resolve=ResolveMode.OldStyleElement) -> bool\n"
1736
"Check if a given object is selected.\n"
1738
"obj : App.DocumentObject\n Object to check.\n"
1739
"subName : str\n Name of the subelement.\n"
1740
"resolve : int\n Resolve subelement reference."},
1741
{"setPreselection", reinterpret_cast<PyCFunction>(reinterpret_cast<void (*) ()>( SelectionSingleton::sSetPreselection )), METH_VARARGS|METH_KEYWORDS,
1742
"setPreselection(obj, subName, x=0, y=0, z=0, type=1) -> None\n"
1744
"Set preselected object.\n"
1746
"obj : App.DocumentObject\n Object to preselect.\n"
1747
"subName : str\n Subelement name.\n"
1748
"x : float\n Coordinate `x` of the point to preselect.\n"
1749
"y : float\n Coordinate `y` of the point to preselect.\n"
1750
"z : float\n Coordinate `z` of the point to preselect.\n"
1752
{"getPreselection", (PyCFunction) SelectionSingleton::sGetPreselection, METH_VARARGS,
1753
"getPreselection() -> Gui.SelectionObject\n"
1755
"Get preselected object."},
1756
{"clearPreselection", (PyCFunction) SelectionSingleton::sRemPreselection, METH_VARARGS,
1757
"clearPreselection() -> None\n"
1759
"Clear the preselection."},
1760
{"countObjectsOfType", (PyCFunction) SelectionSingleton::sCountObjectsOfType, METH_VARARGS,
1761
"countObjectsOfType(type, docName, resolve=ResolveMode.OldStyleElement) -> int\n"
1763
"Get the number of selected objects. If no document name is given the\n"
1764
"active document is used and '*' means all documents.\n"
1766
"type : str\n Object type id name.\n"
1767
"docName : str\n Name of the `App.Document`.\n"
1769
{"getSelection", (PyCFunction) SelectionSingleton::sGetSelection, METH_VARARGS,
1770
"getSelection(docName, resolve=ResolveMode.OldStyleElement, single=False) -> list\n"
1772
"Return a list of selected objects. If no document name is given\n"
1773
"the active document is used and '*' means all documents.\n"
1775
"docName : str\n Name of the `App.Document`.\n"
1776
"resolve : int\n Resolve the subname references.\n"
1777
" 0: do not resolve, 1: resolve, 2: resolve with element map.\n"
1778
"single : bool\n Only return if there is only one selection."},
1779
{"getPickedList", (PyCFunction) SelectionSingleton::sGetPickedList, 1,
1780
"getPickedList(docName) -> list of Gui.SelectionObject\n"
1782
"Return a list of SelectionObjects generated by the last mouse click.\n"
1783
"If no document name is given the active document is used and '*'\n"
1784
"means all documents.\n"
1786
"docName : str\n Name of the `App.Document`."},
1787
{"enablePickedList", (PyCFunction) SelectionSingleton::sEnablePickedList, METH_VARARGS,
1788
"enablePickedList(enable=True) -> None\n"
1790
"Enable/disable pick list.\n"
1793
{"getCompleteSelection", (PyCFunction) SelectionSingleton::sGetCompleteSelection, METH_VARARGS,
1794
"getCompleteSelection(resolve=ResolveMode.OldStyleElement) -> list\n"
1796
"Return a list of selected objects across all documents.\n"
1799
{"getSelectionEx", (PyCFunction) SelectionSingleton::sGetSelectionEx, METH_VARARGS,
1800
"getSelectionEx(docName, resolve=ResolveMode.OldStyleElement, single=False) -> list of Gui.SelectionObject\n"
1802
"Return a list of SelectionObjects. If no document name is given the\n"
1803
"active document is used and '*' means all documents.\n"
1804
"The SelectionObjects contain a variety of information about the selection,\n"
1805
"e.g. subelement names.\n"
1807
"docName : str\n Name of the `App.Document`.\n"
1808
"resolve : int\n Resolve the subname references.\n"
1809
" 0: do not resolve, 1: resolve, 2: resolve with element map.\n"
1810
"single : bool\n Only return if there is only one selection."},
1811
{"getSelectionObject", (PyCFunction) SelectionSingleton::sGetSelectionObject, METH_VARARGS,
1812
"getSelectionObject(docName, objName, subName, point) -> Gui.SelectionObject\n"
1814
"Return a SelectionObject.\n"
1816
"docName : str\n Name of the `App.Document`.\n"
1817
"objName : str\n Name of the `App.DocumentObject` to select.\n"
1818
"subName : str\n Subelement name.\n"
1819
"point : tuple\n Coordinates of the point to pick."},
1820
{"setSelectionStyle", (PyCFunction) SelectionSingleton::sSetSelectionStyle, METH_VARARGS,
1821
"setSelectionStyle(selectionStyle) -> None\n"
1823
"Change the selection style. 0 for normal selection, 1 for greedy selection\n"
1825
"selectionStyle : int"},
1826
{"addObserver", (PyCFunction) SelectionSingleton::sAddSelObserver, METH_VARARGS,
1827
"addObserver(object, resolve=ResolveMode.OldStyleElement) -> None\n"
1829
"Install an observer.\n"
1831
"object : object\n Python object instance.\n"
1833
{"removeObserver", (PyCFunction) SelectionSingleton::sRemSelObserver, METH_VARARGS,
1834
"removeObserver(object) -> None\n"
1836
"Uninstall an observer.\n"
1838
"object : object\n Python object instance."},
1839
{"addSelectionGate", (PyCFunction) SelectionSingleton::sAddSelectionGate, METH_VARARGS,
1840
"addSelectionGate(filter, resolve=ResolveMode.OldStyleElement) -> None\n"
1842
"Activate the selection gate.\n"
1843
"The selection gate will prohibit all selections that do not match\n"
1844
"the given selection criteria.\n"
1846
"filter : str, SelectionFilter, object\n"
1849
"Examples strings are:\n"
1850
"Gui.Selection.addSelectionGate('SELECT Part::Feature SUBELEMENT Edge')\n"
1851
"Gui.Selection.addSelectionGate('SELECT Robot::RobotObject')\n"
1853
"An instance of SelectionFilter can also be set:\n"
1854
"filter = Gui.Selection.Filter('SELECT Part::Feature SUBELEMENT Edge')\n"
1855
"Gui.Selection.addSelectionGate(filter)\n"
1857
"The most flexible approach is to write a selection gate class that\n"
1858
"implements the method 'allow':\n"
1860
" def allow(self,doc,obj,sub):\n"
1861
" return (sub[0:4] == 'Face')\n"
1862
"Gui.Selection.addSelectionGate(Gate())"},
1863
{"removeSelectionGate", (PyCFunction) SelectionSingleton::sRemoveSelectionGate, METH_VARARGS,
1864
"removeSelectionGate() -> None\n"
1866
"Remove the active selection gate."},
1867
{"setVisible", (PyCFunction) SelectionSingleton::sSetVisible, METH_VARARGS,
1868
"setVisible(visible=None) -> None\n"
1870
"Set visibility of all selection items.\n"
1872
"visible : bool, None\n If None, then toggle visibility."},
1873
{"pushSelStack", (PyCFunction) SelectionSingleton::sPushSelStack, METH_VARARGS,
1874
"pushSelStack(clearForward=True, overwrite=False) -> None\n"
1876
"Push current selection to stack.\n"
1878
"clearForward : bool\n Clear the forward selection stack.\n"
1879
"overwrite : bool\n Overwrite the top back selection stack with current selection."},
1880
{"hasSelection", (PyCFunction) SelectionSingleton::sHasSelection, METH_VARARGS,
1881
"hasSelection(docName, resolve=ResolveMode.NoResolve) -> bool\n"
1883
"Check if there is any selection. If no document name is given,\n"
1884
"checks selections in all documents.\n"
1886
"docName : str\n Name of the `App.Document`.\n"
1888
{"hasSubSelection", (PyCFunction) SelectionSingleton::sHasSubSelection, METH_VARARGS,
1889
"hasSubSelection(docName, subElement=False) -> bool\n"
1891
"Check if there is any selection with subname. If no document name\n"
1892
"is given the active document is used and '*' means all documents.\n"
1894
"docName : str\n Name of the `App.Document`.\n"
1895
"subElement : bool"},
1896
{"getSelectionFromStack",(PyCFunction) SelectionSingleton::sGetSelectionFromStack, METH_VARARGS,
1897
"getSelectionFromStack(docName, resolve=ResolveMode.OldStyleElement, index=0) -> list of Gui.SelectionObject\n"
1899
"Return SelectionObjects from selection stack. If no document name is given\n"
1900
"the active document is used and '*' means all documents.\n"
1902
"docName : str\n Name of the `App.Document`.\n"
1903
"resolve : int\n Resolve the subname references.\n"
1904
" 0: do not resolve, 1: resolve, 2: resolve with element map.\n"
1905
"index : int\n Select stack index.\n"
1906
" 0: last pushed selection, > 0: trace back, < 0: trace forward."},
1907
{nullptr, nullptr, 0, nullptr} /* Sentinel */
1910
PyObject *SelectionSingleton::sAddSelection(PyObject * /*self*/, PyObject *args)
1912
SelectionLogDisabler disabler(true);
1913
PyObject *clearPreselect = Py_True;
1916
char* subname = nullptr;
1917
float x = 0, y = 0, z = 0;
1918
if (PyArg_ParseTuple(args, "ss|sfffO!", &docname, &objname ,
1919
&subname,&x,&y,&z,&PyBool_Type,&clearPreselect)) {
1920
Selection().addSelection(docname, objname, subname, x, y, z, nullptr, Base::asBoolean(clearPreselect));
1927
x = 0, y = 0, z = 0;
1928
if (PyArg_ParseTuple(args, "O!|sfffO!", &(App::DocumentObjectPy::Type),&object,
1929
&subname,&x,&y,&z,&PyBool_Type,&clearPreselect)) {
1930
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
1931
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
1932
if (!docObj || !docObj->isAttachedToDocument()) {
1933
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
1937
Selection().addSelection(docObj->getDocument()->getName(),
1938
docObj->getNameInDocument(),
1939
subname, x, y, z, nullptr, Base::asBoolean(clearPreselect));
1945
if (PyArg_ParseTuple(args, "O!O|O!", &(App::DocumentObjectPy::Type),&object,
1946
&sequence,&PyBool_Type,&clearPreselect))
1948
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
1949
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
1950
if (!docObj || !docObj->isAttachedToDocument()) {
1951
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
1956
if (PyTuple_Check(sequence) || PyList_Check(sequence)) {
1957
Py::Sequence list(sequence);
1958
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
1959
std::string subname = static_cast<std::string>(Py::String(*it));
1960
Selection().addSelection(docObj->getDocument()->getName(),
1961
docObj->getNameInDocument(),
1962
subname.c_str(), 0, 0, 0, nullptr, Base::asBoolean(clearPreselect));
1967
catch (const Py::Exception&) {
1972
PyErr_SetString(PyExc_ValueError, "type must be 'DocumentObject[,subname[,x,y,z]]' or 'DocumentObject, list or tuple of subnames'");
1977
PyObject *SelectionSingleton::sUpdateSelection(PyObject * /*self*/, PyObject *args)
1981
char* subname=nullptr;
1982
if(!PyArg_ParseTuple(args, "O!O!|s", &PyBool_Type, &show, &(App::DocumentObjectPy::Type),
1986
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
1987
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
1988
if (!docObj || !docObj->isAttachedToDocument()) {
1989
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
1993
Selection().updateSelection(Base::asBoolean(show),
1994
docObj->getDocument()->getName(), docObj->getNameInDocument(), subname);
2000
PyObject *SelectionSingleton::sRemoveSelection(PyObject * /*self*/, PyObject *args)
2002
SelectionLogDisabler disabler(true);
2003
char *docname, *objname;
2004
char* subname = nullptr;
2005
if(PyArg_ParseTuple(args, "ss|s", &docname,&objname,&subname)) {
2006
Selection().rmvSelection(docname,objname,subname);
2013
if (!PyArg_ParseTuple(args, "O!|s", &(App::DocumentObjectPy::Type),&object,&subname))
2016
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
2017
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
2018
if (!docObj || !docObj->isAttachedToDocument()) {
2019
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
2023
Selection().rmvSelection(docObj->getDocument()->getName(),
2024
docObj->getNameInDocument(),
2030
PyObject *SelectionSingleton::sClearSelection(PyObject * /*self*/, PyObject *args)
2032
SelectionLogDisabler disabler(true);
2033
PyObject *clearPreSelect = Py_True;
2034
char *documentName = nullptr;
2035
if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &clearPreSelect)) {
2037
if (!PyArg_ParseTuple(args, "|sO!", &documentName, &PyBool_Type, &clearPreSelect))
2040
Selection().clearSelection(documentName, Base::asBoolean(clearPreSelect));
2046
ResolveMode toEnum(int value) {
2049
return ResolveMode::NoResolve;
2051
return ResolveMode::OldStyleElement;
2053
return ResolveMode::NewStyleElement;
2055
return ResolveMode::FollowLink;
2057
throw Base::ValueError("Wrong enum value");
2062
PyObject *SelectionSingleton::sIsSelected(PyObject * /*self*/, PyObject *args)
2065
char* subname = nullptr;
2067
if (!PyArg_ParseTuple(args, "O!|si", &(App::DocumentObjectPy::Type), &object, &subname, &resolve))
2071
auto docObj = static_cast<App::DocumentObjectPy*>(object);
2072
bool ok = Selection().isSelected(docObj->getDocumentObjectPtr(), subname, toEnum(resolve));
2074
return Py_BuildValue("O", (ok ? Py_True : Py_False));
2076
catch (const Base::Exception& e) {
2082
PyObject *SelectionSingleton::sCountObjectsOfType(PyObject * /*self*/, PyObject *args)
2085
char* document = nullptr;
2087
if (!PyArg_ParseTuple(args, "s|si", &objecttype, &document,&resolve))
2091
unsigned int count = Selection().countObjectsOfType(objecttype, document, toEnum(resolve));
2092
return PyLong_FromLong(count);
2094
catch (const Base::Exception& e) {
2100
PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args)
2102
char *documentName = nullptr;
2104
PyObject *single = Py_False;
2105
if (!PyArg_ParseTuple(args, "|siO!", &documentName, &resolve, &PyBool_Type, &single))
2109
std::vector<SelectionSingleton::SelObj> sel;
2110
sel = Selection().getSelection(documentName, toEnum(resolve), Base::asBoolean(single));
2112
std::set<App::DocumentObject*> noduplicates;
2113
std::vector<App::DocumentObject*> selectedObjects; // keep the order of selection
2115
for (const auto & it : sel) {
2116
if (noduplicates.insert(it.pObject).second) {
2117
selectedObjects.push_back(it.pObject);
2120
for (const auto & selectedObject : selectedObjects) {
2121
list.append(Py::asObject(selectedObject->getPyObject()));
2123
return Py::new_reference_to(list);
2125
catch (const Base::Exception& e) {
2129
catch (Py::Exception&) {
2134
PyObject *SelectionSingleton::sEnablePickedList(PyObject * /*self*/, PyObject *args)
2136
PyObject *enable = Py_True;
2137
if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &enable))
2140
Selection().enablePickedList(Base::asBoolean(enable));
2145
PyObject *SelectionSingleton::sSetPreselection(PyObject * /*self*/, PyObject *args, PyObject *kwd)
2148
const char* subname = nullptr;
2149
float x = 0, y = 0, z = 0;
2151
static const std::array<const char *, 7> kwlist{"obj", "subname", "x", "y", "z", "tp", nullptr};
2152
if (Base::Wrapped_ParseTupleAndKeywords(args, kwd, "O!|sfffi", kwlist, &(App::DocumentObjectPy::Type), &object,
2153
&subname, &x, &y, &z, &type)) {
2154
auto docObjPy = static_cast<App::DocumentObjectPy*>(object);
2155
App::DocumentObject* docObj = docObjPy->getDocumentObjectPtr();
2156
if (!docObj || !docObj->isAttachedToDocument()) {
2157
PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check invalid object");
2161
Selection().setPreselect(docObj->getDocument()->getName(),
2162
docObj->getNameInDocument(),
2163
subname,x,y,z, static_cast<SelectionChanges::MsgSource>(type));
2167
PyErr_SetString(PyExc_ValueError, "type must be 'DocumentObject[,subname[,x,y,z]]'");
2172
PyObject *SelectionSingleton::sGetPreselection(PyObject * /*self*/, PyObject *args)
2174
if (!PyArg_ParseTuple(args, ""))
2177
const SelectionChanges& sel = Selection().getPreselection();
2178
SelectionObject obj(sel);
2180
return obj.getPyObject();
2183
PyObject *SelectionSingleton::sRemPreselection(PyObject * /*self*/, PyObject *args)
2185
if (!PyArg_ParseTuple(args, ""))
2188
Selection().rmvPreselect();
2193
PyObject *SelectionSingleton::sGetCompleteSelection(PyObject * /*self*/, PyObject *args)
2196
if (!PyArg_ParseTuple(args, "|i",&resolve))
2200
std::vector<SelectionSingleton::SelObj> sel;
2201
sel = Selection().getCompleteSelection(toEnum(resolve));
2204
for (const auto & it : sel) {
2205
SelectionObject obj(SelectionChanges(SelectionChanges::AddSelection,
2211
list.append(Py::asObject(obj.getPyObject()));
2213
return Py::new_reference_to(list);
2215
catch (const Base::Exception& e) {
2219
catch (Py::Exception&) {
2224
PyObject *SelectionSingleton::sGetSelectionEx(PyObject * /*self*/, PyObject *args)
2226
char *documentName = nullptr;
2228
PyObject *single = Py_False;
2229
if (!PyArg_ParseTuple(args, "|siO!", &documentName, &resolve, &PyBool_Type, &single))
2233
std::vector<SelectionObject> sel;
2234
sel = Selection().getSelectionEx(documentName,
2235
App::DocumentObject::getClassTypeId(), toEnum(resolve), Base::asBoolean(single));
2238
for (auto & it : sel) {
2239
list.append(Py::asObject(it.getPyObject()));
2241
return Py::new_reference_to(list);
2243
catch (const Base::Exception& e) {
2247
catch (Py::Exception&) {
2252
PyObject *SelectionSingleton::sGetPickedList(PyObject * /*self*/, PyObject *args)
2254
char *documentName = nullptr;
2255
if (!PyArg_ParseTuple(args, "|s", &documentName))
2258
std::vector<SelectionObject> sel;
2259
sel = Selection().getPickedListEx(documentName);
2263
for (auto & it : sel) {
2264
list.append(Py::asObject(it.getPyObject()));
2266
return Py::new_reference_to(list);
2268
catch (Py::Exception&) {
2273
PyObject *SelectionSingleton::sGetSelectionObject(PyObject * /*self*/, PyObject *args)
2275
char *docName, *objName, *subName;
2276
PyObject* tuple = nullptr;
2277
if (!PyArg_ParseTuple(args, "sss|O!", &docName, &objName, &subName, &PyTuple_Type, &tuple))
2281
SelectionObject selObj;
2282
selObj.DocName = docName;
2283
selObj.FeatName = objName;
2284
std::string sub = subName;
2286
selObj.SubNames.push_back(sub);
2289
double x = (double)Py::Float(t.getItem(0));
2290
double y = (double)Py::Float(t.getItem(1));
2291
double z = (double)Py::Float(t.getItem(2));
2292
selObj.SelPoses.emplace_back(x,y,z);
2296
return selObj.getPyObject();
2298
catch (const Py::Exception&) {
2301
catch (const Base::Exception& e) {
2307
PyObject *SelectionSingleton::sSetSelectionStyle(PyObject * /*self*/, PyObject *args)
2310
if (!PyArg_ParseTuple(args, "i", &selStyle))
2314
Selection().setSelectionStyle(selStyle == 0 ? SelectionStyle::NormalSelection : SelectionStyle::GreedySelection);
2320
PyObject *SelectionSingleton::sAddSelObserver(PyObject * /*self*/, PyObject *args)
2324
if (!PyArg_ParseTuple(args, "O|i", &o, &resolve))
2328
SelectionObserverPython::addObserver(Py::Object(o), toEnum(resolve));
2334
PyObject *SelectionSingleton::sRemSelObserver(PyObject * /*self*/, PyObject *args)
2337
if (!PyArg_ParseTuple(args, "O", &o))
2341
SelectionObserverPython::removeObserver(Py::Object(o));
2347
PyObject *SelectionSingleton::sAddSelectionGate(PyObject * /*self*/, PyObject *args)
2351
if (PyArg_ParseTuple(args, "s|i", &filter, &resolve)) {
2353
Selection().addSelectionGate(new SelectionFilterGate(filter), toEnum(resolve));
2361
if (PyArg_ParseTuple(args, "O!|i",SelectionFilterPy::type_object(),&filterPy,resolve)) {
2363
Selection().addSelectionGate(new SelectionFilterGatePython(
2364
SelectionFilterPy::cast(filterPy)), toEnum(resolve));
2372
if (PyArg_ParseTuple(args, "O|i",&gate,&resolve)) {
2374
Selection().addSelectionGate(new SelectionGatePython(Py::Object(gate, false)), toEnum(resolve));
2380
PyErr_SetString(PyExc_ValueError, "Argument is neither string nor SelectionFiler nor SelectionGate");
2385
PyObject *SelectionSingleton::sRemoveSelectionGate(PyObject * /*self*/, PyObject *args)
2387
if (!PyArg_ParseTuple(args, ""))
2391
Selection().rmvSelectionGate();
2397
PyObject *SelectionSingleton::sSetVisible(PyObject * /*self*/, PyObject *args)
2399
PyObject *visible = Py_None;
2400
if (!PyArg_ParseTuple(args, "|O", &visible))
2404
VisibleState vis = VisToggle;
2405
Base::PyTypeCheck(&visible, &PyBool_Type);
2407
vis = PyObject_IsTrue(visible) ? VisShow : VisHide;
2409
Selection().setVisible(vis);
2415
PyObject *SelectionSingleton::sPushSelStack(PyObject * /*self*/, PyObject *args)
2417
PyObject *clear = Py_True;
2418
PyObject *overwrite = Py_False;
2419
if (!PyArg_ParseTuple(args, "|O!O!", &PyBool_Type, &clear, &PyBool_Type, &overwrite))
2422
Selection().selStackPush(Base::asBoolean(clear), Base::asBoolean(overwrite));
2427
PyObject *SelectionSingleton::sHasSelection(PyObject * /*self*/, PyObject *args)
2429
const char *doc = nullptr;
2431
if (!PyArg_ParseTuple(args, "|si", &doc, &resolve))
2436
if (doc || resolve > 0)
2437
ret = Selection().hasSelection(doc, toEnum(resolve));
2439
ret = Selection().hasSelection();
2441
return Py::new_reference_to(Py::Boolean(ret));
2446
PyObject *SelectionSingleton::sHasSubSelection(PyObject * /*self*/, PyObject *args)
2448
const char *doc = nullptr;
2449
PyObject *subElement = Py_False;
2450
if (!PyArg_ParseTuple(args, "|sO!",&doc,&PyBool_Type,&subElement))
2454
return Py::new_reference_to(
2455
Py::Boolean(Selection().hasSubSelection(doc, Base::asBoolean(subElement))));
2460
PyObject *SelectionSingleton::sGetSelectionFromStack(PyObject * /*self*/, PyObject *args)
2462
char *documentName = nullptr;
2465
if (!PyArg_ParseTuple(args, "|sii", &documentName, &resolve, &index))
2470
for(auto &sel : Selection().selStackGet(documentName, toEnum(resolve), index))
2471
list.append(Py::asObject(sel.getPyObject()));
2472
return Py::new_reference_to(list);