Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
QmitkPropertyItemModel.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 
17 #include "QmitkPropertyItemModel.h"
18 #include "QmitkPropertyItem.h"
19 #include <QColor>
20 #include <mitkColorProperty.h>
22 #include <mitkIPropertyAliases.h>
23 #include <mitkIPropertyFilters.h>
24 #include <mitkProperties.h>
25 #include <mitkRenderingManager.h>
26 #include <mitkStringProperty.h>
27 
28 #include <usGetModuleContext.h>
29 #include <usModuleContext.h>
30 #include <usServiceReference.h>
31 
32 template <class T>
34 {
35  us::ModuleContext *context = us::GetModuleContext();
36  us::ServiceReference<T> serviceRef = context->GetServiceReference<T>();
37 
38  return serviceRef ? context->GetService<T>(serviceRef) : NULL;
39 }
40 
41 static QColor MitkToQt(const mitk::Color &color)
42 {
43  return QColor(color.GetRed() * 255, color.GetGreen() * 255, color.GetBlue() * 255);
44 }
45 
46 static mitk::BaseProperty *GetBaseProperty(const QVariant &data)
47 {
48  return data.isValid() ? reinterpret_cast<mitk::BaseProperty *>(data.value<void *>()) : NULL;
49 }
50 
51 static mitk::Color QtToMitk(const QColor &color)
52 {
53  mitk::Color mitkColor;
54 
55  mitkColor.SetRed(color.red() / 255.0f);
56  mitkColor.SetGreen(color.green() / 255.0f);
57  mitkColor.SetBlue(color.blue() / 255.0f);
58 
59  return mitkColor;
60 }
61 
62 class PropertyEqualTo
63 {
64 public:
65  PropertyEqualTo(const mitk::BaseProperty *property) : m_Property(property) {}
66  bool operator()(const mitk::PropertyList::PropertyMapElementType &pair) const
67  {
68  return pair.second.GetPointer() == m_Property;
69  }
70 
71 private:
72  const mitk::BaseProperty *m_Property;
73 };
74 
76  : QAbstractItemModel(parent),
77  m_ShowAliases(false),
78  m_FilterProperties(false),
79  m_PropertyAliases(NULL),
80  m_PropertyFilters(NULL)
81 {
82  this->CreateRootItem();
83 }
84 
86 {
87  this->SetNewPropertyList(NULL);
88 }
89 
90 int QmitkPropertyItemModel::columnCount(const QModelIndex &parent) const
91 {
92  if (parent.isValid())
93  return static_cast<QmitkPropertyItem *>(parent.internalPointer())->GetColumnCount();
94  else
95  return m_RootItem->GetColumnCount();
96 }
97 
98 void QmitkPropertyItemModel::CreateRootItem()
99 {
100  QList<QVariant> rootData;
101  rootData << "Property"
102  << "Value";
103 
104  m_RootItem.reset(new QmitkPropertyItem(rootData));
105 
106  this->beginResetModel();
107  this->endResetModel();
108 }
109 
110 QVariant QmitkPropertyItemModel::data(const QModelIndex &index, int role) const
111 {
112  if (!index.isValid())
113  return QVariant();
114 
115  mitk::BaseProperty *property =
116  index.column() == 1 ? GetBaseProperty(static_cast<QmitkPropertyItem *>(index.internalPointer())->GetData(1)) : NULL;
117 
118  if (role == Qt::DisplayRole)
119  {
120  if (index.column() == 0)
121  {
122  return static_cast<QmitkPropertyItem *>(index.internalPointer())->GetData(0);
123  }
124  else if (index.column() == 1 && property != NULL)
125  {
126  if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property))
127  return MitkToQt(colorProperty->GetValue());
128  else if (dynamic_cast<mitk::BoolProperty *>(property) == NULL)
129  return QString::fromStdString(property->GetValueAsString());
130  }
131  }
132  else if (index.column() == 1 && property != NULL)
133  {
134  if (role == Qt::CheckStateRole)
135  {
136  if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property))
137  return boolProperty->GetValue() ? Qt::Checked : Qt::Unchecked;
138  }
139  else if (role == Qt::EditRole)
140  {
141  if (dynamic_cast<mitk::StringProperty *>(property) != NULL)
142  {
143  return QString::fromStdString(property->GetValueAsString());
144  }
145  else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property))
146  {
147  return intProperty->GetValue();
148  }
149  else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property))
150  {
151  return floatProperty->GetValue();
152  }
153  else if (mitk::DoubleProperty *doubleProperty = dynamic_cast<mitk::DoubleProperty *>(property))
154  {
155  return doubleProperty->GetValue();
156  }
157  else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property))
158  {
159  QStringList values;
160 
161  for (mitk::EnumerationProperty::EnumConstIterator it = enumProperty->Begin(); it != enumProperty->End(); it++)
162  values << QString::fromStdString(it->second);
163 
164  return values;
165  }
166  else if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property))
167  {
168  return MitkToQt(colorProperty->GetValue());
169  }
170  }
171  else if (role == mitk::PropertyRole)
172  {
173  return QVariant::fromValue<void *>(property);
174  }
175  }
176 
177  return QVariant();
178 }
179 
180 QModelIndex QmitkPropertyItemModel::FindProperty(const mitk::BaseProperty *property)
181 {
182  if (property == NULL)
183  return QModelIndex();
184 
185  typedef mitk::PropertyList::PropertyMap PropertyMap;
186  const PropertyMap *propertyMap = m_PropertyList->GetMap();
187 
188  PropertyMap::const_iterator it = std::find_if(propertyMap->begin(), propertyMap->end(), PropertyEqualTo(property));
189 
190  if (it == propertyMap->end())
191  return QModelIndex();
192 
193  QString name = QString::fromStdString(it->first);
194 
195  if (!name.contains('.'))
196  {
197  QModelIndexList item = this->match(index(0, 0), Qt::DisplayRole, name, 1, Qt::MatchExactly);
198 
199  if (!item.empty())
200  return item[0];
201  }
202  else
203  {
204  QStringList names = name.split('.');
205  QModelIndexList items =
206  this->match(index(0, 0), Qt::DisplayRole, names.last(), -1, Qt::MatchRecursive | Qt::MatchExactly);
207 
208  foreach (QModelIndex item, items)
209  {
210  QModelIndex candidate = item;
211 
212  for (int i = names.length() - 1; i != 0; --i)
213  {
214  QModelIndex parent = item.parent();
215 
216  if (parent.parent() == QModelIndex())
217  {
218  if (parent.data() != names.first())
219  break;
220 
221  return candidate;
222  }
223 
224  if (parent.data() != names[i - 1])
225  break;
226 
227  item = parent;
228  }
229  }
230  }
231 
232  return QModelIndex();
233 }
234 
235 Qt::ItemFlags QmitkPropertyItemModel::flags(const QModelIndex &index) const
236 {
237  Qt::ItemFlags flags = QAbstractItemModel::flags(index);
238 
239  if (index.column() == 1)
240  {
241  if (index.data(Qt::EditRole).isValid())
242  flags |= Qt::ItemIsEditable;
243 
244  if (index.data(Qt::CheckStateRole).isValid())
245  flags |= Qt::ItemIsUserCheckable;
246  }
247 
248  return flags;
249 }
250 
252 {
253  return m_PropertyList.GetPointer();
254 }
255 
256 QVariant QmitkPropertyItemModel::headerData(int section, Qt::Orientation orientation, int role) const
257 {
258  if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
259  return m_RootItem->GetData(section);
260 
261  return QVariant();
262 }
263 
264 QModelIndex QmitkPropertyItemModel::index(int row, int column, const QModelIndex &parent) const
265 {
266  if (!this->hasIndex(row, column, parent))
267  return QModelIndex();
268 
269  QmitkPropertyItem *parentItem =
270  parent.isValid() ? static_cast<QmitkPropertyItem *>(parent.internalPointer()) : m_RootItem.get();
271 
272  QmitkPropertyItem *childItem = parentItem->GetChild(row);
273 
274  return childItem != NULL ? this->createIndex(row, column, childItem) : QModelIndex();
275 }
276 
278 {
279  bool updateAliases = m_ShowAliases != (m_PropertyAliases != NULL);
280  bool updateFilters = m_FilterProperties != (m_PropertyFilters != NULL);
281 
282  bool resetPropertyList = false;
283 
284  if (updateAliases)
285  {
286  m_PropertyAliases = m_ShowAliases ? GetPropertyService<mitk::IPropertyAliases>() : NULL;
287 
288  resetPropertyList = m_PropertyList.IsNotNull();
289  }
290 
291  if (updateFilters)
292  {
293  m_PropertyFilters = m_FilterProperties ? GetPropertyService<mitk::IPropertyFilters>() : NULL;
294 
295  if (!resetPropertyList)
296  resetPropertyList = m_PropertyList.IsNotNull();
297  }
298 
299  if (resetPropertyList)
300  this->SetNewPropertyList(m_PropertyList.GetPointer());
301 }
302 
303 void QmitkPropertyItemModel::OnPropertyDeleted(const itk::Object * /*property*/, const itk::EventObject &)
304 {
305  /*QModelIndex index = this->FindProperty(static_cast<const mitk::BaseProperty*>(property));
306 
307  if (index != QModelIndex())
308  this->reset();*/
309 }
310 
311 void QmitkPropertyItemModel::OnPropertyListDeleted(const itk::Object *)
312 {
313  this->CreateRootItem();
314 }
315 
316 void QmitkPropertyItemModel::OnPropertyModified(const itk::Object *property, const itk::EventObject &)
317 {
318  QModelIndex index = this->FindProperty(static_cast<const mitk::BaseProperty *>(property));
319 
320  if (index != QModelIndex())
321  emit dataChanged(index, index);
322 }
323 
324 QModelIndex QmitkPropertyItemModel::parent(const QModelIndex &child) const
325 {
326  if (!child.isValid())
327  return QModelIndex();
328 
329  QmitkPropertyItem *parentItem = static_cast<QmitkPropertyItem *>(child.internalPointer())->GetParent();
330 
331  if (parentItem == m_RootItem.get())
332  return QModelIndex();
333 
334  return this->createIndex(parentItem->GetRow(), 0, parentItem);
335 }
336 
337 int QmitkPropertyItemModel::rowCount(const QModelIndex &parent) const
338 {
339  if (parent.column() > 0)
340  return 0;
341 
342  QmitkPropertyItem *parentItem =
343  parent.isValid() ? static_cast<QmitkPropertyItem *>(parent.internalPointer()) : m_RootItem.get();
344 
345  return parentItem->GetChildCount();
346 }
347 
348 bool QmitkPropertyItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
349 {
350  if (!index.isValid() || index.column() != 1 || (role != Qt::EditRole && role != Qt::CheckStateRole))
351  return false;
352 
353  mitk::BaseProperty *property = GetBaseProperty(static_cast<QmitkPropertyItem *>(index.internalPointer())->GetData(1));
354 
355  if (property == NULL)
356  return false;
357 
358  if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property))
359  {
360  boolProperty->SetValue(value.toInt() == Qt::Checked ? true : false);
361  }
362  else if (mitk::StringProperty *stringProperty = dynamic_cast<mitk::StringProperty *>(property))
363  {
364  stringProperty->SetValue(value.toString().toStdString());
365  }
366  else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property))
367  {
368  intProperty->SetValue(value.toInt());
369  }
370  else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property))
371  {
372  floatProperty->SetValue(value.toFloat());
373  }
374  else if (mitk::DoubleProperty *doubleProperty = dynamic_cast<mitk::DoubleProperty *>(property))
375  {
376  doubleProperty->SetValue(value.toDouble());
377  }
378  else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property))
379  {
380  std::string selection = value.toString().toStdString();
381 
382  if (selection != enumProperty->GetValueAsString() && enumProperty->IsValidEnumerationValue(selection))
383  enumProperty->SetValue(selection);
384  }
385  else if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property))
386  {
387  colorProperty->SetValue(QtToMitk(value.value<QColor>()));
388  }
389 
390  m_PropertyList->InvokeEvent(itk::ModifiedEvent());
391  m_PropertyList->Modified();
392 
394 
395  return true;
396 }
397 
398 void QmitkPropertyItemModel::SetNewPropertyList(mitk::PropertyList *propertyList)
399 {
400  typedef mitk::PropertyList::PropertyMap PropertyMap;
401 
402  this->beginResetModel();
403 
404  if (m_PropertyList.IsNotNull())
405  {
407  this, &QmitkPropertyItemModel::OnPropertyListDeleted);
408  m_PropertyList.ObjectDelete.RemoveListener(delegate);
409 
410  const PropertyMap *propertyMap = m_PropertyList->GetMap();
411 
412  for (PropertyMap::const_iterator propertyIt = propertyMap->begin(); propertyIt != propertyMap->end(); ++propertyIt)
413  {
414  std::map<std::string, unsigned long>::const_iterator tagIt = m_PropertyModifiedTags.find(propertyIt->first);
415 
416  if (tagIt != m_PropertyModifiedTags.end())
417  propertyIt->second->RemoveObserver(tagIt->second);
418 
419  tagIt = m_PropertyDeletedTags.find(propertyIt->first);
420 
421  if (tagIt != m_PropertyDeletedTags.end())
422  propertyIt->second->RemoveObserver(tagIt->second);
423  }
424 
425  m_PropertyModifiedTags.clear();
426  m_PropertyDeletedTags.clear();
427  }
428 
429  m_PropertyList = propertyList;
430 
431  if (m_PropertyList.IsNotNull())
432  {
434  this, &QmitkPropertyItemModel::OnPropertyListDeleted);
435  m_PropertyList.ObjectDelete.AddListener(delegate);
436 
438  this, &QmitkPropertyItemModel::OnPropertyModified);
439 
442  modifiedCommand->SetCallbackFunction(this, &QmitkPropertyItemModel::OnPropertyModified);
443 
444  const PropertyMap *propertyMap = m_PropertyList->GetMap();
445 
446  for (PropertyMap::const_iterator it = propertyMap->begin(); it != propertyMap->end(); ++it)
447  m_PropertyModifiedTags.insert(
448  std::make_pair(it->first, it->second->AddObserver(itk::ModifiedEvent(), modifiedCommand)));
449 
452  deletedCommand->SetCallbackFunction(this, &QmitkPropertyItemModel::OnPropertyDeleted);
453 
454  for (PropertyMap::const_iterator it = propertyMap->begin(); it != propertyMap->end(); ++it)
455  m_PropertyDeletedTags.insert(
456  std::make_pair(it->first, it->second->AddObserver(itk::DeleteEvent(), deletedCommand)));
457  }
458 
459  this->CreateRootItem();
460 
461  if (m_PropertyList != NULL && !m_PropertyList->IsEmpty())
462  {
463  mitk::PropertyList::PropertyMap filteredProperties;
464  bool filterProperties = false;
465 
466  if (m_PropertyFilters != NULL &&
467  (m_PropertyFilters->HasFilter() || m_PropertyFilters->HasFilter(m_ClassName.toStdString())))
468  {
469  filteredProperties = m_PropertyFilters->ApplyFilter(*m_PropertyList->GetMap(), m_ClassName.toStdString());
470  filterProperties = true;
471  }
472 
473  const mitk::PropertyList::PropertyMap *propertyMap =
474  !filterProperties ? m_PropertyList->GetMap() : &filteredProperties;
475 
476  mitk::PropertyList::PropertyMap::const_iterator end = propertyMap->end();
477 
478  for (mitk::PropertyList::PropertyMap::const_iterator iter = propertyMap->begin(); iter != end; ++iter)
479  {
480  std::vector<std::string> aliases;
481 
482  if (m_PropertyAliases != NULL)
483  {
484  aliases = m_PropertyAliases->GetAliases(iter->first, m_ClassName.toStdString());
485 
486  if (aliases.empty() && !m_ClassName.isEmpty())
487  aliases = m_PropertyAliases->GetAliases(iter->first);
488  }
489 
490  if (aliases.empty())
491  {
492  QList<QVariant> data;
493  data << QString::fromStdString(iter->first)
494  << QVariant::fromValue((reinterpret_cast<void *>(iter->second.GetPointer())));
495 
496  m_RootItem->AppendChild(new QmitkPropertyItem(data));
497  }
498  else
499  {
500  std::vector<std::string>::const_iterator end = aliases.end();
501  for (std::vector<std::string>::const_iterator aliasIter = aliases.begin(); aliasIter != end; ++aliasIter)
502  {
503  QList<QVariant> data;
504  data << QString::fromStdString(*aliasIter)
505  << QVariant::fromValue((reinterpret_cast<void *>(iter->second.GetPointer())));
506 
507  m_RootItem->AppendChild(new QmitkPropertyItem(data));
508  }
509  }
510  }
511  }
512 
513  this->endResetModel();
514 }
515 
516 void QmitkPropertyItemModel::SetPropertyList(mitk::PropertyList *propertyList, const QString &className)
517 {
518  if (m_PropertyList.GetPointer() != propertyList)
519  {
520  m_ClassName = className;
521  this->SetNewPropertyList(propertyList);
522  }
523 }
524 
526 {
527  this->SetNewPropertyList(m_PropertyList);
528 }
void RemoveListener(const AbstractDelegate &delegate) const
Definition: mitkMessage.h:397
void AddListener(const AbstractDelegate &delegate) const
Definition: mitkMessage.h:378
bool IsEmpty() const
itk::SmartPointer< Self > Pointer
int rowCount(const QModelIndex &parent=QModelIndex()) const override
std::pair< std::string, BaseProperty::Pointer > PropertyMapElementType
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
itkObjectEvent ObjectDelete
AddEvent is emitted when the object pointed to gets deleted.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
bool IsNotNull() const
virtual bool HasFilter(const std::string &className="") const =0
Check if a specific data node class name has a property filter.
virtual std::map< std::string, BaseProperty::Pointer > ApplyFilter(const std::map< std::string, BaseProperty::Pointer > &propertyMap, const std::string &className="") const =0
Apply property filter to property list.
Key-value list holding instances of BaseProperty.
QModelIndex parent(const QModelIndex &child) const override
int GetChildCount() const
mitk::PropertyList * GetPropertyList() const
static mitk::BaseProperty * GetBaseProperty(const QVariant &data)
ObjectType * GetPointer() const
T::Pointer GetData(const std::string &name)
virtual std::vector< std::string > GetAliases(const std::string &propertyName, const std::string &className="")=0
Get aliases for a specific property.
The ColorProperty class RGB color property.
Abstract base class for properties.
std::map< std::string, BaseProperty::Pointer > PropertyMap
QmitkPropertyItem * GetChild(int row) const
QmitkPropertyItemModel(QObject *parent=NULL)
static RenderingManager * GetInstance()
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
EnumIdsContainerType::const_iterator EnumConstIterator
int columnCount(const QModelIndex &parent=QModelIndex()) const override
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
T * GetPropertyService()
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Property for strings.
static QColor MitkToQt(const mitk::Color &color)
void SetPropertyList(mitk::PropertyList *propertyList, const QString &className="")
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
static mitk::Color QtToMitk(const QColor &color)
Qt::ItemFlags flags(const QModelIndex &index) const override
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
const PropertyMap * GetMap() const
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.