1 // Copyright (C) 2014-2020 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "Model_AttributeRefAttrList.h"
21 #include "Model_Application.h"
22 #include "Model_Data.h"
23 #include "Model_Objects.h"
24 #include <ModelAPI_Feature.h>
25 #include <TDF_ListIteratorOfLabelList.hxx>
26 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
28 void Model_AttributeRefAttrList::append(ObjectPtr theObject)
32 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
33 aLabel = aData->label().Father();
36 myRef->Append(aLabel); // store label of the object
37 myIDs->Append(""); // for the object store an empty string
38 // do it before the transaction finish to make just created/removed objects know dependencies
39 // and reference from composite feature is removed automatically
40 ADD_BACK_REF(theObject);
42 owner()->data()->sendAttributeUpdated(this);
45 void Model_AttributeRefAttrList::append(AttributePtr theAttr)
47 std::shared_ptr<Model_Data> aData =
48 std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
49 myRef->Append(aData->label().Father()); // store label of the object
50 myIDs->Append(theAttr->id().c_str()); // store the ID of the referenced attribute
51 // do it before the transaction finish to make just created/removed objects know dependencies
52 // and reference from composite feature is removed automatically
53 ADD_BACK_REF(theAttr->owner());
55 owner()->data()->sendAttributeUpdated(this);
58 void Model_AttributeRefAttrList::remove(ObjectPtr theObject)
61 if (theObject.get() != NULL) {
62 aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theObject->data())->label().Father();
64 std::shared_ptr<Model_Document> aDoc =
65 std::dynamic_pointer_cast<Model_Document>(owner()->document());
66 // remove from the both lists by clearing the list and then appending one by one
67 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
68 TDF_LabelList aRefList = myRef->List();
70 TDataStd_ListOfExtendedString anIDList = myIDs->List();
72 bool aOneisDeleted = false;
73 TDF_ListIteratorOfLabelList aRefIter(aRefList);
74 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
75 for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
76 // append now only not removed
77 if (aOneisDeleted || aRefIter.Value() != aTheObjLab || !anIDIter.Value().IsEmpty() ||
78 (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
79 myRef->Append(aRefIter.Value());
80 myIDs->Append(anIDIter.Value());
81 } else if (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL) {
86 REMOVE_BACK_REF(theObject);
87 owner()->data()->sendAttributeUpdated(this);
91 void Model_AttributeRefAttrList::remove(AttributePtr theAttr)
94 if (theAttr->owner().get() != NULL) {
95 aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data())->label().Father();
97 std::shared_ptr<Model_Document> aDoc =
98 std::dynamic_pointer_cast<Model_Document>(owner()->document());
99 // remove from the both lists by clearing the list and then appending one by one
100 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
101 TDF_LabelList aRefList = myRef->List();
103 TDataStd_ListOfExtendedString anIDList = myIDs->List();
105 bool aOneisDeleted = false;
106 TDF_ListIteratorOfLabelList aRefIter(aRefList);
107 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
108 for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
109 if (aOneisDeleted || anIDIter.Value() != theAttr->id().c_str() ||
110 // append now only not removed
111 aRefIter.Value() != aTheObjLab || // append now only not removed
112 (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
113 myRef->Append(aRefIter.Value());
114 myIDs->Append(anIDIter.Value());
116 aOneisDeleted = true;
120 REMOVE_BACK_REF(theAttr->owner());
121 owner()->data()->sendAttributeUpdated(this);
125 void Model_AttributeRefAttrList::clear()
127 std::list<std::pair<ObjectPtr, AttributePtr> > anOldList = list();
130 std::list<std::pair<ObjectPtr, AttributePtr> >::iterator anOldIter = anOldList.begin();
131 for(; anOldIter != anOldList.end(); anOldIter++) {
132 REMOVE_BACK_REF((anOldIter->first));
134 owner()->data()->sendAttributeUpdated(this);
137 int Model_AttributeRefAttrList::size() const
139 return myRef->Extent();
142 bool Model_AttributeRefAttrList::isInitialized()
144 if (size() == 0) { // empty list is not initialized list: sketch will be not valid after add/undo
147 return ModelAPI_AttributeRefAttrList::isInitialized();
150 std::list<std::pair<ObjectPtr, AttributePtr> > Model_AttributeRefAttrList::list()
152 std::list<std::pair<ObjectPtr, AttributePtr> > aResult;
153 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
154 owner()->document());
156 const TDF_LabelList& aList = myRef->List();
157 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
158 TDF_ListIteratorOfLabelList aLIter(aList);
159 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
160 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
162 if (!aLIter.Value().IsNull()) {
163 anObj = aDoc->objects()->object(aLIter.Value());
164 aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj,
165 anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
167 aResult.push_back(std::pair<ObjectPtr, AttributePtr>(ObjectPtr(), AttributePtr()));
174 bool Model_AttributeRefAttrList::isInList(const ObjectPtr& theObj)
179 std::list<ObjectPtr> aResult;
180 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
181 owner()->document());
183 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
184 if (aData.get() && aData->isValid()) {
185 TDF_Label anObjLab = aData->label().Father();
186 const TDF_LabelList& aList = myRef->List();
187 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
188 TDF_ListIteratorOfLabelList aLIter(aList);
189 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
190 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
191 if (anIDIter.Value().IsEmpty() && aLIter.Value().IsEqual(anObjLab)) {
200 bool Model_AttributeRefAttrList::isInList(const AttributePtr& theAttr)
202 if (!theAttr->owner().get()) {
205 std::list<ObjectPtr> aResult;
206 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
207 owner()->document());
209 std::shared_ptr<Model_Data> aData =
210 std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
211 if (aData.get() && aData->isValid()) {
212 TDF_Label anObjLab = aData->label().Father();
213 const TDF_LabelList& aList = myRef->List();
214 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
215 TDF_ListIteratorOfLabelList aLIter(aList);
216 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
217 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
218 if (anIDIter.Value() == theAttr->id().c_str() && aLIter.Value().IsEqual(anObjLab)) {
227 bool Model_AttributeRefAttrList::isAttribute(const int theIndex) const
229 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
230 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
232 for (; anIDIter.More(); anIDIter.Next()) {
234 if (anIndex == theIndex) {
235 return !anIDIter.Value().IsEmpty();
241 ObjectPtr Model_AttributeRefAttrList::object(const int theIndex) const
243 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
244 owner()->document());
246 const TDF_LabelList& aList = myRef->List();
248 for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
250 if (anIndex == theIndex) {
251 if (aLIter.Value().IsNull()) { // null label => null sub
254 return aDoc->objects()->object(aLIter.Value());
261 AttributePtr Model_AttributeRefAttrList::attribute(const int theIndex) const
263 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
264 owner()->document());
267 const TDF_LabelList& aList = myRef->List();
268 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
269 TDF_ListIteratorOfLabelList aLIter(aList);
270 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
271 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
273 if (anIndex == theIndex) {
274 if (aLIter.Value().IsNull()) { // null label => null sub
275 return AttributePtr();
277 return aDoc->objects()->object(aLIter.Value())->data()->
278 attribute(TCollection_AsciiString(anIDIter.Value().ToExtString()).ToCString());
282 return AttributePtr();
285 void Model_AttributeRefAttrList::removeLast()
287 // remove from the both lists by clearing the list and then appending one by one
288 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
289 std::set<int> aLastSet;
290 aLastSet.insert(size() - 1);
294 void Model_AttributeRefAttrList::remove(const std::set<int>& theIndices)
296 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
297 owner()->document());
298 if (aDoc && !myRef->IsEmpty()) {
299 // remove from the both lists by clearing the list and then appending one by one
300 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
301 TDF_LabelList aRefList = myRef->List();
303 TDataStd_ListOfExtendedString anIDList = myIDs->List();
305 bool aOneisDeleted = false;
306 TDF_ListIteratorOfLabelList aRefIter(aRefList);
307 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
308 for (int anIndex = 0; aRefIter.More(); aRefIter.Next(), anIDIter.Next(), anIndex++) {
309 if (theIndices.find(anIndex) == theIndices.end()) { // not found
310 myRef->Append(aRefIter.Value());
311 myIDs->Append(anIDIter.Value());
312 } else { // found, so need to update the dependencies
313 aOneisDeleted = true;
315 if (!aRefIter.Value().IsNull())
316 anObj = aDoc->objects()->object(aRefIter.Value());
318 REMOVE_BACK_REF(anObj);
323 owner()->data()->sendAttributeUpdated(this);
328 Model_AttributeRefAttrList::Model_AttributeRefAttrList(TDF_Label& theLabel)
334 void Model_AttributeRefAttrList::reinit()
336 myIsInitialized = myLab.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
337 if (!myIsInitialized) {
338 myRef = TDataStd_ReferenceList::Set(myLab);
339 myIDs = TDataStd_ExtStringList::Set(myLab);
341 myLab.FindAttribute(TDataStd_ExtStringList::GetID(), myIDs);