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