Salome HOME
Get rid of compilation warnings. Part II. MSVC warnings.
[modules/shaper.git] / src / XGUI / XGUI_DataModel.cpp
1 // Copyright (C) 2014-2020  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "XGUI_DataModel.h"
21 #include "XGUI_ObjectsBrowser.h"
22
23 #include <ModuleBase_IconFactory.h>
24 #include <ModuleBase_ITreeNode.h>
25
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_ResultField.h>
28
29 #include <Config_FeatureMessage.h>
30
31 #include <Events_Loop.h>
32
33 #include <cassert>
34
35 #ifdef _MSC_VER
36 #pragma warning(disable: 4100)
37 #endif
38
39
40
41 // Constructor *************************************************
42 XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)//,
43   //myIsEventsProcessingBlocked(false)
44 {
45   XGUI_ObjectsBrowser* aOB = qobject_cast<XGUI_ObjectsBrowser*>(theParent);
46   myWorkshop = aOB->workshop();
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(EVENT_OBJECT_UPDATED));
52   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_ORDER_UPDATED));
53   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
54   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
55 }
56
57 XGUI_DataModel::~XGUI_DataModel()
58 {
59   clear();
60 }
61
62 //******************************************************
63 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
64 {
65   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
66     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
67       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
68     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
69     QObjectPtrList aCreated;
70     std::set<ObjectPtr>::const_iterator aIt;
71     for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
72       if ((*aIt)->isInHistory())
73         aCreated.append(*aIt);
74       if ((*aIt)->groupName() == ModelAPI_ResultPart::group()) {
75         emit beforeTreeRebuild();
76         myRoot->update();
77         rebuildDataTree();
78         emit treeRebuilt();
79         return;
80       }
81     }
82     if (aCreated.length() == 0)
83       return;
84
85     emit beforeTreeRebuild();
86     QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
87     ModuleBase_ITreeNode* aParent;
88     int aRow = 0;
89     QModelIndex aParentIndex1, aParentIndex2;
90     ObjectPtr aObj;
91     bool aRebuildAll = false;
92
93     foreach(ModuleBase_ITreeNode* aNode, aNodes) {
94       aObj = aNode->object();
95       aParent = aNode->parent();
96       if (aObj.get() && (aObj->groupName() == ModelAPI_Folder::group())) {
97         aParent->update();
98         aRebuildAll = true;
99       }
100       else {
101         aRow = aParent->nodeRow(aNode);
102         aParentIndex1 = getParentIndex(aNode, 0);
103         aParentIndex2 = getParentIndex(aNode, 2);
104         insertRows(aRow, 1, aParentIndex1);
105         dataChanged(aParentIndex1, aParentIndex2);
106       }
107     }
108     if (aRebuildAll)
109       rebuildDataTree();
110
111     emit treeRebuilt();
112   }
113   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
114     std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
115       std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
116     const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>& aMsgGroups =
117       aUpdMsg->groups();
118     QTreeNodesList aList;
119     std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator aIt;
120     emit beforeTreeRebuild();
121     for (aIt = aMsgGroups.cbegin(); aIt != aMsgGroups.cend(); aIt++) {
122       aList.append(myRoot->objectsDeleted(aIt->first, aIt->second.c_str()));
123     }
124     // Remove obsolete nodes
125     QTreeNodesList aRemaining;
126     foreach(ModuleBase_ITreeNode* aNode, aList) {
127       if (myRoot->hasSubNode(aNode))
128         aRemaining.append(aNode);
129     }
130     // Update remaining nodes
131     foreach(ModuleBase_ITreeNode* aNode, aRemaining) {
132       if (aNode->parent())
133         aNode->parent()->update();
134     }
135     rebuildDataTree();
136     emit treeRebuilt();
137   }
138   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
139     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
140       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
141     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
142
143     QObjectPtrList aCreated;
144     std::set<ObjectPtr>::const_iterator aIt;
145     bool aRebuildAll = false;
146     emit beforeTreeRebuild();
147     for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
148       ObjectPtr aObj = (*aIt);
149       if (!aObj->isInHistory())
150         continue;
151
152       if (aObj->data()->isValid()) {
153         if (aObj->groupName() == ModelAPI_Folder::group()) {
154           aRebuildAll = true;
155           break;
156         }
157         aCreated.append(*aIt);
158       }
159     }
160     if (aRebuildAll) {
161       myRoot->update();
162     }
163     else {
164       QSet<ModuleBase_ITreeNode*> aParents;
165       foreach(ObjectPtr aObj, aCreated) {
166         ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
167         if (aNode) {
168           if (aNode->parent()) {
169             if (aNode->parent() == myRoot) {
170               aParents.clear();
171               aParents.insert(myRoot);
172               break;
173             }
174             else {
175               aNode = aNode->parent();
176             }
177           }
178           aParents.insert(aNode);
179         }
180       }
181       foreach(ModuleBase_ITreeNode* aNode, aParents) {
182         aNode->update();
183       }
184     }
185     rebuildDataTree();
186     emit treeRebuilt();
187   }
188   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
189     std::shared_ptr<ModelAPI_OrderUpdatedMessage> aUpdMsg =
190       std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
191     if (aUpdMsg->reordered().get()) {
192       DocumentPtr aDoc = aUpdMsg->reordered()->document();
193       std::string aGroup = aUpdMsg->reordered()->group();
194       ModuleBase_ITreeNode* aNode = myRoot->findParent(aDoc, aGroup.c_str());
195       if (aNode) {
196         emit beforeTreeRebuild();
197         aNode->update();
198         rebuildDataTree();
199         emit treeRebuilt();
200       }
201     }
202   }
203   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
204     DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
205     ModuleBase_ITreeNode* aRoot = myRoot->findRoot(aDoc);
206     if (aRoot) {
207       updateSubTree(aRoot);
208     }
209   }
210   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
211     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
212       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
213     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
214
215     QObjectPtrList aCreated;
216     std::set<ObjectPtr>::const_iterator aIt;
217     for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
218       ObjectPtr aObj = (*aIt);
219       if (aObj->groupName() == ModelAPI_ResultField::group()) {
220         aCreated.append(aObj);
221       }
222     }
223     if (aCreated.length() == 0)
224       return;
225     emit beforeTreeRebuild();
226     foreach(ObjectPtr aObj, aCreated) {
227       ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
228       if (aNode) {
229         int aOldNb = aNode->childrenCount();
230         aNode->update();
231         int aNewNb = aNode->childrenCount();
232
233         QModelIndex aFirstIdx = getIndex(aNode, 0);
234         QModelIndex aLastIdx = getIndex(aNode, 2);
235
236         if (aNewNb > aOldNb) {
237           insertRows(aOldNb - 1, aNewNb - aOldNb, aFirstIdx);
238         }
239         else if (aNewNb < aOldNb) {
240           if (aNewNb)
241             removeRows(aNewNb - 1, aOldNb - aNewNb, aFirstIdx);
242           else if (aOldNb)
243             removeRows(0, aOldNb, aFirstIdx);
244         }
245         dataChanged(aFirstIdx, aLastIdx);
246       }
247     }
248     emit treeRebuilt();
249   }
250 }
251
252 //******************************************************
253 void XGUI_DataModel::clear()
254 {
255   beginResetModel();
256   endResetModel();
257 }
258
259 //******************************************************
260 void XGUI_DataModel::rebuildDataTree()
261 {
262   beginResetModel();
263   endResetModel();
264 }
265
266 //******************************************************
267 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
268 {
269   if (theIndex.isValid()) {
270     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
271     return aNode->object();
272   }
273   return ObjectPtr();
274 }
275
276 //******************************************************
277 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
278 {
279   ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
280   if (aNode) {
281     return getIndex(aNode, theColumn);
282   }
283   return QModelIndex();
284 }
285
286 //******************************************************
287 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
288 {
289   if (theIndex.isValid()) {
290     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
291     return aNode->data(theIndex.column(), theRole);
292   }
293   return QVariant();
294 }
295
296 //******************************************************
297 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
298 {
299   return QVariant();
300 }
301
302 //******************************************************
303 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
304 {
305   ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
306     (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
307   return aParentNode->childrenCount();
308 }
309
310 //******************************************************
311 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
312 {
313   return 3;
314 }
315
316 //******************************************************
317 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
318 {
319   ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
320     (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
321   ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
322   assert(aSubNode);
323   return createIndex(theRow, theColumn, aSubNode);
324 }
325
326 //******************************************************
327 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
328 {
329   if (theIndex.isValid()) {
330     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
331     return getParentIndex(aNode, 1);
332   }
333   return QModelIndex();
334 }
335
336 //******************************************************
337 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
338 {
339   ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
340     (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
341   return aParentNode->childrenCount() > 0;
342 }
343
344 //******************************************************
345 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
346 {
347   beginInsertRows(theParent, theRow, theRow + theCount - 1);
348   endInsertRows();
349   return true;
350 }
351
352 //******************************************************
353 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
354 {
355   beginRemoveRows(theParent, theRow, theRow + theCount - 1);
356   endRemoveRows();
357   return true;
358 }
359
360 //******************************************************
361 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
362 {
363   if (theIndex.isValid()) {
364     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
365     return aNode->flags(theIndex.column());
366   }
367   return Qt::ItemFlags();
368 }
369
370
371 //******************************************************
372 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
373 {
374   SessionPtr aSession = ModelAPI_Session::get();
375   DocumentPtr aRootDoc = aSession->moduleDocument();
376   if (theDoc == aRootDoc)
377     return QModelIndex();
378   else {
379     ModuleBase_ITreeNode* aDocNode = 0;
380     foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
381       if (aNode->document() == theDoc) {
382         aDocNode = aNode;
383         break;
384       }
385     }
386     if (aDocNode)
387       return getIndex(aDocNode, theColumn);
388   }
389   return QModelIndex();
390 }
391
392 //******************************************************
393 bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
394 {
395   if (theIndex.isValid()) {
396     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
397     return aNode->visibilityState() == ModuleBase_ITreeNode::Hidden;
398   }
399   return false;
400 }
401
402 //******************************************************
403 bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
404 {
405   ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
406   return myRoot->hasSubNode(aNode);
407 }
408
409 //******************************************************
410 QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
411 {
412   ModuleBase_ITreeNode* aParent = theNode->parent();
413   if (aParent == myRoot) {
414     return QModelIndex();
415   } else {
416     return getIndex(aParent, thCol);
417   }
418 }
419
420 //******************************************************
421 QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
422 {
423   if (theNode == myRoot)
424     return QModelIndex();
425   int aRow = theNode->parent()->nodeRow(theNode);
426   return createIndex(aRow, thCol, theNode);
427 }
428
429
430 //******************************************************
431 void XGUI_DataModel::updateSubTree(ModuleBase_ITreeNode* theParent)
432 {
433   int aRows = theParent->childrenCount();
434   if (aRows) {
435     QModelIndex aParent = getIndex(theParent, 0);
436     QModelIndex aFirstIdx = aParent.child(0, 0);
437     QModelIndex aLastIdx = aParent.child(aRows - 1, 2);
438     dataChanged(aFirstIdx, aLastIdx);
439   }
440 }
441
442
443 //******************************************************
444 DocumentPtr XGUI_DataModel::document(const QModelIndex& theIndex) const
445 {
446   ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
447   return aNode->document();
448 }
449
450
451 //******************************************************
452 bool XGUI_DataModel::hasNode(ModuleBase_ITreeNode* theNode) const
453 {
454   return myRoot->hasSubNode(theNode);
455 }