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