Commit 5ad91716 authored by finetjul's avatar finetjul
Browse files

ENH: Make qMRMLSceneAnnotationModel columns configurable

Note: Annotation hierarchies have an unclickable visibility icon

Issue #2606

git-svn-id: http://svn.slicer.org/Slicer4/trunk@21541 3bd1e089-480b-0410-8dfb-8563597acbee
parent abcffae1
......@@ -32,11 +32,12 @@ class vtkMRMLDisplayNode;
class vtkMRMLHierarchyNode;
//------------------------------------------------------------------------------
// qMRMLSceneHierarchyModelPrivate
// qMRMLSceneDisplayableModelPrivate
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
class QMRML_WIDGETS_EXPORT qMRMLSceneDisplayableModelPrivate: public qMRMLSceneHierarchyModelPrivate
class QMRML_WIDGETS_EXPORT qMRMLSceneDisplayableModelPrivate
: public qMRMLSceneHierarchyModelPrivate
{
protected:
Q_DECLARE_PUBLIC(qMRMLSceneDisplayableModel);
......
......@@ -2101,21 +2101,18 @@ const char * vtkSlicerAnnotationModuleLogic::GetAnnotationIcon(const char* id)
{
return 0;
}
// extra check: get node by id can crash if an old scene with a selection
// node with the old style id of vtkMRMLSelectionNode1 is opened, check that
// the passed in id string is an annotation node id string
std::string idString = std::string(id);
if (idString.find("vtkMRMLAnnotation") == std::string::npos)
{
return 0;
}
vtkMRMLNode *mrmlNode = this->GetMRMLScene()->GetNodeByID(id);
if (!mrmlNode)
{
return 0;
}
return this->GetAnnotationIcon(mrmlNode);
}
//---------------------------------------------------------------------------
// Return the icon of an annotation MRML Node
//---------------------------------------------------------------------------
const char * vtkSlicerAnnotationModuleLogic
::GetAnnotationIcon(vtkMRMLNode* mrmlNode)
{
vtkMRMLAnnotationNode* annotationNode = vtkMRMLAnnotationNode::SafeDownCast(
mrmlNode);
mrmlNode);
if (annotationNode)
{
......@@ -2123,8 +2120,7 @@ const char * vtkSlicerAnnotationModuleLogic::GetAnnotationIcon(const char* id)
}
vtkMRMLAnnotationHierarchyNode* hierarchyNode =
vtkMRMLAnnotationHierarchyNode::SafeDownCast(
this->GetMRMLScene()->GetNodeByID(id));
vtkMRMLAnnotationHierarchyNode::SafeDownCast(mrmlNode);
if (hierarchyNode)
{
......@@ -2132,8 +2128,7 @@ const char * vtkSlicerAnnotationModuleLogic::GetAnnotationIcon(const char* id)
}
vtkMRMLAnnotationSnapshotNode* snapshotNode =
vtkMRMLAnnotationSnapshotNode::SafeDownCast(
this->GetMRMLScene()->GetNodeByID(id));
vtkMRMLAnnotationSnapshotNode::SafeDownCast(mrmlNode);
if (snapshotNode)
{
......@@ -2141,7 +2136,6 @@ const char * vtkSlicerAnnotationModuleLogic::GetAnnotationIcon(const char* id)
}
return 0;
}
//---------------------------------------------------------------------------
......
......@@ -16,8 +16,8 @@ class vtkMRMLAnnotationTextDisplayNode;
#include <string>
/// \ingroup Slicer_QtModules_Annotation
class VTK_SLICER_ANNOTATIONS_MODULE_LOGIC_EXPORT vtkSlicerAnnotationModuleLogic :
public vtkSlicerModuleLogic
class VTK_SLICER_ANNOTATIONS_MODULE_LOGIC_EXPORT vtkSlicerAnnotationModuleLogic
:public vtkSlicerModuleLogic
{
public:
enum Events{
......@@ -139,6 +139,7 @@ public:
/// Get the icon name of an Annotation MRML node
const char * GetAnnotationIcon(const char * id);
const char * GetAnnotationIcon(vtkMRMLNode* mrmlNode);
/// Get the lock flag of an Annotation MRML node
int GetAnnotationLockedUnlocked(const char * id);
......
......@@ -176,22 +176,23 @@ void qMRMLAnnotationTreeView::onClicked(const QModelIndex& index)
// check if user clicked on icon, this can happen even after we marked a
// hierarchy as active
if (index.column() == qMRMLSceneAnnotationModel::CheckedColumn)
if (index.column() == d->SceneModel->checkableColumn())
{
// Let the superclass view to handle the event, it will update the item
// which will update the node.
}
else if (index.column() == qMRMLSceneAnnotationModel::VisibilityColumn)
else if (index.column() == d->SceneModel->visibilityColumn())
{
// Let the superclass view to handle the event.
// user wants to toggle the visibility of the annotation
this->onVisibilityColumnClicked(mrmlNode);
//this->onVisibilityColumnClicked(mrmlNode);
}
else if (index.column() == qMRMLSceneAnnotationModel::LockColumn)
else if (index.column() == d->SceneModel->lockColumn())
{
// user wants to toggle the un-/lock of the annotation
this->onLockColumnClicked(mrmlNode);
}
else if (index.column() == qMRMLSceneAnnotationModel::EditColumn)
else if (index.column() == d->SceneModel->editColumn())
{
// user wants to edit the properties of this annotation
// signal the widget
......@@ -237,14 +238,16 @@ void qMRMLAnnotationTreeView::toggleLockForSelected()
return;
}
for (int i = 0; i < selected.size(); ++i) {
for (int i = 0; i < selected.size(); ++i)
{
// we need to prevent looping through all columns
// there we only update once a row
if (selected.at(i).column() == qMRMLSceneAnnotationModel::LockColumn)
if (selected.at(i).column() == d->SceneModel->lockColumn())
{
vtkMRMLAnnotationNode* annotationNode = vtkMRMLAnnotationNode::SafeDownCast(d->SortFilterModel->mrmlNodeFromIndex(selected.at(i)));
vtkMRMLAnnotationNode* annotationNode = vtkMRMLAnnotationNode::SafeDownCast(
d->SortFilterModel->mrmlNodeFromIndex(selected.at(i)));
if (annotationNode)
{
......@@ -263,27 +266,13 @@ void qMRMLAnnotationTreeView::toggleVisibilityForSelected()
Q_D(qMRMLAnnotationTreeView);
QModelIndexList selected = this->selectedIndexes();
// first, check if we selected anything
if (selected.isEmpty())
{
return;
}
for (int i = 0; i < selected.size(); ++i)
foreach(const QModelIndex& index, selected )
{
// we need to prevent looping through all columns
// there we only update once a row
if (selected.at(i).column() == qMRMLSceneAnnotationModel::VisibilityColumn)
if (index.column() == d->SceneModel->visibilityColumn())
{
vtkMRMLAnnotationNode* annotationNode = vtkMRMLAnnotationNode::SafeDownCast(d->SortFilterModel->mrmlNodeFromIndex(selected.at(i)));
if (annotationNode)
{
this->onVisibilityColumnClicked(annotationNode);
}
this->toggleVisibility(index);
}
} // for loop
......@@ -368,7 +357,7 @@ void qMRMLAnnotationTreeView::deleteSelected()
// we need to prevent looping through all columns
// there we only update once a row
if (selected.at(i).column() == qMRMLSceneAnnotationModel::VisibilityColumn)
if (selected.at(i).column() == d->SceneModel->visibilityColumn())
{
vtkMRMLAnnotationNode* annotationNode = vtkMRMLAnnotationNode::SafeDownCast(d->SortFilterModel->mrmlNodeFromIndex(selected.at(i)));
......@@ -427,17 +416,14 @@ void qMRMLAnnotationTreeView::selectedAsCollection(vtkCollection* collection)
// we need to prevent looping through all columns
// there we only update once a row
if (selected.at(i).column() == qMRMLSceneAnnotationModel::VisibilityColumn)
{
vtkMRMLNode* node = vtkMRMLNode::SafeDownCast(d->SortFilterModel->mrmlNodeFromIndex(selected.at(i)));
//if (node->IsA("vtkMRMLAnnotationNode"))
// {
collection->AddItem(node);
// }
}
if (selected.at(i).column() == d->SceneModel->visibilityColumn())
{
vtkMRMLNode* node = vtkMRMLNode::SafeDownCast(d->SortFilterModel->mrmlNodeFromIndex(selected.at(i)));
//if (node->IsA("vtkMRMLAnnotationNode"))
// {
collection->AddItem(node);
// }
}
} // for
......@@ -457,21 +443,24 @@ bool qMRMLAnnotationTreeView::viewportEvent(QEvent* e)
// reset the cursor if we leave the viewport
if(e->type() == QEvent::Leave)
{
setCursor(QCursor());
this->setCursor(QCursor());
}
return QTreeView::viewportEvent(e);
return this->Superclass::viewportEvent(e);
}
//------------------------------------------------------------------------------
void qMRMLAnnotationTreeView::mouseMoveEvent(QMouseEvent* e)
{
this->QTreeView::mouseMoveEvent(e);
Q_D(qMRMLAnnotationTreeView);
this->Superclass::mouseMoveEvent(e);
// get the index of the current column
QModelIndex index = indexAt(e->pos());
if (index.column() == qMRMLSceneAnnotationModel::VisibilityColumn || index.column() == qMRMLSceneAnnotationModel::LockColumn || index.column() == qMRMLSceneAnnotationModel::EditColumn)
if (index.column() == d->SceneModel->visibilityColumn() ||
index.column() == d->SceneModel->lockColumn() ||
index.column() == d->SceneModel->editColumn())
{
// we are over a column with a clickable icon
// let's change the cursor
......@@ -515,16 +504,9 @@ void qMRMLAnnotationTreeView::hideScene()
Q_D(qMRMLAnnotationTreeView);
// set the column widths
// If the model hasn't been populated yet, the columns don't exist and
// QHeaderView::setResizeMode asserts.
if ( this->header()->visualIndex(qMRMLSceneAnnotationModel::LockColumn) != -1)
{
this->header()->setResizeMode(qMRMLSceneAnnotationModel::CheckedColumn, (QHeaderView::ResizeToContents));
this->header()->setResizeMode(qMRMLSceneAnnotationModel::VisibilityColumn, (QHeaderView::ResizeToContents));
this->header()->setResizeMode(qMRMLSceneAnnotationModel::LockColumn, (QHeaderView::ResizeToContents));
this->header()->setResizeMode(qMRMLSceneAnnotationModel::EditColumn, (QHeaderView::ResizeToContents));
this->header()->setResizeMode(qMRMLSceneAnnotationModel::ValueColumn, (QHeaderView::ResizeToContents));
this->header()->setResizeMode(qMRMLSceneAnnotationModel::TextColumn, (QHeaderView::ResizeToContents));
for (int i = 0; i < this->header()->count(); ++i)
{
this->header()->setResizeMode(i, QHeaderView::ResizeToContents);
}
}
......@@ -535,12 +517,12 @@ void qMRMLAnnotationTreeView::hideScene()
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void qMRMLAnnotationTreeView::onVisibilityColumnClicked(vtkMRMLNode* node)
void qMRMLAnnotationTreeView::toggleVisibility(const QModelIndex& index)
{
Q_D(qMRMLAnnotationTreeView);
vtkMRMLNode* node = d->SortFilterModel->mrmlNodeFromIndex(index);
if (!node)
{
// no node found!
return;
}
......@@ -551,7 +533,10 @@ void qMRMLAnnotationTreeView::onVisibilityColumnClicked(vtkMRMLNode* node)
// this is a valid annotationNode
annotationNode->SetDisplayVisibility(!annotationNode->GetDisplayVisibility());
}
else
{
this->Superclass::toggleVisibility(index);
}
// taking out the switch for hierarchy nodes, do it via the buttons above
/*
vtkMRMLAnnotationHierarchyNode* hierarchyNode = vtkMRMLAnnotationHierarchyNode::SafeDownCast(node);
......@@ -628,3 +613,12 @@ void qMRMLAnnotationTreeView::setLogic(vtkSlicerAnnotationModuleLogic* logic)
d->SceneModel->setLogic(this->m_Logic);
}
//-----------------------------------------------------------------------------
/// Annotation model
//-----------------------------------------------------------------------------
qMRMLSceneAnnotationModel* qMRMLAnnotationTreeView::annotationModel()const
{
Q_D(const qMRMLAnnotationTreeView);
return d->SceneModel;
}
......@@ -27,6 +27,7 @@
// Annotations includes
#include "qSlicerAnnotationsModuleWidgetsExport.h"
class qMRMLAnnotationTreeViewPrivate;
class qMRMLSceneAnnotationModel;
// Logic includes
class vtkSlicerAnnotationModuleLogic;
......@@ -67,6 +68,8 @@ public:
void setSelectedNode(const char* id);
qMRMLSceneAnnotationModel* annotationModel()const;
public slots:
void onSelectionChanged(const QItemSelection& index,const QItemSelection& beforeIndex);
......@@ -85,14 +88,13 @@ protected:
#endif
virtual void mousePressEvent(QMouseEvent* event);
virtual void toggleVisibility(const QModelIndex& index);
private:
Q_DECLARE_PRIVATE(qMRMLAnnotationTreeView);
Q_DISABLE_COPY(qMRMLAnnotationTreeView);
vtkSlicerAnnotationModuleLogic* m_Logic;
// toggle the visibility of an annotation
void onVisibilityColumnClicked(vtkMRMLNode* node);
// toggle un-/lock of an annotation
void onLockColumnClicked(vtkMRMLNode* node);
......
......@@ -20,44 +20,62 @@
// Qt includes
#include <QDebug>
#include <QMap>
#include <QMimeData>
#include <QSharedPointer>
#include <QStack>
#include <QStringList>
#include <QVector>
// Annotations includes
#include "qMRMLSceneAnnotationModel.h"
#include "qMRMLSceneAnnotationModel_p.h"
#include "vtkMRMLAnnotationHierarchyNode.h"
#include "vtkMRMLAnnotationSnapshotNode.h"
#include "vtkSlicerAnnotationModuleLogic.h"
// MRML includes
#include <vtkMRMLScene.h>
#include <vtkMRMLNode.h>
#include <vtkMRMLAnnotationNode.h>
#include <vtkMRMLDisplayableHierarchyNode.h>
// VTK includes
#include <vtkVariantArray.h>
#include <typeinfo>
//------------------------------------------------------------------------------
qMRMLSceneAnnotationModelPrivate
::qMRMLSceneAnnotationModelPrivate(qMRMLSceneAnnotationModel& object)
: qMRMLSceneDisplayableModelPrivate(object)
{
this->LockColumn = -1;
this->EditColumn = -1;
this->ValueColumn = -1;
this->TextColumn = -1;
}
//------------------------------------------------------------------------------
qMRMLSceneAnnotationModel::qMRMLSceneAnnotationModel(QObject *vparent)
: qMRMLSceneDisplayableModel(vparent)
void qMRMLSceneAnnotationModelPrivate::init()
{
this->setListenNodeModifiedEvent(true);
this->setNameColumn(5);
this->setVisibilityColumn(-1);
this->setOpacityColumn(-1);
this->setCheckableColumn(qMRMLSceneAnnotationModel::CheckedColumn);
this->setColumnCount(7);
this->setHorizontalHeaderLabels(
Q_Q(qMRMLSceneAnnotationModel);
this->Superclass::init();
q->setCheckableColumn(0);
q->setVisibilityColumn(1);
q->setLockColumn(2);
q->setEditColumn(3);
q->setValueColumn(4);
q->setNameColumn(5);
q->setTextColumn(6);
q->setHorizontalHeaderLabels(
QStringList() << "" << "Vis" << "Lock" << "Edit" << "Value" << "Name" << "Description");
}
//------------------------------------------------------------------------------
qMRMLSceneAnnotationModel::qMRMLSceneAnnotationModel(QObject *vparent)
: Superclass(new qMRMLSceneAnnotationModelPrivate(*this), vparent)
{
Q_D(qMRMLSceneAnnotationModel);
d->init();
}
//------------------------------------------------------------------------------
qMRMLSceneAnnotationModel::qMRMLSceneAnnotationModel(
qMRMLSceneAnnotationModelPrivate* pimpl, QObject *vparent)
: Superclass(pimpl, vparent)
{
// init() is called by derived class.
}
//------------------------------------------------------------------------------
qMRMLSceneAnnotationModel::~qMRMLSceneAnnotationModel()
{
......@@ -94,112 +112,113 @@ void qMRMLSceneAnnotationModel::updateNodeFromItemData(vtkMRMLNode* node, QStand
} // for loop
}// if hierarchyNode
switch (item->column())
if (item->column() == this->textColumn())
{
case qMRMLSceneAnnotationModel::TextColumn:
if (annotationNode)
{
if (annotationNode)
// if we have an annotation node, the text can be changed by editing the textcolumn
annotationNode->SetText(0,item->text().toLatin1(),0,1);
if (annotationNode->IsA("vtkMRMLAnnotationFiducialNode"))
{
// if we have an annotation node, the text can be changed by editing the textcolumn
annotationNode->SetText(0,item->text().toLatin1(),0,1);
if (annotationNode->IsA("vtkMRMLAnnotationFiducialNode"))
{
// also set the name
//annotationNode->SetName(item->text().toLatin1());
}
// also set the name
//annotationNode->SetName(item->text().toLatin1());
}
else if (hierarchyNode)
{
// if we have a hierarchy node, the description can be changed by editing the textcolumn
hierarchyNode->SetDescription(item->text().toLatin1());
}
else if (snapshotNode)
{
// if we have a snapshot node, the name can be changed by editing the textcolumn
snapshotNode->SetName(item->text().toLatin1());
}
break;
}
default:
break;
else if (hierarchyNode)
{
// if we have a hierarchy node, the description can be changed by editing the textcolumn
hierarchyNode->SetDescription(item->text().toLatin1());
}
else if (snapshotNode)
{
// if we have a snapshot node, the name can be changed by editing the textcolumn
snapshotNode->SetName(item->text().toLatin1());
}
}
}
//------------------------------------------------------------------------------
void qMRMLSceneAnnotationModel::updateItemDataFromNode(QStandardItem* item, vtkMRMLNode* node, int column)
{
Q_D(qMRMLSceneAnnotationModel);
if (!node)
{
return;
}
this->qMRMLSceneDisplayableModel::updateItemDataFromNode(item, node, column);
this->Superclass::updateItemDataFromNode(item, node, column);
vtkMRMLAnnotationNode* annotationNode = vtkMRMLAnnotationNode::SafeDownCast(node);
vtkMRMLAnnotationHierarchyNode *hnode = vtkMRMLAnnotationHierarchyNode::SafeDownCast(node);
switch (column)
if (column == this->visibilityColumn())
{
case qMRMLSceneAnnotationModel::VisibilityColumn:
// the visibility icon
if (annotationNode)
{
if (annotationNode->GetDisplayVisibility())
{
item->setData(QPixmap(":/Icons/Small/SlicerVisible.png"),Qt::DecorationRole);
}
else
{
item->setData(QPixmap(":/Icons/Small/SlicerInvisible.png"),Qt::DecorationRole);
}
}
else if (hnode)
{
// don't show anything, handle it in property dialogue
}
break;
case qMRMLSceneAnnotationModel::LockColumn:
// the lock/unlock icon
if (annotationNode)
{
if (annotationNode->GetLocked())
{
item->setData(QPixmap(":/Icons/Small/SlicerLock.png"),Qt::DecorationRole);
}
else
{
item->setData(QPixmap(":/Icons/Small/SlicerUnlock.png"),Qt::DecorationRole);
}
}
else if (hnode)
{
// don't show anything, handle it in property dialogue
}
break;
case qMRMLSceneAnnotationModel::EditColumn:
// the annotation type icon
item->setData(QPixmap(this->m_Logic->GetAnnotationIcon(node->GetID())),Qt::DecorationRole);
break;
case qMRMLSceneAnnotationModel::ValueColumn:
if (annotationNode)
// the visibility icon
if (annotationNode)
{
if (annotationNode->GetDisplayVisibility())
{
// the annotation measurement
item->setText(QString(this->m_Logic->GetAnnotationMeasurement(annotationNode->GetID(),false)));
item->setData(QPixmap(":/Icons/Small/SlicerVisible.png"),Qt::DecorationRole);
}
else if (hnode)
else
{
item->setText(QString(""));
item->setData(QPixmap(":/Icons/Small/SlicerInvisible.png"),Qt::DecorationRole);
}
break;
case qMRMLSceneAnnotationModel::TextColumn:
if (annotationNode)
}
else if (hnode)
{
// don't show anything, handle it in property dialogue
}
}
if (column == this->lockColumn())
{
// the lock/unlock icon
if (annotationNode)
{
if (annotationNode->GetLocked())
{
// the annotation text
item->setText(QString(this->m_Logic->GetAnnotationText(annotationNode->GetID())));
item->setData(QPixmap(":/Icons/Small/SlicerLock.png"),Qt::DecorationRole);
}
else if (hnode)
else
{
item->setText(QString(node->GetDescription()));
item->setData(QPixmap(":/Icons/Small/SlicerUnlock.png"),Qt::DecorationRole);
}
break;
}
else if (hnode)
{
// don't show anything, handle it in property dialogue
}
}
if (column == this->editColumn())
{
// the annotation type icon
item->setData(
QPixmap(d->AnnotationLogic->GetAnnotationIcon(node)), Qt::DecorationRole);
}
if (column == this->valueColumn())
{
if (annotationNode)
{
// the annotation measurement
item->setText(
QString(d->AnnotationLogic->GetAnnotationMeasurement(
annotationNode->GetID(),false)));
}
else if (hnode)
{
item->setText(QString(""));