1 // Copyright (C) 2014-2019 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 email : webmaster.salome@opencascade.com
20 #include "XGUI_DataModel.h"
21 #include "XGUI_ObjectsBrowser.h"
23 #include <ModuleBase_IconFactory.h>
24 #include <ModuleBase_ITreeNode.h>
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_ResultField.h>
29 #include <Config_FeatureMessage.h>
31 #include <Events_Loop.h>
37 // Constructor *************************************************
38 XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)//,
39 //myIsEventsProcessingBlocked(false)
41 XGUI_ObjectsBrowser* aOB = qobject_cast<XGUI_ObjectsBrowser*>(theParent);
42 myWorkshop = aOB->workshop();
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 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
53 XGUI_DataModel::~XGUI_DataModel()
58 //******************************************************
59 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
61 if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
62 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
63 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
64 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
65 QObjectPtrList aCreated;
66 std::set<ObjectPtr>::const_iterator aIt;
67 for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
68 if ((*aIt)->isInHistory())
69 aCreated.append(*aIt);
70 if ((*aIt)->groupName() == ModelAPI_ResultPart::group()) {
71 emit beforeTreeRebuild();
78 if (aCreated.length() == 0)
81 emit beforeTreeRebuild();
82 QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
83 ModuleBase_ITreeNode* aParent;
85 QModelIndex aParentIndex1, aParentIndex2;
87 bool aRebuildAll = false;
89 foreach(ModuleBase_ITreeNode* aNode, aNodes) {
90 aObj = aNode->object();
91 aParent = aNode->parent();
92 if (aObj.get() && (aObj->groupName() == ModelAPI_Folder::group())) {
97 aRow = aParent->nodeRow(aNode);
98 aParentIndex1 = getParentIndex(aNode, 0);
99 aParentIndex2 = getParentIndex(aNode, 2);
100 insertRows(aRow, 1, aParentIndex1);
101 dataChanged(aParentIndex1, aParentIndex2);
109 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
110 std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
111 std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
112 const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>& aMsgGroups =
114 QTreeNodesList aList;
115 std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator aIt;
116 emit beforeTreeRebuild();
117 for (aIt = aMsgGroups.cbegin(); aIt != aMsgGroups.cend(); aIt++) {
118 aList.append(myRoot->objectsDeleted(aIt->first, aIt->second.c_str()));
120 // Remove obsolete nodes
121 QTreeNodesList aRemaining;
122 foreach(ModuleBase_ITreeNode* aNode, aList) {
123 if (myRoot->hasSubNode(aNode))
124 aRemaining.append(aNode);
126 // Update remaining nodes
127 foreach(ModuleBase_ITreeNode* aNode, aRemaining) {
129 aNode->parent()->update();
134 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
135 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
136 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
137 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
139 QObjectPtrList aCreated;
140 std::set<ObjectPtr>::const_iterator aIt;
141 bool aRebuildAll = false;
142 emit beforeTreeRebuild();
143 for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
144 ObjectPtr aObj = (*aIt);
145 if (!aObj->isInHistory())
148 if (aObj->data()->isValid()) {
149 if (aObj->groupName() == ModelAPI_Folder::group()) {
153 aCreated.append(*aIt);
160 QSet<ModuleBase_ITreeNode*> aParents;
161 foreach(ObjectPtr aObj, aCreated) {
162 ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
164 if (aNode->parent()) {
165 if (aNode->parent() == myRoot) {
167 aParents.insert(myRoot);
171 aNode = aNode->parent();
174 aParents.insert(aNode);
177 foreach(ModuleBase_ITreeNode* aNode, aParents) {
184 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
185 std::shared_ptr<ModelAPI_OrderUpdatedMessage> aUpdMsg =
186 std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
187 if (aUpdMsg->reordered().get()) {
188 DocumentPtr aDoc = aUpdMsg->reordered()->document();
189 std::string aGroup = aUpdMsg->reordered()->group();
190 ModuleBase_ITreeNode* aNode = myRoot->findParent(aDoc, aGroup.c_str());
192 emit beforeTreeRebuild();
199 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
200 DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
201 ModuleBase_ITreeNode* aRoot = myRoot->findRoot(aDoc);
203 updateSubTree(aRoot);
206 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
207 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
208 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
209 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
211 QObjectPtrList aCreated;
212 std::set<ObjectPtr>::const_iterator aIt;
213 bool aRebuildAll = false;
214 for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
215 ObjectPtr aObj = (*aIt);
216 if (aObj->groupName() == ModelAPI_ResultField::group()) {
217 aCreated.append(aObj);
220 if (aCreated.length() == 0)
222 emit beforeTreeRebuild();
223 foreach(ObjectPtr aObj, aCreated) {
224 ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
226 int aOldNb = aNode->childrenCount();
228 int aNewNb = aNode->childrenCount();
230 QModelIndex aFirstIdx = getIndex(aNode, 0);
231 QModelIndex aLastIdx = getIndex(aNode, 2);
233 if (aNewNb > aOldNb) {
234 insertRows(aOldNb - 1, aNewNb - aOldNb, aFirstIdx);
236 else if (aNewNb < aOldNb) {
238 removeRows(aNewNb - 1, aOldNb - aNewNb, aFirstIdx);
240 removeRows(0, aOldNb, aFirstIdx);
242 dataChanged(aFirstIdx, aLastIdx);
249 //******************************************************
250 void XGUI_DataModel::clear()
256 //******************************************************
257 void XGUI_DataModel::rebuildDataTree()
263 //******************************************************
264 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
266 if (theIndex.isValid()) {
267 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
268 return aNode->object();
273 //******************************************************
274 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
276 ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
278 return getIndex(aNode, theColumn);
280 return QModelIndex();
283 //******************************************************
284 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
286 if (theIndex.isValid()) {
287 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
288 return aNode->data(theIndex.column(), theRole);
293 //******************************************************
294 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
299 //******************************************************
300 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
302 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
303 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
304 return aParentNode->childrenCount();
307 //******************************************************
308 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
313 //******************************************************
314 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
316 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
317 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
318 ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
320 return createIndex(theRow, theColumn, aSubNode);
323 //******************************************************
324 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
326 if (theIndex.isValid()) {
327 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
328 return getParentIndex(aNode, 1);
330 return QModelIndex();
333 //******************************************************
334 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
336 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
337 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
338 return aParentNode->childrenCount() > 0;
341 //******************************************************
342 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
344 beginInsertRows(theParent, theRow, theRow + theCount - 1);
349 //******************************************************
350 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
352 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
357 //******************************************************
358 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
360 if (theIndex.isValid()) {
361 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
362 return aNode->flags(theIndex.column());
364 return Qt::ItemFlags();
368 //******************************************************
369 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
371 SessionPtr aSession = ModelAPI_Session::get();
372 DocumentPtr aRootDoc = aSession->moduleDocument();
373 if (theDoc == aRootDoc)
374 return QModelIndex();
376 ModuleBase_ITreeNode* aDocNode = 0;
377 foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
378 if (aNode->document() == theDoc) {
384 return getIndex(aDocNode, theColumn);
386 return QModelIndex();
389 //******************************************************
390 bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
392 if (theIndex.isValid()) {
393 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
394 return aNode->visibilityState() == ModuleBase_ITreeNode::Hidden;
399 //******************************************************
400 bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
402 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
403 return myRoot->hasSubNode(aNode);
406 //******************************************************
407 QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
409 ModuleBase_ITreeNode* aParent = theNode->parent();
410 if (aParent == myRoot) {
411 return QModelIndex();
413 return getIndex(aParent, thCol);
417 //******************************************************
418 QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
420 if (theNode == myRoot)
421 return QModelIndex();
422 int aRow = theNode->parent()->nodeRow(theNode);
423 return createIndex(aRow, thCol, theNode);
427 //******************************************************
428 void XGUI_DataModel::updateSubTree(ModuleBase_ITreeNode* theParent)
430 int aRows = theParent->childrenCount();
432 QModelIndex aParent = getIndex(theParent, 0);
433 QModelIndex aFirstIdx = aParent.child(0, 0);
434 QModelIndex aLastIdx = aParent.child(aRows - 1, 2);
435 dataChanged(aFirstIdx, aLastIdx);
440 //******************************************************
441 DocumentPtr XGUI_DataModel::document(const QModelIndex& theIndex) const
443 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
444 return aNode->document();
448 //******************************************************
449 bool XGUI_DataModel::hasNode(ModuleBase_ITreeNode* theNode) const
451 return myRoot->hasSubNode(theNode);