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>
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));
52 XGUI_DataModel::~XGUI_DataModel()
57 //******************************************************
58 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
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);
70 QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
71 ModuleBase_ITreeNode* aParent;
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);
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());
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();
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())
104 if (aObj->data()->isValid()) {
105 if (aObj->groupName() == ModelAPI_Folder::group()) {
109 aCreated.append(*aIt);
116 foreach(ObjectPtr aObj, aCreated) {
117 ModuleBase_ITreeNode* aNode = myRoot->subNode(aObj);
119 QModelIndex aFirstIdx = getIndex(aNode, 0);
120 QModelIndex aLastIdx = getIndex(aNode, 2);
121 dataChanged(aFirstIdx, aLastIdx);
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());
135 updateSubTree(aNode);
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);
143 updateSubTree(aRoot);
148 //******************************************************
149 void XGUI_DataModel::clear()
155 //******************************************************
156 void XGUI_DataModel::rebuildDataTree()
163 //******************************************************
164 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
166 if (theIndex.isValid()) {
167 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
168 return aNode->object();
173 //******************************************************
174 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
176 ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
178 return getIndex(aNode, theColumn);
180 return QModelIndex();
183 //******************************************************
184 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
186 if (theIndex.isValid()) {
187 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
188 return aNode->data(theIndex.column(), theRole);
193 //******************************************************
194 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
199 //******************************************************
200 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
202 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
203 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
204 return aParentNode->childrenCount();
207 //******************************************************
208 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
213 //******************************************************
214 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
216 int aa = theParent.row();
217 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
218 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
219 ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
221 return createIndex(theRow, theColumn, aSubNode);
224 //******************************************************
225 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
227 if (theIndex.isValid()) {
228 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
229 return getParentIndex(aNode, 1);
231 return QModelIndex();
234 //******************************************************
235 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
237 ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
238 (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
239 return aParentNode->childrenCount() > 0;
242 //******************************************************
243 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
245 beginInsertRows(theParent, theRow, theRow + theCount - 1);
250 //******************************************************
251 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
253 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
258 //******************************************************
259 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
261 if (theIndex.isValid()) {
262 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
263 return aNode->flags(theIndex.column());
265 return Qt::ItemFlags();
269 //******************************************************
270 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
272 SessionPtr aSession = ModelAPI_Session::get();
273 DocumentPtr aRootDoc = aSession->moduleDocument();
274 if (theDoc == aRootDoc)
275 return QModelIndex();
277 ModuleBase_ITreeNode* aDocNode = 0;
278 foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
279 if (aNode->document() == theDoc) {
285 return getIndex(aDocNode, theColumn);
287 return QModelIndex();
290 //******************************************************
291 bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
293 if (theIndex.isValid()) {
294 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
295 return aNode->visibilityState() == ModuleBase_ITreeNode::Hidden;
300 //******************************************************
301 bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
303 ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
304 return myRoot->hasSubNode(aNode);
307 //******************************************************
308 QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
310 ModuleBase_ITreeNode* aParent = theNode->parent();
311 if (aParent == myRoot) {
312 return QModelIndex();
314 return getIndex(aParent, thCol);
318 //******************************************************
319 QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
321 if (theNode == myRoot)
322 return QModelIndex();
323 int aRow = theNode->parent()->nodeRow(theNode);
324 return createIndex(aRow, thCol, theNode);
328 //******************************************************
329 void XGUI_DataModel::updateSubTree(ModuleBase_ITreeNode* theParent)
331 int aRows = theParent->childrenCount();
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);