diff --git a/Modules/QtWidgets/files.cmake b/Modules/QtWidgets/files.cmake index 7c9b965120..c895814bf1 100644 --- a/Modules/QtWidgets/files.cmake +++ b/Modules/QtWidgets/files.cmake @@ -1,155 +1,172 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES QmitkAbstractDataStorageModel.cpp QmitkAbstractMultiWidget.cpp QmitkAbstractNodeSelectionWidget.cpp QmitkApplicationCursor.cpp QmitkDataStorageComboBox.cpp QmitkDataStorageDefaultListModel.cpp QmitkDataStorageHistoryModel.cpp QmitkDataStorageListModel.cpp QmitkDataStorageTableModel.cpp QmitkDataStorageSimpleTreeModel.cpp QmitkDataStorageTreeModel.cpp QmitkDataStorageTreeModelInternalItem.cpp QmitkDnDDataNodeWidget.cpp QmitkFileReaderOptionsDialog.cpp QmitkFileReaderWriterOptionsWidget.cpp QmitkFileWriterOptionsDialog.cpp QmitkInteractionSchemeToolBar.cpp QmitkIOUtil.cpp QmitkLevelWindowPresetDefinitionDialog.cpp QmitkLevelWindowRangeChangeDialog.cpp QmitkLevelWindowWidgetContextMenu.cpp QmitkLevelWindowWidget.cpp QmitkLineEditLevelWindowWidget.cpp QmitkMemoryUsageIndicatorView.cpp QmitkMimeTypes.cpp + QmitkMultiNodeSelectionWidget.cpp QmitkMultiWidgetConfigurationToolBar.cpp QmitkMultiWidgetLayoutManager.cpp QmitkMultiWidgetLayoutSelectionWidget.cpp QmitkNodeDescriptor.cpp + QmitkNodeSelectionButton.cpp + QmitkNodeSelectionConstants.cpp + QmitkNodeSelectionDialog.cpp + QmitkNodeSelectionListItemWidget.cpp + QmitkNodeSelectionPreferenceHelper.cpp + QmitkNodeDescriptor.cpp QmitkColoredNodeDescriptor.cpp QmitkNodeDescriptorManager.cpp QmitkProgressBar.cpp QmitkPropertiesTableEditor.cpp QmitkPropertiesTableModel.cpp QmitkPropertyDelegate.cpp QmitkRegisterClasses.cpp QmitkRenderingManager.cpp QmitkRenderWindowDataStorageTreeModel.cpp QmitkRenderingManagerFactory.cpp QmitkRenderWindow.cpp QmitkRenderWindowMenu.cpp QmitkRenderWindowUtilityWidget.cpp QmitkRenderWindowWidget.cpp QmitkRenderWindowContextDataStorageInspector.cpp mitkRenderWindowLayerController.cpp mitkRenderWindowLayerUtilities.cpp mitkRenderWindowViewDirectionController.cpp QmitkServiceListWidget.cpp + QmitkSingleNodeSelectionWidget.cpp QmitkSliceNavigationWidget.cpp QmitkSliderLevelWindowWidget.cpp QmitkStdMultiWidget.cpp QmitkStepperAdapter.cpp QmitkMxNMultiWidget.cpp QmitkDataStorageComboBoxWithSelectNone.cpp QmitkDataStorageFilterProxyModel.cpp QmitkPropertyItem.cpp QmitkPropertyItemDelegate.cpp QmitkPropertyItemModel.cpp QmitkStyleManager.cpp QmitkAbstractDataStorageInspector.cpp QmitkDataStorageFavoriteNodesInspector.cpp QmitkDataStorageListInspector.cpp QmitkDataStorageTreeInspector.cpp QmitkDataStorageSelectionHistoryInspector.cpp QmitkModelViewSelectionConnector.cpp mitkIDataStorageInspectorProvider.cpp mitkQtWidgetsActivator.cpp mitkDataStorageInspectorGenerator.cpp QmitkOverlayWidget.cpp QmitkSimpleTextOverlayWidget.cpp QmitkNodeDetailsDialog.cpp ) set(MOC_H_FILES include/QmitkAbstractDataStorageModel.h include/QmitkAbstractMultiWidget.h include/QmitkAbstractNodeSelectionWidget.h include/QmitkDataStorageComboBox.h include/QmitkDataStorageTableModel.h include/QmitkDataStorageTreeModel.h include/QmitkDataStorageSimpleTreeModel.h include/QmitkDataStorageDefaultListModel.h include/QmitkDnDDataNodeWidget.h include/QmitkFileReaderOptionsDialog.h include/QmitkFileReaderWriterOptionsWidget.h include/QmitkFileWriterOptionsDialog.h include/QmitkInteractionSchemeToolBar.h include/QmitkLevelWindowPresetDefinitionDialog.h include/QmitkLevelWindowRangeChangeDialog.h include/QmitkLevelWindowWidgetContextMenu.h include/QmitkLevelWindowWidget.h include/QmitkLineEditLevelWindowWidget.h include/QmitkMemoryUsageIndicatorView.h + include/QmitkMultiNodeSelectionWidget.h include/QmitkMultiWidgetConfigurationToolBar.h include/QmitkMultiWidgetLayoutManager.h include/QmitkMultiWidgetLayoutSelectionWidget.h include/QmitkNodeDescriptor.h + include/QmitkNodeSelectionButton.h + include/QmitkNodeSelectionDialog.h + include/QmitkNodeSelectionListItemWidget.h include/QmitkColoredNodeDescriptor.h include/QmitkNodeDescriptorManager.h include/QmitkProgressBar.h include/QmitkPropertiesTableEditor.h include/QmitkPropertyDelegate.h include/QmitkRenderingManager.h include/QmitkRenderWindow.h include/QmitkRenderWindowDataStorageTreeModel.h include/QmitkRenderWindowMenu.h include/QmitkRenderWindowUtilityWidget.h include/QmitkRenderWindowWidget.h include/QmitkRenderWindowContextDataStorageInspector.h include/mitkRenderWindowLayerController.h include/mitkRenderWindowLayerUtilities.h include/mitkRenderWindowViewDirectionController.h include/QmitkServiceListWidget.h + include/QmitkSingleNodeSelectionWidget.h include/QmitkSliceNavigationWidget.h include/QmitkSliderLevelWindowWidget.h include/QmitkStdMultiWidget.h include/QmitkMxNMultiWidget.h include/QmitkStepperAdapter.h include/QmitkDataStorageComboBoxWithSelectNone.h include/QmitkPropertyItemDelegate.h include/QmitkPropertyItemModel.h include/QmitkAbstractDataStorageInspector.h include/QmitkDataStorageFavoriteNodesInspector.h include/QmitkDataStorageListInspector.h include/QmitkDataStorageTreeInspector.h include/QmitkDataStorageHistoryModel.h include/QmitkDataStorageSelectionHistoryInspector.h include/QmitkModelViewSelectionConnector.h include/QmitkOverlayWidget.h include/QmitkSimpleTextOverlayWidget.h include/QmitkNodeDetailsDialog.h ) set(UI_FILES src/QmitkFileReaderOptionsDialog.ui src/QmitkFileWriterOptionsDialog.ui src/QmitkLevelWindowPresetDefinition.ui src/QmitkLevelWindowWidget.ui src/QmitkLevelWindowRangeChange.ui src/QmitkMemoryUsageIndicator.ui + src/QmitkMultiNodeSelectionWidget.ui src/QmitkMultiWidgetLayoutSelectionWidget.ui + src/QmitkNodeSelectionDialog.ui + src/QmitkNodeSelectionListItemWidget.ui src/QmitkRenderWindowContextDataStorageInspector.ui src/QmitkServiceListWidgetControls.ui + src/QmitkSingleNodeSelectionWidget.ui src/QmitkSliceNavigationWidget.ui src/QmitkDataStorageListInspector.ui src/QmitkDataStorageTreeInspector.ui src/QmitkDataStorageSelectionHistoryInspector.ui ) set(QRC_FILES resource/Qmitk.qrc ) diff --git a/Modules/QtWidgets/include/QmitkMultiNodeSelectionWidget.h b/Modules/QtWidgets/include/QmitkMultiNodeSelectionWidget.h new file mode 100644 index 0000000000..a82e42d432 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkMultiNodeSelectionWidget.h @@ -0,0 +1,79 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef QMITK_MULTI_NODE_SELECTION_WIDGET_H +#define QMITK_MULTI_NODE_SELECTION_WIDGET_H + +#include + +#include "ui_QmitkMultiNodeSelectionWidget.h" + +#include +#include +#include + +#include +#include + +class QmitkAbstractDataStorageModel; + +/** +* @class QmitkMultiNodeSelectionWidget +* @brief Widget that allows to perform and represents a multiple node selection. +*/ +class MITKQTWIDGETS_EXPORT QmitkMultiNodeSelectionWidget : public QmitkAbstractNodeSelectionWidget +{ + Q_OBJECT + +public: + explicit QmitkMultiNodeSelectionWidget(QWidget* parent = nullptr); + + using NodeList = QmitkAbstractNodeSelectionWidget::NodeList; + + /** + * @brief Helper function that is used to check the given selection for consistency. + * Returning an empty string assumes that everything is alright and the selection + * is valid. If the string is not empty, the content of the string will be used + * as error message in the overlay to indicate the problem. + */ + using SelectionCheckFunctionType = std::function; + /** + * @brief A selection check function can be set. If set the widget uses this function to + * check the made/set selection. If the selection is valid, everything is fine. + * If selection is indicated as invalid, it will not be communicated by the widget + * (no signal emission). + */ + void SetSelectionCheckFunction(const SelectionCheckFunctionType &checkFunction); + +public Q_SLOTS: + void OnEditSelection(); + +protected Q_SLOTS: + void OnClearSelection(const mitk::DataNode* node); + +protected: + void changeEvent(QEvent *event) override; + + void UpdateInfo() override; + void OnInternalSelectionChanged() override; + + bool AllowEmissionOfSelection(const NodeList& emissionCandidates) const override; + + QmitkSimpleTextOverlayWidget* m_Overlay; + + SelectionCheckFunctionType m_CheckFunction; + mutable std::string m_CheckResponse; + + Ui_QmitkMultiNodeSelectionWidget m_Controls; +}; + +#endif // QMITK_MULTI_NODE_SELECTION_WIDGET_H diff --git a/Modules/QtWidgets/include/QmitkNodeSelectionButton.h b/Modules/QtWidgets/include/QmitkNodeSelectionButton.h new file mode 100644 index 0000000000..9da598c092 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkNodeSelectionButton.h @@ -0,0 +1,71 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef QMITK_NODE_SELECTION_BUTTON_H +#define QMITK_NODE_SELECTION_BUTTON_H + +#include + +#include + +#include +#include + +/** +* @class QmitkNodeSelectionButton +* @brief Button class that can be used to display information about a given node. +* If the given node is a nullptr the node info text will be shown. +* The node info can be formated text (e.g. HTML code; like the tooltip text). +*/ +class MITKQTWIDGETS_EXPORT QmitkNodeSelectionButton : public QPushButton +{ + Q_OBJECT + +public: + explicit QmitkNodeSelectionButton(QWidget *parent = nullptr); + ~QmitkNodeSelectionButton() override; + + const mitk::DataNode* GetSelectedNode() const; + bool GetSelectionIsOptional() const; + +public Q_SLOTS: + virtual void SetSelectedNode(const mitk::DataNode* node); + virtual void SetNodeInfo(QString info); + + /** Set the widget into an optional mode. Optional means that the selection of no valid + node does not mean an invalid state. Thus no node is a valid "node" selection too. + The state influences if the info text is handled as an information (optional) or a + warning (optiona==false).*/ + void SetSelectionIsOptional(bool isOptional); + +protected: + void paintEvent(QPaintEvent *p) override; + void changeEvent(QEvent *event) override; + + void AddNodeObserver(); + void RemoveNodeObserver(); + void OnNodeModified(const itk::Object * /*caller*/, const itk::EventObject &); + + mitk::DataNode::ConstPointer m_SelectedNode; + QString m_Info; + bool m_OutDatedThumbNail; + QPixmap m_ThumbNail; + itk::ModifiedTimeType m_DataMTime; + itk::ModifiedTimeType m_SelectionPropMTime; + + bool m_IsOptional; + + unsigned long m_NodeModifiedObserverTag; + bool m_NodeObserved; +}; + +#endif // QMITK_NODE_SELECTION_BUTTON_H diff --git a/Modules/QtWidgets/include/QmitkNodeSelectionConstants.h b/Modules/QtWidgets/include/QmitkNodeSelectionConstants.h new file mode 100644 index 0000000000..99c2d08388 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkNodeSelectionConstants.h @@ -0,0 +1,40 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef QMITK_NODE_SELECTION_CONSTANTS_H_ +#define QMITK_NODE_SELECTION_CONSTANTS_H_ + +#include + +#include + +namespace mitk +{ + struct MITKQTWIDGETS_EXPORT NodeSelectionConstants + { + /** ID/Path of main preference node for node selections.*/ + static const std::string ROOT_PREFERENCE_NODE_ID; + /** ID of main preference node where all visible inspectors are stored (e.g. ROOT_PREFERENCE_NODE_ID+"/"+VISIBLE_INSPECTORS_NODE_ID+"/[orderering #]"). + The sub node naming encodes the ordering number of the visible inspector.*/ + static const std::string VISIBLE_INSPECTORS_NODE_ID; + /** ID for the value that stores the preferred inspector ID in the root preference node.*/ + static const std::string PREFERRED_INSPECTOR_ID; + /** ID for the value that stores the inspector ID in the preference node.*/ + static const std::string VISIBLE_INSPECTOR_ID; + /** ID for the value that stores if the favorite inspector should be visible.*/ + static const std::string SHOW_FAVORITE_INSPECTOR; + /** ID for the value that stores if the history inspector should be visible.*/ + static const std::string SHOW_HISTORY_INSPECTOR; + }; +} + +#endif diff --git a/Modules/QtWidgets/include/QmitkNodeSelectionDialog.h b/Modules/QtWidgets/include/QmitkNodeSelectionDialog.h new file mode 100644 index 0000000000..21155b9e49 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkNodeSelectionDialog.h @@ -0,0 +1,146 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef QMITK_NODE_SELECTION_DIALOG_H +#define QMITK_NODE_SELECTION_DIALOG_H + +#include + +#include "ui_QmitkNodeSelectionDialog.h" + +#include +#include +#include +#include "mitkIDataStorageInspectorProvider.h" + +#include + +#include +#include + +/** +* @class QmitkNodeSelectionDialog +* @brief A customized QDialog that displays different data storage inspectors and allows to +* set and get a current selection by selecting data nodes in the data storage inspectors. +*/ +class MITKQTWIDGETS_EXPORT QmitkNodeSelectionDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QmitkNodeSelectionDialog(QWidget* parent = nullptr, QString caption = "", QString hint = ""); + + /** + * @brief Set the data storage that will be used. + * The function iterates over the dialog's panels and sets the data storage of each panel accordingly. + * Each panel is a specific data storage inspector. + * + * @param dataStorage A pointer to the data storage to set. + */ + void SetDataStorage(mitk::DataStorage* dataStorage); + + /** + * @brief Set the node predicate that will be used. + * The function iterates over the dialog's panels and sets the node predicate of each panel accordingly. + * Each panel is a specific data storage inspector. + * + * @param nodePredicate A pointer to node predicate. + */ + virtual void SetNodePredicate(const mitk::NodePredicateBase* nodePredicate); + + const mitk::NodePredicateBase* GetNodePredicate() const; + + using NodeList = QList; + NodeList GetSelectedNodes() const; + + /** + * @brief Helper function that is used to check the given selection for consistency. + * Returning an empty string assumes that everything is alright and the selection is valid. + * If the string is not empty, the content of the string will be used as error message. + */ + using SelectionCheckFunctionType = std::function; + /** + * @brief A selection check function can be set. If set the dialog uses this function to check the made/set selection. + * If the selection is valid, everything is fine. + * If the selection is indicated as invalid, the dialog will display the selection check function error message. + */ + void SetSelectionCheckFunction(const SelectionCheckFunctionType &checkFunction); + + bool GetSelectOnlyVisibleNodes() const; + + using SelectionMode = QAbstractItemView::SelectionMode; + /** + * @brief Set the Qt selection mode (e.g. Single selection, multi selection). + * The function iterates over the dialog's panels and sets the Qt selection mode of each panel accordingly. + * Each panel is a concrete data storage inspector. + * + * @param mode The QAbstractItemView::SelectionMode to define the selection mode. + */ + void SetSelectionMode(SelectionMode mode); + SelectionMode GetSelectionMode() const; + +Q_SIGNALS: + /** + * @brief A signal that will be emitted if the selected node has changed. + * + * @param nodes A list of data nodes that are newly selected. + */ + void CurrentSelectionChanged(NodeList nodes); + + public Q_SLOTS: + /** + * @brief Set the selection modus to (not) include invisible nodes in the selection. + * The function iterates over the dialog's panels and sets the selection modus of each panel accordingly. + * Each panel is a concrete data storage inspector. + * + * @param selectOnlyVisibleNodes The bool value to define the selection modus. + */ + void SetSelectOnlyVisibleNodes(bool selectOnlyVisibleNodes); + /** + * @brief Set the currently selected nodes given a list of data nodes. + * The function iterates over the dialog's panels and sets the current selection of each panel accordingly. + * Each panel is a concrete data storage inspector. + * + * @param selectedNodes A list of data nodes that should be newly selected. + */ + void SetCurrentSelection(NodeList selectedNodes); + +protected Q_SLOTS: + + void OnSelectionChanged(NodeList selectedNodes); + void OnFavoriteNodesButtonClicked(); + void OnOK(); + void OnCancel(); + void OnDoubleClicked(const QModelIndex& index); + +protected: + void SetErrorText(const std::string& checkResponse); + + void AddPanel(const mitk::IDataStorageInspectorProvider* provider, const mitk::IDataStorageInspectorProvider::InspectorIDType &preferredID, bool &preferredFound, int &preferredIndex); + + mitk::WeakPointer m_DataStorage; + mitk::NodePredicateBase::ConstPointer m_NodePredicate; + bool m_SelectOnlyVisibleNodes; + NodeList m_SelectedNodes; + + SelectionCheckFunctionType m_CheckFunction; + + SelectionMode m_SelectionMode; + + using PanelVectorType = std::vector; + PanelVectorType m_Panels; + + QPushButton* m_FavoriteNodesButton; + Ui_QmitkNodeSelectionDialog m_Controls; +}; + +#endif // QMITK_NODE_SELECTION_DIALOG_H diff --git a/Modules/QtWidgets/include/QmitkNodeSelectionListItemWidget.h b/Modules/QtWidgets/include/QmitkNodeSelectionListItemWidget.h new file mode 100644 index 0000000000..cab0a0c91e --- /dev/null +++ b/Modules/QtWidgets/include/QmitkNodeSelectionListItemWidget.h @@ -0,0 +1,52 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + + +#ifndef QMITK_NODE_SELECTION_LIST_ITEM_WIDGET_H +#define QMITK_NODE_SELECTION_LIST_ITEM_WIDGET_H + +#include + +#include "ui_QmitkNodeSelectionListItemWidget.h" + +#include + +#include + +class MITKQTWIDGETS_EXPORT QmitkNodeSelectionListItemWidget : public QWidget +{ + Q_OBJECT + +public: + explicit QmitkNodeSelectionListItemWidget(QWidget* parent = nullptr); + ~QmitkNodeSelectionListItemWidget() override; + + const mitk::DataNode* GetSelectedNode() const; + +public Q_SLOTS : + virtual void SetSelectedNode(const mitk::DataNode* node); + virtual void SetClearAllowed(bool allowed); + +signals: + void ClearSelection(const mitk::DataNode* node); + +protected Q_SLOTS: + void OnClearSelection(); + +protected: + bool eventFilter(QObject *obj, QEvent *ev) override; + + Ui_QmitkNodeSelectionListItemWidget m_Controls; +}; + + +#endif // QMITK_NODE_SELECTION_LIST_ITEM_WIDGET_H diff --git a/Modules/QtWidgets/include/QmitkNodeSelectionPreferenceHelper.h b/Modules/QtWidgets/include/QmitkNodeSelectionPreferenceHelper.h new file mode 100644 index 0000000000..d2de2f7061 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkNodeSelectionPreferenceHelper.h @@ -0,0 +1,55 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef QMITK_NODE_SELECTION_PREFERENCE_HELPER_H +#define QMITK_NODE_SELECTION_PREFERENCE_HELPER_H + +#include + +#include +#include + +namespace mitk +{ + using DataStorageInspectorIDType = std::string; + + /** map containing the IDs of all inspectors that should be visible. The map key is the order of appearance + of the respective inspector.*/ + using VisibleDataStorageInspectorMapType = std::map; + + /** Stores the given ID as favorite inspector.*/ + MITKQTWIDGETS_EXPORT void PutPreferredDataStorageInspector(const DataStorageInspectorIDType& id); + + /** Gets the ID of the current favorite data storage inspector. + * If empty string is returned, no favorite is set.*/ + MITKQTWIDGETS_EXPORT DataStorageInspectorIDType GetPreferredDataStorageInspector(); + + /** Stores the given map of visible inspectors.*/ + MITKQTWIDGETS_EXPORT void PutVisibleDataStorageInspectors(const VisibleDataStorageInspectorMapType& inspectors); + + /** Gets the map of current visible inspectors.*/ + MITKQTWIDGETS_EXPORT VisibleDataStorageInspectorMapType GetVisibleDataStorageInspectors(); + + /** Stores the given show state of the favorite inspector.*/ + MITKQTWIDGETS_EXPORT void PutShowFavoritesInspector(bool show); + + /** Indicates if the favorites inspector should be shown. */ + MITKQTWIDGETS_EXPORT bool GetShowFavoritesInspector(); + + /** Stores the given show state of the history inspector.*/ + MITKQTWIDGETS_EXPORT void PutShowHistoryInspector(bool show); + + /** Indicates if the history inspector should be shown. */ + MITKQTWIDGETS_EXPORT bool GetShowHistoryInspector(); +} + +#endif diff --git a/Modules/QtWidgets/include/QmitkSingleNodeSelectionWidget.h b/Modules/QtWidgets/include/QmitkSingleNodeSelectionWidget.h new file mode 100644 index 0000000000..af818d8e8b --- /dev/null +++ b/Modules/QtWidgets/include/QmitkSingleNodeSelectionWidget.h @@ -0,0 +1,97 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef QMITK_SINGLE_NODE_SELECTION_WIDGET_H +#define QMITK_SINGLE_NODE_SELECTION_WIDGET_H + +#include + +#include "ui_QmitkSingleNodeSelectionWidget.h" + +#include +#include +#include + +#include +#include + +class QmitkAbstractDataStorageModel; + +/** +* @class QmitkSingleNodeSelectionWidget +* @brief Widget that represents a node selection of (max) one node. It acts like a button. Clicking on it +* allows to change the selection. +* +* @remark This class provides a public function 'SetAutoSelectNewNodes' that can be used to enable +* the auto selection mode (default is false). +* The user of this class calling this function has to make sure that the base-class Q_SIGNAL +* 'CurrentSelectionChanged', which will be emitted by this function, is already +* connected to a receiving slot, if the initial valid auto selection should not get lost. +*/ +class MITKQTWIDGETS_EXPORT QmitkSingleNodeSelectionWidget : public QmitkAbstractNodeSelectionWidget +{ + Q_OBJECT + +public: + explicit QmitkSingleNodeSelectionWidget(QWidget* parent = nullptr); + + mitk::DataNode::Pointer GetSelectedNode() const; + bool GetAutoSelectNewNodes() const; + + using NodeList = QmitkAbstractNodeSelectionWidget::NodeList; + +public Q_SLOTS: + void SetCurrentSelectedNode(mitk::DataNode* selectedNode); + + /** + * Sets the auto selection mode (default is false). + * If auto select is true and the following conditions are fullfilled, the widget will + * select a node automatically from the data storage: + * - a data storage is set + * - data storage contains at least one node that matches the given predicate + * - no selection is set + * + * @remark Enabling the auto selection mode by calling 'SetAutoSelectNewNodes(true)' + * will directly emit a 'QmitkSingleNodeSelectionWidget::CurrentSelectionChanged' Q_SIGNAL + * if a valid auto selection was made. + * If this initial emission should not get lost, auto selection mode needs to be enabled after this + * selection widget has been connected via the 'QmitkSingleNodeSelectionWidget::CurrentSelectionChanged' + * Q_SIGNAL to a receiving function. + */ + void SetAutoSelectNewNodes(bool autoSelect); + +protected Q_SLOTS: + virtual void OnClearSelection(); + +protected: + void ReviseSelectionChanged(const NodeList& oldInternalSelection, NodeList& newInternalSelection) override; + + bool eventFilter(QObject *obj, QEvent *ev) override; + void EditSelection(); + void UpdateInfo() override; + + void OnDataStorageChanged() override; + void OnNodeAddedToStorage(const mitk::DataNode* node) override; + + void AutoSelectNodes(); + + /** Helper function that gets a suitable auto selected node from the datastorage that fits to the predicate settings. + @param ignoreNodes You may pass a list of nodes that must not be choosen as auto selected node. */ + mitk::DataNode::Pointer DetermineAutoSelectNode(const NodeList& ignoreNodes = {}); + + /** See documentation of SetAutoSelectNewNodes for details*/ + bool m_AutoSelectNodes; + + Ui_QmitkSingleNodeSelectionWidget m_Controls; +}; + +#endif // QMITK_SINGLE_NODE_SELECTION_WIDGET_H diff --git a/Modules/QtWidgets/resource/Qmitk.qrc b/Modules/QtWidgets/resource/Qmitk.qrc index 788d6fc8cf..cdfc70682c 100644 --- a/Modules/QtWidgets/resource/Qmitk.qrc +++ b/Modules/QtWidgets/resource/Qmitk.qrc @@ -1,27 +1,28 @@ Binaerbilder_48.png Images_48.png PointSet_48.png Segmentation_48.png Surface_48.png mm_pointer.png mm_scroll.png mm_zoom.png mm_contrast.png mm_pan.png LabelSetImage_48.png mwLayout.png mwSynchronized.png mwDesynchronized.png mwMITK.png mwPACS.png star-solid.svg history-solid.svg tree_inspector.svg list-solid.svg favorite_add.svg favorite_remove.svg hourglass-half-solid.svg + times.svg diff --git a/Modules/QtWidgets/resource/icon-license.txt b/Modules/QtWidgets/resource/icon-license.txt index df5504436b..3878229bfa 100644 --- a/Modules/QtWidgets/resource/icon-license.txt +++ b/Modules/QtWidgets/resource/icon-license.txt @@ -1,7 +1,8 @@ See [Font Awsome 4] in Licenses/ICONS.md for: - history-solid.svg based on Font Awsome's history-solid.svg - list-solid.svg based on Font Awsome's list-solid.svg - star-solid.svg based on Font Awsome's star-solid.svg - favorite_add.svg based on Font Awsome's star-solid.svg - favorite_remove.svg based on Font Awsome's star-solid.svg - hourglass-half-solid.svg based on Font Awsome's hourglass-half-solid.svg +- times.svg diff --git a/Modules/QtWidgets/resource/times.svg b/Modules/QtWidgets/resource/times.svg new file mode 100644 index 0000000000..fdb8c5c03b --- /dev/null +++ b/Modules/QtWidgets/resource/times.svg @@ -0,0 +1,52 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.cpp b/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.cpp new file mode 100644 index 0000000000..88bb1d389f --- /dev/null +++ b/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.cpp @@ -0,0 +1,159 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "QmitkMultiNodeSelectionWidget.h" + +#include + +#include +#include +#include + +QmitkMultiNodeSelectionWidget::QmitkMultiNodeSelectionWidget(QWidget* parent) + : QmitkAbstractNodeSelectionWidget(parent) +{ + m_Controls.setupUi(this); + m_Overlay = new QmitkSimpleTextOverlayWidget(m_Controls.list); + m_Overlay->setVisible(false); + m_CheckFunction = [](const NodeList &) { return ""; }; + + this->OnInternalSelectionChanged(); + this->UpdateInfo(); + + connect(m_Controls.btnChange, SIGNAL(clicked(bool)), this, SLOT(OnEditSelection())); +} + +void QmitkMultiNodeSelectionWidget::SetSelectionCheckFunction(const SelectionCheckFunctionType &checkFunction) +{ + m_CheckFunction = checkFunction; + + auto newEmission = this->CompileEmitSelection(); + auto newCheckResponse = m_CheckFunction(newEmission); + + if (newCheckResponse.empty() && !m_CheckResponse.empty()) + { + this->EmitSelection(newEmission); + } + m_CheckResponse = newCheckResponse; + this->UpdateInfo(); +} + +void QmitkMultiNodeSelectionWidget::OnEditSelection() +{ + QmitkNodeSelectionDialog* dialog = new QmitkNodeSelectionDialog(this, m_PopUpTitel, m_PopUpHint); + + dialog->SetDataStorage(m_DataStorage.Lock()); + dialog->SetNodePredicate(m_NodePredicate); + dialog->SetCurrentSelection(this->CompileEmitSelection()); + dialog->SetSelectOnlyVisibleNodes(m_SelectOnlyVisibleNodes); + dialog->SetSelectionMode(QAbstractItemView::MultiSelection); + dialog->SetSelectionCheckFunction(m_CheckFunction); + + m_Controls.btnChange->setChecked(true); + if (dialog->exec()) + { + this->HandleChangeOfInternalSelection(dialog->GetSelectedNodes()); + } + m_Controls.btnChange->setChecked(false); + + delete dialog; +} + +void QmitkMultiNodeSelectionWidget::UpdateInfo() +{ + if (!m_Controls.list->count()) + { + if (m_IsOptional) + { + if (this->isEnabled()) + { + m_Overlay->SetOverlayText(QStringLiteral("") + m_EmptyInfo + QStringLiteral("")); + } + else + { + m_Overlay->SetOverlayText(QStringLiteral("") + m_EmptyInfo + QStringLiteral("")); + } + } + else + { + if (this->isEnabled()) + { + m_Overlay->SetOverlayText(QStringLiteral("") + m_InvalidInfo + QStringLiteral("")); + } + else + { + m_Overlay->SetOverlayText(QStringLiteral("") + m_InvalidInfo + QStringLiteral("")); + } + } + } + else + { + if (!m_CheckResponse.empty()) + { + m_Overlay->SetOverlayText(QString::fromStdString(m_CheckResponse)); + } + } + + m_Overlay->setVisible(m_Controls.list->count() == 0 || !m_CheckResponse.empty()); + + for (auto i = 0; i < m_Controls.list->count(); ++i) + { + auto item = m_Controls.list->item(i); + auto widget = qobject_cast(m_Controls.list->itemWidget(item)); + widget->SetClearAllowed(m_IsOptional || m_Controls.list->count() > 1); + } +} + +void QmitkMultiNodeSelectionWidget::OnInternalSelectionChanged() +{ + m_Controls.list->clear(); + auto currentSelection = this->GetCurrentInternalSelection(); + for (auto& node : currentSelection) + { + if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)) + { + QListWidgetItem *newItem = new QListWidgetItem; + + newItem->setSizeHint(QSize(0, 40)); + QmitkNodeSelectionListItemWidget* widget = new QmitkNodeSelectionListItemWidget; + + widget->SetSelectedNode(node); + widget->SetClearAllowed(m_IsOptional || currentSelection.size() > 1); + + connect(widget, &QmitkNodeSelectionListItemWidget::ClearSelection, this, &QmitkMultiNodeSelectionWidget::OnClearSelection); + newItem->setData(Qt::UserRole, QVariant::fromValue(node)); + + m_Controls.list->addItem(newItem); + m_Controls.list->setItemWidget(newItem, widget); + } + } +} + +void QmitkMultiNodeSelectionWidget::OnClearSelection(const mitk::DataNode* node) +{ + this->RemoveNodeFromSelection(node); +} + +void QmitkMultiNodeSelectionWidget::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::EnabledChange) + { + this->UpdateInfo(); + } + QmitkAbstractNodeSelectionWidget::changeEvent(event); +} + +bool QmitkMultiNodeSelectionWidget::AllowEmissionOfSelection(const NodeList& emissionCandidates) const +{ + m_CheckResponse = m_CheckFunction(emissionCandidates); + return m_CheckResponse.empty(); +} diff --git a/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.ui b/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.ui new file mode 100644 index 0000000000..172db00d55 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.ui @@ -0,0 +1,85 @@ + + + QmitkMultiNodeSelectionWidget + + + + 0 + 0 + 391 + 265 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::NoDragDrop + + + Qt::MoveAction + + + QAbstractItemView::NoSelection + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + + + + Change selection + + + true + + + + + + + + diff --git a/Modules/QtWidgets/src/QmitkNodeSelectionButton.cpp b/Modules/QtWidgets/src/QmitkNodeSelectionButton.cpp new file mode 100644 index 0000000000..956971f9c5 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkNodeSelectionButton.cpp @@ -0,0 +1,270 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "QmitkNodeSelectionButton.h" + +// mitk core +#include +#include +#include +#include +#include + +// mitk qt widgets module +#include + +#include + +#include +#include +#include +#include + +QPixmap GetPixmapFromImageNode(const mitk::DataNode* dataNode, int height) +{ + if (nullptr == dataNode) + { + return QPixmap(); + } + + const mitk::Image* image = dynamic_cast(dataNode->GetData()); + if ((nullptr == image || !image->IsInitialized()) || // -> must be an image + (image->GetPixelType().GetNumberOfComponents() != 1)) // -> for now only single component are allowed + { + auto descManager = QmitkNodeDescriptorManager::GetInstance(); + auto desc = descManager->GetDescriptor(dataNode); + auto icon = desc->GetIcon(dataNode); + auto fallBackMap = icon.pixmap(height, height); + return fallBackMap; + } + + mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New(); + int sliceNumber = image->GetDimension(2) / 2; + planeGeometry->InitializeStandardPlane(image->GetGeometry(), mitk::AnatomicalPlane::Axial, sliceNumber); + + mitk::ExtractSliceFilter::Pointer extractSliceFilter = mitk::ExtractSliceFilter::New(); + extractSliceFilter->SetInput(image); + extractSliceFilter->SetInterpolationMode(mitk::ExtractSliceFilter::RESLICE_CUBIC); + extractSliceFilter->SetResliceTransformByGeometry(image->GetGeometry()); + extractSliceFilter->SetWorldGeometry(planeGeometry); + extractSliceFilter->SetOutputDimensionality(2); + extractSliceFilter->SetVtkOutputRequest(true); + extractSliceFilter->Update(); + + vtkImageData* imageData = extractSliceFilter->GetVtkOutput(); + + mitk::LevelWindow levelWindow; + dataNode->GetLevelWindow(levelWindow); + vtkSmartPointer lookupTable = vtkSmartPointer::New(); + lookupTable->SetRange(levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound()); + lookupTable->SetSaturationRange(0.0, 0.0); + lookupTable->SetValueRange(0.0, 1.0); + lookupTable->SetHueRange(0.0, 0.0); + lookupTable->SetRampToLinear(); + + vtkSmartPointer levelWindowFilter = vtkSmartPointer::New(); + levelWindowFilter->SetLookupTable(lookupTable); + levelWindowFilter->SetInputData(imageData); + levelWindowFilter->SetMinOpacity(0.0); + levelWindowFilter->SetMaxOpacity(1.0); + int dims[3]; + imageData->GetDimensions(dims); + double clippingBounds[] = { 0.0, static_cast(dims[0]), 0.0, static_cast(dims[1]) }; + levelWindowFilter->SetClippingBounds(clippingBounds); + levelWindowFilter->Update(); + imageData = levelWindowFilter->GetOutput(); + + QImage thumbnailImage(reinterpret_cast(imageData->GetScalarPointer()), dims[0], dims[1], QImage::Format_ARGB32); + + if (dims[0] > dims[1]) + { + thumbnailImage = thumbnailImage.scaledToWidth(height, Qt::SmoothTransformation).rgbSwapped(); + } + else + { + thumbnailImage = thumbnailImage.scaledToHeight(height, Qt::SmoothTransformation).rgbSwapped(); + } + + return QPixmap::fromImage(thumbnailImage); +} + +QmitkNodeSelectionButton::QmitkNodeSelectionButton(QWidget *parent) + : QPushButton(parent) + , m_OutDatedThumbNail(true) + , m_DataMTime(0) + , m_IsOptional(true) + , m_NodeModifiedObserverTag(0) + , m_NodeObserved(false) +{ +} + +QmitkNodeSelectionButton::~QmitkNodeSelectionButton() +{ + this->RemoveNodeObserver(); + this->m_SelectedNode = nullptr; +} + +void QmitkNodeSelectionButton::AddNodeObserver() +{ + if (this->m_SelectedNode.IsNotNull()) + { + if (m_NodeObserved) + { + MITK_DEBUG << "Invalid observer state in QmitkNodeSelectionButton. There is already a registered observer. Internal logic is not correct. May be an old observer was not removed."; + } + + auto modifiedCommand = itk::MemberCommand::New(); + modifiedCommand->SetCallbackFunction(this, &QmitkNodeSelectionButton::OnNodeModified); + + // const cast because we need non const nodes and it seems to be the lesser of two evil. + // the changes to the node are only on the observer level. The other option would be to + // make the public interface require non const nodes, this we don't want to introduce. + auto nonconst_node = const_cast(this->m_SelectedNode.GetPointer()); + m_NodeModifiedObserverTag = nonconst_node->AddObserver(itk::ModifiedEvent(), modifiedCommand); + m_NodeObserved = true; + } +} + +void QmitkNodeSelectionButton::RemoveNodeObserver() +{ + if (this->m_SelectedNode.IsNotNull()) + { + // const cast because we need non const nodes and it seems to be the lesser of two evil. + // the changes to the node are only on the observer level. The other option would be to + // make the public interface require non const nodes, this we don't want to introduce. + auto nonconst_node = const_cast(this->m_SelectedNode.GetPointer()); + nonconst_node->RemoveObserver(m_NodeModifiedObserverTag); + } + m_NodeObserved = false; +} + +void QmitkNodeSelectionButton::OnNodeModified(const itk::Object * /*caller*/, const itk::EventObject & event) +{ + if (itk::ModifiedEvent().CheckEvent(&event)) + { + this->update(); + } +} + +const mitk::DataNode* QmitkNodeSelectionButton::GetSelectedNode() const +{ + return m_SelectedNode; +} + +void QmitkNodeSelectionButton::SetSelectedNode(const mitk::DataNode* node) +{ + if (m_SelectedNode != node) + { + this->RemoveNodeObserver(); + this->m_SelectedNode = node; + this->m_OutDatedThumbNail = true; + this->AddNodeObserver(); + } + + this->update(); +} + +void QmitkNodeSelectionButton::SetNodeInfo(QString info) +{ + this->m_Info = info; + this->update(); +} + +void QmitkNodeSelectionButton::paintEvent(QPaintEvent *p) +{ + QPushButton::paintEvent(p); + + auto styleSheet = qApp->styleSheet(); + + QPainter painter(this); + QTextDocument td(this); + td.setDefaultStyleSheet(styleSheet); + + auto widgetSize = this->size(); + QPoint origin = QPoint(5, 5); + + if (this->m_SelectedNode) + { + auto iconLength = widgetSize.height() - 10; + auto node = this->m_SelectedNode; + + itk::ModifiedTimeType dataMTime = 0; + if (m_SelectedNode->GetData()) + { + dataMTime = m_SelectedNode->GetData()->GetMTime(); + } + if (dataMTime>m_DataMTime || this->m_OutDatedThumbNail) + { + this->m_ThumbNail = GetPixmapFromImageNode(node, iconLength); + this->m_OutDatedThumbNail = false; + m_DataMTime = dataMTime; + } + + auto thumbNailOrigin = origin; + thumbNailOrigin.setY(thumbNailOrigin.y() + ((iconLength - m_ThumbNail.height()) / 2)); + painter.drawPixmap(thumbNailOrigin, m_ThumbNail); + origin.setX(origin.x() + iconLength + 5); + + if (this->isEnabled()) + { + td.setHtml(QString::fromStdString("" + node->GetName() + "")); + } + else + { + td.setHtml(QString::fromStdString("" + node->GetName() + "")); + } + } + else + { + if (this->isEnabled()) + { + if (this->m_IsOptional) + { + td.setHtml(QString("") + m_Info + QString("")); + } + else + { + td.setHtml(QString("") + m_Info + QString("")); + } + } + else + { + td.setHtml(QString("") + m_Info + QString("")); + } + } + + auto textSize = td.size(); + + origin.setY( (widgetSize.height() - textSize.height()) / 2.); + + painter.translate(origin); + td.drawContents(&painter); +} + +void QmitkNodeSelectionButton::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::EnabledChange) + { + this->update(); + } +} + +bool QmitkNodeSelectionButton::GetSelectionIsOptional() const +{ + return m_IsOptional; +} + +void QmitkNodeSelectionButton::SetSelectionIsOptional(bool isOptional) +{ + m_IsOptional = isOptional; + this->update(); +} diff --git a/Modules/QtWidgets/src/QmitkNodeSelectionConstants.cpp b/Modules/QtWidgets/src/QmitkNodeSelectionConstants.cpp new file mode 100644 index 0000000000..4ab85ab5e1 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkNodeSelectionConstants.cpp @@ -0,0 +1,20 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "QmitkNodeSelectionConstants.h" + +const std::string mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID = "/NODESELECTION/UI"; +const std::string mitk::NodeSelectionConstants::VISIBLE_INSPECTORS_NODE_ID = "visibleInspectors"; +const std::string mitk::NodeSelectionConstants::PREFERRED_INSPECTOR_ID = "inspectorID"; +const std::string mitk::NodeSelectionConstants::VISIBLE_INSPECTOR_ID = "inspectorID"; +const std::string mitk::NodeSelectionConstants::SHOW_FAVORITE_INSPECTOR = "showFavoriteInspector"; +const std::string mitk::NodeSelectionConstants::SHOW_HISTORY_INSPECTOR = "showHistoryInspector"; diff --git a/Modules/QtWidgets/src/QmitkNodeSelectionDialog.cpp b/Modules/QtWidgets/src/QmitkNodeSelectionDialog.cpp new file mode 100644 index 0000000000..514b9d35c1 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkNodeSelectionDialog.cpp @@ -0,0 +1,296 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "QmitkNodeSelectionDialog.h" + +#include + +#include +#include +#include +#include + +#include +#include + +QmitkNodeSelectionDialog::QmitkNodeSelectionDialog(QWidget* parent, QString title, QString hint) + : QDialog(parent) + , m_NodePredicate(nullptr) + , m_SelectOnlyVisibleNodes(false) + , m_SelectedNodes(NodeList()) + , m_SelectionMode(QAbstractItemView::SingleSelection) +{ + m_Controls.setupUi(this); + + m_CheckFunction = [](const NodeList &) { return ""; }; + + auto providers = mitk::DataStorageInspectorGenerator::GetProviders(); + auto visibleProviders = mitk::GetVisibleDataStorageInspectors(); + auto preferredID = mitk::GetPreferredDataStorageInspector(); + + if (visibleProviders.empty()) + { + MITK_DEBUG << "No presets for visible node selection inspectors available. Use fallback (show all available inspectors)"; + unsigned int order = 0; + for (const auto &proIter : providers) + { + visibleProviders.insert(std::make_pair(order, proIter.first)); + ++order; + } + } + + int preferredIndex = 0; + bool preferredFound = false; + for (const auto &proIter : visibleProviders) + { + auto finding = providers.find(proIter.second); + if (finding != providers.end()) + { + if (finding->second->GetInspectorID() != QmitkDataStorageFavoriteNodesInspector::INSPECTOR_ID() && finding->second->GetInspectorID() != QmitkDataStorageSelectionHistoryInspector::INSPECTOR_ID()) + { + auto provider = finding->second; + this->AddPanel(provider, preferredID, preferredFound, preferredIndex); + } + } + else + { + MITK_DEBUG << "No provider registered for inspector that is defined as visible in the preferences. Illegal inspector ID: " << proIter.second; + } + } + + if (mitk::GetShowFavoritesInspector()) + { + auto favoritesPorvider = mitk::DataStorageInspectorGenerator::GetProvider(QmitkDataStorageFavoriteNodesInspector::INSPECTOR_ID()); + if (favoritesPorvider != nullptr) + { + this->AddPanel(favoritesPorvider, preferredID, preferredFound, preferredIndex); + } + } + + if (mitk::GetShowHistoryInspector()) + { + auto historyPorvider = mitk::DataStorageInspectorGenerator::GetProvider(QmitkDataStorageSelectionHistoryInspector::INSPECTOR_ID()); + if (historyPorvider != nullptr) + { + this->AddPanel(historyPorvider, preferredID, preferredFound, preferredIndex); + } + } + + m_Controls.tabWidget->setCurrentIndex(preferredIndex); + this->setWindowTitle(title); + this->setToolTip(hint); + + m_Controls.hint->setText(hint); + m_Controls.hint->setVisible(!hint.isEmpty()); + if(hint.isEmpty()) + { + m_Controls.layoutHint->setContentsMargins(0, 0, 0, 0); + } + else + { + m_Controls.layoutHint->setContentsMargins(6, 6, 6, 6); + } + + this->SetErrorText(""); + + m_Controls.btnAddToFav->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/favorite_add.svg"))); + + connect(m_Controls.btnAddToFav, &QPushButton::clicked, this, &QmitkNodeSelectionDialog::OnFavoriteNodesButtonClicked); + connect(m_Controls.buttonBox, &QDialogButtonBox::accepted, this, &QmitkNodeSelectionDialog::OnOK); + connect(m_Controls.buttonBox, &QDialogButtonBox::rejected, this, &QmitkNodeSelectionDialog::OnCancel); +} + +void QmitkNodeSelectionDialog::SetDataStorage(mitk::DataStorage* dataStorage) +{ + if (m_DataStorage != dataStorage) + { + m_DataStorage = dataStorage; + auto lockedDataStorage = m_DataStorage.Lock(); + + if (lockedDataStorage.IsNotNull()) + { + for (auto panel : m_Panels) + { + panel->SetDataStorage(lockedDataStorage); + } + } + } +} + +void QmitkNodeSelectionDialog::SetNodePredicate(const mitk::NodePredicateBase* nodePredicate) +{ + if (m_NodePredicate != nodePredicate) + { + m_NodePredicate = nodePredicate; + + for (auto panel : m_Panels) + { + panel->SetNodePredicate(m_NodePredicate); + } + } +} + +const mitk::NodePredicateBase* QmitkNodeSelectionDialog::GetNodePredicate() const +{ + return m_NodePredicate; +} + +QmitkNodeSelectionDialog::NodeList QmitkNodeSelectionDialog::GetSelectedNodes() const +{ + return m_SelectedNodes; +} + +void QmitkNodeSelectionDialog::SetSelectionCheckFunction(const SelectionCheckFunctionType &checkFunction) +{ + m_CheckFunction = checkFunction; + auto checkResponse = m_CheckFunction(m_SelectedNodes); + + SetErrorText(checkResponse); + + m_Controls.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(checkResponse.empty()); +} + +void QmitkNodeSelectionDialog::SetErrorText(const std::string& checkResponse) +{ + m_Controls.error->setText(QString::fromStdString(checkResponse)); + m_Controls.error->setVisible(!checkResponse.empty()); + if (checkResponse.empty()) + { + m_Controls.layoutError->setContentsMargins(0, 0, 0, 0); + } + else + { + m_Controls.layoutError->setContentsMargins(6, 6, 6, 6); + } +} + +bool QmitkNodeSelectionDialog::GetSelectOnlyVisibleNodes() const +{ + return m_SelectOnlyVisibleNodes; +} + +void QmitkNodeSelectionDialog::SetSelectionMode(SelectionMode mode) +{ + m_SelectionMode = mode; + for (auto panel : m_Panels) + { + panel->SetSelectionMode(mode); + } +} + +QmitkNodeSelectionDialog::SelectionMode QmitkNodeSelectionDialog::GetSelectionMode() const +{ + return m_SelectionMode; +} + +void QmitkNodeSelectionDialog::SetSelectOnlyVisibleNodes(bool selectOnlyVisibleNodes) +{ + if (m_SelectOnlyVisibleNodes != selectOnlyVisibleNodes) + { + m_SelectOnlyVisibleNodes = selectOnlyVisibleNodes; + + for (auto panel : m_Panels) + { + panel->SetSelectOnlyVisibleNodes(m_SelectOnlyVisibleNodes); + } + } +} + +void QmitkNodeSelectionDialog::SetCurrentSelection(NodeList selectedNodes) +{ + m_SelectedNodes = selectedNodes; + auto checkResponse = m_CheckFunction(m_SelectedNodes); + + SetErrorText(checkResponse); + + m_Controls.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(checkResponse.empty()); + + for (auto panel : m_Panels) + { + panel->SetCurrentSelection(selectedNodes); + } +} + +void QmitkNodeSelectionDialog::OnSelectionChanged(NodeList selectedNodes) +{ + SetCurrentSelection(selectedNodes); + emit CurrentSelectionChanged(selectedNodes); +} + +void QmitkNodeSelectionDialog::OnFavoriteNodesButtonClicked() +{ + for (auto node : qAsConst(m_SelectedNodes)) + { + node->SetBoolProperty("org.mitk.selection.favorite", true); + } +} + +void QmitkNodeSelectionDialog::OnOK() +{ + for (const auto &node : qAsConst(m_SelectedNodes)) + { + QmitkDataStorageSelectionHistoryInspector::AddNodeToHistory(node); + } + + this->accept(); +} + +void QmitkNodeSelectionDialog::OnCancel() +{ + this->reject(); +} + +void QmitkNodeSelectionDialog::AddPanel(const mitk::IDataStorageInspectorProvider * provider, const mitk::IDataStorageInspectorProvider::InspectorIDType& preferredID, bool &preferredFound, int &preferredIndex) +{ + auto inspector = provider->CreateInspector(); + QString name = QString::fromStdString(provider->GetInspectorDisplayName()); + QString desc = QString::fromStdString(provider->GetInspectorDescription()); + + inspector->setParent(this); + inspector->SetSelectionMode(m_SelectionMode); + + auto tabPanel = new QWidget(); + tabPanel->setObjectName(QString("tab_") + name); + tabPanel->setToolTip(desc); + + auto verticalLayout = new QVBoxLayout(tabPanel); + verticalLayout->setSpacing(0); + verticalLayout->setContentsMargins(0, 0, 0, 0); + verticalLayout->addWidget(inspector); + + auto panelPos = m_Controls.tabWidget->insertTab(m_Controls.tabWidget->count(), tabPanel, name); + + auto icon = provider->GetInspectorIcon(); + if (!icon.isNull()) + { + m_Controls.tabWidget->setTabIcon(panelPos, icon); + } + + m_Panels.push_back(inspector); + connect(inspector, &QmitkAbstractDataStorageInspector::CurrentSelectionChanged, this, &QmitkNodeSelectionDialog::OnSelectionChanged); + connect(inspector->GetView(), &QAbstractItemView::doubleClicked, this, &QmitkNodeSelectionDialog::OnDoubleClicked); + + preferredFound = preferredFound || provider->GetInspectorID() == preferredID; + if (!preferredFound) + { + ++preferredIndex; + } +} + +void QmitkNodeSelectionDialog::OnDoubleClicked(const QModelIndex& /*index*/) +{ + const auto isOK = m_Controls.buttonBox->button(QDialogButtonBox::Ok)->isEnabled(); + if (!m_SelectedNodes.empty() && isOK) + { + this->OnOK(); + } +} diff --git a/Modules/QtWidgets/src/QmitkNodeSelectionDialog.ui b/Modules/QtWidgets/src/QmitkNodeSelectionDialog.ui new file mode 100644 index 0000000000..26f94b420d --- /dev/null +++ b/Modules/QtWidgets/src/QmitkNodeSelectionDialog.ui @@ -0,0 +1,116 @@ + + + QmitkNodeSelectionDialog + + + + 0 + 0 + 800 + 600 + + + + Dialog + + + true + + + true + + + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + QFrame::NoFrame + + + Info text ... + + + Qt::RichText + + + true + + + + + + + + + -1 + + + + 24 + 24 + + + + + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + error text + + + + + + + + + + + Add the current selection to the favorites. + + + Add to favorites + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + diff --git a/Modules/QtWidgets/src/QmitkNodeSelectionListItemWidget.cpp b/Modules/QtWidgets/src/QmitkNodeSelectionListItemWidget.cpp new file mode 100644 index 0000000000..e0f73cb5cf --- /dev/null +++ b/Modules/QtWidgets/src/QmitkNodeSelectionListItemWidget.cpp @@ -0,0 +1,89 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + + +#include "QmitkNodeSelectionListItemWidget.h" + +#include +#include + +#include + +QmitkNodeSelectionListItemWidget::QmitkNodeSelectionListItemWidget(QWidget *parent) + : QWidget(parent) +{ + m_Controls.setupUi(this); + + m_Controls.btnSelect->installEventFilter(this); + m_Controls.btnSelect->setVisible(true); + m_Controls.btnSelect->SetNodeInfo("No valid selection"); + m_Controls.btnClear->setVisible(false); + + m_Controls.btnClear->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/times.svg"))); + + connect(m_Controls.btnClear, SIGNAL(clicked(bool)), this, SLOT(OnClearSelection())); +} + +QmitkNodeSelectionListItemWidget::~QmitkNodeSelectionListItemWidget() +{ +} + +const mitk::DataNode* QmitkNodeSelectionListItemWidget::GetSelectedNode() const +{ + return m_Controls.btnSelect->GetSelectedNode(); +}; + +void QmitkNodeSelectionListItemWidget::SetSelectedNode(const mitk::DataNode* node) +{ + m_Controls.btnSelect->SetSelectedNode(node); + this->update(); +}; + +void QmitkNodeSelectionListItemWidget::SetClearAllowed(bool allowed) +{ + m_Controls.btnClear->setVisible(allowed); +}; + +void QmitkNodeSelectionListItemWidget::OnClearSelection() +{ + emit ClearSelection(this->GetSelectedNode()); +}; + +bool QmitkNodeSelectionListItemWidget::eventFilter(QObject *obj, QEvent *ev) +{ + if (obj == m_Controls.btnSelect) + { + if (ev->type() == QEvent::MouseButtonRelease) + { + auto mouseEv = dynamic_cast(ev); + if (!mouseEv) + { + return false; + } + + if (mouseEv->button() == Qt::RightButton) + { + auto selection = this->GetSelectedNode(); + + if (selection != nullptr) + { + QList selectionList({ this->GetSelectedNode() }); + QmitkNodeDetailsDialog infoDialog(selectionList, this); + infoDialog.exec(); + return true; + } + } + } + } + + return false; +} diff --git a/Modules/QtWidgets/src/QmitkNodeSelectionListItemWidget.ui b/Modules/QtWidgets/src/QmitkNodeSelectionListItemWidget.ui new file mode 100644 index 0000000000..6f59ef5284 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkNodeSelectionListItemWidget.ui @@ -0,0 +1,124 @@ + + + QmitkNodeSelectionListItemWidget + + + + 0 + 0 + 348 + 25 + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 16777215 + 40 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 25 + + + + Right click to show details about selected node. + + + + + + false + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 25 + 16777215 + + + + Press to remove the current selection. + + + + + + + :/org.mitk.gui.qt.common/resources/times.svg:/org.mitk.gui.qt.common/resources/times.svg + + + + 19 + 19 + + + + + + + + + QmitkNodeSelectionButton + QPushButton +
QmitkNodeSelectionButton.h
+
+
+ + +
diff --git a/Modules/QtWidgets/src/QmitkNodeSelectionPreferenceHelper.cpp b/Modules/QtWidgets/src/QmitkNodeSelectionPreferenceHelper.cpp new file mode 100644 index 0000000000..61ddb2cae7 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkNodeSelectionPreferenceHelper.cpp @@ -0,0 +1,158 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "QmitkNodeSelectionPreferenceHelper.h" + +#include + +#include +#include +#include + +#include +#include + +#include "mitkExceptionMacro.h" +#include "mitkDataStorageInspectorGenerator.h" + +void mitk::PutVisibleDataStorageInspectors(const VisibleDataStorageInspectorMapType &inspectors) +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + auto* visNode = prefNode->Node(mitk::NodeSelectionConstants::VISIBLE_INSPECTORS_NODE_ID); + + visNode->Clear(); + + // store map in new node + for (const auto &inspector : inspectors) + { + std::ostringstream sstr; + sstr << inspector.first; + auto* aNode = visNode->Node(sstr.str()); + + aNode->Put(mitk::NodeSelectionConstants::VISIBLE_INSPECTOR_ID, inspector.second); + } + + visNode->Flush(); +} + +mitk::VisibleDataStorageInspectorMapType mitk::GetVisibleDataStorageInspectors() +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + auto* visNode = prefNode->Node(mitk::NodeSelectionConstants::VISIBLE_INSPECTORS_NODE_ID); + + using NamesType = std::vector; + NamesType names = visNode->ChildrenNames(); + + VisibleDataStorageInspectorMapType visMap; + + if (!names.empty()) + { + for (const auto& name : names) + { + auto* aNode = visNode->Node(name); + + if (aNode == nullptr) + mitkThrow() << "Error in preference interface. Cannot find preset node under given name. Name: " << name; + + std::istringstream isstr(name); + unsigned int order = 0; + isstr >> order; + + auto id = aNode->Get(mitk::NodeSelectionConstants::VISIBLE_INSPECTOR_ID, ""); + + if (id.empty()) + mitkThrow() << "Error in preference interface. ID of visible inspector is not set. Inspector position: " << order; + + visMap.insert(std::make_pair(order, id)); + } + } + + if (visMap.empty()) + { //no visibility preferences set. Generate default + auto allProviders = mitk::DataStorageInspectorGenerator::GetProviders(); + + //fill inspector list + unsigned int pos = 0; + for (const auto& iter : allProviders) + { + if (iter.first != QmitkDataStorageFavoriteNodesInspector::INSPECTOR_ID() && iter.first != QmitkDataStorageSelectionHistoryInspector::INSPECTOR_ID()) + { + visMap.insert(std::make_pair(pos, iter.first)); + ++pos; + } + } + } + + return visMap; +} + +mitk::DataStorageInspectorIDType mitk::GetPreferredDataStorageInspector() +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + auto id = prefNode->Get(mitk::NodeSelectionConstants::PREFERRED_INSPECTOR_ID, ""); + + if (id.empty()) + { //nothing set, deduce default preferred inspector + auto visibleInspectors = GetVisibleDataStorageInspectors(); + if (!visibleInspectors.empty()) + id = visibleInspectors.begin()->second; + } + + return id; +} + +void mitk::PutPreferredDataStorageInspector(const DataStorageInspectorIDType &id) +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + + prefNode->Put(mitk::NodeSelectionConstants::PREFERRED_INSPECTOR_ID, id); + prefNode->Flush(); +} + +void mitk::PutShowFavoritesInspector(bool show) +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + + prefNode->PutBool(mitk::NodeSelectionConstants::SHOW_FAVORITE_INSPECTOR, show); + prefNode->Flush(); +} + +bool mitk::GetShowFavoritesInspector() +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + + return prefNode->GetBool(mitk::NodeSelectionConstants::SHOW_FAVORITE_INSPECTOR, true); +} + +void mitk::PutShowHistoryInspector(bool show) +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + + prefNode->PutBool(mitk::NodeSelectionConstants::SHOW_HISTORY_INSPECTOR, show); + prefNode->Flush(); +} + +bool mitk::GetShowHistoryInspector() +{ + auto* prefService = mitk::CoreServices::GetPreferencesService(); + auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::NodeSelectionConstants::ROOT_PREFERENCE_NODE_ID); + + return prefNode->GetBool(mitk::NodeSelectionConstants::SHOW_HISTORY_INSPECTOR, true); +} diff --git a/Modules/QtWidgets/src/QmitkSingleNodeSelectionWidget.cpp b/Modules/QtWidgets/src/QmitkSingleNodeSelectionWidget.cpp new file mode 100644 index 0000000000..fc30ea2679 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkSingleNodeSelectionWidget.cpp @@ -0,0 +1,240 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "QmitkSingleNodeSelectionWidget.h" + +#include +#include + +#include +#include +#include + +#include + +QmitkSingleNodeSelectionWidget::QmitkSingleNodeSelectionWidget(QWidget* parent) + : QmitkAbstractNodeSelectionWidget(parent) + , m_AutoSelectNodes(false) +{ + m_Controls.setupUi(this); + + m_Controls.btnSelect->installEventFilter(this); + m_Controls.btnSelect->setVisible(true); + m_Controls.btnClear->setVisible(false); + + m_Controls.btnClear->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/times.svg"))); + + this->UpdateInfo(); + + connect(m_Controls.btnClear, SIGNAL(clicked(bool)), this, SLOT(OnClearSelection())); +} + +void QmitkSingleNodeSelectionWidget::ReviseSelectionChanged(const NodeList& oldInternalSelection, NodeList& newInternalSelection) +{ + if (newInternalSelection.empty()) + { + if (m_AutoSelectNodes) + { + auto autoSelectedNode = this->DetermineAutoSelectNode(oldInternalSelection); + + if (autoSelectedNode.IsNotNull()) + { + newInternalSelection.append(autoSelectedNode); + } + } + } + else if (newInternalSelection.size()>1) + { + //this widget only allows one internal selected node. + newInternalSelection = { newInternalSelection.front() }; + } +} + +void QmitkSingleNodeSelectionWidget::OnClearSelection() +{ + if (m_IsOptional) + { + this->SetCurrentSelection({}); + } + + this->UpdateInfo(); +} + +mitk::DataNode::Pointer QmitkSingleNodeSelectionWidget::GetSelectedNode() const +{ + mitk::DataNode::Pointer result; + + auto selection = GetCurrentInternalSelection(); + if (!selection.empty()) + { + result = selection.front(); + } + return result; +} + +bool QmitkSingleNodeSelectionWidget::eventFilter(QObject *obj, QEvent *ev) +{ + if (obj == m_Controls.btnSelect) + { + if (ev->type() == QEvent::MouseButtonRelease) + { + auto mouseEv = dynamic_cast(ev); + if (!mouseEv) + { + return false; + } + + if (mouseEv->button() == Qt::LeftButton) + { + if (this->isEnabled()) + { + this->EditSelection(); + return true; + } + } + else + { + auto selection = this->CompileEmitSelection(); + if (!selection.empty()) + { + QmitkNodeDetailsDialog infoDialog(selection, this); + infoDialog.exec(); + return true; + } + } + } + } + + return false; +} + +void QmitkSingleNodeSelectionWidget::EditSelection() +{ + QmitkNodeSelectionDialog* dialog = new QmitkNodeSelectionDialog(this, m_PopUpTitel, m_PopUpHint); + + dialog->SetDataStorage(m_DataStorage.Lock()); + dialog->SetNodePredicate(m_NodePredicate); + dialog->SetCurrentSelection(this->GetCurrentInternalSelection()); + dialog->SetSelectOnlyVisibleNodes(m_SelectOnlyVisibleNodes); + dialog->SetSelectionMode(QAbstractItemView::SingleSelection); + + m_Controls.btnSelect->setChecked(true); + + if (dialog->exec()) + { + this->HandleChangeOfInternalSelection(dialog->GetSelectedNodes()); + } + + m_Controls.btnSelect->setChecked(false); + + delete dialog; +} + +void QmitkSingleNodeSelectionWidget::UpdateInfo() +{ + if (this->GetSelectedNode().IsNull()) + { + if (m_IsOptional) + { + m_Controls.btnSelect->SetNodeInfo(m_EmptyInfo); + } + else + { + m_Controls.btnSelect->SetNodeInfo(m_InvalidInfo); + } + m_Controls.btnSelect->SetSelectionIsOptional(m_IsOptional); + m_Controls.btnClear->setVisible(false); + } + else + { + m_Controls.btnClear->setVisible(m_IsOptional); + } + + m_Controls.btnSelect->SetSelectedNode(this->GetSelectedNode()); +} + +void QmitkSingleNodeSelectionWidget::SetCurrentSelectedNode(mitk::DataNode* selectedNode) +{ + NodeList selection; + if (selectedNode) + { + selection.append(selectedNode); + } + this->SetCurrentSelection(selection); +} + +void QmitkSingleNodeSelectionWidget::OnDataStorageChanged() +{ + this->AutoSelectNodes(); +} + +void QmitkSingleNodeSelectionWidget::OnNodeAddedToStorage(const mitk::DataNode* /*node*/) +{ + this->AutoSelectNodes(); +} + +bool QmitkSingleNodeSelectionWidget::GetAutoSelectNewNodes() const +{ + return m_AutoSelectNodes; +} + +void QmitkSingleNodeSelectionWidget::SetAutoSelectNewNodes(bool autoSelect) +{ + m_AutoSelectNodes = autoSelect; + this->AutoSelectNodes(); +} + +void QmitkSingleNodeSelectionWidget::AutoSelectNodes() +{ + if (this->GetSelectedNode().IsNull() && m_AutoSelectNodes) + { + auto autoNode = this->DetermineAutoSelectNode(); + + if (autoNode.IsNotNull()) + { + this->HandleChangeOfInternalSelection({ autoNode }); + } + } +} + +mitk::DataNode::Pointer QmitkSingleNodeSelectionWidget::DetermineAutoSelectNode(const NodeList& ignoreNodes) +{ + mitk::DataNode::Pointer result; + auto storage = m_DataStorage.Lock(); + if (storage.IsNotNull()) + { + auto ignoreCheck = [ignoreNodes](const mitk::DataNode * node) + { + bool result = true; + for (const auto& ignoreNode : ignoreNodes) + { + if (node == ignoreNode) + { + result = false; + break; + } + } + return result; + }; + + mitk::NodePredicateFunction::Pointer isNotIgnoredNode = mitk::NodePredicateFunction::New(ignoreCheck); + mitk::NodePredicateBase::Pointer predicate = isNotIgnoredNode.GetPointer(); + + if (m_NodePredicate.IsNotNull()) + { + predicate = mitk::NodePredicateAnd::New(m_NodePredicate.GetPointer(), predicate.GetPointer()).GetPointer(); + } + + result = storage->GetNode(predicate); + } + return result; +} diff --git a/Modules/QtWidgets/src/QmitkSingleNodeSelectionWidget.ui b/Modules/QtWidgets/src/QmitkSingleNodeSelectionWidget.ui new file mode 100644 index 0000000000..94f5047e55 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkSingleNodeSelectionWidget.ui @@ -0,0 +1,124 @@ + + + QmitkSingleNodeSelectionWidget + + + + 0 + 0 + 348 + 25 + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 16777215 + 40 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 25 + + + + <html><head/><body><p>Press to change the selection.</p><p>Right click to show details about selected node.</p></body></html> + + + + + + true + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 25 + 16777215 + + + + Press to remove the current selection. + + + + + + + :/org.mitk.gui.qt.common/resources/times.svg:/org.mitk.gui.qt.common/resources/times.svg + + + + 19 + 19 + + + + + + + + + QmitkNodeSelectionButton + QPushButton +
QmitkNodeSelectionButton.h
+
+
+ + +