1 // Copyright (C) 2014-2022 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 "PartSet_TreeNodes.h"
21 #include "PartSet_Tools.h"
23 #include <ModuleBase_IconFactory.h>
24 #include <ModuleBase_IWorkshop.h>
25 #include <ModuleBase_Tools.h>
27 #include <PartSetPlugin_Part.h>
29 #include <ModelAPI_Session.h>
30 #include <ModelAPI_ResultParameter.h>
31 #include <ModelAPI_ResultField.h>
32 #include <ModelAPI_ResultGroup.h>
33 #include <ModelAPI_ResultConstruction.h>
34 #include <ModelAPI_ResultPart.h>
35 #include <ModelAPI_ResultBody.h>
36 #include <ModelAPI_Tools.h>
37 #include <ModelAPI_ResultBody.h>
38 #include <ModelAPI_CompositeFeature.h>
39 #include <ModelAPI_AttributeDouble.h>
40 #include <ModelAPI_Folder.h>
41 #include <ModelAPI_AttributeReference.h>
43 #include <Config_PropManager.h>
49 #define ACTIVE_COLOR QColor(Qt::black)
50 #define SELECTABLE_COLOR QColor(100, 100, 100)
51 #define DISABLED_COLOR QColor(200, 200, 200)
53 Qt::ItemFlags aNullFlag;
54 Qt::ItemFlags aDefaultFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
55 Qt::ItemFlags aEditingFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
58 ResultPartPtr getPartResult(const ObjectPtr& theObj)
60 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
62 ResultPtr aRes = aFeature->firstResult();
63 if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
64 ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
65 // Use only original parts, not a placement results
66 if (aPartRes == aPartRes->original())
70 return ResultPartPtr();
73 bool isCurrentFeature(const ObjectPtr& theObj)
75 SessionPtr aSession = ModelAPI_Session::get();
76 DocumentPtr aCurDoc = aSession->activeDocument();
77 FeaturePtr aFeature = aCurDoc->currentFeature(true);
78 return aFeature == theObj;
81 //////////////////////////////////////////////////////////////////////////////////
82 QVariant PartSet_TreeNode::data(int theColumn, int theRole) const
84 if ((theColumn == 1) && (theRole == Qt::ForegroundRole)) {
85 Qt::ItemFlags aFlags = flags(theColumn);
86 if (aFlags == Qt::ItemFlags())
87 return QBrush(DISABLED_COLOR);
88 if (!aFlags.testFlag(Qt::ItemIsEditable))
89 return QBrush(SELECTABLE_COLOR);
90 return activeItemColor();
92 return ModuleBase_ITreeNode::data(theColumn, theRole);
95 QColor PartSet_TreeNode::activeItemColor() const
101 //////////////////////////////////////////////////////////////////////////////////
102 QVariant PartSet_ObjectNode::data(int theColumn, int theRole) const
105 case Qt::DisplayRole:
106 if (theColumn == 1) {
107 if (myObject->groupName() == ModelAPI_ResultParameter::group()) {
108 ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(myObject);
109 AttributeDoublePtr aValueAttribute =
110 aParam->data()->real(ModelAPI_ResultParameter::VALUE());
111 QString aVal = QString::number(aValueAttribute->value());
112 QString aTitle = QString::fromStdWString(myObject->data()->name());
113 return aTitle + " = " + aVal;
115 return QString::fromStdWString(myObject->data()->name());
118 case Qt::DecorationRole:
121 switch (visibilityState()) {
125 return QIcon(":pictures/eyeopen.png");
127 return QIcon(":pictures/eyemiclosed.png");
129 return QIcon(":pictures/eyeclosed.png");
132 return ModuleBase_IconFactory::get()->getIcon(myObject);
134 if (isCurrentFeature(myObject))
135 return QIcon(":pictures/arrow.png");
140 return PartSet_TreeNode::data(theColumn, theRole);
143 QColor PartSet_ObjectNode::activeItemColor() const
145 if (myObject.get() && myObject->groupName() == ModelAPI_Feature::group()) {
146 std::vector<int> aColor =
147 Config_PropManager::color("Visualization", "feature_objectbrowser_color");
148 return QColor(aColor[0], aColor[1], aColor[2]);
150 return PartSet_TreeNode::activeItemColor();
154 Qt::ItemFlags PartSet_ObjectNode::flags(int theColumn) const
156 if (myObject->isDisabled()) {
157 return (theColumn == 2) ? Qt::ItemIsSelectable : aNullFlag;
159 DocumentPtr aDoc = myObject->document();
160 SessionPtr aSession = ModelAPI_Session::get();
162 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(myObject);
163 if (aFeature.get() && aFeature->getKind() == "Group")
165 std::shared_ptr<ModelAPI_CompositeFeature> anOwner =
166 ModelAPI_Tools::compositeOwner (aFeature);
168 if (anOwner.get() && anOwner->getKind() == "ImportResult")
172 if (aSession->activeDocument() == aDoc)
178 PartSet_ObjectNode::VisibilityState PartSet_ObjectNode::visibilityState() const
180 Qt::ItemFlags aFlags = flags(1);
181 if (aFlags == Qt::ItemFlags())
184 if (myObject->groupName() == ModelAPI_ResultParameter::group())
186 ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
188 ModuleBase_IWorkshop* aWork = workshop();
189 ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResObj);
190 if (aCompRes.get()) {
191 std::list<ResultPtr> aResultsList;
192 ModelAPI_Tools::allSubs(aCompRes, aResultsList);
193 VisibilityState aState = aResultsList.size() == 0 ?
194 (aWork->isVisible(aCompRes) ? Visible : Hidden) : NoneState;
196 std::list<ResultPtr>::const_iterator aIt;
197 ResultBodyPtr aCompSub;
198 for (aIt = aResultsList.cbegin(); aIt != aResultsList.cend(); aIt++) {
199 ResultPtr aSubRes = (*aIt);
200 aCompSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aSubRes);
201 if (!(aCompSub.get() && aCompSub->numberOfSubs() > 0)) {
202 VisibilityState aS = aWork->isVisible(aSubRes) ? Visible : Hidden;
203 if (aState == NoneState)
205 else if (aState != aS) {
206 aState = SemiVisible;
213 if (aWork->isVisible(aResObj))
222 int PartSet_ObjectNode::numberOfSubs() const
224 ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myObject);
226 return aCompRes->numberOfSubs(true);
228 CompositeFeaturePtr aCompFeature =
229 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myObject);
230 if (aCompFeature.get() && aCompFeature->data()->isValid())
231 return aCompFeature->numberOfSubs(true);
233 ResultFieldPtr aFieldRes = std::dynamic_pointer_cast<ModelAPI_ResultField>(myObject);
235 return aFieldRes->stepsSize();
242 ObjectPtr PartSet_ObjectNode::subObject(int theId) const
244 ResultBodyPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myObject);
246 return aCompRes->subResult(theId, true);
248 CompositeFeaturePtr aCompFeature =
249 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myObject);
250 if (aCompFeature.get())
251 return aCompFeature->subFeature(theId, true);
256 void PartSet_ObjectNode::update()
258 int aNb = numberOfSubs();
260 ResultFieldPtr aFieldRes = std::dynamic_pointer_cast<ModelAPI_ResultField>(myObject);
262 // If the object is a field result then delete extra sub-objects
263 if (aFieldRes.get()) {
264 // Call shape in order to update content of Field.
265 // It is necessary to do for cases when field was created by script when module is inactive.
267 while (myChildren.size() > aNb) {
268 ModuleBase_ITreeNode* aNode = myChildren.last();
269 myChildren.removeAll(aNode);
275 ModuleBase_ITreeNode* aNode;
277 while (aId < myChildren.size()) {
278 aNode = myChildren.at(aId);
279 aObj = subObject(aId);
280 if (aNode->object() != aObj) {
281 myChildren.removeAll(aNode);
289 ModuleBase_ITreeNode* aNode;
292 for (i = 0; i < aNb; i++) {
293 aBody = subObject(i);
295 if (i < myChildren.size()) {
296 aNode = myChildren.at(i);
297 if (aNode->object() != aBody) {
298 ((PartSet_ObjectNode*)aNode)->setObject(aBody);
302 aNode = new PartSet_ObjectNode(aBody, this);
303 myChildren.append(aNode);
307 else if (aFieldRes.get()) {
308 FieldStepPtr aStep = aFieldRes->step(i);
310 if (i < myChildren.size()) {
311 PartSet_StepNode* aStepNode = static_cast<PartSet_StepNode*>(myChildren.at(i));
312 if (aStepNode->object() != aStep) {
313 aStepNode->setObject(aStep);
317 aNode = new PartSet_StepNode(aStep, this);
318 myChildren.append(aNode);
323 // Delete extra objects
324 while (myChildren.size() > aNb) {
325 aNode = myChildren.takeLast();
328 foreach(ModuleBase_ITreeNode* aChildNode, myChildren) {
329 aChildNode->update();
337 QTreeNodesList PartSet_ObjectNode::objectCreated(const QObjectPtrList& theObjects)
339 QTreeNodesList aResult;
340 int aNb = numberOfSubs();
342 ModuleBase_ITreeNode* aNode;
343 ResultFieldPtr aFieldRes = std::dynamic_pointer_cast<ModelAPI_ResultField>(myObject);
346 // Call shape in order to update content of Field.
347 // It is necessary to do for cases when field was created by script when module is inactive.
350 for (i = 0; i < aNb; i++) {
351 aBody = subObject(i);
353 if (i < myChildren.size()) {
354 aNode = myChildren.at(i);
355 if (aNode->object() != aBody) {
356 ((PartSet_ObjectNode*)aNode)->setObject(aBody);
357 aResult.append(aNode);
361 aNode = new PartSet_ObjectNode(aBody, this);
362 myChildren.append(aNode);
363 aResult.append(aNode);
368 FieldStepPtr aStep = aFieldRes->step(i);
370 if (i < myChildren.size()) {
371 PartSet_StepNode* aStepNode = static_cast<PartSet_StepNode*>(myChildren.at(i));
372 if (aStepNode->object() != aStep) {
373 aStepNode->setObject(aStep);
377 aNode = new PartSet_StepNode(aStep, this);
378 myChildren.append(aNode);
383 foreach(ModuleBase_ITreeNode* aChildNode, myChildren) {
384 aResult.append(aChildNode->objectCreated(theObjects));
390 QTreeNodesList PartSet_ObjectNode::objectsDeleted(
391 const DocumentPtr& theDoc, const QString& theGroup)
393 QTreeNodesList aResult;
394 int aNb = numberOfSubs();
395 if (aNb != myChildren.size()) {
398 aResult.append(this);
401 // Delete extra objects
402 bool isDeleted = false;
404 ModuleBase_ITreeNode* aNode;
406 while (aId < myChildren.size()) {
407 aNode = myChildren.at(aId);
408 aObj = subObject(aId);
409 if (aNode->object() != aObj) {
410 myChildren.removeAll(aNode);
418 aResult.append(this);
421 foreach(ModuleBase_ITreeNode* aChildNode, myChildren) {
422 aBody = subObject(i);
423 ((PartSet_ObjectNode*)aChildNode)->setObject(aBody);
424 aResult.append(aChildNode->objectsDeleted(theDoc, theGroup));
431 //////////////////////////////////////////////////////////////////////////////////
432 PartSet_FolderNode::PartSet_FolderNode(ModuleBase_ITreeNode* theParent,
434 : PartSet_TreeNode(theParent), myType(theType)
438 QString PartSet_FolderNode::name() const
441 case ParametersFolder:
442 return QObject::tr("Parameters");
443 case ConstructionFolder:
444 return QObject::tr("Constructions");
446 return QObject::tr("Parts");
448 return QObject::tr("Results");
450 return QObject::tr("Fields");
452 return QObject::tr("Groups");
458 QVariant PartSet_FolderNode::data(int theColumn, int theRole) const
460 static QIcon aParamsIco(":pictures/params_folder.png");
461 static QIcon aConstrIco(":pictures/constr_folder.png");
463 if (theColumn == 1) {
465 case Qt::DisplayRole:
466 return name() + QString(" (%1)").arg(childrenCount());
467 case Qt::DecorationRole:
469 case ParametersFolder:
471 case ConstructionFolder:
484 if ((theColumn == 2) && (theRole == Qt::DecorationRole)) {
485 if (document().get()) {
486 SessionPtr aSession = ModelAPI_Session::get();
487 if (document() != aSession->activeDocument())
490 FeaturePtr aFeature = document()->currentFeature(true);
491 if (!aFeature.get()) { // There is no current feature
492 ModuleBase_ITreeNode* aLastFolder = 0;
493 foreach(ModuleBase_ITreeNode* aNode, parent()->children()) {
494 if (aNode->type() == PartSet_FolderNode::typeId())
499 if (aLastFolder == this)
500 return QIcon(":pictures/arrow.png");
506 return PartSet_TreeNode::data(theColumn, theRole);
509 Qt::ItemFlags PartSet_FolderNode::flags(int theColumn) const
511 SessionPtr aSession = ModelAPI_Session::get();
512 DocumentPtr aActiveDoc = aSession->activeDocument();
513 if (theColumn == 1) {
514 if (document() == aActiveDoc)
520 ModuleBase_ITreeNode* PartSet_FolderNode::createNode(const ObjectPtr& theObj)
522 //ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObj);
523 //if (aCompRes.get())
524 // return new PartSet_CompsolidNode(theObj, this);
525 ModuleBase_ITreeNode* aNode = new PartSet_ObjectNode(theObj, this);
530 void PartSet_FolderNode::update()
532 DocumentPtr aDoc = document();
536 // Remove extra sub-nodes
539 while (aId < myChildren.size()) {
540 ModuleBase_ITreeNode* aNode = myChildren.at(aId);
541 aIndex = aDoc->index(aNode->object(), true);
542 if ((aIndex == -1) || (aId != aIndex)) {
543 myChildren.removeAll(aNode);
550 std::string aGroup = groupName();
551 int aSize = aDoc->size(aGroup, true);
552 for (int i = 0; i < aSize; i++) {
553 ObjectPtr aObj = aDoc->object(aGroup, i, true);
554 if (i < myChildren.size()) {
555 if (myChildren.at(i)->object() != aObj) {
556 ModuleBase_ITreeNode* aNode = createNode(aObj);
557 myChildren.insert(i, aNode);
560 ModuleBase_ITreeNode* aNode = createNode(aObj);
561 myChildren.append(aNode);
565 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
570 std::string PartSet_FolderNode::groupName() const
573 case ParametersFolder:
574 return ModelAPI_ResultParameter::group();
575 case ConstructionFolder:
576 return ModelAPI_ResultConstruction::group();
578 return ModelAPI_ResultPart::group();
580 return ModelAPI_ResultBody::group();
582 return ModelAPI_ResultField::group();
584 return ModelAPI_ResultGroup::group();
589 QTreeNodesList PartSet_FolderNode::objectCreated(const QObjectPtrList& theObjects)
591 QTreeNodesList aResult;
592 std::string aName = groupName();
593 DocumentPtr aDoc = document();
595 QMap<int, ModuleBase_ITreeNode*> aNewNodes;
596 foreach(ObjectPtr aObj, theObjects) {
597 if ((aObj->document() == aDoc) && (aObj->groupName() == aName)) {
598 aIdx = aDoc->index(aObj, true);
600 bool aHasObject = (aIdx < myChildren.size()) && (myChildren.at(aIdx)->object() == aObj);
602 ModuleBase_ITreeNode* aNode = createNode(aObj);
603 aNewNodes[aIdx] = aNode;
604 aResult.append(aNode);
610 // Add nodes in correct order
611 if (aNewNodes.size() > 0) {
613 for (i = 0; i < myChildren.size(); i++) {
614 if (aNewNodes.contains(i)) {
615 myChildren.insert(i, aNewNodes[i]);
619 while (aNewNodes.size()) {
620 i = myChildren.size();
621 myChildren.append(aNewNodes[i]);
625 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
626 aResult.append(aNode->objectCreated(theObjects));
631 QTreeNodesList PartSet_FolderNode::objectsDeleted(const DocumentPtr& theDoc,
632 const QString& theGroup)
634 DocumentPtr aDoc = document();
635 QTreeNodesList aResult;
636 if ((theGroup.toStdString() == groupName()) && (theDoc == aDoc)) {
637 QTreeNodesList aDelList;
640 bool aRemoved = false;
641 bool aToSort = false;
642 while (aId < myChildren.size()) {
643 ModuleBase_ITreeNode* aNode = myChildren.at(aId);
644 aIndex = aDoc->index(aNode->object(), true);
645 aToSort |= ((aIndex != -1) && (aId != aIndex));
647 myChildren.removeAll(aNode);
655 aResult.append(this);
658 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
659 aResult.append(aNode->objectsDeleted(theDoc, theGroup));
665 //////////////////////////////////////////////////////////////////////////////////
666 QTreeNodesList PartSet_FeatureFolderNode::objectCreated(const QObjectPtrList& theObjects)
668 QTreeNodesList aResult;
669 // Process the root sub-objects
670 DocumentPtr aDoc = document();
672 int aNb = numberOfFolders();
673 QMap<int, ModuleBase_ITreeNode*> aNewNodes;
674 foreach(ObjectPtr aObj, theObjects) {
675 if (aDoc == aObj->document()) {
676 if ((aObj->groupName() == ModelAPI_Feature::group()) ||
677 (aObj->groupName() == ModelAPI_Folder::group())){
678 aIdx = aDoc->index(aObj, true);
680 ModuleBase_ITreeNode* aNode = createNode(aObj);
682 bool aHasObject = (aIdx < myChildren.size()) && (myChildren.at(aIdx)->object() == aObj);
684 aNewNodes[aIdx] = aNode;
685 aResult.append(aNode);
692 // To add in correct order
693 if (aNewNodes.size() > 0) {
695 for (i = 0; i < myChildren.size(); i++) {
696 if (aNewNodes.contains(i)) {
697 myChildren.insert(i, aNewNodes[i]);
701 while (aNewNodes.size()) {
702 i = myChildren.size();
703 if (aNewNodes.contains(i)) {
704 myChildren.append(aNewNodes[i]);
709 // Update sub-folders
710 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
711 aResult.append(aNode->objectCreated(theObjects));
716 QTreeNodesList PartSet_FeatureFolderNode::objectsDeleted(const DocumentPtr& theDoc,
717 const QString& theGroup)
719 QTreeNodesList aResult;
721 // Process sub-folders
722 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
723 if (aNode->childrenCount() > 0) { // aFolder node
724 QTreeNodesList aList = aNode->objectsDeleted(theDoc, theGroup);
725 if (aList.size() > 0)
726 aResult.append(aList);
731 DocumentPtr aDoc = document();
732 int aNb = numberOfFolders();
733 bool isGroup = ((theGroup.toStdString() == ModelAPI_Feature::group()) ||
734 (theGroup.toStdString() == ModelAPI_Folder::group()));
735 if ((theDoc == aDoc) && isGroup) {
738 bool aRemoved = false;
739 bool aToSort = false;
740 while (aId < myChildren.size()) {
741 ModuleBase_ITreeNode* aNode = myChildren.at(aId);
742 if (aNode->object().get()) {
743 aIndex = aDoc->index(aNode->object(), true);
744 aToSort |= ((aIndex != -1) && (aId != (aIndex + aNb)));
746 myChildren.removeAll(aNode);
755 aResult.append(this);
762 ModuleBase_ITreeNode* PartSet_FeatureFolderNode::findParent(const DocumentPtr& theDoc,
765 ModuleBase_ITreeNode* aResult = 0;
766 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
767 aResult = aNode->findParent(theDoc, theGroup);
772 bool isGroup = ((theGroup.toStdString() == ModelAPI_Feature::group()) ||
773 (theGroup.toStdString() == ModelAPI_Folder::group()));
774 if ((theDoc == document()) && isGroup)
780 //////////////////////////////////////////////////////////////////////////////////
781 PartSet_RootNode::PartSet_RootNode() : PartSet_FeatureFolderNode(0), myWorkshop(0)
783 SessionPtr aSession = ModelAPI_Session::get();
784 DocumentPtr aDoc = aSession->moduleDocument();
786 myParamsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ParametersFolder);
787 myConstrFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ConstructionFolder);
788 myPartsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::PartsFolder);
790 myChildren.append(myParamsFolder);
791 myChildren.append(myConstrFolder);
792 myChildren.append(myPartsFolder);
798 void PartSet_RootNode::update()
800 myParamsFolder->update();
801 myConstrFolder->update();
802 myPartsFolder->update();
804 // Update features content
805 DocumentPtr aDoc = document();
806 int aNb = numberOfFolders();
808 // Remove extra sub-nodes
811 while (aId < myChildren.size()) {
812 ModuleBase_ITreeNode* aNode = myChildren.at(aId);
813 if (aNode->object().get()) {
814 aIndex = aDoc->index(aNode->object(), true);
815 if ((aIndex == -1) || (aId != (aIndex + aNb))) {
816 myChildren.removeAll(aNode);
825 std::string aGroup = ModelAPI_Feature::group();
826 int aSize = aDoc->size(aGroup, true);
828 for (int i = 0; i < aSize; i++) {
829 ObjectPtr aObj = aDoc->object(aGroup, i, true);
830 aId = i + aNb; // Take into account existing folders
831 if (aId < myChildren.size()) {
832 if (myChildren.at(aId)->object() != aObj) {
833 ModuleBase_ITreeNode* aNode = createNode(aObj);
834 myChildren.insert(aId, aNode);
837 ModuleBase_ITreeNode* aNode = createNode(aObj);
838 myChildren.append(aNode);
841 // Update sub-folders
842 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
843 if ((aNode->type() == PartSet_ObjectFolderNode::typeId()) ||
844 (aNode->type() == PartSet_PartRootNode::typeId()))
849 DocumentPtr PartSet_RootNode::document() const
851 return ModelAPI_Session::get()->moduleDocument();
854 ModuleBase_ITreeNode* PartSet_RootNode::createNode(const ObjectPtr& theObj)
856 if (theObj->groupName() == ModelAPI_Folder::group())
857 return new PartSet_ObjectFolderNode(theObj, this);
859 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
860 if (aFeature->getKind() == PartSetPlugin_Part::ID())
861 return new PartSet_PartRootNode(theObj, this);
863 PartSet_ObjectNode* aNode = new PartSet_ObjectNode(theObj, this);
868 //////////////////////////////////////////////////////////////////////////////////
869 PartSet_PartRootNode::PartSet_PartRootNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent)
870 : PartSet_FeatureFolderNode(theParent), myObject(theObj)
872 myParamsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ParametersFolder);
873 myConstrFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ConstructionFolder);
874 myResultsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ResultsFolder);
875 myFieldsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::FieldsFolder);
876 myGroupsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::GroupsFolder);
878 myChildren.append(myParamsFolder);
879 myChildren.append(myConstrFolder);
880 myChildren.append(myResultsFolder);
885 void PartSet_PartRootNode::deleteChildren()
887 if (!myFieldsFolder->childrenCount()) {
888 delete myFieldsFolder;
890 if (!myGroupsFolder->childrenCount()) {
891 delete myGroupsFolder;
893 PartSet_FeatureFolderNode::deleteChildren();
897 void PartSet_PartRootNode::update()
899 DocumentPtr aDoc = document();
903 myParamsFolder->update();
904 myConstrFolder->update();
905 myResultsFolder->update();
906 myFieldsFolder->update();
907 myGroupsFolder->update();
909 bool aHasFields = myFieldsFolder->childrenCount() > 0;
910 bool aHasGroups = myGroupsFolder->childrenCount() > 0;
912 if (!myChildren.contains(myFieldsFolder)) {
913 myChildren.insert(3, myFieldsFolder);
915 } else if (myChildren.contains(myFieldsFolder)) {
916 myChildren.removeAll(myFieldsFolder);
919 if (!myChildren.contains(myGroupsFolder)) {
920 myChildren.insert(aHasFields ? 4 : 3, myGroupsFolder);
922 } else if (myChildren.contains(myGroupsFolder)) {
923 myChildren.removeAll(myGroupsFolder);
926 // Update features content
927 int aRows = numberOfFolders();
929 // Remove extra sub-nodes
932 QMap<int, ModuleBase_ITreeNode*> aExistingNodes;
933 while (aId < myChildren.size()) {
934 ModuleBase_ITreeNode* aNode = myChildren.at(aId);
935 if (aNode->object().get()) {
936 aIndex = aDoc->index(aNode->object(), true);
937 if ((aIndex == -1) || (aId != (aIndex + aRows))) {
938 myChildren.removeAll(aNode);
942 aExistingNodes[aIndex + aRows] = aNode;
949 std::string aGroup = ModelAPI_Feature::group();
950 int aSize = aDoc->size(aGroup, true);
952 for (int i = 0; i < aSize; i++) {
953 ObjectPtr aObj = aDoc->object(aGroup, i, true);
954 aId = i + aRows; // Take into account existing folders
955 if (aId < myChildren.size()) {
956 if (myChildren.at(aId)->object() != aObj) {
957 if (aExistingNodes.contains(aId)) {
958 myChildren.insert(aId, aExistingNodes[aId]);
959 aExistingNodes.remove(aId);
962 myChildren.insert(aId, createNode(aObj));
966 if (aExistingNodes.contains(myChildren.size()))
967 myChildren.append(aExistingNodes[myChildren.size()]);
969 myChildren.append(createNode(aObj));
972 // Update sub-folders
973 foreach(ModuleBase_ITreeNode* aNode, myChildren) {
974 if (aNode->type() == PartSet_ObjectFolderNode::typeId())
979 DocumentPtr PartSet_PartRootNode::document() const
981 ResultPartPtr aPartRes = getPartResult(myObject);
983 return aPartRes->partDoc();
984 return DocumentPtr();
987 QVariant PartSet_PartRootNode::data(int theColumn, int theRole) const
992 case Qt::DisplayRole:
994 ResultPartPtr aPartRes = getPartResult(myObject);
995 if (aPartRes.get()) {
996 if (aPartRes->partDoc().get() == NULL)
997 return QString::fromStdWString(myObject->data()->name()) + " (Not loaded)";
999 return QString::fromStdWString(myObject->data()->name());
1001 case Qt::DecorationRole:
1002 return ModuleBase_IconFactory::get()->getIcon(myObject);
1005 if (theRole == Qt::DecorationRole) {
1006 if (isCurrentFeature(myObject))
1007 return QIcon(":pictures/arrow.png");
1012 return PartSet_TreeNode::data(theColumn, theRole);
1015 Qt::ItemFlags PartSet_PartRootNode::flags(int theColumn) const
1017 if (myObject->isDisabled())
1018 return (theColumn == 2) ? Qt::ItemIsSelectable : aNullFlag;
1020 SessionPtr aSession = ModelAPI_Session::get();
1021 DocumentPtr aActiveDoc = aSession->activeDocument();
1022 if ((aActiveDoc == document()) || (myObject->document() == aActiveDoc))
1023 return aEditingFlag;
1024 return aDefaultFlag;
1027 ModuleBase_ITreeNode* PartSet_PartRootNode::createNode(const ObjectPtr& theObj)
1029 if (theObj->groupName() == ModelAPI_Folder::group())
1030 return new PartSet_ObjectFolderNode(theObj, this);
1031 PartSet_ObjectNode* aNode = new PartSet_ObjectNode(theObj, this);
1036 int PartSet_PartRootNode::numberOfFolders() const
1039 if (myFieldsFolder->childrenCount() > 0)
1041 if (myGroupsFolder->childrenCount() > 0)
1046 QTreeNodesList PartSet_PartRootNode::objectCreated(const QObjectPtrList& theObjects)
1048 QTreeNodesList aResult = PartSet_FeatureFolderNode::objectCreated(theObjects);
1049 if (!myFieldsFolder->childrenCount()) {
1050 QTreeNodesList aList = myFieldsFolder->objectCreated(theObjects);
1052 myChildren.insert(3, myFieldsFolder);
1053 aResult.append(myFieldsFolder);
1054 aResult.append(aList);
1057 if (!myGroupsFolder->childrenCount()) {
1058 QTreeNodesList aList = myGroupsFolder->objectCreated(theObjects);
1060 myChildren.insert(myFieldsFolder->childrenCount()? 4 : 3, myGroupsFolder);
1061 aResult.append(myGroupsFolder);
1062 aResult.append(aList);
1068 QTreeNodesList PartSet_PartRootNode::objectsDeleted(const DocumentPtr& theDoc,
1069 const QString& theGroup)
1071 QTreeNodesList aResult;
1072 if (myFieldsFolder->childrenCount()) {
1073 QTreeNodesList aList = myFieldsFolder->objectsDeleted(theDoc, theGroup);
1075 aResult.append(aList);
1076 if (!myFieldsFolder->childrenCount())
1077 myChildren.removeAll(myFieldsFolder);
1080 if (myGroupsFolder->childrenCount()) {
1081 QTreeNodesList aList = myGroupsFolder->objectsDeleted(theDoc, theGroup);
1083 aResult.append(aList);
1084 if (!myGroupsFolder->childrenCount())
1085 myChildren.removeAll(myGroupsFolder);
1088 aResult.append(PartSet_FeatureFolderNode::objectsDeleted(theDoc, theGroup));
1092 //////////////////////////////////////////////////////////////////////////////////
1093 void PartSet_ObjectFolderNode::update()
1095 int aFirst = -1, aLast = -1;
1096 PartSet_Tools::getFirstAndLastIndexInFolder(myObject, aFirst, aLast);
1097 if ((aFirst == -1) || (aLast == -1)) {
1102 int aNbItems = aLast - aFirst + 1;
1108 DocumentPtr aDoc = myObject->document();
1109 if (aNbItems < myChildren.size()) {
1110 // Delete obsolete nodes
1112 int aNbOfFeatures = aDoc->size(ModelAPI_Feature::group(), true);
1113 while (aId < myChildren.size()) {
1114 ModuleBase_ITreeNode* aNode = myChildren.at(aId);
1115 if ((aId < aNbItems) && ((aFirst + aId) < aNbOfFeatures)) {
1116 if (aNode->object() != aDoc->object(ModelAPI_Feature::group(), aFirst + aId)) {
1117 myChildren.removeAll(aNode);
1123 myChildren.removeAll(aNode);
1130 if (aNbItems > myChildren.size()) {
1132 ModuleBase_ITreeNode* aNode;
1133 for (int i = 0; i < aNbItems; i++) {
1134 ObjectPtr aObj = aDoc->object(ModelAPI_Feature::group(), aFirst + i);
1135 if (i < myChildren.size()) {
1136 if (aObj != myChildren.at(i)->object()) {
1137 aNode = new PartSet_ObjectNode(aObj, this);
1138 myChildren.insert(i, aNode);
1143 aNode = new PartSet_ObjectNode(aObj, this);
1144 myChildren.append(aNode);
1151 QTreeNodesList PartSet_ObjectFolderNode::objectCreated(const QObjectPtrList& /*theObjects*/)
1153 QTreeNodesList aResult;
1154 int aFirst = -1, aLast = -1;
1155 PartSet_Tools::getFirstAndLastIndexInFolder(myObject, aFirst, aLast);
1156 if ((aFirst == -1) || (aLast == -1)) {
1159 int aNbItems = aLast - aFirst + 1;
1163 DocumentPtr aDoc = myObject->document();
1165 ModuleBase_ITreeNode* aNode;
1166 for (int i = 0; i < aNbItems; i++) {
1167 ObjectPtr aObj = aDoc->object(ModelAPI_Feature::group(), aFirst + i);
1168 if (i < myChildren.size()) {
1169 if (aObj != myChildren.at(i)->object()) {
1170 aNode = new PartSet_ObjectNode(aObj, this);
1171 myChildren.insert(i, aNode);
1172 aResult.append(aNode);
1176 aNode = new PartSet_ObjectNode(aObj, this);
1177 myChildren.append(aNode);
1178 aResult.append(aNode);
1185 QTreeNodesList PartSet_ObjectFolderNode::objectsDeleted(const DocumentPtr& /*theDoc*/,
1186 const QString& /*theGroup*/)
1188 QTreeNodesList aResult;
1189 int aFirst = -1, aLast = -1;
1190 PartSet_Tools::getFirstAndLastIndexInFolder(myObject, aFirst, aLast);
1191 if ((aFirst == -1) || (aLast == -1)) {
1194 int aNbItems = aLast - aFirst + 1;
1198 if (aNbItems >= myChildren.size()) // Nothing was deleted here
1201 DocumentPtr aDoc = myObject->document();
1202 // Delete obsolete nodes
1203 bool aRemoved = false;
1205 int aNbOfFeatures = aDoc->size(ModelAPI_Feature::group(), true);
1206 while (aId < myChildren.size()) {
1207 ModuleBase_ITreeNode* aNode = myChildren.at(aId);
1208 if ((aFirst + aId) < aNbOfFeatures) {
1209 if (aNode->object() != aDoc->object(ModelAPI_Feature::group(), aFirst + aId)) {
1210 myChildren.removeAll(aNode);
1217 myChildren.removeAll(aNode);
1218 aResult.removeAll(aNode);
1226 aResult.append(this);
1231 QVariant PartSet_ObjectFolderNode::data(int theColumn, int theRole) const
1233 if (theRole == Qt::ForegroundRole) {
1234 if (!myObject->isDisabled()) {
1235 std::vector<int> aColor =
1236 Config_PropManager::color("Visualization", "feature_objectbrowser_color");
1237 return QColor(aColor[0], aColor[1], aColor[2]);
1240 return PartSet_ObjectNode::data(theColumn, theRole);
1244 //////////////////////////////////////////////////////////////////////////////////
1245 QVariant PartSet_StepNode::data(int theColumn, int theRole) const
1247 if ((theColumn == 1) && (theRole == Qt::DisplayRole)) {
1248 FieldStepPtr aStep =
1249 std::dynamic_pointer_cast<ModelAPI_ResultField::ModelAPI_FieldStep>(myObject);
1251 return "Step " + QString::number(aStep->id() + 1) + " " +
1252 aStep->field()->textLine(aStep->id()).c_str();
1254 return PartSet_ObjectNode::data(theColumn, theRole);
1257 ModuleBase_ITreeNode::VisibilityState PartSet_StepNode::visibilityState() const
1259 Qt::ItemFlags aFlags = flags(1);
1260 if (aFlags == Qt::ItemFlags())
1263 ModuleBase_IWorkshop* aWork = workshop();
1264 if (aWork->isVisible(myObject))