diff --git a/Modules/QtWidgets/include/QmitkAbstractNodeSelectionWidget.h b/Modules/QtWidgets/include/QmitkAbstractNodeSelectionWidget.h index 041b7e91bd..b8c3af8dbc 100644 --- a/Modules/QtWidgets/include/QmitkAbstractNodeSelectionWidget.h +++ b/Modules/QtWidgets/include/QmitkAbstractNodeSelectionWidget.h @@ -1,246 +1,259 @@ /*============================================================================ 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_ABSTRACT_NODE_SELECTION_WIDGET_H #define QMITK_ABSTRACT_NODE_SELECTION_WIDGET_H +#include + #include #include #include -#include - #include class QmitkAbstractDataStorageModel; class QAbstractItemVew; /** * \class QmitkAbstractNodeSelectionWidget * \brief Abstract base class for the selection of data from a data storage. */ class MITKQTWIDGETS_EXPORT QmitkAbstractNodeSelectionWidget : public QWidget { Q_OBJECT public: explicit QmitkAbstractNodeSelectionWidget(QWidget* parent = nullptr); virtual ~QmitkAbstractNodeSelectionWidget() override; /** - * @brief Sets the data storage that will be used /monitored by widget. + * @brief Sets the data storage that will be used / monitored by widget. * * @par dataStorage A pointer to the data storage to set. */ void SetDataStorage(mitk::DataStorage* dataStorage); /** * Sets the node predicate and updates the widget, according to the node predicate. * Implement OnNodePredicateChange() for custom actualization of a derived widget class. * * @par nodePredicate A pointer to node predicate. */ void SetNodePredicate(const mitk::NodePredicateBase* nodePredicate); const mitk::NodePredicateBase* GetNodePredicate() const; QString GetInvalidInfo() const; QString GetEmptyInfo() const; QString GetPopUpTitel() const; QString GetPopUpHint() const; bool GetSelectionIsOptional() const; bool GetSelectOnlyVisibleNodes() const; using NodeList = QList; /** Other node container type often used in the code base.*/ using ConstNodeStdVector = std::vector; /** Returns the selected nodes, as emitted with CurrentSelectionChanged*/ NodeList GetSelectedNodes() const; /** Convinience method that returns the selected nodes as ConstNodeStdVector. This is a type also often used in the mitk code base.*/ ConstNodeStdVector GetSelectedNodesStdVector() const; Q_SIGNALS: - /* + /** * @brief A signal that will be emitted if the selected node has changed. * * @par nodes A list of data nodes that are newly selected. */ void CurrentSelectionChanged(NodeList nodes); public Q_SLOTS: - /* + /** * @brief Change the selection modus of the item view's selection model. * * If true, an incoming selection will be filtered (reduced) to only those nodes that are visible by the current view. * An outgoing selection can then at most contain the filtered nodes. * If false, the incoming non-visible selection will be stored and later added to the outgoing selection, * to include the original selection that could not be modified. * The part of the original selection, that is non-visible are the nodes, that do not fullfill the predicate. * * @par selectOnlyVisibleNodes The bool value to define the selection modus. */ void SetSelectOnlyVisibleNodes(bool selectOnlyVisibleNodes); - /* - * @brief Transform a list of data nodes into a model selection and set this as a new selection of the + /** + * @brief Transform a list of data nodes (a selection) into a model selection and set this as a new selection of the * selection model of the private member item view. * * The function filters the given list of nodes according to the 'm_SelectOnlyVisibleNodes' member variable. If * necessary, the non-visible nodes are stored. This is done if 'm_SelectOnlyVisibleNodes' is false: In this case * the selection may be filtered and only a subset of the selected nodes may be visible and therefore (de-)selectable * in the data storage viewer. By storing the non-visible nodes it is possible to send the new, modified selection * but also include the selected nodes from the original selection that could not be modified (see 'SetSelectOnlyVisibleNodes'). * * @par nodes A list of data nodes that should be newly selected. */ void SetCurrentSelection(NodeList selectedNodes); /** Set the info text that should be displayed if no (valid) node is selected, - * but a selection is mandatory. - * The string can contain HTML code. if wanted*/ + * but a selection is mandatory. + * The string can contain HTML code, if desired. + */ void SetInvalidInfo(QString info); /** Set the info text that should be displayed if no (valid) node is selected, - * but a selection is optional. - * The string can contain HTML code. if wanted*/ + * but a selection is optional. + * The string can contain HTML code, if desired. + */ void SetEmptyInfo(QString info); /** Set the caption of the popup that is displayed to alter the selection. - * The string can contain HTML code. if wanted*/ + * The string can contain HTML code, if desired. + */ void SetPopUpTitel(QString info); /** Set the hint text of the popup that is displayed to alter the selection. - * The string can contain HTML code. if wanted*/ + * The string can contain HTML code, if desired. + */ void SetPopUpHint(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.*/ + * node does not mean an invalid state. Thus no node is a valid "node" selection too. + */ void SetSelectionIsOptional(bool isOptional); protected Q_SLOTS: /** Call to remove a node from the current selection. If the node is part of the current selection, - this will trigger ReviseSelectionChanged(), AllowEmissionOfSelection() and if there is really a change, - will also emit CurrentSelectionChanged.*/ + * this will trigger ReviseSelectionChanged(), AllowEmissionOfSelection() and if there is really a change, + * will also emit CurrentSelectionChanged. + */ void RemoveNodeFromSelection(const mitk::DataNode* node); protected: - /**Method is called if the display of the selected nodes should be updated (e.g. because the selection changed)*/ + /** Method is called if the display of the selected nodes should be updated (e.g. because the selection changed). */ virtual void UpdateInfo() = 0; - /**Method is called if the predicate has changed, before the selection will be updated according to the new predicate. - The default implementation does nothing. - @remark If you are only interested to know when the selection has changed, overwrite OnInternalSelectionChange().*/ + /** Method is called if the predicate has changed, before the selection will be updated according to the new predicate. + * The default implementation does nothing. + * @remark If you are only interested to know when the selection has changed, overwrite OnInternalSelectionChange(). + */ virtual void OnNodePredicateChanged(); - /**Method is called if the data storage has changed. The selection will be automatically be reseted afterwards. - The default implementation does nothing.*/ + /** Method is called if the data storage has changed. The selection will be automatically be reseted afterwards. + * The default implementation does nothing. + */ virtual void OnDataStorageChanged(); /** This member function will called when ever a new internal selection has been determined. This can be - used to update the state of internal widgets. The default implementation does nothing.*/ + * used to update the state of internal widgets. The default implementation does nothing. + */ virtual void OnInternalSelectionChanged(); - /**Method is called when a node is added to the storage. Default implementation does nothing. - Derived widgets can override the method if they want to react on new nodes in the storage.*/ + /** Method is called when a node is added to the storage. Default implementation does nothing. + * Derived widgets can override the method if they want to react on new nodes in the storage. + */ virtual void OnNodeAddedToStorage(const mitk::DataNode* node); - /**Method is called when a node is removed from the storage. The removed node is passed as - variable. This member is called directly before the node will be removed from the current selection if - he was a part. Default implementation does nothing. */ + /** Method is called when a node is removed from the storage. The removed node is passed as + * variable. This member is called directly before the node will be removed from the current selection if + * he was a part. Default implementation does nothing. + */ virtual void OnNodeRemovedFromStorage(const mitk::DataNode* node); - /**Method is called if the internal selection has changed. It will call following methods, that can be overriden to change - behavior in derived classes: - - pre internal selection change: ReviseSelectionChanged() - - post internal selection change: OnInternalSelectionChanged(), UpdateInfo() and AllowEmissionOfSelection() (via EmitSelection()) - . - If the emission is needed and allowed it will also trigger the emission via EmitSelection().*/ + /** Method is called if the internal selection has changed. It will call following methods, that can be overriden to change + * behavior in derived classes: + * - pre internal selection change: ReviseSelectionChanged() + * - post internal selection change: OnInternalSelectionChanged(), UpdateInfo() and AllowEmissionOfSelection() (via EmitSelection()). + * If the emission is needed and allowed it will also trigger the emission via EmitSelection(). + */ void HandleChangeOfInternalSelection(NodeList newInternalSelection); - /**Compiles the list of node that would be emitted. It always contains the internal selection. - Depending on SelectOnlyVisibleNodes it also adds all external select nodes that weren't visible - (failed the predicate).*/ + /** Compiles the list of node that would be emitted. It always contains the internal selection. + * Depending on SelectOnlyVisibleNodes it also adds all external select nodes that weren't visible (failed the predicate). + */ NodeList CompileEmitSelection() const; - /** This member function is called if the internal selection is about to be changed by the - base implementation. - This is the slot where derived classes can revise and change the internal selection before widget updates, - signal emissions and other things are triggered. Default implementation does nothing, thus it keeps the - passed internal selection as compiled by the base implementation.*/ + /** This member function is called if the internal selection is about to be changed by the base implementation. + * This is the slot where derived classes can revise and change the internal selection before widget updates, + * signal emissions and other things are triggered. Default implementation does nothing, thus it keeps the + * passed internal selection as compiled by the base implementation. + */ virtual void ReviseSelectionChanged(const NodeList& oldInternalSelection, NodeList& newInternalSelection); /** This function will be called before the CurrentSelectionChanged signal is emitted. The return value indicates - if the signal should be emitted (true = emission; false = no emission). The default implementation always - returns true. - @param emissionCandidates The nodes that will be emitted if the function returns true.*/ + * if the signal should be emitted (true = emission; false = no emission). The default implementation always + * returns true. + * @param emissionCandidates The nodes that will be emitted if the function returns true. + */ virtual bool AllowEmissionOfSelection(const NodeList& emissionCandidates) const; /** Checks if the new emission differs from the last emission. If this is the case and AllowEmissionOfSelection() - returns true the new selection will be emited. */ + * returns true the new selection will be emited. + */ void EmitSelection(const NodeList& emissionCandidates); void SetCurrentInternalSelection(NodeList selectedNodes); const NodeList& GetCurrentInternalSelection() const; const NodeList& GetCurrentExternalSelection() const; mitk::WeakPointer m_DataStorage; mitk::NodePredicateBase::ConstPointer m_NodePredicate; QString m_InvalidInfo; QString m_EmptyInfo; QString m_PopUpTitel; QString m_PopUpHint; /** See documentation of SetSelectOnlyVisibleNodes for details*/ bool m_IsOptional; /** See documentation of SetSelectionIsOptional for details*/ bool m_SelectOnlyVisibleNodes; private: /** Helper triggered on the storage delete event */ void SetDataStorageDeleted(); /**Member is called when a node is added to the storage. Derived widgets can override the method OnNodeAddedToStorage if they want to react on new nodes in the storage.*/ void NodeAddedToStorage(const mitk::DataNode* node); /**Member is called when a node is removed from the storage. It calls OnNodeRemovedFromStorage() and afterwards it removes the removed node form the selection (if it is part of the current selection). Derived classes can override OnNodeRemovedFromStorage() to react on the fact that a node might be removed and their selection might change, because the removed node is part of there selection.*/ void NodeRemovedFromStorage(const mitk::DataNode* node); void OnNodeModified(const itk::Object * /*caller*/, const itk::EventObject &); void AddNodeObserver(mitk::DataNode* node); void RemoveNodeObserver(mitk::DataNode* node); unsigned long m_DataStorageDeletedTag; NodeList m_CurrentInternalSelection; NodeList m_CurrentExternalSelection; NodeList m_LastEmission; bool m_LastEmissionAllowance; using NodeObserverTagMapType = std::map; NodeObserverTagMapType m_NodeObserverTags; /** Help to prevent recursions due to signal loops when emitting selections.*/ bool m_RecursionGuard; }; -#endif // QmitkAbstractNodeSelectionWidget_H + +#endif // QMITK_ABSTRACT_NODE_SELECTION_WIDGET_H diff --git a/Modules/QtWidgets/include/QmitkDataStorageSimpleTreeModel.h b/Modules/QtWidgets/include/QmitkDataStorageSimpleTreeModel.h index d70ddec93b..f27390cb5a 100644 --- a/Modules/QtWidgets/include/QmitkDataStorageSimpleTreeModel.h +++ b/Modules/QtWidgets/include/QmitkDataStorageSimpleTreeModel.h @@ -1,101 +1,101 @@ /*============================================================================ 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 QMITKDATASTORAGESIMPLETREEMODEL_H #define QMITKDATASTORAGESIMPLETREEMODEL_H #include // qt widgets module #include class QmitkDataStorageTreeModelInternalItem; /** * @brief The 'QmitkDataStorageSimpleTreeModel' is a basic tree model, derived from the 'QmitkAbstractDataStorageModel'. * It provides functions to accept a data storage and a node predicate in order to customize the model data nodes. * Furthermore it overrides the functions of 'QAbstractItemModel' to create a simple qt list model.* * This model can be used in conjunction with a 'QmitkDataStorageSelectionConnector'. * This model is a "light" version of the classic QmitkDataStorgageTreeModel. The differences between both are the following: * - This class currently does not support DragNDrop. -* - This class does not have the ability to change hirarchy or changes the layer property -*of nodes. This was skipped on purpose, because that is not the job of the storage model. -* - If a tree item A is removed this class does not attach children of A to the parent -*of A. Instead the complete tree representation is updated. This was changed on purpose -*because otherwise the internal representation of the model would not reflect the data storage graph anymore. +* - This class does not have the ability to change hierarchy or changes the layer property of nodes. +* This was skipped on purpose, because that is not the job of the storage model. +* - If a tree item A is removed this class does not attach children of A to the parent of A. +* Instead the complete tree representation is updated. This was changed on purpose because otherwise the internal +* representation of the model would not reflect the data storage graph anymore. */ class MITKQTWIDGETS_EXPORT QmitkDataStorageSimpleTreeModel : public QmitkAbstractDataStorageModel { Q_OBJECT public: QmitkDataStorageSimpleTreeModel(QObject *parent); ~QmitkDataStorageSimpleTreeModel() override; // override from 'QmitkAbstractDataStorageModel' /* * @brief See 'QmitkAbstractDataStorageModel' */ void DataStorageChanged() override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodePredicateChanged() override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodeAdded(const mitk::DataNode *node) override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodeChanged(const mitk::DataNode *node) override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodeRemoved(const mitk::DataNode *node) override; // override pure virtual from 'QAbstractItemModel' QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &child) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; protected: using TreeItem = QmitkDataStorageTreeModelInternalItem; private: void UpdateModelData(); void AddNodeInternal(const mitk::DataNode *node); mitk::DataNode *GetParentNode(const mitk::DataNode *node) const; TreeItem *TreeItemFromIndex(const QModelIndex &index) const; QModelIndex IndexFromTreeItem(TreeItem *item) const; void ResetTree(); TreeItem *m_Root; - /**helper structure to check, if a tree item is realy part of the model. + /**helper structure to check, if a tree item is really part of the model. Prefered over iterating over the tree by hand because we can use std::find.*/ std::list m_TreeItems; }; -#endif // QmitkDataStorageSimpleTreeModel_H +#endif // QMITKDATASTORAGESIMPLETREEMODEL_H diff --git a/Modules/QtWidgets/src/QmitkAbstractNodeSelectionWidget.cpp b/Modules/QtWidgets/src/QmitkAbstractNodeSelectionWidget.cpp index ff1ca235c1..39acb451f4 100644 --- a/Modules/QtWidgets/src/QmitkAbstractNodeSelectionWidget.cpp +++ b/Modules/QtWidgets/src/QmitkAbstractNodeSelectionWidget.cpp @@ -1,419 +1,426 @@ /*============================================================================ 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 "QmitkAbstractNodeSelectionWidget.h" #include "QmitkModelViewSelectionConnector.h" -QmitkAbstractNodeSelectionWidget::QmitkAbstractNodeSelectionWidget(QWidget* parent) : QWidget(parent), m_InvalidInfo("Error. Select data."), -m_EmptyInfo("Empty. Make a selection."), m_PopUpTitel("Select a data node"), m_PopUpHint(""), -m_IsOptional(false), m_SelectOnlyVisibleNodes(true), m_DataStorageDeletedTag(0), m_LastEmissionAllowance(true), m_RecursionGuard(false) +QmitkAbstractNodeSelectionWidget::QmitkAbstractNodeSelectionWidget(QWidget* parent) + : QWidget(parent) + , m_InvalidInfo("Error. Select data.") + , m_EmptyInfo("Empty. Make a selection.") + , m_PopUpTitel("Select a data node") + , m_PopUpHint("") + , m_IsOptional(false) + , m_SelectOnlyVisibleNodes(true) + , m_DataStorageDeletedTag(0) + , m_LastEmissionAllowance(true) + , m_RecursionGuard(false) { } QmitkAbstractNodeSelectionWidget::~QmitkAbstractNodeSelectionWidget() { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNotNull()) { // remove Listener for the data storage itself dataStorage->RemoveObserver(m_DataStorageDeletedTag); // remove "add node listener" from data storage dataStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage)); // remove "remove node listener" from data storage dataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage)); } for (auto& node : m_CurrentInternalSelection) { this->RemoveNodeObserver(node); } } QmitkAbstractNodeSelectionWidget::NodeList QmitkAbstractNodeSelectionWidget::GetSelectedNodes() const { return this->CompileEmitSelection(); } QmitkAbstractNodeSelectionWidget::ConstNodeStdVector QmitkAbstractNodeSelectionWidget::GetSelectedNodesStdVector() const { auto result = this->GetSelectedNodes(); return ConstNodeStdVector(result.begin(), result.end()); } void QmitkAbstractNodeSelectionWidget::SetDataStorage(mitk::DataStorage* dataStorage) { if (m_DataStorage == dataStorage) { return; } auto oldStorage = m_DataStorage.Lock(); if (oldStorage.IsNotNull()) { // remove Listener for the data storage itself oldStorage->RemoveObserver(m_DataStorageDeletedTag); // remove "add node listener" from old data storage oldStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage)); // remove "remove node listener" from old data storage oldStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage)); } m_DataStorage = dataStorage; auto newStorage = m_DataStorage.Lock(); if (newStorage.IsNotNull()) { // add Listener for the data storage itself auto command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted); m_DataStorageDeletedTag = newStorage->AddObserver(itk::DeleteEvent(), command); // add "add node listener" for new data storage newStorage->AddNodeEvent.AddListener( mitk::MessageDelegate1(this, &QmitkAbstractNodeSelectionWidget::NodeAddedToStorage)); // add remove node listener for new data storage newStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1(this, &QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage)); } this->OnDataStorageChanged(); this->HandleChangeOfInternalSelection({}); } void QmitkAbstractNodeSelectionWidget::SetNodePredicate(const mitk::NodePredicateBase* nodePredicate) { if (m_NodePredicate != nodePredicate) { m_NodePredicate = nodePredicate; this->OnNodePredicateChanged(); NodeList newInternalNodes; for (auto& node : m_CurrentInternalSelection) { if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)) { newInternalNodes.append(node); } } if (!m_SelectOnlyVisibleNodes) { for (auto& node : m_CurrentExternalSelection) { if (!newInternalNodes.contains(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node))) { newInternalNodes.append(node); } } } this->HandleChangeOfInternalSelection(newInternalNodes); } } void QmitkAbstractNodeSelectionWidget::HandleChangeOfInternalSelection(NodeList newInternalSelection) { if (!EqualNodeSelections(m_CurrentInternalSelection, newInternalSelection)) { this->ReviseSelectionChanged(m_CurrentInternalSelection, newInternalSelection); this->SetCurrentInternalSelection(newInternalSelection); this->OnInternalSelectionChanged(); auto newEmission = this->CompileEmitSelection(); this->EmitSelection(newEmission); this->UpdateInfo(); } } void QmitkAbstractNodeSelectionWidget::SetCurrentSelection(NodeList selectedNodes) { if (!m_RecursionGuard) { m_CurrentExternalSelection = selectedNodes; auto dataStorage = m_DataStorage.Lock(); NodeList newInternalSelection; for (auto node : selectedNodes) { if (dataStorage.IsNotNull() && dataStorage->Exists(node) && (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node))) { newInternalSelection.append(node); } } this->HandleChangeOfInternalSelection(newInternalSelection); } } const mitk::NodePredicateBase* QmitkAbstractNodeSelectionWidget::GetNodePredicate() const { return m_NodePredicate; } QString QmitkAbstractNodeSelectionWidget::GetInvalidInfo() const { return m_InvalidInfo; } QString QmitkAbstractNodeSelectionWidget::GetEmptyInfo() const { return m_EmptyInfo; } QString QmitkAbstractNodeSelectionWidget::GetPopUpTitel() const { return m_PopUpTitel; } QString QmitkAbstractNodeSelectionWidget::GetPopUpHint() const { return m_PopUpHint; } bool QmitkAbstractNodeSelectionWidget::GetSelectionIsOptional() const { return m_IsOptional; } bool QmitkAbstractNodeSelectionWidget::GetSelectOnlyVisibleNodes() const { return m_SelectOnlyVisibleNodes; } void QmitkAbstractNodeSelectionWidget::SetSelectOnlyVisibleNodes(bool selectOnlyVisibleNodes) { if (m_SelectOnlyVisibleNodes != selectOnlyVisibleNodes) { m_SelectOnlyVisibleNodes = selectOnlyVisibleNodes; auto newEmission = this->CompileEmitSelection(); this->EmitSelection(newEmission); } } void QmitkAbstractNodeSelectionWidget::SetInvalidInfo(QString info) { m_InvalidInfo = info; this->UpdateInfo(); } void QmitkAbstractNodeSelectionWidget::SetEmptyInfo(QString info) { m_EmptyInfo = info; this->UpdateInfo(); } void QmitkAbstractNodeSelectionWidget::SetPopUpTitel(QString info) { m_PopUpTitel = info; } void QmitkAbstractNodeSelectionWidget::SetPopUpHint(QString info) { m_PopUpHint = info; } void QmitkAbstractNodeSelectionWidget::SetSelectionIsOptional(bool isOptional) { m_IsOptional = isOptional; this->UpdateInfo(); } void QmitkAbstractNodeSelectionWidget::SetDataStorageDeleted() { this->OnDataStorageChanged(); this->HandleChangeOfInternalSelection({}); } void QmitkAbstractNodeSelectionWidget::ReviseSelectionChanged(const NodeList& /*oldInternalSelection*/, NodeList& /*newInternalSelection*/) { } bool QmitkAbstractNodeSelectionWidget::AllowEmissionOfSelection(const NodeList& /*emissionCandidates*/) const { return true; } void QmitkAbstractNodeSelectionWidget::EmitSelection(const NodeList& emissionCandidates) { m_LastEmissionAllowance = this->AllowEmissionOfSelection(emissionCandidates); if (m_LastEmissionAllowance && !EqualNodeSelections(m_LastEmission, emissionCandidates)) { m_RecursionGuard = true; emit CurrentSelectionChanged(emissionCandidates); m_RecursionGuard = false; m_LastEmission = emissionCandidates; } } void QmitkAbstractNodeSelectionWidget::SetCurrentInternalSelection(NodeList selectedNodes) { for (auto& node : m_CurrentInternalSelection) { this->RemoveNodeObserver(node); } m_CurrentInternalSelection = selectedNodes; for (auto& node : m_CurrentInternalSelection) { this->AddNodeObserver(node); } } const QmitkAbstractNodeSelectionWidget::NodeList& QmitkAbstractNodeSelectionWidget::GetCurrentInternalSelection() const { return m_CurrentInternalSelection; } const QmitkAbstractNodeSelectionWidget::NodeList& QmitkAbstractNodeSelectionWidget::GetCurrentExternalSelection() const { return m_CurrentExternalSelection; } void QmitkAbstractNodeSelectionWidget::OnNodePredicateChanged() { } void QmitkAbstractNodeSelectionWidget::OnDataStorageChanged() { } void QmitkAbstractNodeSelectionWidget::OnInternalSelectionChanged() { } void QmitkAbstractNodeSelectionWidget::NodeAddedToStorage(const mitk::DataNode* node) { this->OnNodeAddedToStorage(node); } void QmitkAbstractNodeSelectionWidget::OnNodeAddedToStorage(const mitk::DataNode* /*node*/) { } void QmitkAbstractNodeSelectionWidget::NodeRemovedFromStorage(const mitk::DataNode* node) { this->OnNodeRemovedFromStorage(node); this->RemoveNodeFromSelection(node); } void QmitkAbstractNodeSelectionWidget::OnNodeRemovedFromStorage(const mitk::DataNode* /*node*/) { } QmitkAbstractNodeSelectionWidget::NodeList QmitkAbstractNodeSelectionWidget::CompileEmitSelection() const { NodeList result = m_CurrentInternalSelection; if (!m_SelectOnlyVisibleNodes) { for (auto node : m_CurrentExternalSelection) { if (!result.contains(node) && m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node)) { result.append(node); } } } return result; } void QmitkAbstractNodeSelectionWidget::RemoveNodeFromSelection(const mitk::DataNode* node) { auto newSelection = m_CurrentInternalSelection; auto finding = std::find(std::begin(newSelection), std::end(newSelection), node); if (finding != std::end(newSelection)) { newSelection.erase(finding); this->HandleChangeOfInternalSelection(newSelection); } } void QmitkAbstractNodeSelectionWidget::OnNodeModified(const itk::Object * caller, const itk::EventObject & event) { if (itk::ModifiedEvent().CheckEvent(&event)) { auto node = dynamic_cast(caller); if (node) { if (m_NodePredicate.IsNotNull() && !m_NodePredicate->CheckNode(node)) { this->RemoveNodeFromSelection(node); } else { auto oldAllowance = m_LastEmissionAllowance; auto newEmission = this->CompileEmitSelection(); auto nonConstNode = const_cast(node); if (newEmission.contains(nonConstNode) && (oldAllowance != this->AllowEmissionOfSelection(newEmission))) { this->EmitSelection(newEmission); this->UpdateInfo(); } } } } } void QmitkAbstractNodeSelectionWidget::AddNodeObserver(mitk::DataNode* node) { if (node) { auto modifiedCommand = itk::MemberCommand::New(); modifiedCommand->SetCallbackFunction(this, &QmitkAbstractNodeSelectionWidget::OnNodeModified); auto nodeModifiedObserverTag = node->AddObserver(itk::ModifiedEvent(), modifiedCommand); m_NodeObserverTags.insert(std::make_pair(node, nodeModifiedObserverTag)); } } void QmitkAbstractNodeSelectionWidget::RemoveNodeObserver(mitk::DataNode* node) { if (node) { auto finding = m_NodeObserverTags.find(node); if (finding != std::end(m_NodeObserverTags)) { node->RemoveObserver(finding->second); } else { MITK_ERROR << "Selection widget is in a wrong state. A node should be removed from the internal selection but seems to have no observer. Node:" << node; } m_NodeObserverTags.erase(node); } } diff --git a/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp b/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp index 34e8b97a14..dd134255e6 100644 --- a/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp +++ b/Modules/QtWidgets/src/QmitkDataStorageDefaultListModel.cpp @@ -1,178 +1,179 @@ /*============================================================================ 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 // qt widgets module #include "QmitkCustomVariants.h" #include "QmitkEnums.h" #include "QmitkNodeDescriptorManager.h" -QmitkDataStorageDefaultListModel::QmitkDataStorageDefaultListModel(QObject *parent) : QmitkAbstractDataStorageModel(parent) +QmitkDataStorageDefaultListModel::QmitkDataStorageDefaultListModel(QObject *parent) + : QmitkAbstractDataStorageModel(parent) { } void QmitkDataStorageDefaultListModel::DataStorageChanged() { UpdateModelData(); } void QmitkDataStorageDefaultListModel::NodePredicateChanged() { UpdateModelData(); } void QmitkDataStorageDefaultListModel::NodeAdded(const mitk::DataNode* /*node*/) { UpdateModelData(); } void QmitkDataStorageDefaultListModel::NodeChanged(const mitk::DataNode* node) { // since the "NodeChanged" event is sent quite often, we check here, if it is relevant for this model if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node)) { UpdateModelData(); return; } // not relevant - need to check if we have to remove it if (std::find(m_DataNodes.begin(), m_DataNodes.end(), node) != m_DataNodes.end()) { UpdateModelData(); } } void QmitkDataStorageDefaultListModel::NodeRemoved(const mitk::DataNode* /*node*/) { UpdateModelData(); } QModelIndex QmitkDataStorageDefaultListModel::index(int row, int column, const QModelIndex &parent) const { bool hasIndex = this->hasIndex(row, column, parent); if (hasIndex) { return this->createIndex(row, column); } return QModelIndex(); } QModelIndex QmitkDataStorageDefaultListModel::parent(const QModelIndex &/*child*/) const { return QModelIndex(); } int QmitkDataStorageDefaultListModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return m_DataNodes.size(); } int QmitkDataStorageDefaultListModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return 1; } QVariant QmitkDataStorageDefaultListModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.model() != this) { return QVariant(); } if(index.row() < 0 || index.row() >= static_cast(m_DataNodes.size())) { return QVariant(); } mitk::DataNode::Pointer dataNode = m_DataNodes.at(index.row()); QString 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 == QmitkDataNodeRole) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } else if (role == QmitkDataNodeRawPointerRole) { return QVariant::fromValue(dataNode); } return QVariant(); } QVariant QmitkDataStorageDefaultListModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const { return QVariant(tr("Nodes")); } Qt::ItemFlags QmitkDataStorageDefaultListModel::flags(const QModelIndex &index) const { if (index.isValid() && index.model() == this) { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } return Qt::NoItemFlags; } void QmitkDataStorageDefaultListModel::UpdateModelData() { mitk::DataStorage::SetOfObjects::ConstPointer dataNodes; if (!m_DataStorage.IsExpired()) { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNotNull() && m_NodePredicate.IsNotNull()) { dataNodes = dataStorage->GetSubset(m_NodePredicate); } else { dataNodes = dataStorage->GetAll(); } } // update the model, so that it will be filled with the nodes of the new data storage beginResetModel(); m_DataNodes.clear(); // add all (filtered) nodes to the vector of nodes if (dataNodes != nullptr) { for (auto& node : *dataNodes) { m_DataNodes.push_back(node); } } endResetModel(); } diff --git a/Modules/QtWidgets/src/QmitkDataStorageListModel.cpp b/Modules/QtWidgets/src/QmitkDataStorageListModel.cpp index 90358e6033..e9a1c1314c 100755 --- a/Modules/QtWidgets/src/QmitkDataStorageListModel.cpp +++ b/Modules/QtWidgets/src/QmitkDataStorageListModel.cpp @@ -1,329 +1,332 @@ /*============================================================================ 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 "QmitkDataStorageListModel.h" //# Own includes // mitk #include "mitkStringProperty.h" //# Toolkit includes // itk #include "itkCommand.h" QmitkDataStorageListModel::QmitkDataStorageListModel(mitk::DataStorage *dataStorage, mitk::NodePredicateBase::Pointer pred, QObject *parent) - : QAbstractListModel(parent), m_NodePredicate(nullptr), m_DataStorage(nullptr), m_BlockEvents(false) + : QAbstractListModel(parent) + , m_NodePredicate(nullptr) + , m_DataStorage(nullptr) + , m_BlockEvents(false) { this->SetPredicate(pred); this->SetDataStorage(dataStorage); } QmitkDataStorageListModel::~QmitkDataStorageListModel() { // set data storage to nullptr so that the event listener gets removed this->SetDataStorage(nullptr); } void QmitkDataStorageListModel::SetDataStorage(mitk::DataStorage::Pointer dataStorage) { if (m_DataStorage == dataStorage) { return; } // remove old listeners if (m_DataStorage != nullptr) { m_DataStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageListModel::OnDataStorageNodeAdded)); m_DataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageListModel::OnDataStorageNodeRemoved)); m_DataStorage->RemoveObserver(m_DataStorageDeleteObserverTag); m_DataStorageDeleteObserverTag = 0; } m_DataStorage = dataStorage; if (m_DataStorage != nullptr) { // subscribe for node added/removed events m_DataStorage->AddNodeEvent.AddListener(mitk::MessageDelegate1( this, &QmitkDataStorageListModel::OnDataStorageNodeAdded)); m_DataStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageListModel::OnDataStorageNodeRemoved)); // add ITK delete listener on data storage itk::MemberCommand::Pointer deleteCommand = itk::MemberCommand::New(); deleteCommand->SetCallbackFunction(this, &QmitkDataStorageListModel::OnDataStorageDeleted); m_DataStorageDeleteObserverTag = m_DataStorage->AddObserver(itk::DeleteEvent(), deleteCommand); } // reset/rebuild model reset(); } Qt::ItemFlags QmitkDataStorageListModel::flags(const QModelIndex &) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QVariant QmitkDataStorageListModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole && index.isValid()) { const mitk::DataNode *node = std::get(m_NodesAndObserverTags.at(index.row())); return QVariant(QString::fromStdString(node->GetName())); } else { return QVariant(); } } QVariant QmitkDataStorageListModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const { return QVariant(tr("Nodes")); } int QmitkDataStorageListModel::rowCount(const QModelIndex & /*parent*/) const { return m_NodesAndObserverTags.size(); } std::vector QmitkDataStorageListModel::GetDataNodes() const { auto size = m_NodesAndObserverTags.size(); std::vector result(size); for (std::size_t i = 0; i < size; ++i) { result[i] = std::get(m_NodesAndObserverTags[i]); } return result; } mitk::DataStorage *QmitkDataStorageListModel::GetDataStorage() const { return m_DataStorage; } void QmitkDataStorageListModel::SetPredicate(mitk::NodePredicateBase *pred) { m_NodePredicate = pred; // in a prior implementation the call to beginResetModel() been after reset(). // Should this actually be the better order of calls, please document! QAbstractListModel::beginResetModel(); reset(); QAbstractListModel::endResetModel(); } mitk::NodePredicateBase *QmitkDataStorageListModel::GetPredicate() const { return m_NodePredicate; } void QmitkDataStorageListModel::reset() { mitk::DataStorage::SetOfObjects::ConstPointer modelNodes; if (m_DataStorage != nullptr) { if (m_NodePredicate != nullptr) { modelNodes = m_DataStorage->GetSubset(m_NodePredicate); } else { modelNodes = m_DataStorage->GetAll(); } } ClearInternalNodeList(); // add all filtered nodes to our list if (modelNodes != nullptr) { for (auto &node : *modelNodes) { AddNodeToInternalList(node); } } } void QmitkDataStorageListModel::AddNodeToInternalList(mitk::DataNode *node) { if (m_DataStorage != nullptr) { itk::MemberCommand::Pointer nodeModifiedCommand; // add modified observer nodeModifiedCommand = itk::MemberCommand::New(); nodeModifiedCommand->SetCallbackFunction(this, &QmitkDataStorageListModel::OnDataNodeModified); unsigned long nodeObserverTag = node->AddObserver(itk::ModifiedEvent(), nodeModifiedCommand); itk::MemberCommand::Pointer dataModifiedCommand; unsigned long dataObserverTag = 0; // add modified observer if (node->GetData() != nullptr) { dataModifiedCommand = itk::MemberCommand::New(); dataModifiedCommand->SetCallbackFunction(this, &QmitkDataStorageListModel::OnDataModified); dataObserverTag = node->GetData()->AddObserver(itk::ModifiedEvent(), dataModifiedCommand); } m_NodesAndObserverTags.push_back(std::make_tuple(node, nodeObserverTag, dataObserverTag)); } } void QmitkDataStorageListModel::ClearInternalNodeList() { for (auto &iter : m_NodesAndObserverTags) { auto node = std::get(iter); if (node != nullptr) { node->RemoveObserver(std::get(iter)); if (node->GetData() != nullptr) { node->GetData()->RemoveObserver(std::get(iter)); } } } m_NodesAndObserverTags.clear(); } void QmitkDataStorageListModel::RemoveNodeFromInternalList(mitk::DataNode *node) { for (auto iter = m_NodesAndObserverTags.begin(); iter != m_NodesAndObserverTags.end(); ++iter) { if (std::get(*iter) == node) { node->RemoveObserver(std::get(*iter)); if (node->GetData() != nullptr) { node->GetData()->RemoveObserver(std::get(*iter)); } m_NodesAndObserverTags.erase(iter); // invalidate iter break; } } } void QmitkDataStorageListModel::OnDataStorageNodeAdded(const mitk::DataNode *node) { // guarantee no recursions when a new node event is thrown if (!m_BlockEvents) { m_BlockEvents = true; // check if node should be added to the model bool addNode = true; if (m_NodePredicate && !m_NodePredicate->CheckNode(node)) addNode = false; if (addNode) { int newIndex = m_NodesAndObserverTags.size(); beginInsertRows(QModelIndex(), newIndex, newIndex); AddNodeToInternalList(const_cast(node)); endInsertRows(); } m_BlockEvents = false; } } void QmitkDataStorageListModel::OnDataStorageNodeRemoved(const mitk::DataNode *node) { // guarantee no recursions when a new node event is thrown if (!m_BlockEvents) { m_BlockEvents = true; int row = 0; for (auto iter = m_NodesAndObserverTags.begin(); iter != m_NodesAndObserverTags.end(); ++iter, ++row) { if (std::get(*iter) == node) { // node found, remove it beginRemoveRows(QModelIndex(), row, row); RemoveNodeFromInternalList(std::get(*iter)); endRemoveRows(); break; } } } m_BlockEvents = false; } void QmitkDataStorageListModel::OnDataNodeModified(const itk::Object *caller, const itk::EventObject & /*event*/) { if (m_BlockEvents) return; const mitk::DataNode *modifiedNode = dynamic_cast(caller); if (modifiedNode) { QModelIndex changedIndex = getIndex(modifiedNode); if (changedIndex.isValid()) { emit dataChanged(changedIndex, changedIndex); } } } void QmitkDataStorageListModel::OnDataModified(const itk::Object *caller, const itk::EventObject &event) { OnDataNodeModified(caller, event); // until different implementation } void QmitkDataStorageListModel::OnDataStorageDeleted(const itk::Object *, const itk::EventObject &) { if (m_BlockEvents) return; this->SetDataStorage(nullptr); } mitk::DataNode::Pointer QmitkDataStorageListModel::getNode(const QModelIndex &index) const { if (index.isValid()) { return std::get(m_NodesAndObserverTags.at(index.row())); } else { return nullptr; } } QModelIndex QmitkDataStorageListModel::getIndex(const mitk::DataNode *node) const { int row = 0; for (auto iter = m_NodesAndObserverTags.begin(); iter != m_NodesAndObserverTags.end(); ++iter, ++row) { if (std::get(*iter) == node) { return index(row); } } return QModelIndex(); } diff --git a/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp b/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp index 5f7b269025..b85cb7e2bd 100644 --- a/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp +++ b/Modules/QtWidgets/src/QmitkDataStorageSimpleTreeModel.cpp @@ -1,370 +1,371 @@ /*============================================================================ 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 #include #include // qt widgets module #include "QmitkCustomVariants.h" #include "QmitkEnums.h" QmitkDataStorageSimpleTreeModel::QmitkDataStorageSimpleTreeModel(QObject *parent) - : QmitkAbstractDataStorageModel(parent), m_Root(nullptr) + : QmitkAbstractDataStorageModel(parent) + , m_Root(nullptr) { ResetTree(); } QmitkDataStorageSimpleTreeModel::~QmitkDataStorageSimpleTreeModel() { m_Root->Delete(); m_Root = nullptr; -}; +} void QmitkDataStorageSimpleTreeModel::ResetTree() { mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); rootDataNode->SetName("Data Storage"); m_Root = new TreeItem(rootDataNode, nullptr); } void QmitkDataStorageSimpleTreeModel::DataStorageChanged() { if (m_Root) { m_Root->Delete(); } beginResetModel(); ResetTree(); UpdateModelData(); endResetModel(); } void QmitkDataStorageSimpleTreeModel::NodePredicateChanged() { beginResetModel(); ResetTree(); UpdateModelData(); endResetModel(); } void QmitkDataStorageSimpleTreeModel::NodeAdded(const mitk::DataNode *node) { if (node == nullptr || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != nullptr) return; this->AddNodeInternal(node); } void QmitkDataStorageSimpleTreeModel::NodeChanged(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); } } void QmitkDataStorageSimpleTreeModel::NodeRemoved(const mitk::DataNode *node) { if (node == nullptr || !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(); m_TreeItems.remove(treeItem); delete treeItem; //delete in tree if (!children.empty()) { //if not empty we have to rebuild the whole representation, //because the children could be now top level, or at another //source/parent. this->UpdateModelData(); } } QModelIndex QmitkDataStorageSimpleTreeModel::index(int row, int column, const QModelIndex &parent) const { TreeItem *parentItem; if (!parent.isValid() || parent.model() != this) parentItem = m_Root; else parentItem = static_cast(parent.internalPointer()); if (parentItem) { TreeItem *childItem = parentItem->GetChild(row); if (childItem) return createIndex(row, column, childItem); } return QModelIndex(); } QModelIndex QmitkDataStorageSimpleTreeModel::parent(const QModelIndex &child) const { if (!child.isValid() || !m_Root || child.model() != this) return QModelIndex(); TreeItem *childItem = this->TreeItemFromIndex(child); if (!childItem) return QModelIndex(); TreeItem *parentItem = childItem->GetParent(); if (parentItem == m_Root) return QModelIndex(); return this->createIndex(parentItem->GetIndex(), 0, parentItem); } QmitkDataStorageSimpleTreeModel::TreeItem *QmitkDataStorageSimpleTreeModel::TreeItemFromIndex( const QModelIndex &index) const { if (index.isValid() && index.model() == this) { auto item = static_cast(index.internalPointer()); auto finding = std::find(std::begin(m_TreeItems), std::end(m_TreeItems), item); if (finding == std::end(m_TreeItems)) { return nullptr; } return item; } else return m_Root; } int QmitkDataStorageSimpleTreeModel::rowCount(const QModelIndex &parent) const { TreeItem *parentTreeItem = this->TreeItemFromIndex(parent); if (parentTreeItem) return parentTreeItem->GetChildCount(); else return 0; } int QmitkDataStorageSimpleTreeModel::columnCount(const QModelIndex &/*parent*/) const { return 1; } QVariant QmitkDataStorageSimpleTreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.model() != this) { return QVariant(); } auto treeItem = this->TreeItemFromIndex(index); if (!treeItem) return QVariant(); mitk::DataNode *dataNode = treeItem->GetDataNode(); QString 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 == QmitkDataNodeRole) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } else if (role == QmitkDataNodeRawPointerRole) { return QVariant::fromValue(dataNode); } return QVariant(); } bool QmitkDataStorageSimpleTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || index.model() != this) return false; auto treeItem = this->TreeItemFromIndex(index); if (!treeItem) return false; mitk::DataNode *dataNode = treeItem->GetDataNode(); if (!dataNode) return false; if (role == Qt::EditRole && !value.toString().isEmpty()) { dataNode->SetName(value.toString().toStdString().c_str()); } 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); } // inform listeners about changes emit dataChanged(index, index); return true; } QVariant QmitkDataStorageSimpleTreeModel::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(); } Qt::ItemFlags QmitkDataStorageSimpleTreeModel::flags(const QModelIndex &index) const { if (index.isValid() && index.model() == this) { auto treeItem = this->TreeItemFromIndex(index); if (!treeItem) return Qt::NoItemFlags; const auto dataNode = treeItem->GetDataNode(); if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(dataNode)) { return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; } else { return Qt::NoItemFlags; } } return Qt::NoItemFlags; } mitk::DataNode *QmitkDataStorageSimpleTreeModel::GetParentNode(const mitk::DataNode *node) const { mitk::DataNode *dataNode = nullptr; mitk::DataStorage::SetOfObjects::ConstPointer _Sources = m_DataStorage.Lock()->GetSources(node); if (_Sources->Size() > 0) dataNode = _Sources->front(); return dataNode; } void QmitkDataStorageSimpleTreeModel::AddNodeInternal(const mitk::DataNode *node) { if (node == nullptr || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != nullptr) 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->NodeAdded(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); } 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); auto newNode = new TreeItem(const_cast(node)); parentTreeItem->InsertChild(newNode, firstRowWithASiblingBelow); m_TreeItems.push_back(newNode); endInsertRows(); } QModelIndex QmitkDataStorageSimpleTreeModel::IndexFromTreeItem(TreeItem *item) const { if (item == m_Root) return QModelIndex(); else return this->createIndex(item->GetIndex(), 0, item); } void QmitkDataStorageSimpleTreeModel::UpdateModelData() { if (!m_DataStorage.IsExpired()) { auto nodeset = m_DataStorage.Lock()->GetAll(); if (m_NodePredicate != nullptr) { nodeset = m_DataStorage.Lock()->GetSubset(m_NodePredicate); } for (const auto& node : *nodeset) { this->AddNodeInternal(node); } } } diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.cpp index dfca873947..ecae1b05e3 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.cpp +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.cpp @@ -1,159 +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 "QmitkNodeSelectionDialog.h" #include "QmitkCustomVariants.h" #include "internal/QmitkNodeSelectionListItemWidget.h" -QmitkMultiNodeSelectionWidget::QmitkMultiNodeSelectionWidget(QWidget* parent) : QmitkAbstractNodeSelectionWidget(parent) +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/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.h b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.h index 747c9c1951..493db43ec0 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.h +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiNodeSelectionWidget.h @@ -1,77 +1,81 @@ /*============================================================================ 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 #include #include "QmitkSimpleTextOverlayWidget.h" #include "org_mitk_gui_qt_common_Export.h" #include "ui_QmitkMultiNodeSelectionWidget.h" #include class QmitkAbstractDataStorageModel; class QAbstractItemVew; /** -* \class QmitkMultiNodeSelectionWidget -* \brief Widget that allows to perform and represents a multiple node selection. +* @class QmitkMultiNodeSelectionWidget +* @brief Widget that allows to perform and represents a multiple node selection. */ class MITK_QT_COMMON QmitkMultiNodeSelectionWidget : public QmitkAbstractNodeSelectionWidget { Q_OBJECT public: explicit QmitkMultiNodeSelectionWidget(QWidget* parent = nullptr); using NodeList = QmitkAbstractNodeSelectionWidget::NodeList; - /**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.*/ + /** + * @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; - /**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.*/ + /** + * @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 // QmitkMultiNodeSelectionWidget_H + +#endif // QMITK_MULTI_NODE_SELECTION_WIDGET_H diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.cpp index 68adfbd9a2..072b5cd082 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.cpp +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.cpp @@ -1,278 +1,281 @@ /*============================================================================ 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" -// berry includes -#include -#include - -#include "QPainter" -#include "QTextDocument" -#include "QEvent" - -#include -#include - // mitk core #include -#include #include #include #include #include -// vtk +// mitk qt widgets module +#include + +// berry includes +#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::PlaneGeometry::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) -{ } + : 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) { QString stylesheet; ctkPluginContext* context = berry::WorkbenchPlugin::GetDefault()->GetPluginContext(); ctkServiceReference styleManagerRef = context->getServiceReference(); if (styleManagerRef) { auto styleManager = context->getService(styleManagerRef); stylesheet = styleManager->GetStylesheet(); } QPushButton::paintEvent(p); 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/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.h b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.h index ebd5980339..21d328da1c 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.h +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionButton.h @@ -1,73 +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 "org_mitk_gui_qt_common_Export.h" -#include "QPushButton" -#include "QPixmap" +#include +#include +#include -/** Button class that can be used to display informations about a passed node. - * If the passed node is a null ptr the node info text will be shown. - * In difference to the normal push button text property. The node info can - * be formated text (e.g. HTML code; like the tooltip text).*/ +/** +* @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 MITK_QT_COMMON QmitkNodeSelectionButton : public QPushButton { Q_OBJECT public: explicit QmitkNodeSelectionButton(QWidget *parent = nullptr); ~QmitkNodeSelectionButton() override; const mitk::DataNode* GetSelectedNode() const; bool GetSelectionIsOptional() const; -public Q_SLOTS : +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 // QmitkSingleNodeSelectionWidget_H +#endif // QMITK_NODE_SELECTION_BUTTON_H diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.cpp index 56e426b8bf..979715cd2d 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.cpp +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.cpp @@ -1,287 +1,291 @@ /*============================================================================ 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 -QmitkNodeSelectionDialog::QmitkNodeSelectionDialog(QWidget* parent, QString title, QString hint) : QDialog(parent), - m_NodePredicate(nullptr), m_SelectOnlyVisibleNodes(false), m_SelectedNodes(NodeList()), m_SelectionMode(QAbstractItemView::SingleSelection) +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 (auto proIter : providers) { visibleProviders.insert(std::make_pair(order, proIter.first)); ++order; } } int preferredIndex = 0; bool preferredFound = false; for (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(berry::QtStyleManager::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; if (!m_DataStorage.IsExpired()) { for (auto panel : m_Panels) { panel->SetDataStorage(dataStorage); } } } } 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 : m_SelectedNodes) { node->SetBoolProperty("org.mitk.selection.favorite", true); } } void QmitkNodeSelectionDialog::OnOK() { for (auto node : 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*/) { if (!m_SelectedNodes.empty()) { this->OnOK(); } } diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.h b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.h index 25ccda870d..c40dde3199 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.h +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkNodeSelectionDialog.h @@ -1,143 +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 "org_mitk_gui_qt_common_Export.h" + +#include "ui_QmitkNodeSelectionDialog.h" + #include #include #include #include "mitkIDataStorageInspectorProvider.h" #include -#include "org_mitk_gui_qt_common_Export.h" - -#include "ui_QmitkNodeSelectionDialog.h" - #include #include /** -* \class QmitkNodeSelectionDialog -* \brief Widget that allows to show and edit the content of an mitk::IsoDoseLevel instance. +* @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 MITK_QT_COMMON QmitkNodeSelectionDialog : public QDialog { Q_OBJECT public: explicit QmitkNodeSelectionDialog(QWidget* parent = nullptr, QString caption = "", QString hint = ""); /** - * @brief Sets the data storage that will be used /monitored by widget. + * @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 Sets the node predicate and updates the widget, according to the node predicate. + * @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 Change the selection modus of the item view's selection model. - * - * If true, an incoming selection will be filtered (reduced) to only those nodes that are visible by the current view. - * An outgoing selection can then at most contain the filtered nodes. - * If false, the incoming non-visible selection will be stored and later added to the outgoing selection, - * to include the original selection that could not be modified. - * The part of the original selection, that is non-visible are the nodes that are not + /** + * @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 Transform a list of data nodes into a model selection and set this as a new selection of the - * selection model of the private member item view. - * - * The function filters the given list of nodes according to the 'm_SelectOnlyVisibleNodes' member variable. If - * necessary, the non-visible nodes are stored. This is done if 'm_SelectOnlyVisibleNodes' is false: In this case - * the selection may be filtered and only a subset of the selected nodes may be visible and therefore (de-)selectable - * in the data storage viewer. By storing the non-visible nodes it is possible to send the new, modified selection - * but also include the selected nodes from the original selection that could not be modified (see 'SetSelectOnlyVisibleNodes'). + /** + * @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 nodes 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/Plugins/org.mitk.gui.qt.common/src/QmitkSelectionServiceConnector.h b/Plugins/org.mitk.gui.qt.common/src/QmitkSelectionServiceConnector.h index f79dfa3420..b0c8f34647 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkSelectionServiceConnector.h +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkSelectionServiceConnector.h @@ -1,136 +1,133 @@ /*============================================================================ 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 QMITKSELECTIONSERVICECONNECTOR_H #define QMITKSELECTIONSERVICECONNECTOR_H #include -// qt widgets module -#include - // mitk gui qt common plugin #include "QmitkDataNodeSelectionProvider.h" #include "internal/QmitkDataNodeItemModel.h" // blueberry ui qt plugin #include /* * @brief The 'QmitkSelectionServiceConnector' is used to handle the selections of the global selection bus (selection service). * * The selection service connector can listen to a selection service. This should be done by using 'AddPostSelectionListener' * with the existing selection service of the surrounding 'QmitkAbstractView'. * The selection service connector can provide selections. This should be done by using 'SetAsSelectionProvider' * with the existing selection provider of the surrounding 'QmitkAbstractView'. * * The 'QmitkSelectionServiceConnector' offers a public slot and signal that can be used to propagate the selected * nodes from or to the global selection bus: * The 'ChangeServiceSelection'-slot transforms the given list of selected nodes into a QItemSelection of a temporary * data node selection model. This data node selection model is set as the item selection model of the member selection provider. * So by temporary adding a new data node selection model and changing its selection the selection provider sends a new selection * that can be received at any place in the workbench. * * The 'ServiceSelectionChanged'-signal sends a list of selected nodes to it's local environment (e.g. containing widget). * The 'ServiceSelectionChanged'-signal is emitted by the 'ServiceSelectionChanged'-function, which transforms the * berry selection of the selection into a data node list. The 'ServiceSelectionChanged'-function is called whenever * the selection service sends a selection changed event. * * In order to connect the 'QmitkSelectionServiceConnector' with a model-view pair, a 'QmitkModelViewSelectionConnector' needs to be used: * The 'QmitkModelViewSelectionConnector' offers a 'SetCurrentSelection'-slot that can be connected with the * 'ServiceSelectionChanged'-signal of this class. * The 'QmitkModelViewSelectionConnector' offers a 'CurrentSelectionChanged'-signal that can be connected with the * 'ChangeServiceSelection'-slot of this class. */ class MITK_QT_COMMON QmitkSelectionServiceConnector : public QObject { Q_OBJECT public: QmitkSelectionServiceConnector(); ~QmitkSelectionServiceConnector() override; /* * @brief Create a selection listener and add it to the list of selection listener of the given selection service. * * The selection listener is connected to the 'ServiceSelectionChanged' member function, which is * called if a berry selection is changed in the workbench. */ void AddPostSelectionListener(berry::ISelectionService* selectionService); /* * @brief Remove a selection listener from the list of selection listener of the selection service member. */ void RemovePostSelectionListener(); /* * @brief Store the given selection provider as a private member. * In order to use the public slot 'ChangeServiceSelection'-function, the selection provider member had to be * previously set. */ void SetAsSelectionProvider(QmitkDataNodeSelectionProvider* selectionProvider); /* * @brief Set the selection provider member to a nullptr. This will prevent the public slot * 'ChangeServiceSelection'-function from working. */ void RemoveAsSelectionProvider(); Q_SIGNALS: /* * @brief A signal that will be emitted by the private 'ServiceSelectionChanged'-function. This happens if a selection is changed * via the selection service. * * @par nodes A list of data nodes that are newly selected. */ void ServiceSelectionChanged(QList nodes); /* * @brief A signal that will be emitted by the private 'ServiceSelectionChanged'-function. If sourcePart has send an invalid selection * (selection pointer was Null). * @par sourcePart Part that sent the null selection. */ void ServiceNullSelection(const berry::IWorkbenchPart::Pointer& sourcePart); public Q_SLOTS: /* * @brief Send new selections to the selection service via the private selection provider member. * * This slot-function is called whenever a local selection is changed in the surrounding widget and a selection provider was set. * The newly selected data nodes are added temporary to a 'QmitkDataNodeItemModel', which is then used to define * the indices to select. * The 'QItemSelectionModel' is set as the item selection model of the selection provider member and its items are * selected by the indices previously defined by the 'QmitkDataNodeItemModel'. */ void ChangeServiceSelection(QList nodes); private: std::unique_ptr m_BerrySelectionListener; berry::ISelectionService* m_SelectionService; QmitkDataNodeSelectionProvider* m_SelectionProvider; std::shared_ptr m_DataNodeItemModel; std::shared_ptr m_DataNodeSelectionModel; /* * @brief Handle a selection received from the selection service. * * This function is called whenever a berry selection of the selection service is changed in the workbench. * The new selection is transformed into a data node selection and the contained data nodes are propagated * as the new current selection of the item view member. * * @par sourcePart The workbench part containing the selection. * @par selection The current selection. */ void OnServiceSelectionChanged(const berry::IWorkbenchPart::Pointer& sourcePart, const berry::ISelection::ConstPointer& selection); }; #endif // QMITKSELECTIONSERVICECONNECTOR_H diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.cpp index 87bb9cd71a..51b28638a5 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.cpp +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.cpp @@ -1,230 +1,231 @@ /*============================================================================ 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 "mitkNodePredicateFunction.h" #include "mitkNodePredicateAnd.h" #include #include "QmitkNodeSelectionDialog.h" #include "QmitkNodeDetailsDialog.h" -QmitkSingleNodeSelectionWidget::QmitkSingleNodeSelectionWidget(QWidget* parent) : QmitkAbstractNodeSelectionWidget(parent), m_AutoSelectNewNodes(false) +QmitkSingleNodeSelectionWidget::QmitkSingleNodeSelectionWidget(QWidget* parent) + : QmitkAbstractNodeSelectionWidget(parent) + , m_AutoSelectNewNodes(false) { m_Controls.setupUi(this); m_Controls.btnSelect->installEventFilter(this); m_Controls.btnSelect->setVisible(true); m_Controls.btnClear->setVisible(false); m_Controls.btnClear->setIcon(berry::QtStyleManager::ThemeIcon(QStringLiteral(":/org.mitk.gui.qt.common/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_AutoSelectNewNodes) { 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()); } 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; } void QmitkSingleNodeSelectionWidget::SetCurrentSelectedNode(mitk::DataNode* selectedNode) { NodeList selection; if (selectedNode) { selection.append(selectedNode); } this->SetCurrentSelection(selection); -}; +} void QmitkSingleNodeSelectionWidget::OnNodeAddedToStorage(const mitk::DataNode* /*node*/) { if (this->GetSelectedNode().IsNull() && m_AutoSelectNewNodes) { auto autoNode = this->DetermineAutoSelectNode(); if (autoNode.IsNotNull()) { this->HandleChangeOfInternalSelection({ autoNode }); } } } bool QmitkSingleNodeSelectionWidget::GetAutoSelectNewNodes() const { return m_AutoSelectNewNodes; } void QmitkSingleNodeSelectionWidget::SetAutoSelectNewNodes(bool autoSelect) { m_AutoSelectNewNodes = autoSelect; this->OnNodeAddedToStorage(nullptr); } diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.h b/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.h index 27635231ca..3c4571eb93 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.h +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkSingleNodeSelectionWidget.h @@ -1,80 +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_SINGLE_NODE_SELECTION_WIDGET_H #define QMITK_SINGLE_NODE_SELECTION_WIDGET_H #include #include #include #include "org_mitk_gui_qt_common_Export.h" #include "ui_QmitkSingleNodeSelectionWidget.h" #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. +* @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. */ class MITK_QT_COMMON 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.*/ 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 OnNodeAddedToStorage(const mitk::DataNode* node) override; /** 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_AutoSelectNewNodes; Ui_QmitkSingleNodeSelectionWidget m_Controls; }; -#endif // QmitkSingleNodeSelectionWidget_H +#endif // QMITK_SINGLE_NODE_SELECTION_WIDGET_H diff --git a/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestControls.ui b/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestControls.ui index 52adcb5c86..52a3edab6c 100644 --- a/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestControls.ui +++ b/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestControls.ui @@ -1,200 +1,210 @@ QmitkDataStorageViewerTestControls 0 0 945 456 0 0 Data storage viewer test + + + + + + - + Set as selection provider - - + + + + Set as selection provider + + - - + + - Only valid nodes + Set as selection listener Set as selection listener - - - - Only valid nodes + + + + + 0 + 0 + + + + + 0 + 40 + - - + + + + + - Allow only images + Set as selection provider - - + + - Is Optional + Set as selection provider - - + + - Set as selection provider + Set as selection listner - - + + - Is Enabled - - - true + Set as selection listner - - + + - Set as selection provider + Only valid nodes - - + + - Set as selection listener + Only valid nodes - - + + - Allow only uneven selection count -(using check funcktion feature) + Allow only images - - + + - Set as selection listner + Allow only images (using NodePredicate feature and general invalid message) - - + + - Is Optional + Allow only uneven selection count (using check funcktion feature) - - - - - + + - Set as selection listner + Is Optional - - - - - 0 - 0 - - - - - 0 - 40 - + + + + Is Optional - - + + Is Enabled true - - + + - Allow only images -(using NodePredicate feature and general invalid message) + Is Enabled - - - - - - - - - Set as selection provider + + true Auto select node + + QmitkDataStorageListInspector + QWidget +
QmitkDataStorageListInspector.h
+ 1 +
+ + QmitkDataStorageTreeInspector + QWidget +
QmitkDataStorageTreeInspector.h
+ 1 +
QmitkSingleNodeSelectionWidget QWidget
QmitkSingleNodeSelectionWidget.h
1
QmitkMultiNodeSelectionWidget QWidget
QmitkMultiNodeSelectionWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.cpp b/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.cpp index 1ce16e51e0..a3708f6407 100644 --- a/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.cpp +++ b/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.cpp @@ -1,277 +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. ============================================================================*/ // data storage viewer test plugin #include "QmitkDataStorageViewerTestView.h" #include "mitkNodePredicateDataType.h" // berry #include -// qt -#include - const std::string QmitkDataStorageViewerTestView::VIEW_ID = "org.mitk.views.datastorageviewertest"; void QmitkDataStorageViewerTestView::SetFocus() { // nothing here } void QmitkDataStorageViewerTestView::CreateQtPartControl(QWidget* parent) { // create GUI widgets m_Controls.setupUi(parent); - m_DataStorageDefaultListModel = new QmitkDataStorageDefaultListModel(this); - m_DataStorageDefaultListModel->SetDataStorage(GetDataStorage()); - m_Controls.selectionListView->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_Controls.selectionListView->setSelectionBehavior(QAbstractItemView::SelectRows); - m_Controls.selectionListView->setAlternatingRowColors(true); - m_Controls.selectionListView->setModel(m_DataStorageDefaultListModel); - - m_DataStorageDefaultListModel2 = new QmitkDataStorageDefaultListModel(this); - m_DataStorageDefaultListModel2->SetDataStorage(GetDataStorage()); - m_Controls.selectionListView2->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_Controls.selectionListView2->setSelectionBehavior(QAbstractItemView::SelectRows); - m_Controls.selectionListView2->setAlternatingRowColors(true); - m_Controls.selectionListView2->setModel(m_DataStorageDefaultListModel2); + m_Controls.listInspector->SetDataStorage(GetDataStorage()); + m_Controls.treeInspector->SetDataStorage(GetDataStorage()); m_Controls.singleSlot->SetDataStorage(GetDataStorage()); m_Controls.singleSlot->SetEmptyInfo(QStringLiteral("EmptyInfo: Set this to display info in empty state")); m_Controls.singleSlot->SetInvalidInfo(QStringLiteral("InvalidInfo: is displayed for invalid states")); m_Controls.singleSlot->SetPopUpTitel(QStringLiteral("This is the definable caption. Choose your data now!")); m_Controls.singleSlot->SetPopUpHint(QStringLiteral("I am an optional hint, that can be set by the developer

If not set the widget is invisible.")); m_Controls.multiSlot->SetDataStorage(GetDataStorage()); m_Controls.multiSlot->SetEmptyInfo(QStringLiteral("EmptyInfo: Set this to display info in empty state")); m_Controls.multiSlot->SetInvalidInfo(QStringLiteral("InvalidInfo: is displayed for invalid states")); m_Controls.multiSlot->SetPopUpTitel(QStringLiteral("This is the definable caption. Choose your data now!")); m_Controls.multiSlot->SetPopUpHint(QStringLiteral("I am an optional hint, that can be set by the developer

If not set the widget is invisible.")); - m_ModelViewSelectionConnector = std::make_unique(); + m_ModelViewSelectionConnector1 = std::make_unique(); try { - m_ModelViewSelectionConnector->SetView(m_Controls.selectionListView); + m_ModelViewSelectionConnector1->SetView(m_Controls.listInspector->GetView()); } catch (mitk::Exception& e) { mitkReThrow(e) << "Cannot connect the model-view pair signals and slots."; } - m_SelectionServiceConnector = std::make_unique(); + m_SelectionServiceConnector1 = std::make_unique(); m_ModelViewSelectionConnector2 = std::make_unique(); try { - m_ModelViewSelectionConnector2->SetView(m_Controls.selectionListView2); + m_ModelViewSelectionConnector2->SetView(m_Controls.treeInspector->GetView()); } catch (mitk::Exception& e) { mitkReThrow(e) << "Cannot connect the model-view pair signals and slots."; } m_SelectionServiceConnector2 = std::make_unique(); m_SelectionServiceConnector3 = std::make_unique(); m_SelectionServiceConnector4 = std::make_unique(); - connect(m_Controls.selectionProviderCheckBox, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionProvider1(bool))); - connect(m_Controls.selectionProviderCheckBox2, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionProvider2(bool))); - - connect(m_Controls.selectionListenerCheckBox, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionListener1(bool))); - connect(m_Controls.selectionListenerCheckBox2, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionListener2(bool))); - - connect(m_Controls.selectionProviderCheckBox3, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionProvider3(bool))); - connect(m_Controls.selectionListenerCheckBox3, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionListener3(bool))); - - connect(m_Controls.checkOnlyVisible, SIGNAL(toggled(bool)), m_Controls.singleSlot, SLOT(SetSelectOnlyVisibleNodes(bool))); - connect(m_Controls.checkOptional, SIGNAL(toggled(bool)), m_Controls.singleSlot, SLOT(SetSelectionIsOptional(bool))); - connect(m_Controls.checkAuto, SIGNAL(toggled(bool)), m_Controls.singleSlot, SLOT(SetAutoSelectNewNodes(bool))); - connect(m_Controls.checkOnlyImages, SIGNAL(toggled(bool)), this, SLOT(OnOnlyImages(bool))); - connect(m_Controls.checkEnabled, SIGNAL(toggled(bool)), m_Controls.singleSlot, SLOT(setEnabled(bool))); - - connect(m_Controls.selectionProviderCheckBox4, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionProvider4(bool))); - connect(m_Controls.selectionListenerCheckBox4, SIGNAL(toggled(bool)), this, SLOT(SetAsSelectionListener4(bool))); - - connect(m_Controls.checkOnlyVisible_2, SIGNAL(toggled(bool)), m_Controls.multiSlot, SLOT(SetSelectOnlyVisibleNodes(bool))); - connect(m_Controls.checkOptional_2, SIGNAL(toggled(bool)), m_Controls.multiSlot, SLOT(SetSelectionIsOptional(bool))); - connect(m_Controls.checkOnlyImages_2, SIGNAL(toggled(bool)), this, SLOT(OnOnlyImages2(bool))); - connect(m_Controls.checkOnlyUneven, SIGNAL(toggled(bool)), this, SLOT(OnOnlyUneven(bool))); - connect(m_Controls.checkEnabled_2, SIGNAL(toggled(bool)), m_Controls.multiSlot, SLOT(setEnabled(bool))); + connect(m_Controls.selectionProviderCheckBox1, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionProvider1); + connect(m_Controls.selectionProviderCheckBox2, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionProvider2); + + connect(m_Controls.selectionListenerCheckBox1, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionListener1); + connect(m_Controls.selectionListenerCheckBox2, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionListener2); + + connect(m_Controls.selectionProviderCheckBox3, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionProvider3); + connect(m_Controls.selectionListenerCheckBox3, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionListener3); + + connect(m_Controls.checkOnlyVisible1, &QCheckBox::toggled, + m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetSelectOnlyVisibleNodes); + connect(m_Controls.checkOnlyImages1, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::OnOnlyImages1); + connect(m_Controls.checkOptional1, &QCheckBox::toggled, + m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetSelectionIsOptional); + connect(m_Controls.checkEnabled1, &QCheckBox::toggled, + m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::setEnabled); + connect(m_Controls.checkAuto, &QCheckBox::toggled, + m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetAutoSelectNewNodes); + + connect(m_Controls.selectionProviderCheckBox4, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionProvider4); + connect(m_Controls.selectionListenerCheckBox4, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::SetAsSelectionListener4); + + connect(m_Controls.checkOnlyVisible2, &QCheckBox::toggled, + m_Controls.multiSlot, &QmitkMultiNodeSelectionWidget::SetSelectOnlyVisibleNodes); + connect(m_Controls.checkOnlyImages2, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::OnOnlyImages2); + connect(m_Controls.checkOnlyUneven, &QCheckBox::toggled, + this, &QmitkDataStorageViewerTestView::OnOnlyUneven); + connect(m_Controls.checkOptional2, &QCheckBox::toggled, + m_Controls.multiSlot, &QmitkMultiNodeSelectionWidget::SetSelectionIsOptional); + connect(m_Controls.checkEnabled2, &QCheckBox::toggled, + m_Controls.multiSlot, &QmitkSingleNodeSelectionWidget::setEnabled); } void QmitkDataStorageViewerTestView::SetAsSelectionProvider1(bool checked) { if (checked) { - m_SelectionServiceConnector->SetAsSelectionProvider(GetSite()->GetSelectionProvider().Cast().GetPointer()); - connect(m_ModelViewSelectionConnector.get(), SIGNAL(CurrentSelectionChanged(QList)), m_SelectionServiceConnector.get(), SLOT(ChangeServiceSelection(QList))); + m_SelectionServiceConnector1->SetAsSelectionProvider(GetSite()->GetSelectionProvider().Cast().GetPointer()); + connect(m_ModelViewSelectionConnector1.get(), &QmitkModelViewSelectionConnector::CurrentSelectionChanged, + m_SelectionServiceConnector1.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } else { - m_SelectionServiceConnector->RemoveAsSelectionProvider(); - disconnect(m_ModelViewSelectionConnector.get(), SIGNAL(CurrentSelectionChanged(QList)), m_SelectionServiceConnector.get(), SLOT(ChangeServiceSelection(QList))); + m_SelectionServiceConnector1->RemoveAsSelectionProvider(); + disconnect(m_ModelViewSelectionConnector1.get(), &QmitkModelViewSelectionConnector::CurrentSelectionChanged, + m_SelectionServiceConnector1.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } } void QmitkDataStorageViewerTestView::SetAsSelectionListener1(bool checked) { if (checked) { - m_SelectionServiceConnector->AddPostSelectionListener(GetSite()->GetWorkbenchWindow()->GetSelectionService()); - connect(m_SelectionServiceConnector.get(), SIGNAL(ServiceSelectionChanged(QList)), m_ModelViewSelectionConnector.get(), SLOT(SetCurrentSelection(QList))); + m_SelectionServiceConnector1->AddPostSelectionListener(GetSite()->GetWorkbenchWindow()->GetSelectionService()); + connect(m_SelectionServiceConnector1.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_ModelViewSelectionConnector1.get(), &QmitkModelViewSelectionConnector::SetCurrentSelection); } else { - m_SelectionServiceConnector->RemovePostSelectionListener(); - disconnect(m_SelectionServiceConnector.get(), SIGNAL(ServiceSelectionChanged(QList)), m_ModelViewSelectionConnector.get(), SLOT(SetCurrentSelection(QList))); + m_SelectionServiceConnector1->RemovePostSelectionListener(); + disconnect(m_SelectionServiceConnector1.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_ModelViewSelectionConnector1.get(), &QmitkModelViewSelectionConnector::SetCurrentSelection); } } void QmitkDataStorageViewerTestView::SetAsSelectionProvider2(bool checked) { if (checked) { m_SelectionServiceConnector2->SetAsSelectionProvider(GetSite()->GetSelectionProvider().Cast().GetPointer()); - connect(m_ModelViewSelectionConnector2.get(), SIGNAL(CurrentSelectionChanged(QList)), m_SelectionServiceConnector2.get(), SLOT(ChangeServiceSelection(QList))); + connect(m_ModelViewSelectionConnector2.get(), &QmitkModelViewSelectionConnector::CurrentSelectionChanged, + m_SelectionServiceConnector2.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } else { m_SelectionServiceConnector2->RemoveAsSelectionProvider(); - disconnect(m_ModelViewSelectionConnector2.get(), SIGNAL(CurrentSelectionChanged(QList)), m_SelectionServiceConnector2.get(), SLOT(ChangeServiceSelection(QList))); + disconnect(m_ModelViewSelectionConnector2.get(), &QmitkModelViewSelectionConnector::CurrentSelectionChanged, + m_SelectionServiceConnector2.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } } void QmitkDataStorageViewerTestView::SetAsSelectionListener2(bool checked) { if (checked) { m_SelectionServiceConnector2->AddPostSelectionListener(GetSite()->GetWorkbenchWindow()->GetSelectionService()); - connect(m_SelectionServiceConnector2.get(), SIGNAL(ServiceSelectionChanged(QList)), m_ModelViewSelectionConnector2.get(), SLOT(SetCurrentSelection(QList))); + connect(m_SelectionServiceConnector2.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_ModelViewSelectionConnector2.get(), &QmitkModelViewSelectionConnector::SetCurrentSelection); } else { m_SelectionServiceConnector2->RemovePostSelectionListener(); - disconnect(m_SelectionServiceConnector2.get(), SIGNAL(ServiceSelectionChanged(QList)), m_ModelViewSelectionConnector2.get(), SLOT(SetCurrentSelection(QList))); + disconnect(m_SelectionServiceConnector2.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_ModelViewSelectionConnector2.get(), &QmitkModelViewSelectionConnector::SetCurrentSelection); } } void QmitkDataStorageViewerTestView::SetAsSelectionProvider3(bool checked) { if (checked) { - m_SelectionServiceConnector3->SetAsSelectionProvider(GetSite()->GetSelectionProvider().Cast().GetPointer()); - connect(m_Controls.singleSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); + connect(m_Controls.singleSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, + m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } else { m_SelectionServiceConnector3->RemoveAsSelectionProvider(); - disconnect(m_Controls.singleSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); + disconnect(m_Controls.singleSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, + m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } } void QmitkDataStorageViewerTestView::SetAsSelectionListener3(bool checked) { if (checked) { m_SelectionServiceConnector3->AddPostSelectionListener(GetSite()->GetWorkbenchWindow()->GetSelectionService()); - connect(m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection); + connect(m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection); } else { m_SelectionServiceConnector3->RemovePostSelectionListener(); - disconnect(m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection); + disconnect(m_SelectionServiceConnector3.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection); } } void QmitkDataStorageViewerTestView::SetAsSelectionProvider4(bool checked) { if (checked) { m_SelectionServiceConnector4->SetAsSelectionProvider(GetSite()->GetSelectionProvider().Cast().GetPointer()); - connect(m_Controls.multiSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); + connect(m_Controls.multiSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, + m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } else { m_SelectionServiceConnector4->RemoveAsSelectionProvider(); - disconnect(m_Controls.multiSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); + disconnect(m_Controls.multiSlot, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, + m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ChangeServiceSelection); } } void QmitkDataStorageViewerTestView::SetAsSelectionListener4(bool checked) { if (checked) { m_SelectionServiceConnector4->AddPostSelectionListener(GetSite()->GetWorkbenchWindow()->GetSelectionService()); - connect(m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, m_Controls.multiSlot, &QmitkMultiNodeSelectionWidget::SetCurrentSelection); + connect(m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_Controls.multiSlot, &QmitkMultiNodeSelectionWidget::SetCurrentSelection); } else { m_SelectionServiceConnector4->RemovePostSelectionListener(); - disconnect(m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, m_Controls.multiSlot, &QmitkMultiNodeSelectionWidget::SetCurrentSelection); + disconnect(m_SelectionServiceConnector4.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, + m_Controls.multiSlot, &QmitkMultiNodeSelectionWidget::SetCurrentSelection); } } -void QmitkDataStorageViewerTestView::OnOnlyImages(bool checked) +void QmitkDataStorageViewerTestView::OnOnlyImages1(bool checked) { if (checked) { m_Controls.singleSlot->SetNodePredicate(mitk::NodePredicateDataType::New("Image")); } else { m_Controls.singleSlot->SetNodePredicate(nullptr); } -}; +} void QmitkDataStorageViewerTestView::OnOnlyImages2(bool checked) { if (checked) { m_Controls.multiSlot->SetNodePredicate(mitk::NodePredicateDataType::New("Image")); m_Controls.multiSlot->SetInvalidInfo(QStringLiteral("InvalidInfo: is displayed for invalid states. Only images allowed!")); } else { m_Controls.multiSlot->SetNodePredicate(nullptr); m_Controls.multiSlot->SetInvalidInfo(QStringLiteral("InvalidInfo: is displayed for invalid states")); } -}; +} void QmitkDataStorageViewerTestView::OnOnlyUneven(bool checked) { if (checked) { auto checkFunction = [](const QmitkMultiNodeSelectionWidget::NodeList & nodes) { if (!(nodes.size() % 2)) { std::stringstream ss; ss << "

Invalid selection.

The number of selected nodes must be uneven! the current number is " << nodes.size() << ".

"; return ss.str(); } return std::string(); }; m_Controls.multiSlot->SetSelectionCheckFunction(checkFunction); } else { auto checkFunction = [](const QmitkMultiNodeSelectionWidget::NodeList & /*nodes*/) { return std::string(); }; m_Controls.multiSlot->SetSelectionCheckFunction(checkFunction); } -}; +} diff --git a/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.h b/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.h index ff4465af2e..7bdd9390de 100644 --- a/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.h +++ b/Plugins/org.mitk.gui.qt.datastorageviewertest/src/internal/QmitkDataStorageViewerTestView.h @@ -1,74 +1,69 @@ /*============================================================================ 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 QMITKDATASTORAGEVIEWERTESTVIEW_H #define QMITKDATASTORAGEVIEWERTESTVIEW_H +// data storage viewer test plugin +#include "ui_QmitkDataStorageViewerTestControls.h" + // mitk gui qt common plugin #include #include "QmitkModelViewSelectionConnector.h" #include "QmitkSelectionServiceConnector.h" -// data storage viewer test plugin -#include "ui_QmitkDataStorageViewerTestControls.h" - -// qt widgets module -#include "QmitkDataStorageDefaultListModel.h" - /** * @brief DataStorageViewerTestView */ class QmitkDataStorageViewerTestView : public QmitkAbstractView { Q_OBJECT public: static const std::string VIEW_ID; protected: void SetFocus() override; void CreateQtPartControl(QWidget* parent) override; private Q_SLOTS: void SetAsSelectionProvider1(bool checked); void SetAsSelectionProvider2(bool checked); void SetAsSelectionProvider3(bool checked); void SetAsSelectionProvider4(bool checked); void SetAsSelectionListener1(bool checked); void SetAsSelectionListener2(bool checked); void SetAsSelectionListener3(bool checked); void SetAsSelectionListener4(bool checked); - void OnOnlyImages(bool checked); + void OnOnlyImages1(bool checked); void OnOnlyImages2(bool checked); void OnOnlyUneven(bool checked); private: Ui::QmitkDataStorageViewerTestControls m_Controls; - QmitkDataStorageDefaultListModel* m_DataStorageDefaultListModel; - QmitkDataStorageDefaultListModel* m_DataStorageDefaultListModel2; - std::unique_ptr m_ModelViewSelectionConnector; - std::unique_ptr m_SelectionServiceConnector; + std::unique_ptr m_ModelViewSelectionConnector1; + std::unique_ptr m_SelectionServiceConnector1; std::unique_ptr m_ModelViewSelectionConnector2; std::unique_ptr m_SelectionServiceConnector2; std::unique_ptr m_SelectionServiceConnector3; std::unique_ptr m_SelectionServiceConnector4; }; #endif // QMITKDATASTORAGEVIEWERTESTVIEW_H