Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
QmitkPointListView.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "QmitkPointListView.h"
18 
19 #include "QmitkEditPointDialog.h"
20 #include "QmitkPointListModel.h"
21 #include "QmitkStdMultiWidget.h"
22 
23 #include "mitkRenderingManager.h"
24 
25 #include <QKeyEvent>
26 #include <QMenu>
27 #include <QMessageBox>
28 #include <QPalette>
29 #include <QTimer>
30 
32  : QListView(parent),
33  m_Snc1(NULL),
34  m_Snc2(NULL),
35  m_Snc3(NULL),
36  m_PointListModel(new QmitkPointListModel()),
37  m_SelfCall(false),
38  m_showFading(false),
39  m_MultiWidget(NULL)
40 {
41  QListView::setAlternatingRowColors(true);
42 
43  QListView::setSelectionBehavior(QAbstractItemView::SelectRows);
44  QListView::setSelectionMode(QAbstractItemView::SingleSelection);
45  QListView::setModel(m_PointListModel);
46  QString tooltip = QString("Use the F2/F3 keys to move a point up/down, the Del key to remove a point\nand the mouse "
47  "wheel to change the timestep.\n\nTimeStep:\t%1")
48  .arg(0);
49  QListView::setToolTip(tooltip);
50  this->setContextMenuPolicy(Qt::CustomContextMenu);
51 
52  m_TimeStepFaderLabel = new QLabel(this);
53  QFont font("Arial", 17);
54  m_TimeStepFaderLabel->setFont(font);
55 
56  this->setMinimumHeight(40);
57 
58  this->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
59 
60  connect(m_PointListModel, SIGNAL(SignalUpdateSelection()), this, SLOT(OnPointSetSelectionChanged()));
61 
62  connect(this, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(OnPointDoubleClicked(const QModelIndex &)));
63 
64  connect(QListView::selectionModel(),
65  SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
66  this,
67  SLOT(OnListViewSelectionChanged(const QItemSelection &, const QItemSelection &)));
68 
69  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ctxMenu(const QPoint &)));
70 }
71 
73 {
74  delete m_PointListModel;
75 }
76 
78 {
79  m_PointListModel->SetPointSetNode(pointSetNode);
80 }
81 
83 {
84  return m_PointListModel->GetPointSet();
85 }
86 
88 {
89  m_MultiWidget = multiWidget;
90 }
91 
93 {
94  return m_MultiWidget;
95 }
96 
97 void QmitkPointListView::OnPointDoubleClicked(const QModelIndex &index)
98 {
102  QmitkEditPointDialog _EditPointDialog(this);
104  _EditPointDialog.exec();
105 }
106 
108 {
109  const mitk::PointSet *pointSet = m_PointListModel->GetPointSet();
110  if (pointSet == NULL)
111  return;
112 
113  // update this view's selection status as a result to changes in the point set data structure
114  m_SelfCall = true;
115  int timeStep = m_PointListModel->GetTimeStep();
116 
117  if (pointSet->GetNumberOfSelected(timeStep) > 1)
118  {
119  MITK_ERROR << "Point set has multiple selected points. This view is not designed for more than one selected point.";
120  }
121 
122  int selectedIndex = pointSet->SearchSelectedPoint(timeStep);
123 
124  if (selectedIndex == -1) // no selected point is found
125  {
126  m_SelfCall = false;
127  return;
128  }
129 
130  QModelIndex index;
131 
132  bool modelIndexOkay = m_PointListModel->GetModelIndexForPointID(selectedIndex, index);
133 
134  if (modelIndexOkay == true)
135  QListView::selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
136 
138 
139  m_SelfCall = false;
140 }
141 
142 void QmitkPointListView::OnListViewSelectionChanged(const QItemSelection &selected,
143  const QItemSelection & /*deselected*/)
144 {
145  if (m_SelfCall)
146  return;
147 
148  mitk::PointSet *pointSet = const_cast<mitk::PointSet *>(m_PointListModel->GetPointSet());
149 
150  if (pointSet == NULL)
151  return;
152 
153  // (take care that this widget doesn't react to self-induced changes by setting m_SelfCall)
154  m_SelfCall = true;
155 
156  // update selection of all points in pointset: select the one(s) that are selected in the view, deselect all others
157  QModelIndexList selectedIndexes = selected.indexes();
158 
159  for (mitk::PointSet::PointsContainer::Iterator it =
160  pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->Begin();
161  it != pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->End();
162  ++it)
163  {
164  QModelIndex index;
165  if (m_PointListModel->GetModelIndexForPointID(it->Index(), index))
166  {
167  if (selectedIndexes.indexOf(index) != -1) // index is found in the selected indices list
168  {
169  pointSet->SetSelectInfo(it->Index(), true, m_PointListModel->GetTimeStep());
170 
171  // Use Multiwidget or SliceNavigationControllers to set crosshair to selected point
172  if (m_MultiWidget != NULL)
173  {
175  }
176 
177  mitk::Point3D p = pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep());
178 
179  // remove the three ifs below after the SetSnc* methods have been removed
180  if (m_Snc1 != NULL)
181  {
183  }
184  if (m_Snc2 != NULL)
185  {
187  }
188  if (m_Snc3 != NULL)
189  {
191  }
192 
193  for (std::set<mitk::SliceNavigationController *>::const_iterator i = m_Sncs.begin(); i != m_Sncs.end(); ++i)
194  {
195  (*i)->SelectSliceByPoint(p);
196  }
197  }
198  else
199  {
200  pointSet->SetSelectInfo(it->Index(), false, m_PointListModel->GetTimeStep());
201  }
202  }
203  }
204 
205  m_SelfCall = false;
206 
208 
210 }
211 
213 {
214  if (m_PointListModel == NULL)
215  return;
216 
217  int key = e->key();
218 
219  switch (key)
220  {
221  case Qt::Key_F2:
223  break;
224  case Qt::Key_F3:
226  break;
227  case Qt::Key_Delete:
229  break;
230  default:
231  break;
232  }
233 }
234 
235 void QmitkPointListView::wheelEvent(QWheelEvent *event)
236 {
238  (int)(m_PointListModel->GetPointSet()->GetTimeSteps()) == 1)
239  return;
240 
241  int whe = event->delta();
243  unsigned int numberOfTS = ps->GetTimeSteps();
244 
245  if (numberOfTS == 1)
246  return;
247  int currentTS = this->m_PointListModel->GetTimeStep();
248  if (whe > 0)
249  {
250  if ((currentTS + 1 >= (int)numberOfTS))
251  return;
252 
253  this->m_PointListModel->SetTimeStep(++currentTS);
254  }
255  else
256  {
257  if ((currentTS <= 0))
258  return;
259  this->m_PointListModel->SetTimeStep(--currentTS);
260  }
261 
262  QString tooltip = QString("Use the F2/F3 keys to move a point up/down, the Del key to remove a point\nand the mouse "
263  "wheel to change the timestep.\n\nTimeStep:\t%1")
264  .arg(currentTS);
265  this->setToolTip(tooltip);
266 
267  fadeTimeStepIn();
268 }
269 
271 {
272  // Setup Widget
273  QWidget *m_TimeStepFader = new QWidget(this);
274  QHBoxLayout *layout = new QHBoxLayout(m_TimeStepFader);
275 
276  int x = (int)(this->geometry().x() + this->width() * 0.6);
277  int y = (int)(this->geometry().y() + this->height() * 0.8);
278  m_TimeStepFader->move(x, y);
279  m_TimeStepFader->resize(60, 55);
280  m_TimeStepFader->setLayout(layout);
281  m_TimeStepFader->setAttribute(Qt::WA_DeleteOnClose);
282 
283  layout->addWidget(m_TimeStepFaderLabel);
284  m_TimeStepFaderLabel->setAlignment(Qt::AlignCenter);
285  m_TimeStepFaderLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
286  m_TimeStepFaderLabel->setLineWidth(2);
287  m_TimeStepFaderLabel->setText(QString("%1").arg(this->m_PointListModel->GetTimeStep()));
288 
289  // give the widget opacity and some colour
290  QPalette pal = m_TimeStepFaderLabel->palette();
291  QColor semiTransparentColor(139, 192, 223, 50);
292  QColor labelTransparentColor(0, 0, 0, 200);
293  pal.setColor(m_TimeStepFaderLabel->backgroundRole(), semiTransparentColor);
294  pal.setColor(m_TimeStepFaderLabel->foregroundRole(), labelTransparentColor);
295  m_TimeStepFaderLabel->setAutoFillBackground(true);
296  m_TimeStepFaderLabel->setPalette(pal);
297 
298  // show the widget
299  m_TimeStepFader->show();
300 
301  // and start the timer
302  m_TimeStepFaderLabel->setVisible(true);
303  QTimer::singleShot(2000, this, SLOT(fadeTimeStepOut()));
304 }
305 
307 {
308  m_TimeStepFaderLabel->hide();
309 }
310 
311 void QmitkPointListView::ctxMenu(const QPoint &pos)
312 {
313  QMenu *menu = new QMenu;
314 
315  // add Fading check
316  QAction *showFading = new QAction(this);
317  showFading->setCheckable(false); // TODO: reset when fading is working
318  showFading->setEnabled(false); // TODO: reset when fading is working
319  showFading->setText("Fade TimeStep");
320  connect(showFading, SIGNAL(triggered(bool)), this, SLOT(SetFading(bool)));
321  menu->addAction(showFading);
322 
323  // add Clear action
324  QAction *clearList = new QAction(this);
325  clearList->setText("Clear List");
326  connect(clearList, SIGNAL(triggered()), this, SLOT(ClearPointList()));
327  menu->addAction(clearList);
328 
329  // add Clear TimeStep action
330  QAction *clearTS = new QAction(this);
331  clearTS->setText("Clear current time step");
332  connect(clearTS, SIGNAL(triggered()), this, SLOT(ClearPointListTS()));
333  menu->addAction(clearTS);
334 
335  menu->exec(this->mapToGlobal(pos));
336 }
337 
339 {
340  m_showFading = onOff;
341 }
342 
344 {
346  return;
348  if (curPS->GetSize() == 0)
349  return;
350 
351  switch (QMessageBox::question(this,
352  tr("Clear Points"),
353  tr("Remove all points from the displayed list?"),
354  QMessageBox::Yes | QMessageBox::No,
355  QMessageBox::No))
356  {
357  case QMessageBox::Yes:
358  {
360  mitk::PointSet::PointsContainer *curPsPoints;
361  while (!curPS->IsEmptyTimeStep(0))
362  {
363  curPsPoints = curPS->GetPointSet()->GetPoints();
364  it = curPsPoints->Begin();
365  curPS->SetSelectInfo(it->Index(), true);
367  }
369  break;
370  }
371  case QMessageBox::No:
372  default:
373  break;
374  }
375 }
376 
378 {
379 }
380 
382 {
383  m_Snc1 = snc;
384 }
385 
387 {
388  m_Snc2 = snc;
389 }
390 
392 {
393  m_Snc3 = snc;
394 }
395 
397 {
398  if (snc == NULL)
399  return;
400  m_Sncs.insert(snc);
401 }
402 
404 {
405  if (snc == NULL)
406  return;
407  m_Sncs.erase(snc);
408 }
DataType::PointsContainerIterator PointsIterator
Definition: mitkPointSet.h:137
A dialog for editing points directly (coordinates) via TextEdits.
void SetMultiWidget(QmitkStdMultiWidget *multiWidget)
If Multiwidget is set, the crosshair is automatically centering to the selected point As an alternati...
void AddSliceNavigationController(mitk::SliceNavigationController *snc)
Add a mitk::SliceNavigationController instance.
QmitkPointListView(QWidget *parent=0)
void SelectSliceByPoint(const mitk::Point3D &point)
Positions the SNC according to the specified point.
void OnPointDoubleClicked(const QModelIndex &index)
Filtering double click event for editing point coordinates via a dialog.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
void wheelEvent(QWheelEvent *event) override
change timestep of the current pointset by mouse wheel
PointType GetPoint(PointIdentifier id, int t=0) const
Get the point with ID id in world coordinates.
mitk::SliceNavigationController * m_Snc3
unsigned int GetTimeSteps() const
Get the number of time steps from the TimeGeometry As the base data has not a data vector given by it...
Definition: mitkBaseData.h:346
void SetTimeStep(int t)
which time step to display/model
mitk::SliceNavigationController * m_Snc1
virtual void SetSelectInfo(int position, bool selected, int t=0)
void SetSnc3(mitk::SliceNavigationController *snc)
Sets the SliceNavigationController of the three 2D Renderwindows. If they are defined, they can be used to automatically set the crosshair to the selected point.
Controls the selection of the slice the associated BaseRenderer will display.
void SetPointSetNode(mitk::DataNode *pointSetNode)
which point set to work on
DataType::PointIdentifier PointIdentifier
Definition: mitkPointSet.h:135
std::set< mitk::SliceNavigationController * > m_Sncs
void SetSnc1(mitk::SliceNavigationController *snc)
Sets the SliceNavigationController of the three 2D Renderwindows. If they are defined, they can be used to automatically set the crosshair to the selected point.
bool GetPointForModelIndex(const QModelIndex &index, mitk::PointSet::PointType &p, mitk::PointSet::PointIdentifier &id) const
get point and point ID that correspond to a given QModelIndex
QmitkPointListModel * m_PointListModel
int GetTimeStep() const
which time step to display/model
Data structure which stores a set of points. Superclass of mitk::Mesh.
Definition: mitkPointSet.h:79
virtual DataType::Pointer GetPointSet(int t=0) const
returns the pointset
static RenderingManager * GetInstance()
The custom viewer plugin implements simple viewer functionality presented in a customized look and feel It was developed to demonstrate extensibility and customizability of the blueberry application framework As an example for the GUI customization capabilities provided by the BlueBerry application the custom viewer plugin was developed It features simple viewer functionality presented in a customized look and feel The custom viewer consists of two i e a viewer perspective and a DICOM perspective As part of the viewer an instance of QmitkDataManagerView allows for data selection Visualization of the selected data is then performed by a simple render window view According data can either be directly loaded from file or be imported as DICOM data DICOM import functionality is accessible from the DICOM perspective incorporating the QmitkDicomExternalDataWidget The customization of Qt Stylesheets is used to give the application a non native look and feel This is further emphasized by a Tab Widget like unification of the perspectives with the according perspective bar In addition to an absence of menu
void SetSnc2(mitk::SliceNavigationController *snc)
Sets the SliceNavigationController of the three 2D Renderwindows. If they are defined, they can be used to automatically set the crosshair to the selected point.
virtual int SearchSelectedPoint(int t=0) const
searches a selected point and returns the id of that point. If no point is found, then -1 is returned...
void SetFading(bool onOff)
Turn TimeStep Fading On/Off.
void MoveCrossToPosition(const mitk::Point3D &newPosition)
void OnListViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
called when the selection of the view widget changes
DataType::PointsContainer PointsContainer
Definition: mitkPointSet.h:136
mitk::SliceNavigationController * m_Snc2
virtual int GetNumberOfSelected(int t=0) const
returns the number of selected points
void ClearPointListTS()
delete all points in the list in the current timestep
QmitkStdMultiWidget * GetMultiWidget() const
return the QmitkStdMultiWidget that is used for updating render window crosshair
void OnPointSetSelectionChanged()
called when the point set data structure changes
const mitk::PointSet * GetPointSet() const
which point set to work on
void keyPressEvent(QKeyEvent *e) override
react to F2, F3 and DEL keys
bool GetModelIndexForPointID(mitk::PointSet::PointIdentifier id, QModelIndex &index) const
returns a QModelIndex for a given point ID
void ClearPointList()
Delete all points in the list.
QmitkStdMultiWidget * m_MultiWidget
used to position the planes on a selected point
void ctxMenu(const QPoint &pos)
open ContextMenu
void fadeTimeStepOut()
fade the shown timestep out
mitk::PointSet * GetPointSet() const
which point set to work on
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
void SetPointSetNode(mitk::DataNode *pointSetNode)
assign a point set for observation
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
void fadeTimeStepIn()
fade a label with the currently shown timestep in
void SignalPointSelectionChanged()
this signal is emmitted, if the selection of a point in the pointset is changed
void RemoveSliceNavigationController(mitk::SliceNavigationController *snc)
Remove a mitk::SliceNavigationController instance.
void SetPoint(mitk::PointSet *_PointSet, mitk::PointSet::PointIdentifier _PointId, int timestep=0)