From bdfe5fd14f9be4c75b54f90247595d93a9f499ea Mon Sep 17 00:00:00 2001 From: Andras Lasso Date: Wed, 9 Oct 2013 18:31:29 -0400 Subject: [PATCH] ENH: Don't batch process when show/hide only a few child nodes When there are many child nodes in a hierarchy then show/hide is much more efficient if batch processing is enabled. However, if there are few nodes only then a full refresh at the end of a batch processing takes longer than doing the update on each node separately. Count the number of child nodes and if there are less than 30 then update each node separately. --- Libs/MRML/Widgets/qMRMLTreeView.cxx | 51 +++++++++++++++++++++++++++-- Libs/MRML/Widgets/qMRMLTreeView_p.h | 6 ++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/Libs/MRML/Widgets/qMRMLTreeView.cxx b/Libs/MRML/Widgets/qMRMLTreeView.cxx index 2adb1b5e2..638c97657 100644 --- a/Libs/MRML/Widgets/qMRMLTreeView.cxx +++ b/Libs/MRML/Widgets/qMRMLTreeView.cxx @@ -18,6 +18,13 @@ ==============================================================================*/ +// If the number of child nodes is more than this number then show/hide operations +// are performed in batch processing mode. +static const int BATCH_VISIBILITY_UPDATE_THRESHOLD=30; + +// STL includes +#include + // Qt includes #include #include @@ -289,6 +296,39 @@ void qMRMLTreeViewPrivate::scrollTo(const QString& name, bool next) modelIndex, QItemSelectionModel::Current); } +//----------------------------------------------------------------------------- +bool qMRMLTreeViewPrivate::ManyChildrenNodes(vtkMRMLHierarchyNode* rootNode, int manyThreshold) +{ + int totalChildrenCount=0; + std::deque parentNodesToProcess; + parentNodesToProcess.push_back(rootNode); + while (!parentNodesToProcess.empty()) + { + vtkMRMLHierarchyNode* parent=parentNodesToProcess.front(); + if (parent==NULL) + { + continue; + } + + int childrenCount=parent->GetNumberOfChildrenNodes(); + totalChildrenCount+=childrenCount; + if (totalChildrenCount>manyThreshold) + { + return true; + } + for ( int i = 0; i < childrenCount; ++i) + { + vtkMRMLHierarchyNode* child = parent->GetNthChildNode(i); + if (child && child->GetNumberOfChildrenNodes()>0) + { + parentNodesToProcess.push_back(child); + } + } + parentNodesToProcess.pop_front(); + } + return false; +} + //------------------------------------------------------------------------------ // qMRMLTreeView //------------------------------------------------------------------------------ @@ -848,9 +888,16 @@ void qMRMLTreeView::toggleVisibility(const QModelIndex& index) { visibility = (hierDisplayNode->GetVisibility() ? 0 : 1); } - this->mrmlScene()->StartState(vtkMRMLScene::BatchProcessState); + bool batchProcess=qMRMLTreeViewPrivate::ManyChildrenNodes(displayableHierarchyNode,BATCH_VISIBILITY_UPDATE_THRESHOLD); + if (batchProcess) + { + this->mrmlScene()->StartState(vtkMRMLScene::BatchProcessState); + } vtkMRMLModelHierarchyLogic::SetChildrenVisibility(displayableHierarchyNode,visibility); - this->mrmlScene()->EndState(vtkMRMLScene::BatchProcessState); + if (batchProcess) + { + this->mrmlScene()->EndState(vtkMRMLScene::BatchProcessState); + } } else if (displayNode) { diff --git a/Libs/MRML/Widgets/qMRMLTreeView_p.h b/Libs/MRML/Widgets/qMRMLTreeView_p.h index 741e467d0..2b790178b 100644 --- a/Libs/MRML/Widgets/qMRMLTreeView_p.h +++ b/Libs/MRML/Widgets/qMRMLTreeView_p.h @@ -25,6 +25,9 @@ class QAction; class QMenu; +// MRML includes +class vtkMRMLHierarchyNode; + // MRMLWidgets includes #include "qMRMLTreeView.h" class qMRMLSceneModel; @@ -52,6 +55,9 @@ public: void saveChildrenExpandState(QModelIndex& parentIndex); void scrollTo(const QString& name, bool next); + /// Returns true if the hierarchy node has mode children (and descendant) nodes than manyThreshold + static bool ManyChildrenNodes(vtkMRMLHierarchyNode* rootNode, int manyThreshold); + qMRMLSceneModel* SceneModel; qMRMLSortFilterProxyModel* SortFilterModel; QString SceneModelType; -- GitLab