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
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.