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