From 353cb0b3156491b5985a504f65a6953af2c151b0 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 5 Apr 2016 15:52:56 +0300 Subject: [PATCH] Implementation of the issue #1307. Also make connected parameters from different documents updated correctly. --- src/Model/Model_AttributeRefList.cpp | 162 ++++++++++++++---- src/Model/Model_AttributeRefList.h | 15 +- src/Model/Model_Data.cpp | 2 +- src/Model/Model_Document.cpp | 6 +- src/Model/Model_Update.cpp | 5 +- .../ParametersPlugin_Parameter.cpp | 2 +- .../Test/TestConstraintConcidence.py | 2 +- 7 files changed, 157 insertions(+), 37 deletions(-) diff --git a/src/Model/Model_AttributeRefList.cpp b/src/Model/Model_AttributeRefList.cpp index cf45b99a9..36d11541c 100644 --- a/src/Model/Model_AttributeRefList.cpp +++ b/src/Model/Model_AttributeRefList.cpp @@ -10,27 +10,80 @@ #include "Model_Objects.h" #include #include +#include +#include using namespace std; void Model_AttributeRefList::append(ObjectPtr theObject) { - std::shared_ptr aData = std::dynamic_pointer_cast(theObject->data()); - myRef->Append(aData->label().Father()); // store label of the object + if (owner()->document() == theObject->document()) { + std::shared_ptr aData = std::dynamic_pointer_cast(theObject->data()); + myRef->Append(aData->label().Father()); // store label of the object + } else if (theObject.get() && theObject->data()->isValid()) { // reference to the other document + myRef->Append(myRef->Label()); + // if these attributes exist, the link is external: keep reference to access the label + std::ostringstream anIdString; // string with document Id + anIdString<document()->id(); + myExtDocRef->Append(anIdString.str().c_str()); + std::shared_ptr aData = std::dynamic_pointer_cast(theObject->data()); + TCollection_AsciiString anEntry; + TDF_Tool::Entry(aData->label().Father(), anEntry); + myExtDocRef->Append(anEntry); + } else return; // something is wrong + // do it before the transaction finish to make just created/removed objects know dependencies // and reference from composite feature is removed automatically ADD_BACK_REF(theObject); - owner()->data()->sendAttributeUpdated(this); } void Model_AttributeRefList::remove(ObjectPtr theObject) { - std::shared_ptr aData; if (theObject.get() != NULL) { - aData = std::dynamic_pointer_cast(theObject->data()); - myRef->Remove(aData->label().Father()); - REMOVE_BACK_REF(theObject); + if (owner()->document() == theObject->document()) { + std::shared_ptr aData; + aData = std::dynamic_pointer_cast(theObject->data()); + myRef->Remove(aData->label().Father()); + REMOVE_BACK_REF(theObject); + owner()->data()->sendAttributeUpdated(this); + } else { + // create new lists because for the current moment remove one of the duplicated elements + // from the list is buggy + TDF_LabelList anOldList = myRef->List(); + myRef->Clear(); + TDataStd_ListOfExtendedString anOldExts = myExtDocRef->List(); + myExtDocRef->Clear(); + + std::ostringstream anIdString; // string with document Id + anIdString<document()->id(); + std::shared_ptr aData = std::dynamic_pointer_cast(theObject->data()); + TCollection_AsciiString anEntry; + TDF_Tool::Entry(aData->label().Father(), anEntry); + bool aFound = false; + TDataStd_ListIteratorOfListOfExtendedString anExtIter(anOldExts); + for (TDF_ListIteratorOfLabelList aLIter(anOldList); aLIter.More(); aLIter.Next()) { + if (aLIter.Value() == myRef->Label()) { + if (anExtIter.Value() == anIdString.str().c_str()) { + TDataStd_ListIteratorOfListOfExtendedString anExtIter2 = anExtIter; + anExtIter2.Next(); + if (anExtIter2.Value() == anEntry) { // fully maches, so, remove(don't copy) + aFound = true; + continue; + } + } + myExtDocRef->Append(anExtIter.Value()); + anExtIter.Next(); + myExtDocRef->Append(anExtIter.Value()); + anExtIter.Next(); + } + myRef->Append(aLIter.Value()); + } + if (aFound) { + REMOVE_BACK_REF(theObject); + owner()->data()->sendAttributeUpdated(this); + } + } } else { // in case of empty object remove, the first empty object is removed from the list std::shared_ptr aDoc = std::dynamic_pointer_cast( @@ -42,12 +95,12 @@ void Model_AttributeRefList::remove(ObjectPtr theObject) if (anObj.get() == NULL) { myRef->Remove(aLIter.Value()); REMOVE_BACK_REF(theObject); + owner()->data()->sendAttributeUpdated(this); break; } } } } - owner()->data()->sendAttributeUpdated(this); } void Model_AttributeRefList::clear() @@ -58,6 +111,7 @@ void Model_AttributeRefList::clear() for(; anOldIter != anOldList.end(); anOldIter++) { REMOVE_BACK_REF((*anOldIter)); } + myExtDocRef->Clear(); owner()->data()->sendAttributeUpdated(this); } @@ -81,6 +135,33 @@ bool Model_AttributeRefList::isInitialized() return ModelAPI_AttributeRefList::isInitialized(); } +ObjectPtr Model_AttributeRefList::iteratedObject(TDF_ListIteratorOfLabelList& theLIter, + TDataStd_ListIteratorOfListOfExtendedString& theExtIter, + std::shared_ptr theDoc) const +{ + ObjectPtr anObj; + if (!theLIter.Value().IsNull() && !theLIter.Value().IsRoot()) { + if (theLIter.Value() == myRef->Label()) { // external document object + int anID = atoi(TCollection_AsciiString(theExtIter.Value()).ToCString()); + theExtIter.Next(); + DocumentPtr aRefDoc = Model_Application::getApplication()->document(anID); + if (aRefDoc.get()) { + std::shared_ptr aDR = std::dynamic_pointer_cast(aRefDoc); + TDF_Label aRefLab; + TDF_Tool::Label(aDR->objects()->featuresLabel().Data(), + TCollection_AsciiString(theExtIter.Value()).ToCString(), aRefLab); + if (!aRefLab.IsNull()) { + anObj = aDR->objects()->object(aRefLab); + } + } + theExtIter.Next(); + } else { // internal document object + anObj = theDoc->objects()->object(theLIter.Value()); + } + } + return anObj; +} + list Model_AttributeRefList::list() { std::list aResult; @@ -88,11 +169,9 @@ list Model_AttributeRefList::list() owner()->document()); if (aDoc) { const TDF_LabelList& aList = myRef->List(); + TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List()); for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { - ObjectPtr anObj; - if (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot()) - anObj = aDoc->objects()->object(aLIter.Value()); - aResult.push_back(anObj); + aResult.push_back(iteratedObject(aLIter, anExtIter, aDoc)); } } return aResult; @@ -103,18 +182,39 @@ bool Model_AttributeRefList::isInList(const ObjectPtr& theObj) if(!theObj.get()) { return false; } - std::list aResult; - std::shared_ptr aDoc = std::dynamic_pointer_cast( - owner()->document()); - if (aDoc) { + if (theObj->document() == owner()->document()) { // this document object + std::shared_ptr aDoc = std::dynamic_pointer_cast( + owner()->document()); + if (aDoc) { + std::shared_ptr aData = std::dynamic_pointer_cast(theObj->data()); + if (aData.get() && aData->isValid()) { + TDF_Label anObjLab = aData->label().Father(); + const TDF_LabelList& aList = myRef->List(); + for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { + if (aLIter.Value().IsEqual(anObjLab)) { + return true; + } + } + } + } + } else { // external document object + // create new lists because for the current moment remove one of the duplicated elements + // from the list is buggy + std::ostringstream anIdString; // string with document Id + anIdString<document()->id(); std::shared_ptr aData = std::dynamic_pointer_cast(theObj->data()); - if (aData.get() && aData->isValid()) { - TDF_Label anObjLab = aData->label().Father(); - const TDF_LabelList& aList = myRef->List(); - for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { - if (aLIter.Value().IsEqual(anObjLab)) { + TCollection_AsciiString anEntry; + TDF_Tool::Entry(aData->label().Father(), anEntry); + bool aFound = false; + TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List()); + for (; anExtIter.More(); anExtIter.Next()) { + if (anExtIter.Value() == anIdString.str().c_str()) { + anExtIter.Next(); + if (anExtIter.Value() == anEntry) { // fully maches return true; } + } else { + anExtIter.Next(); } } } @@ -123,19 +223,20 @@ bool Model_AttributeRefList::isInList(const ObjectPtr& theObj) ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty) const { - std::shared_ptr aDoc = std::dynamic_pointer_cast( - owner()->document()); + std::shared_ptr aDoc = + std::dynamic_pointer_cast(owner()->document()); if (aDoc) { - const TDF_LabelList& aList = myRef->List(); int anIndex = -1; - for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { + TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List()); + for (TDF_ListIteratorOfLabelList aLIter(myRef->List()); aLIter.More(); aLIter.Next()) { if (theWithEmpty || (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot())) anIndex++; if (anIndex == theIndex) { - if (aLIter.Value().IsNull() || aLIter.Value().IsRoot()) { // null label => null sub - return ObjectPtr(); - } - return aDoc->objects()->object(aLIter.Value()); + return iteratedObject(aLIter, anExtIter, aDoc); + } + if (aLIter.Value() == myRef->Label()) { + anExtIter.Next(); + anExtIter.Next(); } } } @@ -246,4 +347,7 @@ Model_AttributeRefList::Model_AttributeRefList(TDF_Label& theLabel) if (!myIsInitialized) { myRef = TDataStd_ReferenceList::Set(theLabel); } + if (!theLabel.FindAttribute(TDataStd_ExtStringList::GetID(), myExtDocRef)) { + myExtDocRef = TDataStd_ExtStringList::Set(theLabel); + } } diff --git a/src/Model/Model_AttributeRefList.h b/src/Model/Model_AttributeRefList.h index eaa1d9206..9f3df94af 100644 --- a/src/Model/Model_AttributeRefList.h +++ b/src/Model/Model_AttributeRefList.h @@ -12,16 +12,19 @@ #include "ModelAPI_Feature.h" #include +#include /**\class Model_AttributeRefList * \ingroup DataModel - * \brief Attribute that contains list of references to features (located in the same document). - * For the current moment it does not support references to objects in other documents. + * \brief Attribute that contains list of references to features, may be located in different documents. */ class Model_AttributeRefList : public ModelAPI_AttributeRefList { Handle_TDataStd_ReferenceList myRef; ///< references to the features labels + /// pairs of doc ID and entries if reference is to external object, appends some in this list if + /// something in myRef is empty + Handle_TDataStd_ExtStringList myExtDocRef; public: /// Appends the feature to the end of a list MODEL_EXPORT virtual void append(ObjectPtr theObject); @@ -48,15 +51,19 @@ class Model_AttributeRefList : public ModelAPI_AttributeRefList MODEL_EXPORT virtual ObjectPtr object(const int theIndex, const bool theWithEmpty = true) const; /// Substitutes the feature by another one. Does nothing if such object is not found. + /// Does not support the external documents objects yet. MODEL_EXPORT virtual void substitute(const ObjectPtr& theCurrent, const ObjectPtr& theNew); /// Substitutes the object by another one and back. So, features will become exchanged in the list + /// Does not support the external documents objects yet. MODEL_EXPORT virtual void exchange(const ObjectPtr& theObject1, const ObjectPtr& theObject2); /// Removes the last element in the list. + /// Does not support the external documents objects yet. MODEL_EXPORT virtual void removeLast(); /// Removes the elements from the list. + /// Does not support the external documents objects yet. /// \param theIndices a list of indices of elements to be removed MODEL_EXPORT virtual void remove(const std::set& theIndices); @@ -65,6 +72,10 @@ class Model_AttributeRefList : public ModelAPI_AttributeRefList protected: /// Objects are created for features automatically MODEL_EXPORT Model_AttributeRefList(TDF_Label& theLabel); + /// Returns the object by iterators (theExtIter is iterated if necessary) + ObjectPtr iteratedObject(TDF_ListIteratorOfLabelList& theLIter, + TDataStd_ListIteratorOfListOfExtendedString& theExtIter, + std::shared_ptr theDoc) const; friend class Model_Data; }; diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 3d16c14bb..e9d808ade 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -116,7 +116,7 @@ void Model_Data::setName(const std::string& theName) AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType) { AttributePtr aResult; - TDF_Label anAttrLab = myLab.FindChild(myAttrs.size() + 1); + TDF_Label anAttrLab = myLab.FindChild(int(myAttrs.size()) + 1); ModelAPI_Attribute* anAttr = 0; if (theAttrType == ModelAPI_AttributeDocRef::typeId()) { anAttr = new Model_AttributeDocRef(anAttrLab); diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 21823b4e0..7dd2b7366 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -975,6 +975,7 @@ void Model_Document::setCurrentFeature( bool aPassed = false; // flag that the current object is already passed in cycle FeaturePtr anIter = myObjs->lastFeature(); bool aWasChanged = false; + bool isCurrentParameter = theCurrent.get() && theCurrent->getKind() == "Parameter"; for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) { // check this before passed become enabled: the current feature is enabled! if (anIter == theCurrent) aPassed = true; @@ -988,9 +989,12 @@ void Model_Document::setCurrentFeature( } if (anIter->getKind() == "Parameter") {// parameters are always out of the history of features, but not parameters - if (theCurrent.get() && theCurrent->getKind() != "Parameter") + if (!isCurrentParameter) aDisabledFlag = false; + } else if (isCurrentParameter) { // if paramater is active, all other features become enabled (issue 1307) + aDisabledFlag = false; } + if (anIter->setDisabled(aDisabledFlag)) { // state of feature is changed => so feature become updated static Events_ID anUpdateEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED); diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index dfd0a4514..38549c395 100644 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -33,7 +33,7 @@ using namespace std; Model_Update MY_UPDATER_INSTANCE; /// the only one instance initialized on load of the library -#define DEB_UPDATE +//#define DEB_UPDATE Model_Update::Model_Update() { @@ -66,7 +66,9 @@ void Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) { } if (myModified.find(theFeature) != myModified.end()) { if (theReason.get()) { +#ifdef DEB_UPDATE std::cout<<"*** Add already modified "<name()<