Salome HOME
Merge branch 'Results_Hierarchy'
[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
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 }
51
52 XGUI_DataModel::~XGUI_DataModel()
53 {
54   clear();
55 }
56
57 //******************************************************
58 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
59 {
60   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
61     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
62         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
63     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
64     QObjectPtrList aCreated;
65     std::set<ObjectPtr>::const_iterator aIt;
66     for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
67       if ((*aIt)->isInHistory())
68         aCreated.append(*aIt);
69     }
70     QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
71     ModuleBase_ITreeNode* aParent;
72     int aRow = 0;
73     QModelIndex aParentIndex1, aParentIndex2;
74     foreach(ModuleBase_ITreeNode* aNode, aNodes) {
75       aParent = aNode->parent();
76       aRow = aParent->nodeRow(aNode);
77       aParentIndex1 = getParentIndex(aNode, 0);
78       aParentIndex2 = getParentIndex(aNode, 2);
79       insertRows(aRow, 1, aParentIndex1);
80       dataChanged(aParentIndex1, aParentIndex2);
81     }
82   }
83   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
84       std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
85           std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
86       const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>& aMsgGroups =
87         aUpdMsg->groups();
88       std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator aIt;
89       for (aIt = aMsgGroups.cbegin(); aIt != aMsgGroups.cend(); aIt++)
90         QTreeNodesList aList = myRoot->objectsDeleted(aIt->first, aIt->second.c_str());
91       rebuildDataTree();
92   }
93   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
94     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
95       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
96     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
97
98     QObjectPtrList aCreated;
99     std::set<ObjectPtr>::const_iterator aIt;
100     bool aRebuildAll = false;
101     for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
102       ObjectPtr aObj = (*aIt);
103       if (!aObj->isInHistory())
104         continue;
105
106       if (aObj->data()->isValid()) {
107         if (aObj->groupName() == ModelAPI_Folder::group()) {
108           aRebuildAll = true;
109           break;
110         }
111         aCreated.append(*aIt);
112       }
113     }
114     if (aRebuildAll) {
115       myRoot->update();
116       rebuildDataTree();
117     } else {
118       foreach(ObjectPtr aObj, aCreated) {
119         ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
120         if (aNode) {
121           QModelIndex aFirstIdx = getIndex(aNode, 0);
122           QModelIndex aLastIdx = getIndex(aNode, 2);
123           dataChanged(aFirstIdx, aLastIdx);
124         }
125       }
126     }
127   }
128   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
129     std::shared_ptr<ModelAPI_OrderUpdatedMessage> aUpdMsg =
130       std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
131     if (aUpdMsg->reordered().get()) {
132       DocumentPtr aDoc = aUpdMsg->reordered()->document();
133       std::string aGroup = aUpdMsg->reordered()->group();
134       ModuleBase_ITreeNode* aNode = myRoot->findParent(aDoc, aGroup.c_str());
135       if (aNode) {
136         aNode->update();
137         updateSubTree(aNode);
138       }
139     }
140   }
141   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
142     DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
143     ModuleBase_ITreeNode* aRoot = myRoot->findRoot(aDoc);
144     if (aRoot) {
145       updateSubTree(aRoot);
146     }
147   }
148 }
149
150 //******************************************************
151 void XGUI_DataModel::clear()
152 {
153   beginResetModel();
154   endResetModel();
155 }
156
157 //******************************************************
158 void XGUI_DataModel::rebuildDataTree()
159 {
160   beginResetModel();
161   endResetModel();
162   emit treeRebuilt();
163 }
164
165 //******************************************************
166 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
167 {
168   if (theIndex.isValid()) {
169     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
170     return aNode->object();
171   }
172   return ObjectPtr();
173 }
174
175 //******************************************************
176 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
177 {
178   ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
179   if (aNode) {
180     return getIndex(aNode, theColumn);
181   }
182   return QModelIndex();
183 }
184
185 //******************************************************
186 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
187 {
188   if (theIndex.isValid()) {
189     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
190     return aNode->data(theIndex.column(), theRole);
191   }
192   return QVariant();
193 }
194
195 //******************************************************
196 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
197 {
198   return QVariant();
199 }
200
201 //******************************************************
202 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
203 {
204   ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
205     (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
206   return aParentNode->childrenCount();
207 }
208
209 //******************************************************
210 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
211 {
212   return 3;
213 }
214
215 //******************************************************
216 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
217 {
218   int aa = theParent.row();
219   ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
220     (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
221   ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
222   assert(aSubNode);
223   return createIndex(theRow, theColumn, aSubNode);
224 }
225
226 //******************************************************
227 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
228 {
229   if (theIndex.isValid()) {
230     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
231     return getParentIndex(aNode, 1);
232   }
233   return QModelIndex();
234 }
235
236 //******************************************************
237 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
238 {
239   ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
240     (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
241   return aParentNode->childrenCount() > 0;
242 }
243
244 //******************************************************
245 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
246 {
247   beginInsertRows(theParent, theRow, theRow + theCount - 1);
248   endInsertRows();
249   return true;
250 }
251
252 //******************************************************
253 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
254 {
255   beginRemoveRows(theParent, theRow, theRow + theCount - 1);
256   endRemoveRows();
257   return true;
258 }
259
260 //******************************************************
261 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
262 {
263   if (theIndex.isValid()) {
264     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
265     return aNode->flags(theIndex.column());
266   }
267   return Qt::ItemFlags();
268 }
269
270
271 //******************************************************
272 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
273 {
274   SessionPtr aSession = ModelAPI_Session::get();
275   DocumentPtr aRootDoc = aSession->moduleDocument();
276   if (theDoc == aRootDoc)
277     return QModelIndex();
278   else {
279     ModuleBase_ITreeNode* aDocNode = 0;
280     foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
281       if (aNode->document() == theDoc) {
282         aDocNode = aNode;
283         break;
284       }
285     }
286     if (aDocNode)
287       return getIndex(aDocNode, theColumn);
288   }
289   return QModelIndex();
290 }
291
292 //******************************************************
293 bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
294 {
295   if (theIndex.isValid()) {
296     ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
297     return aNode->visibilityState() == ModuleBase_ITreeNode::Hidden;
298   }
299   return false;
300 }
301
302 //******************************************************
303 bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
304 {
305   ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
306   return myRoot->hasSubNode(aNode);
307 }
308
309 //******************************************************
310 QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
311 {
312   ModuleBase_ITreeNode* aParent = theNode->parent();
313   if (aParent == myRoot) {
314     return QModelIndex();
315   } else {
316     return getIndex(aParent, thCol);
317   }
318 }
319
320 //******************************************************
321 QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
322 {
323   if (theNode == myRoot)
324     return QModelIndex();
325   int aRow = theNode->parent()->nodeRow(theNode);
326   return createIndex(aRow, thCol, theNode);
327 }
328
329
330 //******************************************************
331 void XGUI_DataModel::updateSubTree(ModuleBase_ITreeNode* theParent)
332 {
333   int aRows = theParent->childrenCount();
334   if (aRows) {
335     QModelIndex aParent = getIndex(theParent, 0);
336     QModelIndex aFirstIdx = aParent.child(0, 0);
337     QModelIndex aLastIdx = aParent.child(aRows - 1, 2);
338     dataChanged(aFirstIdx, aLastIdx);
339   }
340 }