diff --git a/Modules/QtWidgets/files.cmake b/Modules/QtWidgets/files.cmake index ea539e765a..72319039b4 100644 --- a/Modules/QtWidgets/files.cmake +++ b/Modules/QtWidgets/files.cmake @@ -1,85 +1,86 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES QmitkApplicationCursor.cpp QmitkDataStorageComboBox.cpp QmitkDataStorageListModel.cpp QmitkDataStorageTableModel.cpp QmitkDataStorageTreeModel.cpp QmitkFileReaderOptionsDialog.cpp QmitkFileReaderWriterOptionsWidget.cpp QmitkFileWriterOptionsDialog.cpp QmitkIOUtil.cpp QmitkLevelWindowPresetDefinitionDialog.cpp QmitkLevelWindowRangeChangeDialog.cpp QmitkLevelWindowWidgetContextMenu.cpp QmitkLevelWindowWidget.cpp QmitkLineEditLevelWindowWidget.cpp QmitkMemoryUsageIndicatorView.cpp QmitkMimeTypes.cpp QmitkNodeDescriptor.cpp QmitkColoredNodeDescriptor.cpp QmitkNodeDescriptorManager.cpp QmitkRenderWindowMenu.cpp QmitkProgressBar.cpp QmitkPropertiesTableEditor.cpp QmitkPropertiesTableModel.cpp QmitkPropertyDelegate.cpp QmitkRegisterClasses.cpp QmitkRenderingManager.cpp QmitkRenderingManagerFactory.cpp QmitkRenderWindow.cpp QmitkServiceListWidget.cpp QmitkSliderLevelWindowWidget.cpp QmitkStdMultiWidget.cpp QmitkMouseModeSwitcher.cpp QmitkDataStorageFilterProxyModel.cpp QmitkDataStorageComboBoxWithSelectNone.cpp QmitkPropertyItem.cpp QmitkPropertyItemDelegate.cpp QmitkPropertyItemModel.cpp ) set(MOC_H_FILES include/QmitkDataStorageComboBox.h include/QmitkDataStorageTableModel.h + include/QmitkDataStorageTreeModel.h include/QmitkFileReaderOptionsDialog.h include/QmitkFileReaderWriterOptionsWidget.h include/QmitkFileWriterOptionsDialog.h include/QmitkLevelWindowPresetDefinitionDialog.h include/QmitkLevelWindowRangeChangeDialog.h include/QmitkLevelWindowWidgetContextMenu.h include/QmitkLevelWindowWidget.h include/QmitkLineEditLevelWindowWidget.h include/QmitkMemoryUsageIndicatorView.h include/QmitkNodeDescriptor.h include/QmitkColoredNodeDescriptor.h include/QmitkNodeDescriptorManager.h include/QmitkRenderWindowMenu.h include/QmitkProgressBar.h include/QmitkPropertiesTableEditor.h include/QmitkPropertyDelegate.h include/QmitkRenderingManager.h include/QmitkRenderWindow.h include/QmitkServiceListWidget.h include/QmitkSliderLevelWindowWidget.h include/QmitkStdMultiWidget.h include/QmitkMouseModeSwitcher.h include/QmitkDataStorageComboBoxWithSelectNone.h include/QmitkPropertyItemDelegate.h include/QmitkPropertyItemModel.h ) set(UI_FILES src/QmitkFileReaderOptionsDialog.ui src/QmitkFileWriterOptionsDialog.ui src/QmitkLevelWindowPresetDefinition.ui src/QmitkLevelWindowWidget.ui src/QmitkLevelWindowRangeChange.ui src/QmitkMemoryUsageIndicator.ui src/QmitkServiceListWidgetControls.ui ) set(QRC_FILES resource/Qmitk.qrc ) diff --git a/Modules/QtWidgets/include/QmitkDataStorageTreeModel.h b/Modules/QtWidgets/include/QmitkDataStorageTreeModel.h index f796739c31..1660fb6e5d 100644 --- a/Modules/QtWidgets/include/QmitkDataStorageTreeModel.h +++ b/Modules/QtWidgets/include/QmitkDataStorageTreeModel.h @@ -1,271 +1,277 @@ /*=================================================================== 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 QMITKDATASTORAGETREEMODEL_H_ #define QMITKDATASTORAGETREEMODEL_H_ #include #include #include #include #include #include "QmitkCustomVariants.h" #include "QmitkEnums.h" #include #include #include /// \ingroup QmitkModule class MITKQTWIDGETS_EXPORT QmitkDataStorageTreeModel : public QAbstractItemModel { + Q_OBJECT + //# CONSTANTS,TYPEDEFS public: static const std::string COLUMN_NAME; static const std::string COLUMN_TYPE; static const std::string COLUMN_VISIBILITY; //# CTORS,DTOR public: QmitkDataStorageTreeModel(mitk::DataStorage *_DataStorage, bool _PlaceNewNodesOnTop = false, QObject *parent = 0); ~QmitkDataStorageTreeModel() override; //# GETTER public: /// /// Get node at a specific model index. /// This function is used to get a node from a QModelIndex /// mitk::DataNode::Pointer GetNode(const QModelIndex &index) const; /// /// Returns a copy of the node-vector that is shown by this model /// virtual QList GetNodeSet() const; /// /// Get the DataStorage. /// const mitk::DataStorage::Pointer GetDataStorage() const; /// /// Get the top placement flag /// bool GetPlaceNewNodesOnTopFlag() { return m_PlaceNewNodesOnTop; } /// /// Set the top placement flag /// void SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop); //# (Re-)implemented from QAbstractItemModel //# Read model Qt::ItemFlags flags(const QModelIndex &index) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; //# hierarchical model /// /// called whenever the model or the view needs to create a QModelIndex for a particular /// child item (or a top-level item if parent is an invalid QModelIndex) /// QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &index) const override; //# editable model bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override; bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; Qt::DropActions supportedDropActions() const override; Qt::DropActions supportedDragActions() const override; QStringList mimeTypes() const override; QMimeData *mimeData(const QModelIndexList &indexes) const override; static QMimeData *mimeDataFromModelIndexList(const QModelIndexList &indexes); //# End of QAbstractItemModel //# SETTER public: /// /// Sets the DataStorage. The whole model will be resetted. /// void SetDataStorage(mitk::DataStorage *_DataStorage); /// /// Notify that the DataStorage was deleted. The whole model will be resetted. /// void SetDataStorageDeleted(); /// /// Adds a node to this model. /// If a predicate is set (not null) the node will be checked against it.The node has to have a data object (no one /// wants to see empty nodes). /// virtual void AddNode(const mitk::DataNode *node); /// /// Removes a node from this model. Also removes any event listener from the node. /// virtual void RemoveNode(const mitk::DataNode *node); /// /// Sets a node to modfified. Called by the DataStorage /// virtual void SetNodeModified(const mitk::DataNode *node); /// /// \return an index for the given datatreenode in the tree. If the node is not found /// QModelIndex GetIndex(const mitk::DataNode *) const; /// Set whether to allow hierarchy changes by dragging and dropping void SetAllowHierarchyChange(bool allowHierarchyChange); +signals: + + void nodeVisibilityChanged(); + //# MISC protected: /// /// Helper class to represent a tree structure of DataNodes /// class TreeItem { public: /// /// Constructs a new TreeItem with the given DataNode (must not be 0) /// TreeItem(mitk::DataNode *_DataNode, TreeItem *_Parent = 0); /// /// Removes itself as child from its parent-> Does not delete its children /// \sa Delete() /// virtual ~TreeItem(); /// /// Find the index of an item /// int IndexOfChild(const TreeItem *item) const; /// /// \return The child at pos index or 0 if it not exists /// TreeItem *GetChild(int index) const; /// /// Find the TreeItem containing a special tree node (recursive tree function) /// TreeItem *Find(const mitk::DataNode *_DataNode) const; /// /// Get the amount of children /// int GetChildCount() const; /// /// \return the index of this node in its parent list /// int GetIndex() const; /// /// \return the parent of this tree item /// TreeItem *GetParent() const; /// /// Return the DataNode associated with this node /// mitk::DataNode::Pointer GetDataNode() const; /// /// Get all children as vector /// std::vector GetChildren() const; /// /// add another item as a child of this (only if not already in that list) /// void AddChild(TreeItem *item); /// /// remove another item as child from this /// void RemoveChild(TreeItem *item); /// /// inserts a child at the given position. if pos is not in range /// the element is added at the end /// void InsertChild(TreeItem *item, int index = -1); /// Sets the parent on the treeitem void SetParent(TreeItem *_Parent); /// /// Deletes the whole tree branch /// void Delete(); protected: TreeItem *m_Parent; std::vector m_Children; mitk::DataNode::Pointer m_DataNode; }; QList ToTreeItemPtrList(const QMimeData *mimeData); QList ToTreeItemPtrList(const QByteArray &ba); /// /// Adjusts the LayerProperty according to the nodes position /// void AdjustLayerProperty(); /// /// invoked after m_DataStorage or m_Predicate changed /// TreeItem *TreeItemFromIndex(const QModelIndex &index) const; /// /// Gives a ModelIndex for the Tree Item /// QModelIndex IndexFromTreeItem(TreeItem *) const; /// /// Returns the first element in the nodes sources list (if available) or 0 /// mitk::DataNode *GetParentNode(const mitk::DataNode *node) const; /// /// Adds all Childs in parent to vec. Before a child is added the function is called recursively /// void TreeToVector(TreeItem *parent, std::vector &vec) const; /// /// Adds all Childs in parent to vec. Before a child is added the function is called recursively /// void TreeToNodeSet(TreeItem *parent, QList &vec) const; /// /// Update Tree Model /// void Update(); //# ATTRIBUTES protected: mitk::WeakPointer m_DataStorage; mitk::NodePredicateBase::Pointer m_Predicate; bool m_PlaceNewNodesOnTop; TreeItem *m_Root; /// Flag to block the data storage events if nodes are added/removed by this class. bool m_BlockDataStorageEvents; /// This decides whether or not it is allowed to assign a different parent to a node /// If it is false, it is not possible to change the hierarchy of nodes by dragging /// and dropping. /// If it is true, dragging nodes on another node will replace all of their parents /// with that one. bool m_AllowHierarchyChange; private: void AddNodeInternal(const mitk::DataNode *); void RemoveNodeInternal(const mitk::DataNode *); /// /// Checks if dicom properties patient name, study names and series name exists /// bool DicomPropertiesExists(const mitk::DataNode &) const; unsigned long m_DataStorageDeletedTag; }; #endif /* QMITKDATASTORAGETREEMODEL_H_ */ diff --git a/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp b/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp index a5b633993d..0eb69dc16a 100644 --- a/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp +++ b/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp @@ -1,1041 +1,1041 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include #include #include #include "QmitkDataStorageTreeModel.h" #include "QmitkNodeDescriptorManager.h" #include #include #include #include #include #include #include #include #include QmitkDataStorageTreeModel::QmitkDataStorageTreeModel(mitk::DataStorage *_DataStorage, bool _PlaceNewNodesOnTop, QObject *parent) : QAbstractItemModel(parent), m_DataStorage(0), m_PlaceNewNodesOnTop(_PlaceNewNodesOnTop), m_Root(0), m_BlockDataStorageEvents(false), m_AllowHierarchyChange(false) { this->SetDataStorage(_DataStorage); } QmitkDataStorageTreeModel::~QmitkDataStorageTreeModel() { // set data storage to 0 = remove all listeners this->SetDataStorage(0); m_Root->Delete(); m_Root = 0; } mitk::DataNode::Pointer QmitkDataStorageTreeModel::GetNode(const QModelIndex &index) const { return this->TreeItemFromIndex(index)->GetDataNode(); } const mitk::DataStorage::Pointer QmitkDataStorageTreeModel::GetDataStorage() const { return m_DataStorage.Lock(); } QModelIndex QmitkDataStorageTreeModel::index(int row, int column, const QModelIndex &parent) const { TreeItem *parentItem; if (!parent.isValid()) parentItem = m_Root; else parentItem = static_cast(parent.internalPointer()); TreeItem *childItem = parentItem->GetChild(row); if (childItem) return createIndex(row, column, childItem); else return QModelIndex(); } int QmitkDataStorageTreeModel::rowCount(const QModelIndex &parent) const { TreeItem *parentTreeItem = this->TreeItemFromIndex(parent); return parentTreeItem->GetChildCount(); } Qt::ItemFlags QmitkDataStorageTreeModel::flags(const QModelIndex &index) const { mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode(); if (index.isValid()) { if (DicomPropertiesExists(*dataNode)) { return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } else { return Qt::ItemIsDropEnabled; } } int QmitkDataStorageTreeModel::columnCount(const QModelIndex & /* parent = QModelIndex() */) const { return 1; } QModelIndex QmitkDataStorageTreeModel::parent(const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); TreeItem *childItem = this->TreeItemFromIndex(index); TreeItem *parentItem = childItem->GetParent(); if (parentItem == m_Root) return QModelIndex(); return this->createIndex(parentItem->GetIndex(), 0, parentItem); } QmitkDataStorageTreeModel::TreeItem *QmitkDataStorageTreeModel::TreeItemFromIndex(const QModelIndex &index) const { if (index.isValid()) return static_cast(index.internalPointer()); else return m_Root; } Qt::DropActions QmitkDataStorageTreeModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions QmitkDataStorageTreeModel::supportedDragActions() const { return Qt::CopyAction | Qt::MoveAction; } bool QmitkDataStorageTreeModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent) { // Early exit, returning true, but not actually doing anything (ignoring data). if (action == Qt::IgnoreAction) { return true; } // Note, we are returning true if we handled it, and false otherwise bool returnValue = false; if (data->hasFormat("application/x-qabstractitemmodeldatalist")) { returnValue = true; // First we extract a Qlist of TreeItem* pointers. QList listOfItemsToDrop = ToTreeItemPtrList(data); if (listOfItemsToDrop.empty()) { return false; } // Retrieve the TreeItem* where we are dropping stuff, and its parent. TreeItem *dropItem = this->TreeItemFromIndex(parent); TreeItem *parentItem = dropItem->GetParent(); // If item was dropped onto empty space, we select the root node if (dropItem == m_Root) { parentItem = m_Root; } // Dragging and Dropping is only allowed within the same parent, so use the first item in list to validate. // (otherwise, you could have a derived image such as a segmentation, and assign it to another image). // NOTE: We are assuming the input list is valid... i.e. when it was dragged, all the items had the same parent. // Determine whether or not the drag and drop operation is a valid one. // Examples of invalid operations include: // - dragging nodes with different parents // - dragging nodes from one parent to another parent, if m_AllowHierarchyChange is false // - dragging a node on one of its child nodes (only relevant if m_AllowHierarchyChange is true) bool isValidDragAndDropOperation(true); // different parents { TreeItem *firstParent = listOfItemsToDrop[0]->GetParent(); QList::iterator diIter; for (diIter = listOfItemsToDrop.begin() + 1; diIter != listOfItemsToDrop.end(); diIter++) { if (firstParent != (*diIter)->GetParent()) { isValidDragAndDropOperation = false; break; } } } // dragging from one parent to another if ((!m_AllowHierarchyChange) && isValidDragAndDropOperation) { if (row == -1) // drag onto a node { isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == parentItem; } else // drag between nodes { isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == dropItem; } } // dragging on a child node of one the dragged nodes { QList::iterator diIter; for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++) { TreeItem *tempItem = dropItem; while (tempItem != m_Root) { tempItem = tempItem->GetParent(); if (tempItem == *diIter) { isValidDragAndDropOperation = false; } } } } if (!isValidDragAndDropOperation) return isValidDragAndDropOperation; if (listOfItemsToDrop[0] != dropItem && isValidDragAndDropOperation) { // Retrieve the index of where we are dropping stuff. QModelIndex parentModelIndex = this->IndexFromTreeItem(parentItem); int dragIndex = 0; // Iterate through the list of TreeItem (which may be at non-consecutive indexes). QList::iterator diIter; for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++) { TreeItem *itemToDrop = *diIter; // if the item is dragged down we have to compensate its final position for the // fact it is deleted lateron, this only applies if it is dragged within the same level if ((itemToDrop->GetIndex() < row) && (itemToDrop->GetParent() == dropItem)) { dragIndex = 1; } // Here we assume that as you remove items, one at a time, that GetIndex() will be valid. this->beginRemoveRows( this->IndexFromTreeItem(itemToDrop->GetParent()), itemToDrop->GetIndex(), itemToDrop->GetIndex()); itemToDrop->GetParent()->RemoveChild(itemToDrop); this->endRemoveRows(); } // row = -1 dropped on an item, row != -1 dropped in between two items // Select the target index position, or put it at the end of the list. int dropIndex = 0; if (row != -1) { if (dragIndex == 0) dropIndex = std::min(row, parentItem->GetChildCount() - 1); else dropIndex = std::min(row - 1, parentItem->GetChildCount() - 1); } else { dropIndex = dropItem->GetIndex(); } QModelIndex dropItemModelIndex = this->IndexFromTreeItem(dropItem); if ((row == -1 && dropItemModelIndex.row() == -1) || dropItemModelIndex.row() > parentItem->GetChildCount()) dropIndex = parentItem->GetChildCount() - 1; // Now insert items again at the drop item position if (m_AllowHierarchyChange) { this->beginInsertRows(dropItemModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1); } else { this->beginInsertRows(parentModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1); } for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++) { // dropped on node, behaviour depends on preference setting if (m_AllowHierarchyChange) { auto dataStorage = m_DataStorage.Lock(); m_BlockDataStorageEvents = true; mitk::DataNode *droppedNode = (*diIter)->GetDataNode(); mitk::DataNode *dropOntoNode = dropItem->GetDataNode(); dataStorage->Remove(droppedNode); dataStorage->Add(droppedNode, dropOntoNode); m_BlockDataStorageEvents = false; dropItem->InsertChild((*diIter), dropIndex); } else { if (row == -1) // drag onto a node { parentItem->InsertChild((*diIter), dropIndex); } else // drag between nodes { dropItem->InsertChild((*diIter), dropIndex); } } dropIndex++; } this->endInsertRows(); // Change Layers to match. this->AdjustLayerProperty(); } } else if (data->hasFormat("application/x-mitk-datanodes")) { returnValue = true; int numberOfNodesDropped = 0; QList dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data); mitk::DataNode *node = nullptr; foreach (node, dataNodeList) { if (node && !m_DataStorage.IsExpired() && !m_DataStorage.Lock()->Exists(node)) { m_DataStorage.Lock()->Add(node); mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); numberOfNodesDropped++; } } } // Only do a rendering update, if we actually dropped anything. if (numberOfNodesDropped > 0) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } return returnValue; } QStringList QmitkDataStorageTreeModel::mimeTypes() const { QStringList types = QAbstractItemModel::mimeTypes(); types << "application/x-qabstractitemmodeldatalist"; types << "application/x-mitk-datanodes"; return types; } QMimeData *QmitkDataStorageTreeModel::mimeData(const QModelIndexList &indexes) const { return mimeDataFromModelIndexList(indexes); } QMimeData *QmitkDataStorageTreeModel::mimeDataFromModelIndexList(const QModelIndexList &indexes) { QMimeData *ret = new QMimeData; QString treeItemAddresses(""); QString dataNodeAddresses(""); QByteArray baTreeItemPtrs; QByteArray baDataNodePtrs; QDataStream dsTreeItemPtrs(&baTreeItemPtrs, QIODevice::WriteOnly); QDataStream dsDataNodePtrs(&baDataNodePtrs, QIODevice::WriteOnly); for (int i = 0; i < indexes.size(); i++) { TreeItem *treeItem = static_cast(indexes.at(i).internalPointer()); dsTreeItemPtrs << reinterpret_cast(treeItem); dsDataNodePtrs << reinterpret_cast(treeItem->GetDataNode().GetPointer()); // --------------- deprecated ----------------- unsigned long long treeItemAddress = reinterpret_cast(treeItem); unsigned long long dataNodeAddress = reinterpret_cast(treeItem->GetDataNode().GetPointer()); QTextStream(&treeItemAddresses) << treeItemAddress; QTextStream(&dataNodeAddresses) << dataNodeAddress; if (i != indexes.size() - 1) { QTextStream(&treeItemAddresses) << ","; QTextStream(&dataNodeAddresses) << ","; } // -------------- end deprecated ------------- } // ------------------ deprecated ----------------- ret->setData("application/x-qabstractitemmodeldatalist", QByteArray(treeItemAddresses.toLatin1())); ret->setData("application/x-mitk-datanodes", QByteArray(dataNodeAddresses.toLatin1())); // --------------- end deprecated ----------------- ret->setData(QmitkMimeTypes::DataStorageTreeItemPtrs, baTreeItemPtrs); ret->setData(QmitkMimeTypes::DataNodePtrs, baDataNodePtrs); return ret; } QVariant QmitkDataStorageTreeModel::data(const QModelIndex &index, int role) const { mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode(); // get name of treeItem (may also be edited) QString nodeName; if (DicomPropertiesExists(*dataNode)) { mitk::BaseProperty *seriesDescription = (dataNode->GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x103e).c_str())); mitk::BaseProperty *studyDescription = (dataNode->GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x1030).c_str())); mitk::BaseProperty *patientsName = (dataNode->GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0010, 0x0010).c_str())); mitk::BaseProperty *seriesDescription_deprecated = (dataNode->GetProperty("dicom.series.SeriesDescription")); mitk::BaseProperty *studyDescription_deprecated = (dataNode->GetProperty("dicom.study.StudyDescription")); mitk::BaseProperty *patientsName_deprecated = (dataNode->GetProperty("dicom.patient.PatientsName")); if (patientsName) { nodeName += QString::fromStdString(patientsName->GetValueAsString()) + "\n"; nodeName += QString::fromStdString(studyDescription->GetValueAsString()) + "\n"; nodeName += QString::fromStdString(seriesDescription->GetValueAsString()); } else { /** Code coveres the deprecated property naming for backwards compatibility */ nodeName += QString::fromStdString(patientsName_deprecated->GetValueAsString()) + "\n"; nodeName += QString::fromStdString(studyDescription_deprecated->GetValueAsString()) + "\n"; nodeName += QString::fromStdString(seriesDescription_deprecated->GetValueAsString()); } } else { nodeName = QString::fromStdString(dataNode->GetName()); } if (nodeName.isEmpty()) { nodeName = "unnamed"; } if (role == Qt::DisplayRole) return nodeName; else if (role == Qt::ToolTipRole) return nodeName; else if (role == Qt::DecorationRole) { QmitkNodeDescriptor *nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(dataNode); return nodeDescriptor->GetIcon(dataNode); } else if (role == Qt::CheckStateRole) { return dataNode->IsVisible(0); } else if (role == QmitkDataNodeRole) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } else if (role == QmitkDataNodeRawPointerRole) { return QVariant::fromValue(dataNode); } return QVariant(); } bool QmitkDataStorageTreeModel::DicomPropertiesExists(const mitk::DataNode &node) const { bool propertiesExists = false; mitk::BaseProperty *seriesDescription_deprecated = (node.GetProperty("dicom.series.SeriesDescription")); mitk::BaseProperty *studyDescription_deprecated = (node.GetProperty("dicom.study.StudyDescription")); mitk::BaseProperty *patientsName_deprecated = (node.GetProperty("dicom.patient.PatientsName")); mitk::BaseProperty *seriesDescription = (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x103e).c_str())); mitk::BaseProperty *studyDescription = (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x1030).c_str())); mitk::BaseProperty *patientsName = (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0010, 0x0010).c_str())); if (patientsName != nullptr && studyDescription != nullptr && seriesDescription != nullptr) { if ((!patientsName->GetValueAsString().empty()) && (!studyDescription->GetValueAsString().empty()) && (!seriesDescription->GetValueAsString().empty())) { propertiesExists = true; } } /** Code coveres the deprecated property naming for backwards compatibility */ if (patientsName_deprecated != nullptr && studyDescription_deprecated != nullptr && seriesDescription_deprecated != nullptr) { if ((!patientsName_deprecated->GetValueAsString().empty()) && (!studyDescription_deprecated->GetValueAsString().empty()) && (!seriesDescription_deprecated->GetValueAsString().empty())) { propertiesExists = true; } } return propertiesExists; } QVariant QmitkDataStorageTreeModel::headerData(int /*section*/, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole && m_Root) return QString::fromStdString(m_Root->GetDataNode()->GetName()); return QVariant(); } void QmitkDataStorageTreeModel::SetDataStorage(mitk::DataStorage *_DataStorage) { if (m_DataStorage != _DataStorage) // dont take the same again { if (!m_DataStorage.IsExpired()) { auto dataStorage = m_DataStorage.Lock(); // remove Listener for the data storage itself dataStorage->RemoveObserver(m_DataStorageDeletedTag); // remove listeners for the nodes dataStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkDataStorageTreeModel::AddNode)); dataStorage->ChangedNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetNodeModified)); dataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::RemoveNode)); } // take over the new data storage m_DataStorage = _DataStorage; // delete the old root (if necessary, create new) if (m_Root) m_Root->Delete(); mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); rootDataNode->SetName("Data Manager"); m_Root = new TreeItem(rootDataNode, 0); this->beginResetModel(); this->endResetModel(); if (!m_DataStorage.IsExpired()) { auto dataStorage = m_DataStorage.Lock(); // add Listener for the data storage itself auto command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkDataStorageTreeModel::SetDataStorageDeleted); m_DataStorageDeletedTag = dataStorage->AddObserver(itk::DeleteEvent(), command); // add listeners for the nodes dataStorage->AddNodeEvent.AddListener(mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::AddNode)); dataStorage->ChangedNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetNodeModified)); dataStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::RemoveNode)); mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = dataStorage->GetSubset(m_Predicate); // finally add all nodes to the model this->Update(); } } } void QmitkDataStorageTreeModel::SetDataStorageDeleted() { this->SetDataStorage(0); } void QmitkDataStorageTreeModel::AddNodeInternal(const mitk::DataNode *node) { if (node == 0 || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != 0) return; // find out if we have a root node TreeItem *parentTreeItem = m_Root; QModelIndex index; mitk::DataNode *parentDataNode = this->GetParentNode(node); if (parentDataNode) // no top level data node { parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item if (!parentTreeItem) { this->AddNode(parentDataNode); parentTreeItem = m_Root->Find(parentDataNode); if (!parentTreeItem) return; } // get the index of this parent with the help of the grand parent index = this->createIndex(parentTreeItem->GetIndex(), 0, parentTreeItem); } // add node if (m_PlaceNewNodesOnTop) { // emit beginInsertRows event beginInsertRows(index, 0, 0); parentTreeItem->InsertChild(new TreeItem(const_cast(node)), 0); } else { int firstRowWithASiblingBelow = 0; int nodeLayer = -1; node->GetIntProperty("layer", nodeLayer); for (TreeItem* siblingTreeItem: parentTreeItem->GetChildren()) { int siblingLayer = -1; if (mitk::DataNode* siblingNode = siblingTreeItem->GetDataNode()) { siblingNode->GetIntProperty("layer", siblingLayer); } if (nodeLayer > siblingLayer) { break; } ++firstRowWithASiblingBelow; } beginInsertRows(index, firstRowWithASiblingBelow, firstRowWithASiblingBelow); parentTreeItem->InsertChild(new TreeItem(const_cast(node)), firstRowWithASiblingBelow); } // emit endInsertRows event endInsertRows(); if(m_PlaceNewNodesOnTop) { this->AdjustLayerProperty(); } } void QmitkDataStorageTreeModel::AddNode(const mitk::DataNode *node) { if (node == 0 || m_BlockDataStorageEvents || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != 0) return; this->AddNodeInternal(node); } void QmitkDataStorageTreeModel::SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop) { m_PlaceNewNodesOnTop = _PlaceNewNodesOnTop; } void QmitkDataStorageTreeModel::RemoveNodeInternal(const mitk::DataNode *node) { if (!m_Root) return; TreeItem *treeItem = m_Root->Find(node); if (!treeItem) return; // return because there is no treeitem containing this node TreeItem *parentTreeItem = treeItem->GetParent(); QModelIndex parentIndex = this->IndexFromTreeItem(parentTreeItem); // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model) this->beginRemoveRows(parentIndex, treeItem->GetIndex(), treeItem->GetIndex()); // remove node std::vector children = treeItem->GetChildren(); delete treeItem; // emit endRemoveRows event endRemoveRows(); // move all children of deleted node into its parent for (std::vector::iterator it = children.begin(); it != children.end(); it++) { // emit beginInsertRows event beginInsertRows(parentIndex, parentTreeItem->GetChildCount(), parentTreeItem->GetChildCount()); // add nodes again parentTreeItem->AddChild(*it); // emit endInsertRows event endInsertRows(); } this->AdjustLayerProperty(); } void QmitkDataStorageTreeModel::RemoveNode(const mitk::DataNode *node) { if (node == 0 || m_BlockDataStorageEvents) return; this->RemoveNodeInternal(node); } void QmitkDataStorageTreeModel::SetNodeModified(const mitk::DataNode *node) { TreeItem *treeItem = m_Root->Find(node); if (treeItem) { TreeItem *parentTreeItem = treeItem->GetParent(); // as the root node should not be removed one should always have a parent item if (!parentTreeItem) return; QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem); // now emit the dataChanged signal emit dataChanged(index, index); } } mitk::DataNode *QmitkDataStorageTreeModel::GetParentNode(const mitk::DataNode *node) const { mitk::DataNode *dataNode = 0; mitk::DataStorage::SetOfObjects::ConstPointer _Sources = m_DataStorage.Lock()->GetSources(node); if (_Sources->Size() > 0) dataNode = _Sources->front(); return dataNode; } bool QmitkDataStorageTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode(); if (!dataNode) return false; if (role == Qt::EditRole && !value.toString().isEmpty()) { dataNode->SetStringProperty("name", value.toString().toStdString().c_str()); mitk::PlanarFigure *planarFigure = dynamic_cast(dataNode->GetData()); if (planarFigure != nullptr) mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if (role == Qt::CheckStateRole) { // Please note: value.toInt() returns 2, independentely from the actual checkstate of the index element. // Therefore the checkstate is being estimated again here. QVariant qcheckstate = index.data(Qt::CheckStateRole); int checkstate = qcheckstate.toInt(); bool isVisible = bool(checkstate); dataNode->SetVisibility(!isVisible); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + emit nodeVisibilityChanged(); } // inform listeners about changes emit dataChanged(index, index); return true; } bool QmitkDataStorageTreeModel::setHeaderData(int /*section*/, Qt::Orientation /*orientation*/, const QVariant & /* value */, int /*role = Qt::EditRole*/) { return false; } void QmitkDataStorageTreeModel::AdjustLayerProperty() { /// transform the tree into an array and set the layer property descending std::vector vec; this->TreeToVector(m_Root, vec); int i = vec.size() - 1; for (std::vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { mitk::DataNode::Pointer dataNode = (*it)->GetDataNode(); bool fixedLayer = false; if (!(dataNode->GetBoolProperty("fixedLayer", fixedLayer) && fixedLayer)) dataNode->SetIntProperty("layer", i); --i; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataStorageTreeModel::TreeToVector(TreeItem *parent, std::vector &vec) const { TreeItem *current; for (int i = 0; i < parent->GetChildCount(); ++i) { current = parent->GetChild(i); this->TreeToVector(current, vec); vec.push_back(current); } } QModelIndex QmitkDataStorageTreeModel::IndexFromTreeItem(TreeItem *item) const { if (item == m_Root) return QModelIndex(); else return this->createIndex(item->GetIndex(), 0, item); } QList QmitkDataStorageTreeModel::GetNodeSet() const { QList res; if (m_Root) this->TreeToNodeSet(m_Root, res); return res; } void QmitkDataStorageTreeModel::TreeToNodeSet(TreeItem *parent, QList &vec) const { TreeItem *current; for (int i = 0; i < parent->GetChildCount(); ++i) { current = parent->GetChild(i); vec.push_back(current->GetDataNode()); this->TreeToNodeSet(current, vec); } } QModelIndex QmitkDataStorageTreeModel::GetIndex(const mitk::DataNode *node) const { if (m_Root) { TreeItem *item = m_Root->Find(node); if (item) return this->IndexFromTreeItem(item); } return QModelIndex(); } QList QmitkDataStorageTreeModel::ToTreeItemPtrList(const QMimeData *mimeData) { if (mimeData == nullptr || !mimeData->hasFormat(QmitkMimeTypes::DataStorageTreeItemPtrs)) { return QList(); } return ToTreeItemPtrList(mimeData->data(QmitkMimeTypes::DataStorageTreeItemPtrs)); } QList QmitkDataStorageTreeModel::ToTreeItemPtrList(const QByteArray &ba) { QList result; QDataStream ds(ba); while (!ds.atEnd()) { quintptr treeItemPtr; ds >> treeItemPtr; result.push_back(reinterpret_cast(treeItemPtr)); } return result; } QmitkDataStorageTreeModel::TreeItem::TreeItem(mitk::DataNode *_DataNode, TreeItem *_Parent) : m_Parent(_Parent), m_DataNode(_DataNode) { if (m_Parent) m_Parent->AddChild(this); } QmitkDataStorageTreeModel::TreeItem::~TreeItem() { if (m_Parent) m_Parent->RemoveChild(this); } void QmitkDataStorageTreeModel::TreeItem::Delete() { while (m_Children.size() > 0) delete m_Children.back(); delete this; } QmitkDataStorageTreeModel::TreeItem *QmitkDataStorageTreeModel::TreeItem::Find(const mitk::DataNode *_DataNode) const { QmitkDataStorageTreeModel::TreeItem *item = 0; if (_DataNode) { if (m_DataNode == _DataNode) item = const_cast(this); else { for (std::vector::const_iterator it = m_Children.begin(); it != m_Children.end(); ++it) { if (item) break; item = (*it)->Find(_DataNode); } } } return item; } int QmitkDataStorageTreeModel::TreeItem::IndexOfChild(const TreeItem *item) const { std::vector::const_iterator it = std::find(m_Children.begin(), m_Children.end(), item); return it != m_Children.end() ? std::distance(m_Children.begin(), it) : -1; } QmitkDataStorageTreeModel::TreeItem *QmitkDataStorageTreeModel::TreeItem::GetChild(int index) const { return (m_Children.size() > 0 && index >= 0 && index < (int)m_Children.size()) ? m_Children.at(index) : 0; } void QmitkDataStorageTreeModel::TreeItem::AddChild(TreeItem *item) { this->InsertChild(item); } void QmitkDataStorageTreeModel::TreeItem::RemoveChild(TreeItem *item) { std::vector::iterator it = std::find(m_Children.begin(), m_Children.end(), item); if (it != m_Children.end()) { m_Children.erase(it); item->SetParent(0); } } int QmitkDataStorageTreeModel::TreeItem::GetChildCount() const { return m_Children.size(); } int QmitkDataStorageTreeModel::TreeItem::GetIndex() const { if (m_Parent) return m_Parent->IndexOfChild(this); return 0; } QmitkDataStorageTreeModel::TreeItem *QmitkDataStorageTreeModel::TreeItem::GetParent() const { return m_Parent; } mitk::DataNode::Pointer QmitkDataStorageTreeModel::TreeItem::GetDataNode() const { return m_DataNode; } void QmitkDataStorageTreeModel::TreeItem::InsertChild(TreeItem *item, int index) { std::vector::iterator it = std::find(m_Children.begin(), m_Children.end(), item); if (it == m_Children.end()) { if (m_Children.size() > 0 && index >= 0 && index < (int)m_Children.size()) { it = m_Children.begin(); std::advance(it, index); m_Children.insert(it, item); } else m_Children.push_back(item); // add parent if necessary if (item->GetParent() != this) item->SetParent(this); } } std::vector QmitkDataStorageTreeModel::TreeItem::GetChildren() const { return m_Children; } void QmitkDataStorageTreeModel::TreeItem::SetParent(TreeItem *_Parent) { m_Parent = _Parent; if (m_Parent) m_Parent->AddChild(this); } void QmitkDataStorageTreeModel::Update() { if (!m_DataStorage.IsExpired()) { mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = m_DataStorage.Lock()->GetAll(); /// Regardless the value of this preference, the new nodes must not be inserted /// at the top now, but at the position according to their layer. bool newNodesWereToBePlacedOnTop = m_PlaceNewNodesOnTop; m_PlaceNewNodesOnTop = false; for (const auto& node: *_NodeSet) { this->AddNodeInternal(node); } m_PlaceNewNodesOnTop = newNodesWereToBePlacedOnTop; /// Adjust the layers to ensure that derived nodes are above their sources. this->AdjustLayerProperty(); } } void QmitkDataStorageTreeModel::SetAllowHierarchyChange(bool allowHierarchyChange) { m_AllowHierarchyChange = allowHierarchyChange; } diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp index 463d5dbfcd..5ce2e74497 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.cpp @@ -1,110 +1,106 @@ /*=================================================================== 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 "QmitkDataManagerPreferencePage.h" #include "QmitkDataManagerView.h" #include #include #include #include #include #include QmitkDataManagerPreferencePage::QmitkDataManagerPreferencePage() -: m_MainControl(nullptr) + : m_MainControl(nullptr) { } void QmitkDataManagerPreferencePage::Init(berry::IWorkbench::Pointer ) { } void QmitkDataManagerPreferencePage::CreateQtControl(QWidget* parent) { berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); m_DataManagerPreferencesNode = prefService->GetSystemPreferences()->Node(QmitkDataManagerView::VIEW_ID); m_MainControl = new QWidget(parent); m_EnableSingleEditing = new QCheckBox; m_PlaceNewNodesOnTop = new QCheckBox; m_ShowHelperObjects = new QCheckBox; m_ShowNodesContainingNoData = new QCheckBox; m_GlobalReinitOnNodeDelete = new QCheckBox; m_GlobalReinitOnNodeAdded = new QCheckBox; + m_GlobalReinitOnNodeVisibilityChanged = new QCheckBox; m_UseSurfaceDecimation = new QCheckBox; m_AllowParentChange = new QCheckBox; auto formLayout = new QFormLayout; formLayout->addRow("&Single click property editing:", m_EnableSingleEditing); formLayout->addRow("&Place new nodes on top:", m_PlaceNewNodesOnTop); formLayout->addRow("&Show helper objects:", m_ShowHelperObjects); formLayout->addRow("&Show nodes containing no data", m_ShowNodesContainingNoData); formLayout->addRow("&Call global reinit if node is deleted", m_GlobalReinitOnNodeDelete); formLayout->addRow("&Call global reinit if node is added", m_GlobalReinitOnNodeAdded); + formLayout->addRow("&Call global reinit if node visibility is changed", m_GlobalReinitOnNodeVisibilityChanged); formLayout->addRow("&Use surface decimation:", m_UseSurfaceDecimation); formLayout->addRow("&Allow changing of parent node:", m_AllowParentChange); m_MainControl->setLayout(formLayout); this->Update(); } QWidget* QmitkDataManagerPreferencePage::GetQtControl() const { return m_MainControl; } bool QmitkDataManagerPreferencePage::PerformOk() { - m_DataManagerPreferencesNode->PutBool("Single click property editing" - , m_EnableSingleEditing->isChecked()); - m_DataManagerPreferencesNode->PutBool("Place new nodes on top" - , m_PlaceNewNodesOnTop->isChecked()); - m_DataManagerPreferencesNode->PutBool("Show helper objects" - , m_ShowHelperObjects->isChecked()); - m_DataManagerPreferencesNode->PutBool("Show nodes containing no data" - , m_ShowNodesContainingNoData->isChecked()); - m_DataManagerPreferencesNode->PutBool("Call global reinit if node is deleted" - , m_GlobalReinitOnNodeDelete->isChecked()); - m_DataManagerPreferencesNode->PutBool("Call global reinit if node is added" - , m_GlobalReinitOnNodeAdded->isChecked()); - m_DataManagerPreferencesNode->PutBool("Use surface decimation" - , m_UseSurfaceDecimation->isChecked()); - m_DataManagerPreferencesNode->PutBool("Allow changing of parent node" - , m_AllowParentChange->isChecked()); + m_DataManagerPreferencesNode->PutBool("Single click property editing", m_EnableSingleEditing->isChecked()); + m_DataManagerPreferencesNode->PutBool("Place new nodes on top", m_PlaceNewNodesOnTop->isChecked()); + m_DataManagerPreferencesNode->PutBool("Show helper objects", m_ShowHelperObjects->isChecked()); + m_DataManagerPreferencesNode->PutBool("Show nodes containing no data", m_ShowNodesContainingNoData->isChecked()); + m_DataManagerPreferencesNode->PutBool("Call global reinit if node is deleted", m_GlobalReinitOnNodeDelete->isChecked()); + m_DataManagerPreferencesNode->PutBool("Call global reinit if node is added", m_GlobalReinitOnNodeAdded->isChecked()); + m_DataManagerPreferencesNode->PutBool("Call global reinit if node visibility is changed", m_GlobalReinitOnNodeVisibilityChanged->isChecked()); + m_DataManagerPreferencesNode->PutBool("Use surface decimation", m_UseSurfaceDecimation->isChecked()); + m_DataManagerPreferencesNode->PutBool("Allow changing of parent node", m_AllowParentChange->isChecked()); return true; } void QmitkDataManagerPreferencePage::PerformCancel() { } void QmitkDataManagerPreferencePage::Update() { m_EnableSingleEditing->setChecked(m_DataManagerPreferencesNode->GetBool("Single click property editing", true)); m_PlaceNewNodesOnTop->setChecked(m_DataManagerPreferencesNode->GetBool("Place new nodes on top", true)); m_ShowHelperObjects->setChecked(m_DataManagerPreferencesNode->GetBool("Show helper objects", false)); m_ShowNodesContainingNoData->setChecked(m_DataManagerPreferencesNode->GetBool("Show nodes containing no data", false)); m_UseSurfaceDecimation->setChecked(m_DataManagerPreferencesNode->GetBool("Use surface decimation", true)); m_GlobalReinitOnNodeDelete->setChecked(m_DataManagerPreferencesNode->GetBool("Call global reinit if node is deleted", true)); m_GlobalReinitOnNodeAdded->setChecked(m_DataManagerPreferencesNode->GetBool("Call global reinit if node is added", true)); + m_GlobalReinitOnNodeVisibilityChanged->setChecked(m_DataManagerPreferencesNode->GetBool("Call global reinit if node visibility is changed", false)); m_AllowParentChange->setChecked(m_DataManagerPreferencesNode->GetBool("Allow changing of parent node", false)); } diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h index 56324aa13c..2c4f826626 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerPreferencePage.h @@ -1,70 +1,71 @@ /*=================================================================== 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 QMITKDATAMANAGERPREFERENCEPAGE_H_ #define QMITKDATAMANAGERPREFERENCEPAGE_H_ #include "berryIQtPreferencePage.h" #include #include class QWidget; class QCheckBox; struct MITK_QT_DATAMANAGER QmitkDataManagerPreferencePage : public QObject, public berry::IQtPreferencePage { Q_OBJECT Q_INTERFACES(berry::IPreferencePage) public: QmitkDataManagerPreferencePage(); void Init(berry::IWorkbench::Pointer workbench) override; void CreateQtControl(QWidget* widget) override; QWidget* GetQtControl() const override; /// /// \see IPreferencePage::PerformOk() /// bool PerformOk() override; /// /// \see IPreferencePage::PerformCancel() /// void PerformCancel() override; /// /// \see IPreferencePage::Update() /// void Update() override; protected: QWidget* m_MainControl; QCheckBox* m_EnableSingleEditing; QCheckBox* m_PlaceNewNodesOnTop; QCheckBox* m_ShowHelperObjects; QCheckBox* m_ShowNodesContainingNoData; QCheckBox* m_GlobalReinitOnNodeDelete; QCheckBox* m_GlobalReinitOnNodeAdded; + QCheckBox* m_GlobalReinitOnNodeVisibilityChanged; QCheckBox* m_UseSurfaceDecimation; QCheckBox* m_AllowParentChange; berry::IPreferences::Pointer m_DataManagerPreferencesNode; }; #endif /* QMITKDATAMANAGERPREFERENCEPAGE_H_ */ diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp index c8b6cecb48..e02f5ac0d4 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp @@ -1,1199 +1,1213 @@ /*=================================================================== 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 "QmitkDataManagerView.h" //# Own Includes //## mitk #include "mitkDataStorageEditorInput.h" #include "mitkIDataStorageReference.h" #include "mitkNodePredicateDataType.h" #include "mitkCoreObjectFactory.h" #include "mitkColorProperty.h" #include "mitkCommon.h" #include "mitkNodePredicateData.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateOr.h" #include "mitkNodePredicateProperty.h" #include "mitkEnumerationProperty.h" #include "mitkLookupTableProperty.h" #include "mitkProperties.h" #include #include #include #include #include //## Qmitk #include #include #include #include #include #include #include #include "src/internal/QmitkNodeTableViewKeyFilter.h" #include "src/internal/QmitkInfoDialog.h" #include "src/internal/QmitkDataManagerItemDelegate.h" //## Berry #include #include #include #include #include #include #include #include //# Toolkit Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDataNodeObject.h" #include "mitkIContextMenuAction.h" #include "berryIExtensionRegistry.h" #include "mitkRenderingModeProperty.h" const QString QmitkDataManagerView::VIEW_ID = "org.mitk.views.datamanager"; QmitkDataManagerView::QmitkDataManagerView() - : m_GlobalReinitOnNodeDelete(true), - m_ItemDelegate(nullptr) + : m_GlobalReinitOnNodeDelete(true) + , m_GlobalReinitOnNodeVisibilityChanged(false) + , m_ItemDelegate(nullptr) { } QmitkDataManagerView::~QmitkDataManagerView() { //Remove all registered actions from each descriptor for (std::vector< std::pair< QmitkNodeDescriptor*, QAction* > >::iterator it = m_DescriptorActionList.begin();it != m_DescriptorActionList.end(); it++) { // first== the NodeDescriptor; second== the registered QAction (it->first)->RemoveAction(it->second); } } void QmitkDataManagerView::CreateQtPartControl(QWidget* parent) { m_CurrentRowCount = 0; m_Parent = parent; //# Preferences berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); berry::IBerryPreferences::Pointer prefs = (prefService->GetSystemPreferences()->Node(VIEW_ID)) .Cast(); assert( prefs ); prefs->OnChanged.AddListener( berry::MessageDelegate1( this , &QmitkDataManagerView::OnPreferencesChanged ) ); //# GUI m_NodeTreeModel = new QmitkDataStorageTreeModel(this->GetDataStorage(), prefs->GetBool("Place new nodes on top", true)); m_NodeTreeModel->setParent( parent ); m_NodeTreeModel->SetAllowHierarchyChange( prefs->GetBool("Allow changing of parent node", false)); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); // Prepare filters m_HelperObjectFilterPredicate = mitk::NodePredicateOr::New( mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)), mitk::NodePredicateProperty::New("hidden object", mitk::BoolProperty::New(true))); m_NodeWithNoDataFilterPredicate = mitk::NodePredicateData::New(0); m_FilterModel = new QmitkDataStorageFilterProxyModel(); m_FilterModel->setSourceModel(m_NodeTreeModel); m_FilterModel->AddFilterPredicate(m_HelperObjectFilterPredicate); m_FilterModel->AddFilterPredicate(m_NodeWithNoDataFilterPredicate); //# Tree View (experimental) m_NodeTreeView = new QTreeView; m_NodeTreeView->setHeaderHidden(true); m_NodeTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection ); m_NodeTreeView->setSelectionBehavior( QAbstractItemView::SelectRows ); m_NodeTreeView->setAlternatingRowColors(true); m_NodeTreeView->setDragEnabled(true); m_NodeTreeView->setDropIndicatorShown(true); m_NodeTreeView->setAcceptDrops(true); m_NodeTreeView->setContextMenuPolicy(Qt::CustomContextMenu); m_NodeTreeView->setModel(m_FilterModel); m_NodeTreeView->setTextElideMode(Qt::ElideMiddle); m_NodeTreeView->installEventFilter(new QmitkNodeTableViewKeyFilter(this)); m_ItemDelegate = new QmitkDataManagerItemDelegate(m_NodeTreeView); m_NodeTreeView->setItemDelegate(m_ItemDelegate); - QObject::connect( m_NodeTreeView, SIGNAL(customContextMenuRequested(const QPoint&)) + connect( m_NodeTreeView, SIGNAL(customContextMenuRequested(const QPoint&)) , this, SLOT(NodeTableViewContextMenuRequested(const QPoint&)) ); - QObject::connect( m_NodeTreeModel, SIGNAL(rowsInserted (const QModelIndex&, int, int)) + connect( m_NodeTreeModel, SIGNAL(rowsInserted (const QModelIndex&, int, int)) , this, SLOT(NodeTreeViewRowsInserted ( const QModelIndex&, int, int )) ); - QObject::connect( m_NodeTreeModel, SIGNAL(rowsRemoved (const QModelIndex&, int, int)) + connect( m_NodeTreeModel, SIGNAL(rowsRemoved (const QModelIndex&, int, int)) , this, SLOT(NodeTreeViewRowsRemoved( const QModelIndex&, int, int )) ); - QObject::connect( m_NodeTreeView->selectionModel() + connect( m_NodeTreeView->selectionModel() , SIGNAL( selectionChanged ( const QItemSelection &, const QItemSelection & ) ) , this , SLOT( NodeSelectionChanged ( const QItemSelection &, const QItemSelection & ) ) ); + connect(m_NodeTreeModel, &QmitkDataStorageTreeModel::nodeVisibilityChanged, this, &QmitkDataManagerView::OnNodeVisibilityChanged); //# m_NodeMenu m_NodeMenu = new QMenu(m_NodeTreeView); // # Actions berry::IEditorRegistry* editorRegistry = berry::PlatformUI::GetWorkbench()->GetEditorRegistry(); QList editors = editorRegistry->GetEditors("*.mitk"); if (editors.size() > 1) { m_ShowInMapper = new QSignalMapper(this); foreach(berry::IEditorDescriptor::Pointer descriptor, editors) { QAction* action = new QAction(descriptor->GetLabel(), this); m_ShowInActions << action; m_ShowInMapper->connect(action, SIGNAL(triggered()), m_ShowInMapper, SLOT(map())); m_ShowInMapper->setMapping(action, descriptor->GetId()); } connect(m_ShowInMapper, SIGNAL(mapped(QString)), this, SLOT(ShowIn(QString))); } auto unknownDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetUnknownDataNodeDescriptor(); auto imageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Image"); auto multiComponentImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("MultiComponentImage"); auto diffusionImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("DiffusionImage"); auto fiberBundleDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("FiberBundle"); auto peakImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PeakImage"); auto segmentDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Segment"); auto surfaceDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Surface"); auto pointSetNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PointSet"); auto planarLineNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarLine"); auto planarCircleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarCircle"); auto planarEllipseNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarEllipse"); auto planarAngleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarAngle"); auto planarFourPointAngleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarFourPointAngle"); auto planarRectangleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarRectangle"); auto planarPolygonNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarPolygon"); auto planarPathNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarPath"); auto planarDoubleEllipseNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarDoubleEllipse"); auto planarBezierCurveNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarBezierCurve"); auto planarSubdivisionPolygonNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarSubdivisionPolygon"); QAction* globalReinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), tr("Global Reinit"), this); QObject::connect( globalReinitAction, SIGNAL( triggered(bool) ) , this, SLOT( GlobalReinit(bool) ) ); unknownDataNodeDescriptor->AddAction(globalReinitAction); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor, globalReinitAction)); QAction* saveAction = new QmitkFileSaveAction(QIcon(":/org.mitk.gui.qt.datamanager/Save_48.png"), this->GetSite()->GetWorkbenchWindow()); unknownDataNodeDescriptor->AddAction(saveAction); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor,saveAction)); QAction* removeAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Remove_48.png"), tr("Remove"), this); QObject::connect( removeAction, SIGNAL( triggered(bool) ) , this, SLOT( RemoveSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(removeAction); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor,removeAction)); QAction* reinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), tr("Reinit"), this); QObject::connect( reinitAction, SIGNAL( triggered(bool) ) , this, SLOT( ReinitSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(reinitAction); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor,reinitAction)); // find contextMenuAction extension points and add them to the node descriptor berry::IExtensionRegistry* extensionPointService = berry::Platform::GetExtensionRegistry(); QList customMenuConfigs = extensionPointService->GetConfigurationElementsFor("org.mitk.gui.qt.datamanager.contextMenuActions"); // Prepare all custom QActions m_ConfElements.clear(); DescriptorActionListType customMenuEntries; for (auto& customMenuConfig : customMenuConfigs) { QString actionNodeDescriptorName = customMenuConfig->GetAttribute("nodeDescriptorName"); QString actionLabel = customMenuConfig->GetAttribute("label"); QString actionClass = customMenuConfig->GetAttribute("class"); if (actionNodeDescriptorName.isEmpty() || actionLabel.isEmpty() || actionClass.isEmpty()) { continue; } QString actionIconName = customMenuConfig->GetAttribute("icon"); // Find matching descriptor auto nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(actionNodeDescriptorName); if ( nodeDescriptor == nullptr) { MITK_WARN << "Cannot add action \"" << actionLabel << "\" because descriptor " << actionNodeDescriptorName << " does not exist."; continue; } // Create action with or without icon QAction* contextMenuAction; if ( !actionIconName.isEmpty() ) { QIcon actionIcon; if ( QFile::exists(actionIconName) ) { actionIcon = QIcon(actionIconName); } else { actionIcon = berry::AbstractUICTKPlugin::ImageDescriptorFromPlugin( customMenuConfig->GetContributor()->GetName(), actionIconName); } contextMenuAction = new QAction(actionIcon, actionLabel, parent); } else { contextMenuAction = new QAction(actionLabel, parent); } // Define menu handler to trigger on click connect(contextMenuAction, static_cast(&QAction::triggered), this, &QmitkDataManagerView::ContextMenuActionTriggered); // Mark configuration element into lookup list for context menu handler m_ConfElements[contextMenuAction] = customMenuConfig; // Mark new action in sortable list for addition to descriptor customMenuEntries.emplace_back(nodeDescriptor, contextMenuAction); } // Sort all custom QActions by their texts { using ListEntryType = std::pair; std::sort(customMenuEntries.begin(), customMenuEntries.end(), [](const ListEntryType& left, const ListEntryType& right) -> bool { assert (left.second != nullptr && right.second != nullptr); // unless we messed up above return left.second->text() < right.second->text(); }); } // Add custom QActions in sorted order int globalAddedMenuIndex=1; for (auto& menuEntryToAdd : customMenuEntries) { auto& nodeDescriptor = menuEntryToAdd.first; auto& contextMenuAction = menuEntryToAdd.second; // TODO is the action "data" used by anything? Otherwise remove! contextMenuAction->setData(static_cast(globalAddedMenuIndex)); ++globalAddedMenuIndex; // Really add this action to that descriptor (in pre-defined order) nodeDescriptor->AddAction(contextMenuAction); // Mark new action into list of descriptors to remove in d'tor m_DescriptorActionList.push_back(menuEntryToAdd); } m_OpacitySlider = new QSlider; m_OpacitySlider->setMinimum(0); m_OpacitySlider->setMaximum(100); m_OpacitySlider->setOrientation(Qt::Horizontal); QObject::connect( m_OpacitySlider, SIGNAL( valueChanged(int) ) , this, SLOT( OpacityChanged(int) ) ); QLabel* _OpacityLabel = new QLabel(tr("Opacity: ")); QHBoxLayout* _OpacityWidgetLayout = new QHBoxLayout; _OpacityWidgetLayout->setContentsMargins(4,4,4,4); _OpacityWidgetLayout->addWidget(_OpacityLabel); _OpacityWidgetLayout->addWidget(m_OpacitySlider); QWidget* _OpacityWidget = new QWidget; _OpacityWidget->setLayout(_OpacityWidgetLayout); QWidgetAction* opacityAction = new QWidgetAction(this); opacityAction ->setDefaultWidget(_OpacityWidget); QObject::connect( opacityAction , SIGNAL( changed() ) , this, SLOT( OpacityActionChanged() ) ); unknownDataNodeDescriptor->AddAction(opacityAction , false); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor,opacityAction)); m_ColorButton = new QPushButton; m_ColorButton->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum); //m_ColorButton->setText("Change color"); QObject::connect( m_ColorButton, SIGNAL( clicked() ) , this, SLOT( ColorChanged() ) ); QLabel* _ColorLabel = new QLabel(tr("Color: ")); _ColorLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); QHBoxLayout* _ColorWidgetLayout = new QHBoxLayout; _ColorWidgetLayout->setContentsMargins(4,4,4,4); _ColorWidgetLayout->addWidget(_ColorLabel); _ColorWidgetLayout->addWidget(m_ColorButton); QWidget* _ColorWidget = new QWidget; _ColorWidget->setLayout(_ColorWidgetLayout); QWidgetAction* colorAction = new QWidgetAction(this); colorAction->setDefaultWidget(_ColorWidget); QObject::connect( colorAction, SIGNAL( changed() ) , this, SLOT( ColorActionChanged() ) ); { // only give the color context menu option where appropriate bool colorActionCanBatch = true; if (imageDataNodeDescriptor != nullptr) { imageDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(imageDataNodeDescriptor, colorAction)); } if (multiComponentImageDataNodeDescriptor != nullptr) { multiComponentImageDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(multiComponentImageDataNodeDescriptor, colorAction)); } if (diffusionImageDataNodeDescriptor != nullptr) { diffusionImageDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(diffusionImageDataNodeDescriptor, colorAction)); } if (fiberBundleDataNodeDescriptor != nullptr) { fiberBundleDataNodeDescriptor->AddAction(colorAction, false); m_DescriptorActionList.push_back(std::make_pair(fiberBundleDataNodeDescriptor, colorAction)); } if (peakImageDataNodeDescriptor != nullptr) { peakImageDataNodeDescriptor->AddAction(colorAction, false); m_DescriptorActionList.push_back(std::make_pair(peakImageDataNodeDescriptor, colorAction)); } if (segmentDataNodeDescriptor != nullptr) { segmentDataNodeDescriptor->AddAction(colorAction, false); m_DescriptorActionList.push_back(std::make_pair(segmentDataNodeDescriptor, colorAction)); } if (surfaceDataNodeDescriptor != nullptr) { surfaceDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(surfaceDataNodeDescriptor, colorAction)); } if (pointSetNodeDescriptor != nullptr) { pointSetNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(pointSetNodeDescriptor, colorAction)); } if (planarLineNodeDescriptor != nullptr) { planarLineNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarLineNodeDescriptor, colorAction)); } if (planarCircleNodeDescriptor != nullptr) { planarCircleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarCircleNodeDescriptor, colorAction)); } if (planarEllipseNodeDescriptor != nullptr) { planarEllipseNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarEllipseNodeDescriptor, colorAction)); } if (planarAngleNodeDescriptor != nullptr) { planarAngleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarAngleNodeDescriptor, colorAction)); } if (planarFourPointAngleNodeDescriptor != nullptr) { planarFourPointAngleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarFourPointAngleNodeDescriptor, colorAction)); } if (planarRectangleNodeDescriptor != nullptr) { planarRectangleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarRectangleNodeDescriptor, colorAction)); } if (planarPolygonNodeDescriptor != nullptr) { planarPolygonNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarPolygonNodeDescriptor, colorAction)); } if (planarPathNodeDescriptor != nullptr) { planarPathNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarPathNodeDescriptor, colorAction)); } if (planarDoubleEllipseNodeDescriptor != nullptr) { planarDoubleEllipseNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarDoubleEllipseNodeDescriptor, colorAction)); } if (planarBezierCurveNodeDescriptor != nullptr) { planarBezierCurveNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarBezierCurveNodeDescriptor, colorAction)); } if (planarSubdivisionPolygonNodeDescriptor != nullptr) { planarSubdivisionPolygonNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(planarSubdivisionPolygonNodeDescriptor, colorAction)); } } m_ComponentSlider = new QmitkNumberPropertySlider; m_ComponentSlider->setOrientation(Qt::Horizontal); //QObject::connect( m_OpacitySlider, SIGNAL( valueChanged(int) ) // , this, SLOT( OpacityChanged(int) ) ); QLabel* _ComponentLabel = new QLabel(tr("Component: ")); QHBoxLayout* _ComponentWidgetLayout = new QHBoxLayout; _ComponentWidgetLayout->setContentsMargins(4,4,4,4); _ComponentWidgetLayout->addWidget(_ComponentLabel); _ComponentWidgetLayout->addWidget(m_ComponentSlider); QLabel* _ComponentValueLabel = new QLabel(); _ComponentWidgetLayout->addWidget(_ComponentValueLabel); connect(m_ComponentSlider, SIGNAL(valueChanged(int)), _ComponentValueLabel, SLOT(setNum(int))); QWidget* _ComponentWidget = new QWidget; _ComponentWidget->setLayout(_ComponentWidgetLayout); QWidgetAction* componentAction = new QWidgetAction(this); componentAction->setDefaultWidget(_ComponentWidget); QObject::connect( componentAction , SIGNAL( changed() ) , this, SLOT( ComponentActionChanged() ) ); multiComponentImageDataNodeDescriptor->AddAction(componentAction, false); m_DescriptorActionList.push_back(std::make_pair(multiComponentImageDataNodeDescriptor,componentAction)); if (diffusionImageDataNodeDescriptor!=nullptr) { diffusionImageDataNodeDescriptor->AddAction(componentAction, false); m_DescriptorActionList.push_back(std::make_pair(diffusionImageDataNodeDescriptor,componentAction)); } m_TextureInterpolation = new QAction(tr("Texture Interpolation"), this); m_TextureInterpolation->setCheckable ( true ); QObject::connect( m_TextureInterpolation, SIGNAL( changed() ) , this, SLOT( TextureInterpolationChanged() ) ); QObject::connect( m_TextureInterpolation, SIGNAL( toggled(bool) ) , this, SLOT( TextureInterpolationToggled(bool) ) ); imageDataNodeDescriptor->AddAction(m_TextureInterpolation, false); m_DescriptorActionList.push_back(std::make_pair(imageDataNodeDescriptor,m_TextureInterpolation)); if (diffusionImageDataNodeDescriptor!=nullptr) { diffusionImageDataNodeDescriptor->AddAction(m_TextureInterpolation, false); m_DescriptorActionList.push_back(std::make_pair(diffusionImageDataNodeDescriptor,m_TextureInterpolation)); } if (segmentDataNodeDescriptor != nullptr) { segmentDataNodeDescriptor->AddAction(m_TextureInterpolation, false); m_DescriptorActionList.push_back(std::make_pair(segmentDataNodeDescriptor, m_TextureInterpolation)); } m_ColormapAction = new QAction(tr("Colormap"), this); m_ColormapAction->setMenu(new QMenu); QObject::connect( m_ColormapAction->menu(), SIGNAL( aboutToShow() ) , this, SLOT( ColormapMenuAboutToShow() ) ); imageDataNodeDescriptor->AddAction(m_ColormapAction, false); m_DescriptorActionList.push_back(std::make_pair(imageDataNodeDescriptor, m_ColormapAction)); if (diffusionImageDataNodeDescriptor!=nullptr) { diffusionImageDataNodeDescriptor->AddAction(m_ColormapAction, false); m_DescriptorActionList.push_back(std::make_pair(diffusionImageDataNodeDescriptor, m_ColormapAction)); } m_SurfaceRepresentation = new QAction(tr("Surface Representation"), this); m_SurfaceRepresentation->setMenu(new QMenu(m_NodeTreeView)); QObject::connect( m_SurfaceRepresentation->menu(), SIGNAL( aboutToShow() ) , this, SLOT( SurfaceRepresentationMenuAboutToShow() ) ); surfaceDataNodeDescriptor->AddAction(m_SurfaceRepresentation, false); m_DescriptorActionList.push_back(std::make_pair(surfaceDataNodeDescriptor, m_SurfaceRepresentation)); QAction* showOnlySelectedNodes = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowSelectedNode_48.png") , tr("Show only selected nodes"), this); QObject::connect( showOnlySelectedNodes, SIGNAL( triggered(bool) ) , this, SLOT( ShowOnlySelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(showOnlySelectedNodes); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor, showOnlySelectedNodes)); QAction* toggleSelectedVisibility = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/InvertShowSelectedNode_48.png") , tr("Toggle visibility"), this); QObject::connect( toggleSelectedVisibility, SIGNAL( triggered(bool) ) , this, SLOT( ToggleVisibilityOfSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(toggleSelectedVisibility); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor,toggleSelectedVisibility)); QAction* actionShowInfoDialog = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowDataInfo_48.png") , tr("Details..."), this); QObject::connect( actionShowInfoDialog, SIGNAL( triggered(bool) ) , this, SLOT( ShowInfoDialogForSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(actionShowInfoDialog); m_DescriptorActionList.push_back(std::make_pair(unknownDataNodeDescriptor,actionShowInfoDialog)); QGridLayout* _DndFrameWidgetLayout = new QGridLayout; _DndFrameWidgetLayout->addWidget(m_NodeTreeView, 0, 0); _DndFrameWidgetLayout->setContentsMargins(0,0,0,0); m_DndFrameWidget = new QmitkDnDFrameWidget(m_Parent); m_DndFrameWidget->setLayout(_DndFrameWidgetLayout); QVBoxLayout* layout = new QVBoxLayout(parent); layout->addWidget(m_DndFrameWidget); layout->setContentsMargins(0,0,0,0); m_Parent->setLayout(layout); } void QmitkDataManagerView::SetFocus() { } void QmitkDataManagerView::ContextMenuActionTriggered( bool ) { QAction* action = qobject_cast ( sender() ); std::map::iterator it = m_ConfElements.find( action ); if( it == m_ConfElements.end() ) { MITK_WARN << "associated conf element for action " << action->text().toStdString() << " not found"; return; } berry::IConfigurationElement::Pointer confElem = it->second; mitk::IContextMenuAction* contextMenuAction = confElem->CreateExecutableExtension("class"); QString className = confElem->GetAttribute("class"); QString smoothed = confElem->GetAttribute("smoothed"); contextMenuAction->SetDataStorage(this->GetDataStorage()); if(className == "QmitkCreatePolygonModelAction") { if(smoothed == "false") { contextMenuAction->SetSmoothed(false); } else { contextMenuAction->SetSmoothed(true); } contextMenuAction->SetDecimated(m_SurfaceDecimation); } else if(className == "QmitkStatisticsAction") { contextMenuAction->SetFunctionality(this); } contextMenuAction->Run( this->GetCurrentSelection() ); // run the action } void QmitkDataManagerView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { - if( m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() != prefs->GetBool("Place new nodes on top", true) ) - m_NodeTreeModel->SetPlaceNewNodesOnTop( !m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() ); + if (m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() != prefs->GetBool("Place new nodes on top", true)) + { + m_NodeTreeModel->SetPlaceNewNodesOnTop(!m_NodeTreeModel->GetPlaceNewNodesOnTopFlag()); + } bool hideHelperObjects = !prefs->GetBool("Show helper objects", false); if (m_FilterModel->HasFilterPredicate(m_HelperObjectFilterPredicate) != hideHelperObjects) { if (hideHelperObjects) { - m_FilterModel->AddFilterPredicate(m_HelperObjectFilterPredicate); + m_FilterModel->AddFilterPredicate(m_HelperObjectFilterPredicate); } else { - m_FilterModel->RemoveFilterPredicate(m_HelperObjectFilterPredicate); + m_FilterModel->RemoveFilterPredicate(m_HelperObjectFilterPredicate); } } - bool hideNodesWithNoData = !prefs->GetBool("Show nodes containing no data", false); + bool hideNodesWithNoData = !prefs->GetBool("Show nodes containing no data", false); if (m_FilterModel->HasFilterPredicate(m_NodeWithNoDataFilterPredicate) != hideNodesWithNoData) { if (hideNodesWithNoData) { - m_FilterModel->AddFilterPredicate(m_NodeWithNoDataFilterPredicate); + m_FilterModel->AddFilterPredicate(m_NodeWithNoDataFilterPredicate); } else { - m_FilterModel->RemoveFilterPredicate(m_NodeWithNoDataFilterPredicate); + m_FilterModel->RemoveFilterPredicate(m_NodeWithNoDataFilterPredicate); } } m_GlobalReinitOnNodeDelete = prefs->GetBool("Call global reinit if node is deleted", true); + m_GlobalReinitOnNodeVisibilityChanged = prefs->GetBool("Call global reinit if node visibility is changed", false); m_NodeTreeView->expandAll(); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); - m_NodeTreeModel->SetAllowHierarchyChange( - prefs->GetBool("Allow changing of parent node", false)); + m_NodeTreeModel->SetAllowHierarchyChange(prefs->GetBool("Allow changing of parent node", false)); this->GlobalReinit(); - - } void QmitkDataManagerView::NodeTableViewContextMenuRequested( const QPoint & pos ) { QModelIndex selectedProxy = m_NodeTreeView->indexAt ( pos ); QModelIndex selected = m_FilterModel->mapToSource(selectedProxy); mitk::DataNode::Pointer node = m_NodeTreeModel->GetNode(selected); QList selectedNodes = this->GetCurrentSelection(); if(!selectedNodes.isEmpty()) { ColorActionChanged(); // update color button m_NodeMenu->clear(); QList actions; if(selectedNodes.size() == 1 ) { actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(node); for(QList::iterator it = actions.begin(); it != actions.end(); ++it) { (*it)->setData(QVariant::fromValue(node.GetPointer())); } } else actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(selectedNodes); if (!m_ShowInActions.isEmpty()) { QMenu* showInMenu = m_NodeMenu->addMenu(tr("Show In")); showInMenu->addActions(m_ShowInActions); } m_NodeMenu->addActions(actions); m_NodeMenu->popup(QCursor::pos()); } } void QmitkDataManagerView::OpacityChanged(int value) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { float opacity = static_cast(value)/100.0f; node->SetFloatProperty("opacity", opacity); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::OpacityActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { float opacity = 0.0; if(node->GetFloatProperty("opacity", opacity)) { m_OpacitySlider->setValue(static_cast(opacity*100)); } } } void QmitkDataManagerView::ComponentActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); mitk::IntProperty* componentProperty = nullptr; int numComponents = 0; if(node) { componentProperty = dynamic_cast(node->GetProperty("Image.Displayed Component")); mitk::Image* img = dynamic_cast(node->GetData()); if (img != nullptr) { numComponents = img->GetPixelType().GetNumberOfComponents(); } } if (componentProperty && numComponents > 1) { m_ComponentSlider->SetProperty(componentProperty); m_ComponentSlider->setMinValue(0); m_ComponentSlider->setMaxValue(numComponents-1); } else { m_ComponentSlider->SetProperty(static_cast(nullptr)); } } void QmitkDataManagerView::ColorChanged() { bool color_selected = false; QColor newColor; auto selected_indices = m_NodeTreeView->selectionModel()->selectedIndexes(); for (auto& selected_index : selected_indices) { auto node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(selected_index)); if(node) { float rgb[3]; if (node->GetColor(rgb)) { if (!color_selected) { QColor initial(rgb[0] * 255, rgb[1] * 255, rgb[2] * 255); newColor = QColorDialog::getColor(initial, 0, QString(tr("Change color"))); if ( newColor.isValid() ) { color_selected = true; } else { return; } } node->SetProperty("color", mitk::ColorProperty::New(newColor.redF(), newColor.greenF(), newColor.blueF())); if ( node->GetProperty("binaryimage.selectedcolor") ) { node->SetProperty("binaryimage.selectedcolor", mitk::ColorProperty::New(newColor.redF(), newColor.greenF(), newColor.blueF())); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ColorActionChanged() { // Adapts color displayed in context menu item auto selected_indices = m_NodeTreeView->selectionModel()->selectedIndexes(); if (selected_indices.isEmpty()) return; mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(selected_indices.front())); if(node) { float rgb[3]; if (node->GetColor(rgb)) { QColor color(rgb[0] * 255, rgb[1] * 255, rgb[2] * 255); QString styleSheet = QString("background-color: ") + color.name(QColor::HexRgb); m_ColorButton->setAutoFillBackground(true); m_ColorButton->setStyleSheet(styleSheet); } } } void QmitkDataManagerView::TextureInterpolationChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { bool textureInterpolation = false; node->GetBoolProperty("texture interpolation", textureInterpolation); m_TextureInterpolation->setChecked(textureInterpolation); } } void QmitkDataManagerView::TextureInterpolationToggled( bool checked ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { node->SetBoolProperty("texture interpolation", checked); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::ColormapActionToggled( bool /*checked*/ ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(!node) return; mitk::LookupTableProperty::Pointer lookupTableProperty = dynamic_cast(node->GetProperty("LookupTable")); if (!lookupTableProperty) return; QAction* senderAction = qobject_cast(QObject::sender()); if(!senderAction) return; std::string activatedItem = senderAction->text().toStdString(); mitk::LookupTable::Pointer lookupTable = lookupTableProperty->GetValue(); if (!lookupTable) return; lookupTable->SetType(activatedItem); lookupTableProperty->SetValue(lookupTable); mitk::RenderingModeProperty::Pointer renderingMode = dynamic_cast(node->GetProperty("Image Rendering.Mode")); renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ColormapMenuAboutToShow() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(!node) return; mitk::LookupTableProperty::Pointer lookupTableProperty = dynamic_cast(node->GetProperty("LookupTable")); if (!lookupTableProperty) { mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); lookupTableProperty = mitk::LookupTableProperty::New(); lookupTableProperty->SetLookupTable(mitkLut); node->SetProperty("LookupTable", lookupTableProperty); } mitk::LookupTable::Pointer lookupTable = lookupTableProperty->GetValue(); if (!lookupTable) return; m_ColormapAction->menu()->clear(); QAction* tmp; int i = 0; std::string lutType = lookupTable->typenameList[i]; while (lutType != "END_OF_ARRAY") { tmp = m_ColormapAction->menu()->addAction(QString::fromStdString(lutType)); tmp->setCheckable(true); if (lutType == lookupTable->GetActiveTypeAsString()) { tmp->setChecked(true); } QObject::connect(tmp, SIGNAL(triggered(bool)), this, SLOT(ColormapActionToggled(bool))); lutType = lookupTable->typenameList[++i]; } } void QmitkDataManagerView::SurfaceRepresentationMenuAboutToShow() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(!node) return; mitk::EnumerationProperty* representationProp = dynamic_cast (node->GetProperty("material.representation")); if(!representationProp) return; // clear menu m_SurfaceRepresentation->menu()->clear(); QAction* tmp; // create menu entries for(mitk::EnumerationProperty::EnumConstIterator it=representationProp->Begin(); it!=representationProp->End() ; it++) { tmp = m_SurfaceRepresentation->menu()->addAction(QString::fromStdString(it->second)); tmp->setCheckable(true); if(it->second == representationProp->GetValueAsString()) { tmp->setChecked(true); } QObject::connect( tmp, SIGNAL( triggered(bool) ) , this, SLOT( SurfaceRepresentationActionToggled(bool) ) ); } } void QmitkDataManagerView::SurfaceRepresentationActionToggled( bool /*checked*/ ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(!node) return; mitk::EnumerationProperty* representationProp = dynamic_cast (node->GetProperty("material.representation")); if(!representationProp) return; QAction* senderAction = qobject_cast ( QObject::sender() ); if(!senderAction) return; std::string activatedItem = senderAction->text().toStdString(); if ( activatedItem != representationProp->GetValueAsString() ) { if ( representationProp->IsValidEnumerationValue( activatedItem ) ) { representationProp->SetValue( activatedItem ); representationProp->InvokeEvent( itk::ModifiedEvent() ); representationProp->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkDataManagerView::ReinitSelectedNodes( bool ) { mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); if (renderWindow == nullptr) renderWindow = this->OpenRenderWindowPart(false); QList selectedNodes = this->GetCurrentSelection(); foreach(mitk::DataNode::Pointer node, selectedNodes) { mitk::BaseData::Pointer basedata = node->GetData(); if ( basedata.IsNotNull() && basedata->GetTimeGeometry()->IsValid() ) { renderWindow->GetRenderingManager()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); } } } void QmitkDataManagerView::RemoveSelectedNodes( bool ) { QModelIndexList indexesOfSelectedRowsFiltered = m_NodeTreeView->selectionModel()->selectedRows(); QModelIndexList indexesOfSelectedRows; for (int i = 0; i < indexesOfSelectedRowsFiltered.size(); ++i) { indexesOfSelectedRows.push_back(m_FilterModel->mapToSource(indexesOfSelectedRowsFiltered[i])); } if(indexesOfSelectedRows.size() < 1) { return; } std::vector selectedNodes; mitk::DataNode::Pointer node = 0; QString question = tr("Do you really want to remove "); for (QModelIndexList::iterator it = indexesOfSelectedRows.begin() ; it != indexesOfSelectedRows.end(); it++) { node = m_NodeTreeModel->GetNode(*it); // if node is not defined or if the node contains geometry data do not remove it if ( node.IsNotNull() /*& strcmp(node->GetData()->GetNameOfClass(), "PlaneGeometryData") != 0*/ ) { selectedNodes.push_back(node); question.append(QString::fromStdString(node->GetName())); question.append(", "); } } // remove the last two characters = ", " question = question.remove(question.size()-2, 2); question.append(tr(" from data storage?")); QMessageBox::StandardButton answerButton = QMessageBox::question( m_Parent , tr("DataManager") , question , QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if(answerButton == QMessageBox::Yes) { for (std::vector::iterator it = selectedNodes.begin() ; it != selectedNodes.end(); it++) { node = *it; this->GetDataStorage()->Remove(node); if (m_GlobalReinitOnNodeDelete) this->GlobalReinit(false); } } } void QmitkDataManagerView::MakeAllNodesInvisible( bool ) { QList nodes = m_NodeTreeModel->GetNodeSet(); foreach(mitk::DataNode::Pointer node, nodes) { node->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ShowOnlySelectedNodes( bool ) { QList selectedNodes = this->GetCurrentSelection(); QList allNodes = m_NodeTreeModel->GetNodeSet(); foreach(mitk::DataNode::Pointer node, allNodes) { node->SetVisibility(selectedNodes.contains(node)); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ToggleVisibilityOfSelectedNodes( bool ) { QList selectedNodes = this->GetCurrentSelection(); bool isVisible = false; foreach(mitk::DataNode::Pointer node, selectedNodes) { isVisible = false; node->GetBoolProperty("visible", isVisible); node->SetVisibility(!isVisible); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ShowInfoDialogForSelectedNodes( bool ) { QList selectedNodes = this->GetCurrentSelection(); QmitkInfoDialog _QmitkInfoDialog(selectedNodes, this->m_Parent); _QmitkInfoDialog.exec(); } void QmitkDataManagerView::NodeChanged(const mitk::DataNode* /*node*/) { // m_FilterModel->invalidate(); // fix as proposed by R. Khlebnikov in the mitk-users mail from 02.09.2014 QMetaObject::invokeMethod( m_FilterModel, "invalidate", Qt::QueuedConnection ); } QItemSelectionModel *QmitkDataManagerView::GetDataNodeSelectionModel() const { return m_NodeTreeView->selectionModel(); } void QmitkDataManagerView::GlobalReinit( bool ) { mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); if (renderWindow == nullptr) renderWindow = this->OpenRenderWindowPart(false); // no render window available if (renderWindow == nullptr) return; mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); } void QmitkDataManagerView::NodeTreeViewRowsRemoved ( const QModelIndex & /*parent*/, int /*start*/, int /*end*/ ) { m_CurrentRowCount = m_NodeTreeModel->rowCount(); } void QmitkDataManagerView::NodeTreeViewRowsInserted( const QModelIndex & parent, int, int ) { QModelIndex viewIndex = m_FilterModel->mapFromSource(parent); m_NodeTreeView->setExpanded(viewIndex, true); // a new row was inserted if( m_CurrentRowCount == 0 && m_NodeTreeModel->rowCount() == 1 ) { this->OpenRenderWindowPart(); m_CurrentRowCount = m_NodeTreeModel->rowCount(); } } void QmitkDataManagerView::NodeSelectionChanged( const QItemSelection & /*selected*/, const QItemSelection & /*deselected*/ ) { QList nodes = m_NodeTreeModel->GetNodeSet(); foreach(mitk::DataNode::Pointer node, nodes) { if ( node.IsNotNull() ) node->SetBoolProperty("selected", false); } nodes.clear(); nodes = this->GetCurrentSelection(); foreach(mitk::DataNode::Pointer node, nodes) { if ( node.IsNotNull() ) node->SetBoolProperty("selected", true); } //changing the selection does NOT require any rendering processes! //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } +void QmitkDataManagerView::OnNodeVisibilityChanged() +{ + if (m_GlobalReinitOnNodeVisibilityChanged) + { + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); + } + else + { + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } +} + void QmitkDataManagerView::ShowIn(const QString &editorId) { berry::IWorkbenchPage::Pointer page = this->GetSite()->GetPage(); berry::IEditorInput::Pointer input(new mitk::DataStorageEditorInput(this->GetDataStorageReference())); page->OpenEditor(input, editorId, false, berry::IWorkbenchPage::MATCH_ID); } mitk::IRenderWindowPart* QmitkDataManagerView::OpenRenderWindowPart(bool activatedEditor) { if (activatedEditor) { return this->GetRenderWindowPart(QmitkAbstractView::ACTIVATE | QmitkAbstractView::OPEN); } else { return this->GetRenderWindowPart(QmitkAbstractView::BRING_TO_FRONT | QmitkAbstractView::OPEN); } } diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h index ed6dcf5db9..2d2e5515aa 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h @@ -1,267 +1,270 @@ /*=================================================================== 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 QMITKDATAMANAGERVIEW_H_ #define QMITKDATAMANAGERVIEW_H_ // BlueBerry includes #include /// Qmitk #include #include /// Qt #include #include // Forward declarations class QMenu; class QAction; class QComboBox; class QWidgetAction; class QSlider; class QModelIndex; class QTreeView; class QPushButton; class QToolBar; class QMenu; class QSignalMapper; class QmitkDnDFrameWidget; class QmitkDataStorageTreeModel; class QmitkDataManagerItemDelegate; class QmitkNumberPropertySlider; class QmitkDataStorageFilterProxyModel; /// /// \ingroup org_mitk_gui_qt_datamanager_internal /// /// \brief A View class that can show all data tree nodes of a certain DataStorage /// /// \TODO: complete PACS support, in save dialog show regular filename /// class MITK_QT_DATAMANAGER QmitkDataManagerView : public QmitkAbstractView { Q_OBJECT public: static const QString VIEW_ID; // = "org.mitk.extapp.defaultperspective" /// /// \brief Standard ctor. /// QmitkDataManagerView(); /// /// \brief Standard dtor. /// ~QmitkDataManagerView() override; public slots: /// /// Invoked when the opacity slider changed /// void OpacityChanged(int value); /// /// Invoked when the opacity action changed /// In this function the the opacity slider is set to the selected nodes opacity value /// void OpacityActionChanged(); /// Invoked when the component action changed /// In this function the the opacity slider is set to the selected nodes opacity value /// void ComponentActionChanged(); /// /// Invoked when the color button is pressed /// void ColorChanged(); /// /// Invoked when the color action changed /// void ColorActionChanged(); /// /// Invoked when the color button is pressed /// void TextureInterpolationChanged(); /// /// Invoked when the color action changed /// void TextureInterpolationToggled ( bool checked ); /// /// \brief Agreggates available colormaps /// void ColormapMenuAboutToShow (); /// /// \brief changes the active colormap /// void ColormapActionToggled (bool); /// /// SurfaceRepresentationActionToggled /// void SurfaceRepresentationMenuAboutToShow (); /// /// SurfaceRepresentationActionToggled /// void SurfaceRepresentationActionToggled ( bool checked ); /// /// \brief Shows a node context menu. /// void NodeTableViewContextMenuRequested( const QPoint & index ); /// /// \brief Invoked when an element should be removed. /// void RemoveSelectedNodes( bool checked = false ); /// /// \brief Invoked when an element should be reinitiliased. /// void ReinitSelectedNodes( bool checked = false ); /// /// \brief Invoked when the visibility of the selected nodes should be toggled. /// void MakeAllNodesInvisible ( bool checked = false ); /// /// \brief Makes all selected nodes visible, all other nodes invisible. /// void ShowOnlySelectedNodes ( bool checked = false ); /// /// \brief Invoked when the visibility of the selected nodes should be toggled. /// void ToggleVisibilityOfSelectedNodes ( bool checked = false ); /// /// \brief Invoked when infos of the selected nodes should be shown in a dialog. /// void ShowInfoDialogForSelectedNodes ( bool checked = false ); /// /// \brief Reinits everything. /// void GlobalReinit ( bool checked = false ); /// /// Invoked when the preferences were changed /// void OnPreferencesChanged(const berry::IBerryPreferences*) override; /// /// \brief will be toggled when a extension point context menu action is toggled /// this is a proxy method which will load the corresponding extension class /// and run IContextMenuAction /// void ContextMenuActionTriggered( bool ); /// When rows are inserted auto expand them void NodeTreeViewRowsInserted ( const QModelIndex & parent, int start, int end ); /// will setup m_CurrentRowCount void NodeTreeViewRowsRemoved ( const QModelIndex & parent, int start, int end ); /// Whenever the selection changes set the "selected" property respectively void NodeSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected ); + void OnNodeVisibilityChanged(); + /// Opens the editor with the given id using the current data storage void ShowIn(const QString& editorId); protected: /// /// \brief Create the view here. /// void CreateQtPartControl(QWidget* parent) override; void SetFocus() override; /// /// \brief Shows a file open dialog. /// void FileOpen( const char * fileName, mitk::DataNode* parentNode ); /// /// React to node changes. Overridden from QmitkAbstractView. /// void NodeChanged(const mitk::DataNode* /*node*/) override; protected: QWidget* m_Parent; QmitkDnDFrameWidget* m_DndFrameWidget; /// /// \brief A plain widget as the base pane. /// QmitkDataStorageTreeModel* m_NodeTreeModel; QmitkDataStorageFilterProxyModel* m_FilterModel; mitk::NodePredicateBase::Pointer m_HelperObjectFilterPredicate; mitk::NodePredicateBase::Pointer m_NodeWithNoDataFilterPredicate; /// /// Holds the preferences for the datamanager. /// berry::IBerryPreferences::Pointer m_DataManagerPreferencesNode; /// /// saves the configuration elements for the context menu actions from extension points /// std::map m_ConfElements; /// /// \brief The Table view to show the selected nodes. /// QTreeView* m_NodeTreeView; /// /// \brief The context menu that shows up when right clicking on a node. /// QMenu* m_NodeMenu; /// /// \brief flag indicating whether a surface created from a selected decimation is decimated with vtkQuadricDecimation or not /// bool m_SurfaceDecimation; ///# A list of ALL actions for the Context Menu using DescriptorActionListType = std::vector< std::pair< QmitkNodeDescriptor*, QAction* > >; DescriptorActionListType m_DescriptorActionList; /// A Slider widget to change the opacity of a node QSlider* m_OpacitySlider; /// A Slider widget to change the rendered vector component of an image QmitkNumberPropertySlider* m_ComponentSlider; /// button to change the color of a node QPushButton* m_ColorButton; /// TextureInterpolation action QAction* m_TextureInterpolation; /// SurfaceRepresentation action QAction* m_SurfaceRepresentation; /// Lookuptable selection action QAction* m_ColormapAction; /// Maps "Show in" actions to editor ids QSignalMapper* m_ShowInMapper; /// A list of "Show in" actions QList m_ShowInActions; /// saves the current amount of rows shown in the datamanager size_t m_CurrentRowCount; /// if true, GlobalReinit() is called if a node is deleted bool m_GlobalReinitOnNodeDelete; + bool m_GlobalReinitOnNodeVisibilityChanged; QmitkDataManagerItemDelegate* m_ItemDelegate; private: QItemSelectionModel* GetDataNodeSelectionModel() const override; /// Reopen multi widget editor if it has been closed mitk::IRenderWindowPart *OpenRenderWindowPart(bool activatedEditor = true); }; #endif /*QMITKDATAMANAGERVIEW_H_*/