Salome HOME
1ee46e331e9d07ca4d2c47980bf40cdea6af65a0
[modules/shaper.git] / src / XGUI / XGUI_DocumentDataModel.cpp
1 #include "XGUI_DocumentDataModel.h"
2 #include "XGUI_PartDataModel.h"
3
4 #include <ModelAPI_PluginManager.h>
5 #include <ModelAPI_Iterator.h>
6 #include <ModelAPI_Document.h>
7 #include <ModelAPI_Feature.h>
8 #include <ModelAPI_Data.h>
9 #include <Model_Events.h>
10
11 #include <Events_Loop.h>
12
13
14 #include <QIcon>
15 #include <QString>
16
17
18 XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
19   : QAbstractItemModel(theParent)
20 {
21   // Find Document object
22   boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
23   myDocument = aMgr->currentDocument();
24
25   // Register in event loop
26   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
27   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
28   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
29
30   // Create a top part of data tree model
31   myModel = new XGUI_TopDataModel(myDocument, this);
32 }
33
34
35 XGUI_DocumentDataModel::~XGUI_DocumentDataModel()
36 {
37   clearModelIndexes();
38 }
39
40
41 void XGUI_DocumentDataModel::processEvent(const Events_Message* theMessage)
42 {
43   // Created object event *******************
44   if (QString(theMessage->eventID().eventText()) == EVENT_FEATURE_CREATED) {
45     const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
46     boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
47     boost::shared_ptr<ModelAPI_Document> aDoc = aFeature->document();
48
49     if (aDoc == myDocument) {  // If root objects
50       if (aFeature->getGroup().compare(PARTS_GROUP) == 0) { // Updsate only Parts group
51         // Add a new part
52         int aStart = myModel->rowCount(QModelIndex()) + myPartModels.size() + 1;
53         XGUI_PartDataModel* aModel = new XGUI_PartDataModel(myDocument, this);
54         aModel->setPartId(myPartModels.count());
55         myPartModels.append(aModel);
56         insertRows(QModelIndex(), aStart, aStart);
57       } else { // Update top groups (other except parts
58         QModelIndex aIndex = myModel->findParent(aFeature);
59         int aStart = myModel->rowCount(aIndex) - 1;
60         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
61         insertRows(aIndex, aStart, aStart);
62       }
63     } else { // if sub-objects of first level nodes
64       XGUI_PartModel* aPartModel = 0;
65       QList<XGUI_PartModel*>::const_iterator aIt;
66       for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
67         if ((*aIt)->hasDocument(aDoc)) {
68           aPartModel = (*aIt);
69           break;
70         }
71       }
72       if (aPartModel) {
73         QModelIndex aIndex = aPartModel->findParent(aFeature);
74         int aStart = aPartModel->rowCount(aIndex) - 1;
75         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
76         insertRows(aIndex, aStart, aStart);
77       }
78     }
79
80   // Deteted object event ***********************
81   } else if (QString(theMessage->eventID().eventText()) == EVENT_FEATURE_DELETED) {
82     const Model_FeatureDeletedMessage* aUpdMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
83     boost::shared_ptr<ModelAPI_Document> aDoc = aUpdMsg->document();
84
85     if (aDoc == myDocument) {  // If root objects
86       if (aUpdMsg->group().compare(PARTS_GROUP) == 0) { // Updsate only Parts group
87         int aStart = myModel->rowCount(QModelIndex()) + myPartModels.size() - 1;
88         beginRemoveRows(QModelIndex(), aStart, aStart);
89         removeSubModel(myPartModels.size() - 1);
90         endRemoveRows();
91       } else { // Update top groups (other except parts
92         QModelIndex aIndex = myModel->findGroup(aUpdMsg->group());
93         int aStart = myModel->rowCount(aIndex);
94         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
95         beginRemoveRows(aIndex, aStart, aStart);
96         endRemoveRows();
97       }
98     } else {
99       XGUI_PartModel* aPartModel = 0;
100       QList<XGUI_PartModel*>::const_iterator aIt;
101       for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
102         if ((*aIt)->hasDocument(aDoc)) {
103           aPartModel = (*aIt);
104           break;
105         }
106       }
107       if (aPartModel) {
108         QModelIndex aIndex = aPartModel->findGroup(aUpdMsg->group());
109         int aStart = aPartModel->rowCount(aIndex);
110         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
111         beginRemoveRows(aIndex, aStart, aStart);
112         endRemoveRows();
113       }
114     }
115
116   // Reset whole tree **************************
117   } else {  
118     beginResetModel();
119     int aNbParts = myDocument->featuresIterator(PARTS_GROUP)->numIterationsLeft();
120     if (myPartModels.size() != aNbParts) { // resize internal models
121       while (myPartModels.size() > aNbParts) {
122         delete myPartModels.last();
123         myPartModels.removeLast();
124       }
125       while (myPartModels.size() < aNbParts) {
126         myPartModels.append(new XGUI_PartDataModel(myDocument, this));
127       }
128       for (int i = 0; i < myPartModels.size(); i++)
129         myPartModels.at(i)->setPartId(i);
130     }
131     clearModelIndexes();
132     endResetModel();
133   }
134 }
135
136 QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
137 {
138   if (!theIndex.isValid())
139     return QVariant();
140   return toSourceModelIndex(theIndex).data(theRole);
141 }
142
143
144 QVariant XGUI_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
145 {
146   return QVariant();
147 }
148
149 int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
150 {
151   if (!theParent.isValid()) {
152     int aVal = myModel->rowCount(theParent) + myPartModels.size();
153     return myModel->rowCount(theParent) + myPartModels.size();
154   }
155   QModelIndex aParent = toSourceModelIndex(theParent);
156   if (!hasSubModel(aParent.model())) 
157     return 0;
158
159   return aParent.model()->rowCount(aParent);
160 }
161
162 int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
163 {
164   return 1;
165 }
166
167 QModelIndex XGUI_DocumentDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
168 {
169   QModelIndex aIndex;
170   if (!theParent.isValid()) {
171     int aOffs = myModel->rowCount();
172     if (theRow < aOffs) 
173       aIndex = myModel->index(theRow, theColumn, theParent);
174     else  {
175       if (myPartModels.size() > 0) {
176         int aPos = theRow - aOffs;
177         if (aPos >= myPartModels.size())
178           aPos = 0;
179         aIndex = myPartModels.at(aPos)->index(aPos, theColumn, theParent);
180       } else 
181         return aIndex;
182     }
183     aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
184   } else {
185     QModelIndex* aParent = (QModelIndex*)theParent.internalPointer();
186     aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
187
188     aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
189   }
190   return aIndex;
191 }
192
193
194 QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
195 {
196   QModelIndex aParent = toSourceModelIndex(theIndex);
197   if (!hasSubModel(aParent.model())) 
198     return QModelIndex();
199
200   aParent = aParent.model()->parent(aParent);
201   if (aParent.isValid())
202     return createIndex(aParent.row(), aParent.column(), (void*)getModelIndex(aParent));
203   return aParent;
204 }
205
206
207 bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
208 {
209   if (!theParent.isValid())
210     return true;
211   return rowCount(theParent) > 0;
212 }
213
214
215 QModelIndex XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
216 {
217   QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
218   return (*aIndexPtr);
219 }
220
221
222 QModelIndex* XGUI_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
223 {
224   QList<QModelIndex*>::const_iterator aIt;
225   for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
226     QModelIndex* aIndex = (*aIt);
227     if ((*aIndex) == theIndex)
228       return aIndex;
229   }
230   return 0;
231 }
232
233 QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
234 {
235   QModelIndex* aIndexPtr = findModelIndex(theIndex);
236   if (!aIndexPtr) {
237     aIndexPtr = new QModelIndex(theIndex);
238     XGUI_DocumentDataModel* that = (XGUI_DocumentDataModel*) this;
239     that->myIndexes.append(aIndexPtr);
240   }
241   return aIndexPtr;
242 }
243
244 void XGUI_DocumentDataModel::clearModelIndexes()
245 {
246   QList<QModelIndex*>::const_iterator aIt;
247   for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) 
248     delete (*aIt);
249   myIndexes.clear();
250 }
251
252 FeaturePtr XGUI_DocumentDataModel::feature(const QModelIndex& theIndex) const
253 {
254   QModelIndex aIndex = toSourceModelIndex(theIndex);
255   if (!hasSubModel(aIndex.model())) 
256     return FeaturePtr();
257
258   const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex.model());
259   return aModel->feature(aIndex);
260 }
261
262 void XGUI_DocumentDataModel::insertRows(const QModelIndex& theParent, int theStart, int theEnd)
263 {
264   beginInsertRows(theParent, theStart, theEnd);
265   endInsertRows();
266   if (theStart == 0) // Update parent if this is a first child in order to update node decoration
267     emit dataChanged(theParent, theParent);
268 }
269
270 void XGUI_DocumentDataModel::removeSubModel(int theModelId)
271 {
272   XGUI_PartModel* aModel = myPartModels.at(theModelId);
273   QIntList aToRemove;
274   for (int i = 0; i < myIndexes.size(); i++) {
275     if (myIndexes.at(i)->model() == aModel)
276       aToRemove.append(i);
277   }
278   int aId;
279   while(aToRemove.size() > 0) {
280     aId = aToRemove.last();
281     delete myIndexes.at(aId);
282     myIndexes.removeAt(aId);
283     aToRemove.removeLast();
284   }
285   delete aModel;
286   myPartModels.removeAt(theModelId);
287 }
288
289 bool XGUI_DocumentDataModel::hasSubModel(const QAbstractItemModel* theModel) const
290 {
291   if (theModel == myModel)
292     return true;
293   QList<XGUI_PartModel*>::const_iterator aIt;
294   for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) 
295     if ((*aIt) == theModel)
296       return true;
297   return false;
298 }