Allow add/remove multiple objects in a group

This commit is contained in:
Stefan Tröger
2017-02-17 06:51:46 +01:00
committed by wmayer
parent f9200f4502
commit da866e5b4d
8 changed files with 205 additions and 74 deletions

View File

@@ -119,47 +119,61 @@ Base::Placement GeoFeatureGroupExtension::recursiveGroupPlacement(GeoFeatureGrou
return group->placement().getValue();
}
std::vector<DocumentObject*> GeoFeatureGroupExtension::addObject(App::DocumentObject* object) {
std::vector<DocumentObject*> GeoFeatureGroupExtension::addObjects(std::vector<App::DocumentObject*> objects) {
if(!allowObject(object))
return std::vector<DocumentObject*>();
//cross CoordinateSystem links are not allowed, so we need to move the whole link group
auto links = getCSRelevantLinks(object);
links.push_back(object);
auto ret = links;
std::vector<DocumentObject*> grp = Group.getValues();
for( auto obj : links) {
//only one geofeaturegroup per object.
auto *group = App::GeoFeatureGroupExtension::getGroupOfObject(obj);
if(group && group != getExtendedObject())
group->getExtensionByType<App::GroupExtension>()->removeObject(obj);
std::vector<DocumentObject*> ret;
for(auto object : objects) {
if (!hasObject(obj))
grp.push_back(obj);
else
ret.erase(std::remove(ret.begin(), ret.end(), obj), ret.end());
if(!allowObject(object))
continue;
//cross CoordinateSystem links are not allowed, so we need to move the whole link group
auto links = getCSRelevantLinks(object);
links.push_back(object);
for( auto obj : links) {
//only one geofeaturegroup per object.
auto *group = App::GeoFeatureGroupExtension::getGroupOfObject(obj);
if(group && group != getExtendedObject())
group->getExtensionByType<App::GroupExtension>()->removeObject(obj);
if (!hasObject(obj)) {
grp.push_back(obj);
ret.push_back(obj);
}
}
}
Group.setValues(grp);
return ret;
}
std::vector<DocumentObject*> GeoFeatureGroupExtension::removeObject(App::DocumentObject* object) {
//cross CoordinateSystem links are not allowed, so we need to remove the whole link group
auto links = getCSRelevantLinks(object);
links.push_back(object);
std::vector<DocumentObject*> GeoFeatureGroupExtension::removeObjects(std::vector<App::DocumentObject*> objects) {
//remove all links out of group
std::vector<DocumentObject*> removed;
std::vector<DocumentObject*> grp = Group.getValues();
for(auto link : links)
grp.erase(std::remove(grp.begin(), grp.end(), link), grp.end());
Group.setValues(grp);
return links;
for(auto object : objects) {
//cross CoordinateSystem links are not allowed, so we need to remove the whole link group
auto links = getCSRelevantLinks(object);
links.push_back(object);
//remove all links out of group
for(auto link : links) {
auto end = std::remove(grp.begin(), grp.end(), link);
if(end != grp.end()) {
grp.erase(end, grp.end());
removed.push_back(link);
}
}
}
if(!removed.empty())
Group.setValues(grp);
return removed;
}
std::vector< DocumentObject* > GeoFeatureGroupExtension::getObjectsFromLinks(DocumentObject* obj) {

View File

@@ -96,8 +96,8 @@ public:
!obj->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId());
}
virtual std::vector<DocumentObject*> addObject(DocumentObject* obj) override;
virtual std::vector<DocumentObject*> removeObject(DocumentObject* obj) override;
virtual std::vector< DocumentObject* > addObjects(std::vector< DocumentObject* > obj) override;
virtual std::vector< DocumentObject* > removeObjects(std::vector< DocumentObject* > obj) override;
/// returns GeoFeatureGroup relevant objects that are linked from the given one. That meas all linked objects
/// including their linkes (recursively) except GeoFeatureGroups, where the recursion stops. Expressions

View File

@@ -62,35 +62,46 @@ DocumentObject* GroupExtension::addObject(const char* sType, const char* pObject
std::vector<DocumentObject*> GroupExtension::addObject(DocumentObject* obj)
{
if(!allowObject(obj))
return std::vector<DocumentObject*>();
std::vector<DocumentObject*> vec = {obj};
return addObjects(vec);
}
std::vector< DocumentObject* > GroupExtension::addObjects(std::vector< DocumentObject* > objs) {
if (hasObject(obj))
return std::vector<DocumentObject*>();
std::vector<DocumentObject*> added;
std::vector<DocumentObject*> grp = Group.getValues();
for(auto obj : objs) {
if(!allowObject(obj))
continue;
//only one group per object. Note that it is allowed to be in a group and geofeaturegroup. However,
//getGroupOfObject() returns only normal groups, no GeoFeatureGroups. Hence this works.
auto *group = App::GroupExtension::getGroupOfObject(obj);
if(group && group != getExtendedObject())
group->getExtensionByType<App::GroupExtension>()->removeObject(obj);
//if we are on a geofeaturegroup we need to ensure the object is too
auto geogrp = GeoFeatureGroupExtension::getGroupOfObject(getExtendedObject());
auto objgrp = GeoFeatureGroupExtension::getGroupOfObject(obj);
if( geogrp != objgrp ) {
//what to doo depends on if we are in geofeature group or not
if(geogrp)
geogrp->getExtensionByType<GeoFeatureGroupExtension>()->addObject(obj);
else
objgrp->getExtensionByType<GeoFeatureGroupExtension>()->removeObject(obj);
if (hasObject(obj))
continue;
//only one group per object. Note that it is allowed to be in a group and geofeaturegroup. However,
//getGroupOfObject() returns only normal groups, no GeoFeatureGroups. Hence this works.
auto *group = App::GroupExtension::getGroupOfObject(obj);
if(group && group != getExtendedObject())
group->getExtensionByType<App::GroupExtension>()->removeObject(obj);
//if we are in a geofeaturegroup we need to ensure the object is too
auto geogrp = GeoFeatureGroupExtension::getGroupOfObject(getExtendedObject());
auto objgrp = GeoFeatureGroupExtension::getGroupOfObject(obj);
if( geogrp != objgrp ) {
//what to doo depends on if we are in geofeature group or not
if(geogrp)
geogrp->getExtensionByType<GeoFeatureGroupExtension>()->addObject(obj);
else
objgrp->getExtensionByType<GeoFeatureGroupExtension>()->removeObject(obj);
}
grp.push_back(obj);
added.push_back(obj);
}
std::vector<DocumentObject*> grp = Group.getValues();
grp.push_back(obj);
Group.setValues(grp);
std::vector<DocumentObject*> vec = {obj};
return vec;
return added;
}
void GroupExtension::addObjects(const std::vector<App::DocumentObject*>& objs)
@@ -118,18 +129,34 @@ void GroupExtension::addObjects(const std::vector<App::DocumentObject*>& objs)
std::vector<DocumentObject*> GroupExtension::removeObject(DocumentObject* obj)
{
const std::vector<DocumentObject*> & grp = Group.getValues();
std::vector<DocumentObject*> newGrp;
std::vector<DocumentObject*> vec = {obj};
return removeObjects(vec);
}
std::remove_copy (grp.begin(), grp.end(), std::back_inserter (newGrp), obj);
std::vector< DocumentObject* > GroupExtension::removeObjects(std::vector< DocumentObject* > objs) {
const std::vector<DocumentObject*> & grp = Group.getValues();
std::vector<DocumentObject*> newGrp = grp;
std::vector<DocumentObject*> removed;
std::vector<DocumentObject*>::iterator end = newGrp.end();
for(auto obj : objs) {
auto res = std::remove(newGrp.begin(), end, obj);
if(res != end) {
end = res;
removed.push_back(obj);
}
}
newGrp.erase(end, newGrp.end());
if (grp.size() != newGrp.size()) {
Group.setValues (newGrp);
}
std::vector<DocumentObject*> vec = {obj};
return vec;
return removed;
}
void GroupExtension::removeObjectsFromDocument()
{
const std::vector<DocumentObject*> & grp = Group.getValues();

View File

@@ -53,9 +53,9 @@ public:
/* Adds the object \a obj to this group. Returns all objects that have been added.
*/
virtual std::vector<DocumentObject*> addObject(DocumentObject* obj);
/* Adds an array of object \a objs to this group.
/* Adds the objects \a objs to this group. Returns all objects that have been added.
*/
virtual void addObjects(const std::vector<App::DocumentObject*>& objs);
virtual std::vector<DocumentObject*> addObjects(std::vector<DocumentObject*> obj);
/*override this function if you want only special objects
*/
virtual bool allowObject(DocumentObject* ) {return true;}
@@ -63,6 +63,9 @@ public:
/** Removes an object from this group. Returns all objects that have been removed.
*/
virtual std::vector<DocumentObject*> removeObject(DocumentObject* obj);
/** Removes objects from this group. Returns all objects that have been removed.
*/
virtual std::vector<DocumentObject*> removeObjects(std::vector<DocumentObject*> obj);
/** Removes all children objects from this group and the document.
*/
virtual void removeObjectsFromDocument();

View File

@@ -18,15 +18,25 @@
<UserDocu>Create and add an object with given type and name to the group</UserDocu>
</Documentation>
</Methode>
<Methode Name="addObject">
<Documentation>
<UserDocu>Add an object to the group</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeObject">
<Documentation>
<UserDocu>Remove an object from the group</UserDocu>
</Documentation>
<Methode Name="addObject">
<Documentation>
<UserDocu>Add an object to the group</UserDocu>
</Documentation>
</Methode>
<Methode Name="addObjects">
<Documentation>
<UserDocu>Adds multiple objects to the group. Expects a list.</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeObject">
<Documentation>
<UserDocu>Remove an object from the group</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeObjects">
<Documentation>
<UserDocu>Remove multiple objects from the group. Expects a list.</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeObjectsFromDocument">
<Documentation>

View File

@@ -94,6 +94,43 @@ PyObject* GroupExtensionPy::addObject(PyObject *args)
return Py::new_reference_to(list);
}
PyObject* GroupExtensionPy::addObjects(PyObject *args) {
PyObject *object;
if (!PyArg_ParseTuple(args, "O", &object)) // convert args: Python->C
return NULL; // NULL triggers exception
if (PyTuple_Check(object) || PyList_Check(object)) {
Py::Sequence list(object);
Py::Sequence::size_type size = list.size();
std::vector<DocumentObject*> values;
values.resize(size);
for (Py::Sequence::size_type i = 0; i < size; i++) {
Py::Object item = list[i];
if (!PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) {
std::string error = std::string("type in list must be 'DocumentObject', not ");
error += (*item)->ob_type->tp_name;
throw Base::TypeError(error);
}
values[i] = static_cast<DocumentObjectPy*>(*item)->getDocumentObjectPtr();
}
GroupExtension* grp = getGroupExtensionPtr();
auto vec = grp->addObjects(values);
Py::List result;
for (App::DocumentObject* obj : vec)
result.append(Py::asObject(obj->getPyObject()));
return Py::new_reference_to(result);
}
std::string error = std::string("type must be list of 'DocumentObject', not ");
error += object->ob_type->tp_name;
throw Base::TypeError(error);
};
PyObject* GroupExtensionPy::removeObject(PyObject *args)
{
PyObject *object;
@@ -120,6 +157,43 @@ PyObject* GroupExtensionPy::removeObject(PyObject *args)
return Py::new_reference_to(list);
}
PyObject* GroupExtensionPy::removeObjects(PyObject *args) {
PyObject *object;
if (!PyArg_ParseTuple(args, "O", &object)) // convert args: Python->C
return NULL; // NULL triggers exception
if (PyTuple_Check(object) || PyList_Check(object)) {
Py::Sequence list(object);
Py::Sequence::size_type size = list.size();
std::vector<DocumentObject*> values;
values.resize(size);
for (Py::Sequence::size_type i = 0; i < size; i++) {
Py::Object item = list[i];
if (!PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) {
std::string error = std::string("type in list must be 'DocumentObject', not ");
error += (*item)->ob_type->tp_name;
throw Base::TypeError(error);
}
values[i] = static_cast<DocumentObjectPy*>(*item)->getDocumentObjectPtr();
}
GroupExtension* grp = getGroupExtensionPtr();
auto vec = grp->removeObjects(values);
Py::List result;
for (App::DocumentObject* obj : vec)
result.append(Py::asObject(obj->getPyObject()));
return Py::new_reference_to(result);
}
std::string error = std::string("type must be list of 'DocumentObject', not ");
error += object->ob_type->tp_name;
throw Base::TypeError(error);
};
PyObject* GroupExtensionPy::removeObjectsFromDocument(PyObject *args)
{
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C

View File

@@ -184,9 +184,12 @@ void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
}
}
std::vector< DocumentObject* > OriginGroupExtension::addObject(DocumentObject* obj) {
relinkToOrigin(obj);
return App::GeoFeatureGroupExtension::addObject(obj);
std::vector< DocumentObject* > OriginGroupExtension::addObjects(std::vector<DocumentObject*> objs) {
for(auto obj : objs)
relinkToOrigin(obj);
return App::GeoFeatureGroupExtension::addObjects(objs);
}

View File

@@ -66,7 +66,7 @@ public:
//changes all links of obj to a origin to point to this groupes origin
void relinkToOrigin(App::DocumentObject* obj);
virtual std::vector<DocumentObject*> addObject(DocumentObject* obj) override;
virtual std::vector<DocumentObject*> addObjects(std::vector<DocumentObject*> obj) override;
protected:
/// Checks integrity of the Origin