1 // Copyright (C) 2014-2020 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>
36 #pragma warning(disable: 4100)
41 // Constructor *************************************************
42 XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)//,
43 //myIsEventsProcessingBlocked(false)
45 XGUI_ObjectsBrowser* aOB = qobject_cast<XGUI_ObjectsBrowser*>(theParent);
46 myWorkshop = aOB->workshop();
48 Events_Loop* aLoop = Events_Loop::loop();
49 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
50 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
51 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
52 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_ORDER_UPDATED));
53 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
54 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
57 XGUI_DataModel::~XGUI_DataModel()
62 //******************************************************
63 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
65 if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
66 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
67 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
68 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
69 QObjectPtrList aCreated;
70 std::set<ObjectPtr>::const_iterator aIt;
71 for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
72 if ((*aIt)->isInHistory())
73 aCreated.append(*aIt);
74 if ((*aIt)->groupName() == ModelAPI_ResultPart::group()) {
75 emit beforeTreeRebuild();
82 if (aCreated.length() == 0)
85 emit beforeTreeRebuild();
86 QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
87 ModuleBase_ITreeNode* aParent;
89 QModelIndex aParentIndex1, aParentIndex2;
91 bool aRebuildAll = false;
93 foreach(ModuleBase_ITreeNode* aNode, aNodes) {
94 aObj = aNode->object();
95 aParent = aNode->parent();
96 if (aObj.get() && (aObj->groupName() == ModelAPI_Folder::group())) {
101 aRow = aParent->nodeRow(aNode);
102 aParentIndex1 = getParentIndex(aNode, 0);
103 aParentIndex2 = getParentIndex(aNode, 2);
104 insertRows(aRow, 1, aParentIndex1);
105 dataChanged(aParentIndex1, aParentIndex2);
113 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
114 std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
115 std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
116 const std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>& aMsgGroups =
118 QTreeNodesList aList;
119 std::list<std::pair<std::shared_ptr<ModelAPI_Document>, std::string>>::const_iterator aIt;
120 emit beforeTreeRebuild();
121 for (aIt = aMsgGroups.cbegin(); aIt != aMsgGroups.cend(); aIt++) {
122 aList.append(myRoot->objectsDeleted(aIt->first, aIt->second.c_str()));
124 // Remove obsolete nodes
125 QTreeNodesList aRemaining;
126 foreach(ModuleBase_ITreeNode* aNode, aList) {
127 if (myRoot->hasSubNode(aNode))
128 aRemaining.append(aNode);
130 // Update remaining nodes
131 foreach(ModuleBase_ITreeNode* aNode, aRemaining) {
133 aNode->parent()->update();
138 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
139 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
140 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
141 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
143 QObjectPtrList aCreated;
144 std::set<ObjectPtr>::const_iterator aIt;
145 bool aRebuildAll = false;
146 emit beforeTreeRebuild();
147 for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
148 ObjectPtr aObj = (*aIt);
149 if (!aObj->isInHistory())
152 if (aObj->data()->isValid()) {
153 if (aObj->groupName() == ModelAPI_Folder::group()) {
157 aCreated.append(*aIt);
164 QSet<ModuleBase_ITreeNode*> aParents;
165 foreach(ObjectPtr aObj, aCreated) {
166 ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
168 if (aNode->parent()) {
169 if (aNode->parent() == myRoot) {
171 aParents.insert(myRoot);
175 aNode = aNode->parent();
178 aParents.insert(aNode);
181 foreach(ModuleBase_ITreeNode* aNode, aParents) {
188 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
189 std::shared_ptr<ModelAPI_OrderUpdatedMessage> aUpdMsg =
190 std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
191 if (aUpdMsg->reordered().get()) {
192 DocumentPtr aDoc = aUpdMsg->reordered()->document();
193 std::string aGroup = aUpdMsg->reordered()->group();
194 ModuleBase_ITreeNode* aNode = myRoot->findParent(aDoc, aGroup.c_str());
196 emit beforeTreeRebuild();
203 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
204 if (ModelAPI_Session::get()->hasModuleDocument()) {
205 DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
206 ModuleBase_ITreeNode* aRoot = myRoot->findRoot(aDoc);
208 updateSubTree(aRoot);
212 else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
213 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
214 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
215 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
217 QObjectPtrList aCreated;
218 std::set<ObjectPtr>::const_iterator aIt;
219 for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
220 ObjectPtr aObj = (*aIt);
221 if (aObj->groupName() == ModelAPI_ResultField::group()) {
222 aCreated.append(aObj);
225 if (aCreated.length() == 0)
227 emit beforeTreeRebuild();
228 foreach(ObjectPtr aObj, aCreated) {
229 ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
231 int aOldNb = aNode->childrenCount();
233 int aNewNb = aNode->childrenCount();
235 QModelIndex aFirstIdx = getIndex(aNode, 0);
236 QModelIndex aLastIdx = getIndex(aNode, 2);
238 if (aNewNb > aOldNb) {
239 insertRows(aOldNb - 1, aNewNb - aOldNb, aFirstIdx);
241 else if (aNewNb < aOldNb) {
243 removeRows(aNewNb - 1, aOldNb - aNewNb, aFirstIdx);
245 removeRows(0, aOldNb, aFirstIdx);
247 dataChanged(aFirstIdx, aLastIdx);
254 //******************************************************
255 void XGUI_DataModel::clear()
261 //******************************************************
262 void XGUI_DataModel::rebuildDataTree()
268 //******************************************************
269 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
271 if (theIndex.isValid()) {
272 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
273 return aNode->object();
278 //******************************************************
279 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
281 ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
283 return getIndex(aNode, theColumn);
285 return QModelIndex();
288 //******************************************************
289 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
291 if (theIndex.isValid()) {
292 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
293 return aNode->data(theIndex.column(), theRole);
298 //******************************************************
299 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
304 //******************************************************
305 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
307 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
308 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
309 return aParentNode->childrenCount();
312 //******************************************************
313 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
318 //******************************************************
319 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
321 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
322 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
323 ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
325 return createIndex(theRow, theColumn, aSubNode);
328 //******************************************************
329 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
331 if (theIndex.isValid()) {
332 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
333 return getParentIndex(aNode, 1);
335 return QModelIndex();
338 //******************************************************
339 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
341 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
342 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
343 return aParentNode->childrenCount() > 0;
346 //******************************************************
347 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
349 beginInsertRows(theParent, theRow, theRow + theCount - 1);
354 //******************************************************
355 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
357 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
362 //******************************************************
363 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
365 if (theIndex.isValid()) {
366 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
367 return aNode->flags(theIndex.column());
369 return Qt::ItemFlags();
373 //******************************************************
374 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
376 SessionPtr aSession = ModelAPI_Session::get();
377 DocumentPtr aRootDoc = aSession->moduleDocument();
378 if (theDoc == aRootDoc)
379 return QModelIndex();
381 ModuleBase_ITreeNode* aDocNode = 0;
382 foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
383 if (aNode->document() == theDoc) {
389 return getIndex(aDocNode, theColumn);
391 return QModelIndex();
394 //******************************************************
395 bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
397 if (theIndex.isValid()) {
398 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
399 return aNode->visibilityState() == ModuleBase_ITreeNode::Hidden;
404 //******************************************************
405 bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
407 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
408 return myRoot->hasSubNode(aNode);
411 //******************************************************
412 QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
414 ModuleBase_ITreeNode* aParent = theNode->parent();
415 if (aParent == myRoot) {
416 return QModelIndex();
418 return getIndex(aParent, thCol);
422 //******************************************************
423 QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
425 if (theNode == myRoot)
426 return QModelIndex();
427 int aRow = theNode->parent()->nodeRow(theNode);
428 return createIndex(aRow, thCol, theNode);
432 //******************************************************
433 void XGUI_DataModel::updateSubTree(ModuleBase_ITreeNode* theParent)
435 int aRows = theParent->childrenCount();
437 QModelIndex aParent = getIndex(theParent, 0);
438 QModelIndex aFirstIdx = aParent.child(0, 0);
439 QModelIndex aLastIdx = aParent.child(aRows - 1, 2);
440 dataChanged(aFirstIdx, aLastIdx);
445 //******************************************************
446 DocumentPtr XGUI_DataModel::document(const QModelIndex& theIndex) const
448 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
449 return aNode->document();
453 //******************************************************
454 bool XGUI_DataModel::hasNode(ModuleBase_ITreeNode* theNode) const
456 return myRoot->hasSubNode(theNode);