1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "XGUI_DataModel.h"
22 #include "XGUI_ObjectsBrowser.h"
24 #include <ModuleBase_IconFactory.h>
25 #include <ModuleBase_ITreeNode.h>
27 #include <ModelAPI_Session.h>
28 #include <ModelAPI_ResultField.h>
30 #include <Config_FeatureMessage.h>
32 #include <Events_Loop.h>
38 // Constructor *************************************************
39 XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)//,
40 //myIsEventsProcessingBlocked(false)
42 XGUI_ObjectsBrowser* aOB = qobject_cast<XGUI_ObjectsBrowser*>(theParent);
43 myWorkshop = aOB->workshop();
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));
54 XGUI_DataModel::~XGUI_DataModel()
59 //******************************************************
60 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
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);
72 QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
73 ModuleBase_ITreeNode* aParent;
75 QModelIndex aParentIndex1, aParentIndex2;
77 foreach(ModuleBase_ITreeNode* aNode, aNodes) {
78 aObj = aNode->object();
79 aParent = aNode->parent();
80 if (aObj.get() && (aObj->groupName() == ModelAPI_Folder::group())) {
85 aRow = aParent->nodeRow(aNode);
86 aParentIndex1 = getParentIndex(aNode, 0);
87 aParentIndex2 = getParentIndex(aNode, 2);
88 insertRows(aRow, 1, aParentIndex1);
89 dataChanged(aParentIndex1, aParentIndex2);
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 =
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()));
103 // Remove obsolete nodes
104 QTreeNodesList aRemaining;
105 foreach(ModuleBase_ITreeNode* aNode, aList) {
106 if (myRoot->hasSubNode(aNode))
107 aRemaining.append(aNode);
109 // Update remaining nodes
110 foreach(ModuleBase_ITreeNode* aNode, aRemaining) {
112 aNode->parent()->update();
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();
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())
129 if (aObj->data()->isValid()) {
130 if (aObj->groupName() == ModelAPI_Folder::group()) {
134 aCreated.append(*aIt);
142 QSet<ModuleBase_ITreeNode*> aParents;
143 foreach(ObjectPtr aObj, aCreated) {
144 ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
146 if (aNode->parent()) {
147 if (aNode->parent() == myRoot) {
149 aParents.insert(myRoot);
153 aNode = aNode->parent();
156 aParents.insert(aNode);
159 foreach(ModuleBase_ITreeNode* aNode, aParents) {
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());
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);
182 updateSubTree(aRoot);
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();
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);
199 foreach(ObjectPtr aObj, aCreated) {
200 ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
202 int aOldNb = aNode->childrenCount();
204 int aNewNb = aNode->childrenCount();
206 QModelIndex aFirstIdx = getIndex(aNode, 0);
207 QModelIndex aLastIdx = getIndex(aNode, 2);
209 if (aNewNb > aOldNb) {
210 insertRows(aOldNb - 1, aNewNb - aOldNb, aFirstIdx);
212 else if (aNewNb < aOldNb) {
214 removeRows(aNewNb - 1, aOldNb - aNewNb, aFirstIdx);
216 removeRows(0, aOldNb, aFirstIdx);
218 dataChanged(aFirstIdx, aLastIdx);
224 //******************************************************
225 void XGUI_DataModel::clear()
231 //******************************************************
232 void XGUI_DataModel::rebuildDataTree()
239 //******************************************************
240 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
242 if (theIndex.isValid()) {
243 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
244 return aNode->object();
249 //******************************************************
250 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
252 ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
254 return getIndex(aNode, theColumn);
256 return QModelIndex();
259 //******************************************************
260 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
262 if (theIndex.isValid()) {
263 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
264 return aNode->data(theIndex.column(), theRole);
269 //******************************************************
270 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
275 //******************************************************
276 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
278 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
279 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
280 return aParentNode->childrenCount();
283 //******************************************************
284 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
289 //******************************************************
290 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
292 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
293 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
294 ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
296 return createIndex(theRow, theColumn, aSubNode);
299 //******************************************************
300 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
302 if (theIndex.isValid()) {
303 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
304 return getParentIndex(aNode, 1);
306 return QModelIndex();
309 //******************************************************
310 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
312 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
313 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
314 return aParentNode->childrenCount() > 0;
317 //******************************************************
318 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
320 beginInsertRows(theParent, theRow, theRow + theCount - 1);
325 //******************************************************
326 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
328 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
333 //******************************************************
334 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
336 if (theIndex.isValid()) {
337 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
338 return aNode->flags(theIndex.column());
340 return Qt::ItemFlags();
344 //******************************************************
345 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
347 SessionPtr aSession = ModelAPI_Session::get();
348 DocumentPtr aRootDoc = aSession->moduleDocument();
349 if (theDoc == aRootDoc)
350 return QModelIndex();
352 ModuleBase_ITreeNode* aDocNode = 0;
353 foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
354 if (aNode->document() == theDoc) {
360 return getIndex(aDocNode, theColumn);
362 return QModelIndex();
365 //******************************************************
366 bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
368 if (theIndex.isValid()) {
369 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
370 return aNode->visibilityState() == ModuleBase_ITreeNode::Hidden;
375 //******************************************************
376 bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
378 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
379 return myRoot->hasSubNode(aNode);
382 //******************************************************
383 QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
385 ModuleBase_ITreeNode* aParent = theNode->parent();
386 if (aParent == myRoot) {
387 return QModelIndex();
389 return getIndex(aParent, thCol);
393 //******************************************************
394 QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
396 if (theNode == myRoot)
397 return QModelIndex();
398 int aRow = theNode->parent()->nodeRow(theNode);
399 return createIndex(aRow, thCol, theNode);
403 //******************************************************
404 void XGUI_DataModel::updateSubTree(ModuleBase_ITreeNode* theParent)
406 int aRows = theParent->childrenCount();
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);
416 //******************************************************
417 DocumentPtr XGUI_DataModel::document(const QModelIndex& theIndex) const
419 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
420 return aNode->document();