]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_DataModel.cpp
Salome HOME
74257d5ff8c4c9dc114371e0b7bf9ae249bfb2d0
[modules/shaper.git] / src / XGUI / XGUI_DataModel.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        ModuleBase_IDocumentDataModel.cpp
4 // Created:     28 Apr 2015
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "XGUI_DataModel.h"
8
9 #include <ModelAPI_Session.h>
10 #include <ModelAPI_Document.h>
11 #include <ModelAPI_Events.h>
12 #include <ModelAPI_ResultParameter.h>
13 #include <ModelAPI_AttributeDouble.h>
14 #include <ModelAPI_ResultPart.h>
15
16 #include <Config_FeatureMessage.h>
17
18 #include <Events_Loop.h>
19
20 #include <QIcon>
21
22 /// Returns ResultPart object if the given object is a Part feature
23 /// Otherwise returns NULL
24 ResultPartPtr getPartResult(ModelAPI_Object* theObj)
25 {
26   ModelAPI_Feature* aFeature = dynamic_cast<ModelAPI_Feature*>(theObj);
27   if (aFeature) {
28     ResultPtr aRes = aFeature->firstResult();
29     if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
30       return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
31     }
32   }
33   return ResultPartPtr();
34 }
35
36 ModelAPI_Document* getSubDocument(void* theObj)
37 {
38   ModelAPI_Document* aDoc = dynamic_cast<ModelAPI_Document*>((ModelAPI_Entity*)theObj);
39   return aDoc;
40 }
41
42
43 // Constructor *************************************************
44 XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)
45 {
46   myXMLReader.readAll();
47
48   Events_Loop* aLoop = Events_Loop::loop();
49   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
50   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
51   aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
52 }
53
54 //******************************************************
55 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
56 {
57   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
58   std::string aRootType = myXMLReader.rootType();
59   int aNbFolders = myXMLReader.rootFoldersNumber();
60
61   // Created object event *******************
62   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
63     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
64         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
65     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
66
67     std::set<ObjectPtr>::const_iterator aIt;
68     std::string aObjType;
69     for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
70       ObjectPtr aObject = (*aIt);
71       aObjType = aObject->groupName();
72       DocumentPtr aDoc = aObject->document();
73       if (aDoc == aRootDoc) {
74         int aRow = aRootDoc->size(aObjType) - 1;
75         if (aRow != -1) {
76           if (aObjType == aRootType) {
77             insertRow(aRow + aNbFolders);
78           } else {
79             int aFolderId = myXMLReader.rootFolderId(aObjType);
80             if (aFolderId != -1) {
81               insertRow(aRow, createIndex(aFolderId, 0, -1));
82             }
83           } 
84         }
85       }
86     }
87     // Deleted object event ***********************
88   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
89     std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
90         std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
91     DocumentPtr aDoc = aUpdMsg->document();
92     std::set<std::string> aGroups = aUpdMsg->groups();
93     std::set<std::string>::const_iterator aIt;
94     for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
95       std::string aGroup = (*aIt);
96       if (aDoc == aRootDoc) {  // If root objects
97         int aRow = aRootDoc->size(aGroup);
98         if (aGroup == aRootType) {
99           removeRow(aRow + aNbFolders);
100         } else {
101           int aFolderId = myXMLReader.rootFolderId(aGroup);
102           if (aFolderId != -1) {
103             QModelIndex aFolderIndex = createIndex(aFolderId, 0, -1);
104             removeRow(aRow, aFolderIndex);
105           }
106         }
107       }
108     }
109   } 
110 }
111
112 //******************************************************
113 void XGUI_DataModel::clear()
114 {
115
116 }
117
118 //******************************************************
119 void XGUI_DataModel::rebuildDataTree()
120 {
121
122 }
123
124 //******************************************************
125 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
126 {
127   if (theIndex.internalId() < 0) // this is a folder
128     return ObjectPtr();
129   ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer();
130   // We can not create the ObjectPtr directly because the pointer will be deleted 
131   // with deletion of the ObjectPtr because its counter become to 0.
132   DocumentPtr aDoc = aObj->document();
133   std::string aType = aObj->groupName();
134
135   ObjectPtr aObjPtr;
136   for (int i = 0; i < aDoc->size(aType); i++) {
137     aObjPtr = aDoc->object(aType, i);
138     if (aObjPtr.get() == aObj)
139       return aObjPtr;
140   }
141   return ObjectPtr();
142 }
143
144 //******************************************************
145 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject) const
146 {
147   std::string aType = theObject->groupName();
148   DocumentPtr aDoc = theObject->document();
149   int aRow = aDoc->index(theObject);
150   if (aRow == -1)
151     return QModelIndex();
152
153   SessionPtr aSession = ModelAPI_Session::get();
154   DocumentPtr aRootDoc = aSession->moduleDocument();
155   if (aDoc == aRootDoc && myXMLReader.rootType() == aType) { 
156     // The object from root document
157     aRow += myXMLReader.rootFoldersNumber();
158   } else if (myXMLReader.subType() == aType) { 
159     // The object from sub document
160     aRow += myXMLReader.subFoldersNumber();
161   }
162   return createIndex(aRow, 0, theObject.get());
163 }
164
165 //******************************************************
166 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
167 {
168   SessionPtr aSession = ModelAPI_Session::get();
169   DocumentPtr aRootDoc = aSession->moduleDocument();
170   int aNbFolders = myXMLReader.rootFoldersNumber();
171   int theIndexRow = theIndex.row();
172
173   if ((theIndex.column() == 1) ) {
174     //if (theIndexRow >= aNbFolders) {
175     //  if (theRole == Qt::DecorationRole) {
176     //    return QIcon(":pictures/arrow.png");
177     //  }
178     //}
179     return QVariant();
180   }
181
182   int aParentId = theIndex.internalId();
183   if (aParentId == -1) { // root folders
184     switch (theRole) {
185       case Qt::DisplayRole:
186         return QString(myXMLReader.rootFolderName(theIndexRow).c_str()) + 
187           QString(" (%1)").arg(rowCount(theIndex));
188       case Qt::DecorationRole:
189         return QIcon(myXMLReader.rootFolderIcon(theIndexRow).c_str());
190     }
191   } else {
192     ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer());
193     if (aSubDoc) { // this is a folder of sub document
194       switch (theRole) {
195         case Qt::DisplayRole:
196           return QString(myXMLReader.subFolderName(theIndexRow).c_str()) + 
197             QString(" (%1)").arg(rowCount(theIndex));
198         case Qt::DecorationRole:
199           return QIcon(myXMLReader.subFolderIcon(theIndexRow).c_str());
200       }
201     } else {
202       ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer();
203       switch (theRole) {
204       case Qt::DisplayRole:
205         if (aObj->groupName() == ModelAPI_ResultParameter::group()) {
206           ModelAPI_ResultParameter* aParam = dynamic_cast<ModelAPI_ResultParameter*>(aObj);
207           AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
208           QString aVal = QString::number(aValueAttribute->value());
209           QString aTitle = QString(aObj->data()->name().c_str());
210           return aTitle + " = " + aVal;
211         }
212         return aObj->data()->name().c_str();
213       }
214     }
215   }
216   return QVariant();
217 }
218
219 //******************************************************
220 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
221 {
222   return QVariant();
223 }
224
225 //******************************************************
226 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
227 {
228   SessionPtr aSession = ModelAPI_Session::get();
229   if (!aSession->hasModuleDocument())
230     return 0;
231   DocumentPtr aRootDoc = aSession->moduleDocument();
232
233   if (!theParent.isValid()) {
234     // Return number of items in root
235     int aNbFolders = myXMLReader.rootFoldersNumber();
236     int aNbItems = 0;
237     std::string aType = myXMLReader.rootType();
238     if (!aType.empty())
239       aNbItems = aRootDoc->size(aType);
240     return aNbFolders + aNbItems;
241   }
242
243   int aId = theParent.internalId();
244   if (aId < 0) { 
245     // this is a folder
246     int aParentPos = theParent.row();
247     if (aId == -1) { // first level of folders
248       std::string aType = myXMLReader.rootFolderType(aParentPos);
249       return aRootDoc->size(aType);
250     }
251   } else {
252     // It is an object which could have children
253     ModelAPI_Object* aObj = (ModelAPI_Object*)theParent.internalPointer();
254
255     // Check for Part feature
256     ResultPartPtr aPartRes = getPartResult(aObj);
257     if (aPartRes.get()) {
258       DocumentPtr aSubDoc = aPartRes->partDoc();
259       int aNbSubFolders = myXMLReader.subFoldersNumber();
260       int aNbSubItems = 0;
261       std::string aSubType = myXMLReader.subType();
262       if (!aSubType.empty())
263         aNbSubItems = aSubDoc->size(aSubType);
264       return aNbSubItems + aNbSubFolders;
265     }
266   }
267   return 0;
268 }
269
270 //******************************************************
271 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
272 {
273   return 2;
274 }
275
276 //******************************************************
277 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
278 {
279   SessionPtr aSession = ModelAPI_Session::get();
280   DocumentPtr aRootDoc = aSession->moduleDocument();
281   int aNbFolders = myXMLReader.rootFoldersNumber();
282
283   if (!theParent.isValid()) {
284     if (theRow < aNbFolders) // Return first level folder index
285       return createIndex(theRow, theColumn, -1);
286     else { // return object under root index
287       std::string aType = myXMLReader.rootType();
288       int aObjId = theRow - aNbFolders;
289       if (aObjId < aRootDoc->size(aType)) {
290         ObjectPtr aObj = aRootDoc->object(aType, aObjId);
291         QModelIndex aIndex = objectIndex(aObj);
292         if (theColumn != 0)
293           return createIndex(aIndex.row(), theColumn, aIndex.internalPointer());
294         return aIndex;
295       }
296       return QModelIndex();
297     }
298   }
299   int aId = theParent.internalId();
300   if (aId == -1) { // return object index inside of first level of folders
301     int aParentPos = theParent.row();
302     std::string aType = myXMLReader.rootFolderType(aParentPos);
303     if (theRow < aRootDoc->size(aType)) {
304       ObjectPtr aObj = aRootDoc->object(aType, theRow);
305       QModelIndex aIndex = objectIndex(aObj);
306       if (theColumn != 0)
307         return createIndex(aIndex.row(), theColumn, aIndex.internalPointer());
308       return aIndex;
309     }
310   } else {
311     // It is an object which could have children
312     ModelAPI_Object* aParentObj = (ModelAPI_Object*)theParent.internalPointer();
313
314     // Check for Part feature
315     ResultPartPtr aPartRes = getPartResult(aParentObj);
316     if (aPartRes.get()) {
317       DocumentPtr aSubDoc = aPartRes->partDoc();
318       int aNbSubFolders = myXMLReader.subFoldersNumber();
319       if (theRow < aNbSubFolders) { // Create a Folder of sub-document
320         return createIndex(theRow, theColumn, aSubDoc.get());
321       }
322     }
323   }
324   return QModelIndex();
325 }
326
327 //******************************************************
328 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
329 {
330   int aId = theIndex.internalId();
331   if (aId != -1) { // The object is not a root folder
332     ModelAPI_Document* aDoc = getSubDocument(theIndex.internalPointer());
333     if (aDoc) { 
334       // It is a folder of sub-document
335       SessionPtr aSession = ModelAPI_Session::get();
336       DocumentPtr aRootDoc = aSession->moduleDocument();
337       if (myXMLReader.isAttachToResult()) { // If document is attached to result
338         int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
339         ObjectPtr aObj;
340         ResultPartPtr aPartRes;
341         for (int i = 0; i < aNb; i++) {
342           aObj = aRootDoc->object(ModelAPI_ResultPart::group(), i);
343           aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
344           if (aPartRes.get() && (aPartRes->partDoc().get() == aDoc)) {
345             int aRow = i;
346             if (myXMLReader.rootType() == ModelAPI_Feature::group())
347               aRow += myXMLReader.rootFoldersNumber();
348             return createIndex(aRow, 0, aObj.get());
349           }
350         }
351       } else { // If document is attached to feature
352         int aNb = aRootDoc->size(ModelAPI_Feature::group());
353         ObjectPtr aObj;
354         ResultPartPtr aPartRes;
355         for (int i = 0; i < aNb; i++) {
356           aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
357           aPartRes = getPartResult(aObj.get());
358           if (aPartRes.get() && (aPartRes->partDoc().get() == aDoc)) {
359             int aRow = i;
360             if (myXMLReader.rootType() == ModelAPI_Feature::group())
361               aRow += myXMLReader.rootFoldersNumber();
362             return createIndex(aRow, 0, aObj.get());
363           }
364         }
365       }
366     }
367     ModelAPI_Object* aObj = (ModelAPI_Object*) theIndex.internalPointer();
368     std::string aType = aObj->groupName();
369     if (aType == myXMLReader.rootType())
370       return QModelIndex();
371     else {
372       // return first level of folder index
373       int aFolderId = myXMLReader.rootFolderId(aType);
374       // Items in a one row must have the same parent
375       return createIndex(aFolderId, 0, -1);
376     }
377   } 
378   return QModelIndex();
379 }
380
381 //******************************************************
382 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
383 {
384   int aNbFolders = myXMLReader.rootFoldersNumber();
385   if (!theParent.isValid() && aNbFolders)
386     return true;
387   if (theParent.internalId() == -1) {
388     std::string aType = myXMLReader.rootFolderType(theParent.row());
389     if (!aType.empty()) {
390       SessionPtr aSession = ModelAPI_Session::get();
391       DocumentPtr aRootDoc = aSession->moduleDocument();
392       return aRootDoc->size(aType) > 0;
393     }
394   } else {
395     ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
396     if (aDoc) { 
397       // a folder of sub-document
398       std::string aType = myXMLReader.subFolderType(theParent.row());
399       return aDoc->size(aType) > 0;
400     } else {
401       // Check that it could be an object with children
402       ModelAPI_Object* aObj = (ModelAPI_Object*)theParent.internalPointer();
403
404       // Check for Part feature
405       ResultPartPtr aPartRes = getPartResult(aObj);
406       if (aPartRes.get())
407         return true;
408     }
409   }
410   return false;
411 }
412
413 //******************************************************
414 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
415 {
416   beginInsertRows(theParent, theRow, theRow + theCount - 1);
417   endInsertRows();
418
419   return true;
420 }
421
422 //******************************************************
423 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
424 {
425   beginRemoveRows(theParent, theRow, theRow + theCount - 1);
426   endRemoveRows();
427   return true;
428 }
429
430 //******************************************************
431 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
432 {
433   Qt::ItemFlags aFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
434   if (theIndex.internalId() > -1) {
435     aFlags |= Qt::ItemIsEditable;
436   }
437   return aFlags;
438 }