Introduce Scoped links to prevent cross cs links

This commit is contained in:
Stefan Tröger
2017-06-10 11:14:44 +02:00
committed by wmayer
parent 51005bb81e
commit 3dccf50e83
4 changed files with 106 additions and 21 deletions

View File

@@ -76,7 +76,7 @@ App::DocumentObjectExecReturn *DocumentObject::recompute(void)
{
//check if the links are valid before making the recompute
if(!GeoFeatureGroupExtension::areLinksValid(this))
return new App::DocumentObjectExecReturn("Links between different GeoFeatureGroups are not valid", this);
return new App::DocumentObjectExecReturn("Links go out of the allowed scope", this);
// set/unset the execution bit
ObjectStatusLocker<ObjectStatus, DocumentObject> exe(App::Recompute, this);

View File

@@ -210,23 +210,33 @@ void GeoFeatureGroupExtension::extensionOnChanged(const Property* p) {
}
std::vector< DocumentObject* > GeoFeatureGroupExtension::getObjectsFromLinks(DocumentObject* obj) {
std::vector< DocumentObject* > GeoFeatureGroupExtension::getScopedObjectsFromLinks(DocumentObject* obj, LinkScope scope) {
//we get all linked objects. We can't use outList() as this includes the links from expressions
std::vector< App::DocumentObject* > result;
std::vector<App::Property*> list;
obj->getPropertyList(list);
for(App::Property* prop : list) {
if(prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId()))
if(prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId()) &&
static_cast<App::PropertyLink*>(prop)->getScope() == scope) {
result.push_back(static_cast<App::PropertyLink*>(prop)->getValue());
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
}
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId()) &&
static_cast<App::PropertyLinkList*>(prop)->getScope() == scope) {
auto vec = static_cast<App::PropertyLinkList*>(prop)->getValues();
result.insert(result.end(), vec.begin(), vec.end());
}
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSub::getClassTypeId()) &&
static_cast<App::PropertyLinkSub*>(prop)->getScope() == scope) {
result.push_back(static_cast<App::PropertyLinkSub*>(prop)->getValue());
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())) {
auto vec = static_cast<App::PropertyLinkList*>(prop)->getValues();
}
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSubList::getClassTypeId()) &&
static_cast<App::PropertyLinkSubList*>(prop)->getScope() == scope) {
auto vec = static_cast<App::PropertyLinkSubList*>(prop)->getValues();
result.insert(result.end(), vec.begin(), vec.end());
}
}
@@ -249,8 +259,9 @@ void GeoFeatureGroupExtension::getCSOutList(App::DocumentObject* obj, std::vecto
if(obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId()))
return;
//we get all linked objects. We can't use outList() as this includes the links from expressions
auto result = getObjectsFromLinks(obj);
//we get all relevant linked objects. We can't use outList() as this includes the links from expressions,
//also we only want links with scope Local
auto result = getScopedObjectsFromLinks(obj);
//we remove all links to origin features and origins, they belong to a CS too and can't be moved
result.erase(std::remove_if(result.begin(), result.end(), [](App::DocumentObject* obj)->bool {
@@ -295,9 +306,9 @@ void GeoFeatureGroupExtension::getCSInList(DocumentObject* obj, std::vector< Doc
if(std::find(vec.begin(), vec.end(), parent) != vec.end())
throw Base::Exception("Graph is not DAG");
//check if the link is real or if it is a expression one (could also be both, so it is not
//check if the link is real Local scope one or if it is a expression one (could also be both, so it is not
//enough to check the expressions)
auto res = getObjectsFromLinks(parent);
auto res = getScopedObjectsFromLinks(parent);
if(std::find(res.begin(), res.end(), obj) != res.end())
result.push_back(parent);
}
@@ -338,16 +349,25 @@ void GeoFeatureGroupExtension::getCSRelevantLinks(DocumentObject* obj, std::vect
}
bool GeoFeatureGroupExtension::areLinksValid(DocumentObject* obj) {
//we get all linked objects. We can't use outList() as this includes the links from expressions
auto result = getObjectsFromLinks(obj);
//no cross CS links.
//no cross CS link for local links.
auto result = getScopedObjectsFromLinks(obj, LinkScope::Local);
auto group = obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId()) ? obj : getGroupOfObject(obj);
for(auto link : result) {
if(getGroupOfObject(link) != group)
return false;
}
//for links with scope SubGroup we need to check if all features are part of subgroups
if(group) {
result = getScopedObjectsFromLinks(obj, LinkScope::SubGroup);
auto groupExt = group->getExtensionByType<App::GeoFeatureGroupExtension>();
for(auto link : result) {
if(!groupExt->hasObject(link, true))
return false;
}
}
return true;
}

View File

@@ -116,7 +116,7 @@ public:
static bool areLinksValid(App::DocumentObject* obj);
private:
Base::Placement recursiveGroupPlacement(GeoFeatureGroupExtension* group);
static std::vector<App::DocumentObject*> getObjectsFromLinks(App::DocumentObject*);
static std::vector<App::DocumentObject*> getScopedObjectsFromLinks(App::DocumentObject*, LinkScope scope = LinkScope::Local);
};
typedef ExtensionPythonT<GroupExtensionPythonT<GeoFeatureGroupExtension>> GeoFeatureGroupExtensionPython;

View File

@@ -39,9 +39,19 @@ namespace App
{
class DocumentObject;
enum class LinkScope {
Local,
SubGroup,
Global
};
/** the general Link Poperty
* Main Purpose of this property is to Link Objects and Feautures in a document.
/** The general Link Property
* Main Purpose of this property is to Link Objects and Feautures in a document. Like all links this
* property is scope aware, meaning it does define which objects are allowed to be linked depending
* of the GeoFeatureGroup where it is in.
*
* @note Links that invalid in respect to the scope this property is set to are not rejected. They
* are only detected to be invalid and prevent the feature from recomputing.
*/
class AppExport PropertyLink : public Property
{
@@ -93,9 +103,23 @@ public:
}
virtual const char* getEditorName(void) const
{ return "Gui::PropertyEditor::PropertyLinkItem"; }
/**
* @brief Set the links scope
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
void setScope(LinkScope scope) {_pcScope = scope;};
/**
* @brief Get the links scope
* Retreive what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
LinkScope getScope() {return _pcScope;};
protected:
App::DocumentObject *_pcLink;
LinkScope _pcScope = LinkScope::Local;
};
class AppExport PropertyLinkList : public PropertyLists
@@ -148,8 +172,22 @@ public:
virtual unsigned int getMemSize(void) const;
/**
* @brief Set the links scope
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
void setScope(LinkScope scope) {_pcScope = scope;};
/**
* @brief Get the links scope
* Retreive what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
LinkScope getScope() {return _pcScope;};
private:
std::vector<DocumentObject*> _lValueList;
LinkScope _pcScope = LinkScope::Local;
};
/** the Link Poperty with sub elements
@@ -212,11 +250,24 @@ public:
virtual unsigned int getMemSize (void) const{
return sizeof(App::DocumentObject *);
}
/**
* @brief Set the links scope
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
void setScope(LinkScope scope) {_pcScope = scope;};
/**
* @brief Get the links scope
* Retreive what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
LinkScope getScope() {return _pcScope;};
protected:
App::DocumentObject *_pcLinkSub;
App::DocumentObject* _pcLinkSub;
std::vector<std::string> _cSubList;
LinkScope _pcScope = LinkScope::Local;
};
class AppExport PropertyLinkSubList: public PropertyLists
@@ -285,10 +336,24 @@ public:
virtual unsigned int getMemSize (void) const;
/**
* @brief Set the links scope
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
void setScope(LinkScope scope) {_pcScope = scope;};
/**
* @brief Get the links scope
* Retreive what kind of links are allowed. Only in the Local GeoFeatureGroup, in this an
* all SubGroups or to all object within the Glocal scope.
*/
LinkScope getScope() {return _pcScope;};
private:
//FIXME: Do not make two independent lists because this will lead to some inconsistencies!
std::vector<DocumentObject*> _lValueList;
std::vector<std::string> _lSubList;
LinkScope _pcScope = LinkScope::Local;
};
} // namespace App