From cad25bcd598bcadee23dacf41626b8c340ed3286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 13 May 2013 12:00:52 +0200 Subject: [PATCH] Caf:PdmUiTree: Rewrote rebuildUiSubTree to become updateUiSubTree Now the UI state is preserved when refreshing the tree, making it suitable to use this method more extensively. This paves the way to make changes to the Pdm data structure without considering the ui at all, until a call to updateUiSubTree gets the ui gracefully into sync. p4#: 21599 --- .../Application/RiaApplication.cpp | 2 +- .../ProjectDataModel/RimResultSlot.cpp | 4 +- .../ProjectDataModel/RimScriptCollection.cpp | 2 +- .../ProjectDataModel/RimStatisticsCase.cpp | 2 +- .../ProjectDataModel/RimUiTreeModelPdm.cpp | 4 +- .../SocketInterface/RiaSocketServer.cpp | 2 +- cafUserInterface/cafUiTreeItem.h | 49 ++++--- cafUserInterface/cafUiTreeModelPdm.cpp | 127 ++++++++++++------ cafUserInterface/cafUiTreeModelPdm.h | 10 +- 9 files changed, 125 insertions(+), 77 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index bfec67d2f6..2c9a09c52f 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1098,7 +1098,7 @@ void RiaApplication::applyPreferences() { this->project()->setScriptDirectories(m_preferences->scriptDirectories()); RimUiTreeModelPdm* treeModel = RiuMainWindow::instance()->uiPdmModel(); - if (treeModel) treeModel->rebuildUiSubTree(this->project()->scriptCollection()); + if (treeModel) treeModel->updateUiSubTree(this->project()->scriptCollection()); } } diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp index 41d8c625cf..6163f5b5e7 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp @@ -102,7 +102,7 @@ void RimResultSlot::changeLegendConfig(QString resultVarNameOfNewLegend) m_legendConfigData.v().erase(it); m_legendConfigData.v().push_back(this->legendConfig()); this->legendConfig = newLegend; - RiuMainWindow::instance()->uiPdmModel()->rebuildUiSubTree(this); + RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); found = true; break; } @@ -116,7 +116,7 @@ void RimResultSlot::changeLegendConfig(QString resultVarNameOfNewLegend) newLegend->resultVariableName = resultVarNameOfNewLegend; m_legendConfigData.v().push_back(this->legendConfig()); this->legendConfig = newLegend; - RiuMainWindow::instance()->uiPdmModel()->rebuildUiSubTree(this); + RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); } } diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index 05297be1bb..2e597e678e 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -174,7 +174,7 @@ void RimScriptCollection::fieldChangedByUi(const caf::PdmFieldHandle *changedFie this->setUiName(fi.baseName()); this->readContentFromDisc(); RimUiTreeModelPdm* treeModel = RiuMainWindow::instance()->uiPdmModel(); - if (treeModel) treeModel->rebuildUiSubTree(this); + if (treeModel) treeModel->updateUiSubTree(this); } } diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp index a864f220a8..4ca841b957 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp @@ -510,7 +510,7 @@ void RimStatisticsCase::setWellResultsAndUpdateViews(const cvf::CollectionwellCollection()->wells.deleteAllChildObjects(); reservoirView->updateDisplayModelForWellResults(); - treeModel->rebuildUiSubTree(reservoirView->wellCollection()); + treeModel->updateUiSubTree(reservoirView->wellCollection()); progInfo.incrementProgress(); } diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp index 3611926de0..44eb084893 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp @@ -459,7 +459,7 @@ void RimUiTreeModelPdm::slotRefreshScriptTree(QString path) if (changedSColl) { changedSColl->readContentFromDisc(); - this->rebuildUiSubTree(changedSColl); + this->updateUiSubTree(changedSColl); } } @@ -484,7 +484,7 @@ void RimUiTreeModelPdm::addInputProperty(const QModelIndex& itemIndex, const QSt inputReservoir->openDataFileSet(fileNames); } - this->rebuildUiSubTree(inputPropertyCollection); + this->updateUiSubTree(inputPropertyCollection); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/SocketInterface/RiaSocketServer.cpp b/ApplicationCode/SocketInterface/RiaSocketServer.cpp index abb3747f72..b0088309b0 100644 --- a/ApplicationCode/SocketInterface/RiaSocketServer.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketServer.cpp @@ -548,7 +548,7 @@ void RiaSocketServer::readPropertyDataFromOctave() inputProperty->fileName = ""; inputRes->m_inputPropertyCollection->inputProperties.push_back(inputProperty); RimUiTreeModelPdm* treeModel = RiuMainWindow::instance()->uiPdmModel(); - treeModel->rebuildUiSubTree(inputRes->m_inputPropertyCollection()); + treeModel->updateUiSubTree(inputRes->m_inputPropertyCollection()); } inputProperty->resolvedState = RimInputProperty::RESOLVED_NOT_SAVED; } diff --git a/cafUserInterface/cafUiTreeItem.h b/cafUserInterface/cafUiTreeItem.h index 60b3f2e6df..08382be5d8 100644 --- a/cafUserInterface/cafUiTreeItem.h +++ b/cafUserInterface/cafUiTreeItem.h @@ -28,7 +28,6 @@ namespace caf //================================================================================================== /// Class used to build a tree item holding a data object -/// Todo: Needs destructor !!! //================================================================================================== template class UiTreeItem @@ -98,23 +97,10 @@ public: child->m_parentItem = this; } - bool insertChildren(int position, int count) + void insertChild( int position, UiTreeItem* child) { - if (position < 0 || position > m_childItems.size()) - return false; - - for (int row = 0; row < count; ++row) - { - createChild(this, position + row); - } - - return true; - } - - // Create a new Ui tree item at given position pointing to a NULL data object - virtual UiTreeItem* createChild(UiTreeItem* parent, int position) - { - return new UiTreeItem(this, position, NULL); + m_childItems.insert(position, child); + child->m_parentItem = this; } bool removeChildren(int position, int count) @@ -132,27 +118,40 @@ public: return true; } + bool removeChildrenNoDelete(int position, int count) + { + if (position < 0 || position + count > m_childItems.size()) + return false; + + for (int row = 0; row < count; ++row) + { + m_childItems.removeAt(position); + } + return true; + } + void removeAllChildrenNoDelete() { m_childItems.clear(); } - UiTreeItem* findUiItem(const T& dataObject) + // Returns the index of the first child with dataObject() == dataObject. -1 if not found + int findChildItemIndex(const T& dataObject) { - if (m_dataObject == dataObject) return this; - int i; - for (i = 0; i < m_childItems.size(); ++i) + for (int i = 0; i < m_childItems.size(); ++i) { - UiTreeItem* itemFound = m_childItems[i]->findUiItem(dataObject); - if (itemFound != NULL) return itemFound; + if (m_childItems[i]->dataObject() == dataObject) + { + return i; + } } - return NULL; + return -1; } private: QList m_childItems; UiTreeItem* m_parentItem; - T m_dataObject; + T m_dataObject; }; diff --git a/cafUserInterface/cafUiTreeModelPdm.cpp b/cafUserInterface/cafUiTreeModelPdm.cpp index 40e652fa48..c595c64e92 100644 --- a/cafUserInterface/cafUiTreeModelPdm.cpp +++ b/cafUserInterface/cafUiTreeModelPdm.cpp @@ -332,28 +332,12 @@ Qt::ItemFlags UiTreeModelPdm::flags(const QModelIndex &index) const return flagMask; } -//-------------------------------------------------------------------------------------------------- -/// TO BE DELETED -//-------------------------------------------------------------------------------------------------- -bool UiTreeModelPdm::insertRows_special(int position, int rows, const QModelIndex &parent /*= QModelIndex()*/) -{ - PdmUiTreeItem* parentItem = getTreeItemFromIndex(parent); - - bool success; - - beginInsertRows(parent, position, position + rows - 1); - success = parentItem->insertChildren(position, rows); - endInsertRows(); - - return success; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool UiTreeModelPdm::removeRows_special(int position, int rows, const QModelIndex &parent /*= QModelIndex()*/) +bool UiTreeModelPdm::removeRows_special(int position, int count, const QModelIndex &parent /*= QModelIndex()*/) { - if (rows <= 0) return true; + if (count <= 0) return true; PdmUiTreeItem* parentItem = NULL; if (parent.isValid()) @@ -369,38 +353,105 @@ bool UiTreeModelPdm::removeRows_special(int position, int rows, const QModelInde bool success = true; - beginRemoveRows(parent, position, position + rows - 1); - success = parentItem->removeChildren(position, rows); + beginRemoveRows(parent, position, position + count - 1); + success = parentItem->removeChildren(position, count); endRemoveRows(); return success; } //-------------------------------------------------------------------------------------------------- -/// +/// Refreshes the UI-tree below the supplied root PdmObject //-------------------------------------------------------------------------------------------------- -void UiTreeModelPdm::rebuildUiSubTree(PdmObject* root) +void UiTreeModelPdm::updateUiSubTree(PdmObject* pdmRoot) { - QModelIndex item = getModelIndexFromPdmObject(root); - if (item.isValid()) + // Build the new "Correct" Tree + + PdmUiTreeItem* tempUpdatedPdmTree = UiTreeItemBuilderPdm::buildViewItems(NULL, -1, pdmRoot); + + // Find the corresponding entry for "root" in the existing Ui tree + + QModelIndex uiSubTreeRootModelIdx = getModelIndexFromPdmObject(pdmRoot); + + PdmUiTreeItem* uiModelSubTreeRoot = NULL; + if (uiSubTreeRootModelIdx.isValid()) { - this->removeRows_special(0, rowCount(item), item); - PdmUiTreeItem* treeItem = getTreeItemFromIndex(item); - - - PdmUiTreeItem* fakeRoot = UiTreeItemBuilderPdm::buildViewItems(NULL, -1, root); - - this->beginInsertRows(item, 0, fakeRoot->childCount()); - for(int i = 0; i < fakeRoot->childCount(); ++i) - { - treeItem->appendChild(fakeRoot->child(i)); - } - this->endInsertRows(); - fakeRoot->removeAllChildrenNoDelete(); - delete fakeRoot; + uiModelSubTreeRoot = getTreeItemFromIndex(uiSubTreeRootModelIdx); } + else + { + uiModelSubTreeRoot = m_treeItemRoot; + } + + + updateModelSubTree(uiSubTreeRootModelIdx, uiModelSubTreeRoot, tempUpdatedPdmTree); + + delete tempUpdatedPdmTree; } +//-------------------------------------------------------------------------------------------------- +/// Makes the olUiTreeRoot tree become identical to the tree in newUiTreeRoot, +/// calling begin..() end..() to make the UI update accordingly. +/// This assumes that all the items have a pointer an unique PdmObject +//-------------------------------------------------------------------------------------------------- +void UiTreeModelPdm::updateModelSubTree(const QModelIndex& uiSubTreeRootModelIdx, PdmUiTreeItem* uiModelSubTreeRoot, PdmUiTreeItem* updatedPdmSubTreeRoot) +{ + // First loop over children in the old ui tree, deleting the ones not present in + // the newUiTree + + for (int i = 0; i < uiModelSubTreeRoot->childCount() ; ++i) + { + PdmUiTreeItem* oldChild = uiModelSubTreeRoot->child(i); + int childIndex = updatedPdmSubTreeRoot->findChildItemIndex(oldChild->dataObject()); + + if (childIndex == -1) // Not found + { + this->beginRemoveRows(uiSubTreeRootModelIdx, i, i); + uiModelSubTreeRoot->removeChildren(i, 1); + this->endRemoveRows(); + i--; + } + } + + // Then loop over the children in the new ui tree, finding the corresponding items in the old tree. + // If they are found, we move them to the correct position. + // If not found, we pulls the item out of the old ui tree, inserting it into the old tree. + + for (int i = 0; i < updatedPdmSubTreeRoot->childCount() ; ++i) + { + PdmUiTreeItem* newChild = updatedPdmSubTreeRoot->child(i); + int childIndex = uiModelSubTreeRoot->findChildItemIndex(newChild->dataObject()); + + if (childIndex == -1) // Not found + { + this->beginInsertRows(uiSubTreeRootModelIdx, i, i); + uiModelSubTreeRoot->insertChild(i, newChild); + this->endInsertRows(); + updatedPdmSubTreeRoot->removeChildrenNoDelete(i, 1); + i--; + } + else if (childIndex != i) // Found, but must be moved + { + assert(childIndex > i); + + PdmUiTreeItem* oldChild = uiModelSubTreeRoot->child(childIndex); + this->beginMoveRows(uiSubTreeRootModelIdx, childIndex, childIndex, uiSubTreeRootModelIdx, i); + uiModelSubTreeRoot->removeChildrenNoDelete(childIndex, 1); + uiModelSubTreeRoot->insertChild(i, oldChild); + this->endMoveRows(); + updateModelSubTree( index(i, 0, uiSubTreeRootModelIdx) ,oldChild, newChild); + } + else // Found the corresponding item in the right place. + { + PdmUiTreeItem* oldChild = uiModelSubTreeRoot->child(childIndex); + updateModelSubTree( index(i, 0, uiSubTreeRootModelIdx) ,oldChild, newChild); + } + } + + +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/cafUserInterface/cafUiTreeModelPdm.h b/cafUserInterface/cafUiTreeModelPdm.h index 5609937543..94354d3d84 100644 --- a/cafUserInterface/cafUiTreeModelPdm.h +++ b/cafUserInterface/cafUiTreeModelPdm.h @@ -50,7 +50,7 @@ public: static PdmUiTreeItem* getTreeItemFromIndex(const QModelIndex& index); QModelIndex getModelIndexFromPdmObject(const PdmObject* object) const; - void rebuildUiSubTree(PdmObject* root); + void updateUiSubTree(PdmObject* root); public: // Overrides from QAbstractItemModel @@ -63,16 +63,14 @@ public: virtual Qt::ItemFlags flags(const QModelIndex &index) const; virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - // TO BE DELETED, NOT USED - virtual bool insertRows_special(int position, int rows, const QModelIndex &parent = QModelIndex()); - virtual bool removeRows_special(int position, int rows, const QModelIndex &parent = QModelIndex()); protected: QModelIndex getModelIndexFromPdmObjectRecursive(const QModelIndex& currentIndex, const PdmObject * object) const; - private: - PdmUiTreeItem* m_treeItemRoot; + void updateModelSubTree(const QModelIndex& uiSubTreeRootModelIdx, PdmUiTreeItem* uiModelSubTreeRoot, PdmUiTreeItem* updatedPdmSubTreeRoot); + + PdmUiTreeItem* m_treeItemRoot; };