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