diff --git a/Modules/QtWidgets/include/QmitkPropertyItemModel.h b/Modules/QtWidgets/include/QmitkPropertyItemModel.h index d3263b638f..cad26e11bf 100644 --- a/Modules/QtWidgets/include/QmitkPropertyItemModel.h +++ b/Modules/QtWidgets/include/QmitkPropertyItemModel.h @@ -1,87 +1,88 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkPropertyItemModel_h #define QmitkPropertyItemModel_h #include <MitkQtWidgetsExports.h> #include <QAbstractItemModel> #include <mitkPropertyList.h> #include <mitkWeakPointer.h> class QmitkPropertyItem; namespace berry { struct IBerryPreferences; } namespace mitk { class IPropertyAliases; class IPropertyFilters; enum { PropertyRole = Qt::UserRole + 1 }; } class MITKQTWIDGETS_EXPORT QmitkPropertyItemModel : public QAbstractItemModel { Q_OBJECT public: explicit QmitkPropertyItemModel(QObject *parent = nullptr); ~QmitkPropertyItemModel(); int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; mitk::PropertyList *GetPropertyList() const; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; void OnPreferencesChanged(); QModelIndex parent(const QModelIndex &child) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; void SetPropertyList(mitk::PropertyList *propertyList, const QString &className = ""); void Update(); void SetShowAliases(const bool showAliases) { this->m_ShowAliases = showAliases; } bool GetShowAliases() const { return this->m_ShowAliases; } void SetFilterProperties(const bool filterProperties) { this->m_FilterProperties = filterProperties; } bool GetFilterProperties() const { return this->m_FilterProperties; } private: void CreateRootItem(); QModelIndex FindProperty(const mitk::BaseProperty *property); - void OnPropertyDeleted(const itk::Object *property, const itk::EventObject &event); + void OnPropertyListModified(const itk::Object *propertyList); void OnPropertyListDeleted(const itk::Object *propertyList); + void OnPropertyDeleted(const itk::Object *property, const itk::EventObject &event); void OnPropertyModified(const itk::Object *property, const itk::EventObject &event); void SetNewPropertyList(mitk::PropertyList *propertyList); bool m_ShowAliases; bool m_FilterProperties; mitk::IPropertyAliases *m_PropertyAliases; mitk::IPropertyFilters *m_PropertyFilters; mitk::WeakPointer<mitk::PropertyList> m_PropertyList; QString m_ClassName; std::unique_ptr<QmitkPropertyItem> m_RootItem; std::map<std::string, unsigned long> m_PropertyDeletedTags; std::map<std::string, unsigned long> m_PropertyModifiedTags; }; #endif diff --git a/Modules/QtWidgets/src/QmitkPropertyItemModel.cpp b/Modules/QtWidgets/src/QmitkPropertyItemModel.cpp index f465f4db91..8825572b07 100644 --- a/Modules/QtWidgets/src/QmitkPropertyItemModel.cpp +++ b/Modules/QtWidgets/src/QmitkPropertyItemModel.cpp @@ -1,528 +1,539 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPropertyItemModel.h" #include "QmitkPropertyItem.h" #include <QColor> #include <mitkColorProperty.h> #include <mitkEnumerationProperty.h> #include <mitkIPropertyAliases.h> #include <mitkIPropertyFilters.h> #include <mitkProperties.h> #include <mitkRenderingManager.h> #include <mitkStringProperty.h> #include <usGetModuleContext.h> #include <usModuleContext.h> #include <usServiceReference.h> template <class T> T *GetPropertyService() { us::ModuleContext *context = us::GetModuleContext(); us::ServiceReference<T> serviceRef = context->GetServiceReference<T>(); return serviceRef ? context->GetService<T>(serviceRef) : nullptr; } static QColor MitkToQt(const mitk::Color &color) { return QColor(color.GetRed() * 255, color.GetGreen() * 255, color.GetBlue() * 255); } static mitk::BaseProperty *GetBaseProperty(const QVariant &data) { return data.isValid() ? reinterpret_cast<mitk::BaseProperty *>(data.value<void *>()) : nullptr; } static mitk::Color QtToMitk(const QColor &color) { mitk::Color mitkColor; mitkColor.SetRed(color.red() / 255.0f); mitkColor.SetGreen(color.green() / 255.0f); mitkColor.SetBlue(color.blue() / 255.0f); return mitkColor; } class PropertyEqualTo { public: PropertyEqualTo(const mitk::BaseProperty *property) : m_Property(property) {} bool operator()(const mitk::PropertyList::PropertyMapElementType &pair) const { return pair.second.GetPointer() == m_Property; } private: const mitk::BaseProperty *m_Property; }; QmitkPropertyItemModel::QmitkPropertyItemModel(QObject *parent) : QAbstractItemModel(parent), m_ShowAliases(false), m_FilterProperties(false), m_PropertyAliases(nullptr), m_PropertyFilters(nullptr) { this->CreateRootItem(); } QmitkPropertyItemModel::~QmitkPropertyItemModel() { this->SetNewPropertyList(nullptr); } int QmitkPropertyItemModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) return static_cast<QmitkPropertyItem *>(parent.internalPointer())->GetColumnCount(); else return m_RootItem->GetColumnCount(); } void QmitkPropertyItemModel::CreateRootItem() { QList<QVariant> rootData; rootData << "Property" << "Value"; m_RootItem.reset(new QmitkPropertyItem(rootData)); this->beginResetModel(); this->endResetModel(); } QVariant QmitkPropertyItemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); mitk::BaseProperty *property = index.column() == 1 ? GetBaseProperty(static_cast<QmitkPropertyItem *>(index.internalPointer())->GetData(1)) : nullptr; if (role == Qt::DisplayRole) { if (index.column() == 0) { return static_cast<QmitkPropertyItem *>(index.internalPointer())->GetData(0); } else if (index.column() == 1 && property != nullptr) { - if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property)) + if (auto colorProperty = dynamic_cast<mitk::ColorProperty *>(property)) return MitkToQt(colorProperty->GetValue()); else if (dynamic_cast<mitk::BoolProperty *>(property) == nullptr) return QString::fromStdString(property->GetValueAsString()); } } else if (index.column() == 1 && property != nullptr) { if (role == Qt::CheckStateRole) { - if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property)) + if (auto boolProperty = dynamic_cast<mitk::BoolProperty *>(property)) return boolProperty->GetValue() ? Qt::Checked : Qt::Unchecked; } else if (role == Qt::EditRole) { if (dynamic_cast<mitk::StringProperty *>(property) != nullptr) { return QString::fromStdString(property->GetValueAsString()); } - else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property)) + else if (auto intProperty = dynamic_cast<mitk::IntProperty *>(property)) { return intProperty->GetValue(); } - else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property)) + else if (auto floatProperty = dynamic_cast<mitk::FloatProperty *>(property)) { return floatProperty->GetValue(); } - else if (mitk::DoubleProperty *doubleProperty = dynamic_cast<mitk::DoubleProperty *>(property)) + else if (auto doubleProperty = dynamic_cast<mitk::DoubleProperty *>(property)) { return doubleProperty->GetValue(); } - else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property)) + else if (auto enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property)) { QStringList values; for (mitk::EnumerationProperty::EnumConstIterator it = enumProperty->Begin(); it != enumProperty->End(); it++) values << QString::fromStdString(it->second); return values; } - else if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property)) + else if (auto colorProperty = dynamic_cast<mitk::ColorProperty *>(property)) { return MitkToQt(colorProperty->GetValue()); } } else if (role == mitk::PropertyRole) { return QVariant::fromValue<void *>(property); } } return QVariant(); } QModelIndex QmitkPropertyItemModel::FindProperty(const mitk::BaseProperty *property) { if (property == nullptr) return QModelIndex(); - typedef mitk::PropertyList::PropertyMap PropertyMap; - const PropertyMap *propertyMap = m_PropertyList->GetMap(); - - PropertyMap::const_iterator it = std::find_if(propertyMap->begin(), propertyMap->end(), PropertyEqualTo(property)); + auto propertyMap = m_PropertyList->GetMap(); + auto it = std::find_if(propertyMap->begin(), propertyMap->end(), PropertyEqualTo(property)); if (it == propertyMap->end()) return QModelIndex(); QString name = QString::fromStdString(it->first); if (!name.contains('.')) { QModelIndexList item = this->match(index(0, 0), Qt::DisplayRole, name, 1, Qt::MatchExactly); if (!item.empty()) return item[0]; } else { QStringList names = name.split('.'); QModelIndexList items = this->match(index(0, 0), Qt::DisplayRole, names.last(), -1, Qt::MatchRecursive | Qt::MatchExactly); - foreach (QModelIndex item, items) + for (auto item : items) { QModelIndex candidate = item; for (int i = names.length() - 1; i != 0; --i) { QModelIndex parent = item.parent(); if (parent.parent() == QModelIndex()) { if (parent.data() != names.first()) break; return candidate; } if (parent.data() != names[i - 1]) break; item = parent; } } } return QModelIndex(); } Qt::ItemFlags QmitkPropertyItemModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); if (index.column() == 1) { if (index.data(Qt::EditRole).isValid()) flags |= Qt::ItemIsEditable; if (index.data(Qt::CheckStateRole).isValid()) flags |= Qt::ItemIsUserCheckable; } return flags; } mitk::PropertyList *QmitkPropertyItemModel::GetPropertyList() const { return m_PropertyList.GetPointer(); } QVariant QmitkPropertyItemModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) return m_RootItem->GetData(section); return QVariant(); } QModelIndex QmitkPropertyItemModel::index(int row, int column, const QModelIndex &parent) const { if (!this->hasIndex(row, column, parent)) return QModelIndex(); QmitkPropertyItem *parentItem = parent.isValid() ? static_cast<QmitkPropertyItem *>(parent.internalPointer()) : m_RootItem.get(); QmitkPropertyItem *childItem = parentItem->GetChild(row); return childItem != nullptr ? this->createIndex(row, column, childItem) : QModelIndex(); } void QmitkPropertyItemModel::OnPreferencesChanged() { bool updateAliases = m_ShowAliases != (m_PropertyAliases != nullptr); bool updateFilters = m_FilterProperties != (m_PropertyFilters != nullptr); bool resetPropertyList = false; if (updateAliases) { m_PropertyAliases = m_ShowAliases ? GetPropertyService<mitk::IPropertyAliases>() : nullptr; resetPropertyList = m_PropertyList.IsNotNull(); } if (updateFilters) { m_PropertyFilters = m_FilterProperties ? GetPropertyService<mitk::IPropertyFilters>() : nullptr; if (!resetPropertyList) resetPropertyList = m_PropertyList.IsNotNull(); } if (resetPropertyList) this->SetNewPropertyList(m_PropertyList.GetPointer()); } void QmitkPropertyItemModel::OnPropertyDeleted(const itk::Object * /*property*/, const itk::EventObject &) { /*QModelIndex index = this->FindProperty(static_cast<const mitk::BaseProperty*>(property)); if (index != QModelIndex()) this->reset();*/ } +void QmitkPropertyItemModel::OnPropertyListModified(const itk::Object *propertyList) +{ + this->SetNewPropertyList(dynamic_cast<mitk::PropertyList *>(const_cast<itk::Object *>(propertyList))); +} + void QmitkPropertyItemModel::OnPropertyListDeleted(const itk::Object *) { this->CreateRootItem(); } void QmitkPropertyItemModel::OnPropertyModified(const itk::Object *property, const itk::EventObject &) { QModelIndex index = this->FindProperty(static_cast<const mitk::BaseProperty *>(property)); if (index != QModelIndex()) emit dataChanged(index, index); } QModelIndex QmitkPropertyItemModel::parent(const QModelIndex &child) const { if (!child.isValid()) return QModelIndex(); QmitkPropertyItem *parentItem = static_cast<QmitkPropertyItem *>(child.internalPointer())->GetParent(); if (parentItem == m_RootItem.get()) return QModelIndex(); return this->createIndex(parentItem->GetRow(), 0, parentItem); } int QmitkPropertyItemModel::rowCount(const QModelIndex &parent) const { if (parent.column() > 0) return 0; QmitkPropertyItem *parentItem = parent.isValid() ? static_cast<QmitkPropertyItem *>(parent.internalPointer()) : m_RootItem.get(); return parentItem->GetChildCount(); } bool QmitkPropertyItemModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || index.column() != 1 || (role != Qt::EditRole && role != Qt::CheckStateRole)) return false; mitk::BaseProperty *property = GetBaseProperty(static_cast<QmitkPropertyItem *>(index.internalPointer())->GetData(1)); if (property == nullptr) return false; if (mitk::BoolProperty *boolProperty = dynamic_cast<mitk::BoolProperty *>(property)) { boolProperty->SetValue(value.toInt() == Qt::Checked ? true : false); } else if (mitk::StringProperty *stringProperty = dynamic_cast<mitk::StringProperty *>(property)) { stringProperty->SetValue(value.toString().toStdString()); } else if (mitk::IntProperty *intProperty = dynamic_cast<mitk::IntProperty *>(property)) { intProperty->SetValue(value.toInt()); } else if (mitk::FloatProperty *floatProperty = dynamic_cast<mitk::FloatProperty *>(property)) { floatProperty->SetValue(value.toFloat()); } else if (mitk::DoubleProperty *doubleProperty = dynamic_cast<mitk::DoubleProperty *>(property)) { doubleProperty->SetValue(value.toDouble()); } else if (mitk::EnumerationProperty *enumProperty = dynamic_cast<mitk::EnumerationProperty *>(property)) { std::string selection = value.toString().toStdString(); if (selection != enumProperty->GetValueAsString() && enumProperty->IsValidEnumerationValue(selection)) enumProperty->SetValue(selection); } else if (mitk::ColorProperty *colorProperty = dynamic_cast<mitk::ColorProperty *>(property)) { colorProperty->SetValue(QtToMitk(value.value<QColor>())); } m_PropertyList->InvokeEvent(itk::ModifiedEvent()); m_PropertyList->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } void QmitkPropertyItemModel::SetNewPropertyList(mitk::PropertyList *propertyList) { typedef mitk::PropertyList::PropertyMap PropertyMap; this->beginResetModel(); if (m_PropertyList.IsNotNull()) { - mitk::MessageDelegate1<QmitkPropertyItemModel, const itk::Object *> delegate( + mitk::MessageDelegate1<QmitkPropertyItemModel, const itk::Object *> onPropertyListDeleted( this, &QmitkPropertyItemModel::OnPropertyListDeleted); - m_PropertyList.ObjectDelete.RemoveListener(delegate); + m_PropertyList.ObjectDelete.RemoveListener(onPropertyListDeleted); + + mitk::MessageDelegate1<QmitkPropertyItemModel, const itk::Object *> onPropertyListModified( + this, &QmitkPropertyItemModel::OnPropertyListModified); + m_PropertyList.ObjectModified.RemoveListener(onPropertyListModified); const PropertyMap *propertyMap = m_PropertyList->GetMap(); for (PropertyMap::const_iterator propertyIt = propertyMap->begin(); propertyIt != propertyMap->end(); ++propertyIt) { std::map<std::string, unsigned long>::const_iterator tagIt = m_PropertyModifiedTags.find(propertyIt->first); if (tagIt != m_PropertyModifiedTags.end()) propertyIt->second->RemoveObserver(tagIt->second); tagIt = m_PropertyDeletedTags.find(propertyIt->first); if (tagIt != m_PropertyDeletedTags.end()) propertyIt->second->RemoveObserver(tagIt->second); } m_PropertyModifiedTags.clear(); m_PropertyDeletedTags.clear(); } m_PropertyList = propertyList; if (m_PropertyList.IsNotNull()) { - mitk::MessageDelegate1<QmitkPropertyItemModel, const itk::Object *> delegate( + mitk::MessageDelegate1<QmitkPropertyItemModel, const itk::Object *> onPropertyListModified( + this, &QmitkPropertyItemModel::OnPropertyListModified); + m_PropertyList.ObjectModified.AddListener(onPropertyListModified); + + mitk::MessageDelegate1<QmitkPropertyItemModel, const itk::Object *> onPropertyListDeleted( this, &QmitkPropertyItemModel::OnPropertyListDeleted); - m_PropertyList.ObjectDelete.AddListener(delegate); + m_PropertyList.ObjectDelete.AddListener(onPropertyListDeleted); - mitk::MessageDelegate2<QmitkPropertyItemModel, const itk::Object *, const itk::EventObject &> propertyDelegate( + mitk::MessageDelegate2<QmitkPropertyItemModel, const itk::Object *, const itk::EventObject &> onPropertyModified( this, &QmitkPropertyItemModel::OnPropertyModified); itk::MemberCommand<QmitkPropertyItemModel>::Pointer modifiedCommand = itk::MemberCommand<QmitkPropertyItemModel>::New(); modifiedCommand->SetCallbackFunction(this, &QmitkPropertyItemModel::OnPropertyModified); const PropertyMap *propertyMap = m_PropertyList->GetMap(); for (PropertyMap::const_iterator it = propertyMap->begin(); it != propertyMap->end(); ++it) m_PropertyModifiedTags.insert( std::make_pair(it->first, it->second->AddObserver(itk::ModifiedEvent(), modifiedCommand))); itk::MemberCommand<QmitkPropertyItemModel>::Pointer deletedCommand = itk::MemberCommand<QmitkPropertyItemModel>::New(); deletedCommand->SetCallbackFunction(this, &QmitkPropertyItemModel::OnPropertyDeleted); for (PropertyMap::const_iterator it = propertyMap->begin(); it != propertyMap->end(); ++it) m_PropertyDeletedTags.insert( std::make_pair(it->first, it->second->AddObserver(itk::DeleteEvent(), deletedCommand))); } this->CreateRootItem(); if (m_PropertyList != nullptr && !m_PropertyList->IsEmpty()) { mitk::PropertyList::PropertyMap filteredProperties; bool filterProperties = false; if (m_PropertyFilters != nullptr && (m_PropertyFilters->HasFilter() || m_PropertyFilters->HasFilter(m_ClassName.toStdString()))) { filteredProperties = m_PropertyFilters->ApplyFilter(*m_PropertyList->GetMap(), m_ClassName.toStdString()); filterProperties = true; } const mitk::PropertyList::PropertyMap *propertyMap = !filterProperties ? m_PropertyList->GetMap() : &filteredProperties; mitk::PropertyList::PropertyMap::const_iterator end = propertyMap->end(); for (mitk::PropertyList::PropertyMap::const_iterator iter = propertyMap->begin(); iter != end; ++iter) { std::vector<std::string> aliases; if (m_PropertyAliases != nullptr) { aliases = m_PropertyAliases->GetAliases(iter->first, m_ClassName.toStdString()); if (aliases.empty() && !m_ClassName.isEmpty()) aliases = m_PropertyAliases->GetAliases(iter->first); } if (aliases.empty()) { QList<QVariant> data; data << QString::fromStdString(iter->first) << QVariant::fromValue((reinterpret_cast<void *>(iter->second.GetPointer()))); m_RootItem->AppendChild(new QmitkPropertyItem(data)); } else { std::vector<std::string>::const_iterator end = aliases.end(); for (std::vector<std::string>::const_iterator aliasIter = aliases.begin(); aliasIter != end; ++aliasIter) { QList<QVariant> data; data << QString::fromStdString(*aliasIter) << QVariant::fromValue((reinterpret_cast<void *>(iter->second.GetPointer()))); m_RootItem->AppendChild(new QmitkPropertyItem(data)); } } } } this->endResetModel(); } void QmitkPropertyItemModel::SetPropertyList(mitk::PropertyList *propertyList, const QString &className) { if (m_PropertyList.GetPointer() != propertyList) { m_ClassName = className; this->SetNewPropertyList(propertyList); } } void QmitkPropertyItemModel::Update() { this->SetNewPropertyList(m_PropertyList); } diff --git a/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyItemSortFilterProxyModel.cpp b/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyItemSortFilterProxyModel.cpp index d0e96f4653..e927c371cf 100644 --- a/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyItemSortFilterProxyModel.cpp +++ b/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyItemSortFilterProxyModel.cpp @@ -1,58 +1,58 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPropertyItemSortFilterProxyModel.h" QmitkPropertyItemSortFilterProxyModel::QmitkPropertyItemSortFilterProxyModel(QObject* parent) : QSortFilterProxyModel(parent) { } QmitkPropertyItemSortFilterProxyModel::~QmitkPropertyItemSortFilterProxyModel() { } bool QmitkPropertyItemSortFilterProxyModel::FilterAcceptsAnyChildRow(const QModelIndex& sourceParent) const { QString propertyName = this->sourceModel()->data(sourceParent).toString(); - if (propertyName.contains(filterRegExp())) + if (propertyName.contains(this->filterRegExp())) return true; if (this->sourceModel()->hasChildren(sourceParent)) { for (int row = 0; row < this->sourceModel()->rowCount(sourceParent); ++row) { if(this->FilterAcceptsAnyChildRow(this->sourceModel()->index(row, 0, sourceParent))) return true; } } return false; } bool QmitkPropertyItemSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { return this->FilterAcceptsAnyChildRow(this->sourceModel()->index(sourceRow, 0, sourceParent)); } bool QmitkPropertyItemSortFilterProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { QString leftString = this->sourceModel()->data(left).toString(); QString rightString = this->sourceModel()->data(right).toString(); return leftString.compare(rightString, this->sortCaseSensitivity()) < 0; } diff --git a/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyTreeView.cpp b/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyTreeView.cpp index c99d81c134..a5274aff70 100644 --- a/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyTreeView.cpp +++ b/Plugins/org.mitk.gui.qt.properties/src/internal/QmitkPropertyTreeView.cpp @@ -1,463 +1,451 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkGetPropertyService.h" #include "QmitkAddNewPropertyDialog.h" #include "QmitkPropertiesPreferencePage.h" #include "QmitkPropertyItemDelegate.h" #include "QmitkPropertyItemModel.h" #include "QmitkPropertyItemSortFilterProxyModel.h" #include "QmitkPropertyTreeView.h" #include <berryIBerryPreferences.h> #include <mitkIPropertyAliases.h> #include <mitkIPropertyDescriptions.h> #include <mitkIPropertyPersistence.h> #include <QmitkRenderWindow.h> #include <QPainter> #include <memory> const std::string QmitkPropertyTreeView::VIEW_ID = "org.mitk.views.properties"; QmitkPropertyTreeView::QmitkPropertyTreeView() : m_Parent(nullptr), m_PropertyNameChangedTag(0), m_PropertyAliases(nullptr), m_PropertyDescriptions(nullptr), m_PropertyPersistence(nullptr), m_ShowAliasesInDescription(true), m_ShowPersistenceInDescription(true), m_DeveloperMode(false), m_ProxyModel(nullptr), m_Model(nullptr), m_Delegate(nullptr), m_Renderer(nullptr) { } QmitkPropertyTreeView::~QmitkPropertyTreeView() { } void QmitkPropertyTreeView::CreateQtPartControl(QWidget* parent) { m_Parent = parent; m_Controls.setupUi(parent); m_Controls.propertyListComboBox->addItem("Data node: common"); mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart(); if (renderWindowPart != nullptr) { QHash<QString, QmitkRenderWindow*> renderWindows = renderWindowPart->GetQmitkRenderWindows(); Q_FOREACH(QString renderWindow, renderWindows.keys()) { m_Controls.propertyListComboBox->addItem(QString("Data node: ") + renderWindow); } } m_Controls.propertyListComboBox->addItem("Base data"); m_Controls.newButton->setEnabled(false); m_Controls.description->hide(); m_Controls.propertyListLabel->hide(); m_Controls.propertyListComboBox->hide(); m_Controls.newButton->hide(); m_ProxyModel = new QmitkPropertyItemSortFilterProxyModel(m_Controls.treeView); m_Model = new QmitkPropertyItemModel(m_ProxyModel); m_ProxyModel->setSourceModel(m_Model); m_ProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); m_ProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); m_ProxyModel->setDynamicSortFilter(true); m_Delegate = new QmitkPropertyItemDelegate(m_Controls.treeView); -#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) m_Controls.filterLineEdit->setClearButtonEnabled(true); -#endif m_Controls.treeView->setItemDelegateForColumn(1, m_Delegate); m_Controls.treeView->setModel(m_ProxyModel); m_Controls.treeView->setColumnWidth(0, 160); m_Controls.treeView->sortByColumn(0, Qt::AscendingOrder); m_Controls.treeView->setSelectionBehavior(QAbstractItemView::SelectRows); m_Controls.treeView->setSelectionMode(QAbstractItemView::SingleSelection); m_Controls.treeView->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::DoubleClicked); connect(m_Controls.filterLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnFilterTextChanged(const QString&))); connect(m_Controls.propertyListComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnPropertyListChanged(int))); connect(m_Controls.newButton, SIGNAL(clicked()), this, SLOT(OnAddNewProperty())); connect(m_Controls.treeView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(OnCurrentRowChanged(const QModelIndex&, const QModelIndex&))); connect(m_Model, SIGNAL(modelReset()), this, SLOT(OnModelReset())); } QString QmitkPropertyTreeView::GetPropertyNameOrAlias(const QModelIndex& index) { QString propertyName; if (index.isValid()) { QModelIndex current = index; while (current.isValid()) { QString name = m_ProxyModel->data(m_ProxyModel->index(current.row(), 0, current.parent())).toString(); propertyName.prepend(propertyName.isEmpty() ? name : name.append('.')); current = current.parent(); } } return propertyName; } void QmitkPropertyTreeView::OnCurrentRowChanged(const QModelIndex& current, const QModelIndex&) { if (m_PropertyDescriptions != nullptr && current.isValid()) { QString name = this->GetPropertyNameOrAlias(current); if (!name.isEmpty()) { QString alias; bool isTrueName = true; if (m_PropertyAliases != nullptr) { std::string trueName = m_PropertyAliases->GetPropertyName(name.toStdString()); if (trueName.empty() && !m_SelectionClassName.empty()) trueName = m_PropertyAliases->GetPropertyName(name.toStdString(), m_SelectionClassName); if (!trueName.empty()) { alias = name; name = QString::fromStdString(trueName); isTrueName = false; } } QString description = QString::fromStdString(m_PropertyDescriptions->GetDescription(name.toStdString())); std::vector<std::string> aliases; if (!isTrueName && m_PropertyAliases != nullptr) { aliases = m_PropertyAliases->GetAliases(name.toStdString(), m_SelectionClassName); if (aliases.empty() && !m_SelectionClassName.empty()) aliases = m_PropertyAliases->GetAliases(name.toStdString()); } bool isPersistent = false; - // QString persistenceKey; if (m_PropertyPersistence != nullptr) - { isPersistent = m_PropertyPersistence->HasInfo(name.toStdString()); - /*if (isPersistent) - { - persistenceKey = QString::fromStdString(m_PropertyPersistence->GetInfo(name.toStdString())->GetKey()); - - if (persistenceKey.isEmpty()) - persistenceKey = name; - }*/ - } - if (!description.isEmpty() || !aliases.empty() || isPersistent) { QString customizedDescription; if (m_ShowAliasesInDescription && !aliases.empty()) { customizedDescription = "<h3 style=\"margin-bottom:0\">" + name + "</h3>"; std::size_t numAliases = aliases.size(); std::size_t lastAlias = numAliases - 1; for (std::size_t i = 0; i < numAliases; ++i) { customizedDescription += i != lastAlias ? "<h5 style=\"margin-top:0;margin-bottom:0\">" : "<h5 style=\"margin-top:0;margin-bottom:10px\">"; customizedDescription += QString::fromStdString(aliases[i]) + "</h5>"; } } else { customizedDescription = "<h3 style=\"margin-bottom:10px\">" + name + "</h3>"; } if (!description.isEmpty()) customizedDescription += "<p>" + description + "</p>"; if (!aliases.empty() || isPersistent) { customizedDescription += "<div align=\"right\">"; if (!aliases.empty()) { customizedDescription += aliases.size() > 1 ? "<img height=\"32\" src=\":/org_mitk_icons/icons/awesome/scalable/tags.svg\"/>" : "<img height=\"32\" src=\":/org_mitk_icons/icons/awesome/scalable/tag.svg\"/>"; } if (isPersistent) customizedDescription += "<img height=\"32\" src=\":/org_mitk_icons/icons/awesome/scalable/actions/document-save.svg\"/>"; customizedDescription += "</div>"; } m_Controls.description->setText(customizedDescription); m_Controls.description->show(); return; } } } m_Controls.description->hide(); } void QmitkPropertyTreeView::OnFilterTextChanged(const QString& filter) { m_ProxyModel->setFilterWildcard(filter); if (filter.isEmpty()) m_Controls.treeView->collapseAll(); else m_Controls.treeView->expandAll(); } void QmitkPropertyTreeView::OnModelReset() { m_Controls.description->hide(); } void QmitkPropertyTreeView::OnPreferencesChanged(const berry::IBerryPreferences* preferences) { bool showAliases = preferences->GetBool(QmitkPropertiesPreferencePage::SHOW_ALIASES, true); bool showDescriptions = preferences->GetBool(QmitkPropertiesPreferencePage::SHOW_DESCRIPTIONS, true); bool showAliasesInDescription = preferences->GetBool(QmitkPropertiesPreferencePage::SHOW_ALIASES_IN_DESCRIPTION, true); bool showPersistenceInDescription = preferences->GetBool(QmitkPropertiesPreferencePage::SHOW_PERSISTENCE_IN_DESCRIPTION, true); bool developerMode = preferences->GetBool(QmitkPropertiesPreferencePage::DEVELOPER_MODE, false); bool filterProperties = preferences->GetBool(QmitkPropertiesPreferencePage::FILTER_PROPERTIES, true); + m_Model->SetFilterProperties(filterProperties); m_Model->SetShowAliases(showAliases); bool updateAliases = showAliases != (m_PropertyAliases != nullptr); bool updateDescriptions = showDescriptions != (m_PropertyDescriptions != nullptr); bool updateAliasesInDescription = showAliasesInDescription != m_ShowAliasesInDescription; bool updatePersistenceInDescription = showPersistenceInDescription != m_ShowPersistenceInDescription; bool updateDeveloperMode = developerMode != m_DeveloperMode; if (updateAliases) m_PropertyAliases = showAliases ? mitk::GetPropertyService<mitk::IPropertyAliases>() : nullptr; if (updateDescriptions) m_PropertyDescriptions = showDescriptions ? mitk::GetPropertyService<mitk::IPropertyDescriptions>() : nullptr; if (showPersistenceInDescription) m_PropertyPersistence = mitk::GetPropertyService<mitk::IPropertyPersistence>(); if (updateAliasesInDescription) m_ShowAliasesInDescription = showAliasesInDescription; if (updatePersistenceInDescription) m_ShowPersistenceInDescription = showPersistenceInDescription; if (updateDescriptions || updateAliasesInDescription || updatePersistenceInDescription) { QModelIndexList selection = m_Controls.treeView->selectionModel()->selectedRows(); if (!selection.isEmpty()) this->OnCurrentRowChanged(selection[0], selection[0]); } if (updateDeveloperMode) { m_DeveloperMode = developerMode; if (!developerMode) m_Controls.propertyListComboBox->setCurrentIndex(0); m_Controls.propertyListLabel->setVisible(developerMode); m_Controls.propertyListComboBox->setVisible(developerMode); m_Controls.newButton->setVisible(developerMode); } m_Model->OnPreferencesChanged(); } void QmitkPropertyTreeView::OnPropertyNameChanged(const itk::EventObject&) { mitk::PropertyList* propertyList = m_Model->GetPropertyList(); if (propertyList != nullptr) { mitk::BaseProperty* nameProperty = propertyList->GetProperty("name"); if (nameProperty != nullptr) { QString partName = "Properties ("; partName.append(QString::fromStdString(nameProperty->GetValueAsString())).append(')'); this->SetPartName(partName); } } } void QmitkPropertyTreeView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes) { mitk::PropertyList* propertyList = m_Model->GetPropertyList(); if (propertyList != nullptr) { mitk::BaseProperty* nameProperty = propertyList->GetProperty("name"); if (nameProperty != nullptr) nameProperty->RemoveObserver(m_PropertyNameChangedTag); m_PropertyNameChangedTag = 0; } if (nodes.empty() || nodes.front().IsNull()) { m_SelectedNode = nullptr; this->SetPartName("Properties"); m_Model->SetPropertyList(nullptr); m_Delegate->SetPropertyList(nullptr); m_Controls.newButton->setEnabled(false); } else { m_SelectedNode = nodes.front(); QString selectionClassName = m_SelectedNode->GetData() != nullptr ? m_SelectedNode->GetData()->GetNameOfClass() : ""; m_SelectionClassName = selectionClassName.toStdString(); mitk::PropertyList::Pointer propertyList; if (m_Renderer == nullptr && m_Controls.propertyListComboBox->currentText() == "Base data") { propertyList = m_SelectedNode->GetData() != nullptr ? m_SelectedNode->GetData()->GetPropertyList() : nullptr; } else { propertyList = m_SelectedNode->GetPropertyList(m_Renderer); } m_Model->SetPropertyList(propertyList, selectionClassName); m_Delegate->SetPropertyList(propertyList); OnPropertyNameChanged(itk::ModifiedEvent()); mitk::BaseProperty* nameProperty = m_SelectedNode->GetProperty("name"); if (nameProperty != nullptr) { itk::ReceptorMemberCommand<QmitkPropertyTreeView>::Pointer command = itk::ReceptorMemberCommand<QmitkPropertyTreeView>::New(); command->SetCallbackFunction(this, &QmitkPropertyTreeView::OnPropertyNameChanged); m_PropertyNameChangedTag = nameProperty->AddObserver(itk::ModifiedEvent(), command); } m_Controls.newButton->setEnabled(true); } if (!m_ProxyModel->filterRegExp().isEmpty()) m_Controls.treeView->expandAll(); } void QmitkPropertyTreeView::SetFocus() { m_Controls.filterLineEdit->setFocus(); } void QmitkPropertyTreeView::RenderWindowPartActivated(mitk::IRenderWindowPart* /*renderWindowPart*/) { if (m_Controls.propertyListComboBox->count() == 2) { QHash<QString, QmitkRenderWindow*> renderWindows = this->GetRenderWindowPart()->GetQmitkRenderWindows(); Q_FOREACH(QString renderWindow, renderWindows.keys()) { m_Controls.propertyListComboBox->insertItem(m_Controls.propertyListComboBox->count() - 1, QString("Data node: ") + renderWindow); } } } void QmitkPropertyTreeView::RenderWindowPartDeactivated(mitk::IRenderWindowPart*) { if (m_Controls.propertyListComboBox->count() > 2) { m_Controls.propertyListComboBox->clear(); m_Controls.propertyListComboBox->addItem("Data node: common"); m_Controls.propertyListComboBox->addItem("Base data"); } } void QmitkPropertyTreeView::OnPropertyListChanged(int index) { if (index == -1) return; QString renderer = m_Controls.propertyListComboBox->itemText(index); if (renderer.startsWith("Data node: ")) renderer = QString::fromStdString(renderer.toStdString().substr(11)); m_Renderer = renderer != "common" && renderer != "Base data" ? this->GetRenderWindowPart()->GetQmitkRenderWindow(renderer)->GetRenderer() : nullptr; QList<mitk::DataNode::Pointer> nodes; if (m_SelectedNode.IsNotNull()) nodes << m_SelectedNode; berry::IWorkbenchPart::Pointer workbenchPart; this->OnSelectionChanged(workbenchPart, nodes); } void QmitkPropertyTreeView::OnAddNewProperty() { std::unique_ptr<QmitkAddNewPropertyDialog> dialog(m_Controls.propertyListComboBox->currentText() != "Base data" ? new QmitkAddNewPropertyDialog(m_SelectedNode, m_Renderer, m_Parent) : new QmitkAddNewPropertyDialog(m_SelectedNode->GetData())); if (dialog->exec() == QDialog::Accepted) this->m_Model->Update(); }