Salome HOME
Fix for the issue #910: never fully remove the results, just make them disabled when...
[modules/shaper.git] / src / PartSet / PartSet_DocumentDataModel.cpp
index 2041d5cb0739a3e0815e7ad7837ebb2423dc42cb..84ac7a1697ea1820628022c43d0111c696a38c67 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "PartSet_DocumentDataModel.h"
 #include "PartSet_PartDataModel.h"
+#include "PartSet_TopDataModel.h"
 #include "PartSet_Module.h"
 //#include "XGUI_Tools.h"
 
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_ActionInfo.h>
 
+#include <PartSetPlugin_Part.h>
+
 #include <QIcon>
 #include <QString>
 #include <QBrush>
+#include <QTreeView>
 
 #include <set>
 
@@ -33,7 +37,7 @@ QMap<QString, QString> PartSet_DocumentDataModel::myIcons;
 
 PartSet_DocumentDataModel::PartSet_DocumentDataModel(QObject* theParent)
     : ModuleBase_IDocumentDataModel(theParent),
-      myActivePart(0), myHistoryBackOffset(0)
+      myActivePartModel(0)
 {
   // Create a top part of data tree model
   myModel = new PartSet_TopDataModel(this);
@@ -56,6 +60,7 @@ void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Messag
 {
   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
 
+
   // Created object event *******************
   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
@@ -73,11 +78,15 @@ void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Messag
       if (aDoc == aRootDoc) {  // If root objects
         if (aObject->groupName() == ModelAPI_ResultPart::group()) {  // Update only Parts group
             // Add a new part
-          int aStart = myPartModels.size();
-          PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
-          aModel->setPartId(myPartModels.count());
-          myPartModels.append(aModel);
-          insertRow(aStart, partFolderNode(0));
+          int aStart = aRootDoc->size(ModelAPI_ResultPart::group());
+          if (aStart > 0) {
+            FeaturePtr aPartFeature = ModelAPI_Feature::feature(aObject);
+            PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
+            int anId = aRootDoc->index(aPartFeature);
+            aModel->setPart(aPartFeature);
+            myPartModels.append(aModel);
+            insertRow(aStart, partFolderNode(0));
+          }
         } else {  // Update top groups (other except parts
           QModelIndex aIndex = myModel->findParent(aObject);
           int aStart = myModel->rowCount(aIndex) - 1;
@@ -115,16 +124,22 @@ void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Messag
       std::string aGroup = (*aIt);
       if (aDoc == aRootDoc) {  // If root objects
         if (aGroup == ModelAPI_ResultPart::group()) {  // Update only Parts group
-          int aStart = myPartModels.size() - 1;
-          if (aStart >= 0) {// MPV: this could be reproduced on close
-            removeSubModel(aStart);
-            removeRow(aStart, partFolderNode(0));
-            if (myActivePart && (!isPartSubModel(myActivePart))) {
-              myActivePart = 0;
-              myActivePartIndex = QModelIndex();
-              myModel->setItemsColor(ACTIVE_COLOR);
+          PartSet_PartModel* aDelPartModel = 0;
+          foreach (PartSet_PartModel* aPartModel, myPartModels) {
+            if (aPartModel->position() == -1) {
+              aDelPartModel = aPartModel;
+              break;
             }
           }
+          if (aDelPartModel) {
+            deactivatePart();
+            int aStart = myPartModels.size() - 1;
+            removeSubModel(aDelPartModel);
+            removeRow(aStart, partFolderNode(0));
+          }
+        } if (aGroup == ModelAPI_Feature::group()) { // Update History node
+          int aRow = historyOffset() + aRootDoc->size(ModelAPI_Feature::group());
+          removeRow(aRow);
         } else {  // Update top groups (other except parts
           QModelIndex aIndex = myModel->findGroup(aGroup);
           int aStart = myModel->rowCount(aIndex);
@@ -141,9 +156,15 @@ void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Messag
         }
         if (aPartModel) {
           QModelIndex aIndex = aPartModel->findGroup(aGroup);
-          int aStart = aPartModel->rowCount(aIndex);
-          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
-          removeRow(aStart, aIndex);
+          if (aIndex.isValid()) {
+            int aStart = aPartModel->rowCount(aIndex);
+            aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+            removeRow(aStart, aIndex);
+          } else {
+            int aRow = aPartModel->rowCount();
+            aIndex = createIndex(aPartModel->position() + historyOffset(), 0, HistoryNode);
+            removeRow(aRow, aIndex);
+          }
         }
       }
     }
@@ -179,17 +200,29 @@ void PartSet_DocumentDataModel::rebuildDataTree()
   beginResetModel();
   clearModelIndexes();
 
-  int aNbParts = aRootDoc->size(ModelAPI_ResultPart::group());
-  if (myPartModels.size() != aNbParts) {  // resize internal models
-    while (myPartModels.size() > aNbParts) {
-      delete myPartModels.last();
-      myPartModels.removeLast();
-    }
-    while (myPartModels.size() < aNbParts) {
-      myPartModels.append(new PartSet_PartDataModel(this));
+  // Delete extra models
+  ObjectPtr aObj;
+  FeaturePtr aFeature;
+  QList<PartSet_PartModel*> aDelList;
+  foreach (PartSet_PartModel* aPartModel, myPartModels) {
+    if (aPartModel->position() == -1) 
+      aDelList.append(aPartModel);
+  }
+  foreach (PartSet_PartModel* aPartModel, aDelList) {
+    removeSubModel(aPartModel);
+  }
+  // Add non existing models
+  int aHistNb = aRootDoc->size(ModelAPI_Feature::group());
+  for (int i = 0; i < aHistNb; i++) {
+    aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
+    aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+    if (aFeature->getKind() == PartSetPlugin_Part::ID()) {
+      if (!findPartModel(aFeature)) {
+        PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
+        aModel->setPart(aFeature);
+        myPartModels.append(aModel);
+      }
     }
-    for (int i = 0; i < myPartModels.size(); i++)
-      myPartModels.at(i)->setPartId(i);
   }
   endResetModel();
 }
@@ -198,14 +231,25 @@ QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRol
 {
   if (!theIndex.isValid())
     return QVariant();
-  QModelIndex aParent = theIndex.parent();
 
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  QModelIndex aParent = theIndex.parent();
   if ((theIndex.column() == 1) ) {
-    if ((theIndex.internalId() == HistoryNode) && (!aParent.isValid())) {
-      switch (theRole) {
-      case Qt::DecorationRole:
-        if (theIndex.row() == lastHistoryRow())
-          return QIcon(":pictures/arrow.png");
+    if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+      if (ModelAPI_Session::get()->activeDocument() == aRootDoc) {
+        if (!aParent.isValid()) {
+          switch (theRole) {
+          case Qt::DecorationRole:
+            if (theIndex.row() == lastHistoryRow())
+              return QIcon(":pictures/arrow.png");
+          }
+        }
+      }
+    } else {
+      QModelIndex* aIndex = toSourceModelIndex(theIndex);
+      const QAbstractItemModel* aModel = aIndex->model();
+      if (isPartSubModel(aModel)) {
+        return aModel->data(*aIndex, theRole);
       }
     }
     return QVariant();
@@ -221,7 +265,7 @@ QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRol
         case Qt::ToolTipRole:
           return tr("Parts folder");
         case Qt::ForegroundRole:
-          if (myActivePart)
+          if (myActivePartIndex.isValid())
               return QBrush(PASSIVE_COLOR);
             else
               return QBrush(ACTIVE_COLOR);
@@ -232,7 +276,6 @@ QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRol
     case HistoryNode:
       {
         int aOffset = historyOffset();
-        DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
         ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
         FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
         if (!aFeature)
@@ -246,12 +289,25 @@ QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRol
           case Qt::DecorationRole:
             return featureIcon(aFeature);
           case Qt::ToolTipRole:
-            return tr("Feature object");
+            {
+              ResultPtr aResult = aFeature->firstResult();
+              bool isResultAndNotLoaded = false;
+              if( aResult.get() )
+              {
+                ResultPartPtr aResultPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>( aResult );
+                if( aResultPart.get() )
+                  isResultAndNotLoaded = !aResultPart->isActivated();
+              }
+              if( isResultAndNotLoaded )
+                return tr( "The part should be activated before the user may edit it" );
+              else
+                return tr( "Feature object" );
+            }
           case Qt::ForegroundRole:
             if (theIndex.row() > lastHistoryRow())
               return QBrush(Qt::lightGray);
             else {
-              if (myActivePart)
+              if (myActivePartIndex.isValid())
                 return QBrush(PASSIVE_COLOR);
               else
                 return QBrush(ACTIVE_COLOR);
@@ -261,9 +317,33 @@ QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRol
         }
       }
       break;
+    case PartResult:
+      {
+        ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
+        if (aObject) {
+          switch (theRole) {
+            case Qt::DisplayRole:
+              return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
+            case Qt::DecorationRole:
+              return QIcon(":pictures/part_ico.png");
+            case Qt::ForegroundRole:
+              {
+                if (theIndex == myActivePartIndex)
+                  return QBrush(ACTIVE_COLOR);
+                else
+                  return QBrush(PASSIVE_COLOR);
+              }
+            default:
+              return QVariant();
+          }
+        }
+      }
+      break;
   }
-  if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
-    return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
+  if (aParent.internalId() == HistoryNode) {
+    int aId = aParent.row() - historyOffset();
+    QModelIndex* aIndex = toSourceModelIndex(theIndex);
+    return findPartModel(aId)->data(*aIndex, theRole);
   }
   return toSourceModelIndex(theIndex)->data(theRole);
 }
@@ -276,8 +356,11 @@ QVariant PartSet_DocumentDataModel::headerData(int theSection, Qt::Orientation t
 
 int PartSet_DocumentDataModel::rowCount(const QModelIndex& theParent) const
 {
+  SessionPtr aSession = ModelAPI_Session::get();
+  if (!aSession->hasModuleDocument())
+    return 0;
+  DocumentPtr aRootDoc = aSession->moduleDocument();
   if (!theParent.isValid()) {
-    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
     // Size of external models
     int aVal = historyOffset();
     // Plus history size
@@ -285,12 +368,20 @@ int PartSet_DocumentDataModel::rowCount(const QModelIndex& theParent) const
     return aVal;
   }
   if (theParent.internalId() == PartsFolder) {
-    int aSize = myPartModels.size();
-    return myPartModels.size();
+    return aRootDoc->size(ModelAPI_ResultPart::group());
+    //int aSize = myPartModels.size();
+    //return myPartModels.size();
   }
   if (theParent.internalId() == HistoryNode) {
+    int aId = theParent.row() - historyOffset();
+    PartSet_PartModel* aModel = findPartModel(aId);
+    if (aModel)
+      return aModel->rowCount(QModelIndex());
     return 0;
   }
+  if (theParent.internalId() == PartResult)
+    return 0;
   QModelIndex* aParent = toSourceModelIndex(theParent);
   const QAbstractItemModel* aModel = aParent->model();
   if (!isSubModel(aModel))
@@ -305,7 +396,7 @@ int PartSet_DocumentDataModel::rowCount(const QModelIndex& theParent) const
 
 int PartSet_DocumentDataModel::columnCount(const QModelIndex& theParent) const
 {
-  return 1;
+  return 2;
 }
 
 QModelIndex PartSet_DocumentDataModel::index(int theRow, int theColumn,
@@ -320,18 +411,24 @@ QModelIndex PartSet_DocumentDataModel::index(int theRow, int theColumn,
     } else {
       if (theRow == aOffs)  // Create Parts node
         aIndex = partFolderNode(theColumn);
-      else
+      else {
         // create history node
         aIndex = createIndex(theRow, theColumn, HistoryNode);
+      }
     }
   } else {
     if (theParent.internalId() == PartsFolder) {
-      aIndex = myPartModels.at(theRow)->index(0, theColumn, QModelIndex());
-    } else {
-      QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
-      aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
+       aIndex = createIndex(theRow, theColumn, PartResult);
+    } else { 
+      if (theParent.internalId() == HistoryNode) {
+        int aId = theParent.row() - historyOffset();
+        aIndex = findPartModel(aId)->index(theRow, theColumn, QModelIndex());
+      } else {
+        QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
+        aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
+      }
+      aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
     }
-    aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
   }
   return aIndex;
 }
@@ -341,20 +438,24 @@ QModelIndex PartSet_DocumentDataModel::parent(const QModelIndex& theIndex) const
   if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
     return QModelIndex();
 
+  if (theIndex.internalId() == PartResult)
+    return partFolderNode(0);
+
   QModelIndex* aIndex = toSourceModelIndex(theIndex);
   const QAbstractItemModel* aModel = aIndex->model();
   if (!isSubModel(aModel))
     return QModelIndex();
 
-  if (isPartSubModel(aModel)) {
-    if (!aModel->parent(*aIndex).isValid()) {
-      return partFolderNode(theIndex.column());
-    }
+  QModelIndex aIndex1 = aModel->parent(*aIndex);
+  const PartSet_PartModel* aPartModel = dynamic_cast<const PartSet_PartModel*>(aModel);
+  if (aPartModel && (!aIndex1.isValid())) {
+    int aId = aPartModel->position();
+    int aRow = aId + historyOffset();
+    return createIndex(aRow, 0, (qint32) HistoryNode);
   }
 
-  QModelIndex aIndex1 = aModel->parent(*aIndex);
   if (aIndex1.isValid())
-    return createIndex(aIndex1.row(), aIndex1.column(), (void*) getModelIndex(aIndex1));
+    return createIndex(aIndex1.row(), 0, (void*) getModelIndex(aIndex1));
   return aIndex1;
 }
 
@@ -405,17 +506,21 @@ void PartSet_DocumentDataModel::clearSubModels()
   foreach (PartSet_PartModel* aPart, myPartModels) 
     delete aPart;
   myPartModels.clear();
+  myActivePartModel = 0;
 }
 
 ObjectPtr PartSet_DocumentDataModel::object(const QModelIndex& theIndex) const
 {
   if (theIndex.internalId() == PartsFolder)
     return ObjectPtr();
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
   if (theIndex.internalId() == HistoryNode) {
-    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
     int aOffset = historyOffset();
     return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
   }
+  if (theIndex.internalId() == PartResult) {
+    return aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
+  }
   QModelIndex* aIndex = toSourceModelIndex(theIndex);
   if (!isSubModel(aIndex->model()))
     return ObjectPtr();
@@ -448,9 +553,14 @@ bool PartSet_DocumentDataModel::removeRows(int theRow, int theCount, const QMode
 void PartSet_DocumentDataModel::removeSubModel(int theModelId)
 {
   PartSet_PartModel* aModel = myPartModels.at(theModelId);
+  removeSubModel(aModel);
+}
+
+void PartSet_DocumentDataModel::removeSubModel(PartSet_PartModel* theModel)
+{
   QIntList aToRemove;
   for (int i = 0; i < myIndexes.size(); i++) {
-    if (myIndexes.at(i)->model() == aModel)
+    if (myIndexes.at(i)->model() == theModel)
       aToRemove.append(i);
   }
   int aId;
@@ -460,10 +570,13 @@ void PartSet_DocumentDataModel::removeSubModel(int theModelId)
     myIndexes.removeAt(aId);
     aToRemove.removeLast();
   }
-  delete aModel;
-  myPartModels.removeAt(theModelId);
+  if (theModel == myActivePartModel)
+    myActivePartModel = 0;
+  myPartModels.removeAll(theModel);
+  delete theModel;
 }
 
+
 bool PartSet_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
 {
   if (theModel == myModel)
@@ -493,81 +606,86 @@ bool PartSet_DocumentDataModel::activatePart(const QModelIndex& theIndex)
   if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
     return false;
 
-  QModelIndex* aIndex = toSourceModelIndex(theIndex);
-  if (!aIndex)
-    return false;
-
-  const QAbstractItemModel* aModel = aIndex->model();
-
-  if (isPartSubModel(aModel)) {
-    // if this is root node (Part item index)
-    if (!aIndex->parent().isValid()) {
-      if (myActivePart)
-        myActivePart->setItemsColor(PASSIVE_COLOR);
-
-        if (myActivePart == aModel) {
-          myActivePart = 0;
-          myActivePartIndex = QModelIndex();
-        } else {
-          myActivePart = (PartSet_PartModel*)aModel;
-          myActivePartIndex = theIndex;
-        }
-
-        if (myActivePart) {
-          myActivePart->setItemsColor(ACTIVE_COLOR);
-          myModel->setItemsColor(PASSIVE_COLOR);
-        } else
-          myModel->setItemsColor(ACTIVE_COLOR);
-        return true;
-      }
+  if (theIndex.isValid() && (theIndex.internalId() == PartResult)) {
+    myActivePartIndex = theIndex;
+    myModel->setItemsColor(PASSIVE_COLOR);
+    if (myActivePartModel) 
+      myActivePartModel->setItemsColor(PASSIVE_COLOR);
+    
+    // Find activated part feature by its ID
+    ResultPartPtr aPartRes = activePart();
+    FeaturePtr aFeature = ModelAPI_Feature::feature(aPartRes);
+    if (aFeature.get()) {
+      myActivePartModel = findPartModel(aFeature);
+      myActivePartModel->setItemsColor(ACTIVE_COLOR);
     }
-  return false;
+  } 
+  return true;
 }
 
 ResultPartPtr PartSet_DocumentDataModel::activePart() const
 {
-  if (myActivePart)
-    return myActivePart->part();
+  if (myActivePartIndex.isValid()) {
+    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+    ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myActivePartIndex.row());
+    return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+  }
   return ResultPartPtr();
 }
 
+QModelIndex PartSet_DocumentDataModel::activePartTree() const
+{
+  if (myActivePartModel) {
+    return createIndex(myActivePartModel->position() + historyOffset(), 0, HistoryNode);
+  }
+  return QModelIndex();
+}
+
 void PartSet_DocumentDataModel::deactivatePart()
 {
-  if (myActivePart)
-    myActivePart->setItemsColor(PASSIVE_COLOR);
-    myActivePart = 0;
+  if (myActivePartIndex.isValid()) {
+    if (myActivePartModel) 
+      myActivePartModel->setItemsColor(PASSIVE_COLOR);
+    myActivePartModel = 0;
     myActivePartIndex = QModelIndex();
     myModel->setItemsColor(ACTIVE_COLOR);
   }
+}
 
 Qt::ItemFlags PartSet_DocumentDataModel::flags(const QModelIndex& theIndex) const
 {
-  Qt::ItemFlags aFlags = QAbstractItemModel::flags(theIndex); //Qt::ItemIsSelectable; 
-  if (object(theIndex)) {
-    aFlags |= Qt::ItemIsEditable;
+  if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+    Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
+    if (object(theIndex).get()) {
+      aFlags |= Qt::ItemIsEditable;
+    }
+    // Disable items which are below of last history row
+    // Do not disable second column
+    if (theIndex.internalId() == HistoryNode) {
+      if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
+        aFlags |= Qt::ItemIsEnabled;
+    } else
+      aFlags |= Qt::ItemIsEnabled;
+    return aFlags;
+  } else {
+    QModelIndex* aIndex = toSourceModelIndex(theIndex);
+    const QAbstractItemModel* aModel = aIndex->model();
+    Qt::ItemFlags aFlags = aModel->flags(*aIndex);
+    if (aModel == myModel) {
+      if (myModel->object(*aIndex).get())
+        aFlags |= Qt::ItemIsEditable;
+    }
+    return aFlags;
   }
-  // Disable items which are below of last history row
-  // Do not disable second column
-  //if (theIndex.row() <= lastHistoryRow() || theIndex.column() == 1) {
-  //  aFlags |= Qt::ItemIsEnabled;
-  //}
-  return aFlags;
 }
 
 QModelIndex PartSet_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
 {
-  int aRow = -1;
-  PartSet_PartModel* aModel = 0;
-  foreach (PartSet_PartModel* aPartModel, myPartModels)
-  {
-    aRow++;
-    if (aPartModel->part() == theObject) {
-      aModel = aPartModel;
-      break;
-    }
-  }
-  if (aModel) {
-    return createIndex(aRow, 0, (void*) getModelIndex(aModel->index(0, 0, QModelIndex())));
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
+  for (int aId = 0; aId < aNb; aId++) {
+    if (theObject == aRootDoc->object(ModelAPI_ResultPart::group(), aId))
+      return createIndex(aId, 0, PartResult);
   }
   return QModelIndex();
 }
@@ -593,13 +711,12 @@ QModelIndex PartSet_DocumentDataModel::objectIndex(const ObjectPtr theObject) co
       QModelIndex aIndex = myModel->objectIndex(theObject);
       return
           aIndex.isValid() ?
-              createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex)) :
+              createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
               QModelIndex();
     }
   } else {
     PartSet_PartModel* aPartModel = 0;
-    foreach(PartSet_PartModel* aModel, myPartModels)
-    {
+    foreach(PartSet_PartModel* aModel, myPartModels) {
       if (aModel->hasDocument(aDoc)) {
         aPartModel = aModel;
         break;
@@ -607,9 +724,8 @@ QModelIndex PartSet_DocumentDataModel::objectIndex(const ObjectPtr theObject) co
     }
     if (aPartModel) {
       QModelIndex aIndex = aPartModel->objectIndex(theObject);
-      return
-          aIndex.isValid() ?
-              createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex)) :
+      return aIndex.isValid() ?
+              createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
               QModelIndex();
     }
   }
@@ -621,20 +737,35 @@ void PartSet_DocumentDataModel::clear()
 {
   clearModelIndexes();
   clearSubModels();
-  myActivePart = 0;
+  //myActivePart = 0;
   myActivePartIndex = QModelIndex();
   myModel->setItemsColor(ACTIVE_COLOR);
 }
 
 int PartSet_DocumentDataModel::lastHistoryRow() const
 {
-  return rowCount() - 1 - myHistoryBackOffset;
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  FeaturePtr aFeature = aRootDoc->currentFeature(true);
+  if (aFeature.get())
+    return historyOffset() + aRootDoc->index(aFeature);
+  else 
+    return historyOffset() - 1;
 }
 
 void PartSet_DocumentDataModel::setLastHistoryItem(const QModelIndex& theIndex)
 {
+  SessionPtr aMgr = ModelAPI_Session::get();
+  DocumentPtr aRootDoc = aMgr->moduleDocument();
+  std::string aOpName = tr("History change").toStdString();
   if (theIndex.internalId() == HistoryNode) {
-    myHistoryBackOffset = rowCount() - 1 - theIndex.row();
+    ObjectPtr aObject = object(theIndex);
+    aMgr->startOperation(aOpName);
+    aRootDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
+    aMgr->finishOperation();
+  } else {
+    aMgr->startOperation(aOpName);
+    aRootDoc->setCurrentFeature(FeaturePtr(), true);
+    aMgr->finishOperation();
   }
 }
 
@@ -680,3 +811,66 @@ QIcon PartSet_DocumentDataModel::featureIcon(const FeaturePtr& theFeature)
   return anIcon;  
 }
 
+void PartSet_DocumentDataModel::onMouseDoubleClick(const QModelIndex& theIndex)
+{
+  if (theIndex.column() != 1)
+    return;
+  if (flags(theIndex) == 0)
+    return;
+  QTreeView* aTreeView = dynamic_cast<QTreeView*>(sender());
+  if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+    if (myActivePartModel)
+      // It means that the root document is not active
+      return;
+    QModelIndex aNewIndex;
+    if (theIndex.internalId() == HistoryNode) 
+      aNewIndex = theIndex;
+    int aOldId = lastHistoryRow();
+    setLastHistoryItem(theIndex);
+    int aStartRow = std::min(aOldId, theIndex.row());
+    int aEndRow = std::max(aOldId, theIndex.row());
+    for (int i = aStartRow; i <= aEndRow; i++) {
+      aTreeView->update(createIndex(i, 0, HistoryNode));
+      aTreeView->update(createIndex(i, 1, HistoryNode));
+    }
+    
+  } else {
+    QModelIndex* aIndex = toSourceModelIndex(theIndex);
+    const QAbstractItemModel* aModel = aIndex->model();
+    if (isPartSubModel(aModel)) {
+      PartSet_PartDataModel* aPartModel = (PartSet_PartDataModel*)aModel;
+      QModelIndex aOldItem = aPartModel->lastHistoryItem();
+      aPartModel->setLastHistoryItem(*aIndex);
+      QModelIndex aOldIndex = createIndex(aOldItem.row(), aOldItem.column(), (void*) getModelIndex(aOldItem));
+      int aStartRow = std::min(aOldItem.row(), aIndex->row());
+      int aEndRow = std::max(aOldItem.row(), aIndex->row());
+      for (int i = aStartRow; i <= aEndRow; i++) {
+        QModelIndex aInd1 = aPartModel->index(i, 0);
+        QModelIndex aInd2 = createIndex(i, 0, (void*) getModelIndex(aInd1));
+        aTreeView->update(aInd2);
+        aInd1 = aPartModel->index(i, 1);
+        aInd2 = createIndex(i, 1, (void*) getModelIndex(aInd1));
+        aTreeView->update(aInd2);
+      }
+    }
+  }
+} 
+
+
+PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(FeaturePtr thePart) const
+{
+  foreach (PartSet_PartModel* aModel, myPartModels) {
+    if (aModel->part() == thePart)
+      return aModel;
+  }
+  return 0;
+}
+
+PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(int thePosition) const
+{
+  foreach (PartSet_PartModel* aModel, myPartModels) {
+    if (aModel->position() == thePosition)
+      return aModel;
+  }
+  return 0;
+}
\ No newline at end of file