1 // Copyright (C) 2014-2019 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)
30 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
31 myRef->Append(aData->label().Father()); // store label of the object
32 myIDs->Append(""); // for the object store an empty string
33 // do it before the transaction finish to make just created/removed objects know dependencies
34 // and reference from composite feature is removed automatically
35 ADD_BACK_REF(theObject);
37 owner()->data()->sendAttributeUpdated(this);
40 void Model_AttributeRefAttrList::append(AttributePtr theAttr)
42 std::shared_ptr<Model_Data> aData =
43 std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
44 myRef->Append(aData->label().Father()); // store label of the object
45 myIDs->Append(theAttr->id().c_str()); // store the ID of the referenced attribute
46 // do it before the transaction finish to make just created/removed objects know dependencies
47 // and reference from composite feature is removed automatically
48 ADD_BACK_REF(theAttr->owner());
50 owner()->data()->sendAttributeUpdated(this);
53 void Model_AttributeRefAttrList::remove(ObjectPtr theObject)
56 if (theObject.get() != NULL) {
57 aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theObject->data())->label().Father();
59 std::shared_ptr<Model_Document> aDoc =
60 std::dynamic_pointer_cast<Model_Document>(owner()->document());
61 // remove from the both lists by clearing the list and then appending one by one
62 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
63 TDF_LabelList aRefList = myRef->List();
65 TDataStd_ListOfExtendedString anIDList = myIDs->List();
67 bool aOneisDeleted = false;
68 TDF_ListIteratorOfLabelList aRefIter(aRefList);
69 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
70 for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
71 // append now only not removed
72 if (aOneisDeleted || aRefIter.Value() != aTheObjLab || !anIDIter.Value().IsEmpty() ||
73 (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
74 myRef->Append(aRefIter.Value());
75 myIDs->Append(anIDIter.Value());
76 } else if (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL) {
81 REMOVE_BACK_REF(theObject);
82 owner()->data()->sendAttributeUpdated(this);
86 void Model_AttributeRefAttrList::remove(AttributePtr theAttr)
89 if (theAttr->owner().get() != NULL) {
90 aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data())->label().Father();
92 std::shared_ptr<Model_Document> aDoc =
93 std::dynamic_pointer_cast<Model_Document>(owner()->document());
94 // remove from the both lists by clearing the list and then appending one by one
95 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
96 TDF_LabelList aRefList = myRef->List();
98 TDataStd_ListOfExtendedString anIDList = myIDs->List();
100 bool aOneisDeleted = false;
101 TDF_ListIteratorOfLabelList aRefIter(aRefList);
102 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
103 for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
104 if (aOneisDeleted || anIDIter.Value() != theAttr->id().c_str() ||
105 // append now only not removed
106 aRefIter.Value() != aTheObjLab || // append now only not removed
107 (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
108 myRef->Append(aRefIter.Value());
109 myIDs->Append(anIDIter.Value());
111 aOneisDeleted = true;
115 REMOVE_BACK_REF(theAttr->owner());
116 owner()->data()->sendAttributeUpdated(this);
120 void Model_AttributeRefAttrList::clear()
122 std::list<std::pair<ObjectPtr, AttributePtr> > anOldList = list();
125 std::list<std::pair<ObjectPtr, AttributePtr> >::iterator anOldIter = anOldList.begin();
126 for(; anOldIter != anOldList.end(); anOldIter++) {
127 REMOVE_BACK_REF((anOldIter->first));
129 owner()->data()->sendAttributeUpdated(this);
132 int Model_AttributeRefAttrList::size() const
134 return myRef->Extent();
137 bool Model_AttributeRefAttrList::isInitialized()
139 if (size() == 0) { // empty list is not initialized list: sketch will be not valid after add/undo
142 return ModelAPI_AttributeRefAttrList::isInitialized();
145 std::list<std::pair<ObjectPtr, AttributePtr> > Model_AttributeRefAttrList::list()
147 std::list<std::pair<ObjectPtr, AttributePtr> > aResult;
148 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
149 owner()->document());
151 const TDF_LabelList& aList = myRef->List();
152 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
153 TDF_ListIteratorOfLabelList aLIter(aList);
154 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
155 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
157 if (!aLIter.Value().IsNull()) {
158 anObj = aDoc->objects()->object(aLIter.Value());
159 aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj,
160 anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
162 aResult.push_back(std::pair<ObjectPtr, AttributePtr>(ObjectPtr(), AttributePtr()));
169 bool Model_AttributeRefAttrList::isInList(const ObjectPtr& theObj)
174 std::list<ObjectPtr> aResult;
175 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
176 owner()->document());
178 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
179 if (aData.get() && aData->isValid()) {
180 TDF_Label anObjLab = aData->label().Father();
181 const TDF_LabelList& aList = myRef->List();
182 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
183 TDF_ListIteratorOfLabelList aLIter(aList);
184 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
185 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
186 if (anIDIter.Value().IsEmpty() && aLIter.Value().IsEqual(anObjLab)) {
195 bool Model_AttributeRefAttrList::isInList(const AttributePtr& theAttr)
197 if (!theAttr->owner().get()) {
200 std::list<ObjectPtr> aResult;
201 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
202 owner()->document());
204 std::shared_ptr<Model_Data> aData =
205 std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
206 if (aData.get() && aData->isValid()) {
207 TDF_Label anObjLab = aData->label().Father();
208 const TDF_LabelList& aList = myRef->List();
209 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
210 TDF_ListIteratorOfLabelList aLIter(aList);
211 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
212 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
213 if (anIDIter.Value() == theAttr->id().c_str() && aLIter.Value().IsEqual(anObjLab)) {
222 bool Model_AttributeRefAttrList::isAttribute(const int theIndex) const
224 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
225 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
227 for (; anIDIter.More(); anIDIter.Next()) {
229 if (anIndex == theIndex) {
230 return !anIDIter.Value().IsEmpty();
236 ObjectPtr Model_AttributeRefAttrList::object(const int theIndex) const
238 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
239 owner()->document());
241 const TDF_LabelList& aList = myRef->List();
243 for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
245 if (anIndex == theIndex) {
246 if (aLIter.Value().IsNull()) { // null label => null sub
249 return aDoc->objects()->object(aLIter.Value());
256 AttributePtr Model_AttributeRefAttrList::attribute(const int theIndex) const
258 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
259 owner()->document());
262 const TDF_LabelList& aList = myRef->List();
263 const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
264 TDF_ListIteratorOfLabelList aLIter(aList);
265 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
266 for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
268 if (anIndex == theIndex) {
269 if (aLIter.Value().IsNull()) { // null label => null sub
270 return AttributePtr();
272 return aDoc->objects()->object(aLIter.Value())->data()->
273 attribute(TCollection_AsciiString(anIDIter.Value().ToExtString()).ToCString());
277 return AttributePtr();
280 void Model_AttributeRefAttrList::removeLast()
282 // remove from the both lists by clearing the list and then appending one by one
283 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
284 std::set<int> aLastSet;
285 aLastSet.insert(size() - 1);
289 void Model_AttributeRefAttrList::remove(const std::set<int>& theIndices)
291 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
292 owner()->document());
293 if (aDoc && !myRef->IsEmpty()) {
294 // remove from the both lists by clearing the list and then appending one by one
295 // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
296 TDF_LabelList aRefList = myRef->List();
298 TDataStd_ListOfExtendedString anIDList = myIDs->List();
300 bool aOneisDeleted = false;
301 TDF_ListIteratorOfLabelList aRefIter(aRefList);
302 TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
303 for (int anIndex = 0; aRefIter.More(); aRefIter.Next(), anIDIter.Next(), anIndex++) {
304 if (theIndices.find(anIndex) == theIndices.end()) { // not found
305 myRef->Append(aRefIter.Value());
306 myIDs->Append(anIDIter.Value());
307 } else { // found, so need to update the dependencies
308 aOneisDeleted = true;
309 ObjectPtr anObj = aDoc->objects()->object(aRefIter.Value());
311 REMOVE_BACK_REF(anObj);
316 owner()->data()->sendAttributeUpdated(this);
321 Model_AttributeRefAttrList::Model_AttributeRefAttrList(TDF_Label& theLabel)
327 void Model_AttributeRefAttrList::reinit()
329 myIsInitialized = myLab.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
330 if (!myIsInitialized) {
331 myRef = TDataStd_ReferenceList::Set(myLab);
332 myIDs = TDataStd_ExtStringList::Set(myLab);
334 myLab.FindAttribute(TDataStd_ExtStringList::GetID(), myIDs);