1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 #include "PartSet_DocumentDataModel.h"
4 #include "PartSet_PartDataModel.h"
5 #include "PartSet_Module.h"
6 //#include "XGUI_Tools.h"
8 #include <ModelAPI_Session.h>
9 #include <ModelAPI_Document.h>
10 #include <ModelAPI_Feature.h>
11 #include <ModelAPI_Data.h>
12 #include <ModelAPI_ResultPart.h>
13 #include <ModelAPI_Events.h>
14 #include <ModelAPI_Object.h>
16 #include <Events_Loop.h>
18 #include <Config_FeatureMessage.h>
19 #include <ModuleBase_Tools.h>
20 #include <ModuleBase_ActionInfo.h>
22 #include <PartSetPlugin_Part.h>
31 #define ACTIVE_COLOR QColor(0,72,140)
32 #define PASSIVE_COLOR Qt::black
34 QMap<QString, QString> PartSet_DocumentDataModel::myIcons;
37 PartSet_DocumentDataModel::PartSet_DocumentDataModel(QObject* theParent)
38 : ModuleBase_IDocumentDataModel(theParent),
41 // Create a top part of data tree model
42 myModel = new PartSet_TopDataModel(this);
43 myModel->setItemsColor(ACTIVE_COLOR);
45 Events_Loop* aLoop = Events_Loop::loop();
46 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
47 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
48 aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
49 aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
52 PartSet_DocumentDataModel::~PartSet_DocumentDataModel()
58 void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
60 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
63 // Created object event *******************
64 if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
65 std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
66 std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
67 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
69 std::set<ObjectPtr>::const_iterator aIt;
70 for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
71 ObjectPtr aObject = (*aIt);
72 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
73 if (aFeature && (!aFeature->isInHistory()))
76 DocumentPtr aDoc = aObject->document();
77 if (aDoc == aRootDoc) { // If root objects
78 if (aObject->groupName() == ModelAPI_ResultPart::group()) { // Update only Parts group
80 int aStart = aRootDoc->size(ModelAPI_ResultPart::group());
82 FeaturePtr aPartFeature = ModelAPI_Feature::feature(aObject);
83 PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
84 int anId = aRootDoc->index(aPartFeature);
85 aModel->setPart(aPartFeature);
86 myPartModels.append(aModel);
87 insertRow(aStart, partFolderNode(0));
89 } else { // Update top groups (other except parts
90 QModelIndex aIndex = myModel->findParent(aObject);
91 int aStart = myModel->rowCount(aIndex) - 1;
94 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
95 insertRow(aStart, aIndex);
97 } else { // if sub-objects of first level nodes
98 PartSet_PartModel* aPartModel = 0;
99 foreach (PartSet_PartModel* aPart, myPartModels) {
100 if (aPart->hasDocument(aDoc)) {
106 QModelIndex aIndex = aPartModel->findParent(aObject);
107 int aStart = aPartModel->rowCount(aIndex); // check this index
108 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
109 insertRow(aStart, aIndex);
114 // Deleted object event ***********************
115 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
116 std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
117 std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
118 DocumentPtr aDoc = aUpdMsg->document();
119 std::set<std::string> aGroups = aUpdMsg->groups();
121 std::set<std::string>::const_iterator aIt;
122 for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
123 std::string aGroup = (*aIt);
124 if (aDoc == aRootDoc) { // If root objects
125 if (aGroup == ModelAPI_ResultPart::group()) { // Update only Parts group
126 PartSet_PartModel* aDelPartModel = 0;
127 foreach (PartSet_PartModel* aPartModel, myPartModels) {
128 if (aPartModel->position() == -1) {
129 aDelPartModel = aPartModel;
135 int aStart = myPartModels.size() - 1;
136 removeSubModel(aDelPartModel);
137 removeRow(aStart, partFolderNode(0));
139 } if (aGroup == ModelAPI_Feature::group()) { // Update History node
140 int aRow = historyOffset() + aRootDoc->size(ModelAPI_Feature::group());
142 } else { // Update top groups (other except parts
143 QModelIndex aIndex = myModel->findGroup(aGroup);
144 int aStart = myModel->rowCount(aIndex);
145 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
146 removeRow(aStart, aIndex);
149 PartSet_PartModel* aPartModel = 0;
150 foreach (PartSet_PartModel* aPart, myPartModels) {
151 if (aPart->hasDocument(aDoc)) {
157 QModelIndex aIndex = aPartModel->findGroup(aGroup);
158 int aStart = aPartModel->rowCount(aIndex);
159 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
160 removeRow(aStart, aIndex);
164 // Deleted object event ***********************
165 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
166 //std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg = std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
167 //ObjectPtr aFeature = aUpdMsg->feature();
168 //DocumentPtr aDoc = aFeature->document();
170 // TODO: Identify the necessary index by the modified feature
172 emit dataChanged(aIndex, aIndex);
174 // Reset whole tree **************************
175 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
176 std::shared_ptr<Config_FeatureMessage> aFeatureMsg =
177 std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
178 if (!aFeatureMsg->isInternal()) {
179 ActionInfo aFeatureInfo;
180 aFeatureInfo.initFrom(aFeatureMsg);
181 // Remember features icons
182 myIcons[QString::fromStdString(aFeatureMsg->id())] = aFeatureInfo.iconFile;
189 void PartSet_DocumentDataModel::rebuildDataTree()
191 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
196 // Delete extra models
199 QList<PartSet_PartModel*> aDelList;
200 foreach (PartSet_PartModel* aPartModel, myPartModels) {
201 if (aPartModel->position() == -1)
202 aDelList.append(aPartModel);
204 foreach (PartSet_PartModel* aPartModel, aDelList) {
205 removeSubModel(aPartModel);
207 // Add non existing models
208 int aHistNb = aRootDoc->size(ModelAPI_Feature::group());
209 for (int i = 0; i < aHistNb; i++) {
210 aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
211 aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
212 if (aFeature->getKind() == PartSetPlugin_Part::ID()) {
213 if (!findPartModel(aFeature)) {
214 PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
215 aModel->setPart(aFeature);
216 myPartModels.append(aModel);
223 QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
225 if (!theIndex.isValid())
228 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
229 QModelIndex aParent = theIndex.parent();
230 if ((theIndex.column() == 1) ) {
231 if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
232 if (ModelAPI_Session::get()->activeDocument() == aRootDoc) {
233 if (!aParent.isValid()) {
235 case Qt::DecorationRole:
236 if (theIndex.row() == lastHistoryRow())
237 return QIcon(":pictures/arrow.png");
242 QModelIndex* aIndex = toSourceModelIndex(theIndex);
243 const QAbstractItemModel* aModel = aIndex->model();
244 if (isPartSubModel(aModel)) {
245 return aModel->data(*aIndex, theRole);
251 switch (theIndex.internalId()) {
254 case Qt::DisplayRole:
255 return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
256 case Qt::DecorationRole:
257 return QIcon(":pictures/constr_folder.png");
258 case Qt::ToolTipRole:
259 return tr("Parts folder");
260 case Qt::ForegroundRole:
261 if (myActivePartIndex.isValid())
262 return QBrush(PASSIVE_COLOR);
264 return QBrush(ACTIVE_COLOR);
271 int aOffset = historyOffset();
272 ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
273 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
277 case Qt::DisplayRole:
279 return aFeature->data()->name().c_str();
282 case Qt::DecorationRole:
283 return featureIcon(aFeature);
284 case Qt::ToolTipRole:
285 return tr("Feature object");
286 case Qt::ForegroundRole:
287 if (theIndex.row() > lastHistoryRow())
288 return QBrush(Qt::lightGray);
290 if (myActivePartIndex.isValid())
291 return QBrush(PASSIVE_COLOR);
293 return QBrush(ACTIVE_COLOR);
302 ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
305 case Qt::DisplayRole:
306 return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
307 case Qt::DecorationRole:
308 return QIcon(":pictures/part_ico.png");
309 case Qt::ForegroundRole:
311 if (theIndex == myActivePartIndex)
312 return QBrush(ACTIVE_COLOR);
314 return QBrush(PASSIVE_COLOR);
323 if (aParent.internalId() == HistoryNode) {
324 int aId = aParent.row() - historyOffset();
325 QModelIndex* aIndex = toSourceModelIndex(theIndex);
326 return findPartModel(aId)->data(*aIndex, theRole);
328 return toSourceModelIndex(theIndex)->data(theRole);
331 QVariant PartSet_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient,
337 int PartSet_DocumentDataModel::rowCount(const QModelIndex& theParent) const
339 SessionPtr aSession = ModelAPI_Session::get();
340 if (!aSession->hasModuleDocument())
342 DocumentPtr aRootDoc = aSession->moduleDocument();
343 if (!theParent.isValid()) {
344 // Size of external models
345 int aVal = historyOffset();
347 aVal += aRootDoc->size(ModelAPI_Feature::group());
350 if (theParent.internalId() == PartsFolder) {
351 return aRootDoc->size(ModelAPI_ResultPart::group());
352 //int aSize = myPartModels.size();
353 //return myPartModels.size();
355 if (theParent.internalId() == HistoryNode) {
356 int aId = theParent.row() - historyOffset();
357 PartSet_PartModel* aModel = findPartModel(aId);
359 return aModel->rowCount(QModelIndex());
362 if (theParent.internalId() == PartResult)
365 QModelIndex* aParent = toSourceModelIndex(theParent);
366 const QAbstractItemModel* aModel = aParent->model();
367 if (!isSubModel(aModel))
370 /*if (isPartSubModel(aModel)) {
371 if (aModel != myActivePart)
374 return aModel->rowCount(*aParent);
377 int PartSet_DocumentDataModel::columnCount(const QModelIndex& theParent) const
382 QModelIndex PartSet_DocumentDataModel::index(int theRow, int theColumn,
383 const QModelIndex& theParent) const
386 if (!theParent.isValid()) {
387 int aOffs = myModel->rowCount();
388 if (theRow < aOffs) {
389 aIndex = myModel->index(theRow, theColumn, theParent);
390 aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
392 if (theRow == aOffs) // Create Parts node
393 aIndex = partFolderNode(theColumn);
395 // create history node
396 aIndex = createIndex(theRow, theColumn, HistoryNode);
400 if (theParent.internalId() == PartsFolder) {
401 aIndex = createIndex(theRow, theColumn, PartResult);
403 if (theParent.internalId() == HistoryNode) {
404 int aId = theParent.row() - historyOffset();
405 aIndex = findPartModel(aId)->index(theRow, theColumn, QModelIndex());
407 QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
408 aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
410 aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
416 QModelIndex PartSet_DocumentDataModel::parent(const QModelIndex& theIndex) const
418 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
419 return QModelIndex();
421 if (theIndex.internalId() == PartResult)
422 return partFolderNode(0);
424 QModelIndex* aIndex = toSourceModelIndex(theIndex);
425 const QAbstractItemModel* aModel = aIndex->model();
426 if (!isSubModel(aModel))
427 return QModelIndex();
429 QModelIndex aIndex1 = aModel->parent(*aIndex);
430 const PartSet_PartModel* aPartModel = dynamic_cast<const PartSet_PartModel*>(aModel);
431 if (aPartModel && (!aIndex1.isValid())) {
432 int aId = aPartModel->position();
433 int aRow = aId + historyOffset();
434 return createIndex(aRow, 0, (qint32) HistoryNode);
437 if (aIndex1.isValid())
438 return createIndex(aIndex1.row(), 0, (void*) getModelIndex(aIndex1));
442 bool PartSet_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
444 if (!theParent.isValid())
446 return rowCount(theParent) > 0;
449 QModelIndex* PartSet_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
451 QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
455 QModelIndex* PartSet_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
457 QList<QModelIndex*>::const_iterator aIt;
458 for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
459 QModelIndex* aIndex = (*aIt);
460 if ((*aIndex) == theIndex)
466 QModelIndex* PartSet_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
468 QModelIndex* aIndexPtr = findModelIndex(theIndex);
470 aIndexPtr = new QModelIndex(theIndex);
471 PartSet_DocumentDataModel* that = (PartSet_DocumentDataModel*) this;
472 that->myIndexes.append(aIndexPtr);
477 void PartSet_DocumentDataModel::clearModelIndexes()
479 foreach (QModelIndex* aIndex, myIndexes)
484 void PartSet_DocumentDataModel::clearSubModels()
486 foreach (PartSet_PartModel* aPart, myPartModels)
488 myPartModels.clear();
489 myActivePartModel = 0;
492 ObjectPtr PartSet_DocumentDataModel::object(const QModelIndex& theIndex) const
494 if (theIndex.internalId() == PartsFolder)
496 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
497 if (theIndex.internalId() == HistoryNode) {
498 int aOffset = historyOffset();
499 return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
501 if (theIndex.internalId() == PartResult) {
502 return aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
504 QModelIndex* aIndex = toSourceModelIndex(theIndex);
505 if (!isSubModel(aIndex->model()))
508 const PartSet_FeaturesModel* aModel = dynamic_cast<const PartSet_FeaturesModel*>(aIndex->model());
509 return aModel->object(*aIndex);
512 bool PartSet_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
514 beginInsertRows(theParent, theRow, theRow + theCount - 1);
519 int aRow = rowCount(aRoot);
520 beginInsertRows(aRoot, aRow, aRow);
526 bool PartSet_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
528 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
533 void PartSet_DocumentDataModel::removeSubModel(int theModelId)
535 PartSet_PartModel* aModel = myPartModels.at(theModelId);
536 removeSubModel(aModel);
539 void PartSet_DocumentDataModel::removeSubModel(PartSet_PartModel* theModel)
542 for (int i = 0; i < myIndexes.size(); i++) {
543 if (myIndexes.at(i)->model() == theModel)
547 while (aToRemove.size() > 0) {
548 aId = aToRemove.last();
549 delete myIndexes.at(aId);
550 myIndexes.removeAt(aId);
551 aToRemove.removeLast();
553 if (theModel == myActivePartModel)
554 myActivePartModel = 0;
555 myPartModels.removeAll(theModel);
560 bool PartSet_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
562 if (theModel == myModel)
564 return isPartSubModel(theModel);
567 bool PartSet_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
569 return myPartModels.contains((PartSet_PartModel*) theModel);
572 QModelIndex PartSet_DocumentDataModel::partFolderNode(int theColumn) const
574 int aPos = myModel->rowCount(QModelIndex());
575 return createIndex(aPos, theColumn, PartsFolder);
578 int PartSet_DocumentDataModel::historyOffset() const
580 // Nb of rows of top model + Parts folder
581 return myModel->rowCount(QModelIndex()) + 1;
584 bool PartSet_DocumentDataModel::activatePart(const QModelIndex& theIndex)
586 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
589 if (theIndex.isValid() && (theIndex.internalId() == PartResult)) {
590 myActivePartIndex = theIndex;
591 myModel->setItemsColor(PASSIVE_COLOR);
592 if (myActivePartModel)
593 myActivePartModel->setItemsColor(PASSIVE_COLOR);
595 // Find activated part feature by its ID
596 ResultPartPtr aPartRes = activePart();
597 FeaturePtr aFeature = ModelAPI_Feature::feature(aPartRes);
598 if (aFeature.get()) {
599 myActivePartModel = findPartModel(aFeature);
600 myActivePartModel->setItemsColor(ACTIVE_COLOR);
606 ResultPartPtr PartSet_DocumentDataModel::activePart() const
608 if (myActivePartIndex.isValid()) {
609 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
610 ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myActivePartIndex.row());
611 return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
613 return ResultPartPtr();
616 QModelIndex PartSet_DocumentDataModel::activePartTree() const
618 if (myActivePartModel) {
619 return createIndex(myActivePartModel->position() + historyOffset(), 0, HistoryNode);
621 return QModelIndex();
624 void PartSet_DocumentDataModel::deactivatePart()
626 if (myActivePartIndex.isValid()) {
627 if (myActivePartModel)
628 myActivePartModel->setItemsColor(PASSIVE_COLOR);
629 myActivePartModel = 0;
630 myActivePartIndex = QModelIndex();
631 myModel->setItemsColor(ACTIVE_COLOR);
635 Qt::ItemFlags PartSet_DocumentDataModel::flags(const QModelIndex& theIndex) const
637 if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
638 Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
639 if (object(theIndex)) {
640 aFlags |= Qt::ItemIsEditable;
642 // Disable items which are below of last history row
643 // Do not disable second column
644 if (theIndex.internalId() == HistoryNode) {
645 if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
646 aFlags |= Qt::ItemIsEnabled;
648 aFlags |= Qt::ItemIsEnabled;
651 QModelIndex* aIndex = toSourceModelIndex(theIndex);
652 const QAbstractItemModel* aModel = aIndex->model();
653 Qt::ItemFlags aFlags = aModel->flags(*aIndex);
654 if (aModel == myModel) {
655 if (myModel->object(*aIndex))
656 aFlags |= Qt::ItemIsEditable;
662 QModelIndex PartSet_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
664 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
665 int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
666 for (int aId = 0; aId < aNb; aId++) {
667 if (theObject == aRootDoc->object(ModelAPI_ResultPart::group(), aId))
668 return createIndex(aId, 0, PartResult);
670 return QModelIndex();
673 QModelIndex PartSet_DocumentDataModel::objectIndex(const ObjectPtr theObject) const
675 // Check that this feature belongs to root document
676 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
677 DocumentPtr aDoc = theObject->document();
678 if (aDoc == aRootDoc) {
679 // This feature belongs to histrory or top model
680 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
683 int aNb = aRootDoc->size(ModelAPI_Feature::group());
684 for (aId = 0; aId < aNb; aId++) {
685 if (theObject == aRootDoc->object(ModelAPI_Feature::group(), aId))
689 return index(aId + historyOffset(), 0, QModelIndex());
691 QModelIndex aIndex = myModel->objectIndex(theObject);
694 createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
698 PartSet_PartModel* aPartModel = 0;
699 foreach(PartSet_PartModel* aModel, myPartModels) {
700 if (aModel->hasDocument(aDoc)) {
706 QModelIndex aIndex = aPartModel->objectIndex(theObject);
707 return aIndex.isValid() ?
708 createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
712 return QModelIndex();
716 void PartSet_DocumentDataModel::clear()
721 myActivePartIndex = QModelIndex();
722 myModel->setItemsColor(ACTIVE_COLOR);
725 int PartSet_DocumentDataModel::lastHistoryRow() const
727 DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
728 FeaturePtr aFeature = aRootDoc->currentFeature(true);
730 return historyOffset() + aRootDoc->index(aFeature);
732 return historyOffset() - 1;
735 void PartSet_DocumentDataModel::setLastHistoryItem(const QModelIndex& theIndex)
737 SessionPtr aMgr = ModelAPI_Session::get();
738 DocumentPtr aRootDoc = aMgr->moduleDocument();
739 std::string aOpName = tr("History change").toStdString();
740 if (theIndex.internalId() == HistoryNode) {
741 ObjectPtr aObject = object(theIndex);
742 aMgr->startOperation(aOpName);
743 aRootDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
744 aMgr->finishOperation();
746 aMgr->startOperation(aOpName);
747 aRootDoc->setCurrentFeature(FeaturePtr(), true);
748 aMgr->finishOperation();
752 QModelIndex PartSet_DocumentDataModel::lastHistoryItem() const
754 return index(lastHistoryRow(), 1);
758 QIcon PartSet_DocumentDataModel::featureIcon(const FeaturePtr& theFeature)
762 std::string aKind = theFeature->getKind();
763 QString aId(aKind.c_str());
764 if (!myIcons.contains(aId))
767 QString anIconString = myIcons[aId];
769 ModelAPI_ExecState aState = theFeature->data()->execState();
771 case ModelAPI_StateDone:
772 case ModelAPI_StateNothing: {
773 anIcon = QIcon(anIconString);
776 case ModelAPI_StateMustBeUpdated: {
777 anIcon = ModuleBase_Tools::lighter(anIconString);
780 case ModelAPI_StateExecFailed: {
781 anIcon = ModuleBase_Tools::composite(":icons/exec_state_failed.png", anIconString);
784 case ModelAPI_StateInvalidArgument: {
785 anIcon = ModuleBase_Tools::composite(":icons/exec_state_invalid_parameters.png",
794 void PartSet_DocumentDataModel::onMouseDoubleClick(const QModelIndex& theIndex)
796 if (theIndex.column() != 1)
798 QTreeView* aTreeView = dynamic_cast<QTreeView*>(sender());
799 if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
800 if (myActivePartModel)
801 // It means that the root document is not active
803 QModelIndex aNewIndex;
804 if (theIndex.internalId() == HistoryNode)
805 aNewIndex = theIndex;
806 int aOldId = lastHistoryRow();
807 setLastHistoryItem(theIndex);
808 int aStartRow = std::min(aOldId, theIndex.row());
809 int aEndRow = std::max(aOldId, theIndex.row());
810 for (int i = aStartRow; i <= aEndRow; i++) {
811 aTreeView->update(createIndex(i, 0, HistoryNode));
812 aTreeView->update(createIndex(i, 1, HistoryNode));
816 QModelIndex* aIndex = toSourceModelIndex(theIndex);
817 const QAbstractItemModel* aModel = aIndex->model();
818 if (isPartSubModel(aModel)) {
819 PartSet_PartDataModel* aPartModel = (PartSet_PartDataModel*)aModel;
820 QModelIndex aOldItem = aPartModel->lastHistoryItem();
821 aPartModel->setLastHistoryItem(*aIndex);
822 QModelIndex aOldIndex = createIndex(aOldItem.row(), aOldItem.column(), (void*) getModelIndex(aOldItem));
823 int aStartRow = std::min(aOldItem.row(), aIndex->row());
824 int aEndRow = std::max(aOldItem.row(), aIndex->row());
825 for (int i = aStartRow; i <= aEndRow; i++) {
826 QModelIndex aInd1 = aPartModel->index(i, 0);
827 QModelIndex aInd2 = createIndex(i, 0, (void*) getModelIndex(aInd1));
828 aTreeView->update(aInd2);
829 aInd1 = aPartModel->index(i, 1);
830 aInd2 = createIndex(i, 1, (void*) getModelIndex(aInd1));
831 aTreeView->update(aInd2);
838 PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(FeaturePtr thePart) const
840 foreach (PartSet_PartModel* aModel, myPartModels) {
841 if (aModel->part() == thePart)
847 PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(int thePosition) const
849 foreach (PartSet_PartModel* aModel, myPartModels) {
850 if (aModel->position() == thePosition)