1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 #include "PartSet_DocumentDataModel.h"
4 #include "PartSet_PartDataModel.h"
5 #include "PartSet_TopDataModel.h"
6 #include "PartSet_Module.h"
7 //#include "XGUI_Tools.h"
9 #include <ModelAPI_Session.h>
10 #include <ModelAPI_Document.h>
11 #include <ModelAPI_Feature.h>
12 #include <ModelAPI_Data.h>
13 #include <ModelAPI_ResultPart.h>
14 #include <ModelAPI_Events.h>
15 #include <ModelAPI_Object.h>
17 #include <Events_Loop.h>
19 #include <Config_FeatureMessage.h>
20 #include <ModuleBase_Tools.h>
21 #include <ModuleBase_ActionInfo.h>
23 #include <PartSetPlugin_Part.h>
32 #define ACTIVE_COLOR QColor(0,72,140)
33 #define PASSIVE_COLOR Qt::black
35 QMap<QString, QString> PartSet_DocumentDataModel::myIcons;
38 PartSet_DocumentDataModel::PartSet_DocumentDataModel(QObject* theParent)
39 : ModuleBase_IDocumentDataModel(theParent),
42 // Create a top part of data tree model
43 myModel = new PartSet_TopDataModel(this);
44 myModel->setItemsColor(ACTIVE_COLOR);
46 Events_Loop* aLoop = Events_Loop::loop();
47 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
48 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
49 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
50 aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
53 PartSet_DocumentDataModel::~PartSet_DocumentDataModel()
59 void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
61 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
64 // Created object event *******************
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();
70 std::set<ObjectPtr>::const_iterator aIt;
71 for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
72 ObjectPtr aObject = (*aIt);
73 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
74 if (aFeature && (!aFeature->isInHistory()))
77 DocumentPtr aDoc = aObject->document();
78 if (aDoc == aRootDoc) { // If root objects
79 if (aObject->groupName() == ModelAPI_ResultPart::group()) { // Update only Parts group
81 int aStart = aRootDoc->size(ModelAPI_ResultPart::group());
83 FeaturePtr aPartFeature = ModelAPI_Feature::feature(aObject);
84 PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
85 int anId = aRootDoc->index(aPartFeature);
86 aModel->setPart(aPartFeature);
87 myPartModels.append(aModel);
88 insertRow(aStart, partFolderNode(0));
90 } else { // Update top groups (other except parts
91 QModelIndex aIndex = myModel->findParent(aObject);
92 int aStart = myModel->rowCount(aIndex) - 1;
95 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
96 insertRow(aStart, aIndex);
98 } else { // if sub-objects of first level nodes
99 PartSet_PartModel* aPartModel = 0;
100 foreach (PartSet_PartModel* aPart, myPartModels) {
101 if (aPart->hasDocument(aDoc)) {
107 QModelIndex aIndex = aPartModel->findParent(aObject);
108 int aStart = aPartModel->rowCount(aIndex); // check this index
109 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
110 insertRow(aStart, aIndex);
115 // Deleted object event ***********************
116 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
117 std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
118 std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
119 DocumentPtr aDoc = aUpdMsg->document();
120 std::set<std::string> aGroups = aUpdMsg->groups();
122 std::set<std::string>::const_iterator aIt;
123 for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
124 std::string aGroup = (*aIt);
125 if (aDoc == aRootDoc) { // If root objects
126 if (aGroup == ModelAPI_ResultPart::group()) { // Update only Parts group
127 PartSet_PartModel* aDelPartModel = 0;
128 foreach (PartSet_PartModel* aPartModel, myPartModels) {
129 if (aPartModel->position() == -1) {
130 aDelPartModel = aPartModel;
136 int aStart = myPartModels.size() - 1;
137 removeSubModel(aDelPartModel);
138 removeRow(aStart, partFolderNode(0));
140 } if (aGroup == ModelAPI_Feature::group()) { // Update History node
141 int aRow = historyOffset() + aRootDoc->size(ModelAPI_Feature::group());
143 } else { // Update top groups (other except parts
144 QModelIndex aIndex = myModel->findGroup(aGroup);
145 int aStart = myModel->rowCount(aIndex);
146 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
147 removeRow(aStart, aIndex);
150 PartSet_PartModel* aPartModel = 0;
151 foreach (PartSet_PartModel* aPart, myPartModels) {
152 if (aPart->hasDocument(aDoc)) {
158 QModelIndex aIndex = aPartModel->findGroup(aGroup);
159 if (aIndex.isValid()) {
160 int aStart = aPartModel->rowCount(aIndex);
161 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
162 removeRow(aStart, aIndex);
164 int aRow = aPartModel->rowCount();
165 aIndex = createIndex(aPartModel->position() + historyOffset(), 0, HistoryNode);
166 removeRow(aRow, aIndex);
171 // Deleted object event ***********************
172 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
173 //std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg = std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
174 //ObjectPtr aFeature = aUpdMsg->feature();
175 //DocumentPtr aDoc = aFeature->document();
177 // TODO: Identify the necessary index by the modified feature
179 emit dataChanged(aIndex, aIndex);
181 // Reset whole tree **************************
182 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
183 std::shared_ptr<Config_FeatureMessage> aFeatureMsg =
184 std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
185 if (!aFeatureMsg->isInternal()) {
186 ActionInfo aFeatureInfo;
187 aFeatureInfo.initFrom(aFeatureMsg);
188 // Remember features icons
189 myIcons[QString::fromStdString(aFeatureMsg->id())] = aFeatureInfo.iconFile;
196 void PartSet_DocumentDataModel::rebuildDataTree()
198 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
203 // Delete extra models
206 QList<PartSet_PartModel*> aDelList;
207 foreach (PartSet_PartModel* aPartModel, myPartModels) {
208 if (aPartModel->position() == -1)
209 aDelList.append(aPartModel);
211 foreach (PartSet_PartModel* aPartModel, aDelList) {
212 removeSubModel(aPartModel);
214 // Add non existing models
215 int aHistNb = aRootDoc->size(ModelAPI_Feature::group());
216 for (int i = 0; i < aHistNb; i++) {
217 aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
218 aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
219 if (aFeature->getKind() == PartSetPlugin_Part::ID()) {
220 if (!findPartModel(aFeature)) {
221 PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
222 aModel->setPart(aFeature);
223 myPartModels.append(aModel);
230 QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
232 if (!theIndex.isValid())
235 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
236 QModelIndex aParent = theIndex.parent();
237 if ((theIndex.column() == 1) ) {
238 if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
239 if (ModelAPI_Session::get()->activeDocument() == aRootDoc) {
240 if (!aParent.isValid()) {
242 case Qt::DecorationRole:
243 if (theIndex.row() == lastHistoryRow())
244 return QIcon(":pictures/arrow.png");
249 QModelIndex* aIndex = toSourceModelIndex(theIndex);
250 const QAbstractItemModel* aModel = aIndex->model();
251 if (isPartSubModel(aModel)) {
252 return aModel->data(*aIndex, theRole);
258 switch (theIndex.internalId()) {
261 case Qt::DisplayRole:
262 return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
263 case Qt::DecorationRole:
264 return QIcon(":pictures/constr_folder.png");
265 case Qt::ToolTipRole:
266 return tr("Parts folder");
267 case Qt::ForegroundRole:
268 if (myActivePartIndex.isValid())
269 return QBrush(PASSIVE_COLOR);
271 return QBrush(ACTIVE_COLOR);
278 int aOffset = historyOffset();
279 ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
280 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
284 case Qt::DisplayRole:
286 return aFeature->data()->name().c_str();
289 case Qt::DecorationRole:
290 return featureIcon(aFeature);
291 case Qt::ToolTipRole:
293 ResultPtr aResult = aFeature->firstResult();
294 bool isResultAndNotLoaded = false;
297 ResultPartPtr aResultPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>( aResult );
298 if( aResultPart.get() )
299 isResultAndNotLoaded = !aResultPart->isActivated();
301 if( isResultAndNotLoaded )
302 return tr( "The part should be activated before the user may edit it" );
304 return tr( "Feature object" );
306 case Qt::ForegroundRole:
307 if (theIndex.row() > lastHistoryRow())
308 return QBrush(Qt::lightGray);
310 if (myActivePartIndex.isValid())
311 return QBrush(PASSIVE_COLOR);
313 return QBrush(ACTIVE_COLOR);
322 ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
325 case Qt::DisplayRole:
326 return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
327 case Qt::DecorationRole:
328 return QIcon(":pictures/part_ico.png");
329 case Qt::ForegroundRole:
331 if (theIndex == myActivePartIndex)
332 return QBrush(ACTIVE_COLOR);
334 return QBrush(PASSIVE_COLOR);
343 if (aParent.internalId() == HistoryNode) {
344 int aId = aParent.row() - historyOffset();
345 QModelIndex* aIndex = toSourceModelIndex(theIndex);
346 return findPartModel(aId)->data(*aIndex, theRole);
348 return toSourceModelIndex(theIndex)->data(theRole);
351 QVariant PartSet_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient,
357 int PartSet_DocumentDataModel::rowCount(const QModelIndex& theParent) const
359 SessionPtr aSession = ModelAPI_Session::get();
360 if (!aSession->hasModuleDocument())
362 DocumentPtr aRootDoc = aSession->moduleDocument();
363 if (!theParent.isValid()) {
364 // Size of external models
365 int aVal = historyOffset();
367 aVal += aRootDoc->size(ModelAPI_Feature::group());
370 if (theParent.internalId() == PartsFolder) {
371 return aRootDoc->size(ModelAPI_ResultPart::group());
372 //int aSize = myPartModels.size();
373 //return myPartModels.size();
375 if (theParent.internalId() == HistoryNode) {
376 int aId = theParent.row() - historyOffset();
377 PartSet_PartModel* aModel = findPartModel(aId);
379 return aModel->rowCount(QModelIndex());
382 if (theParent.internalId() == PartResult)
385 QModelIndex* aParent = toSourceModelIndex(theParent);
386 const QAbstractItemModel* aModel = aParent->model();
387 if (!isSubModel(aModel))
390 /*if (isPartSubModel(aModel)) {
391 if (aModel != myActivePart)
394 return aModel->rowCount(*aParent);
397 int PartSet_DocumentDataModel::columnCount(const QModelIndex& theParent) const
402 QModelIndex PartSet_DocumentDataModel::index(int theRow, int theColumn,
403 const QModelIndex& theParent) const
406 if (!theParent.isValid()) {
407 int aOffs = myModel->rowCount();
408 if (theRow < aOffs) {
409 aIndex = myModel->index(theRow, theColumn, theParent);
410 aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
412 if (theRow == aOffs) // Create Parts node
413 aIndex = partFolderNode(theColumn);
415 // create history node
416 aIndex = createIndex(theRow, theColumn, HistoryNode);
420 if (theParent.internalId() == PartsFolder) {
421 aIndex = createIndex(theRow, theColumn, PartResult);
423 if (theParent.internalId() == HistoryNode) {
424 int aId = theParent.row() - historyOffset();
425 aIndex = findPartModel(aId)->index(theRow, theColumn, QModelIndex());
427 QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
428 aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
430 aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
436 QModelIndex PartSet_DocumentDataModel::parent(const QModelIndex& theIndex) const
438 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
439 return QModelIndex();
441 if (theIndex.internalId() == PartResult)
442 return partFolderNode(0);
444 QModelIndex* aIndex = toSourceModelIndex(theIndex);
445 const QAbstractItemModel* aModel = aIndex->model();
446 if (!isSubModel(aModel))
447 return QModelIndex();
449 QModelIndex aIndex1 = aModel->parent(*aIndex);
450 const PartSet_PartModel* aPartModel = dynamic_cast<const PartSet_PartModel*>(aModel);
451 if (aPartModel && (!aIndex1.isValid())) {
452 int aId = aPartModel->position();
453 int aRow = aId + historyOffset();
454 return createIndex(aRow, 0, (qint32) HistoryNode);
457 if (aIndex1.isValid())
458 return createIndex(aIndex1.row(), 0, (void*) getModelIndex(aIndex1));
462 bool PartSet_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
464 if (!theParent.isValid())
466 return rowCount(theParent) > 0;
469 QModelIndex* PartSet_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
471 QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
475 QModelIndex* PartSet_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
477 QList<QModelIndex*>::const_iterator aIt;
478 for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
479 QModelIndex* aIndex = (*aIt);
480 if ((*aIndex) == theIndex)
486 QModelIndex* PartSet_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
488 QModelIndex* aIndexPtr = findModelIndex(theIndex);
490 aIndexPtr = new QModelIndex(theIndex);
491 PartSet_DocumentDataModel* that = (PartSet_DocumentDataModel*) this;
492 that->myIndexes.append(aIndexPtr);
497 void PartSet_DocumentDataModel::clearModelIndexes()
499 foreach (QModelIndex* aIndex, myIndexes)
504 void PartSet_DocumentDataModel::clearSubModels()
506 foreach (PartSet_PartModel* aPart, myPartModels)
508 myPartModels.clear();
509 myActivePartModel = 0;
512 ObjectPtr PartSet_DocumentDataModel::object(const QModelIndex& theIndex) const
514 if (theIndex.internalId() == PartsFolder)
516 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
517 if (theIndex.internalId() == HistoryNode) {
518 int aOffset = historyOffset();
519 return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
521 if (theIndex.internalId() == PartResult) {
522 return aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
524 QModelIndex* aIndex = toSourceModelIndex(theIndex);
525 if (!isSubModel(aIndex->model()))
528 const PartSet_FeaturesModel* aModel = dynamic_cast<const PartSet_FeaturesModel*>(aIndex->model());
529 return aModel->object(*aIndex);
532 bool PartSet_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
534 beginInsertRows(theParent, theRow, theRow + theCount - 1);
539 int aRow = rowCount(aRoot);
540 beginInsertRows(aRoot, aRow, aRow);
546 bool PartSet_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
548 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
553 void PartSet_DocumentDataModel::removeSubModel(int theModelId)
555 PartSet_PartModel* aModel = myPartModels.at(theModelId);
556 removeSubModel(aModel);
559 void PartSet_DocumentDataModel::removeSubModel(PartSet_PartModel* theModel)
562 for (int i = 0; i < myIndexes.size(); i++) {
563 if (myIndexes.at(i)->model() == theModel)
567 while (aToRemove.size() > 0) {
568 aId = aToRemove.last();
569 delete myIndexes.at(aId);
570 myIndexes.removeAt(aId);
571 aToRemove.removeLast();
573 if (theModel == myActivePartModel)
574 myActivePartModel = 0;
575 myPartModels.removeAll(theModel);
580 bool PartSet_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
582 if (theModel == myModel)
584 return isPartSubModel(theModel);
587 bool PartSet_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
589 return myPartModels.contains((PartSet_PartModel*) theModel);
592 QModelIndex PartSet_DocumentDataModel::partFolderNode(int theColumn) const
594 int aPos = myModel->rowCount(QModelIndex());
595 return createIndex(aPos, theColumn, PartsFolder);
598 int PartSet_DocumentDataModel::historyOffset() const
600 // Nb of rows of top model + Parts folder
601 return myModel->rowCount(QModelIndex()) + 1;
604 bool PartSet_DocumentDataModel::activatePart(const QModelIndex& theIndex)
606 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
609 if (theIndex.isValid() && (theIndex.internalId() == PartResult)) {
610 myActivePartIndex = theIndex;
611 myModel->setItemsColor(PASSIVE_COLOR);
612 if (myActivePartModel)
613 myActivePartModel->setItemsColor(PASSIVE_COLOR);
615 // Find activated part feature by its ID
616 ResultPartPtr aPartRes = activePart();
617 FeaturePtr aFeature = ModelAPI_Feature::feature(aPartRes);
618 if (aFeature.get()) {
619 myActivePartModel = findPartModel(aFeature);
620 myActivePartModel->setItemsColor(ACTIVE_COLOR);
626 ResultPartPtr PartSet_DocumentDataModel::activePart() const
628 if (myActivePartIndex.isValid()) {
629 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
630 ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myActivePartIndex.row());
631 return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
633 return ResultPartPtr();
636 QModelIndex PartSet_DocumentDataModel::activePartTree() const
638 if (myActivePartModel) {
639 return createIndex(myActivePartModel->position() + historyOffset(), 0, HistoryNode);
641 return QModelIndex();
644 void PartSet_DocumentDataModel::deactivatePart()
646 if (myActivePartIndex.isValid()) {
647 if (myActivePartModel)
648 myActivePartModel->setItemsColor(PASSIVE_COLOR);
649 myActivePartModel = 0;
650 myActivePartIndex = QModelIndex();
651 myModel->setItemsColor(ACTIVE_COLOR);
655 Qt::ItemFlags PartSet_DocumentDataModel::flags(const QModelIndex& theIndex) const
657 if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
658 Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
659 if (object(theIndex).get()) {
660 aFlags |= Qt::ItemIsEditable;
662 // Disable items which are below of last history row
663 // Do not disable second column
664 if (theIndex.internalId() == HistoryNode) {
665 if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
666 aFlags |= Qt::ItemIsEnabled;
668 aFlags |= Qt::ItemIsEnabled;
671 QModelIndex* aIndex = toSourceModelIndex(theIndex);
672 const QAbstractItemModel* aModel = aIndex->model();
673 Qt::ItemFlags aFlags = aModel->flags(*aIndex);
674 if (aModel == myModel) {
675 if (myModel->object(*aIndex).get())
676 aFlags |= Qt::ItemIsEditable;
682 QModelIndex PartSet_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
684 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
685 int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
686 for (int aId = 0; aId < aNb; aId++) {
687 if (theObject == aRootDoc->object(ModelAPI_ResultPart::group(), aId))
688 return createIndex(aId, 0, PartResult);
690 return QModelIndex();
693 QModelIndex PartSet_DocumentDataModel::objectIndex(const ObjectPtr theObject) const
695 // Check that this feature belongs to root document
696 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
697 DocumentPtr aDoc = theObject->document();
698 if (aDoc == aRootDoc) {
699 // This feature belongs to histrory or top model
700 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
703 int aNb = aRootDoc->size(ModelAPI_Feature::group());
704 for (aId = 0; aId < aNb; aId++) {
705 if (theObject == aRootDoc->object(ModelAPI_Feature::group(), aId))
709 return index(aId + historyOffset(), 0, QModelIndex());
711 QModelIndex aIndex = myModel->objectIndex(theObject);
714 createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
718 PartSet_PartModel* aPartModel = 0;
719 foreach(PartSet_PartModel* aModel, myPartModels) {
720 if (aModel->hasDocument(aDoc)) {
726 QModelIndex aIndex = aPartModel->objectIndex(theObject);
727 return aIndex.isValid() ?
728 createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
732 return QModelIndex();
736 void PartSet_DocumentDataModel::clear()
741 myActivePartIndex = QModelIndex();
742 myModel->setItemsColor(ACTIVE_COLOR);
745 int PartSet_DocumentDataModel::lastHistoryRow() const
747 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
748 FeaturePtr aFeature = aRootDoc->currentFeature(true);
750 return historyOffset() + aRootDoc->index(aFeature);
752 return historyOffset() - 1;
755 void PartSet_DocumentDataModel::setLastHistoryItem(const QModelIndex& theIndex)
757 SessionPtr aMgr = ModelAPI_Session::get();
758 DocumentPtr aRootDoc = aMgr->moduleDocument();
759 std::string aOpName = tr("History change").toStdString();
760 if (theIndex.internalId() == HistoryNode) {
761 ObjectPtr aObject = object(theIndex);
762 aMgr->startOperation(aOpName);
763 aRootDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
764 aMgr->finishOperation();
766 aMgr->startOperation(aOpName);
767 aRootDoc->setCurrentFeature(FeaturePtr(), true);
768 aMgr->finishOperation();
772 QModelIndex PartSet_DocumentDataModel::lastHistoryItem() const
774 return index(lastHistoryRow(), 1);
778 QIcon PartSet_DocumentDataModel::featureIcon(const FeaturePtr& theFeature)
782 std::string aKind = theFeature->getKind();
783 QString aId(aKind.c_str());
784 if (!myIcons.contains(aId))
787 QString anIconString = myIcons[aId];
789 ModelAPI_ExecState aState = theFeature->data()->execState();
791 case ModelAPI_StateDone:
792 case ModelAPI_StateNothing: {
793 anIcon = QIcon(anIconString);
796 case ModelAPI_StateMustBeUpdated: {
797 anIcon = ModuleBase_Tools::lighter(anIconString);
800 case ModelAPI_StateExecFailed: {
801 anIcon = ModuleBase_Tools::composite(":icons/exec_state_failed.png", anIconString);
804 case ModelAPI_StateInvalidArgument: {
805 anIcon = ModuleBase_Tools::composite(":icons/exec_state_invalid_parameters.png",
814 void PartSet_DocumentDataModel::onMouseDoubleClick(const QModelIndex& theIndex)
816 if (theIndex.column() != 1)
818 if (flags(theIndex) == 0)
820 QTreeView* aTreeView = dynamic_cast<QTreeView*>(sender());
821 if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
822 if (myActivePartModel)
823 // It means that the root document is not active
825 QModelIndex aNewIndex;
826 if (theIndex.internalId() == HistoryNode)
827 aNewIndex = theIndex;
828 int aOldId = lastHistoryRow();
829 setLastHistoryItem(theIndex);
830 int aStartRow = std::min(aOldId, theIndex.row());
831 int aEndRow = std::max(aOldId, theIndex.row());
832 for (int i = aStartRow; i <= aEndRow; i++) {
833 aTreeView->update(createIndex(i, 0, HistoryNode));
834 aTreeView->update(createIndex(i, 1, HistoryNode));
838 QModelIndex* aIndex = toSourceModelIndex(theIndex);
839 const QAbstractItemModel* aModel = aIndex->model();
840 if (isPartSubModel(aModel)) {
841 PartSet_PartDataModel* aPartModel = (PartSet_PartDataModel*)aModel;
842 QModelIndex aOldItem = aPartModel->lastHistoryItem();
843 aPartModel->setLastHistoryItem(*aIndex);
844 QModelIndex aOldIndex = createIndex(aOldItem.row(), aOldItem.column(), (void*) getModelIndex(aOldItem));
845 int aStartRow = std::min(aOldItem.row(), aIndex->row());
846 int aEndRow = std::max(aOldItem.row(), aIndex->row());
847 for (int i = aStartRow; i <= aEndRow; i++) {
848 QModelIndex aInd1 = aPartModel->index(i, 0);
849 QModelIndex aInd2 = createIndex(i, 0, (void*) getModelIndex(aInd1));
850 aTreeView->update(aInd2);
851 aInd1 = aPartModel->index(i, 1);
852 aInd2 = createIndex(i, 1, (void*) getModelIndex(aInd1));
853 aTreeView->update(aInd2);
860 PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(FeaturePtr thePart) const
862 foreach (PartSet_PartModel* aModel, myPartModels) {
863 if (aModel->part() == thePart)
869 PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(int thePosition) const
871 foreach (PartSet_PartModel* aModel, myPartModels) {
872 if (aModel->position() == thePosition)