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