Gui: clean-up Selection API

Replace the int of the 'resolve' argument of several functions with a proper enum class.
* This avoids the inconsistencies in client code where often true/false is passed when an int is expected
* This avoids the use of magic numbers like 0, 1, 2 or the undocumented 3
This commit is contained in:
wmayer
2022-04-09 17:03:43 +02:00
parent 2d266a75cd
commit 0b2c73cf32
24 changed files with 365 additions and 274 deletions

View File

@@ -79,7 +79,7 @@ bool SelectionGateFilterExternal::allow(App::Document *doc ,App::DocumentObject
//////////////////////////////////////////////////////////////////////////////////////////
SelectionObserver::SelectionObserver(bool attach, int resolve)
SelectionObserver::SelectionObserver(bool attach, ResolveMode resolve)
: resolve(resolve)
, blockedSelection(false)
{
@@ -87,7 +87,7 @@ SelectionObserver::SelectionObserver(bool attach, int resolve)
attachSelection();
}
SelectionObserver::SelectionObserver(const ViewProviderDocumentObject *vp,bool attach, int resolve)
SelectionObserver::SelectionObserver(const ViewProviderDocumentObject *vp, bool attach, ResolveMode resolve)
: resolve(resolve)
, blockedSelection(false)
{
@@ -125,9 +125,11 @@ bool SelectionObserver::isSelectionAttached() const
void SelectionObserver::attachSelection()
{
if (!connectSelection.connected()) {
auto &signal = resolve > 1 ? Selection().signalSelectionChanged3 :
resolve ? Selection().signalSelectionChanged2 :
Selection().signalSelectionChanged ;
bool newStyle = (resolve >= ResolveMode::NewStyleElement);
bool oldStyle = (resolve == ResolveMode::OldStyleElement);
auto &signal = newStyle ? Selection().signalSelectionChanged3 :
oldStyle ? Selection().signalSelectionChanged2 :
Selection().signalSelectionChanged ;
connectSelection = signal.connect(boost::bind
(&SelectionObserver::_onSelectionChanged, this, bp::_1));
@@ -166,8 +168,8 @@ void SelectionObserver::detachSelection()
std::vector<SelectionObserverPython*> SelectionObserverPython::_instances;
SelectionObserverPython::SelectionObserverPython(const Py::Object& obj, int resolve)
: SelectionObserver(true,resolve),inst(obj)
SelectionObserverPython::SelectionObserverPython(const Py::Object& obj, ResolveMode resolve)
: SelectionObserver(true, resolve), inst(obj)
{
#undef FC_PY_ELEMENT
#define FC_PY_ELEMENT(_name) FC_PY_GetCallable(obj.ptr(),#_name,py_##_name);
@@ -178,9 +180,9 @@ SelectionObserverPython::~SelectionObserverPython()
{
}
void SelectionObserverPython::addObserver(const Py::Object& obj, int resolve)
void SelectionObserverPython::addObserver(const Py::Object& obj, ResolveMode resolve)
{
_instances.push_back(new SelectionObserverPython(obj,resolve));
_instances.push_back(new SelectionObserverPython(obj, resolve));
}
void SelectionObserverPython::removeObserver(const Py::Object& obj)
@@ -362,20 +364,20 @@ bool SelectionSingleton::hasPreselection() const {
return !CurrentPreselection.Object.getObjectName().empty();
}
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getCompleteSelection(int resolve) const
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getCompleteSelection(ResolveMode resolve) const
{
return getSelection("*",resolve);
return getSelection("*", resolve);
}
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getSelection(const char* pDocName,
int resolve, bool single) const
std::vector<SelectionSingleton::SelObj> SelectionSingleton::getSelection(const char* pDocName, ResolveMode resolve, bool single) const
{
std::vector<SelObj> temp;
if(single) temp.reserve(1);
if (single)
temp.reserve(1);
SelObj tempSelObj;
App::Document *pcDoc = nullptr;
if(!pDocName || strcmp(pDocName,"*")!=0) {
if(!pDocName || strcmp(pDocName,"*") != 0) {
pcDoc = getDocument(pDocName);
if (!pcDoc)
return temp;
@@ -384,17 +386,18 @@ std::vector<SelectionSingleton::SelObj> SelectionSingleton::getSelection(const c
std::map<App::DocumentObject*,std::set<std::string> > objMap;
for(auto &sel : _SelList) {
if(!sel.pDoc) continue;
if (!sel.pDoc)
continue;
const char *subelement = nullptr;
auto obj = getObjectOfType(sel,App::DocumentObject::getClassTypeId(),resolve,&subelement);
if(!obj || (pcDoc && sel.pObject->getDocument()!=pcDoc))
auto obj = getObjectOfType(sel, App::DocumentObject::getClassTypeId(), resolve, &subelement);
if (!obj || (pcDoc && sel.pObject->getDocument() != pcDoc))
continue;
// In case we are resolving objects, make sure no duplicates
if(resolve && !objMap[obj].insert(std::string(subelement?subelement:"")).second)
if (resolve != ResolveMode::NoResolve && !objMap[obj].insert(std::string(subelement ? subelement : "")).second)
continue;
if(single && temp.size()) {
if (single && temp.size()) {
temp.clear();
break;
}
@@ -416,18 +419,19 @@ std::vector<SelectionSingleton::SelObj> SelectionSingleton::getSelection(const c
return temp;
}
bool SelectionSingleton::hasSelection(const char* doc, bool resolve) const
bool SelectionSingleton::hasSelection(const char* doc, ResolveMode resolve) const
{
App::Document *pcDoc = nullptr;
if(!doc || strcmp(doc,"*")!=0) {
if (!doc || strcmp(doc,"*") != 0) {
pcDoc = getDocument(doc);
if (!pcDoc)
return false;
}
for(auto &sel : _SelList) {
if(!sel.pDoc) continue;
auto obj = getObjectOfType(sel,App::DocumentObject::getClassTypeId(),resolve);
if(obj && (!pcDoc || sel.pObject->getDocument()==pcDoc)) {
if (!sel.pDoc)
continue;
auto obj = getObjectOfType(sel, App::DocumentObject::getClassTypeId(), resolve);
if (obj && (!pcDoc || sel.pObject->getDocument()==pcDoc)) {
return true;
}
}
@@ -463,7 +467,7 @@ std::vector<SelectionSingleton::SelObj> SelectionSingleton::getPickedList(const
SelObj tempSelObj;
App::Document *pcDoc = nullptr;
if(!pDocName || strcmp(pDocName,"*")!=0) {
if(!pDocName || strcmp(pDocName,"*") != 0) {
pcDoc = getDocument(pDocName);
if (!pcDoc)
return temp;
@@ -488,20 +492,24 @@ std::vector<SelectionSingleton::SelObj> SelectionSingleton::getPickedList(const
return temp;
}
std::vector<SelectionObject> SelectionSingleton::getSelectionEx(
const char* pDocName, Base::Type typeId, int resolve, bool single) const {
return getObjectList(pDocName,typeId,_SelList,resolve,single);
std::vector<SelectionObject> SelectionSingleton::getSelectionEx(const char* pDocName, Base::Type typeId,
ResolveMode resolve, bool single) const
{
return getObjectList(pDocName, typeId, _SelList, resolve, single);
}
std::vector<SelectionObject> SelectionSingleton::getPickedListEx(const char* pDocName, Base::Type typeId) const {
return getObjectList(pDocName,typeId,_PickedList,false);
std::vector<SelectionObject> SelectionSingleton::getPickedListEx(const char* pDocName, Base::Type typeId) const
{
return getObjectList(pDocName, typeId, _PickedList, ResolveMode::NoResolve);
}
std::vector<SelectionObject> SelectionSingleton::getObjectList(const char* pDocName, Base::Type typeId,
std::list<_SelObj> &objList, int resolve, bool single) const
std::list<_SelObj> &objList,
ResolveMode resolve, bool single) const
{
std::vector<SelectionObject> temp;
if(single) temp.reserve(1);
if (single)
temp.reserve(1);
std::map<App::DocumentObject*,size_t> SortMap;
// check the type
@@ -509,30 +517,31 @@ std::vector<SelectionObject> SelectionSingleton::getObjectList(const char* pDocN
return temp;
App::Document *pcDoc = nullptr;
if(!pDocName || strcmp(pDocName,"*")!=0) {
if (!pDocName || strcmp(pDocName,"*") != 0) {
pcDoc = getDocument(pDocName);
if (!pcDoc)
return temp;
}
for (auto &sel : objList) {
if(!sel.pDoc) continue;
if(!sel.pDoc)
continue;
const char *subelement = nullptr;
auto obj = getObjectOfType(sel,typeId,resolve,&subelement);
if(!obj || (pcDoc && sel.pObject->getDocument()!=pcDoc))
if (!obj || (pcDoc && sel.pObject->getDocument() != pcDoc))
continue;
auto it = SortMap.find(obj);
if(it!=SortMap.end()) {
// only add sub-element
if (subelement && *subelement) {
if(resolve && !temp[it->second]._SubNameSet.insert(subelement).second)
if (resolve != ResolveMode::NoResolve && !temp[it->second]._SubNameSet.insert(subelement).second)
continue;
temp[it->second].SubNames.push_back(subelement);
temp[it->second].SelPoses.emplace_back(sel.x,sel.y,sel.z);
}
}
else {
if(single && temp.size()) {
if (single && temp.size()) {
temp.clear();
break;
}
@@ -541,7 +550,7 @@ std::vector<SelectionObject> SelectionSingleton::getObjectList(const char* pDocN
if (subelement && *subelement) {
temp.back().SubNames.push_back(subelement);
temp.back().SelPoses.emplace_back(sel.x,sel.y,sel.z);
if(resolve)
if (resolve != ResolveMode::NoResolve)
temp.back()._SubNameSet.insert(subelement);
}
SortMap.insert(std::make_pair(obj,temp.size()-1));
@@ -551,11 +560,13 @@ std::vector<SelectionObject> SelectionSingleton::getObjectList(const char* pDocN
return temp;
}
bool SelectionSingleton::needPickedList() const {
bool SelectionSingleton::needPickedList() const
{
return _needPickedList;
}
void SelectionSingleton::enablePickedList(bool enable) {
void SelectionSingleton::enablePickedList(bool enable)
{
if(enable != _needPickedList) {
_needPickedList = enable;
_PickedList.clear();
@@ -563,7 +574,8 @@ void SelectionSingleton::enablePickedList(bool enable) {
}
}
void SelectionSingleton::notify(SelectionChanges &&Chng) {
void SelectionSingleton::notify(SelectionChanges &&Chng)
{
if(Notifying) {
NotificationQueue.push_back(std::move(Chng));
return;
@@ -575,10 +587,10 @@ void SelectionSingleton::notify(SelectionChanges &&Chng) {
bool notify;
switch(msg.Type) {
case SelectionChanges::AddSelection:
notify = isSelected(msg.pDocName,msg.pObjectName,msg.pSubName,0);
notify = isSelected(msg.pDocName, msg.pObjectName, msg.pSubName, ResolveMode::NoResolve);
break;
case SelectionChanges::RmvSelection:
notify = !isSelected(msg.pDocName,msg.pObjectName,msg.pSubName,0);
notify = !isSelected(msg.pDocName, msg.pObjectName, msg.pSubName, ResolveMode::NoResolve);
break;
case SelectionChanges::SetPreselect:
notify = CurrentPreselection.Type==SelectionChanges::SetPreselect
@@ -604,23 +616,27 @@ void SelectionSingleton::notify(SelectionChanges &&Chng) {
}
}
bool SelectionSingleton::hasPickedList() const {
bool SelectionSingleton::hasPickedList() const
{
return _PickedList.size();
}
int SelectionSingleton::getAsPropertyLinkSubList(App::PropertyLinkSubList &prop) const
{
std::vector<Gui::SelectionObject> sel = this->getSelectionEx();
std::vector<App::DocumentObject*> objs; objs.reserve(sel.size()*2);
std::vector<App::DocumentObject*> objs; objs.reserve(sel.size() * 2);
std::vector<std::string> subs; subs.reserve(sel.size()*2);
for (std::size_t iobj = 0; iobj < sel.size(); iobj++) {
Gui::SelectionObject &selitem = sel[iobj];
App::DocumentObject* obj = selitem.getObject();
const std::vector<std::string> &subnames = selitem.getSubNames();
if (subnames.size() == 0){//whole object is selected
//whole object is selected
if (subnames.size() == 0){
objs.push_back(obj);
subs.emplace_back();
} else {
}
else {
for (std::size_t isub = 0; isub < subnames.size(); isub++) {
objs.push_back(obj);
subs.push_back(subnames[isub]);
@@ -632,35 +648,39 @@ int SelectionSingleton::getAsPropertyLinkSubList(App::PropertyLinkSubList &prop)
return objs.size();
}
App::DocumentObject *SelectionSingleton::getObjectOfType(_SelObj &sel,
Base::Type typeId, int resolve, const char **subelement)
App::DocumentObject *SelectionSingleton::getObjectOfType(_SelObj &sel, Base::Type typeId,
ResolveMode resolve, const char **subelement)
{
auto obj = sel.pObject;
if(!obj || !obj->getNameInDocument())
return nullptr;
const char *subname = sel.SubName.c_str();
if(resolve) {
if (resolve != ResolveMode::NoResolve) {
obj = sel.pResolvedObject;
if(resolve==2 && sel.elementName.first.size())
if (resolve == ResolveMode::NewStyleElement && sel.elementName.first.size())
subname = sel.elementName.first.c_str();
else
subname = sel.elementName.second.c_str();
}
if(!obj)
if (!obj)
return nullptr;
if(!obj->isDerivedFrom(typeId) &&
(resolve!=3 || !obj->getLinkedObject(true)->isDerivedFrom(typeId)))
if (!obj->isDerivedFrom(typeId) && (resolve != ResolveMode::FollowLink || !obj->getLinkedObject(true)->isDerivedFrom(typeId)))
return nullptr;
if(subelement) *subelement = subname;
if (subelement)
*subelement = subname;
return obj;
}
vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Type& typeId, const char* pDocName, int resolve) const
vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Type& typeId, const char* pDocName, ResolveMode resolve) const
{
std::vector<App::DocumentObject*> temp;
App::Document *pcDoc = nullptr;
if(!pDocName || strcmp(pDocName,"*")!=0) {
if (!pDocName || strcmp(pDocName,"*") != 0) {
pcDoc = getDocument(pDocName);
if (!pcDoc)
return temp;
@@ -669,7 +689,7 @@ vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Ty
std::set<App::DocumentObject*> objs;
for(auto &sel : _SelList) {
if(pcDoc && pcDoc!=sel.pDoc) continue;
App::DocumentObject *pObject = getObjectOfType(sel,typeId,resolve);
App::DocumentObject *pObject = getObjectOfType(sel, typeId, resolve);
if (pObject) {
auto ret = objs.insert(pObject);
if(ret.second)
@@ -680,7 +700,7 @@ vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const Base::Ty
return temp;
}
std::vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const char* typeName, const char* pDocName, int resolve) const
std::vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const char* typeName, const char* pDocName, ResolveMode resolve) const
{
Base::Type typeId = Base::Type::fromName(typeName);
if (typeId == Base::Type::badType())
@@ -688,25 +708,25 @@ std::vector<App::DocumentObject*> SelectionSingleton::getObjectsOfType(const cha
return getObjectsOfType(typeId, pDocName, resolve);
}
unsigned int SelectionSingleton::countObjectsOfType(const Base::Type& typeId, const char* pDocName, int resolve) const
unsigned int SelectionSingleton::countObjectsOfType(const Base::Type& typeId, const char* pDocName, ResolveMode resolve) const
{
unsigned int iNbr=0;
App::Document *pcDoc = nullptr;
if(!pDocName || strcmp(pDocName,"*")!=0) {
if(!pDocName || strcmp(pDocName,"*") != 0) {
pcDoc = getDocument(pDocName);
if (!pcDoc)
return 0;
}
for (auto &sel : _SelList) {
if((!pcDoc||pcDoc==sel.pDoc) && getObjectOfType(sel,typeId,resolve))
if((!pcDoc||pcDoc==sel.pDoc) && getObjectOfType(sel, typeId, resolve))
iNbr++;
}
return iNbr;
}
unsigned int SelectionSingleton::countObjectsOfType(const char* typeName, const char* pDocName, int resolve) const
unsigned int SelectionSingleton::countObjectsOfType(const char* typeName, const char* pDocName, ResolveMode resolve) const
{
Base::Type typeId = Base::Type::fromName(typeName);
if (typeId == Base::Type::badType())
@@ -715,7 +735,8 @@ unsigned int SelectionSingleton::countObjectsOfType(const char* typeName, const
}
void SelectionSingleton::slotSelectionChanged(const SelectionChanges& msg) {
void SelectionSingleton::slotSelectionChanged(const SelectionChanges& msg)
{
if(msg.Type == SelectionChanges::SetPreselectSignal ||
msg.Type == SelectionChanges::ShowSelection ||
msg.Type == SelectionChanges::HideSelection)
@@ -723,13 +744,13 @@ void SelectionSingleton::slotSelectionChanged(const SelectionChanges& msg) {
if(msg.Object.getSubName().size()) {
auto pParent = msg.Object.getObject();
if(!pParent)
if(!pParent)
return;
std::pair<std::string,std::string> elementName;
auto &newElementName = elementName.first;
auto &oldElementName = elementName.second;
auto pObject = App::GeoFeature::resolveElement(pParent,msg.pSubName,elementName);
if (!pObject)
if (!pObject)
return;
SelectionChanges msg2(msg.Type,pObject->getDocument()->getName(),
pObject->getNameInDocument(),
@@ -797,18 +818,18 @@ int SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectNa
return 0;
const char *subelement = pSubName;
if(gateResolve) {
if (gateResolve != ResolveMode::NoResolve) {
auto &newElementName = elementName.first;
auto &oldElementName = elementName.second;
pObject = App::GeoFeature::resolveElement(pObject,pSubName,elementName);
if (!pObject)
return 0;
if(gateResolve > 1)
subelement = newElementName.size()?newElementName.c_str():oldElementName.c_str();
if (gateResolve > ResolveMode::OldStyleElement)
subelement = newElementName.size() ? newElementName.c_str() : oldElementName.c_str();
else
subelement = oldElementName.c_str();
}
if (!ActiveGate->allow(pObject->getDocument(),pObject,subelement)) {
if (!ActiveGate->allow(pObject->getDocument(), pObject, subelement)) {
QString msg;
if (ActiveGate->notAllowedReason.length() > 0){
msg = QObject::tr(ActiveGate->notAllowedReason.c_str());
@@ -894,7 +915,7 @@ void SelectionSingleton::setPreselectCoord( float x, float y, float z)
static char buf[513];
// if nothing is in preselect ignore
if(CurrentPreselection.Object.getObjectName().empty())
if(CurrentPreselection.Object.getObjectName().empty())
return;
CurrentPreselection.x = x;
@@ -955,7 +976,7 @@ const SelectionChanges &SelectionSingleton::getPreselection(void) const
}
// add a SelectionGate to control what is selectable
void SelectionSingleton::addSelectionGate(Gui::SelectionGate *gate, int resolve)
void SelectionSingleton::addSelectionGate(Gui::SelectionGate *gate, ResolveMode resolve)
{
if (ActiveGate)
rmvSelectionGate();
@@ -1059,8 +1080,8 @@ bool SelectionSingleton::addSelection(const char* pDocName, const char* pObjectN
}
_SelObj temp;
int ret = checkSelection(pDocName,pObjectName,pSubName,0,temp);
if(ret!=0)
int ret = checkSelection(pDocName, pObjectName, pSubName, ResolveMode::NoResolve, temp);
if (ret!=0)
return false;
temp.x = x;
@@ -1206,15 +1227,15 @@ void SelectionSingleton::selStackGoForward(int count) {
getMainWindow()->updateActions();
}
std::vector<SelectionObject> SelectionSingleton::selStackGet(
const char* pDocName, int resolve, int index) const
std::vector<SelectionObject> SelectionSingleton::selStackGet(const char* pDocName, ResolveMode resolve, int index) const
{
const SelStackItem *item = nullptr;
if(index>=0) {
if(index>=(int)_SelStackBack.size())
if (index >= 0) {
if(index >= (int)_SelStackBack.size())
return {};
item = &_SelStackBack[_SelStackBack.size()-1-index];
}else{
}
else {
index = -index-1;
if(index>=(int)_SelStackForward.size())
return {};
@@ -1227,7 +1248,7 @@ std::vector<SelectionObject> SelectionSingleton::selStackGet(
if(checkSelection(sobjT.getDocumentName().c_str(),
sobjT.getObjectName().c_str(),
sobjT.getSubName().c_str(),
0,
ResolveMode::NoResolve,
sel,
&selList)==0)
{
@@ -1235,7 +1256,7 @@ std::vector<SelectionObject> SelectionSingleton::selStackGet(
}
}
return getObjectList(pDocName,App::DocumentObject::getClassTypeId(),selList,resolve);
return getObjectList(pDocName,App::DocumentObject::getClassTypeId(), selList, resolve);
}
bool SelectionSingleton::addSelections(const char* pDocName, const char* pObjectName, const std::vector<std::string>& pSubNames)
@@ -1248,8 +1269,8 @@ bool SelectionSingleton::addSelections(const char* pDocName, const char* pObject
bool update = false;
for(std::vector<std::string>::const_iterator it = pSubNames.begin(); it != pSubNames.end(); ++it) {
_SelObj temp;
int ret = checkSelection(pDocName,pObjectName,it->c_str(),0,temp);
if(ret!=0)
int ret = checkSelection(pDocName, pObjectName, it->c_str(), ResolveMode::NoResolve, temp);
if (ret!=0)
continue;
temp.x = 0;
@@ -1288,12 +1309,12 @@ bool SelectionSingleton::updateSelection(bool show, const char* pDocName,
rmvPreselect();
}
auto pDoc = getDocument(pDocName);
if(!pDoc)
if(!pDoc)
return false;
auto pObject = pDoc->getObject(pObjectName);
if(!pObject)
if(!pObject)
return false;
if (!isSelected(pObject, pSubName,0))
if (!isSelected(pObject, pSubName, ResolveMode::NoResolve))
return false;
SelectionChanges Chng(show?SelectionChanges::ShowSelection:SelectionChanges::HideSelection,
@@ -1306,7 +1327,7 @@ bool SelectionSingleton::updateSelection(bool show, const char* pDocName,
return true;
}
bool SelectionSingleton::addSelection(const SelectionObject& obj,bool clearPreselect)
bool SelectionSingleton::addSelection(const SelectionObject& obj, bool clearPreselect)
{
const std::vector<std::string>& subNames = obj.getSubNames();
const std::vector<Base::Vector3d> points = obj.getPickedPoints();
@@ -1357,12 +1378,12 @@ void SelectionSingleton::rmvSelection(const char* pDocName, const char* pObjectN
notify(SelectionChanges(SelectionChanges::PickedListChanged));
}
if(!pDocName)
if(!pDocName)
return;
_SelObj temp;
int ret = checkSelection(pDocName,pObjectName,pSubName,0,temp);
if(ret<0)
int ret = checkSelection(pDocName, pObjectName, pSubName, ResolveMode::NoResolve, temp);
if (ret<0)
return;
std::vector<SelectionChanges> changes;
@@ -1518,8 +1539,8 @@ void SelectionSingleton::setSelection(const char* pDocName, const std::vector<Ap
if(!obj || !obj->getNameInDocument())
continue;
_SelObj temp;
int ret = checkSelection(pDocName,obj->getNameInDocument(),nullptr,0,temp);
if(ret!=0)
int ret = checkSelection(pDocName,obj->getNameInDocument(), nullptr, ResolveMode::NoResolve, temp);
if (ret!=0)
continue;
touched = true;
_SelList.push_back(temp);
@@ -1527,7 +1548,7 @@ void SelectionSingleton::setSelection(const char* pDocName, const std::vector<Ap
if(touched) {
_SelStackForward.clear();
notify(SelectionChanges(SelectionChanges::SetSelection,pDocName));
notify(SelectionChanges(SelectionChanges::SetSelection, pDocName));
getMainWindow()->updateActions();
}
}
@@ -1611,24 +1632,24 @@ void SelectionSingleton::clearCompleteSelection(bool clearPreSelect)
getMainWindow()->updateActions();
}
bool SelectionSingleton::isSelected(const char* pDocName,
const char* pObjectName, const char* pSubName, int resolve) const
bool SelectionSingleton::isSelected(const char* pDocName, const char* pObjectName,
const char* pSubName, ResolveMode resolve) const
{
_SelObj sel;
return checkSelection(pDocName,pObjectName,pSubName,resolve,sel,&_SelList)>0;
return checkSelection(pDocName, pObjectName, pSubName, resolve, sel, &_SelList) > 0;
}
bool SelectionSingleton::isSelected(App::DocumentObject* pObject, const char* pSubName, int resolve) const
bool SelectionSingleton::isSelected(App::DocumentObject* pObject, const char* pSubName, ResolveMode resolve) const
{
if(!pObject || !pObject->getNameInDocument() || !pObject->getDocument())
if (!pObject || !pObject->getNameInDocument() || !pObject->getDocument())
return false;
_SelObj sel;
return checkSelection(pObject->getDocument()->getName(),
pObject->getNameInDocument(),pSubName,resolve,sel,&_SelList)>0;
pObject->getNameInDocument(), pSubName, resolve, sel, &_SelList) > 0;
}
int SelectionSingleton::checkSelection(const char *pDocName, const char *pObjectName,
const char *pSubName, int resolve, _SelObj &sel, const std::list<_SelObj> *selList) const
int SelectionSingleton::checkSelection(const char *pDocName, const char *pObjectName, const char *pSubName,
ResolveMode resolve, _SelObj &sel, const std::list<_SelObj> *selList) const
{
sel.pDoc = getDocument(pDocName);
if(!sel.pDoc) {
@@ -1648,11 +1669,11 @@ int SelectionSingleton::checkSelection(const char *pDocName, const char *pObject
FC_ERR("Object not found");
return -1;
}
if(sel.pObject->testStatus(App::ObjectStatus::Remove))
if (sel.pObject->testStatus(App::ObjectStatus::Remove))
return -1;
if(pSubName)
if (pSubName)
sel.SubName = pSubName;
if(!resolve)
if (resolve == ResolveMode::NoResolve)
TreeWidget::checkTopParent(sel.pObject,sel.SubName);
pSubName = sel.SubName.size()?sel.SubName.c_str():nullptr;
sel.FeatName = sel.pObject->getNameInDocument();
@@ -1688,20 +1709,21 @@ int SelectionSingleton::checkSelection(const char *pDocName, const char *pObject
if (s.DocName==pDocName && s.FeatName==sel.FeatName) {
if(s.SubName==pSubName)
return 1;
if(resolve>1 && boost::starts_with(s.SubName,prefix))
if (resolve > ResolveMode::OldStyleElement && boost::starts_with(s.SubName,prefix))
return 1;
}
}
if(resolve==1) {
if (resolve == ResolveMode::OldStyleElement) {
for(auto &s : *selList) {
if(s.pResolvedObject != sel.pResolvedObject)
continue;
if(!pSubName[0])
return 1;
if(s.elementName.first.size()) {
if(s.elementName.first == sel.elementName.first)
if (s.elementName.first.size()) {
if (s.elementName.first == sel.elementName.first)
return 1;
}else if(s.SubName == sel.elementName.second)
}
else if(s.SubName == sel.elementName.second)
return 1;
}
}
@@ -1710,7 +1732,7 @@ int SelectionSingleton::checkSelection(const char *pDocName, const char *pObject
const char *SelectionSingleton::getSelectedElement(App::DocumentObject *obj, const char* pSubName) const
{
if (!obj)
if (!obj)
return nullptr;
for(list<_SelObj>::const_iterator It = _SelList.begin();It != _SelList.end();++It) {
@@ -1729,7 +1751,7 @@ const char *SelectionSingleton::getSelectedElement(App::DocumentObject *obj, con
void SelectionSingleton::slotDeletedObject(const App::DocumentObject& Obj)
{
if(!Obj.getNameInDocument())
if(!Obj.getNameInDocument())
return;
// For safety reason, don't bother checking
@@ -1787,7 +1809,7 @@ SelectionSingleton::SelectionSingleton()
hy = 0;
hz = 0;
ActiveGate = nullptr;
gateResolve = 1;
gateResolve = ResolveMode::OldStyleElement;
App::GetApplication().signalDeletedObject.connect(boost::bind(&Gui::SelectionSingleton::slotDeletedObject, this, bp::_1));
signalSelectionChanged.connect(boost::bind(&Gui::SelectionSingleton::slotSelectionChanged, this, bp::_1));
}
@@ -2171,19 +2193,41 @@ PyObject *SelectionSingleton::sClearSelection(PyObject * /*self*/, PyObject *arg
Py_Return;
}
namespace {
ResolveMode toEnum(int value) {
switch (value) {
case 0:
return ResolveMode::NoResolve;
case 1:
return ResolveMode::OldStyleElement;
case 2:
return ResolveMode::NewStyleElement;
case 3:
return ResolveMode::FollowLink;
default:
throw Base::ValueError("Wrong enum value");
}
}
}
PyObject *SelectionSingleton::sIsSelected(PyObject * /*self*/, PyObject *args)
{
PyObject *object;
char* subname = nullptr;
PyObject *resolve = Py_True;
if (!PyArg_ParseTuple(args, "O!|sO!", &(App::DocumentObjectPy::Type), &object,
&subname, &PyBool_Type, &resolve))
int resolve = 1;
if (!PyArg_ParseTuple(args, "O!|si", &(App::DocumentObjectPy::Type), &object, &subname, &resolve))
return nullptr;
App::DocumentObjectPy* docObj = static_cast<App::DocumentObjectPy*>(object);
bool ok = Selection().isSelected(docObj->getDocumentObjectPtr(), subname,PyObject_IsTrue(resolve));
try {
App::DocumentObjectPy* docObj = static_cast<App::DocumentObjectPy*>(object);
bool ok = Selection().isSelected(docObj->getDocumentObjectPtr(), subname, toEnum(resolve));
return Py_BuildValue("O", (ok ? Py_True : Py_False));
return Py_BuildValue("O", (ok ? Py_True : Py_False));
}
catch (const Base::Exception& e) {
e.setPyException();
return nullptr;
}
}
PyObject *SelectionSingleton::sCountObjectsOfType(PyObject * /*self*/, PyObject *args)
@@ -2194,9 +2238,14 @@ PyObject *SelectionSingleton::sCountObjectsOfType(PyObject * /*self*/, PyObject
if (!PyArg_ParseTuple(args, "s|si", &objecttype, &document,&resolve))
return nullptr;
unsigned int count = Selection().countObjectsOfType(objecttype, document, resolve);
return PyLong_FromLong(count);
try {
unsigned int count = Selection().countObjectsOfType(objecttype, document, toEnum(resolve));
return PyLong_FromLong(count);
}
catch (const Base::Exception& e) {
e.setPyException();
return nullptr;
}
}
PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args)
@@ -2207,10 +2256,10 @@ PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args)
if (!PyArg_ParseTuple(args, "|siO!", &documentName, &resolve, &PyBool_Type, &single))
return nullptr;
std::vector<SelectionSingleton::SelObj> sel;
sel = Selection().getSelection(documentName,resolve,PyObject_IsTrue(single));
try {
std::vector<SelectionSingleton::SelObj> sel;
sel = Selection().getSelection(documentName, toEnum(resolve), PyObject_IsTrue(single));
std::set<App::DocumentObject*> noduplicates;
std::vector<App::DocumentObject*> selectedObjects; // keep the order of selection
Py::List list;
@@ -2224,6 +2273,10 @@ PyObject *SelectionSingleton::sGetSelection(PyObject * /*self*/, PyObject *args)
}
return Py::new_reference_to(list);
}
catch (const Base::Exception& e) {
e.setPyException();
return nullptr;
}
catch (Py::Exception&) {
return nullptr;
}
@@ -2294,16 +2347,20 @@ PyObject *SelectionSingleton::sGetCompleteSelection(PyObject * /*self*/, PyObjec
if (!PyArg_ParseTuple(args, "|i",&resolve))
return nullptr;
std::vector<SelectionSingleton::SelObj> sel;
sel = Selection().getCompleteSelection(resolve);
try {
std::vector<SelectionSingleton::SelObj> sel;
sel = Selection().getCompleteSelection(toEnum(resolve));
Py::List list;
for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
list.append(Py::asObject(it->pObject->getPyObject()));
}
return Py::new_reference_to(list);
}
catch (const Base::Exception& e) {
e.setPyException();
return nullptr;
}
catch (Py::Exception&) {
return nullptr;
}
@@ -2317,17 +2374,21 @@ PyObject *SelectionSingleton::sGetSelectionEx(PyObject * /*self*/, PyObject *arg
if (!PyArg_ParseTuple(args, "|siO!", &documentName, &resolve, &PyBool_Type, &single))
return nullptr;
std::vector<SelectionObject> sel;
sel = Selection().getSelectionEx(documentName,
App::DocumentObject::getClassTypeId(),resolve,PyObject_IsTrue(single));
try {
std::vector<SelectionObject> sel;
sel = Selection().getSelectionEx(documentName,
App::DocumentObject::getClassTypeId(), toEnum(resolve), PyObject_IsTrue(single));
Py::List list;
for (std::vector<SelectionObject>::iterator it = sel.begin(); it != sel.end(); ++it) {
list.append(Py::asObject(it->getPyObject()));
}
return Py::new_reference_to(list);
}
catch (const Base::Exception& e) {
e.setPyException();
return nullptr;
}
catch (Py::Exception&) {
return nullptr;
}
@@ -2396,7 +2457,7 @@ PyObject *SelectionSingleton::sAddSelObserver(PyObject * /*self*/, PyObject *arg
return nullptr;
PY_TRY {
SelectionObserverPython::addObserver(Py::Object(o),resolve);
SelectionObserverPython::addObserver(Py::Object(o), toEnum(resolve));
Py_Return;
}
PY_CATCH;
@@ -2421,7 +2482,7 @@ PyObject *SelectionSingleton::sAddSelectionGate(PyObject * /*self*/, PyObject *a
int resolve = 1;
if (PyArg_ParseTuple(args, "s|i", &filter, &resolve)) {
PY_TRY {
Selection().addSelectionGate(new SelectionFilterGate(filter),resolve);
Selection().addSelectionGate(new SelectionFilterGate(filter), toEnum(resolve));
Py_Return;
}
PY_CATCH;
@@ -2432,7 +2493,7 @@ PyObject *SelectionSingleton::sAddSelectionGate(PyObject * /*self*/, PyObject *a
if (PyArg_ParseTuple(args, "O!|i",SelectionFilterPy::type_object(),&filterPy,resolve)) {
PY_TRY {
Selection().addSelectionGate(new SelectionFilterGatePython(
static_cast<SelectionFilterPy*>(filterPy)),resolve);
static_cast<SelectionFilterPy*>(filterPy)), toEnum(resolve));
Py_Return;
}
PY_CATCH;
@@ -2442,7 +2503,7 @@ PyObject *SelectionSingleton::sAddSelectionGate(PyObject * /*self*/, PyObject *a
PyObject* gate;
if (PyArg_ParseTuple(args, "O|i",&gate,&resolve)) {
PY_TRY {
Selection().addSelectionGate(new SelectionGatePython(Py::Object(gate, false)),resolve);
Selection().addSelectionGate(new SelectionGatePython(Py::Object(gate, false)), toEnum(resolve));
Py_Return;
}
PY_CATCH;
@@ -2505,14 +2566,14 @@ PyObject *SelectionSingleton::sPushSelStack(PyObject * /*self*/, PyObject *args)
PyObject *SelectionSingleton::sHasSelection(PyObject * /*self*/, PyObject *args)
{
const char *doc = nullptr;
PyObject *resolve = Py_False;
if (!PyArg_ParseTuple(args, "|sO!", &doc, &PyBool_Type, &resolve))
int resolve = 0;
if (!PyArg_ParseTuple(args, "|sO!", &doc, &resolve))
return nullptr;
PY_TRY {
bool ret;
if(doc || PyObject_IsTrue(resolve))
ret = Selection().hasSelection(doc,PyObject_IsTrue(resolve));
if (doc || resolve > 0)
ret = Selection().hasSelection(doc, toEnum(resolve));
else
ret = Selection().hasSelection();
@@ -2545,7 +2606,7 @@ PyObject *SelectionSingleton::sGetSelectionFromStack(PyObject * /*self*/, PyObje
PY_TRY {
Py::List list;
for(auto &sel : Selection().selStackGet(documentName, resolve, index))
for(auto &sel : Selection().selStackGet(documentName, toEnum(resolve), index))
list.append(Py::asObject(sel.getPyObject()));
return Py::new_reference_to(list);
}