Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
QmitkPropertyItemDelegate.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 
18 #include "QmitkPropertyItemModel.h"
19 #include <QApplication>
20 #include <QColorDialog>
21 #include <QComboBox>
22 #include <QHBoxLayout>
23 #include <QLineEdit>
24 #include <QPaintEvent>
25 #include <QPainter>
26 #include <QSpinBox>
27 #include <QToolButton>
28 #include <algorithm>
29 #include <mitkBaseProperty.h>
33 #include <usGetModuleContext.h>
34 #include <usModuleContext.h>
35 #include <usServiceReference.h>
36 
38 {
39  us::ModuleContext *context = us::GetModuleContext();
41  context->GetServiceReference<mitk::IPropertyExtensions>();
42 
43  return serviceRef ? context->GetService<mitk::IPropertyExtensions>(serviceRef) : NULL;
44 }
45 
47  : QWidget(parent), m_LineEdit(new QLineEdit), m_Button(new QToolButton)
48 {
49  m_LineEdit->setText(m_Color.name());
50  m_Button->setText("...");
51 
52  QHBoxLayout *layout = new QHBoxLayout;
53  layout->setContentsMargins(0, 0, 0, 0);
54  layout->setSpacing(0);
55 
56  layout->addWidget(m_LineEdit);
57  layout->addWidget(m_Button);
58 
59  this->setFocusProxy(m_LineEdit);
60  this->setLayout(layout);
61 
62  connect(m_LineEdit, SIGNAL(editingFinished()), this, SLOT(OnLineEditEditingFinished()));
63  connect(m_Button, SIGNAL(clicked()), this, SLOT(OnButtonClicked()));
64 }
65 
67 {
68 }
69 
71 {
72  return m_Color;
73 }
74 
75 void QmitkColorWidget::SetColor(QColor color)
76 {
77  m_Color = color;
78  m_LineEdit->setText(color.name());
79 }
80 
81 void QmitkColorWidget::OnLineEditEditingFinished()
82 {
83  if (!QColor::isValidColor(m_LineEdit->text()))
84  m_LineEdit->setText("#000000");
85 
86  m_Color.setNamedColor(m_LineEdit->text());
87 }
88 
89 void QmitkColorWidget::OnButtonClicked()
90 {
91  QColor color = QColorDialog::getColor(m_Color, QApplication::activeWindow());
92 
93  if (color.isValid())
94  {
95  this->SetColor(color);
96  emit ColorPicked();
97  }
98 }
99 
100 QmitkComboBoxListView::QmitkComboBoxListView(QComboBox *comboBox) : m_ComboBox(comboBox)
101 {
102 }
103 
105 {
106 }
107 
108 void QmitkComboBoxListView::paintEvent(QPaintEvent *event)
109 {
110  if (m_ComboBox != NULL)
111  {
112  QStyleOptionComboBox option;
113 
114  option.initFrom(m_ComboBox);
115  option.editable = m_ComboBox->isEditable();
116 
117  if (m_ComboBox->style()->styleHint(QStyle::SH_ComboBox_Popup, &option, m_ComboBox))
118  {
119  QStyleOptionMenuItem menuOption;
120  menuOption.initFrom(this);
121  menuOption.palette = this->palette();
122  menuOption.state = QStyle::State_None;
123  menuOption.checkType = QStyleOptionMenuItem::NotCheckable;
124  menuOption.menuRect = event->rect();
125  menuOption.maxIconWidth = 0;
126  menuOption.tabWidth = 0;
127 
128  QPainter painter(this->viewport());
129  m_ComboBox->style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOption, &painter, this);
130  }
131  }
132 
133  QListView::paintEvent(event);
134 }
135 
136 void QmitkComboBoxListView::resizeEvent(QResizeEvent *event)
137 {
138  int width = this->viewport()->width();
139  int height = this->contentsSize().height();
140 
141  this->resizeContents(width, height);
142 
143  QListView::resizeEvent(event);
144 }
145 
146 QStyleOptionViewItem QmitkComboBoxListView::viewOptions() const
147 {
148  QStyleOptionViewItem option = QListView::viewOptions();
149  option.showDecorationSelected = true;
150 
151  if (m_ComboBox != NULL)
152  option.font = m_ComboBox->font();
153 
154  return option;
155 }
156 
157 class PropertyEqualTo
158 {
159 public:
160  PropertyEqualTo(const mitk::BaseProperty *property) : m_Property(property) {}
161  bool operator()(const mitk::PropertyList::PropertyMapElementType &pair) const
162  {
163  return pair.second.GetPointer() == m_Property;
164  }
165 
166 private:
167  const mitk::BaseProperty *m_Property;
168 };
169 
170 QmitkPropertyItemDelegate::QmitkPropertyItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
171 {
172 }
173 
175 {
176 }
177 
179  const QStyleOptionViewItem &option,
180  const QModelIndex &index) const
181 {
182  QVariant data = index.data(Qt::EditRole);
183 
184  if (data.isValid())
185  {
186  if (data.type() == QVariant::Int)
187  {
188  QSpinBox *spinBox = new QSpinBox(parent);
189 
191  std::string name = this->GetPropertyName(index);
192 
193  if (extensions != NULL && !name.empty() && extensions->HasExtension(name))
194  {
196  dynamic_cast<mitk::IntPropertyExtension *>(extensions->GetExtension(name).GetPointer());
197 
198  if (extension.IsNotNull())
199  {
200  spinBox->setMinimum(extension->GetMinimum());
201  spinBox->setMaximum(extension->GetMaximum());
202  spinBox->setSingleStep(extension->GetSingleStep());
203  }
204  }
205 
206  connect(spinBox, SIGNAL(editingFinished()), this, SLOT(OnSpinBoxEditingFinished()));
207 
208  return spinBox;
209  }
210 
211  if (data.type() == QVariant::Double || static_cast<QMetaType::Type>(data.type()) == QMetaType::Float)
212  {
213  QDoubleSpinBox *spinBox = new QDoubleSpinBox(parent);
214 
216  std::string name = this->GetPropertyName(index);
217 
218  if (extensions != NULL && !name.empty() && extensions->HasExtension(name))
219  {
221  dynamic_cast<mitk::FloatPropertyExtension *>(extensions->GetExtension(name).GetPointer());
222 
223  if (extension.IsNotNull())
224  {
225  spinBox->setMinimum(extension->GetMinimum());
226  spinBox->setMaximum(extension->GetMaximum());
227  spinBox->setSingleStep(extension->GetSingleStep());
228  spinBox->setDecimals(extension->GetDecimals());
229  }
230  }
231  else
232  {
233  spinBox->setSingleStep(0.1);
234  spinBox->setDecimals(4);
235  }
236 
237  if (name == "opacity") // TODO
238  {
239  spinBox->setMinimum(0.0);
240  spinBox->setMaximum(1.0);
241  }
242 
243  connect(spinBox, SIGNAL(editingFinished()), this, SLOT(OnSpinBoxEditingFinished()));
244 
245  return spinBox;
246  }
247 
248  if (data.type() == QVariant::StringList)
249  {
250  QComboBox *comboBox = new QComboBox(parent);
251  comboBox->setView(new QmitkComboBoxListView(comboBox));
252 
253  comboBox->addItems(data.toStringList());
254 
255  connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnComboBoxCurrentIndexChanged(int)));
256 
257  return comboBox;
258  }
259 
260  if (data.type() == QVariant::Color)
261  {
262  QmitkColorWidget *colorWidget = new QmitkColorWidget(parent);
263 
264  connect(colorWidget, SIGNAL(ColorPicked()), this, SLOT(OnColorPicked()));
265 
266  return colorWidget;
267  }
268  }
269 
270  return QStyledItemDelegate::createEditor(parent, option, index);
271 }
272 
273 std::string QmitkPropertyItemDelegate::GetPropertyName(const QModelIndex &index) const
274 {
275  if (m_PropertyList.IsNotNull())
276  {
277  mitk::BaseProperty *property =
278  reinterpret_cast<mitk::BaseProperty *>(index.data(mitk::PropertyRole).value<void *>());
279  const mitk::PropertyList::PropertyMap *propertyMap = m_PropertyList->GetMap();
280 
281  mitk::PropertyList::PropertyMap::const_iterator it =
282  std::find_if(propertyMap->begin(), propertyMap->end(), PropertyEqualTo(property));
283 
284  if (it != propertyMap->end())
285  return it->first;
286  }
287 
288  return "";
289 }
290 
291 void QmitkPropertyItemDelegate::OnComboBoxCurrentIndexChanged(int)
292 {
293  QComboBox *comboBox = qobject_cast<QComboBox *>(sender());
294 
295  emit commitData(comboBox);
296  emit closeEditor(comboBox);
297 }
298 
299 void QmitkPropertyItemDelegate::OnSpinBoxEditingFinished()
300 {
301  QAbstractSpinBox *spinBox = qobject_cast<QAbstractSpinBox *>(sender());
302 
303  emit commitData(spinBox);
304  emit closeEditor(spinBox);
305 }
306 
307 void QmitkPropertyItemDelegate::OnColorPicked()
308 {
309  QmitkColorWidget *colorWidget = qobject_cast<QmitkColorWidget *>(sender());
310 
311  emit commitData(colorWidget);
312  emit closeEditor(colorWidget);
313 }
314 
315 void QmitkPropertyItemDelegate::paint(QPainter *painter,
316  const QStyleOptionViewItem &option,
317  const QModelIndex &index) const
318 {
319  QVariant data = index.data();
320 
321  if (index.column() == 1 && data.type() == QVariant::Color)
322  {
323  painter->fillRect(option.rect, data.value<QColor>());
324  return;
325  }
326 
327  QStyledItemDelegate::paint(painter, option, index);
328 }
329 
330 void QmitkPropertyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
331 {
332  QVariant data = index.data(Qt::EditRole);
333 
334  if (!data.isValid())
335  return;
336 
337  if (data.type() == QVariant::StringList)
338  {
339  QComboBox *comboBox = qobject_cast<QComboBox *>(editor);
340  comboBox->setCurrentIndex(comboBox->findText(index.data().toString()));
341  }
342  if (data.type() == QVariant::Color)
343  {
344  QmitkColorWidget *colorWidget = qobject_cast<QmitkColorWidget *>(editor);
345  colorWidget->SetColor(data.value<QColor>());
346  }
347  else
348  {
349  QStyledItemDelegate::setEditorData(editor, index);
350  }
351 }
352 
353 void QmitkPropertyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
354 {
355  QVariant data = index.data(Qt::EditRole);
356 
357  if (!data.isValid())
358  return;
359 
360  if (data.type() == QVariant::Int)
361  {
362  QSpinBox *spinBox = qobject_cast<QSpinBox *>(editor);
363  model->setData(index, spinBox->value());
364  }
365  else if (data.type() == QVariant::Double)
366  {
367  QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox *>(editor);
368  model->setData(index, spinBox->value());
369  }
370  else if (static_cast<QMetaType::Type>(data.type()) == QMetaType::Float)
371  {
372  QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox *>(editor);
373  model->setData(index, static_cast<float>(spinBox->value()));
374  }
375  else if (data.type() == QVariant::StringList)
376  {
377  QComboBox *comboBox = qobject_cast<QComboBox *>(editor);
378  model->setData(index, comboBox->currentText());
379  }
380  else if (data.type() == QVariant::Color)
381  {
382  QmitkColorWidget *colorWidget = qobject_cast<QmitkColorWidget *>(editor);
383  model->setData(index, colorWidget->GetColor());
384  }
385  else
386  {
387  QStyledItemDelegate::setModelData(editor, model, index);
388  }
389 }
390 
392 {
393  if (m_PropertyList.GetPointer() != propertyList)
394  m_PropertyList = propertyList;
395 }
void resizeEvent(QResizeEvent *event) override
std::pair< std::string, BaseProperty::Pointer > PropertyMapElementType
mitk::IPropertyExtensions * GetPropertyService()
QmitkComboBoxListView(QComboBox *comboBox=NULL)
void SetPropertyList(mitk::PropertyList *propertyList)
bool IsNotNull() const
virtual PropertyExtension::Pointer GetExtension(const std::string &propertyName, const std::string &className="")=0
Get the extension of a specific property.
Key-value list holding instances of BaseProperty.
Interface of property extensions service.
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
ObjectType * GetPointer() const
QStyleOptionViewItem viewOptions() const override
Abstract base class for properties.
std::map< std::string, BaseProperty::Pointer > PropertyMap
Property extension for mitk::IntProperty.
void SetColor(QColor color)
virtual bool HasExtension(const std::string &propertyName, const std::string &className="")=0
Check if a specific property has an extension.
int Int
Definition: jsoncpp.h:158
QmitkPropertyItemDelegate(QObject *parent=NULL)
std::vector< std::string > StringList
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
QmitkColorWidget(QWidget *parent=nullptr)
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Property extension for mitk::FloatProperty.
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void paintEvent(QPaintEvent *event) override
void setEditorData(QWidget *editor, const QModelIndex &index) const override
const PropertyMap * GetMap() const