Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
QmitkPointListWidget.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 #include "QmitkPointListWidget.h"
17 
18 #include <QDir>
19 #include <QFileDialog>
20 #include <QHBoxLayout>
21 #include <QMessageBox>
22 #include <mitkIOUtil.h>
23 
24 #include <QmitkEditPointDialog.h>
25 
27 
28 #include <mitkDataInteractor.h>
29 
30 QmitkPointListWidget::QmitkPointListWidget(QWidget *parent, int orientation)
31  : QWidget(parent),
32  m_PointListView(NULL),
33  m_MultiWidget(NULL),
34  m_PointSetNode(NULL),
35  m_Orientation(0),
36  m_MovePointUpBtn(NULL),
37  m_MovePointDownBtn(NULL),
38  m_RemovePointBtn(NULL),
39  m_SavePointsBtn(NULL),
40  m_LoadPointsBtn(NULL),
41  m_ToggleAddPoint(NULL),
42  m_AddPoint(NULL),
43  m_Snc1(NULL),
44  m_Snc2(NULL),
45  m_Snc3(NULL),
46  m_DataInteractor(NULL),
47  m_TimeStep(0),
48  m_EditAllowed(true),
49  m_NodeObserverTag(0)
50 {
52 
53  if (orientation != 0)
54  m_Orientation = orientation;
55 
56  SetupUi();
58  ObserveNewNode(NULL);
59 }
60 
62 {
63  m_DataInteractor = NULL;
64 
66  {
67  m_PointSetNode->RemoveObserver(m_NodeObserverTag);
69  }
70 
71  m_MultiWidget = NULL;
72  delete m_PointListView;
73 }
74 
76 {
77  connect(this->m_LoadPointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnLoadPoints()));
78  connect(this->m_SavePointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnSavePoints()));
79  connect(this->m_MovePointUpBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointUp()));
80  connect(this->m_MovePointDownBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointDown()));
81  connect(this->m_RemovePointBtn, SIGNAL(clicked()), this, SLOT(RemoveSelectedPoint()));
82  connect(this->m_ToggleAddPoint, SIGNAL(toggled(bool)), this, SLOT(OnBtnAddPoint(bool)));
83  connect(this->m_AddPoint, SIGNAL(clicked()), this, SLOT(OnBtnAddPointManually()));
84  connect(this->m_PointListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnListDoubleClick()));
85  connect(this->m_PointListView, SIGNAL(SignalPointSelectionChanged()), this, SLOT(OnPointSelectionChanged()));
86 }
87 
89 {
90  // Setup the buttons
91 
92  m_ToggleAddPoint = new QPushButton();
93  m_ToggleAddPoint->setMaximumSize(25, 25);
94  m_ToggleAddPoint->setCheckable(true);
95  m_ToggleAddPoint->setToolTip("Toggle point editing (use SHIFT + Left Mouse Button to add Points)");
96  QIcon iconAdd(":/QtWidgetsExt/btnSetPoints.xpm");
97  m_ToggleAddPoint->setIcon(iconAdd);
98 
99  m_AddPoint = new QPushButton();
100  m_AddPoint->setMaximumSize(25, 25);
101  m_AddPoint->setToolTip("Manually add point");
102  QIcon iconAddManually(":/QtWidgetsExt/btnSetPointsManually.xpm");
103  m_AddPoint->setIcon(iconAddManually);
104 
105  m_RemovePointBtn = new QPushButton();
106  m_RemovePointBtn->setMaximumSize(25, 25);
107  const QIcon iconDel(":/QtWidgetsExt/btnClear.xpm");
108  m_RemovePointBtn->setIcon(iconDel);
109  m_RemovePointBtn->setToolTip("Erase one point from list (Hotkey: DEL)");
110 
111  m_MovePointUpBtn = new QPushButton();
112  m_MovePointUpBtn->setMaximumSize(25, 25);
113  const QIcon iconUp(":/QtWidgetsExt/btnUp.xpm");
114  m_MovePointUpBtn->setIcon(iconUp);
115  m_MovePointUpBtn->setToolTip("Swap selected point upwards (Hotkey: F2)");
116 
117  m_MovePointDownBtn = new QPushButton();
118  m_MovePointDownBtn->setMaximumSize(25, 25);
119  const QIcon iconDown(":/QtWidgetsExt/btnDown.xpm");
120  m_MovePointDownBtn->setIcon(iconDown);
121  m_MovePointDownBtn->setToolTip("Swap selected point downwards (Hotkey: F3)");
122 
123  m_SavePointsBtn = new QPushButton();
124  m_SavePointsBtn->setMaximumSize(25, 25);
125  QIcon iconSave(":/QtWidgetsExt/btnSave.xpm");
126  m_SavePointsBtn->setIcon(iconSave);
127  m_SavePointsBtn->setToolTip("Save points to file");
128 
129  m_LoadPointsBtn = new QPushButton();
130  m_LoadPointsBtn->setMaximumSize(25, 25);
131  QIcon iconLoad(":/QtWidgetsExt/btnLoad.xpm");
132  m_LoadPointsBtn->setIcon(iconLoad);
133  m_LoadPointsBtn->setToolTip("Load list of points from file (REPLACES current content)");
134 
135  int i;
136 
137  QBoxLayout *lay1;
138  QBoxLayout *lay2;
139 
140  switch (m_Orientation)
141  {
142  case 0:
143  lay1 = new QVBoxLayout(this);
144  lay2 = new QHBoxLayout();
145  i = 0;
146  break;
147 
148  case 1:
149  lay1 = new QHBoxLayout(this);
150  lay2 = new QVBoxLayout();
151  i = -1;
152  break;
153 
154  case 2:
155  lay1 = new QHBoxLayout(this);
156  lay2 = new QVBoxLayout();
157  i = 0;
158  break;
159 
160  default:
161  lay1 = new QVBoxLayout(this);
162  lay2 = new QHBoxLayout();
163  i = -1;
164  break;
165  }
166 
167  // setup Layouts
168 
169  this->setLayout(lay1);
170  lay1->addLayout(lay2);
171 
172  lay2->stretch(true);
173  lay2->addWidget(m_ToggleAddPoint);
174  lay2->addWidget(m_AddPoint);
175  lay2->addWidget(m_RemovePointBtn);
176  lay2->addWidget(m_MovePointUpBtn);
177  lay2->addWidget(m_MovePointDownBtn);
178  lay2->addWidget(m_SavePointsBtn);
179  lay2->addWidget(m_LoadPointsBtn);
180 
181  lay1->insertWidget(i, m_PointListView);
182  this->setLayout(lay1);
183 }
184 
186 {
187  if (newPs == NULL)
188  return;
189 
190  this->m_PointSetNode->SetData(newPs);
191  dynamic_cast<QmitkPointListModel *>(this->m_PointListView->model())->SetPointSetNode(m_PointSetNode);
193 }
194 
196 {
197  if (m_DataInteractor.IsNotNull())
198  m_DataInteractor->SetDataNode(newNode);
199 
200  ObserveNewNode(newNode);
201  dynamic_cast<QmitkPointListModel *>(this->m_PointListView->model())->SetPointSetNode(newNode);
202 }
203 
205 {
206  if ((dynamic_cast<mitk::PointSet *>(m_PointSetNode->GetData())) == NULL)
207  return; // don't write empty point sets. If application logic requires something else then do something else.
208  if ((dynamic_cast<mitk::PointSet *>(m_PointSetNode->GetData()))->GetSize() == 0)
209  return;
210 
211  // take the previously defined name of node as proposal for filename
212  std::string nodeName = m_PointSetNode->GetName();
213  nodeName = "/" + nodeName + ".mps";
214  QString fileNameProposal = QString();
215  fileNameProposal.append(nodeName.c_str());
216 
217  QString aFilename = QFileDialog::getSaveFileName(
218  NULL, "Save point set", QDir::currentPath() + fileNameProposal, "MITK Pointset (*.mps)");
219  if (aFilename.isEmpty())
220  return;
221 
222  try
223  {
224  mitk::IOUtil::Save(m_PointSetNode->GetData(), aFilename.toStdString());
225  }
226  catch (...)
227  {
228  QMessageBox::warning(this,
229  "Save point set",
230  QString("File writer reported problems writing %1\n\n"
231  "PLEASE CHECK output file!")
232  .arg(aFilename));
233  }
234 }
235 
237 {
238  // get the name of the file to load
239  QString filename = QFileDialog::getOpenFileName(NULL, "Open MITK Pointset", "", "MITK Point Sets (*.mps)");
240  if (filename.isEmpty())
241  return;
242 
243  // attempt to load file
244  try
245  {
246  mitk::PointSet::Pointer pointSet = mitk::IOUtil::LoadPointSet(filename.toStdString());
247  if (pointSet.IsNull())
248  {
249  QMessageBox::warning(this, "Load point set", QString("File reader could not read %1").arg(filename));
250  return;
251  }
252 
253  // loading successful
254 
255  this->SetPointSet(pointSet);
256  }
257  catch (...)
258  {
259  QMessageBox::warning(this, "Load point set", QString("File reader collapsed while reading %1").arg(filename));
260  }
261  emit PointListChanged();
263 }
264 
266 {
267  return dynamic_cast<mitk::PointSet *>(m_PointSetNode->GetData());
268 }
269 
271 {
272  return m_PointSetNode;
273 }
274 
276 {
277  this->m_MultiWidget = multiWidget;
278  m_PointListView->SetMultiWidget(multiWidget);
279 }
280 
282 {
283  if (!m_PointSetNode)
284  return;
285  mitk::PointSet *pointSet = dynamic_cast<mitk::PointSet *>(m_PointSetNode->GetData());
286  if (!pointSet)
287  return;
288  if (pointSet->GetSize() == 0)
289  return;
290 
291  QmitkPointListModel *pointListModel = dynamic_cast<QmitkPointListModel *>(m_PointListView->model());
292  pointListModel->RemoveSelectedPoint();
293  emit PointListChanged();
294 }
295 
297 {
298  if (!m_PointSetNode)
299  return;
300  mitk::PointSet *pointSet = dynamic_cast<mitk::PointSet *>(m_PointSetNode->GetData());
301  if (!pointSet)
302  return;
303  if (pointSet->GetSize() == 0)
304  return;
305 
306  QmitkPointListModel *pointListModel = dynamic_cast<QmitkPointListModel *>(m_PointListView->model());
307  pointListModel->MoveSelectedPointDown();
308  emit PointListChanged();
309 }
310 
312 {
313  if (!m_PointSetNode)
314  return;
315  mitk::PointSet *pointSet = dynamic_cast<mitk::PointSet *>(m_PointSetNode->GetData());
316  if (!pointSet)
317  return;
318  if (pointSet->GetSize() == 0)
319  return;
320 
321  QmitkPointListModel *pointListModel = dynamic_cast<QmitkPointListModel *>(m_PointListView->model());
322  pointListModel->MoveSelectedPointUp();
323  emit PointListChanged();
324 }
325 
327 {
328  if (m_PointSetNode.IsNotNull())
329  {
330  if (checked)
331  {
332  m_DataInteractor = m_PointSetNode->GetDataInteractor();
333  // If no data Interactor is present create a new one
334  if (m_DataInteractor.IsNull())
335  {
336  // Create PointSetData Interactor
338  // Load the according state machine for regular point set interaction
339  m_DataInteractor->LoadStateMachine("PointSet.xml");
340  // Set the configuration file that defines the triggers for the transitions
341  m_DataInteractor->SetEventConfig("PointSetConfig.xml");
342  // set the DataNode (which already is added to the DataStorage
343  m_DataInteractor->SetDataNode(m_PointSetNode);
344  }
345  }
346  else
347  {
348  m_PointSetNode->SetDataInteractor(NULL);
349  m_DataInteractor = NULL;
350  }
351  emit EditPointSets(checked);
352  }
353 }
354 
356 {
357  mitk::PointSet *pointSet = this->GetPointSet();
358 
359  mitk::PointSet::PointsIterator maxIt = pointSet->GetMaxId();
360  mitk::PointSet::PointIdentifier maxId = maxIt->Index();
361 
362  QmitkEditPointDialog editPointDialog(this);
363  editPointDialog.SetPoint(pointSet, maxId + 1, m_TimeStep);
364  editPointDialog.exec();
365 }
366 
368 {
369 }
370 
372 {
373  emit this->PointSelectionChanged();
374 }
375 
377 {
378 }
379 
381 {
382  m_EditAllowed = enabled;
383  if (enabled == false)
384  m_ToggleAddPoint->setEnabled(false);
385  else
386  m_ToggleAddPoint->setEnabled(true);
387  OnBtnAddPoint(enabled);
388 }
389 
391 {
392  if (m_DataInteractor.IsNotNull())
393  m_DataInteractor->SetDataNode(node);
394 
395  // remove old observer
396  if (m_PointSetNode)
397  {
398  if (m_DataInteractor)
399  {
400  m_DataInteractor = NULL;
401  m_ToggleAddPoint->setChecked(false);
402  }
403 
404  m_PointSetNode->RemoveObserver(m_NodeObserverTag);
405  m_NodeObserverTag = 0;
406  }
407 
408  m_PointSetNode = node;
409  // add new observer if necessary
410  if (m_PointSetNode)
411  {
414  command->SetCallbackFunction(this, &QmitkPointListWidget::OnNodeDeleted);
415  m_NodeObserverTag = m_PointSetNode->AddObserver(itk::DeleteEvent(), command);
416  }
417  else
418  {
419  m_NodeObserverTag = 0;
420  }
421 
422  if (m_EditAllowed == true)
423  m_ToggleAddPoint->setEnabled(m_PointSetNode);
424  else
425  m_ToggleAddPoint->setEnabled(false);
426 
427  m_RemovePointBtn->setEnabled(m_PointSetNode);
428  m_LoadPointsBtn->setEnabled(m_PointSetNode);
429  m_SavePointsBtn->setEnabled(m_PointSetNode);
430  m_AddPoint->setEnabled(m_PointSetNode);
431 }
432 
433 void QmitkPointListWidget::OnNodeDeleted(const itk::EventObject &)
434 {
435  if (m_PointSetNode.IsNotNull() && !m_NodeObserverTag)
436  m_PointSetNode->RemoveObserver(m_NodeObserverTag);
437  m_NodeObserverTag = 0;
438  m_PointSetNode = NULL;
440  m_ToggleAddPoint->setEnabled(false);
441 
442  m_RemovePointBtn->setEnabled(false);
443  m_LoadPointsBtn->setEnabled(false);
444  m_SavePointsBtn->setEnabled(false);
445  m_AddPoint->setEnabled(false);
446 }
447 
449 {
450  if (snc == NULL)
451  {
453  }
454  else
455  {
457  }
458  m_Snc1 = snc;
459 }
460 
462 {
463  if (snc == NULL)
464  {
466  }
467  else
468  {
470  }
471  m_Snc2 = snc;
472 }
473 
475 {
476  if (snc == NULL)
477  {
479  }
480  else
481  {
483  }
484  m_Snc3 = snc;
485 }
486 
488 {
490 }
491 
493 {
495 }
496 
498 {
499  m_ToggleAddPoint->setChecked(false);
500 }
DataType::PointsContainerIterator PointsIterator
Definition: mitkPointSet.h:137
PointsIterator GetMaxId(int t=0)
Get an iterator to the max ID element if existent. Return End() otherwise.
static void Save(const mitk::BaseData *data, const std::string &path)
Save a mitk::BaseData instance.
Definition: mitkIOUtil.cpp:824
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 RemoveSliceNavigationController(mitk::SliceNavigationController *snc)
Remove a mitk::SliceNavigationController instance.
itk::SmartPointer< Self > Pointer
void AddSliceNavigationController(mitk::SliceNavigationController *snc)
Add a mitk::SliceNavigationController instance.
QmitkPointListWidget(QWidget *parent=0, int orientation=0)
virtual int GetSize(unsigned int t=0) const
returns the current size of the point-list
void OnBtnAddPoint(bool checked)
void PointListChanged()
signal to inform about cleared or loaded point sets
void SetPointSet(mitk::PointSet *newPs)
assign a point set (contained in a node of DataStorage) for observation
void EditPointSets(bool active)
signal to inform about the state of the EditPointSetButton, whether an interactor for setting points ...
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.
QmitkStdMultiWidget * m_MultiWidget
GUI widget for handling mitk::PointSet.
QPushButton * m_MovePointDownBtn
Controls the selection of the slice the associated BaseRenderer will display.
QmitkPointListView * m_PointListView
DataType::PointIdentifier PointIdentifier
Definition: mitkPointSet.h:135
void PointSelectionChanged()
signal to inform that the selection of a point in the pointset has changed
void SetPointSetNode(mitk::DataNode *newNode)
assign a point set (contained in a node of DataStorage) for observation
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.
mitk::DataNode::Pointer m_PointSetNode
void OnPointSelectionChanged()
pass through signal from PointListView that point selection has changed
Data structure which stores a set of points. Superclass of mitk::Mesh.
Definition: mitkPointSet.h:79
void ObserveNewNode(mitk::DataNode *node)
mitk::SliceNavigationController * m_Snc3
static RenderingManager * GetInstance()
static const std::string filename
static mitk::PointSet::Pointer LoadPointSet(const std::string &path)
LoadPointSet Convenience method to load an arbitrary mitkPointSet.
Definition: mitkIOUtil.cpp:619
void DeactivateInteractor(bool deactivate)
mitk::DataNode * GetPointSetNode()
mitk::DataInteractor::Pointer m_DataInteractor
void UnselectEditButton()
Unselects the edit button if it is selected.
void SetMultiWidget(QmitkStdMultiWidget *multiWidget)
assign a QmitkStdMultiWidget for updating render window crosshair
mitk::SliceNavigationController * m_Snc2
void AddSliceNavigationController(mitk::SliceNavigationController *snc)
Add a mitk::SliceNavigationController instance.
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.
void EnableEditButton(bool enabled)
mitk::PointSet * GetPointSet()
void OnNodeDeleted(const itk::EventObject &e)
itk observer for node "delete" events
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
mitk::SliceNavigationController * m_Snc1
void RemoveSliceNavigationController(mitk::SliceNavigationController *snc)
Remove a mitk::SliceNavigationController instance.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.
void SetPoint(mitk::PointSet *_PointSet, mitk::PointSet::PointIdentifier _PointId, int timestep=0)