Commit 656c2126 authored by finetjul's avatar finetjul
Browse files

ENH: Add qMRMLTreeView::showScene and qMRMLTreeView::showRootNode

Give more flexibility to decide what item is root.
A root index for QTreeView is the invisible index that is the parent of all
the top level indexes.
showScene or showRootNode give the option to decide if the root scene/node
is visible, which implies that its parent becomes the root index for QTreeView.

git-svn-id: http://svn.slicer.org/Slicer4/trunk@21536 3bd1e089-480b-0410-8dfb-8563597acbee
parent 4adcae6e
......@@ -539,6 +539,26 @@ bool qMRMLSceneModel::reparent(vtkMRMLNode* node, vtkMRMLNode* newParent)
return false;
}
//------------------------------------------------------------------------------
bool qMRMLSceneModel::isParentNode(vtkMRMLNode* child, vtkMRMLNode* parent)const
{
for (; child; child = this->parentNode(child))
{
if (child == parent)
{
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
bool qMRMLSceneModel
::isAffiliatedNode(vtkMRMLNode* nodeA, vtkMRMLNode* nodeB)const
{
return this->isParentNode(nodeA, nodeB) || this->isParentNode(nodeB, nodeA);
}
//------------------------------------------------------------------------------
void qMRMLSceneModel::setListenNodeModifiedEvent(bool listen)
{
......
......@@ -188,6 +188,14 @@ public:
/// Must be reimplemented in derived classes.
/// Doesn't reparent and returns false by qMRMLSceneModel
virtual bool reparent(vtkMRMLNode* node, vtkMRMLNode* newParent);
/// Utility method that returns true if \a child has \a parent as parent,
/// grandparent, great grandparent etc...
/// \sa isAffiliatedNode()
bool isParentNode(vtkMRMLNode* child, vtkMRMLNode* parent)const;
/// Utility method that returns true if 2 nodes are child/parent for each
/// other. It can be grandchild, great grand child...
/// \sa isParentNode()
bool isAffiliatedNode(vtkMRMLNode* nodeA, vtkMRMLNode* nodeB)const;
protected slots:
......
......@@ -26,6 +26,7 @@
// VTK includes
#include <vtkMRMLNode.h>
#include <vtkMRMLScene.h>
// -----------------------------------------------------------------------------
// qMRMLSortFilterProxyModelPrivate
......@@ -42,6 +43,7 @@ public:
bool ShowChildNodeTypes;
QStringList HideChildNodeTypes;
QStringList HiddenNodeIDs;
QString HideNodesUnaffiliatedWithNodeID;
typedef QPair<QString, QVariant> AttributeType;
QHash<QString, AttributeType> Attributes;
};
......@@ -191,6 +193,17 @@ bool qMRMLSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelInd
}
}
if (!d->HideNodesUnaffiliatedWithNodeID.isEmpty())
{
vtkMRMLNode* theNode = sceneModel->mrmlScene()->GetNodeByID(
d->HideNodesUnaffiliatedWithNodeID.toLatin1());
bool affiliated = sceneModel->isAffiliatedNode(node, theNode);
if (!affiliated)
{
return false;
}
}
// Accept all the nodes if no type has been set
if (d->NodeTypes.isEmpty())
{
......@@ -375,6 +388,26 @@ QStringList qMRMLSortFilterProxyModel::hiddenNodeIDs()const
return d->HiddenNodeIDs;
}
// --------------------------------------------------------------------------
void qMRMLSortFilterProxyModel
::setHideNodesUnaffiliatedWithNodeID(const QString& nodeID)
{
Q_D(qMRMLSortFilterProxyModel);
if (nodeID == d->HideNodesUnaffiliatedWithNodeID)
{
return;
}
d->HideNodesUnaffiliatedWithNodeID = nodeID;
this->invalidateFilter();
}
// --------------------------------------------------------------------------
QString qMRMLSortFilterProxyModel::hideNodesUnaffiliatedWithNodeID()const
{
Q_D(const qMRMLSortFilterProxyModel);
return d->HideNodesUnaffiliatedWithNodeID;
}
// --------------------------------------------------------------------------
qMRMLSceneModel* qMRMLSortFilterProxyModel::sceneModel()const
{
......
......@@ -53,15 +53,17 @@ class QMRML_WIDGETS_EXPORT qMRMLSortFilterProxyModel : public QSortFilterProxyMo
/// This property controls whether the nodes with the HideFromEditor flag
/// on are filtered by the proxy model or not.
/// False by default.
/// \sa showHiddenForTypes
Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden)
/// This property overrides the behavior of \a showHidden for specific types.
/// Empty by default.
/// \sa showHidden
Q_PROPERTY(QStringList showHiddenForTypes READ showHiddenForTypes WRITE setShowHiddenForTypes)
/// This property controls whether \a nodeType subclasses are visible
/// This property controls whether \a nodeType subclasses are visible.
/// If \a showChildNodeTypes is false and \a nodeTypes is vtkMRMLVolumeNode
/// then vtkMRMLDScalarVolumeNode are not visible.
/// then vtkMRMLScalarVolumeNode are not visible.
/// True by default.
Q_PROPERTY(bool showChildNodeTypes READ showChildNodeTypes WRITE setShowChildNodeTypes)
......@@ -77,6 +79,11 @@ class QMRML_WIDGETS_EXPORT qMRMLSortFilterProxyModel : public QSortFilterProxyMo
/// This property controls the nodes to hide by node IDs.
Q_PROPERTY(QStringList hiddenNodeIDs READ hiddenNodeIDs WRITE setHiddenNodeIDs)
/// This property controls whether nodes unaffiliated with a given node ID are
/// hidden or not.
/// All the nodes are visible (empty string) by default.
Q_PROPERTY(QString hideNodesUnaffiliatedWithNodeID READ hideNodesUnaffiliatedWithNodeID WRITE setHideNodesUnaffiliatedWithNodeID)
public:
typedef QSortFilterProxyModel Superclass;
qMRMLSortFilterProxyModel(QObject *parent=0);
......@@ -128,12 +135,26 @@ public:
/// If a node is a nodeType, hide the node if it is also
/// a ExcludedChildNodeType. (this can happen if nodeType is a
/// mother class of ExcludedChildNodeType)
/// \sa hideChildNodeTypes, hideChildNodeTypes()
void setHideChildNodeTypes(const QStringList& nodeTypes);
/// \sa hideChildNodeTypes, setHideChildNodeTypes()
QStringList hideChildNodeTypes()const;
/// Set the list of nodes to hide.
/// \sa hiddenNodeIDs, hiddenNodeIDs()
void setHiddenNodeIDs(const QStringList& nodeIDsToHide);
/// Return the list of nodes to hide.
/// \sa hiddenNodeIDs, setHiddenNodeIDs()
QStringList hiddenNodeIDs()const;
/// Set the node ID used to filter out nodes that are not associated to it.
/// Recompute the filtering.
/// \sa hideNodesUnaffiliatedWithNodeID, hideNodesUnaffiliatedWithNodeID()
void setHideNodesUnaffiliatedWithNodeID(const QString& nodeID);
/// Return the node ID used to filter out nodes that are not associated to it.
/// \sa hideNodesUnaffiliatedWithNodeID, setHideNodesUnaffiliatedWithNodeID()
QString hideNodesUnaffiliatedWithNodeID()const;
/// Return the scene model used as input if any.
qMRMLSceneModel* sceneModel()const;
......
......@@ -57,6 +57,8 @@ qMRMLTreeViewPrivate::qMRMLTreeViewPrivate(qMRMLTreeView& object)
this->FitSizeToVisibleIndexes = true;
this->TreeViewSizeHint = QSize();
this->TreeViewMinSizeHint = QSize(120, 120);
this->ShowScene = true;
this->ShowRootNode = false;
this->NodeMenu = 0;
this->RenameAction = 0;
this->DeleteAction = 0;
......@@ -280,8 +282,10 @@ void qMRMLTreeView::setMRMLScene(vtkMRMLScene* scene)
{
Q_D(qMRMLTreeView);
Q_ASSERT(d->SortFilterModel);
vtkMRMLNode* rootNode = this->rootNode();
// only qMRMLSceneModel needs the scene, the other proxies don't care.
d->SceneModel->setMRMLScene(scene);
this->setRootNode(rootNode);
this->expandToDepth(2);
}
......@@ -514,18 +518,95 @@ void qMRMLTreeView::editCurrentNode()
emit editNodeRequested(this->currentNode());
}
//--------------------------------------------------------------------------
void qMRMLTreeView::setShowScene(bool show)
{
Q_D(qMRMLTreeView);
if (d->ShowScene == show)
{
return;
}
vtkMRMLNode* oldRootNode = this->rootNode();
d->ShowScene = show;
this->setRootNode(oldRootNode);
}
//--------------------------------------------------------------------------
bool qMRMLTreeView::showScene()const
{
Q_D(const qMRMLTreeView);
return d->ShowScene;
}
//--------------------------------------------------------------------------
void qMRMLTreeView::setShowRootNode(bool show)
{
Q_D(qMRMLTreeView);
if (d->ShowRootNode == show)
{
return;
}
vtkMRMLNode* oldRootNode = this->rootNode();
d->ShowRootNode = show;
this->setRootNode(oldRootNode);
}
//--------------------------------------------------------------------------
bool qMRMLTreeView::showRootNode()const
{
Q_D(const qMRMLTreeView);
return d->ShowRootNode;
}
//--------------------------------------------------------------------------
void qMRMLTreeView::setRootNode(vtkMRMLNode* rootNode)
{
Q_D(qMRMLTreeView);
// Need to reset the filter to be able to find indexes from nodes that
// could potentially be filtered out.
this->sortFilterProxyModel()->setHideNodesUnaffiliatedWithNodeID(QString());
QModelIndex treeRootIndex;
if (rootNode == 0)
{
if (!d->ShowScene)
{
treeRootIndex = this->sortFilterProxyModel()->mrmlSceneIndex();
}
}
else
{
treeRootIndex = this->sortFilterProxyModel()->indexFromMRMLNode(rootNode);
if (d->ShowRootNode)
{
// Hide the siblings of the root node.
this->sortFilterProxyModel()->setHideNodesUnaffiliatedWithNodeID(
rootNode->GetID());
// The parent of the root node becomes the root for QTreeView.
treeRootIndex = treeRootIndex.parent();
rootNode = this->sortFilterProxyModel()->mrmlNodeFromIndex(treeRootIndex);
}
}
qvtkReconnect(this->rootNode(), rootNode, vtkCommand::ModifiedEvent,
this, SLOT(updateRootNode(vtkObject*)));
this->setRootIndex(this->sortFilterProxyModel()->indexFromMRMLNode(rootNode));
qDebug() << rootNode << treeRootIndex;
this->setRootIndex(treeRootIndex);
}
//--------------------------------------------------------------------------
vtkMRMLNode* qMRMLTreeView::rootNode()const
{
return this->sortFilterProxyModel()->mrmlNodeFromIndex(this->rootIndex());
Q_D(const qMRMLTreeView);
vtkMRMLNode* treeRootNode =
this->sortFilterProxyModel()->mrmlNodeFromIndex(this->rootIndex());
if (d->ShowRootNode &&
this->mrmlScene() &&
this->sortFilterProxyModel()->hideNodesUnaffiliatedWithNodeID()
.isEmpty())
{
return this->mrmlScene()->GetNodeByID(
this->sortFilterProxyModel()->hideNodesUnaffiliatedWithNodeID().toLatin1());
}
return treeRootNode;
}
//--------------------------------------------------------------------------
......@@ -624,6 +705,7 @@ void qMRMLTreeView::mousePressEvent(QMouseEvent* e)
{
return;
}
qDebug() << "Mouse press";
// get the index of the current column
QModelIndex index = this->indexAt(e->pos());
......
......@@ -95,6 +95,22 @@ class QMRML_WIDGETS_EXPORT qMRMLTreeView : public QTreeView
/// False by default (only nodes with HideFromEditors = 0 are visible)
/// \sa vtkMRMLNode::GetHideFromEditors()
Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden)
/// This property controls whether the scene is visible (is a top-level item).
/// It doesn't have any effect if \a rootNode() is not null.
/// Visible by default.
/// \sa setShowScene(), showScene(),
/// showRootNode, setRootNode(), setRootIndex()
Q_PROPERTY(bool showScene READ showScene WRITE setShowScene)
/// This property controls whether the root node if any is visible.
/// When the root node is visible, it appears as a top-level item, if it is
/// hidden only its children are top-level items.
/// It doesn't have any effect if \a rootNode() is null.
/// Hidden by default.
/// Don't use qMRMLSortFilterProxyModel::HideNodesUnaffiliatedWithNodeID if
/// showRootNode is true, it is internally being used.
/// \sa setShowRootNode(), showRootNode(),
/// showScene, setRootNode(), setRootIndex()
Q_PROPERTY(bool showRootNode READ showRootNode WRITE setShowRootNode)
public:
typedef QTreeView Superclass;
......@@ -167,10 +183,22 @@ public:
inline void setShowHidden(bool);
inline bool showHidden()const;
/// Similar to setRootIndex(QModelIndex) but observe the ModifiedEvent of
/// the node to stay in sync.
/// A null node (default) means QModelIndex() is the root index.
Q_INVOKABLE void setRootNode(vtkMRMLNode* root);
/// Set the show root node flag.
/// \sa showRootNode, showRootNode()
void setShowRootNode(bool show);
/// Return the show root node flag.
/// \sa showRootNode, setShowRootNode()
bool showRootNode()const;
/// Set the show scene flag.
/// \sa showScene, showScene()
void setShowScene(bool show);
/// Return the show scene flag.
/// \sa showScene, setShowScene()
bool showScene()const;
/// Return the root node of the tree.
/// \sa setRootNode(), showRootNode
vtkMRMLNode* rootNode()const;
/// Retrieve the sortFilterProxyModel used to filter/sort
......@@ -213,6 +241,12 @@ public slots:
/// will happen
void setSceneModelType(const QString& modelType);
/// Similar to setRootIndex(QModelIndex) but observe the ModifiedEvent of
/// the node to stay in sync.
/// A null node (default) means QModelIndex() is the root index.
/// \sa rootNode(), setRootIndex(), showRootNode
void setRootNode(vtkMRMLNode* root);
void deleteCurrentNode();
void editCurrentNode();
void renameCurrentNode();
......
......@@ -57,6 +57,8 @@ public:
bool FitSizeToVisibleIndexes;
mutable QSize TreeViewSizeHint;
QSize TreeViewMinSizeHint;
bool ShowScene;
bool ShowRootNode;
QMenu* NodeMenu;
QAction* RenameAction;
......
......@@ -84,6 +84,7 @@ void qMRMLAnnotationTreeViewPrivate::init()
q->setNodeTypes(nodeTypes);
this->SortFilterModel = q->sortFilterProxyModel();
q->setShowScene(false);
//this->SortFilterModel->setSourceModel(this->SceneModel);
//q->qMRMLTreeView::setModel(this->SortFilterModel);
......@@ -513,27 +514,6 @@ void qMRMLAnnotationTreeView::hideScene()
{
Q_D(qMRMLAnnotationTreeView);
// first, we set the root index to the mrmlScene
// this works also if the scene is not defined yet
QModelIndex root = d->SceneModel->mrmlSceneIndex();
/* don't hide the top level node
if (this->m_Logic &&
this->m_Logic->GetMRMLScene())
{
// if the logic is already registered, we look for the first annotationHierarchyNode
vtkMRMLNode* toplevelNode = this->m_Logic->GetMRMLScene()->GetNthNodeByClass(0,"vtkMRMLAnnotationHierarchyNode");
if (toplevelNode)
{
// if we find it, we use it as the root index
root = d->SceneModel->indexes(toplevelNode)[0];
}
}
*/
this->setRootIndex(d->SortFilterModel->mapFromSource(root));
// set the column widths
// If the model hasn't been populated yet, the columns don't exist and
// QHeaderView::setResizeMode asserts.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment