]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_DocumentDataModel.cpp
Salome HOME
Functionality for dynamic libraries loading is assigned to Config_ModuleReader
[modules/shaper.git] / src / XGUI / XGUI_DocumentDataModel.cpp
1 #include "XGUI_DocumentDataModel.h"
2 #include "XGUI_PartDataModel.h"
3 #include "XGUI_Workshop.h"
4
5 #include <ModelAPI_PluginManager.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 #include <Config_FeatureMessage.h>
14
15 #include <QIcon>
16 #include <QString>
17
18
19 XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
20   : QAbstractItemModel(theParent)
21 {
22   // Find Document object
23   boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
24   myDocument = aMgr->currentDocument();
25
26   // Register in event loop
27   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
28   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
29   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
30
31   // Create a top part of data tree model
32   myModel = new XGUI_TopDataModel(myDocument, this);
33 }
34
35
36 XGUI_DocumentDataModel::~XGUI_DocumentDataModel()
37 {
38   clearModelIndexes();
39 }
40
41
42 void XGUI_DocumentDataModel::processEvent(const Events_Message* theMessage)
43 {
44   // Created object event *******************
45   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_CREATED)) {
46     const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
47     boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
48     boost::shared_ptr<ModelAPI_Document> aDoc = aFeature->document();
49
50     if (aDoc == myDocument) {  // If root objects
51       if (aFeature->getGroup().compare(PARTS_GROUP) == 0) { // Update only Parts group
52         // Add a new part
53         int aStart = myPartModels.size() + 1;
54         XGUI_PartDataModel* aModel = new XGUI_PartDataModel(myDocument, this);
55         aModel->setPartId(myPartModels.count());
56         myPartModels.append(aModel);
57         insertRow(aStart, partFolderNode());
58       } else { // Update top groups (other except parts
59         QModelIndex aIndex = myModel->findParent(aFeature);
60         int aStart = myModel->rowCount(aIndex) - 1;
61         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
62         insertRow(aStart, aIndex);
63       }
64     } else { // if sub-objects of first level nodes
65       XGUI_PartModel* aPartModel = 0;
66       QList<XGUI_PartModel*>::const_iterator aIt;
67       for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
68         if ((*aIt)->hasDocument(aDoc)) {
69           aPartModel = (*aIt);
70           break;
71         }
72       }
73       if (aPartModel) {
74         QModelIndex aIndex = aPartModel->findParent(aFeature);
75         int aStart = aPartModel->rowCount(aIndex) - 1;
76         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
77         insertRow(aStart, aIndex);
78       }
79     }
80
81   // Deleted object event ***********************
82   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_DELETED)) {
83     const Model_FeatureDeletedMessage* aUpdMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
84     boost::shared_ptr<ModelAPI_Document> aDoc = aUpdMsg->document();
85
86     if (aDoc == myDocument) {  // If root objects
87       if (aUpdMsg->group().compare(PARTS_GROUP) == 0) { // Updsate only Parts group
88         int aStart = myPartModels.size();
89         removeSubModel(myPartModels.size() - 1);
90         removeRow(aStart - 1, partFolderNode());
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         removeRow(aStart - 1, aIndex);
96       }
97     } else {
98       XGUI_PartModel* aPartModel = 0;
99       QList<XGUI_PartModel*>::const_iterator aIt;
100       for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
101         if ((*aIt)->hasDocument(aDoc)) {
102           aPartModel = (*aIt);
103           break;
104         }
105       }
106       if (aPartModel) {
107         QModelIndex aIndex = aPartModel->findGroup(aUpdMsg->group());
108         int aStart = aPartModel->rowCount(aIndex);
109         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
110         removeRow(aStart - 1, aIndex);
111       }
112     }
113
114   // Deleted object event ***********************
115   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED)) {
116     //const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
117     //boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
118     //boost::shared_ptr<ModelAPI_Document> aDoc = aFeature->document();
119     
120     // TODO: Identify the necessary index by the modified feature
121     QModelIndex aIndex;
122     emit dataChanged(aIndex, aIndex);
123
124   // Reset whole tree **************************
125   } else {  
126     beginResetModel();
127     int aNbParts = myDocument->size(PARTS_GROUP);
128     if (myPartModels.size() != aNbParts) { // resize internal models
129       while (myPartModels.size() > aNbParts) {
130         delete myPartModels.last();
131         myPartModels.removeLast();
132       }
133       while (myPartModels.size() < aNbParts) {
134         myPartModels.append(new XGUI_PartDataModel(myDocument, this));
135       }
136       for (int i = 0; i < myPartModels.size(); i++)
137         myPartModels.at(i)->setPartId(i);
138     }
139     clearModelIndexes();
140     endResetModel();
141   }
142 }
143
144 QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
145 {
146   if (!theIndex.isValid())
147     return QVariant();
148   switch (theIndex.internalId()) {
149   case PartsFolder:
150     switch (theRole) {
151     case Qt::DisplayRole:
152       return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
153     case Qt::DecorationRole:
154       return QIcon(":pictures/constr_folder.png");
155     case Qt::ToolTipRole:
156       return tr("Parts folder");
157     default:
158       return QVariant();
159     }
160     break;
161   case HistoryNode:
162     {
163       int aOffset = historyOffset();
164       FeaturePtr aFeature = myDocument->feature(FEATURES_GROUP, theIndex.row() - aOffset);
165       if (!aFeature)
166         return QVariant();
167       switch (theRole) {
168       case Qt::DisplayRole:
169         if (aFeature)
170           return aFeature->data()->getName().c_str();
171         else 
172           return QVariant();
173       case Qt::DecorationRole:
174         return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
175       case Qt::ToolTipRole:
176         return tr("Feature object");
177       default:
178         return QVariant();
179       }
180     }
181     break;
182   }
183   QModelIndex aParent = theIndex.parent();
184   if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
185     return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
186   }
187   return toSourceModelIndex(theIndex).data(theRole);
188 }
189
190
191 QVariant XGUI_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
192 {
193   return QVariant();
194 }
195
196 int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
197 {
198   if (!theParent.isValid()) {
199     // Size of external models
200     int aVal = historyOffset();
201     // Plus history size
202     aVal += myDocument->size(FEATURES_GROUP);
203     return aVal;
204   }
205   if (theParent.internalId() == PartsFolder) {
206     return myPartModels.size();
207   }
208   if (theParent.internalId() == HistoryNode) {
209     return 0;
210   }
211   QModelIndex aParent = toSourceModelIndex(theParent);
212   if (!isSubModel(aParent.model())) 
213     return 0;
214
215   return aParent.model()->rowCount(aParent);
216 }
217
218 int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
219 {
220   return 1;
221 }
222
223 QModelIndex XGUI_DocumentDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
224 {
225   QModelIndex aIndex;
226   if (!theParent.isValid()) {
227     int aOffs = myModel->rowCount();
228     if (theRow < aOffs) {
229       aIndex = myModel->index(theRow, theColumn, theParent);
230       aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
231     } else {
232       if (theRow == aOffs)  // Create Parts node
233         aIndex = partFolderNode();
234       else // create history node
235         aIndex = createIndex(theRow, theColumn, HistoryNode);
236     }
237   } else {
238     if (theParent.internalId() == PartsFolder) {
239       aIndex = myPartModels.at(theRow)->index(0, theColumn, QModelIndex());
240     } else {
241       QModelIndex* aParent = (QModelIndex*)theParent.internalPointer();
242       aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
243     }
244     aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
245   }
246   return aIndex;
247 }
248
249
250 QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
251 {
252   if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
253     return QModelIndex();
254
255   QModelIndex aIndex = toSourceModelIndex(theIndex);
256   const QAbstractItemModel* aModel = aIndex.model();
257   if (!isSubModel(aModel)) 
258     return QModelIndex();
259
260   if (isPartSubModel(aModel)) {
261     if (!aModel->parent(aIndex).isValid()) {
262       return partFolderNode();
263     }
264   }
265
266   aIndex = aModel->parent(aIndex);
267   if (aIndex.isValid())
268     return createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
269   return aIndex;
270 }
271
272
273 bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
274 {
275   if (!theParent.isValid())
276     return true;
277   return rowCount(theParent) > 0;
278 }
279
280
281 QModelIndex XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
282 {
283   QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
284   return (*aIndexPtr);
285 }
286
287
288 QModelIndex* XGUI_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
289 {
290   QList<QModelIndex*>::const_iterator aIt;
291   for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
292     QModelIndex* aIndex = (*aIt);
293     if ((*aIndex) == theIndex)
294       return aIndex;
295   }
296   return 0;
297 }
298
299 QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
300 {
301   QModelIndex* aIndexPtr = findModelIndex(theIndex);
302   if (!aIndexPtr) {
303     aIndexPtr = new QModelIndex(theIndex);
304     XGUI_DocumentDataModel* that = (XGUI_DocumentDataModel*) this;
305     that->myIndexes.append(aIndexPtr);
306   }
307   return aIndexPtr;
308 }
309
310 void XGUI_DocumentDataModel::clearModelIndexes()
311 {
312   QList<QModelIndex*>::const_iterator aIt;
313   for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) 
314     delete (*aIt);
315   myIndexes.clear();
316 }
317
318 FeaturePtr XGUI_DocumentDataModel::feature(const QModelIndex& theIndex) const
319 {
320   if (theIndex.internalId() == PartsFolder)
321     return FeaturePtr();
322   if (theIndex.internalId() == HistoryNode) {
323       int aOffset = historyOffset();
324       return myDocument->feature(FEATURES_GROUP, theIndex.row() - aOffset);
325   }
326   QModelIndex aIndex = toSourceModelIndex(theIndex);
327   if (!isSubModel(aIndex.model())) 
328     return FeaturePtr();
329
330   const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex.model());
331   return aModel->feature(aIndex);
332 }
333
334 bool XGUI_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
335 {
336   beginInsertRows(theParent, theRow, theRow + theCount - 1);
337   //endInsertRows();
338
339   // Update history
340   QModelIndex aRoot;
341   int aRow = rowCount(aRoot);
342   beginInsertRows(aRoot, aRow, aRow);
343   endInsertRows();
344
345   return true;
346 }
347
348 bool XGUI_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
349 {
350   beginRemoveRows(theParent, theRow, theRow + theCount - 1);
351   endRemoveRows();
352   return true;
353 }
354
355
356 void XGUI_DocumentDataModel::removeSubModel(int theModelId)
357 {
358   XGUI_PartModel* aModel = myPartModels.at(theModelId);
359   QIntList aToRemove;
360   for (int i = 0; i < myIndexes.size(); i++) {
361     if (myIndexes.at(i)->model() == aModel)
362       aToRemove.append(i);
363   }
364   int aId;
365   while(aToRemove.size() > 0) {
366     aId = aToRemove.last();
367     delete myIndexes.at(aId);
368     myIndexes.removeAt(aId);
369     aToRemove.removeLast();
370   }
371   delete aModel;
372   myPartModels.removeAt(theModelId);
373 }
374
375 bool XGUI_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
376 {
377   if (theModel == myModel)
378     return true;
379   return isPartSubModel(theModel);
380 }
381
382 bool XGUI_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
383 {
384   return myPartModels.contains((XGUI_PartModel*)theModel);
385 }
386
387 QModelIndex XGUI_DocumentDataModel::partFolderNode() const
388 {
389   int aPos = myModel->rowCount(QModelIndex());
390   return createIndex(aPos, columnCount() - 1, PartsFolder);
391 }
392
393 int XGUI_DocumentDataModel::historyOffset() const
394 {
395   // Nb of rows of top model + Parts folder
396   return myModel->rowCount(QModelIndex()) + 1;
397 }