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