diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index 4198c42426..6a6156e0f2 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -422,10 +422,12 @@ void DocumentObject::onChanged(const Property* prop) if (prop == &Label && _pDoc && oldLabel != Label.getStrValue()) _pDoc->signalRelabelObject(*this); - if (prop->getType() & Prop_Output) - return; - // set object touched - StatusBits.set(ObjectStatus::Touch); + // set object touched if it is a input ptoperty + if (!(prop->getType() & Prop_Output)) + StatusBits.set(0); + + //call the parent for appropriate handling + TransactionalObject::onChanged(prop); } PyObject *DocumentObject::getPyObject(void) diff --git a/src/App/GroupExtension.cpp b/src/App/GroupExtension.cpp index bd092dd8c1..b34da464b5 100644 --- a/src/App/GroupExtension.cpp +++ b/src/App/GroupExtension.cpp @@ -32,6 +32,7 @@ #include "Document.h" #include "FeaturePythonPyImp.h" #include "GeoFeatureGroupExtension.h" +#include using namespace App; @@ -75,8 +76,14 @@ std::vector GroupExtension::addObject(DocumentObject* obj) //if we are on a geofeaturegroup we need to ensure the object is too auto geogrp = GeoFeatureGroupExtension::getGroupOfObject(getExtendedObject()); - if( geogrp && (geogrp != GeoFeatureGroupExtension::getGroupOfObject(obj)) ) - geogrp->getExtensionByType()->addObject(obj); + 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()->addObject(obj); + else + objgrp->getExtensionByType()->removeObject(obj); + } std::vector grp = Group.getValues(); grp.push_back(obj); @@ -245,19 +252,29 @@ PyObject* GroupExtension::getExtensionPyObject(void) { void GroupExtension::extensionOnChanged(const Property* p) { - //we need to remove all object that have other parent geofeature groups - if(strcmp(p->getName(), "Group")==0) { + //objects are only allowed in a single group. Note that this check must only be done for normal + //groups, not any derived classes + if((this->getExtensionTypeId() == GroupExtension::getExtensionClassTypeId()) && + (strcmp(p->getName(), "Group")==0)) { bool error = false; auto corrected = Group.getValues(); for(auto obj : Group.getValues()) { - auto grp = GroupExtension::getGroupOfObject(obj); - if(grp && (grp != getExtendedObject())) { - error = true; - corrected.erase(std::remove(corrected.begin(), corrected.end(), obj), corrected.end()); + //we have already set the obj into the group, so in a case of multiple groups getGroupOfObject + //would return anyone of it and hence it is possible that we miss an error. We need a custom check + auto list = obj->getInList(); + for (auto in : list) { + if(in->hasExtension(App::GroupExtension::getExtensionClassTypeId(), false) && + in != getExtendedObject()) { + error = true; + corrected.erase(std::remove(corrected.begin(), corrected.end(), obj), corrected.end()); + break; + } } - } + } + + //if an error was found we need to correct the values and inform the user if(error) { Group.setValues(corrected); throw Base::Exception("Object can only be in a single Group"); diff --git a/src/Mod/Test/Document.py b/src/Mod/Test/Document.py index c1a9d051e9..039a9c581c 100644 --- a/src/Mod/Test/Document.py +++ b/src/Mod/Test/Document.py @@ -862,14 +862,28 @@ class UndoRedoCases(unittest.TestCase): self.failUnless(prt1.hasObject(obj1)==False) self.failUnless(prt2.hasObject(grp2)) self.failUnless(prt2.hasObject(obj1)) + + #to test: try add obj to second group by .Group = [] + grp = prt1.Group + grp.append(grp2) + try: + prt1.Group=grp + except: + pass + else: + self.fail("No exception at cross geofeaturegroup links") - #adding the object to a geofeaturegroup, but not its group, should handle it automatically when used - #addObject - - #to test: try add obj to second group, once by addObject, once by .Group = [] - - #test set links over geofeaturegroup borders - + prt2.addObject(grp1) + grp = grp1.Group + grp.append(obj1) + try: + grp1.Group = grp + except: + pass + else: + self.fail("No exception thrown when object is in multiple Groups") + + def tearDown(self): # closing doc