App: add hiddenref() expression built-in function
Any object reference inside this function is treated as hidden to exclude it from dependency calculation. This function allows some form of cyclic depdenency. Merger note: renamed from "HREF" to "HIDDENREF" to avoid confusion with the standard "hypertext reference" use of HREF.
This commit is contained in:
@@ -4483,7 +4483,7 @@ void PropertyXLinkContainer::afterRestore() {
|
||||
if(info.docLabel != obj->getDocument()->Label.getValue())
|
||||
_DocMap[App::quote(info.docLabel)] = obj->getDocument()->Label.getValue();
|
||||
}
|
||||
if(_Deps.insert(obj).second)
|
||||
if(_Deps.insert(std::make_pair(obj,info.xlink->getScope()==LinkScope::Hidden)).second)
|
||||
_XLinks[obj->getFullName()] = std::move(info.xlink);
|
||||
}
|
||||
_XLinkRestores.reset();
|
||||
@@ -4496,24 +4496,27 @@ void PropertyXLinkContainer::breakLink(App::DocumentObject *obj, bool clear) {
|
||||
if(!owner || !owner->getNameInDocument())
|
||||
return;
|
||||
if(!clear || obj!=owner) {
|
||||
if(!_Deps.erase(obj))
|
||||
auto it = _Deps.find(obj);
|
||||
if(it == _Deps.end())
|
||||
return;
|
||||
aboutToSetValue();
|
||||
onBreakLink(obj);
|
||||
if(obj->getDocument() == owner->getDocument())
|
||||
obj->_removeBackLink(owner);
|
||||
else
|
||||
if (obj->getDocument() != owner->getDocument())
|
||||
_XLinks.erase(obj->getFullName());
|
||||
else if (!it->second)
|
||||
obj->_removeBackLink(owner);
|
||||
_Deps.erase(it);
|
||||
hasSetValue();
|
||||
return;
|
||||
}
|
||||
if(obj!=owner)
|
||||
return;
|
||||
for(auto obj : _Deps) {
|
||||
for(auto &v : _Deps) {
|
||||
auto obj = v.first;
|
||||
if(!obj || !obj->getNameInDocument())
|
||||
continue;
|
||||
onBreakLink(obj);
|
||||
if(obj->getDocument()==owner->getDocument())
|
||||
if(!v.second && obj->getDocument()==owner->getDocument())
|
||||
obj->_removeBackLink(owner);
|
||||
}
|
||||
_XLinks.clear();
|
||||
@@ -4553,6 +4556,19 @@ void PropertyXLinkContainer::Save (Base::Writer &writer) const {
|
||||
writer.Stream() << "\" docs=\"" << docSet.size();
|
||||
}
|
||||
|
||||
std::ostringstream ss;
|
||||
int hidden = 0;
|
||||
int i=-1;
|
||||
for(auto &v : _XLinks) {
|
||||
++i;
|
||||
if(v.second->getScope() == LinkScope::Hidden) {
|
||||
ss << i << ' ';
|
||||
++hidden;
|
||||
}
|
||||
}
|
||||
if(hidden)
|
||||
writer.Stream() << "\" hidden=\"" << ss.str();
|
||||
|
||||
writer.Stream() << "\">" << std::endl;
|
||||
writer.incInd();
|
||||
|
||||
@@ -4575,6 +4591,15 @@ void PropertyXLinkContainer::Restore(Base::XMLReader &reader) {
|
||||
auto count = reader.getAttributeAsUnsigned("count");
|
||||
_XLinkRestores.reset(new std::vector<RestoreInfo>(count));
|
||||
|
||||
if(reader.hasAttribute("hidden")) {
|
||||
std::istringstream iss(reader.getAttribute("hidden"));
|
||||
int index;
|
||||
while(iss >> index) {
|
||||
if(index>=0 && index<static_cast<int>(count))
|
||||
_XLinkRestores->at(index).hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(reader.hasAttribute("docs")) {
|
||||
auto docCount = reader.getAttributeAsUnsigned("docs");
|
||||
_DocMap.clear();
|
||||
@@ -4593,6 +4618,8 @@ void PropertyXLinkContainer::Restore(Base::XMLReader &reader) {
|
||||
|
||||
for(auto &info : *_XLinkRestores) {
|
||||
info.xlink.reset(createXLink());
|
||||
if(info.hidden)
|
||||
info.xlink->setScope(LinkScope::Hidden);
|
||||
info.xlink->Restore(reader);
|
||||
}
|
||||
reader.readEndElement("XLinks");
|
||||
@@ -4624,16 +4651,23 @@ bool PropertyXLinkContainer::isLinkedToDocument(const App::Document &doc) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void PropertyXLinkContainer::updateDeps(std::set<DocumentObject*> &&newDeps) {
|
||||
void PropertyXLinkContainer::updateDeps(std::map<DocumentObject*,bool> &&newDeps) {
|
||||
auto owner = Base::freecad_dynamic_cast<App::DocumentObject>(getContainer());
|
||||
if(!owner || !owner->getNameInDocument())
|
||||
return;
|
||||
newDeps.erase(owner);
|
||||
|
||||
for(auto obj : newDeps) {
|
||||
for(auto &v : newDeps) {
|
||||
auto obj = v.first;
|
||||
if(obj && obj->getNameInDocument()) {
|
||||
auto it = _Deps.find(obj);
|
||||
if(it != _Deps.end()) {
|
||||
if(v.second != it->second) {
|
||||
if(v.second)
|
||||
obj->_removeBackLink(owner);
|
||||
else
|
||||
obj->_addBackLink(owner);
|
||||
}
|
||||
_Deps.erase(it);
|
||||
continue;
|
||||
}
|
||||
@@ -4643,21 +4677,21 @@ void PropertyXLinkContainer::updateDeps(std::set<DocumentObject*> &&newDeps) {
|
||||
xlink.reset(createXLink());
|
||||
xlink->setValue(obj);
|
||||
}
|
||||
xlink->setScope(v.second?LinkScope::Hidden:LinkScope::Global);
|
||||
}
|
||||
#ifndef USE_OLD_DAG
|
||||
else
|
||||
else if(!v.second)
|
||||
obj->_addBackLink(owner);
|
||||
#endif
|
||||
|
||||
onAddDep(obj);
|
||||
}
|
||||
}
|
||||
for(auto obj : _Deps) {
|
||||
for(auto &v : _Deps) {
|
||||
auto obj = v.first;
|
||||
if(!obj || !obj->getNameInDocument())
|
||||
continue;
|
||||
if(obj->getDocument()==owner->getDocument()) {
|
||||
#ifndef USE_OLD_DAG
|
||||
obj->_removeBackLink(owner);
|
||||
#endif
|
||||
if(!v.second)
|
||||
obj->_removeBackLink(owner);
|
||||
}else
|
||||
_XLinks.erase(obj->getFullName());
|
||||
onRemoveDep(obj);
|
||||
@@ -4681,8 +4715,9 @@ void PropertyXLinkContainer::clearDeps() {
|
||||
return;
|
||||
#ifndef USE_OLD_DAG
|
||||
if (!owner->testStatus(ObjectStatus::Destroy)) {
|
||||
for(auto obj : _Deps) {
|
||||
if(obj && obj->getNameInDocument() && obj->getDocument()==owner->getDocument())
|
||||
for(auto &v : _Deps) {
|
||||
auto obj = v.first;
|
||||
if(!v.second && obj && obj->getNameInDocument() && obj->getDocument()==owner->getDocument())
|
||||
obj->_removeBackLink(owner);
|
||||
}
|
||||
}
|
||||
@@ -4692,8 +4727,11 @@ void PropertyXLinkContainer::clearDeps() {
|
||||
_LinkRestored = false;
|
||||
}
|
||||
|
||||
void PropertyXLinkContainer::getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool, std::vector<std::string> * /*subs*/, bool /*newStyle*/) const
|
||||
void PropertyXLinkContainer::getLinks(std::vector<App::DocumentObject *> &objs,
|
||||
bool all, std::vector<std::string> * /*subs*/, bool /*newStyle*/) const
|
||||
{
|
||||
objs.insert(objs.end(),_Deps.begin(),_Deps.end());
|
||||
for(auto &v : _Deps) {
|
||||
if(all || !v.second)
|
||||
objs.push_back(v.first);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user