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