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