Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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