]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Redevelopment of object browser data model
authorvsv <vsv@opencascade.com>
Thu, 19 Jul 2018 12:56:52 +0000 (15:56 +0300)
committervsv <vsv@opencascade.com>
Thu, 19 Jul 2018 12:56:52 +0000 (15:56 +0300)
16 files changed:
src/ModuleBase/ModuleBase_ITreeNode.h
src/ModuleBase/ModuleBase_IWorkshop.h
src/ModuleBase/ModuleBase_OperationFeature.cpp
src/PartSet/CMakeLists.txt
src/PartSet/PartSet_DataModel.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_TreeNodes.cpp
src/PartSet/PartSet_TreeNodes.h
src/XGUI/XGUI_DataModel.cpp
src/XGUI/XGUI_DataModel.h
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ModuleConnector.h
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_ObjectsBrowser.h
src/XGUI/XGUI_Workshop.cpp

index 954e72f0349dc6228c3743864dbe8aee0e7be6de..9e33eeae5fc9d752bd844d13f27fc034084753fd 100644 (file)
 #define ModuleBase_ITreeNode_H
 
 #include "ModuleBase.h"
+#include "ModuleBase_Definitions.h"
 
 #include <ModelAPI_Object.h>
+#include <ModelAPI_Document.h>
 
 #include <QList>
 #include <QString>
 #include <QIcon>
+#include <QVariant>
 
 class ModuleBase_ITreeNode;
+class ModuleBase_IWorkshop;
 
 typedef QList<ModuleBase_ITreeNode*> QTreeNodesList;
 
@@ -37,19 +41,13 @@ class ModuleBase_ITreeNode
 {
 public:
   /// Default constructor
-  ModuleBase_ITreeNode() : myParent(0) {}
+  ModuleBase_ITreeNode(ModuleBase_ITreeNode* theParent = 0) : myParent(theParent) {}
 
-  /// Returns name of the node
-  virtual QString name() const { return "Item"; }
-
-  /// Returns icon of the node
-  virtual QIcon icon() const { return QIcon(); }
-
-  /// Returns foreground color of the node
-  virtual QColor color() const { return Qt::black;  }
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const { return QVariant(); }
 
   /// Returns properties flag of the item
-  virtual Qt::ItemFlags falg() const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; }
+  virtual Qt::ItemFlags flags(int theColumn) const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; }
 
   /// Returns parent node of the current node
   ModuleBase_ITreeNode* parent() const { return myParent; }
@@ -57,9 +55,83 @@ public:
   /// Returns list of the node children
   QTreeNodesList children() const { return myChildren; }
 
+  /// Returns a children node according to given row (index)
+  ModuleBase_ITreeNode* subNode(int theRow) const
+  {
+    if ((theRow > -1) && (theRow < myChildren.length()))
+      return myChildren.at(theRow);
+    return 0;
+  }
+
+  /// Finds a node which contains the referenced object
+  /// \param theObj an object to find
+  /// \param allLevels if true then all sub-trees will be processed
+  ModuleBase_ITreeNode* subNode(const ObjectPtr& theObj, bool allLevels = true) const
+  {
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      if (aNode->object() == theObj)
+        return aNode;
+      if (allLevels) {
+        ModuleBase_ITreeNode* aSubNode = aNode->subNode(theObj, allLevels);
+        if (aSubNode)
+          return aSubNode;
+      }
+    }
+    return 0;
+  }
+
+  /// Returns true if the given node is found within children
+  /// \param theNode a node to find
+  /// \param allLevels if true then all sub-trees will be processed
+  bool hasSubNode(ModuleBase_ITreeNode* theNode, bool allLevels = true) const
+  {
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      if (aNode == theNode)
+        return true;
+      if (allLevels) {
+        if (aNode->hasSubNode(theNode))
+          return true;
+      }
+    }
+    return false;
+  }
+
+  /// Returns number of children
+  int childrenCount() const { return myChildren.length(); }
+
+  int nodeRow(ModuleBase_ITreeNode* theNode) const { return myChildren.indexOf(theNode); }
+
   /// Returns object referenced by the node (can be null)
   virtual ObjectPtr object() const { return ObjectPtr(); }
 
+  /// Updates all sub-nodes of the node (checks whole sub-tree)
+  virtual void update() {}
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects) { return QTreeNodesList(); }
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  /// \return a list of parents where nodes were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup)
+  { return QTreeNodesList(); }
+
+  /// Returns workshop object. Has to be reimplemented in a root node
+  virtual ModuleBase_IWorkshop* workshop() const { return parent()->workshop(); }
+
+  /// Returns document object of the sub-tree. Has to be reimplemented in sub-tree root object
+  virtual DocumentPtr document() const { return parent()->document(); }
+
+  /// Returns a node which belongs to the given document and contains objects of the given group
+  /// \param theDoc a document
+  /// \param theGroup a name of objects group
+  /// \return a parent node if it is found
+  virtual ModuleBase_ITreeNode* findParent(const DocumentPtr& theDoc, QString theGroup)
+  { return 0; }
+
 protected:
   ModuleBase_ITreeNode* myParent; //!< Parent of the node
   QTreeNodesList myChildren; //!< Children of the node
index e9a4d2c350b788ee8249c6cc19500ec370f2bba4..e8cf8b62215e291d3aebbee535a3ebe3cf9eea22 100644 (file)
@@ -112,6 +112,10 @@ Q_OBJECT
   //! \param theAIS a presentation
   virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const = 0;
 
+  //! Returns true if the object is displayed
+  //! \param theObject a data object
+  virtual bool isVisible(const ObjectPtr& theObject) const = 0;
+
   //! Select features clearing previous selection.
   //! If the list is empty then selection will be cleared
   //! \param theValues a list of presentations
index c54669495dc94918a5ad39125cc288fe312591c9..b7b72a47b2c91ad85888612732fff36771c0dc44 100755 (executable)
@@ -187,10 +187,10 @@ FeaturePtr ModuleBase_OperationFeature::createFeature(const bool theFlushMessage
      }*/
   }
 
-  if (theFlushMessage) {
-    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  }
+  //if (theFlushMessage) {
+  //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+  //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  //}
   return myFeature;
 }
 
index 2ed698518e31c3da57347612e08108a4ad4ae6a2..c029f0565752068615d9af7f9698f927de30a50f 100644 (file)
@@ -58,7 +58,6 @@ SET(PROJECT_HEADERS
     PartSet_WidgetSketchLabel.h
     PartSet_CenterPrs.h
     PartSet_ExternalPointsMgr.h
-       PartSet_DataModel.h
        PartSet_TreeNodes.h
 )
 
@@ -108,7 +107,6 @@ SET(PROJECT_SOURCES
     PartSet_WidgetSketchLabel.cpp
     PartSet_CenterPrs.cpp
     PartSet_ExternalPointsMgr.cpp
-       PartSet_DataModel.cpp
        PartSet_TreeNodes.cpp
 )
 
index 57f0735b537a08da50beecac64c03818b376ae79..a95e64d8bd67a7c6073fe04492fd053ecdb1b554 100644 (file)
@@ -19,6 +19,7 @@
 //
 
 #include "PartSet_DataModel.h"
+#include "PartSet_TreeNodes.h"
 
 #include <ModelAPI_Events.h>
 
 
 PartSet_DataModel::PartSet_DataModel()
 {
-  Events_Loop* aLoop = Events_Loop::loop();
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_ORDER_UPDATED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
+//  Events_Loop* aLoop = Events_Loop::loop();
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_ORDER_UPDATED));
+//  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
 }
 
 
index 14d46deaed39edc733f30129b06ff47af82786c3..b5c1821be845f9621cd779c094d9fde3df617363 100755 (executable)
@@ -38,7 +38,7 @@
 #include "PartSet_CustomPrs.h"
 #include "PartSet_IconFactory.h"
 #include "PartSet_OverconstraintListener.h"
-#include "PartSet_DataModel.h"
+#include "PartSet_TreeNodes.h"
 
 #include "PartSet_Filters.h"
 #include "PartSet_FilterInfinite.h"
@@ -151,6 +151,7 @@ extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop*
 PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
 : ModuleBase_IModule(theWshop),
   myVisualLayerId(0),
+  myRoot(0),
   myIsOperationIsLaunched(false)
 {
   new PartSet_IconFactory();
@@ -158,8 +159,6 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
   mySketchMgr = new PartSet_SketcherMgr(this);
   mySketchReentrantMgr = new PartSet_SketcherReentrantMgr(theWshop);
 
-  myDataModel = new PartSet_DataModel();
-
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
 
@@ -222,8 +221,18 @@ PartSet_Module::~PartSet_Module()
   }
   delete myCustomPrs;
   delete myOverconstraintListener;
+  delete myRoot;
+}
+
+//******************************************************
+void PartSet_Module::createFeatures()
+{
+  ModuleBase_IModule::createFeatures();
+  myRoot = new PartSet_RootNode();
+  myRoot->setWorkshop(workshop());
 }
 
+
 //******************************************************
 void PartSet_Module::storeSelection()
 {
@@ -1644,5 +1653,5 @@ void PartSet_Module::setDefaultConstraintShown()
 //******************************************************
 ModuleBase_ITreeNode* PartSet_Module::rootNode() const
 {
-  return myDataModel->root();
+  return myRoot;
 }
index d196b6bdd392d4ccbfc823627cc95cb613af6421..3979a599bc8fa0273d067dd3b37a561fac44d009 100755 (executable)
@@ -58,7 +58,7 @@ class PartSet_MenuMgr;
 class PartSet_CustomPrs;
 class PartSet_SketcherMgr;
 class PartSet_SketcherReentrantMgr;
-class PartSet_DataModel;
+class PartSet_RootNode;
 class ModelAPI_Result;
 
 class QAction;
@@ -400,6 +400,9 @@ public:
   /// Returns the workshop
   XGUI_Workshop* getWorkshop() const;
 
+  /// Reads description of features from XML file
+  virtual void createFeatures();
+
 public slots:
   /// Slolt called on object display
   /// \param theObject a data object
@@ -495,7 +498,7 @@ private:
   PartSet_SketcherMgr::FeatureToSelectionMap myCurrentSelection;
   QModelIndex myActivePartIndex;
 
-  PartSet_DataModel* myDataModel;
+  PartSet_RootNode* myRoot;
 };
 
 #endif
index 3d029e57b61da1390b7847ed46264f9d46576a77..6c1c9dd89267c5444c17225efdbaacfc47ad1fdc 100644 (file)
 
 #include "PartSet_TreeNodes.h"
 
+#include <ModuleBase_IconFactory.h>
+#include <ModuleBase_IWorkshop.h>
 
-PartSet_RootNode::PartSet_RootNode()
+#include <PartSetPlugin_Part.h>
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_ResultField.h>
+#include <ModelAPI_ResultGroup.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_CompositeFeature.h>
+#include <ModelAPI_AttributeDouble.h>
+
+
+#include <QBrush>
+
+
+#define ACTIVE_COLOR QColor(Qt::black)
+#define SELECTABLE_COLOR QColor(100, 100, 100)
+#define DISABLED_COLOR QColor(200, 200, 200)
+
+Qt::ItemFlags aNullFlag;
+Qt::ItemFlags aDefaultFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+Qt::ItemFlags aEditingFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+
+
+ResultPartPtr getPartResult(const ObjectPtr& theObj)
+{
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+  if (aFeature) {
+    ResultPtr aRes = aFeature->firstResult();
+    if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
+      ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
+      // Use only original parts, not a placement results
+      if (aPartRes == aPartRes->original())
+        return aPartRes;
+    }
+  }
+  return ResultPartPtr();
+}
+
+bool isCurrentFeature(const ObjectPtr& theObj)
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aCurDoc = aSession->activeDocument();
+  FeaturePtr aFeature = aCurDoc->currentFeature(true);
+  return aFeature == theObj;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+QVariant PartSet_TreeNode::data(int theColumn, int theRole) const
+{
+  if ((theColumn == 1) && (theRole == Qt::ForegroundRole)) {
+    Qt::ItemFlags aFlags = flags(theColumn);
+    if (aFlags == Qt::ItemFlags())
+      return QBrush(DISABLED_COLOR);
+    if (!aFlags.testFlag(Qt::ItemIsEditable))
+      return QBrush(SELECTABLE_COLOR);
+    return ACTIVE_COLOR;
+  }
+  return ModuleBase_ITreeNode::data(theColumn, theRole);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+QVariant PartSet_ObjectNode::data(int theColumn, int theRole) const
+{
+  switch (theRole) {
+  case Qt::DisplayRole:
+    if (theColumn == 1) {
+      if (myObject->groupName() == ModelAPI_ResultParameter::group()) {
+        ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(myObject);
+        AttributeDoublePtr aValueAttribute =
+          aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+        QString aVal = QString::number(aValueAttribute->value());
+        QString aTitle = QString(myObject->data()->name().c_str());
+        return aTitle + " = " + aVal;
+      }
+      return myObject->data()->name().c_str();
+    }
+    break;
+  case Qt::DecorationRole:
+    switch (theColumn) {
+    case 0:
+      switch (getVisibilityState()) {
+      case NoneState:
+        return QIcon();
+      case Visible:
+        return QIcon(":pictures/eyeopen.png");
+      case SemiVisible:
+        return QIcon(":pictures/eyemiclosed.png");
+      case Hidden:
+        return QIcon(":pictures/eyeclosed.png");
+      }
+    case 1:
+      return ModuleBase_IconFactory::get()->getIcon(myObject);
+    case 2:
+      if (isCurrentFeature(myObject))
+        return QIcon(":pictures/arrow.png");
+    }
+  }
+  return PartSet_TreeNode::data(theColumn, theRole);
+}
+
+Qt::ItemFlags PartSet_ObjectNode::flags(int theColumn) const
+{
+  if (!myObject->isDisabled()) {
+    DocumentPtr aDoc = myObject->document();
+    SessionPtr aSession = ModelAPI_Session::get();
+    if (aSession->activeDocument() == aDoc)
+      return aEditingFlag;
+  }
+  return aDefaultFlag;
+}
+
+PartSet_ObjectNode::VisibilityState PartSet_ObjectNode::getVisibilityState() const
+{
+  Qt::ItemFlags aFlags = flags(1);
+  if (aFlags == Qt::ItemFlags())
+    return NoneState;
+
+  if (myObject->groupName() == ModelAPI_ResultParameter::group())
+    return NoneState;
+  ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+  if (aResObj.get()) {
+    ModuleBase_IWorkshop* aWork = workshop();
+    ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResObj);
+    if (aCompRes.get()) {
+      VisibilityState aState = aCompRes->numberOfSubs(true) == 0 ?
+        (aWork->isVisible(aCompRes) ? Visible : Hidden) : NoneState;
+      for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
+        ResultPtr aSubRes = aCompRes->subResult(i, true);
+        VisibilityState aS = aWork->isVisible(aSubRes) ? Visible : Hidden;
+        if (aState == NoneState)
+          aState = aS;
+        else if (aState != aS) {
+          aState = SemiVisible;
+          break;
+        }
+      }
+      return aState;
+    } else {
+      if (aWork->isVisible(aResObj))
+        return Visible;
+      else
+        return Hidden;
+    }
+  }
+  return NoneState;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+PartSet_FolderNode::PartSet_FolderNode(ModuleBase_ITreeNode* theParent,
+  FolderType theType)
+  : PartSet_TreeNode(theParent), myType(theType)
+{
+}
+
+PartSet_FolderNode::~PartSet_FolderNode()
+{
+  while (myChildren.length() > 0) {
+    ModuleBase_ITreeNode* aNode = myChildren.last();
+    myChildren.removeAll(aNode);
+    delete aNode;
+  }
+}
+
+QString PartSet_FolderNode::name() const
+{
+  switch (myType) {
+  case ParametersFolder:
+    return QObject::tr("Parameters");
+  case ConstructionFolder:
+    return QObject::tr("Constructions");
+  case PartsFolder:
+    return QObject::tr("Parts");
+  case ResultsFolder:
+    return QObject::tr("Results");
+  case FieldsFolder:
+    return QObject::tr("Fields");
+  case GroupsFolder:
+    return QObject::tr("Groups");
+  }
+  return "NoName";
+}
+
+
+QVariant PartSet_FolderNode::data(int theColumn, int theRole) const
+{
+  static QIcon aParamsIco(":pictures/params_folder.png");
+  static QIcon aConstrIco(":pictures/constr_folder.png");
+
+  if (theColumn == 1) {
+    switch (theRole) {
+    case Qt::DisplayRole:
+      return name() + QString(" (%1)").arg(childrenCount());
+    case Qt::DecorationRole:
+      switch (myType) {
+      case ParametersFolder:
+        return aParamsIco;
+      case ConstructionFolder:
+        return aConstrIco;
+      case PartsFolder:
+        return aConstrIco;
+      case ResultsFolder:
+        return aConstrIco;
+      case FieldsFolder:
+        return aConstrIco;
+      case GroupsFolder:
+        return aConstrIco;
+      }
+    }
+  }
+  return PartSet_TreeNode::data(theColumn, theRole);
+}
+
+Qt::ItemFlags PartSet_FolderNode::flags(int theColumn) const
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aActiveDoc = aSession->activeDocument();
+  if (theColumn == 1) {
+    if (document() == aActiveDoc)
+      return aEditingFlag;
+  }
+  return aDefaultFlag;
+}
+
+void PartSet_FolderNode::update()
+{
+  DocumentPtr aDoc = document();
+  if (!aDoc.get())
+    return;
+
+  // Remove extra sub-nodes
+  QTreeNodesList aDelList;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if (aDoc->index(aNode->object()) == -1)
+      aDelList.append(aNode);
+  }
+  foreach(ModuleBase_ITreeNode* aNode, aDelList) {
+    myChildren.removeAll(aNode);
+    delete aNode;
+  }
+
+  // Add new nodes
+  std::string aGroup = groupName();
+  int aSize = aDoc->size(aGroup);
+  for (int i = 0; i < aSize; i++) {
+    ObjectPtr aObj = aDoc->object(aGroup, i);
+    if (i < myChildren.size()) {
+      if (myChildren.at(i)->object() != aObj) {
+        PartSet_ObjectNode* aNode = new PartSet_ObjectNode(aObj, this);
+        myChildren.insert(i, aNode);
+      }
+    } else {
+      PartSet_ObjectNode* aNode = new PartSet_ObjectNode(aObj, this);
+      myChildren.append(aNode);
+    }
+  }
+}
+
+std::string PartSet_FolderNode::groupName() const
+{
+  switch (myType) {
+  case ParametersFolder:
+    return ModelAPI_ResultParameter::group();
+  case ConstructionFolder:
+    return ModelAPI_ResultConstruction::group();
+  case PartsFolder:
+    return ModelAPI_ResultPart::group();
+  case ResultsFolder:
+    return ModelAPI_ResultBody::group();
+  case FieldsFolder:
+    return ModelAPI_ResultField::group();
+  case GroupsFolder:
+    return ModelAPI_ResultGroup::group();
+  }
+  return "";
+}
+
+QTreeNodesList PartSet_FolderNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult;
+  std::string aName = groupName();
+  DocumentPtr aDoc = document();
+  int aIdx = -1;
+  foreach(ObjectPtr aObj, theObjects) {
+    if ((aObj->document() == aDoc) && (aObj->groupName() == aName)) {
+      aIdx = aDoc->index(aObj);
+      if (aIdx != -1) {
+        bool aHasObject = (aIdx < myChildren.size()) && (myChildren.at(aIdx)->object() == aObj);
+        if (!aHasObject) {
+          PartSet_ObjectNode* aNode = new PartSet_ObjectNode(aObj, this);
+          aResult.append(aNode);
+          if (aIdx < myChildren.size())
+            myChildren.insert(aIdx, aNode);
+          else
+            myChildren.append(aNode);
+        }
+      }
+    }
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_FolderNode::objectsDeleted(const DocumentPtr& theDoc,
+  const QString& theGroup)
+{
+  DocumentPtr aDoc = document();
+  QTreeNodesList aResult;
+  if ((theGroup.toStdString() == groupName()) && (theDoc == aDoc)) {
+    QTreeNodesList aDelList;
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      if (aDoc->index(aNode->object()) == -1)
+        aDelList.append(aNode);
+    }
+    if (aDelList.size() > 0) {
+      foreach(ModuleBase_ITreeNode* aNode, aDelList) {
+        myChildren.removeAll(aNode);
+        delete aNode;
+      }
+      aResult.append(this);
+    }
+  }
+  return aResult;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+QTreeNodesList PartSet_FeatureFolderNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult;
+  // Process all folders
+  ModuleBase_ITreeNode* aFoder = 0;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    aFoder = dynamic_cast<PartSet_FolderNode*>(aNode);
+    if (!aFoder)
+      aFoder = dynamic_cast<PartSet_FeatureFolderNode*>(aNode);
+
+    if (aFoder) { // aFolder node
+      QTreeNodesList aList = aNode->objectCreated(theObjects);
+      if (aList.size() > 0)
+        aResult.append(aList);
+    }
+  }
+  // Process the root sub-objects
+  DocumentPtr aDoc = document();
+  int aIdx = -1;
+  int aNb = numberOfFolders();
+  foreach(ObjectPtr aObj, theObjects) {
+    if (aDoc == aObj->document()) {
+      if (aObj->groupName() == ModelAPI_Feature::group()) {
+        ModuleBase_ITreeNode* aNode = createNode(aObj);
+        aIdx = aDoc->index(aObj) + aNb;
+        bool aHasObject = (aIdx < myChildren.size()) && (myChildren.at(aIdx)->object() == aObj);
+        if (!aHasObject) {
+          if (aIdx < myChildren.size())
+            myChildren.insert(aIdx, aNode);
+          else
+            myChildren.append(aNode);
+          aResult.append(aNode);
+        }
+      }
+    }
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_FeatureFolderNode::objectsDeleted(const DocumentPtr& theDoc,
+  const QString& theGroup)
 {
+  QTreeNodesList aResult;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if (aNode->childrenCount() > 0) { // aFolder node
+      QTreeNodesList aList = aNode->objectsDeleted(theDoc, theGroup);
+      if (aList.size() > 0)
+        aResult.append(aList);
+    }
+  }
+  DocumentPtr aDoc = document();
+  if ((theDoc == aDoc) && (theGroup.toStdString() == ModelAPI_Feature::group())) {
+    QTreeNodesList aDelList;
+    foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+      if (aNode->object().get()) {
+        if (aDoc->index(aNode->object()) == -1)
+          aDelList.append(aNode);
+      }
+    }
+    if (aDelList.size() > 0) {
+      foreach(ModuleBase_ITreeNode* aNode, aDelList) {
+        myChildren.removeAll(aNode);
+        delete aNode;
+      }
+      aResult.append(this);
+    }
+  }
+  return aResult;
+}
 
-}
\ No newline at end of file
+ModuleBase_ITreeNode* PartSet_FeatureFolderNode::findParent(const DocumentPtr& theDoc,
+  QString theGroup)
+{
+  ModuleBase_ITreeNode* aResult = 0;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    aResult = aNode->findParent(theDoc, theGroup);
+    if (aResult) {
+      return aResult;
+    }
+  }
+  if ((theDoc == document()) && (theGroup.toStdString() == ModelAPI_Feature::group()))
+    return this;
+  return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+PartSet_RootNode::PartSet_RootNode() : PartSet_FeatureFolderNode(0), myWorkshop(0)
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aDoc = aSession->moduleDocument();
+
+  myParamsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ParametersFolder);
+  myConstrFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ConstructionFolder);
+  myPartsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::PartsFolder);
+
+  myChildren.append(myParamsFolder);
+  myChildren.append(myConstrFolder);
+  myChildren.append(myPartsFolder);
+
+  update();
+}
+
+PartSet_RootNode::~PartSet_RootNode()
+{
+  delete myParamsFolder;
+  delete myConstrFolder;
+  delete myPartsFolder;
+}
+
+
+void PartSet_RootNode::update()
+{
+  myParamsFolder->update();
+  myConstrFolder->update();
+  myPartsFolder->update();
+
+  // Update features content
+  DocumentPtr aDoc = document();
+
+  // Remove extra sub-nodes
+  QTreeNodesList aDelList;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    if (aNode->object().get()) {
+      if (aDoc->index(aNode->object()) == -1)
+        aDelList.append(aNode);
+    }
+  }
+  foreach(ModuleBase_ITreeNode* aNode, aDelList) {
+    myChildren.removeAll(aNode);
+    delete aNode;
+  }
+
+  // Add new nodes
+  std::string aGroup = ModelAPI_Feature::group();
+  int aSize = aDoc->size(aGroup);
+  int aId;
+  FeaturePtr aFeature;
+  int aNb = numberOfFolders();
+  for (int i = 0; i < aSize; i++) {
+    ObjectPtr aObj = aDoc->object(aGroup, i);
+    aId = i + aNb; // Take into account existing folders
+    if (aId < myChildren.size()) {
+      if (myChildren.at(aId)->object() != aObj) {
+        aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+        ModuleBase_ITreeNode* aNode;
+        if (aFeature->getKind() == PartSetPlugin_Part::ID())
+          aNode = new PartSet_PartRootNode(aObj, this);
+        else
+          aNode = new PartSet_ObjectNode(aObj, this);
+        myChildren.insert(aId, aNode);
+      }
+    } else {
+      aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+      ModuleBase_ITreeNode* aNode;
+      if (aFeature->getKind() == PartSetPlugin_Part::ID())
+        aNode = new PartSet_PartRootNode(aObj, this);
+      else
+        aNode = new PartSet_ObjectNode(aObj, this);
+      myChildren.append(aNode);
+    }
+  }
+  // Update sub-folders
+  ModuleBase_ITreeNode* aSubFolder = 0;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    aSubFolder = dynamic_cast<PartSet_PartRootNode*>(aNode);
+    if (aSubFolder)
+      aSubFolder->update();
+  }
+}
+
+DocumentPtr PartSet_RootNode::document() const
+{
+  return ModelAPI_Session::get()->moduleDocument();
+}
+
+ModuleBase_ITreeNode* PartSet_RootNode::createNode(const ObjectPtr& theObj)
+{
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+  if (aFeature->getKind() == PartSetPlugin_Part::ID())
+    return new PartSet_PartRootNode(theObj, this);
+  else
+    return new PartSet_ObjectNode(theObj, this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+PartSet_PartRootNode::PartSet_PartRootNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent)
+  : PartSet_FeatureFolderNode(theParent), myObject(theObj)
+{
+  myParamsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ParametersFolder);
+  myConstrFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ConstructionFolder);
+  myResultsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::ResultsFolder);
+  myFieldsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::FieldsFolder);
+  myGroupsFolder = new PartSet_FolderNode(this, PartSet_FolderNode::GroupsFolder);
+
+  myChildren.append(myParamsFolder);
+  myChildren.append(myConstrFolder);
+  myChildren.append(myResultsFolder);
+
+  update();
+}
+
+PartSet_PartRootNode::~PartSet_PartRootNode()
+{
+  delete myParamsFolder;
+  delete myConstrFolder;
+  delete myResultsFolder;
+  delete myFieldsFolder;
+  delete myGroupsFolder;
+}
+
+
+void PartSet_PartRootNode::update()
+{
+  DocumentPtr aDoc = document();
+  if (!aDoc.get())
+    return;
+
+  myParamsFolder->update();
+  myConstrFolder->update();
+  myResultsFolder->update();
+  myFieldsFolder->update();
+  myGroupsFolder->update();
+
+  bool aHasFields = myFieldsFolder->childrenCount() > 0;
+  bool aHasGroups = myGroupsFolder->childrenCount() > 0;
+  if (aHasFields && (!myChildren.contains(myFieldsFolder))) {
+    myChildren.insert(3, myFieldsFolder);
+  }
+  if (aHasGroups && (!myChildren.contains(myGroupsFolder))) {
+    myChildren.insert(aHasFields ? 4 : 3, myGroupsFolder);
+  }
+
+  // Update features content
+  int aRows = numberOfFolders();
+
+  // Remove extra sub-nodes
+  QTreeNodesList aDelList;
+  int aIndex = -1;
+  int aId = -1;
+  foreach(ModuleBase_ITreeNode* aNode, myChildren) {
+    aId++;
+    if (aNode->object().get()) {
+      aIndex = aDoc->index(aNode->object());
+      if ((aIndex == -1) || (aId != (aIndex + aRows)))
+        aDelList.append(aNode);
+    }
+  }
+  foreach(ModuleBase_ITreeNode* aNode, aDelList) {
+    myChildren.removeAll(aNode);
+    delete aNode;
+  }
+
+  std::string aGroup = ModelAPI_Feature::group();
+  int aSize = aDoc->size(aGroup);
+  FeaturePtr aFeature;
+  for (int i = 0; i < aSize; i++) {
+    ObjectPtr aObj = aDoc->object(aGroup, i);
+    aId = i + aRows; // Take into account existing folders
+    if (aId < myChildren.size()) {
+      if (myChildren.at(aId)->object() != aObj) {
+        ModuleBase_ITreeNode* aNode = new PartSet_ObjectNode(aObj, this);
+        myChildren.insert(aId, aNode);
+      }
+    } else {
+      ModuleBase_ITreeNode* aNode = new PartSet_ObjectNode(aObj, this);
+      myChildren.append(aNode);
+    }
+  }
+}
+
+DocumentPtr PartSet_PartRootNode::document() const
+{
+  ResultPartPtr aPartRes = getPartResult(myObject);
+  if (aPartRes.get())
+    return aPartRes->partDoc();
+  return DocumentPtr();
+}
+
+QVariant PartSet_PartRootNode::data(int theColumn, int theRole) const
+{
+  switch (theColumn) {
+  case 1:
+    switch (theRole) {
+    case Qt::DisplayRole:
+      return QString(myObject->data()->name().c_str());
+    case Qt::DecorationRole:
+      return ModuleBase_IconFactory::get()->getIcon(myObject);
+    }
+  case 2:
+    if (theRole == Qt::DecorationRole)
+      if (isCurrentFeature(myObject))
+        return QIcon(":pictures/arrow.png");
+  }
+  return PartSet_TreeNode::data(theColumn, theRole);
+}
+
+Qt::ItemFlags PartSet_PartRootNode::flags(int theColumn) const
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aActiveDoc = aSession->activeDocument();
+  if ((aActiveDoc == document()) || (myObject->document() == aActiveDoc))
+    return aEditingFlag;
+  return aDefaultFlag;
+}
+
+ModuleBase_ITreeNode* PartSet_PartRootNode::createNode(const ObjectPtr& theObj)
+{
+  return new PartSet_ObjectNode(theObj, this);
+}
+
+int PartSet_PartRootNode::numberOfFolders() const
+{
+  int aNb = 3;
+  if (myFieldsFolder->childrenCount() > 0)
+    aNb++;
+  if (myGroupsFolder->childrenCount() > 0)
+    aNb++;
+  return aNb;
+}
+
+QTreeNodesList PartSet_PartRootNode::objectCreated(const QObjectPtrList& theObjects)
+{
+  QTreeNodesList aResult = PartSet_FeatureFolderNode::objectCreated(theObjects);
+  if (!myFieldsFolder->childrenCount()) {
+    QTreeNodesList aList = myFieldsFolder->objectCreated(theObjects);
+    if (aList.size()) {
+      myChildren.insert(3, myFieldsFolder);
+      aResult.append(myFieldsFolder);
+      aResult.append(aList);
+    }
+  }
+  if (!myGroupsFolder->childrenCount()) {
+    QTreeNodesList aList = myGroupsFolder->objectCreated(theObjects);
+    if (aList.size()) {
+      myChildren.insert(myFieldsFolder->childrenCount()? 4 : 3, myGroupsFolder);
+      aResult.append(myGroupsFolder);
+      aResult.append(aList);
+    }
+  }
+  return aResult;
+}
+
+QTreeNodesList PartSet_PartRootNode::objectsDeleted(const DocumentPtr& theDoc,
+  const QString& theGroup)
+{
+  QTreeNodesList aResult;
+  if (myFieldsFolder->childrenCount()) {
+    QTreeNodesList aList = myFieldsFolder->objectsDeleted(theDoc, theGroup);
+    if (aList.size()) {
+      aResult.append(aList);
+      if (!myFieldsFolder->childrenCount())
+        myChildren.removeAll(myFieldsFolder);
+    }
+  }
+  if (myGroupsFolder->childrenCount()) {
+    QTreeNodesList aList = myGroupsFolder->objectsDeleted(theDoc, theGroup);
+    if (aList.size()) {
+      aResult.append(aList);
+      if (!myGroupsFolder->childrenCount())
+        myChildren.removeAll(myGroupsFolder);
+    }
+  }
+  aResult.append(PartSet_FeatureFolderNode::objectsDeleted(theDoc, theGroup));
+  return aResult;
+}
index 6c165b1981581a93231dddc719b553b9b2f73dd5..f3a596ecdffc9bd97268f0394a2954a85210a2bc 100644 (file)
 
 #include <ModuleBase_ITreeNode.h>
 
-class PartSet_RootNode : public ModuleBase_ITreeNode
+
+/**
+* \ingroup Modules
+* Implementation of base node for the module data tree
+*/
+class PartSet_TreeNode : public ModuleBase_ITreeNode
+{
+public:
+  PartSet_TreeNode(ModuleBase_ITreeNode* theParent = 0) : ModuleBase_ITreeNode(theParent) {}
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+};
+
+/**
+* \ingroup Modules
+* Implementation of a node for object repesentation
+*/
+class PartSet_ObjectNode : public PartSet_TreeNode
+{
+public:
+  enum VisibilityState {
+    NoneState,
+    Visible,
+    SemiVisible,
+    Hidden
+  };
+
+  PartSet_ObjectNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent = 0)
+    : PartSet_TreeNode(theParent), myObject(theObj) {}
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+
+  /// Returns properties flag of the item
+  virtual Qt::ItemFlags flags(int theColumn) const;
+
+  /// Returns object referenced by the node (can be null)
+  virtual ObjectPtr object() const { return myObject; }
+
+  /// Updates sub-nodes of the node
+  virtual void update() {}
+
+  VisibilityState getVisibilityState() const;
+
+private:
+  ObjectPtr myObject;
+};
+
+/**
+* \ingroup Modules
+* Implementation of aFolder node in data tree
+*/
+class PartSet_FolderNode : public PartSet_TreeNode
+{
+public:
+  enum FolderType {
+    ParametersFolder,
+    ConstructionFolder,
+    PartsFolder,
+    ResultsFolder,
+    FieldsFolder,
+    GroupsFolder
+  };
+
+  PartSet_FolderNode(ModuleBase_ITreeNode* theParent, FolderType theType);
+
+  virtual ~PartSet_FolderNode();
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+
+  /// Returns properties flag of the item
+  virtual Qt::ItemFlags flags(int theColumn) const;
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+  QString name() const;
+
+  /// Returns a node which belongs to the given document and contains objects of the given group
+  /// \param theDoc a document
+  /// \param theGroup a name of objects group
+  /// \return a parent node if it is found
+  virtual ModuleBase_ITreeNode* findParent(const DocumentPtr& theDoc, QString theGroup)
+  {
+    if ((theDoc == document()) && (theGroup.toStdString() == groupName()))
+      return this;
+    return 0;
+  }
+
+private:
+  std::string groupName() const;
+
+  FolderType myType;
+};
+
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* A base class for root folders
+*/
+class PartSet_FeatureFolderNode : public PartSet_TreeNode
+{
+public:
+  PartSet_FeatureFolderNode(ModuleBase_ITreeNode* theParent = 0) : PartSet_TreeNode(theParent) {}
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+  /// Returns a node which belongs to the given document and contains objects of the given group
+  /// \param theDoc a document
+  /// \param theGroup a name of objects group
+  /// \return a parent node if it is found
+  virtual ModuleBase_ITreeNode* findParent(const DocumentPtr& theDoc, QString theGroup);
+
+protected:
+  virtual ModuleBase_ITreeNode* createNode(const ObjectPtr& theObj) = 0;
+
+  virtual int numberOfFolders() const { return 0; }
+};
+
+
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* Implementation of Root node in data tree
+*/
+class PartSet_RootNode : public PartSet_FeatureFolderNode
 {
 public:
   PartSet_RootNode();
+  virtual ~PartSet_RootNode();
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  virtual ModuleBase_IWorkshop* workshop() const { return myWorkshop; }
+
+  /// Returns document object of the sub-tree.
+  virtual DocumentPtr document() const;
+
+  void setWorkshop(ModuleBase_IWorkshop* theWork) { myWorkshop = theWork; }
+
+protected:
+  virtual ModuleBase_ITreeNode* createNode(const ObjectPtr& theObj);
+
+  virtual int numberOfFolders() const { return 3; }
 
+private:
+  PartSet_FolderNode* myParamsFolder;
+  PartSet_FolderNode* myConstrFolder;
+  PartSet_FolderNode* myPartsFolder;
+
+  ModuleBase_IWorkshop* myWorkshop;
 };
 
+/////////////////////////////////////////////////////////////////////
+/**
+* \ingroup Modules
+* Implementation of Root node of a Part document in data tree
+*/
+class PartSet_PartRootNode : public PartSet_FeatureFolderNode
+{
+public:
+  PartSet_PartRootNode(const ObjectPtr& theObj, ModuleBase_ITreeNode* theParent);
+
+  virtual ~PartSet_PartRootNode();
+
+  /// Returns object referenced by the node (can be null)
+  virtual ObjectPtr object() const { return myObject; }
+
+  /// Returns document object of the sub-tree.
+  virtual DocumentPtr document() const;
+
+  /// Updates sub-nodes of the node
+  virtual void update();
+
+  /// Returns the node representation according to theRole.
+  virtual QVariant data(int theColumn, int theRole) const;
+
+  /// Returns properties flag of the item
+  virtual Qt::ItemFlags flags(int theColumn) const;
+
+  /// Process creation of objects.
+  /// \param theObjects a list of created objects
+  /// \return a list of nodes which corresponds to the created objects
+  virtual QTreeNodesList objectCreated(const QObjectPtrList& theObjects);
+
+  /// Process deletion of objects.
+  /// \param theDoc a document where objects were deleted
+  /// \param theGroup a name of group where objects were deleted
+  virtual QTreeNodesList objectsDeleted(const DocumentPtr& theDoc, const QString& theGroup);
+
+protected:
+  virtual ModuleBase_ITreeNode* createNode(const ObjectPtr& theObj);
+
+  virtual int numberOfFolders() const;
+
+private:
+  PartSet_FolderNode* myParamsFolder;
+  PartSet_FolderNode* myConstrFolder;
+  PartSet_FolderNode* myResultsFolder;
+  PartSet_FolderNode* myFieldsFolder;
+  PartSet_FolderNode* myGroupsFolder;
+
+  ObjectPtr myObject;
+};
 
 #endif
\ No newline at end of file
index 051402c908ebb3bff6077ce63741c944129af17c..d8fd37391df02b057a66b51bab9d42229f61cf10 100644 (file)
 //
 
 #include "XGUI_DataModel.h"
-#include "XGUI_Workshop.h"
+//#include "XGUI_Workshop.h"
 #include "XGUI_ObjectsBrowser.h"
-#include "XGUI_Displayer.h"
+//#include "XGUI_Displayer.h"
 
 #include <ModuleBase_IconFactory.h>
+#include <ModuleBase_ITreeNode.h>
 
 #include <ModelAPI_Session.h>
-#include <ModelAPI_Events.h>
-#include <ModelAPI_ResultParameter.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_ResultPart.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_CompositeFeature.h>
-#include <ModelAPI_ResultCompSolid.h>
-#include <ModelAPI_ResultField.h>
-#include <ModelAPI_Tools.h>
-#include <ModelAPI_Folder.h>
-#include <ModelAPI_AttributeReference.h>
+//#include <ModelAPI_Events.h>
+//#include <ModelAPI_ResultParameter.h>
+//#include <ModelAPI_AttributeDouble.h>
+//#include <ModelAPI_ResultPart.h>
+//#include <ModelAPI_Feature.h>
+//#include <ModelAPI_CompositeFeature.h>
+//#include <ModelAPI_ResultCompSolid.h>
+//#include <ModelAPI_ResultField.h>
+//#include <ModelAPI_Tools.h>
+//#include <ModelAPI_Folder.h>
+//#include <ModelAPI_AttributeReference.h>
 
 #include <Config_FeatureMessage.h>
-#include <Config_DataModelReader.h>
+//#include <Config_DataModelReader.h>
 
 #include <Events_Loop.h>
 
-#include <QIcon>
-#include <QBrush>
+//#include <QIcon>
+//#include <QBrush>
 
-#define ACTIVE_COLOR QColor(Qt::black)
+#include <cassert>
+
+//#define ACTIVE_COLOR QColor(Qt::black)
 //#define ACTIVE_COLOR QColor(0,72,140)
 //#define PASSIVE_COLOR Qt::black
 
 /// Returns ResultPart object if the given object is a Part feature
 /// Otherwise returns NULL
 
-#define SELECTABLE_COLOR QColor(110, 110, 110)
-#define DISABLED_COLOR QColor(200, 200, 200)
+//#define SELECTABLE_COLOR QColor(110, 110, 110)
+//#define DISABLED_COLOR QColor(200, 200, 200)
 
 
-ResultPartPtr getPartResult(ModelAPI_Object* theObj)
-{
-  ModelAPI_Feature* aFeature = dynamic_cast<ModelAPI_Feature*>(theObj);
-  if (aFeature) {
-    ResultPtr aRes = aFeature->firstResult();
-    if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
-      ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
-      // Use only original parts, not a placement results
-      if (aPartRes == aPartRes->original())
-      return aPartRes;
-    }
-  }
-  return ResultPartPtr();
-}
-
+//ResultPartPtr getPartResult(ModelAPI_Object* theObj)
+//{
+//  ModelAPI_Feature* aFeature = dynamic_cast<ModelAPI_Feature*>(theObj);
+//  if (aFeature) {
+//    ResultPtr aRes = aFeature->firstResult();
+//    if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
+//      ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
+//      // Use only original parts, not a placement results
+//      if (aPartRes == aPartRes->original())
+//      return aPartRes;
+//    }
+//  }
+//  return ResultPartPtr();
+//}
+//
 /// Returns pointer on document if the given object is document object
-ModelAPI_Document* getSubDocument(void* theObj)
-{
-  ModelAPI_Document* aDoc = 0;
-  try {
-    aDoc = dynamic_cast<ModelAPI_Document*>((ModelAPI_Entity*)theObj);
-  } catch(...) {}
-  return aDoc;
-}
+//ModelAPI_Document* getSubDocument(void* theObj)
+//{
+//  ModelAPI_Document* aDoc = 0;
+//  try {
+//    aDoc = dynamic_cast<ModelAPI_Document*>((ModelAPI_Entity*)theObj);
+//  } catch(...) {}
+//  return aDoc;
+//}
 
 
 
@@ -108,258 +111,309 @@ XGUI_DataModel::~XGUI_DataModel()
 //******************************************************
 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
 {
-  //if (myIsEventsProcessingBlocked)
-  //  return;
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-  std::string aRootType = myXMLReader->rootType();
-  std::string aSubType = myXMLReader->subType();
-  int aNbFolders = foldersCount();
-
-  // Created object event *******************
   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
-
-    std::set<ObjectPtr>::const_iterator aIt;
-    std::string aObjType;
-    for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
-      ObjectPtr aObject = (*aIt);
-      // We do not show objects which does not need to be shown in object browser
-      if (!aObject->isInHistory())
-        continue;
-
-      aObjType = aObject->groupName();
-      DocumentPtr aDoc = aObject->document();
-      if (aDoc == aRootDoc) {
-        // Check that new folders could appear
-        QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
-        foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-          if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) > 0)) {
-            // Appears first object in folder which can not be shown empty
-            if (!hasShownFolder(aRootDoc, aNotEmptyFolder)) {
-              insertRow(myXMLReader->rootFolderId(aObjType));
-              addShownFolder(aRootDoc, aNotEmptyFolder);
-            }
-          }
-        }
-        // Insert new object
-        int aRow = aRootDoc->size(aObjType) - 1;
-        if (aRow != -1) {
-          if ((aObjType == aRootType) || (aObjType == ModelAPI_Folder::group())) {
-            insertRow(aRow + aNbFolders + 1);
-          } else {
-            int aFolderId = myXMLReader->rootFolderId(aObjType);
-            if (aFolderId != -1) {
-              insertRow(aRow, createIndex(aFolderId, 0, (void*)Q_NULLPTR));
-            }
-          }
-        }
-      } else {
-        // Object created in sub-document
-        QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
-        if (aDocRoot.isValid()) {
-          // Check that new folders could appear
-          QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
-          foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-            if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) > 0)) {
-              // Appears first object in folder which can not be shown empty
-              if (!hasShownFolder(aDoc, aNotEmptyFolder)) {
-                insertRow(myXMLReader->subFolderId(aObjType), aDocRoot);
-                addShownFolder(aDoc, aNotEmptyFolder);
-              }
-            }
-         }
-          int aRow = aDoc->index(aObject, true);
-          if (aRow != -1) {
-            int aNbSubFolders = foldersCount(aDoc.get());
-            if ((aObjType == aSubType) || (aObjType == ModelAPI_Folder::group())) {
-              // List of objects under document root
-              insertRow(aRow + aNbSubFolders, aDocRoot);
-            } else {
-              // List of objects under a folder
-              if (aRow != -1) {
-                int aFolderId = folderId(aObjType, aDoc.get());
-                if (aFolderId != -1) {
-                  QModelIndex aParentFolder = createIndex(aFolderId, 0, aDoc.get());
-                  insertRow(aRow, aParentFolder);
-                  emit dataChanged(aParentFolder, aParentFolder);
-                }
-              }
-            }
-          } else {
-            rebuildDataTree();
-            break;
-          }
-        } else {
-          rebuildDataTree();
-          break;
-        }
-      }
-    }
-    // Deleted object event ***********************
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
-    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-    DocumentPtr aDoc = aUpdMsg->document();
-    std::set<std::string> aMsgGroups = aUpdMsg->groups();
-
-    /// Sort groups because RootType deletion has to be done after others
-    std::string aType = (aDoc == aRootDoc)? aRootType : aSubType;
-    std::list<std::string> aGroups;
-    std::set<std::string>::const_iterator aSetIt;
-    for (aSetIt = aMsgGroups.begin(); aSetIt != aMsgGroups.end(); ++aSetIt) {
-      std::string aGroup = (*aSetIt);
-      if (aGroup == aType)
-        aGroups.push_back(aGroup);
-      else
-        aGroups.push_front(aGroup);
-    }
-
-    std::list<std::string>::const_iterator aIt;
-    for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
-      std::string aGroup = (*aIt);
-      if (aDoc == aRootDoc) {  // If root objects
-        int aRow = aRootDoc->size(aGroup, true);
-        if (aGroup == aRootType) {
-          // Process root folder
-          // remove optimization due to the issue #2456
-          //removeRow(aRow + aNbFolders);
-          //rebuildBranch(aNbFolders, aRow);
-          rebuildDataTree();
-        } else if (aGroup == ModelAPI_Folder::group()) {
-          rebuildDataTree();
-        } else {
-          // Process root sub-folder
-          int aFolderId = myXMLReader->rootFolderId(aGroup);
-          if (aFolderId != -1) {
-            QModelIndex aFolderIndex = createIndex(aFolderId, 0, (void*)Q_NULLPTR);
-            removeRow(aRow, aFolderIndex);
-            //rebuildBranch(0, aRow);
-          }
-        }
-        // Check that some folders could erased
-        QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
-        foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-          if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup, true) == 0)) {
-            // Appears first object in folder which can not be shown empty
-            removeRow(myXMLReader->rootFolderId(aGroup));
-            removeShownFolder(aRootDoc, aNotEmptyFolder);
-            //rebuildBranch(0, aNbFolders + aDoc->size(myXMLReader->rootType()));
-            break;
-          }
-        }
-      } else {
-        // Remove row for sub-document
-        QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
-        if (aDocRoot.isValid()) {
-          int aRow = aDoc->size(aGroup, true);
-          int aNbSubFolders = foldersCount(aDoc.get());
-          if (aGroup == aSubType) {
-            // List of objects under document root
-            removeRow(aRow + aNbSubFolders, aDocRoot);
-            rebuildBranch(aNbSubFolders, aRow, aDocRoot);
-          } if (aGroup == ModelAPI_Folder::group()) {
-            rebuildDataTree();
-          } else {
-            // List of objects under a folder
-            int aFolderId = folderId(aGroup, aDoc.get());
-            if (aFolderId != -1) {
-              QModelIndex aFolderRoot = createIndex(aFolderId, 0, aDoc.get());
-              removeRow(aRow, aFolderRoot);
-              //rebuildBranch(0, aRow, aFolderRoot);
-            }
-          }
-          // Check that some folders could disappear
-          QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
-          int aSize = aDoc->size(aGroup, true);
-          foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
-            if ((aNotEmptyFolder.toStdString() == aGroup) && (aSize == 0)) {
-              // Appears first object in folder which can not be shown empty
-              removeRow(myXMLReader->subFolderId(aGroup), aDocRoot);
-              removeShownFolder(aDoc, aNotEmptyFolder);
-              //rebuildBranch(0, aNbSubFolders + aDoc->size(myXMLReader->subType()), aDocRoot);
-              break;
-            }
-          }
-        } else {
-          rebuildDataTree();
-          break;
-        }
-      }
-    }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    std::set<ObjectPtr> aObjects = aUpdMsg->objects();
-
+    QObjectPtrList aCreated;
     std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
-      ObjectPtr aObject = (*aIt);
-      if (aObject->data()->isValid()) {
-        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
-        if (aFeature.get() && aFeature->firstResult().get()
-          && (aFeature->firstResult()->groupName() == ModelAPI_ResultField::group())) {
-            ResultFieldPtr aResult =
-              std::dynamic_pointer_cast<ModelAPI_ResultField>(aFeature->firstResult());
-            QModelIndex aIndex = objectIndex(aResult, 0);
-            removeRows(0, aResult->stepsSize(), aIndex);
-        } else {
-          if (aObject->groupName() == ModelAPI_Folder::group()) {
-            rebuildDataTree();
-          } else {
-            QModelIndex aIndex = objectIndex(aObject, 0);
-            if (aIndex.isValid()) {
-              emit dataChanged(aIndex, aIndex);
-            }
-          }
-        }
-      } else {
-        rebuildDataTree();
-        break;
-      }
+    for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++)
+      aCreated.append(*aIt);
+    QTreeNodesList aNodes = myRoot->objectCreated(aCreated);
+    ModuleBase_ITreeNode* aParent;
+    int aRow = 0;
+    QModelIndex aParentIndex;
+    foreach(ModuleBase_ITreeNode* aNode, aNodes) {
+      aParent = aNode->parent();
+      aRow = aParent->nodeRow(aNode);
+      aParentIndex = getParentIndex(aNode, 0);
+      insertRows(aRow, 1, aParentIndex);
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
+  }
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
+      std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
+          std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+      DocumentPtr aDoc = aUpdMsg->document();
+      std::set<std::string> aMsgGroups = aUpdMsg->groups();
+      std::set<std::string>::const_iterator aIt;
+      for (aIt = aMsgGroups.cbegin(); aIt != aMsgGroups.cend(); aIt++)
+        QTreeNodesList aList = myRoot->objectsDeleted(aDoc, (*aIt).c_str());
+      rebuildDataTree();
+  }
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
     std::shared_ptr<ModelAPI_OrderUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
+      std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
     if (aUpdMsg->reordered().get()) {
       DocumentPtr aDoc = aUpdMsg->reordered()->document();
       std::string aGroup = aUpdMsg->reordered()->group();
-
-      QModelIndex aParent;
-      int aStartId = 0;
-      if (aDoc == aRootDoc) {
-        // Update a group under root
-        if (aGroup == myXMLReader->rootType()) // Update objects under root
-          aStartId = foldersCount();
-        else // Update objects in folder under root
-          aParent = createIndex(folderId(aGroup), 0, (void*)Q_NULLPTR);
-      } else {
-        // Update a sub-document
-        if (aGroup == myXMLReader->subType()) {
-          // Update sub-document root
-          aParent = findDocumentRootIndex(aDoc.get(), 0);
-          aStartId = foldersCount(aDoc.get());
-        } else
-          // update folder in sub-document
-          aParent = createIndex(folderId(aGroup, aDoc.get()), 0, aDoc.get());
+      ModuleBase_ITreeNode* aNode = myRoot->findParent(aDoc, aGroup.c_str());
+      if (aNode) {
+        aNode->update();
+        int aRows = aNode->childrenCount();
+        if (aRows) {
+          QModelIndex aParent = getIndex(aNode, 0);
+          QModelIndex aFirstIdx = aParent.child(0, 0);
+          QModelIndex aLastIdx = aParent.child(aRows - 1, 2);
+          dataChanged(aFirstIdx, aLastIdx);
+        }
       }
-      int aChildNb = rowCount(aParent);
-      rebuildBranch(aStartId, aChildNb - aStartId, aParent);
-    } else {
-      rebuildDataTree();
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
+  }
+  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
     DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
-    if (aDoc != aRootDoc) {
-      QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
-      if (aDocRoot.isValid())
-        emit dataChanged(aDocRoot, aDocRoot);
-      else
-        // We have got a new document
-        rebuildDataTree();
-    }
   }
+  //if (myIsEventsProcessingBlocked)
+  //  return;
+  //DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  //std::string aRootType = myXMLReader->rootType();
+  //std::string aSubType = myXMLReader->subType();
+  //int aNbFolders = foldersCount();
+
+  //// Created object event *******************
+  //if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
+  //  std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+  //      std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+  //  std::set<ObjectPtr> aObjects = aUpdMsg->objects();
+
+  //  std::set<ObjectPtr>::const_iterator aIt;
+  //  std::string aObjType;
+  //  for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
+  //    ObjectPtr aObject = (*aIt);
+  //    // We do not show objects which does not need to be shown in object browser
+  //    if (!aObject->isInHistory())
+  //      continue;
+
+  //    aObjType = aObject->groupName();
+  //    DocumentPtr aDoc = aObject->document();
+  //    if (aDoc == aRootDoc) {
+  //      // Check that new folders could appear
+  //      QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
+  //      foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
+  //        if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) > 0)) {
+  //          // Appears first object in folder which can not be shown empty
+  //          if (!hasShownFolder(aRootDoc, aNotEmptyFolder)) {
+  //            insertRow(myXMLReader->rootFolderId(aObjType));
+  //            addShownFolder(aRootDoc, aNotEmptyFolder);
+  //          }
+  //        }
+  //      }
+  //      // Insert new object
+  //      int aRow = aRootDoc->size(aObjType) - 1;
+  //      if (aRow != -1) {
+  //        if ((aObjType == aRootType) || (aObjType == ModelAPI_Folder::group())) {
+  //          insertRow(aRow + aNbFolders + 1);
+  //        } else {
+  //          int aFolderId = myXMLReader->rootFolderId(aObjType);
+  //          if (aFolderId != -1) {
+  //            insertRow(aRow, createIndex(aFolderId, 0, (void*)Q_NULLPTR));
+  //          }
+  //        }
+  //      }
+  //    } else {
+  //      // Object created in sub-document
+  //      QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
+  //      if (aDocRoot.isValid()) {
+  //        // Check that new folders could appear
+  //        QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
+  //        foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
+  //          if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) > 0)) {
+  //            // Appears first object in folder which can not be shown empty
+  //            if (!hasShownFolder(aDoc, aNotEmptyFolder)) {
+  //              insertRow(myXMLReader->subFolderId(aObjType), aDocRoot);
+  //              addShownFolder(aDoc, aNotEmptyFolder);
+  //            }
+  //          }
+  //       }
+  //        int aRow = aDoc->index(aObject, true);
+  //        if (aRow != -1) {
+  //          int aNbSubFolders = foldersCount(aDoc.get());
+  //          if ((aObjType == aSubType) || (aObjType == ModelAPI_Folder::group())) {
+  //            // List of objects under document root
+  //            insertRow(aRow + aNbSubFolders, aDocRoot);
+  //          } else {
+  //            // List of objects under a folder
+  //            if (aRow != -1) {
+  //              int aFolderId = folderId(aObjType, aDoc.get());
+  //              if (aFolderId != -1) {
+  //                QModelIndex aParentFolder = createIndex(aFolderId, 0, aDoc.get());
+  //                insertRow(aRow, aParentFolder);
+  //                emit dataChanged(aParentFolder, aParentFolder);
+  //              }
+  //            }
+  //          }
+  //        } else {
+  //          rebuildDataTree();
+  //          break;
+  //        }
+  //      } else {
+  //        rebuildDataTree();
+  //        break;
+  //      }
+  //    }
+  //  }
+  //  // Deleted object event ***********************
+  //} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
+  //  std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
+  //      std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+  //  DocumentPtr aDoc = aUpdMsg->document();
+  //  std::set<std::string> aMsgGroups = aUpdMsg->groups();
+
+  //  /// Sort groups because RootType deletion has to be done after others
+  //  std::string aType = (aDoc == aRootDoc)? aRootType : aSubType;
+  //  std::list<std::string> aGroups;
+  //  std::set<std::string>::const_iterator aSetIt;
+  //  for (aSetIt = aMsgGroups.begin(); aSetIt != aMsgGroups.end(); ++aSetIt) {
+  //    std::string aGroup = (*aSetIt);
+  //    if (aGroup == aType)
+  //      aGroups.push_back(aGroup);
+  //    else
+  //      aGroups.push_front(aGroup);
+  //  }
+
+  //  std::list<std::string>::const_iterator aIt;
+  //  for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
+  //    std::string aGroup = (*aIt);
+  //    if (aDoc == aRootDoc) {  // If root objects
+  //      int aRow = aRootDoc->size(aGroup, true);
+  //      if (aGroup == aRootType) {
+  //        // Process root folder
+  //        // remove optimization due to the issue #2456
+  //        //removeRow(aRow + aNbFolders);
+  //        //rebuildBranch(aNbFolders, aRow);
+  //        rebuildDataTree();
+  //      } else if (aGroup == ModelAPI_Folder::group()) {
+  //        rebuildDataTree();
+  //      } else {
+  //        // Process root sub-folder
+  //        int aFolderId = myXMLReader->rootFolderId(aGroup);
+  //        if (aFolderId != -1) {
+  //          QModelIndex aFolderIndex = createIndex(aFolderId, 0, (void*)Q_NULLPTR);
+  //          removeRow(aRow, aFolderIndex);
+  //          //rebuildBranch(0, aRow);
+  //        }
+  //      }
+  //      // Check that some folders could erased
+  //      QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
+  //      foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
+  //        if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup, true) == 0)) {
+  //          // Appears first object in folder which can not be shown empty
+  //          removeRow(myXMLReader->rootFolderId(aGroup));
+  //          removeShownFolder(aRootDoc, aNotEmptyFolder);
+  //          //rebuildBranch(0, aNbFolders + aDoc->size(myXMLReader->rootType()));
+  //          break;
+  //        }
+  //      }
+  //    } else {
+  //      // Remove row for sub-document
+  //      QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
+  //      if (aDocRoot.isValid()) {
+  //        int aRow = aDoc->size(aGroup, true);
+  //        int aNbSubFolders = foldersCount(aDoc.get());
+  //        if (aGroup == aSubType) {
+  //          // List of objects under document root
+  //          removeRow(aRow + aNbSubFolders, aDocRoot);
+  //          rebuildBranch(aNbSubFolders, aRow, aDocRoot);
+  //        } if (aGroup == ModelAPI_Folder::group()) {
+  //          rebuildDataTree();
+  //        } else {
+  //          // List of objects under a folder
+  //          int aFolderId = folderId(aGroup, aDoc.get());
+  //          if (aFolderId != -1) {
+  //            QModelIndex aFolderRoot = createIndex(aFolderId, 0, aDoc.get());
+  //            removeRow(aRow, aFolderRoot);
+  //            //rebuildBranch(0, aRow, aFolderRoot);
+  //          }
+  //        }
+  //        // Check that some folders could disappear
+  //        QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
+  //        int aSize = aDoc->size(aGroup, true);
+  //        foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
+  //          if ((aNotEmptyFolder.toStdString() == aGroup) && (aSize == 0)) {
+  //            // Appears first object in folder which can not be shown empty
+  //            removeRow(myXMLReader->subFolderId(aGroup), aDocRoot);
+  //            removeShownFolder(aDoc, aNotEmptyFolder);
+  //            //rebuildBranch(0, aNbSubFolders + aDoc->size(myXMLReader->subType()), aDocRoot);
+  //            break;
+  //          }
+  //        }
+  //      } else {
+  //        rebuildDataTree();
+  //        break;
+  //      }
+  //    }
+  //  }
+  //} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
+  //  std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+  //      std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+  //  std::set<ObjectPtr> aObjects = aUpdMsg->objects();
+
+  //  std::set<ObjectPtr>::const_iterator aIt;
+  //  for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
+  //    ObjectPtr aObject = (*aIt);
+  //    if (aObject->data()->isValid()) {
+  //      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+  //      if (aFeature.get() && aFeature->firstResult().get()
+  //        && (aFeature->firstResult()->groupName() == ModelAPI_ResultField::group())) {
+  //          ResultFieldPtr aResult =
+  //            std::dynamic_pointer_cast<ModelAPI_ResultField>(aFeature->firstResult());
+  //          QModelIndex aIndex = objectIndex(aResult, 0);
+  //          removeRows(0, aResult->stepsSize(), aIndex);
+  //      } else {
+  //        if (aObject->groupName() == ModelAPI_Folder::group()) {
+  //          rebuildDataTree();
+  //        } else {
+  //          QModelIndex aIndex = objectIndex(aObject, 0);
+  //          if (aIndex.isValid()) {
+  //            emit dataChanged(aIndex, aIndex);
+  //          }
+  //        }
+  //      }
+  //    } else {
+  //      rebuildDataTree();
+  //      break;
+  //    }
+  //  }
+  //} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) {
+  //  std::shared_ptr<ModelAPI_OrderUpdatedMessage> aUpdMsg =
+  //      std::dynamic_pointer_cast<ModelAPI_OrderUpdatedMessage>(theMessage);
+  //  if (aUpdMsg->reordered().get()) {
+  //    DocumentPtr aDoc = aUpdMsg->reordered()->document();
+  //    std::string aGroup = aUpdMsg->reordered()->group();
+
+  //    QModelIndex aParent;
+  //    int aStartId = 0;
+  //    if (aDoc == aRootDoc) {
+  //      // Update a group under root
+  //      if (aGroup == myXMLReader->rootType()) // Update objects under root
+  //        aStartId = foldersCount();
+  //      else // Update objects in folder under root
+  //        aParent = createIndex(folderId(aGroup), 0, (void*)Q_NULLPTR);
+  //    } else {
+  //      // Update a sub-document
+  //      if (aGroup == myXMLReader->subType()) {
+  //        // Update sub-document root
+  //        aParent = findDocumentRootIndex(aDoc.get(), 0);
+  //        aStartId = foldersCount(aDoc.get());
+  //      } else
+  //        // update folder in sub-document
+  //        aParent = createIndex(folderId(aGroup, aDoc.get()), 0, aDoc.get());
+  //    }
+  //    int aChildNb = rowCount(aParent);
+  //    rebuildBranch(aStartId, aChildNb - aStartId, aParent);
+  //  } else {
+  //    rebuildDataTree();
+  //  }
+  //} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
+  //  DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
+  //  if (aDoc != aRootDoc) {
+  //    QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
+  //    if (aDocRoot.isValid())
+  //      emit dataChanged(aDocRoot, aDocRoot);
+  //    else
+  //      // We have got a new document
+  //      rebuildDataTree();
+  //  }
+  //}
 }
 
 //******************************************************
@@ -380,194 +434,213 @@ void XGUI_DataModel::rebuildDataTree()
 //******************************************************
 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
 {
-  if (theIndex.internalId() == 0) // this is a folder
-    return ObjectPtr();
-  ModelAPI_Object* aObj = 0;
-  try {
-    aObj = dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
-  } catch(...) {}
-
-  if (!aObj)
-    return ObjectPtr();
-  if (getSubDocument(aObj)) // the selected index is a folder of sub-document
-    return ObjectPtr();
-
-  return aObj->data()->owner();
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return aNode->object();
+  }
+  return ObjectPtr();
+
+  //if (theIndex.internalId() == 0) // this is a folder
+  //  return ObjectPtr();
+  //ModelAPI_Object* aObj = 0;
+  //try {
+  //  aObj = dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
+  //} catch(...) {}
+
+  //if (!aObj)
+  //  return ObjectPtr();
+  //if (getSubDocument(aObj)) // the selected index is a folder of sub-document
+  //  return ObjectPtr();
+
+  //return aObj->data()->owner();
 }
 
 //******************************************************
 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
 {
-  std::string aType = theObject->groupName();
-  DocumentPtr aDoc = theObject->document();
-  int aRow = aDoc->index(theObject, true);
-  if (aRow == -1) {
-    // it could be a part of complex object
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
-    if (aFeature.get()) {
-      CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
-      if (aCompFea.get()) {
-        for (int i = 0; i < aCompFea->numberOfSubs(true); i++) {
-          if (aCompFea->subFeature(i, true) == theObject) {
-            aRow = i;
-            break;
-          }
-        }
-      }
-      int aFRow = -1;
-      FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aFRow);
-      if (aFolder.get())
-        aRow = aFRow;
-    } else {
-      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-      if (aResult.get()) {
-        ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
-        if (aCompRes.get()) {
-          aRow = ModelAPI_Tools::compSolidIndex(aResult);
-        }
-      }
-    }
-    if (aRow == -1)
-      return QModelIndex();
-    else
-      return createIndex(aRow, theColumn, theObject.get());
+  ModuleBase_ITreeNode* aNode = myRoot->subNode(theObject);
+  if (aNode) {
+    ModuleBase_ITreeNode* aParent = aNode->parent();
+    assert(aParent);
+    return getIndex(aNode, theColumn);
   }
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if (aDoc == aRootDoc &&
-    ((myXMLReader->rootType() == aType) || (aType == ModelAPI_Folder::group()))) {
-    // The object from root document
-    aRow += foldersCount();
-  } else if ((myXMLReader->subType() == aType) || (aType == ModelAPI_Folder::group())) {
-    // The object from sub document
-    aRow += foldersCount(aDoc.get());
-  }
-  return createIndex(aRow, theColumn, theObject.get());
+  return QModelIndex();
+  //std::string aType = theObject->groupName();
+  //DocumentPtr aDoc = theObject->document();
+  //int aRow = aDoc->index(theObject, true);
+  //if (aRow == -1) {
+  //  // it could be a part of complex object
+  //  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+  //  if (aFeature.get()) {
+  //    CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
+  //    if (aCompFea.get()) {
+  //      for (int i = 0; i < aCompFea->numberOfSubs(true); i++) {
+  //        if (aCompFea->subFeature(i, true) == theObject) {
+  //          aRow = i;
+  //          break;
+  //        }
+  //      }
+  //    }
+  //    int aFRow = -1;
+  //    FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aFRow);
+  //    if (aFolder.get())
+  //      aRow = aFRow;
+  //  } else {
+  //    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+  //    if (aResult.get()) {
+  //      ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
+  //      if (aCompRes.get()) {
+  //        aRow = ModelAPI_Tools::compSolidIndex(aResult);
+  //      }
+  //    }
+  //  }
+  //  if (aRow == -1)
+  //    return QModelIndex();
+  //  else
+  //    return createIndex(aRow, theColumn, theObject.get());
+  //}
+  //SessionPtr aSession = ModelAPI_Session::get();
+  //DocumentPtr aRootDoc = aSession->moduleDocument();
+  //if (aDoc == aRootDoc &&
+  //  ((myXMLReader->rootType() == aType) || (aType == ModelAPI_Folder::group()))) {
+  //  // The object from root document
+  //  aRow += foldersCount();
+  //} else if ((myXMLReader->subType() == aType) || (aType == ModelAPI_Folder::group())) {
+  //  // The object from sub document
+  //  aRow += foldersCount(aDoc.get());
+  //}
+  //return createIndex(aRow, theColumn, theObject.get());
 }
 
 //******************************************************
 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  int aNbFolders = foldersCount();
-  int theIndexRow = theIndex.row();
-
-  if (theRole == Qt::DecorationRole) {
-    if (theIndex == lastHistoryIndex())
-      return QIcon(":pictures/arrow.png");
-    else if (theIndex.column() == 0) {
-      VisibilityState aState = getVisibilityState(theIndex);
-      switch (aState) {
-      case NoneState:
-        return QIcon();
-      case Visible:
-        return QIcon(":pictures/eyeopen.png");
-      case SemiVisible:
-        return QIcon(":pictures/eyemiclosed.png");
-      case Hidden:
-        return QIcon(":pictures/eyeclosed.png");
-      }
-    }
-  }
-
-  //if (theIndex.column() == 1)
-  if (theIndex.column() != 1)
-    return QVariant();
-
-  quintptr aParentId = theIndex.internalId();
-  if (aParentId == 0) { // root folders
-    switch (theRole) {
-      case Qt::DisplayRole:
-        return QString(myXMLReader->rootFolderName(theIndexRow).c_str()) +
-          QString(" (%1)").arg(rowCount(theIndex));
-      case Qt::DecorationRole:
-        return QIcon(myXMLReader->rootFolderIcon(theIndexRow).c_str());
-      case Qt::ForegroundRole:
-        {
-          Qt::ItemFlags aFlags = theIndex.flags();
-          if (aFlags == Qt::ItemFlags())
-            return QBrush(DISABLED_COLOR);
-          if (!aFlags.testFlag(Qt::ItemIsEditable))
-            return QBrush(SELECTABLE_COLOR);
-        }
-        return ACTIVE_COLOR;
-    }
-  } else { // an object or sub-document
-    if (theRole == Qt::ForegroundRole) {
-      Qt::ItemFlags aFlags = theIndex.flags();
-      if (aFlags == Qt::ItemFlags())
-        return QBrush(DISABLED_COLOR);
-      if (!aFlags.testFlag(Qt::ItemIsEditable))
-        return QBrush(SELECTABLE_COLOR);
-      return ACTIVE_COLOR;
-    }
-
-    ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer());
-    if (aSubDoc) { // this is a folder of sub document
-      QIntList aMissedIdx = missedFolderIndexes(aSubDoc);
-      int aRow = theIndexRow;
-      while (aMissedIdx.contains(aRow))
-        aRow++;
-      if (aRow < myXMLReader->subFoldersNumber()) {
-        switch (theRole) {
-          case Qt::DisplayRole:
-            return QString(myXMLReader->subFolderName(aRow).c_str()) +
-              QString(" (%1)").arg(rowCount(theIndex));
-          case Qt::DecorationRole:
-            return QIcon(myXMLReader->subFolderIcon(aRow).c_str());
-        }
-      }
-    } else {
-      ObjectPtr aObj = object(theIndex);
-      if (aObj) {
-        switch (theRole) {
-        case Qt::DisplayRole:
-          {
-            if (aObj->groupName() == ModelAPI_ResultParameter::group()) {
-              ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObj);
-              AttributeDoublePtr aValueAttribute =
-                aParam->data()->real(ModelAPI_ResultParameter::VALUE());
-              QString aVal = QString::number(aValueAttribute->value());
-              QString aTitle = QString(aObj->data()->name().c_str());
-              return aTitle + " = " + aVal;
-            }
-            QString aSuffix;
-            if (aObj->groupName() == myXMLReader->subType()) {
-              ResultPartPtr aPartRes = getPartResult(aObj.get());
-              if (aPartRes.get()) {
-                if (aPartRes->partDoc().get() == NULL)
-                  aSuffix = " (Not loaded)";
-              }
-            }
-            return aObj->data()->name().c_str() + aSuffix;
-          }
-        case Qt::DecorationRole:
-          {
-            if (aObj->groupName() == ModelAPI_Folder::group())
-              return QIcon(":pictures/features_folder.png");
-            else
-              return ModuleBase_IconFactory::get()->getIcon(aObj);
-          }
-        }
-      } else {
-        switch (theRole) {
-        case Qt::DisplayRole:
-          {
-            ModelAPI_ResultField::ModelAPI_FieldStep* aStep =
-              dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
-              ((ModelAPI_Entity*)theIndex.internalPointer());
-            if (aStep) {
-              return "Step " + QString::number(aStep->id() + 1) + " " +
-                aStep->field()->textLine(aStep->id()).c_str();
-            }
-          }
-          break;
-        }
-      }
-    }
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return aNode->data(theIndex.column(), theRole);
   }
   return QVariant();
+
+  //SessionPtr aSession = ModelAPI_Session::get();
+  //DocumentPtr aRootDoc = aSession->moduleDocument();
+  //int aNbFolders = foldersCount();
+  //int theIndexRow = theIndex.row();
+
+  //if (theRole == Qt::DecorationRole) {
+  //  if (theIndex == lastHistoryIndex())
+  //    return QIcon(":pictures/arrow.png");
+  //  else if (theIndex.column() == 0) {
+  //    VisibilityState aState = getVisibilityState(theIndex);
+  //    switch (aState) {
+  //    case NoneState:
+  //      return QIcon();
+  //    case Visible:
+  //      return QIcon(":pictures/eyeopen.png");
+  //    case SemiVisible:
+  //      return QIcon(":pictures/eyemiclosed.png");
+  //    case Hidden:
+  //      return QIcon(":pictures/eyeclosed.png");
+  //    }
+  //  }
+  //}
+
+  ////if (theIndex.column() == 1)
+  //if (theIndex.column() != 1)
+  //  return QVariant();
+
+  //quintptr aParentId = theIndex.internalId();
+  //if (aParentId == 0) { // root folders
+  //  switch (theRole) {
+  //    case Qt::DisplayRole:
+  //      return QString(myXMLReader->rootFolderName(theIndexRow).c_str()) +
+  //        QString(" (%1)").arg(rowCount(theIndex));
+  //    case Qt::DecorationRole:
+  //      return QIcon(myXMLReader->rootFolderIcon(theIndexRow).c_str());
+  //    case Qt::ForegroundRole:
+  //      {
+  //        Qt::ItemFlags aFlags = theIndex.flags();
+  //        if (aFlags == Qt::ItemFlags())
+  //          return QBrush(DISABLED_COLOR);
+  //        if (!aFlags.testFlag(Qt::ItemIsEditable))
+  //          return QBrush(SELECTABLE_COLOR);
+  //      }
+  //      return ACTIVE_COLOR;
+  //  }
+  //} else { // an object or sub-document
+  //  if (theRole == Qt::ForegroundRole) {
+  //    Qt::ItemFlags aFlags = theIndex.flags();
+  //    if (aFlags == Qt::ItemFlags())
+  //      return QBrush(DISABLED_COLOR);
+  //    if (!aFlags.testFlag(Qt::ItemIsEditable))
+  //      return QBrush(SELECTABLE_COLOR);
+  //    return ACTIVE_COLOR;
+  //  }
+
+  //  ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer());
+  //  if (aSubDoc) { // this is a folder of sub document
+  //    QIntList aMissedIdx = missedFolderIndexes(aSubDoc);
+  //    int aRow = theIndexRow;
+  //    while (aMissedIdx.contains(aRow))
+  //      aRow++;
+  //    if (aRow < myXMLReader->subFoldersNumber()) {
+  //      switch (theRole) {
+  //        case Qt::DisplayRole:
+  //          return QString(myXMLReader->subFolderName(aRow).c_str()) +
+  //            QString(" (%1)").arg(rowCount(theIndex));
+  //        case Qt::DecorationRole:
+  //          return QIcon(myXMLReader->subFolderIcon(aRow).c_str());
+  //      }
+  //    }
+  //  } else {
+  //    ObjectPtr aObj = object(theIndex);
+  //    if (aObj) {
+  //      switch (theRole) {
+  //      case Qt::DisplayRole:
+  //        {
+  //          if (aObj->groupName() == ModelAPI_ResultParameter::group()) {
+  //            ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObj);
+  //            AttributeDoublePtr aValueAttribute =
+  //              aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+  //            QString aVal = QString::number(aValueAttribute->value());
+  //            QString aTitle = QString(aObj->data()->name().c_str());
+  //            return aTitle + " = " + aVal;
+  //          }
+  //          QString aSuffix;
+  //          if (aObj->groupName() == myXMLReader->subType()) {
+  //            ResultPartPtr aPartRes = getPartResult(aObj.get());
+  //            if (aPartRes.get()) {
+  //              if (aPartRes->partDoc().get() == NULL)
+  //                aSuffix = " (Not loaded)";
+  //            }
+  //          }
+  //          return aObj->data()->name().c_str() + aSuffix;
+  //        }
+  //      case Qt::DecorationRole:
+  //        {
+  //          if (aObj->groupName() == ModelAPI_Folder::group())
+  //            return QIcon(":pictures/features_folder.png");
+  //          else
+  //            return ModuleBase_IconFactory::get()->getIcon(aObj);
+  //        }
+  //      }
+  //    } else {
+  //      switch (theRole) {
+  //      case Qt::DisplayRole:
+  //        {
+  //          ModelAPI_ResultField::ModelAPI_FieldStep* aStep =
+  //            dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
+  //            ((ModelAPI_Entity*)theIndex.internalPointer());
+  //          if (aStep) {
+  //            return "Step " + QString::number(aStep->id() + 1) + " " +
+  //              aStep->field()->textLine(aStep->id()).c_str();
+  //          }
+  //        }
+  //        break;
+  //      }
+  //    }
+  //  }
+  //}
+  //return QVariant();
 }
 
 //******************************************************
@@ -579,74 +652,78 @@ QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, i
 //******************************************************
 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  if (!aSession->hasModuleDocument())
-    return 0;
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-
-  if (!theParent.isValid()) {
-    // Return number of items in root
-    int aNbFolders = foldersCount();
-    int aNbItems = 0;
-    std::string aType = myXMLReader->rootType();
-    if (!aType.empty())
-      aNbItems = aRootDoc->size(aType, true);
-    return aNbFolders + aNbItems;
-  }
-
-  quintptr aId = theParent.internalId();
-  if (aId == 0) {
-    // this is a folder under root
-    int aParentPos = theParent.row();
-    std::string aType = myXMLReader->rootFolderType(aParentPos);
-    return aRootDoc->size(aType);
-  } else {
-    // It is an object which could have children
-    ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
-    if (aDoc) {
-      // a folder of sub-document
-      QIntList aMissedIdx = missedFolderIndexes(aDoc);
-      int aRow = theParent.row();
-      while (aMissedIdx.contains(aRow))
-        aRow++;
-      if (aRow < myXMLReader->subFoldersNumber()) {
-        std::string aType = myXMLReader->subFolderType(aRow);
-        return aDoc->size(aType);
-      }
-    } else {
-      ModelAPI_Object* aObj =
-        dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theParent.internalPointer());
-      // Check for Part feature
-      ResultPartPtr aPartRes = getPartResult(aObj);
-      if (aPartRes.get()) {
-        DocumentPtr aSubDoc = aPartRes->partDoc();
-        if (!aSubDoc.get())
-          return 0;
-
-        int aNbSubFolders = foldersCount(aSubDoc.get());
-        int aNbSubItems = 0;
-        std::string aSubType = myXMLReader->subType();
-        if (!aSubType.empty())
-          aNbSubItems = aSubDoc->size(aSubType, true);
-        return aNbSubItems + aNbSubFolders;
-      } else {
-        // Check for composite object
-        ModelAPI_CompositeFeature* aCompFeature = dynamic_cast<ModelAPI_CompositeFeature*>(aObj);
-        if (aCompFeature)
-          return aCompFeature->numberOfSubs(true);
-        ModelAPI_ResultCompSolid* aCompRes = dynamic_cast<ModelAPI_ResultCompSolid*>(aObj);
-        if (aCompRes)
-          return aCompRes->numberOfSubs(true);
-        ModelAPI_ResultField* aFieldRes = dynamic_cast<ModelAPI_ResultField*>(aObj);
-        if (aFieldRes)
-          return aFieldRes->stepsSize();
-        ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aObj);
-        if (aFolder)
-          return getNumberOfFolderItems(aFolder);
-      }
-    }
-  }
-  return 0;
+  ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
+    (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
+  return aParentNode->childrenCount();
+
+  //SessionPtr aSession = ModelAPI_Session::get();
+  //if (!aSession->hasModuleDocument())
+  //  return 0;
+  //DocumentPtr aRootDoc = aSession->moduleDocument();
+
+  //if (!theParent.isValid()) {
+  //  // Return number of items in root
+  //  int aNbFolders = foldersCount();
+  //  int aNbItems = 0;
+  //  std::string aType = myXMLReader->rootType();
+  //  if (!aType.empty())
+  //    aNbItems = aRootDoc->size(aType, true);
+  //  return aNbFolders + aNbItems;
+  //}
+
+  //quintptr aId = theParent.internalId();
+  //if (aId == 0) {
+  //  // this is a folder under root
+  //  int aParentPos = theParent.row();
+  //  std::string aType = myXMLReader->rootFolderType(aParentPos);
+  //  return aRootDoc->size(aType);
+  //} else {
+  //  // It is an object which could have children
+  //  ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
+  //  if (aDoc) {
+  //    // a folder of sub-document
+  //    QIntList aMissedIdx = missedFolderIndexes(aDoc);
+  //    int aRow = theParent.row();
+  //    while (aMissedIdx.contains(aRow))
+  //      aRow++;
+  //    if (aRow < myXMLReader->subFoldersNumber()) {
+  //      std::string aType = myXMLReader->subFolderType(aRow);
+  //      return aDoc->size(aType);
+  //    }
+  //  } else {
+  //    ModelAPI_Object* aObj =
+  //      dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theParent.internalPointer());
+  //    // Check for Part feature
+  //    ResultPartPtr aPartRes = getPartResult(aObj);
+  //    if (aPartRes.get()) {
+  //      DocumentPtr aSubDoc = aPartRes->partDoc();
+  //      if (!aSubDoc.get())
+  //        return 0;
+
+  //      int aNbSubFolders = foldersCount(aSubDoc.get());
+  //      int aNbSubItems = 0;
+  //      std::string aSubType = myXMLReader->subType();
+  //      if (!aSubType.empty())
+  //        aNbSubItems = aSubDoc->size(aSubType, true);
+  //      return aNbSubItems + aNbSubFolders;
+  //    } else {
+  //      // Check for composite object
+  //      ModelAPI_CompositeFeature* aCompFeature = dynamic_cast<ModelAPI_CompositeFeature*>(aObj);
+  //      if (aCompFeature)
+  //        return aCompFeature->numberOfSubs(true);
+  //      ModelAPI_ResultCompSolid* aCompRes = dynamic_cast<ModelAPI_ResultCompSolid*>(aObj);
+  //      if (aCompRes)
+  //        return aCompRes->numberOfSubs(true);
+  //      ModelAPI_ResultField* aFieldRes = dynamic_cast<ModelAPI_ResultField*>(aObj);
+  //      if (aFieldRes)
+  //        return aFieldRes->stepsSize();
+  //      ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aObj);
+  //      if (aFolder)
+  //        return getNumberOfFolderItems(aFolder);
+  //    }
+  //  }
+  //}
+  //return 0;
 }
 
 //******************************************************
@@ -658,189 +735,203 @@ int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
 //******************************************************
 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
 {
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  int aNbFolders = foldersCount();
-
-  QModelIndex aIndex;
-
-  if (!theParent.isValid()) {
-    if (theRow < aNbFolders) // Return first level folder index
-      return createIndex(theRow, theColumn, (void*)Q_NULLPTR);
-    else { // return object under root index
-      std::string aType = myXMLReader->rootType();
-      int aObjId = theRow - aNbFolders;
-      if (aObjId < aRootDoc->size(aType, true)) {
-        ObjectPtr aObj = aRootDoc->object(aType, aObjId, true);
-        aIndex = objectIndex(aObj, theColumn);
-      }
-    }
-  } else {
-    quintptr aId = theParent.internalId();
-    int aParentPos = theParent.row();
-    if (aId == 0) { // return object index inside of first level of folders
-      std::string aType = myXMLReader->rootFolderType(aParentPos);
-      if (theRow < aRootDoc->size(aType)) {
-        ObjectPtr aObj = aRootDoc->object(aType, theRow, true);
-        aIndex = objectIndex(aObj, theColumn);
-      }
-    } else {
-      // It is an object which could have children
-      ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
-      if (aDoc) {
-        // It is a folder of sub-document
-        int aParentRow = aParentPos;
-        QIntList aMissedIdx = missedFolderIndexes(aDoc);
-        while (aMissedIdx.contains(aParentRow))
-          aParentRow++;
-        if (aParentRow < myXMLReader->subFoldersNumber()) {
-          std::string aType = myXMLReader->subFolderType(aParentRow);
-          if (theRow < aDoc->size(aType)) {
-            ObjectPtr aObj = aDoc->object(aType, theRow);
-            aIndex = objectIndex(aObj, theColumn);
-          }
-        }
-      } else {
-        ModelAPI_Object* aParentObj =
-          dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theParent.internalPointer());
-
-        // Check for Part feature
-        ResultPartPtr aPartRes = getPartResult(aParentObj);
-        if (aPartRes.get()) {
-          DocumentPtr aSubDoc = aPartRes->partDoc();
-          int aNbSubFolders = foldersCount(aSubDoc.get());
-          if (theRow < aNbSubFolders) { // Create a Folder of sub-document
-            aIndex = createIndex(theRow, theColumn, aSubDoc.get());
-          } else {
-            // this is an object under sub document root
-            std::string aType = myXMLReader->subType();
-            ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders, true);
-            aIndex = objectIndex(aObj, theColumn);
-          }
-        } else {
-          // Check for composite object
-          ModelAPI_CompositeFeature* aCompFeature =
-            dynamic_cast<ModelAPI_CompositeFeature*>(aParentObj);
-          if (aCompFeature) {
-            aIndex = objectIndex(aCompFeature->subFeature(theRow), theColumn);
-          } else {
-            ModelAPI_ResultCompSolid* aCompRes =
-              dynamic_cast<ModelAPI_ResultCompSolid*>(aParentObj);
-            if (aCompRes)
-              aIndex = objectIndex(aCompRes->subResult(theRow), theColumn);
-            else {
-              ModelAPI_ResultField* aFieldRes =
-                dynamic_cast<ModelAPI_ResultField*>(aParentObj);
-              if (aFieldRes) {
-                aIndex = createIndex(theRow, theColumn, aFieldRes->step(theRow));
-              } else {
-                ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aParentObj);
-                ObjectPtr aObj = getObjectInFolder(aFolder, theRow);
-                if (aObj.get())
-                  aIndex = objectIndex(aObj, theColumn);
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-  return aIndex;
+  int aa = theParent.row();
+  ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
+    (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
+  ModuleBase_ITreeNode* aSubNode = aParentNode->subNode(theRow);
+  assert(aSubNode);
+  return createIndex(theRow, theColumn, aSubNode);
+
+  //SessionPtr aSession = ModelAPI_Session::get();
+  //DocumentPtr aRootDoc = aSession->moduleDocument();
+  //int aNbFolders = foldersCount();
+
+  //QModelIndex aIndex;
+
+  //if (!theParent.isValid()) {
+  //  if (theRow < aNbFolders) // Return first level folder index
+  //    return createIndex(theRow, theColumn, (void*)Q_NULLPTR);
+  //  else { // return object under root index
+  //    std::string aType = myXMLReader->rootType();
+  //    int aObjId = theRow - aNbFolders;
+  //    if (aObjId < aRootDoc->size(aType, true)) {
+  //      ObjectPtr aObj = aRootDoc->object(aType, aObjId, true);
+  //      aIndex = objectIndex(aObj, theColumn);
+  //    }
+  //  }
+  //} else {
+  //  quintptr aId = theParent.internalId();
+  //  int aParentPos = theParent.row();
+  //  if (aId == 0) { // return object index inside of first level of folders
+  //    std::string aType = myXMLReader->rootFolderType(aParentPos);
+  //    if (theRow < aRootDoc->size(aType)) {
+  //      ObjectPtr aObj = aRootDoc->object(aType, theRow, true);
+  //      aIndex = objectIndex(aObj, theColumn);
+  //    }
+  //  } else {
+  //    // It is an object which could have children
+  //    ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
+  //    if (aDoc) {
+  //      // It is a folder of sub-document
+  //      int aParentRow = aParentPos;
+  //      QIntList aMissedIdx = missedFolderIndexes(aDoc);
+  //      while (aMissedIdx.contains(aParentRow))
+  //        aParentRow++;
+  //      if (aParentRow < myXMLReader->subFoldersNumber()) {
+  //        std::string aType = myXMLReader->subFolderType(aParentRow);
+  //        if (theRow < aDoc->size(aType)) {
+  //          ObjectPtr aObj = aDoc->object(aType, theRow);
+  //          aIndex = objectIndex(aObj, theColumn);
+  //        }
+  //      }
+  //    } else {
+  //      ModelAPI_Object* aParentObj =
+  //        dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theParent.internalPointer());
+
+  //      // Check for Part feature
+  //      ResultPartPtr aPartRes = getPartResult(aParentObj);
+  //      if (aPartRes.get()) {
+  //        DocumentPtr aSubDoc = aPartRes->partDoc();
+  //        int aNbSubFolders = foldersCount(aSubDoc.get());
+  //        if (theRow < aNbSubFolders) { // Create a Folder of sub-document
+  //          aIndex = createIndex(theRow, theColumn, aSubDoc.get());
+  //        } else {
+  //          // this is an object under sub document root
+  //          std::string aType = myXMLReader->subType();
+  //          ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders, true);
+  //          aIndex = objectIndex(aObj, theColumn);
+  //        }
+  //      } else {
+  //        // Check for composite object
+  //        ModelAPI_CompositeFeature* aCompFeature =
+  //          dynamic_cast<ModelAPI_CompositeFeature*>(aParentObj);
+  //        if (aCompFeature) {
+  //          aIndex = objectIndex(aCompFeature->subFeature(theRow), theColumn);
+  //        } else {
+  //          ModelAPI_ResultCompSolid* aCompRes =
+  //            dynamic_cast<ModelAPI_ResultCompSolid*>(aParentObj);
+  //          if (aCompRes)
+  //            aIndex = objectIndex(aCompRes->subResult(theRow), theColumn);
+  //          else {
+  //            ModelAPI_ResultField* aFieldRes =
+  //              dynamic_cast<ModelAPI_ResultField*>(aParentObj);
+  //            if (aFieldRes) {
+  //              aIndex = createIndex(theRow, theColumn, aFieldRes->step(theRow));
+  //            } else {
+  //              ModelAPI_Folder* aFolder = dynamic_cast<ModelAPI_Folder*>(aParentObj);
+  //              ObjectPtr aObj = getObjectInFolder(aFolder, theRow);
+  //              if (aObj.get())
+  //                aIndex = objectIndex(aObj, theColumn);
+  //            }
+  //          }
+  //        }
+  //      }
+  //    }
+  //  }
+  //}
+  //return aIndex;
 }
 
 //******************************************************
-static QModelIndex MYLastDeleted;
+//static QModelIndex MYLastDeleted;
 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
 {
-  if (!theIndex.isValid())
-    return QModelIndex();
-  // To avoid additional request about index which was already deleted
-  if (theIndex == MYLastDeleted)
-    return QModelIndex();
-
-  SessionPtr aSession = ModelAPI_Session::get();
-  quintptr aId = theIndex.internalId();
-  if (aId != 0) { // The object is not a root folder
-    ModelAPI_Document* aDoc = getSubDocument(theIndex.internalPointer());
-    if (aDoc) {
-      // It is a folder of sub-document
-      return findDocumentRootIndex(aDoc);
-    }
-    ObjectPtr aObj = object(theIndex);
-    if (!aObj.get()) {
-      // It can be a step of a field
-      ModelAPI_ResultField::ModelAPI_FieldStep* aStep = 0;
-      try {
-        aStep = dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
-                ((ModelAPI_Entity*)theIndex.internalPointer());
-      } catch(...) {}
-
-      if (aStep) {
-        ModelAPI_ResultField* aField = aStep->field();
-        DocumentPtr aDoc = aSession->activeDocument();
-        ObjectPtr aFld;
-        for(int i = 0; i < aDoc->size(ModelAPI_ResultField::group()); i++) {
-          aFld = aDoc->object(ModelAPI_ResultField::group(), i);
-          if (aFld.get() == aField)
-            return objectIndex(aFld);
-        }
-      }
-      // To avoid additional request about index which was already deleted
-      // If deleted it causes a crash on delete object from Part
-      MYLastDeleted = theIndex;
-      return QModelIndex();
-    }
-    // Check is it object a sub-object of a complex object
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
-    if (aFeature.get()) {
-      CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
-      if (aCompFea.get()) {
-        return objectIndex(aCompFea);
-      }
-      DocumentPtr aDoc = aFeature->document();
-      int aRow;
-      FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aRow);
-      if (aFolder.get())
-        return objectIndex(aFolder);
-    }
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
-    if (aResult.get()) {
-      ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
-      if (aCompRes.get()) {
-        return objectIndex(aCompRes);
-      }
-    }
-    // Use as ordinary object
-    std::string aType = aObj->groupName();
-    DocumentPtr aRootDoc = aSession->moduleDocument();
-    DocumentPtr aSubDoc = aObj->document();
-    if (aSubDoc == aRootDoc) {
-      if ((aType == myXMLReader->rootType()) || (aType == ModelAPI_Folder::group()))
-        return QModelIndex();
-      else {
-        // return first level of folder index
-        int aFolderId = myXMLReader->rootFolderId(aType);
-        // Items in a one row must have the same parent
-        return createIndex(aFolderId, 1, (void*)Q_NULLPTR);
-      }
-    } else {
-      if ((aType == myXMLReader->subType()) || (aType == ModelAPI_Folder::group()))
-        return findDocumentRootIndex(aSubDoc.get());
-      else {
-        // return first level of folder index
-        int aFolderId = folderId(aType, aSubDoc.get());
-        // Items in a one row must have the same parent
-        return createIndex(aFolderId, 1, aSubDoc.get());
-      }
-    }
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return getParentIndex(aNode, 1);
   }
   return QModelIndex();
+
+  //if (!theIndex.isValid())
+  //  return QModelIndex();
+  //// To avoid additional request about index which was already deleted
+  //if (theIndex == MYLastDeleted)
+  //  return QModelIndex();
+
+  //SessionPtr aSession = ModelAPI_Session::get();
+  //quintptr aId = theIndex.internalId();
+  //if (aId != 0) { // The object is not a root folder
+  //  ModelAPI_Document* aDoc = getSubDocument(theIndex.internalPointer());
+  //  if (aDoc) {
+  //    // It is a folder of sub-document
+  //    return findDocumentRootIndex(aDoc);
+  //  }
+  //  ObjectPtr aObj = object(theIndex);
+  //  if (!aObj.get()) {
+  //    // It can be a step of a field
+  //    ModelAPI_ResultField::ModelAPI_FieldStep* aStep = 0;
+  //    try {
+  //      aStep = dynamic_cast<ModelAPI_ResultField::ModelAPI_FieldStep*>
+  //              ((ModelAPI_Entity*)theIndex.internalPointer());
+  //    } catch(...) {}
+
+  //    if (aStep) {
+  //      ModelAPI_ResultField* aField = aStep->field();
+  //      DocumentPtr aDoc = aSession->activeDocument();
+  //      ObjectPtr aFld;
+  //      for(int i = 0; i < aDoc->size(ModelAPI_ResultField::group()); i++) {
+  //        aFld = aDoc->object(ModelAPI_ResultField::group(), i);
+  //        if (aFld.get() == aField)
+  //          return objectIndex(aFld);
+  //      }
+  //    }
+  //    // To avoid additional request about index which was already deleted
+  //    // If deleted it causes a crash on delete object from Part
+  //    MYLastDeleted = theIndex;
+  //    return QModelIndex();
+  //  }
+  //  // Check is it object a sub-object of a complex object
+  //  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+  //  if (aFeature.get()) {
+  //    CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
+  //    if (aCompFea.get()) {
+  //      return objectIndex(aCompFea);
+  //    }
+  //    DocumentPtr aDoc = aFeature->document();
+  //    int aRow;
+  //    FolderPtr aFolder = aDoc->findContainingFolder(aFeature, aRow);
+  //    if (aFolder.get())
+  //      return objectIndex(aFolder);
+  //  }
+  //  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+  //  if (aResult.get()) {
+  //    ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
+  //    if (aCompRes.get()) {
+  //      return objectIndex(aCompRes);
+  //    }
+  //  }
+  //  // Use as ordinary object
+  //  std::string aType = aObj->groupName();
+  //  DocumentPtr aRootDoc = aSession->moduleDocument();
+  //  DocumentPtr aSubDoc = aObj->document();
+  //  if (aSubDoc == aRootDoc) {
+  //    if ((aType == myXMLReader->rootType()) || (aType == ModelAPI_Folder::group()))
+  //      return QModelIndex();
+  //    else {
+  //      // return first level of folder index
+  //      int aFolderId = myXMLReader->rootFolderId(aType);
+  //      // Items in a one row must have the same parent
+  //      return createIndex(aFolderId, 1, (void*)Q_NULLPTR);
+  //    }
+  //  } else {
+  //    if ((aType == myXMLReader->subType()) || (aType == ModelAPI_Folder::group()))
+  //      return findDocumentRootIndex(aSubDoc.get());
+  //    else {
+  //      // return first level of folder index
+  //      int aFolderId = folderId(aType, aSubDoc.get());
+  //      // Items in a one row must have the same parent
+  //      return createIndex(aFolderId, 1, aSubDoc.get());
+  //    }
+  //  }
+  //}
 }
 
 //******************************************************
 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
 {
-  return rowCount(theParent) > 0;
+  ModuleBase_ITreeNode* aParentNode = (theParent.isValid()) ?
+    (ModuleBase_ITreeNode*)theParent.internalPointer() : myRoot;
+  return aParentNode->childrenCount() > 0;
 }
 
 //******************************************************
@@ -848,7 +939,6 @@ bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& the
 {
   beginInsertRows(theParent, theRow, theRow + theCount - 1);
   endInsertRows();
-
   return true;
 }
 
@@ -863,113 +953,119 @@ bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& the
 //******************************************************
 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
 {
-  quintptr aIt = theIndex.internalId();
-  ModelAPI_Object* aObj = 0;
-  ModelAPI_Document* aDoc = 0;
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aActiveDoc = aSession->activeDocument();
-
-  Qt::ItemFlags aNullFlag;
-  Qt::ItemFlags aDefaultFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
-  Qt::ItemFlags aEditingFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
-
-
-  if (aIt == 0) {
-    // Folders under root
-    DocumentPtr aRootDoc = aSession->moduleDocument();
-    if (aRootDoc != aActiveDoc)
-      return aDefaultFlag;
-  } else {
-    aDoc = getSubDocument(theIndex.internalPointer());
-    if (!aDoc)
-      aObj = dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
-  }
-
-  if (aObj) {
-    // An object
-    if (aObj->isDisabled())
-      return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
-
-    if (aSession->moduleDocument() != aObj->document())
-      if (aActiveDoc != aObj->document())
-        return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
-
-    bool isCompositeSub = false;
-    // An object which is sub-object of a composite object can not be accessible in column 2
-    if (theIndex.column() == 2) {
-      ObjectPtr aObjPtr = aObj->data()->owner();
-      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjPtr);
-      if (aFeature.get()) {
-        CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
-        if (aCompFea.get())
-          isCompositeSub = true;
-      } else {
-        ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObjPtr);
-        if (aResult.get()) {
-          ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
-          if (aCompRes.get())
-            isCompositeSub = true;
-        }
-      }
-    }
-    if (isCompositeSub)
-      return Qt::ItemIsSelectable;
-
-    if (aObj->document() != aActiveDoc) {
-      // The object could be a root of sub-tree
-      ResultPartPtr aPartRes = getPartResult(aObj);
-      if (aPartRes.get()) {
-        if (aPartRes->partDoc() == aActiveDoc)
-          return aEditingFlag;
-      }
-      return aDefaultFlag;
-    }
-  } else if (aDoc) {
-    // A folder under sub-document
-    if (aActiveDoc.get() != aDoc)
-      return aNullFlag;
+  if (theIndex.isValid()) {
+    ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+    return aNode->flags(theIndex.column());
   }
-  return aEditingFlag;
+  return Qt::ItemFlags();
+
+  //quintptr aIt = theIndex.internalId();
+  //ModelAPI_Object* aObj = 0;
+  //ModelAPI_Document* aDoc = 0;
+  //SessionPtr aSession = ModelAPI_Session::get();
+  //DocumentPtr aActiveDoc = aSession->activeDocument();
+
+  //Qt::ItemFlags aNullFlag;
+  //Qt::ItemFlags aDefaultFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+  //Qt::ItemFlags aEditingFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+
+
+  //if (aIt == 0) {
+  //  // Folders under root
+  //  DocumentPtr aRootDoc = aSession->moduleDocument();
+  //  if (aRootDoc != aActiveDoc)
+  //    return aDefaultFlag;
+  //} else {
+  //  aDoc = getSubDocument(theIndex.internalPointer());
+  //  if (!aDoc)
+  //    aObj = dynamic_cast<ModelAPI_Object*>((ModelAPI_Entity*)theIndex.internalPointer());
+  //}
+
+  //if (aObj) {
+  //  // An object
+  //  if (aObj->isDisabled())
+  //    return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
+
+  //  if (aSession->moduleDocument() != aObj->document())
+  //    if (aActiveDoc != aObj->document())
+  //      return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
+
+  //  bool isCompositeSub = false;
+  //  // An object which is sub-object of a composite object can not be accessible in column 2
+  //  if (theIndex.column() == 2) {
+  //    ObjectPtr aObjPtr = aObj->data()->owner();
+  //    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjPtr);
+  //    if (aFeature.get()) {
+  //      CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
+  //      if (aCompFea.get())
+  //        isCompositeSub = true;
+  //    } else {
+  //      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObjPtr);
+  //      if (aResult.get()) {
+  //        ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult);
+  //        if (aCompRes.get())
+  //          isCompositeSub = true;
+  //      }
+  //    }
+  //  }
+  //  if (isCompositeSub)
+  //    return Qt::ItemIsSelectable;
+
+  //  if (aObj->document() != aActiveDoc) {
+  //    // The object could be a root of sub-tree
+  //    ResultPartPtr aPartRes = getPartResult(aObj);
+  //    if (aPartRes.get()) {
+  //      if (aPartRes->partDoc() == aActiveDoc)
+  //        return aEditingFlag;
+  //    }
+  //    return aDefaultFlag;
+  //  }
+  //} else if (aDoc) {
+  //  // A folder under sub-document
+  //  if (aActiveDoc.get() != aDoc)
+  //    return aNullFlag;
+  //}
+  //return aEditingFlag;
 }
 
 //******************************************************
-QModelIndex
-  XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn) const
-{
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if (myXMLReader->isAttachToResult()) { // If document is attached to result
-    int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
-    ObjectPtr aObj;
-    ResultPartPtr aPartRes;
-    for (int i = 0; i < aNb; i++) {
-      aObj = aRootDoc->object(ModelAPI_ResultPart::group(), i);
-      aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
-      if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
-        int aRow = i;
-        if (myXMLReader->rootType() == ModelAPI_Feature::group()) {
-          aRow += foldersCount();
-        }
-        return createIndex(aRow, aColumn, aObj.get());
-      }
-    }
-  } else { // If document is attached to feature
-    int aNb = aRootDoc->size(ModelAPI_Feature::group(), true);
-    ObjectPtr aObj;
-    ResultPartPtr aPartRes;
-    for (int i = 0; i < aNb; i++) {
-      aObj = aRootDoc->object(ModelAPI_Feature::group(), i, true);
-      aPartRes = getPartResult(aObj.get());
-      if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
-        int aRow = i;
-        if (myXMLReader->rootType() == ModelAPI_Feature::group())
-          aRow += foldersCount();
-        return createIndex(aRow, aColumn, aObj.get());
-      }
-    }
-  }
-  return QModelIndex();
-}
+//QModelIndex
+//  XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn) const
+//{
+//  SessionPtr aSession = ModelAPI_Session::get();
+//  DocumentPtr aRootDoc = aSession->moduleDocument();
+//  if (myXMLReader->isAttachToResult()) { // If document is attached to result
+//    int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
+//    ObjectPtr aObj;
+//    ResultPartPtr aPartRes;
+//    for (int i = 0; i < aNb; i++) {
+//      aObj = aRootDoc->object(ModelAPI_ResultPart::group(), i);
+//      aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+//      if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
+//        int aRow = i;
+//        if (myXMLReader->rootType() == ModelAPI_Feature::group()) {
+//          aRow += foldersCount();
+//        }
+//        return createIndex(aRow, aColumn, aObj.get());
+//      }
+//    }
+//  } else { // If document is attached to feature
+//    int aNb = aRootDoc->size(ModelAPI_Feature::group(), true);
+//    ObjectPtr aObj;
+//    ResultPartPtr aPartRes;
+//    for (int i = 0; i < aNb; i++) {
+//      aObj = aRootDoc->object(ModelAPI_Feature::group(), i, true);
+//      aPartRes = getPartResult(aObj.get());
+//      if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
+//        int aRow = i;
+//        if (myXMLReader->rootType() == ModelAPI_Feature::group())
+//          aRow += foldersCount();
+//        return createIndex(aRow, aColumn, aObj.get());
+//      }
+//    }
+//  }
+//  return QModelIndex();
+//}
 
 //******************************************************
 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
@@ -978,146 +1074,158 @@ QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn)
   DocumentPtr aRootDoc = aSession->moduleDocument();
   if (theDoc == aRootDoc)
     return QModelIndex();
-  else
-    return findDocumentRootIndex(theDoc.get(), theColumn);
-}
-
-//******************************************************
-int XGUI_DataModel::foldersCount(ModelAPI_Document* theDoc) const
-{
-  int aNb = 0;
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if ((theDoc == 0) || (theDoc == aRootDoc.get())) {
-    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
-      if (myXMLReader->rootShowEmpty(i))
-        aNb++;
-      else {
-        if (aRootDoc->size(myXMLReader->rootFolderType(i)) > 0)
-          aNb++;
-      }
-    }
-  } else {
-    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
-      if (myXMLReader->subShowEmpty(i))
-        aNb++;
-      else {
-        if (theDoc->size(myXMLReader->subFolderType(i)) > 0)
-          aNb++;
+  else {
+    ModuleBase_ITreeNode* aDocNode = 0;
+    foreach(ModuleBase_ITreeNode* aNode, myRoot->children()) {
+      if (aNode->document() == theDoc) {
+        aDocNode = aNode;
+        break;
       }
     }
+    if (aDocNode)
+      return getIndex(aDocNode, theColumn);
   }
-  return aNb;
+  return QModelIndex();
+  //  return findDocumentRootIndex(theDoc.get(), theColumn);
 }
 
+//******************************************************
+//int XGUI_DataModel::foldersCount(ModelAPI_Document* theDoc) const
+//{
+//  int aNb = 0;
+//  SessionPtr aSession = ModelAPI_Session::get();
+//  DocumentPtr aRootDoc = aSession->moduleDocument();
+//  if ((theDoc == 0) || (theDoc == aRootDoc.get())) {
+//    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
+//      if (myXMLReader->rootShowEmpty(i))
+//        aNb++;
+//      else {
+//        if (aRootDoc->size(myXMLReader->rootFolderType(i)) > 0)
+//          aNb++;
+//      }
+//    }
+//  } else {
+//    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
+//      if (myXMLReader->subShowEmpty(i))
+//        aNb++;
+//      else {
+//        if (theDoc->size(myXMLReader->subFolderType(i)) > 0)
+//          aNb++;
+//      }
+//    }
+//  }
+//  return aNb;
+//}
+
 
 //******************************************************
-QIntList XGUI_DataModel::missedFolderIndexes(ModelAPI_Document* theDoc) const
-{
-  QIntList aList;
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aRootDoc = aSession->moduleDocument();
-  if ((theDoc == 0) || (theDoc == aRootDoc.get())) {
-    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
-      if (!myXMLReader->rootShowEmpty(i)) {
-        if (aRootDoc->size(myXMLReader->rootFolderType(i)) == 0)
-          aList.append(i);
-      }
-    }
-  } else {
-    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
-      if (!myXMLReader->subShowEmpty(i)) {
-        if (theDoc->size(myXMLReader->subFolderType(i)) == 0)
-          aList.append(i);
-      }
-    }
-  }
-  return aList;
-}
+//QIntList XGUI_DataModel::missedFolderIndexes(ModelAPI_Document* theDoc) const
+//{
+//  QIntList aList;
+//  SessionPtr aSession = ModelAPI_Session::get();
+//  DocumentPtr aRootDoc = aSession->moduleDocument();
+//  if ((theDoc == 0) || (theDoc == aRootDoc.get())) {
+//    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
+//      if (!myXMLReader->rootShowEmpty(i)) {
+//        if (aRootDoc->size(myXMLReader->rootFolderType(i)) == 0)
+//          aList.append(i);
+//      }
+//    }
+//  } else {
+//    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
+//      if (!myXMLReader->subShowEmpty(i)) {
+//        if (theDoc->size(myXMLReader->subFolderType(i)) == 0)
+//          aList.append(i);
+//      }
+//    }
+//  }
+//  return aList;
+//}
 
 
 //******************************************************
-QStringList XGUI_DataModel::listOfShowNotEmptyFolders(bool fromRoot) const
-{
-  QStringList aResult;
-  if (fromRoot) {
-    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
-      if (!myXMLReader->rootShowEmpty(i))
-        aResult << myXMLReader->rootFolderType(i).c_str();
-    }
-  } else {
-    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
-      if (!myXMLReader->subShowEmpty(i))
-        aResult << myXMLReader->subFolderType(i).c_str();
-    }
-  }
-  return aResult;
-}
+//QStringList XGUI_DataModel::listOfShowNotEmptyFolders(bool fromRoot) const
+//{
+//  QStringList aResult;
+//  if (fromRoot) {
+//    for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) {
+//      if (!myXMLReader->rootShowEmpty(i))
+//        aResult << myXMLReader->rootFolderType(i).c_str();
+//    }
+//  } else {
+//    for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) {
+//      if (!myXMLReader->subShowEmpty(i))
+//        aResult << myXMLReader->subFolderType(i).c_str();
+//    }
+//  }
+//  return aResult;
+//}
 
 //******************************************************
-QModelIndex XGUI_DataModel::lastHistoryIndex() const
-{
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aCurDoc = aSession->activeDocument();
-  FeaturePtr aFeature = aCurDoc->currentFeature(true);
-  if (aFeature.get()) {
-    QModelIndex aInd = objectIndex(aFeature);
-    return createIndex(aInd.row(), 2, aInd.internalPointer());
-  } else {
-    if (aCurDoc == aSession->moduleDocument())
-      return createIndex(foldersCount() - 1, 2, -1);
-    else
-      return createIndex(foldersCount(aCurDoc.get()) - 1, 2, aCurDoc.get());
-  }
-}
+//QModelIndex XGUI_DataModel::lastHistoryIndex() const
+//{
+  //SessionPtr aSession = ModelAPI_Session::get();
+  //DocumentPtr aCurDoc = aSession->activeDocument();
+  //FeaturePtr aFeature = aCurDoc->currentFeature(true);
+  //if (aFeature.get()) {
+  //  QModelIndex aInd = objectIndex(aFeature);
+  //  return createIndex(aInd.row(), 2, aInd.internalPointer());
+  //} else {
+  //  if (aCurDoc == aSession->moduleDocument())
+  //    return createIndex(foldersCount() - 1, 2, -1);
+  //  else
+  //    return createIndex(foldersCount(aCurDoc.get()) - 1, 2, aCurDoc.get());
+  //}
+//}
 
 //******************************************************
 bool XGUI_DataModel::hasHiddenState(const QModelIndex& theIndex)
 {
-  return getVisibilityState(theIndex) == Hidden;
+  return false;
+  //return getVisibilityState(theIndex) == Hidden;
 }
 
 //******************************************************
-int XGUI_DataModel::folderId(std::string theType, ModelAPI_Document* theDoc) const
-{
-  SessionPtr aSession = ModelAPI_Session::get();
-  ModelAPI_Document* aDoc = theDoc;
-  if (aDoc == 0)
-    aDoc = aSession->moduleDocument().get();
-
-  bool aUseSubDoc = (aDoc != aSession->moduleDocument().get());
-
-  int aRes = -1;
-  if (aUseSubDoc) {
-    int aId = myXMLReader->subFolderId(theType);
-    aRes = aId;
-    for (int i = 0; i < aId; i++) {
-      if (!myXMLReader->subShowEmpty(i)) {
-        if (aDoc->size(myXMLReader->subFolderType(i)) == 0)
-          aRes--;
-      }
-    }
-  } else {
-    int aId = myXMLReader->rootFolderId(theType);
-    aRes = aId;
-    for (int i = 0; i < aId; i++) {
-      if (!myXMLReader->rootShowEmpty(i)) {
-        if (aDoc->size(myXMLReader->rootFolderType(i)) == 0)
-          aRes--;
-      }
-    }
-  }
-  return aRes;
-}
+//int XGUI_DataModel::folderId(std::string theType, ModelAPI_Document* theDoc) const
+//{
+//  SessionPtr aSession = ModelAPI_Session::get();
+//  ModelAPI_Document* aDoc = theDoc;
+//  if (aDoc == 0)
+//    aDoc = aSession->moduleDocument().get();
+//
+//  bool aUseSubDoc = (aDoc != aSession->moduleDocument().get());
+//
+//  int aRes = -1;
+//  if (aUseSubDoc) {
+//    int aId = myXMLReader->subFolderId(theType);
+//    aRes = aId;
+//    for (int i = 0; i < aId; i++) {
+//      if (!myXMLReader->subShowEmpty(i)) {
+//        if (aDoc->size(myXMLReader->subFolderType(i)) == 0)
+//          aRes--;
+//      }
+//    }
+//  } else {
+//    int aId = myXMLReader->rootFolderId(theType);
+//    aRes = aId;
+//    for (int i = 0; i < aId; i++) {
+//      if (!myXMLReader->rootShowEmpty(i)) {
+//        if (aDoc->size(myXMLReader->rootFolderType(i)) == 0)
+//          aRes--;
+//      }
+//    }
+//  }
+//  return aRes;
+//}
 
 //******************************************************
-void XGUI_DataModel::rebuildBranch(int theRow, int theCount, const QModelIndex& theParent)
-{
-  if (theCount > 0) {
-    removeRows(theRow, theCount, theParent);
-    insertRows(theRow, theCount, theParent);
-  }
-}
+//void XGUI_DataModel::rebuildBranch(int theRow, int theCount, const QModelIndex& theParent)
+//{
+//  if (theCount > 0) {
+//    removeRows(theRow, theCount, theParent);
+//    insertRows(theRow, theCount, theParent);
+//  }
+//}
 
 //******************************************************
 //bool XGUI_DataModel::blockEventsProcessing(const bool theState)
@@ -1128,84 +1236,106 @@ void XGUI_DataModel::rebuildBranch(int theRow, int theCount, const QModelIndex&
 //}
 
 //******************************************************
-XGUI_DataModel::VisibilityState
-  XGUI_DataModel::getVisibilityState(const QModelIndex& theIndex) const
+//XGUI_DataModel::VisibilityState
+//  XGUI_DataModel::getVisibilityState(const QModelIndex& theIndex) const
+//{
+//  Qt::ItemFlags aFlags = theIndex.flags();
+//  if (aFlags == Qt::ItemFlags())
+//    return NoneState;
+//
+//  ObjectPtr aObj = object(theIndex);
+//  if (aObj.get()) {
+//    if (aObj->groupName() == ModelAPI_ResultParameter::group())
+//      return NoneState;
+//    ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+//    if (aResObj.get()) {
+//      XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+//      ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResObj);
+//      if (aCompRes.get()) {
+//        VisibilityState aState = aCompRes->numberOfSubs(true) == 0 ?
+//          (aDisplayer->isVisible(aCompRes)? Visible : Hidden) : NoneState;
+//        for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
+//          ResultPtr aSubRes = aCompRes->subResult(i, true);
+//          VisibilityState aS = aDisplayer->isVisible(aSubRes)? Visible : Hidden;
+//          if (aState == NoneState)
+//            aState = aS;
+//          else if (aState != aS) {
+//            aState = SemiVisible;
+//            break;
+//          }
+//        }
+//        return aState;
+//      } else {
+//        if (aDisplayer->isVisible(aResObj))
+//          return Visible;
+//        else
+//          return Hidden;
+//      }
+//    }
+//  }
+//  return NoneState;
+//}
+
+
+//int XGUI_DataModel::getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const
+//{
+//  DocumentPtr aDoc = theFolder->document();
+//
+//  FeaturePtr aFirstFeatureInFolder;
+//  AttributeReferencePtr aFirstFeatAttr =
+//      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+//  if (aFirstFeatAttr)
+//    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
+//  if (!aFirstFeatureInFolder.get())
+//    return 0;
+//
+//  FeaturePtr aLastFeatureInFolder;
+//  AttributeReferencePtr aLastFeatAttr =
+//      theFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+//  if (aLastFeatAttr)
+//    aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value());
+//  if (!aLastFeatureInFolder.get())
+//    return 0;
+//
+//  int aFirst = aDoc->index(aFirstFeatureInFolder);
+//  int aLast = aDoc->index(aLastFeatureInFolder);
+//  return aLast - aFirst + 1;
+//}
+
+//ObjectPtr XGUI_DataModel::getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const
+//{
+//  DocumentPtr aDoc = theFolder->document();
+//
+//  FeaturePtr aFirstFeatureInFolder;
+//  AttributeReferencePtr aFirstFeatAttr =
+//      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
+//  if (aFirstFeatAttr)
+//    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
+//  if (!aFirstFeatureInFolder.get())
+//    return ObjectPtr();
+//
+//  int aFirst = aDoc->index(aFirstFeatureInFolder);
+//  return aDoc->object(ModelAPI_Feature::group(), aFirst + theId);
+//}
+
+bool XGUI_DataModel::hasIndex(const QModelIndex& theIndex) const
 {
-  Qt::ItemFlags aFlags = theIndex.flags();
-  if (aFlags == Qt::ItemFlags())
-    return NoneState;
-
-  ObjectPtr aObj = object(theIndex);
-  if (aObj.get()) {
-    if (aObj->groupName() == ModelAPI_ResultParameter::group())
-      return NoneState;
-    ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
-    if (aResObj.get()) {
-      XGUI_Displayer* aDisplayer = myWorkshop->displayer();
-      ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResObj);
-      if (aCompRes.get()) {
-        VisibilityState aState = aCompRes->numberOfSubs(true) == 0 ?
-          (aDisplayer->isVisible(aCompRes)? Visible : Hidden) : NoneState;
-        for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
-          ResultPtr aSubRes = aCompRes->subResult(i, true);
-          VisibilityState aS = aDisplayer->isVisible(aSubRes)? Visible : Hidden;
-          if (aState == NoneState)
-            aState = aS;
-          else if (aState != aS) {
-            aState = SemiVisible;
-            break;
-          }
-        }
-        return aState;
-      } else {
-        if (aDisplayer->isVisible(aResObj))
-          return Visible;
-        else
-          return Hidden;
-      }
-    }
-  }
-  return NoneState;
+  ModuleBase_ITreeNode* aNode = (ModuleBase_ITreeNode*)theIndex.internalPointer();
+  return myRoot->hasSubNode(aNode);
 }
 
-
-int XGUI_DataModel::getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const
+QModelIndex XGUI_DataModel::getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const
 {
-  DocumentPtr aDoc = theFolder->document();
-
-  FeaturePtr aFirstFeatureInFolder;
-  AttributeReferencePtr aFirstFeatAttr =
-      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
-  if (aFirstFeatAttr)
-    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
-  if (!aFirstFeatureInFolder.get())
-    return 0;
-
-  FeaturePtr aLastFeatureInFolder;
-  AttributeReferencePtr aLastFeatAttr =
-      theFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID());
-  if (aLastFeatAttr)
-    aLastFeatureInFolder = ModelAPI_Feature::feature(aLastFeatAttr->value());
-  if (!aLastFeatureInFolder.get())
-    return 0;
-
-  int aFirst = aDoc->index(aFirstFeatureInFolder);
-  int aLast = aDoc->index(aLastFeatureInFolder);
-  return aLast - aFirst + 1;
+  ModuleBase_ITreeNode* aParent = theNode->parent();
+  if (aParent == myRoot) {
+    return QModelIndex();
+  } else {
+    return getIndex(aParent, thCol);
+  }
 }
 
-ObjectPtr XGUI_DataModel::getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const
+QModelIndex XGUI_DataModel::getIndex(ModuleBase_ITreeNode* theNode, int thCol) const
 {
-  DocumentPtr aDoc = theFolder->document();
-
-  FeaturePtr aFirstFeatureInFolder;
-  AttributeReferencePtr aFirstFeatAttr =
-      theFolder->data()->reference(ModelAPI_Folder::FIRST_FEATURE_ID());
-  if (aFirstFeatAttr)
-    aFirstFeatureInFolder = ModelAPI_Feature::feature(aFirstFeatAttr->value());
-  if (!aFirstFeatureInFolder.get())
-    return ObjectPtr();
-
-  int aFirst = aDoc->index(aFirstFeatureInFolder);
-  return aDoc->object(ModelAPI_Feature::group(), aFirst + theId);
+  int aRow = theNode->parent()->nodeRow(theNode);
+  return createIndex(aRow, 0, theNode);
 }
index e89546161dda5a6b3a564dcc0fe37741a607a222..477370cc6309fcc78249930dfcc1f7829da2399e 100644 (file)
@@ -31,6 +31,7 @@
 
 class Config_DataModelReader;
 class XGUI_Workshop;
+class ModuleBase_ITreeNode;
 
 /**\class XGUI_DataModel
  * \ingroup GUI
@@ -54,6 +55,11 @@ public:
   /// Destructor
   virtual ~XGUI_DataModel();
 
+
+  void setRoot(ModuleBase_ITreeNode* theRoot) { myRoot = theRoot; }
+
+  ModuleBase_ITreeNode* root() const { return myRoot; }
+
   /// Event Listener method
   /// \param theMessage an event message
   virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
@@ -72,7 +78,6 @@ public:
   //! Rebuild data tree
   virtual void rebuildDataTree();
 
-
   /// Returns the data stored under the given role for the item referred to by the index.
   /// \param theIndex a model index
   /// \param theRole a data role (see Qt::ItemDataRole)
@@ -134,10 +139,10 @@ public:
   QModelIndex documentRootIndex(DocumentPtr theDoc, int theColumn = 1) const;
 
   /// Returns last history object index
-  virtual QModelIndex lastHistoryIndex() const;
+  //virtual QModelIndex lastHistoryIndex() const;
 
   /// Initialises XML data model reader. It must be initialised before DataModel using.
-  void setXMLReader(Config_DataModelReader* theReader) { myXMLReader = theReader; }
+  //void setXMLReader(Config_DataModelReader* theReader) { myXMLReader = theReader; }
 
   /// Do not processing anymore events of model loop
   //bool blockEventsProcessing(const bool theState);
@@ -147,6 +152,10 @@ public:
   /// \return boolean value
   bool hasHiddenState(const QModelIndex& theIndex);
 
+  /// Returns true if the given index exists in data tree
+  /// \param theIndex an index to check
+  bool hasIndex(const QModelIndex& theIndex) const;
+
 signals:
   /// Signal about tree had been rebuilt
   void treeRebuilt();
@@ -158,69 +167,76 @@ private:
     SemiVisible,
     Hidden };
 
+
+  QModelIndex getParentIndex(ModuleBase_ITreeNode* theNode, int thCol) const;
+
+  QModelIndex getIndex(ModuleBase_ITreeNode* theNode, int thCol) const;
+
   /// Find a root index which contains objects of the given document
   /// \param theDoc the document object
-  QModelIndex findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn = 1) const;
+  //QModelIndex findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn = 1) const;
 
   /// Returns number of folders in document.
   /// Considered folders which has to be shown only if they are not empty.
   /// \param theDoc document which has to be checked. If 0 then Root document will be considered
-  int foldersCount(ModelAPI_Document* theDoc = 0) const;
+  //int foldersCount(ModelAPI_Document* theDoc = 0) const;
 
   /// Retrurns indexes of folders which can not be shown because they are empty
   /// \param theDoc document which has to be checked. If 0 then Root document will be considered
-  QIntList missedFolderIndexes(ModelAPI_Document* theDoc = 0) const;
+  //QIntList missedFolderIndexes(ModelAPI_Document* theDoc = 0) const;
 
   /// Returns Id (row) of a folder taking into consideration
   /// folders which can not be shown non empty
   /// \param theType Type of the folder
   /// \param theDoc a document which contains this folder
-  int folderId(std::string theType, ModelAPI_Document* theDoc = 0) const;
+  //int folderId(std::string theType, ModelAPI_Document* theDoc = 0) const;
 
   /// Removes a row from branch of tree
   /// \param theStart - start row to update indexes
   /// \param theSize - number of indexes in the folder
   /// \param theParent - index of parent folder
-  void rebuildBranch(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
+  //void rebuildBranch(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
 
   /// Returns list of folders types which can not be shown empty
   /// \param fromRoot - root document flag
-  QStringList listOfShowNotEmptyFolders(bool fromRoot = true) const;
-
-  int getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const;
-  ObjectPtr getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const;
-
-  VisibilityState getVisibilityState(const QModelIndex& theIndex) const;
-
-  void addShownFolder(DocumentPtr theDoc, QString theFolder)
-  {
-    if (!myShownFolders.contains(theDoc)) {
-      myShownFolders[theDoc] = QStringList();
-    }
-    myShownFolders[theDoc].append(theFolder);
-  }
-
-  void removeShownFolder(DocumentPtr theDoc, QString theFolder)
-  {
-    if (myShownFolders.contains(theDoc)) {
-      myShownFolders[theDoc].removeAll(theFolder);
-      if (myShownFolders[theDoc].isEmpty())
-        myShownFolders.remove(theDoc);
-    }
-  }
-
-  bool hasShownFolder(DocumentPtr theDoc, QString theFolder) const
-  {
-    if (myShownFolders.contains(theDoc))
-      return myShownFolders[theDoc].contains(theFolder);
-    return false;
-  }
-
-  Config_DataModelReader* myXMLReader;
+  //QStringList listOfShowNotEmptyFolders(bool fromRoot = true) const;
+
+  //int getNumberOfFolderItems(const ModelAPI_Folder* theFolder) const;
+  //ObjectPtr getObjectInFolder(const ModelAPI_Folder* theFolder, int theId) const;
+
+  //VisibilityState getVisibilityState(const QModelIndex& theIndex) const;
+
+  //void addShownFolder(DocumentPtr theDoc, QString theFolder)
+  //{
+  //  if (!myShownFolders.contains(theDoc)) {
+  //    myShownFolders[theDoc] = QStringList();
+  //  }
+  //  myShownFolders[theDoc].append(theFolder);
+  //}
+
+  //void removeShownFolder(DocumentPtr theDoc, QString theFolder)
+  //{
+  //  if (myShownFolders.contains(theDoc)) {
+  //    myShownFolders[theDoc].removeAll(theFolder);
+  //    if (myShownFolders[theDoc].isEmpty())
+  //      myShownFolders.remove(theDoc);
+  //  }
+  //}
+
+  //bool hasShownFolder(DocumentPtr theDoc, QString theFolder) const
+  //{
+  //  if (myShownFolders.contains(theDoc))
+  //    return myShownFolders[theDoc].contains(theFolder);
+  //  return false;
+  //}
+
+  //Config_DataModelReader* myXMLReader;
 
   XGUI_Workshop* myWorkshop;
   QMap<DocumentPtr, QStringList> myShownFolders;
   //bool myIsEventsProcessingBlocked;
+
+  ModuleBase_ITreeNode* myRoot;
 };
 
 #endif
\ No newline at end of file
index 4f2130509984d134c0c2bf2190fe2b48febe0670..5c67a3d5037b62d454236c5de5ec2b8b403b1c11 100644 (file)
@@ -109,6 +109,13 @@ AISObjectPtr XGUI_ModuleConnector::findPresentation(const ObjectPtr& theObject)
   return aDisp->getAISObject(theObject);
 }
 
+bool XGUI_ModuleConnector::isVisible(const ObjectPtr& theObject) const
+{
+  XGUI_Displayer* aDisp = myWorkshop->displayer();
+  return aDisp->isVisible(theObject);
+}
+
+
 ObjectPtr XGUI_ModuleConnector::findPresentedObject(const AISObjectPtr& theAIS) const
 {
   XGUI_Displayer* aDisp = myWorkshop->displayer();
index 6bf3914c29d3656eee583281953927fe99e97c4f..409c6edee4eb305688782e69a30dfc2afd0979bc 100644 (file)
@@ -94,6 +94,10 @@ Q_OBJECT
   //! Returns data object by AIS
   virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const;
 
+  //! Returns true if the object is displayed
+  //! \param theObject a data object
+  virtual bool isVisible(const ObjectPtr& theObject) const;
+
   //! Select features clearing previous selection.
   //! If the list is empty then selection will be cleared
   virtual void setSelected(const QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues);
index d256e56dba733e6704d73550683ba4d21846cb25..ab86347b5ce62bc98f1df65ce324a8eff8ad9770 100644 (file)
@@ -220,7 +220,6 @@ void XGUI_DataTree::processHistoryChange(const QModelIndex& theIndex)
     aDoc->setCurrentFeature(FeaturePtr(), true);
     aMgr->finishOperation();
   }
-  QModelIndex aNewIndex = aModel->lastHistoryIndex();
   QModelIndex aParent = theIndex.parent();
   int aSize = aModel->rowCount(aParent);
   for (int i = 0; i < aSize; i++) {
@@ -426,9 +425,10 @@ XGUI_ObjectsBrowser::~XGUI_ObjectsBrowser()
 {
 }
 
-void XGUI_ObjectsBrowser::setXMLReader(Config_DataModelReader* theReader)
+void XGUI_ObjectsBrowser::initialize(ModuleBase_ITreeNode* theRoot)
 {
-  myDocModel->setXMLReader(theReader);
+  //myDocModel->setXMLReader(theReader);
+  myDocModel->setRoot(theRoot);
   myTreeView->setModel(myDocModel);
 
   // It has to be done after setting of model
@@ -606,7 +606,8 @@ void XGUI_ObjectsBrowser::onBeforeReset()
 void XGUI_ObjectsBrowser::onAfterModelReset()
 {
   foreach(QModelIndex aIndex, myExpandedItems) {
-    myTreeView->setExpanded(aIndex, true);
+    if (myTreeView->dataModel()->hasIndex(aIndex))
+      myTreeView->setExpanded(aIndex, true);
   }
 }
 
@@ -646,9 +647,10 @@ void XGUI_ObjectsBrowser::updateAllIndexes(int theColumn, const QModelIndex& the
   int aNb = myDocModel->rowCount(theParent);
   for (int i = 0; i < aNb; i++) {
     QModelIndex aIdx = myDocModel->index(i, theColumn, theParent);
-    if (aIdx.isValid()) {
+    if (aIdx.isValid() && myDocModel->hasIndex(aIdx)) {
       myTreeView->update(aIdx);
-      updateAllIndexes(theColumn, aIdx);
+      if (myTreeView->isExpanded(aIdx))
+        updateAllIndexes(theColumn, aIdx);
     }
   }
 }
index f83ddfcadfc13583265d06c6036755b9ab053ab9..c0507306554db1acea9b123afedfcdf72bf7e576 100644 (file)
@@ -37,6 +37,7 @@ class ModuleBase_IDocumentDataModel;
 class XGUI_DataModel;
 class Config_DataModelReader;
 class XGUI_Workshop;
+class ModuleBase_ITreeNode;
 
 //#define DEBUG_INDXES
 
@@ -175,7 +176,10 @@ Q_OBJECT
   //! Returns currently selected indexes
   QModelIndexList selectedIndexes() const
   {
-    return myTreeView->selectionModel()->selectedIndexes();
+    if (myTreeView->selectionModel())
+      return myTreeView->selectionModel()->selectedIndexes();
+    else
+      return QModelIndexList();
   }
 
   //! Returns TreeView widget
@@ -193,9 +197,8 @@ Q_OBJECT
   /// Resets the object browser into initial state
   void clearContent();
 
-  /// Set XML reader object for data model
-  /// \param theReader the reader object
-  void setXMLReader(Config_DataModelReader* theReader);
+  /// Initialize the Object browser
+  void initialize(ModuleBase_ITreeNode* theRoot);
 
   /// Returns list of folders opened state for the given document
   /// \param theDoc the document
index 0a1b1570ca901a64d408103893edbf3050ec8f3b..9fe73219f76fd987f92830dbf102151eb320d52f 100755 (executable)
@@ -1310,7 +1310,7 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
   aObjDock->setStyleSheet(
       "::title { position: relative; padding-left: 5px; text-align: left center }");
   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock, this);
-  myObjectBrowser->setXMLReader(myDataModelXMLReader);
+  myObjectBrowser->initialize(myModule->rootNode());
   myModule->customizeObjectBrowser(myObjectBrowser);
   aObjDock->setWidget(myObjectBrowser);
 
@@ -1443,8 +1443,9 @@ void XGUI_Workshop::hidePanel(QDockWidget* theDockWidget)
 //******************************************************
 void XGUI_Workshop::showObjectBrowser()
 {
-  if (!isSalomeMode())
+  if (!isSalomeMode()) {
     myObjectBrowser->parentWidget()->show();
+  }
 }
 
 //******************************************************