CustusX  15.4.0-beta
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxDataViewSelectionWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
33 #include "cxToolListWidget.h"
34 #include "cxData.h"
35 #include <QListWidgetItem>
36 #include <QDir>
37 #include <QHBoxLayout>
38 #include <QDropEvent>
39 #include <QMimeData>
40 #include <QAction>
41 #include <QLabel>
42 #include <QMenu>
43 #include "cxEnumConverter.h"
44 #include "cxLogger.h"
45 #include "cxImageAlgorithms.h"
46 #include "cxImage.h"
47 #include "cxPatientModelService.h"
48 #include "cxViewService.h"
49 #include "cxViewGroupData.h"
50 #include "cxLogger.h"
51 
52 
53 //TODO: remove
54 #include "cxLegacySingletons.h"
55 
56 namespace cx
57 {
58 
60  QListWidget(parent)
61 {
62 // connect(this, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(toolClickedSlot(QListWidgetItem*)));
63 
64  this->setSelectionBehavior(QAbstractItemView::SelectItems);
65  this->setSelectionMode(QAbstractItemView::SingleSelection);
66 
67  connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChangedSlot()));
68 
69 // this->setMinimumSize(QSize(20, 20));
70  this->setSizePolicy(QSizePolicy::Expanding, this->sizePolicy().verticalPolicy());
71 
72 }
73 
81 {
82  return QSize(80,20);
83 }
84 
85 //QSize DataListWidget::minimumSizeHint () const
86 //{
87 // return QSize(20,20);
88 //}
89 
91 {}
92 
93 void DataListWidget::populate(QStringList dataUids)
94 {
95  this->clear();
96 
97  foreach(QString data, dataUids)
98  {
99  this->populateData(data);
100  }
101  emit listSizeChanged();
102 }
103 
104 void DataListWidget::itemSelectionChangedSlot()
105 {
106  QList<QListWidgetItem*> items = this->selectedItems();
107  if (items.empty())
108  return;
109  ImagePtr image = patientService()->getData<Image>(items[0]->data(Qt::UserRole).toString());
110  if (image)
111  patientService()->setActiveImage(image);
112 
113 }
114 
115 void DataListWidget::populateData(QString uid, bool indent, QListWidgetItem* after)
116 {
117  DataPtr data = patientService()->getData(uid);
118  if (!data)
119  return;
120 
121  QListWidgetItem* item = new QListWidgetItem(data->getName());
122  item->setData(Qt::UserRole, uid);
123 
124  if (indent)
125  item->setText(" " + item->text());
126 
127  if (boost::dynamic_pointer_cast<Image>(data))
128  item->setIcon(QIcon(":/icons/volume.png"));
129  else
130  item->setIcon(QIcon(":/icons/surface.png"));
131 
132  if (after)
133  {
134  std::cout << "set " << item->text() << " before: " << after->text() << " " << this->currentRow() << std::endl;
135  this->setCurrentItem(after);
136  this->insertItem(this->currentRow(), item);
137  this->setCurrentItem(item);
138  }
139  else
140  {
141  this->addItem(item);
142  }
143 
144  item->setToolTip(item->text());
145 
146  emit listSizeChanged();
147 }
148 
149 //---------------------------------------------------------------------------------------------------------------------
150 //---------------------------------------------------------------------------------------------------------------------
151 //---------------------------------------------------------------------------------------------------------------------
152 
153 
155  DataListWidget(parent)
156 {
157  this->setDropIndicatorShown(false);
158  this->setDragEnabled(true);
159 
160  connect(patientService().get(), SIGNAL(dataAddedOrRemoved()), this, SLOT(populateAllDataList()));
161 }
162 
164 {}
165 
166 void AllDataListWidget::mousePressEvent(QMouseEvent *event)
167 {
168  QListWidget::mousePressEvent(event);
169 }
170 
171 void AllDataListWidget::mouseMoveEvent(QMouseEvent *event)
172 {
173  QListWidget::mouseMoveEvent(event);
174 }
175 
176 void AllDataListWidget::populateAllDataList()
177 {
178  this->clear();
179 
180  //add actions to the actiongroups and the contextmenu
181  std::vector<DataPtr> sorted = sortOnGroupsAndAcquisitionTime(patientService()->getData());
182  QString lastDataActionUid = "________________________";
183  for (std::vector<DataPtr>::iterator iter=sorted.begin(); iter!=sorted.end(); ++iter)
184  {
185  QString uid = (*iter)->getUid();
186 
187  if (uid.contains(lastDataActionUid))
188  {
189  this->populateData(uid, true);
190  }
191  else
192  {
193  this->populateData(uid, false);
194  lastDataActionUid = uid;
195  }
196 
197  }
198 
199  emit listSizeChanged();
200 }
201 
202 
203 //---------------------------------------------------------------------------------------------------------------------
204 //---------------------------------------------------------------------------------------------------------------------
205 //---------------------------------------------------------------------------------------------------------------------
206 
207 
208 
210  DataListWidget(parent)
211 {
212  this->setContextMenuPolicy(Qt::CustomContextMenu);
213 
214  this->setDropIndicatorShown(true);
215  this->setDragEnabled(true);
216  this->setAcceptDrops(true);
217  this->viewport()->setAcceptDrops(true);
218  this->setDragDropOverwriteMode(true);
219 
220  connect(this, SIGNAL(userChangedList()), this, SLOT(userChangedListSlot()));
221  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenuSlot(const QPoint &)));
222 }
223 
224 
226 {}
227 
228 
229 
231 {
232  QStringList data = this->getData();
233  std::reverse(data.begin(), data.end());
234 
235  mViewGroupData->clearData();
236  for (int i=0; i<data.size(); ++i)
237  {
238  DataPtr current = patientService()->getData(data[i]);
239  if (!current)
240  continue;
241  mViewGroupData->addData(current->getUid());
242  }
243 }
244 
245 void SelectedDataListWidget::keyPressEvent(QKeyEvent* event)
246 {
247  if (event->matches(QKeySequence::Delete) || event->matches(QKeySequence::Back))
248  {
249  QList<QListWidgetItem*> items = this->selectedItems();
250  for (int i=0; i<items.size(); ++i)
251  delete items[i];
252  emit userChangedList();
253  emit listSizeChanged();
254  }
255 }
256 
261 QMap<int, QVariant> SelectedDataListWidget::convertFromCustomQtMimeFormat(const QMimeData* mimeData) const
262 {
263  QMap<int, QVariant> v;
264  if (!mimeData->hasFormat("application/x-qabstractitemmodeldatalist"))
265  return v;
266 
267  QByteArray itemData = mimeData->data("application/x-qabstractitemmodeldatalist");
268  QDataStream stream(&itemData, QIODevice::ReadOnly);
269  int r, c;
270 // QMap<int, QVariant> v;
271  stream >> r >> c >> v;
272 // std::cout << "var: " << r << " " << c << " " << v.size() << std::endl;
273 // if (!v.empty())
274 // {
275 // QString uid = v[Qt::UserRole].toString();
276 // std::cout << "v: " << " " << v.begin()->typeName() << " " << v.begin()->toString() << " uid= " << uid << std::endl;
277 //
280 // }
281  return v;
282 }
283 
284 void SelectedDataListWidget::dropEvent(QDropEvent *event)
285 {
286  if (event->source()==this)
287  {
288  std::cout << "drop this: " << event->mimeData()->formats().join(",") << std::endl;
289  event->setDropAction(Qt::MoveAction);
290  }
291 
292  QString sourceUid;
293  QMap<int, QVariant> sourceData = this->convertFromCustomQtMimeFormat(event->mimeData());
294  if (sourceData.contains(Qt::UserRole))
295  sourceUid = sourceData[Qt::UserRole].toString();
296 
297 // if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
298 // {
299 // QByteArray itemData = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
300 // QDataStream stream(&itemData, QIODevice::ReadOnly);
301 // int r, c;
302 // QMap<int, QVariant> v;
303 // stream >> r >> c >> v;
304 // std::cout << "var: " << r << " " << c << " " << v.size() << std::endl;
305 // if (!v.empty())
306 // {
307 // QString uid = v[Qt::UserRole].toString();
308 // std::cout << "v: " << " " << v.begin()->typeName() << " " << v.begin()->toString() << " uid= " << uid << std::endl;
309 //
311 // newUid = uid;
312 // }
313 // }
314 
315  QListWidgetItem* itemToDelete = 0;
316  for(int i=0; i < this->count(); ++i)
317  {
318  QListWidgetItem* item = this->item(i);
319  if (item->data(Qt::UserRole)==sourceUid)
320  itemToDelete = item;
321  }
322 
323 // std:: cout << "received dropEvent: " << event->mimeData()->text() << std::endl;
324 // this->populateData(event->mimeData()->text(), false, pos);
325 // event->setDropAction(Qt::MoveAction);
326 // event->accept();
327 // std::cout << "dropaction " << event->dropAction() << std::endl;
328  QListWidget::dropEvent(event);
329  if (event->source()!=this) // remove old item if new if moved in from external source
330  delete itemToDelete;
331 
332  emit userChangedList();
333  emit listSizeChanged();
334 }
335 
337 {
338  QStringList retval;
339 
340  for(int i=0; i < this->count(); ++i)
341  {
342  QListWidgetItem* item = this->item(i);
343  retval << item->data(Qt::UserRole).toString();
344  }
345 
346  return retval;
347 }
348 
349 void SelectedDataListWidget::deleteSlot()
350 {
351  if(!mItemToDelete)
352  {
353  reportDebug("Found no item to delete...");
354  return;
355  }
356  this->deleteItemSlot(mItemToDelete);
357 }
358 
359 void SelectedDataListWidget::deleteItemSlot(QListWidgetItem* item)
360 {
361  delete item;
362  emit userChangedList();
363  emit listSizeChanged();
364 }
365 
366 void SelectedDataListWidget::contextMenuSlot(const QPoint& point)
367 {
368  QWidget* sender = dynamic_cast<QWidget*>(this->sender());
369  QPoint pointGlobal = sender->mapToGlobal(point);
370  QMenu contextMenu(sender);
371 
372  QAction* action = new QAction("Remove", &contextMenu);
373 
374  QListWidgetItem* item = this->itemAt(point);
375  if(!item)
376  {
377  reportDebug("Found no item to delete...");
378  }
379  mItemToDelete = item;
380 
381  connect(action, SIGNAL(triggered()), this, SLOT(deleteSlot()));
382  contextMenu.addAction(action);
383 
384  contextMenu.exec(pointGlobal);
385 }
386 
388 {
389  this->clear();
390 
391  std::vector<DataPtr> sorted = mViewGroupData->getData();
392  std::reverse(sorted.begin(), sorted.end());
393  for (std::vector<DataPtr>::iterator iter=sorted.begin(); iter!=sorted.end(); ++iter)
394  {
395  QString uid = (*iter)->getUid();
396  this->populateData(uid);
397  }
398 
399  emit listSizeChanged();
400 }
401 
403 {
404  if (mViewGroupData)
405  {
406  disconnect(mViewGroupData.get(), SIGNAL(initialized()), this, SLOT(populateList()));
407  disconnect(mViewGroupData.get(), SIGNAL(dataViewPropertiesChanged(QString)), this, SLOT(populateList()));
408  }
409 
410  mViewGroupData = viewGroupData;
411 
412  if (mViewGroupData)
413  {
414  connect(mViewGroupData.get(), SIGNAL(initialized()), this, SLOT(populateList()));
415  connect(mViewGroupData.get(), SIGNAL(dataViewPropertiesChanged(QString)), this, SLOT(populateList()));
416  }
417 
418  this->populateList();
419 }
420 
421 
422 
423 //---------------------------------------------------------
424 //---------------------------------------------------------
425 //---------------------------------------------------------
426 
427 
428 class AbraClass : public QListWidget
429 {
430 public:
431  AbraClass(QWidget* parent) : QListWidget(parent) {}
432 protected:
433  void dropEvent(QDropEvent *event)
434  {
435 // QListWidgetItem* pos = NULL;
436 
437  if (event->source()==this)
438  {
439  std::cout << "drop this: " << event->mimeData()->formats().join(",") << std::endl;
440  event->setDropAction(Qt::MoveAction);
441  }
442 
443  QString newUid;
444  if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
445  {
446  QByteArray itemData = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
447  QDataStream stream(&itemData, QIODevice::ReadOnly);
448  int r, c;
449  QMap<int, QVariant> v;
450  stream >> r >> c >> v;
451  std::cout << "var: " << r << " " << c << " " << v.size() << std::endl;
452  if (!v.empty())
453  {
454  std::cout << "v: " << " " << v.begin()->typeName() << " " << v.begin()->toString() << std::endl;
455  newUid = v.begin()->toString();
456  }
457  }
458 
459  QListWidgetItem* itemToDelete = 0;
460  for(int i=0; i < this->count(); ++i)
461  {
462  QListWidgetItem* item = this->item(i);
463  if (item->text()==newUid)
464  itemToDelete = item;
465  }
466 
467  // std:: cout << "received dropEvent: " << event->mimeData()->text() << std::endl;
468 // this->populateData(event->mimeData()->text(), false, pos);
469 // event->setDropAction(Qt::MoveAction);
470 // event->accept();
471  std::cout << "dropaction " << event->dropAction() << std::endl;
472  QListWidget::dropEvent(event);
473  if (event->source()!=this) // remove old item if new if moved in from external source
474  delete itemToDelete;
475  }
476 
477 };
478 
479 class TestClass : public QListWidget
480 {
481 public:
482  TestClass(QWidget* parent) : QListWidget(parent) {}
483 protected:
484  void dropEvent(QDropEvent *event)
485  {
486  // ignore drop
487  event->setDropAction(Qt::MoveAction);
488  event->acceptProposedAction();
489 // QListWidget::dropEvent(event);
490  }
491 
492 };
493 
495 {
496  // TODO Auto-generated constructor stub
497  QHBoxLayout* layout = new QHBoxLayout(this);
498 
499  mSelectedDataListWidget = new SelectedDataListWidget(this);
500  mAllDataListWidget = new AllDataListWidget(this);
501 #if 0
502  TestClass* test = new TestClass(this);
503  test->addItem("test1");
504  test->addItem("test2");
505  test->addItem("test3");
506  test->addItem("test4");
507  //test->setDragDropMode(QAbstractItemView::InternalMove);
508  test->setDropIndicatorShown(false);
509  test->setDragEnabled(true);
510  test->setAcceptDrops(true);
511 
512  AbraClass* abra = new AbraClass(this);
513  abra->addItem("abra1");
514  abra->addItem("abra2");
515  abra->addItem("abra3");
516  abra->addItem("abra4");
517 // abra->setDragDropMode(QAbstractItemView::InternalMove);
518  abra->setDropIndicatorShown(true);
519  abra->setDragEnabled(true);
520  abra->setAcceptDrops(true);
521  abra->viewport()->setAcceptDrops(true);
522  abra->setDragDropOverwriteMode(true);
523 
524  layout->addWidget(test);
525  layout->addWidget(abra);
526 #endif
527 
528  QVBoxLayout* selLayout = new QVBoxLayout;
529  mVisibleLabel = new QLabel("Visible", this);
530  selLayout->addWidget(mVisibleLabel);
531  selLayout->addWidget(mSelectedDataListWidget);
532  layout->addLayout(selLayout);
533 
534  QVBoxLayout* allLayout = new QVBoxLayout;
535  allLayout->addWidget(new QLabel("All"));
536  allLayout->addWidget(mAllDataListWidget);
537  layout->addLayout(allLayout);
538 
539  connect(viewService().get(), SIGNAL(activeViewChanged()), this, SLOT(viewGroupChangedSlot()));
540  this->viewGroupChangedSlot();
541 }
542 
543 void DataViewSelectionWidget::viewGroupChangedSlot()
544 {
545  int vg = viewService()->getActiveGroup();
546  if (vg<0)
547  vg = 0;
548 
549  ViewGroupDataPtr group = viewService()->getGroup(vg);
550  if (group)
551  mSelectedDataListWidget->setViewGroupData(group);
552 
553  mVisibleLabel->setText("Visible in group "+qstring_cast(vg));
554 }
555 
556 
558 {
559  // TODO Auto-generated destructor stub
560 }
561 
562 }
QString qstring_cast(const T &val)
boost::shared_ptr< class ViewGroupData > ViewGroupDataPtr
Definition: cxViewGroup.h:50
void setViewGroupData(ViewGroupDataPtr viewGroupData)
void mouseMoveEvent(QMouseEvent *event)
DataListWidget(QWidget *parent=NULL)
void mousePressEvent(QMouseEvent *event)
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
virtual QSize sizeHint() const
TestClass(QWidget *parent)
void listSizeChanged()
emitted whenever the count changes
virtual void dropEvent(QDropEvent *event)
void userChangedList()
emitted whenever the user changes the list
void populateData(QString uid, bool indent=false, QListWidgetItem *after=NULL)
boost::shared_ptr< class Data > DataPtr
QMap< int, QVariant > convertFromCustomQtMimeFormat(const QMimeData *mimeData) const
std::vector< T > sortOnGroupsAndAcquisitionTime(std::map< QString, T > input)
void populate(QStringList dataUids)
A volumetric data set.
Definition: cxImage.h:66
QStringList getData()
get absolute file path to all tools currently in the list
AbraClass(QWidget *parent)
void dropEvent(QDropEvent *event)
void dropEvent(QDropEvent *event)
cxLogicManager_EXPORT ViewServicePtr viewService()
cxLogicManager_EXPORT PatientModelServicePtr patientService()
DataViewSelectionWidget(QWidget *parent=NULL)
void reportDebug(QString msg)
Definition: cxLogger.cpp:89
SelectedDataListWidget(QWidget *parent=NULL)
AllDataListWidget(QWidget *parent=NULL)