From 54628b51168c3048b959fa69defba8ec70a45de0 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Tue, 23 Nov 2021 11:58:49 +0100 Subject: [PATCH] delete obsolete code for generic UI creation --- GUI/Model/Component/ComponentProxyModel.cpp | 189 --------- GUI/Model/Component/ComponentProxyModel.h | 71 ---- .../Component/ComponentProxyStrategy.cpp | 187 --------- GUI/Model/Component/ComponentProxyStrategy.h | 42 -- GUI/Model/Component/ComponentUtils.cpp | 72 ---- GUI/Model/Component/ComponentUtils.h | 35 -- GUI/Model/Component/ProxyModelStrategy.cpp | 83 ---- GUI/Model/Component/ProxyModelStrategy.h | 62 --- GUI/View/PropertyEditor/ComponentTreeView.cpp | 146 ------- GUI/View/PropertyEditor/ComponentTreeView.h | 57 --- Tests/Unit/GUI/TestComponentProxyModel.cpp | 381 ------------------ Tests/Unit/GUI/TestComponentUtils.cpp | 50 --- Tests/Unit/GUI/TestProxyModelStrategy.cpp | 178 -------- 13 files changed, 1553 deletions(-) delete mode 100644 GUI/Model/Component/ComponentProxyModel.cpp delete mode 100644 GUI/Model/Component/ComponentProxyModel.h delete mode 100644 GUI/Model/Component/ComponentProxyStrategy.cpp delete mode 100644 GUI/Model/Component/ComponentProxyStrategy.h delete mode 100644 GUI/Model/Component/ComponentUtils.cpp delete mode 100644 GUI/Model/Component/ComponentUtils.h delete mode 100644 GUI/Model/Component/ProxyModelStrategy.cpp delete mode 100644 GUI/Model/Component/ProxyModelStrategy.h delete mode 100644 GUI/View/PropertyEditor/ComponentTreeView.cpp delete mode 100644 GUI/View/PropertyEditor/ComponentTreeView.h delete mode 100644 Tests/Unit/GUI/TestComponentProxyModel.cpp delete mode 100644 Tests/Unit/GUI/TestComponentUtils.cpp delete mode 100644 Tests/Unit/GUI/TestProxyModelStrategy.cpp diff --git a/GUI/Model/Component/ComponentProxyModel.cpp b/GUI/Model/Component/ComponentProxyModel.cpp deleted file mode 100644 index 7a210cfd060..00000000000 --- a/GUI/Model/Component/ComponentProxyModel.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ComponentProxyModel.cpp -//! @brief Implements class ComponentProxyModel -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#include "GUI/Model/Component/ComponentProxyModel.h" -#include "GUI/Model/Component/ComponentProxyStrategy.h" -#include "GUI/Model/Group/GroupItem.h" -#include "GUI/Model/Session/SessionModel.h" -#include <QSet> -#include <functional> - -ComponentProxyModel::ComponentProxyModel(QObject* parent) - : QAbstractProxyModel(parent) - , m_model(nullptr) - // , m_proxyStrategy(new IndentityProxyStrategy) - , m_proxyStrategy(new ComponentProxyStrategy) -{ -} - -void ComponentProxyModel::setSessionModel(SessionModel* model) -{ - beginResetModel(); - - if (sourceModel()) { - disconnect(sourceModel(), &QAbstractItemModel::dataChanged, this, - &ComponentProxyModel::sourceDataChanged); - disconnect(sourceModel(), &QAbstractItemModel::rowsInserted, this, - &ComponentProxyModel::sourceRowsInserted); - disconnect(sourceModel(), &QAbstractItemModel::rowsRemoved, this, - &ComponentProxyModel::sourceRowsRemoved); - } - - QAbstractProxyModel::setSourceModel(model); - - if (sourceModel()) { - connect(sourceModel(), &QAbstractItemModel::dataChanged, this, - &ComponentProxyModel::sourceDataChanged); - connect(sourceModel(), &QAbstractItemModel::rowsInserted, this, - &ComponentProxyModel::sourceRowsInserted); - connect(sourceModel(), &QAbstractItemModel::rowsRemoved, this, - &ComponentProxyModel::sourceRowsRemoved); - } - - endResetModel(); - - m_model = model; - buildModelMap(); -} - -void ComponentProxyModel::setRootIndex(const QModelIndex& sourceRootIndex) -{ - m_proxyStrategy->setRootIndex(sourceRootIndex); - buildModelMap(); -} - -void ComponentProxyModel::setProxyStrategy(ProxyModelStrategy* strategy) -{ - m_proxyStrategy.reset(strategy); - buildModelMap(); -} - -QModelIndex ComponentProxyModel::mapToSource(const QModelIndex& proxyIndex) const -{ - if (!proxyIndex.isValid()) - return QModelIndex(); - - return m_proxyStrategy->sourceToProxy().key(proxyIndex); -} - -QModelIndex ComponentProxyModel::mapFromSource(const QModelIndex& sourceIndex) const -{ - if (!sourceIndex.isValid()) - return QModelIndex(); - - return m_proxyStrategy->sourceToProxy().value(sourceIndex); -} - -QModelIndex ComponentProxyModel::index(int row, int column, const QModelIndex& parent) const -{ - QModelIndex sourceParent; - if (parent.isValid()) - sourceParent = mapToSource(parent); - - QMapIterator<QPersistentModelIndex, QPersistentModelIndex> it( - m_proxyStrategy->proxySourceParent()); - while (it.hasNext()) { - it.next(); - if (it.value() == sourceParent && it.key().row() == row && it.key().column() == column) - return it.key(); - } - return QModelIndex(); -} - -QModelIndex ComponentProxyModel::parent(const QModelIndex& child) const -{ - QModelIndex sourceParent = m_proxyStrategy->proxySourceParent().value(child); - if (sourceParent.isValid()) - return mapFromSource(sourceParent); - - return QModelIndex(); -} - -int ComponentProxyModel::rowCount(const QModelIndex& parent) const -{ - QModelIndex sourceParent; - if (parent.isValid()) - sourceParent = mapToSource(parent); - QMapIterator<QPersistentModelIndex, QPersistentModelIndex> it( - m_proxyStrategy->proxySourceParent()); - - QSet<int> rows; - while (it.hasNext()) { - it.next(); - if (it.value() == sourceParent) - rows.insert(it.key().row()); - } - return rows.size(); -} - -int ComponentProxyModel::columnCount(const QModelIndex& parent) const -{ - if (parent.isValid() && parent.column() != 0) - return 0; - return SessionFlags::MAX_COLUMNS; -} - -bool ComponentProxyModel::hasChildren(const QModelIndex& parent) const -{ - QModelIndex source_parent = mapToSource(parent); - if (parent.isValid() && !source_parent.isValid()) - return false; - - return rowCount(parent) != 0; -} - -void ComponentProxyModel::sourceDataChanged(const QModelIndex& topLeft, - const QModelIndex& bottomRight, - const QVector<int>& roles) -{ - ASSERT(topLeft.isValid() ? topLeft.model() == sourceModel() : true); - ASSERT(bottomRight.isValid() ? bottomRight.model() == sourceModel() : true); - - if (SessionItem* item = m_model->itemForIndex(topLeft)) { - if (item->hasModelType<GroupItem>()) - updateModelMap(); - } - dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight), roles); -} - -void ComponentProxyModel::sourceRowsInserted(const QModelIndex& parent, int start, int end) -{ - Q_UNUSED(parent); - Q_UNUSED(start); - Q_UNUSED(end); - buildModelMap(); -} - -void ComponentProxyModel::sourceRowsRemoved(const QModelIndex& parent, int start, int end) -{ - Q_UNUSED(parent); - Q_UNUSED(start); - Q_UNUSED(end); - buildModelMap(); -} - -//! Main method to build the map of persistent indeses. - -void ComponentProxyModel::buildModelMap() -{ - if (!m_model) - return; - m_proxyStrategy->buildModelMap(m_model, this); - layoutChanged(); -} - -void ComponentProxyModel::updateModelMap() -{ - m_proxyStrategy->onDataChanged(m_model, this); -} diff --git a/GUI/Model/Component/ComponentProxyModel.h b/GUI/Model/Component/ComponentProxyModel.h deleted file mode 100644 index 24afc194b90..00000000000 --- a/GUI/Model/Component/ComponentProxyModel.h +++ /dev/null @@ -1,71 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ComponentProxyModel.h -//! @brief Defines class ComponentProxyModel -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#ifndef BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTPROXYMODEL_H -#define BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTPROXYMODEL_H - -#include "GUI/Model/Component/ProxyModelStrategy.h" -#include <QAbstractProxyModel> -#include <QMap> -#include <QPersistentModelIndex> -#include <memory> - -class SessionModel; -class ProxyModelStrategy; - -//! Proxy model to adjust SessionModel for component editor -//! -//! The model hides all SessionItems which are not PropertyItems. -//! The model hides GroupPropertyItem children and shows grand-children of currently selected item -//! one level up. - -class ComponentProxyModel : public QAbstractProxyModel { - Q_OBJECT - - friend class ProxyModelStrategy; - -public: - ComponentProxyModel(QObject* parent = nullptr); - - void setSessionModel(SessionModel* model); - - void setRootIndex(const QModelIndex& sourceRootIndex); - - void setProxyStrategy(ProxyModelStrategy* strategy); - - QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; - QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; - - QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override; - QModelIndex parent(const QModelIndex& child) const override; - int rowCount(const QModelIndex& parent = {}) const override; - int columnCount(const QModelIndex& parent = {}) const override; - - bool hasChildren(const QModelIndex& parent) const override; - -private slots: - void sourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, - const QVector<int>& roles = {}); - void sourceRowsInserted(const QModelIndex& parent, int start, int end); - void sourceRowsRemoved(const QModelIndex& parent, int start, int end); - -private: - void buildModelMap(); - void updateModelMap(); - - SessionModel* m_model; - std::unique_ptr<ProxyModelStrategy> m_proxyStrategy; -}; - -#endif // BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTPROXYMODEL_H diff --git a/GUI/Model/Component/ComponentProxyStrategy.cpp b/GUI/Model/Component/ComponentProxyStrategy.cpp deleted file mode 100644 index 250f43f028c..00000000000 --- a/GUI/Model/Component/ComponentProxyStrategy.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ComponentProxyStrategy.cpp -//! @brief Implements class ComponentProxyStrategy -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#include "GUI/Model/Component/ComponentProxyStrategy.h" -#include "GUI/Model/Component/ComponentProxyModel.h" -#include "GUI/Model/Component/ComponentUtils.h" -#include "GUI/Model/Group/GroupItem.h" -#include "GUI/Model/Session/ModelPath.h" -#include "GUI/Model/Session/SessionModel.h" - -void ComponentProxyStrategy::onDataChanged(SessionModel* source, ComponentProxyModel* proxy) -{ - buildModelMap(source, proxy); - proxy->layoutChanged(); -} - -bool ComponentProxyStrategy::processSourceIndex(const QModelIndex& index) -{ - QPersistentModelIndex sourceIndex = {index}; - - SessionItem* item = m_source->itemForIndex(index); - - QString tag; - if (item->parent()) - tag = item->parent()->tagFromItem(item); - - if (!isPropertyRelated(item)) - return false; // not going to visit non-property items - - if (isNewRootItem(item)) { - processRootItem(item, sourceIndex); - - } else if (isSubGroup(item)) { - processSubGroupItem(item, sourceIndex); - - } else if (isGroupChildren(item)) { - processGroupItem(item, sourceIndex); - - } else { - processDefaultItem(item, sourceIndex); - } - - return true; -} - -//! Returns true if item is property related to exclude top level items (ParticleLayout, Particle -//! etc from the tree). - -bool ComponentProxyStrategy::isPropertyRelated(SessionItem* item) -{ - static const QStringList& propertyRelated = GUI::Model::ComponentUtils::propertyRelatedTypes(); - - if (m_sourceRootIndex.isValid() && item->parent()->index() == m_sourceRootIndex - && !item->parent()->hasModelType<GroupItem>()) - return propertyRelated.contains(item->modelType()); - - return true; -} - -//! Returns true if item should become new root item. -//! This is used when we want to show single item (Layer, Particle) on top of the tree. - -bool ComponentProxyStrategy::isNewRootItem(SessionItem* item) -{ - return item->index() == m_sourceRootIndex; -} - -//! Makes SessionItem to become the only one item in a tree. - -void ComponentProxyStrategy::processRootItem(SessionItem* item, - const QPersistentModelIndex& sourceIndex) -{ - const int nrows = 0; // invisible root item will contain only single item - QPersistentModelIndex proxyIndex = createProxyIndex(nrows, sourceIndex.column(), item); - m_sourceToProxy.insert(sourceIndex, proxyIndex); - m_proxySourceParent.insert(proxyIndex, QModelIndex()); // new parent will be root -} - -//! Returns true if item is a group property which in turn is inside of another group property. - -bool ComponentProxyStrategy::isSubGroup(SessionItem* item) -{ - const SessionItem* ancestor = GUI::Model::Path::ancestor(item->parent(), GroupItem::M_TYPE); - return item->hasModelType<GroupItem>() && ancestor && ancestor->hasModelType<GroupItem>(); -} - -//! Returns true if item is a children/grandchildrent of some group item. - -bool ComponentProxyStrategy::isGroupChildren(SessionItem* item) -{ - if (item->parent() && item->parent()->hasModelType<GroupItem>()) - return true; - - if (const SessionItem* ancestor = GUI::Model::Path::ancestor(item, GroupItem::M_TYPE)) { - if (ancestor != item) - return true; - } - - return false; -} - -//! All properties of current item of group item - -void ComponentProxyStrategy::processGroupItem(SessionItem* item, - const QPersistentModelIndex& sourceIndex) -{ - if (const SessionItem* ancestor = GUI::Model::Path::ancestor(item, GroupItem::M_TYPE)) { - if (ancestor == item) - return; - - const auto* groupItem = dynamic_cast<const GroupItem*>(ancestor); - if (item->parent() == groupItem->currentItem()) { - QPersistentModelIndex proxyIndex = createProxyIndex( - parentVisibleRow(*item), sourceIndex.column(), sourceIndex.internalPointer()); - - m_sourceToProxy.insert(sourceIndex, proxyIndex); - m_proxySourceParent.insert(proxyIndex, groupItem->index()); - } - } -} - -//! Process group property which is inside of other group property. - -void ComponentProxyStrategy::processSubGroupItem(SessionItem* item, - const QPersistentModelIndex& sourceIndex) -{ - if (const SessionItem* ancestor = - GUI::Model::Path::ancestor(item->parent(), GroupItem::M_TYPE)) { - const auto* groupItem = dynamic_cast<const GroupItem*>(ancestor); - - if (item->parent() == groupItem->currentItem()) { - QPersistentModelIndex proxyIndex = createProxyIndex( - parentVisibleRow(*item), sourceIndex.column(), sourceIndex.internalPointer()); - - m_sourceToProxy.insert(sourceIndex, proxyIndex); - m_proxySourceParent.insert(proxyIndex, groupItem->index()); - } - } -} - -void ComponentProxyStrategy::processDefaultItem(SessionItem* item, - const QPersistentModelIndex& sourceIndex) -{ - ASSERT(item); - if (!item->isVisible()) - return; - - QPersistentModelIndex proxyIndex = - createProxyIndex(parentVisibleRow(*item), sourceIndex.column(), item); - - m_sourceToProxy.insert(sourceIndex, proxyIndex); - - QPersistentModelIndex sourceParent; - if (sourceIndex.parent().isValid()) - sourceParent = sourceIndex.parent(); - - m_proxySourceParent.insert(proxyIndex, sourceParent); -} - -int ComponentProxyStrategy::parentVisibleRow(const SessionItem& item) -{ - int result(-1); - - if (!item.parent() || !item.isVisible()) - return result; - - for (auto* child : item.parent()->children()) { - if (child->isVisible() && isPropertyRelated(child)) - ++result; - - if (&item == child) - return result; - } - - return result; -} diff --git a/GUI/Model/Component/ComponentProxyStrategy.h b/GUI/Model/Component/ComponentProxyStrategy.h deleted file mode 100644 index 52cafeb8b41..00000000000 --- a/GUI/Model/Component/ComponentProxyStrategy.h +++ /dev/null @@ -1,42 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ComponentProxyStrategy.h -//! @brief Defines class ComponentProxyStrategy -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#ifndef BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTPROXYSTRATEGY_H -#define BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTPROXYSTRATEGY_H - -#include "GUI/Model/Component/ProxyModelStrategy.h" - -//! Strategy for ComponentProxyModel which hides extra level of GroupProperty. - -class ComponentProxyStrategy : public ProxyModelStrategy { -public: - void onDataChanged(SessionModel* source, ComponentProxyModel* proxy) override; - -protected: - bool processSourceIndex(const QModelIndex& index) override; - -private: - bool isPropertyRelated(SessionItem* item); - bool isNewRootItem(SessionItem* item); - void processRootItem(SessionItem* item, const QPersistentModelIndex& sourceIndex); - bool isSubGroup(SessionItem* item); - bool isGroupChildren(SessionItem* item); - void processGroupItem(SessionItem* item, const QPersistentModelIndex& sourceIndex); - void processSubGroupItem(SessionItem* item, const QPersistentModelIndex& sourceIndex); - void processDefaultItem(SessionItem* item, const QPersistentModelIndex& sourceIndex); - - int parentVisibleRow(const SessionItem& item); -}; - -#endif // BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTPROXYSTRATEGY_H diff --git a/GUI/Model/Component/ComponentUtils.cpp b/GUI/Model/Component/ComponentUtils.cpp deleted file mode 100644 index 07e908e7183..00000000000 --- a/GUI/Model/Component/ComponentUtils.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ComponentUtils.cpp -//! @brief Implements ComponentUtils namespace -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#include "GUI/Model/Component/ComponentUtils.h" -#include "GUI/Model/Data/AxesItems.h" -#include "GUI/Model/Group/GroupItem.h" -#include "GUI/Model/Group/PropertyItem.h" -#include "GUI/Model/Material/MaterialDataItems.h" -#include "GUI/Model/Types/VectorItem.h" - -namespace { - -QList<const SessionItem*> groupItems(const GroupItem& item) -{ - QList<const SessionItem*> result; - for (auto* grandchild : item.children()) - if (grandchild->isVisible()) - result += GUI::Model::ComponentUtils::componentItems(*grandchild); - return result; -} - -} // namespace - - -const QStringList& GUI::Model::ComponentUtils::propertyRelatedTypes() -{ - static const QStringList result = { - PropertyItem::M_TYPE, GroupItem::M_TYPE, VectorItem::M_TYPE, - BasicAxisItem::M_TYPE, AmplitudeAxisItem::M_TYPE, MaterialRefractiveDataItem::M_TYPE}; - return result; -} - -QList<const SessionItem*> GUI::Model::ComponentUtils::componentItems(const SessionItem& item) -{ - static const QStringList& propertyRelated = GUI::Model::ComponentUtils::propertyRelatedTypes(); - - QList<const SessionItem*> result; - - if (item.hasModelType<PropertyItem>()) { - result.push_back(&item); - - } else if (item.hasModelType<GroupItem>()) { - result.push_back(&item); - result += groupItems(dynamic_cast<const GroupItem&>(item)); - - } else { - - for (auto* child : item.children()) { - if (!child->isVisible()) - continue; - - if (propertyRelated.contains(child->modelType())) - result.append(child); - - if (child->hasModelType<GroupItem>()) - result += groupItems(*dynamic_cast<GroupItem*>(child)); - } - } - - return result; -} diff --git a/GUI/Model/Component/ComponentUtils.h b/GUI/Model/Component/ComponentUtils.h deleted file mode 100644 index e5a6c5513ef..00000000000 --- a/GUI/Model/Component/ComponentUtils.h +++ /dev/null @@ -1,35 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ComponentUtils.h -//! @brief Defines namespace GUI::Model::ComponentUtils -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#ifndef BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTUTILS_H -#define BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTUTILS_H - -#include <QList> -#include <QStringList> - -class SessionItem; - -//! Contains collection of utility functions to support editing of SessionItem's components. - -namespace GUI::Model::ComponentUtils { - -//! Returns list of strings representing modelTypes suitable for editing in component editors. -const QStringList& propertyRelatedTypes(); - -//! Returns list of SessionItem's children suitable for editing in property editors. -QList<const SessionItem*> componentItems(const SessionItem& item); - -} // namespace GUI::Model::ComponentUtils - -#endif // BORNAGAIN_GUI_MODEL_COMPONENT_COMPONENTUTILS_H diff --git a/GUI/Model/Component/ProxyModelStrategy.cpp b/GUI/Model/Component/ProxyModelStrategy.cpp deleted file mode 100644 index b710199532c..00000000000 --- a/GUI/Model/Component/ProxyModelStrategy.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ProxyModelStrategy.cpp -//! @brief Implements class ProxyModelStrategy -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#include "GUI/Model/Component/ComponentProxyModel.h" -#include "GUI/Model/Session/ModelUtils.h" -#include "GUI/Model/Session/SessionModel.h" - -ProxyModelStrategy::ProxyModelStrategy() : m_source(nullptr), m_proxy(nullptr) {} - -void ProxyModelStrategy::buildModelMap(SessionModel* source, ComponentProxyModel* proxy) -{ - m_sourceToProxy.clear(); - m_proxySourceParent.clear(); - m_source = source; - m_proxy = proxy; - - GUI::Model::ItemUtils::iterate_if( - m_sourceRootIndex, source, - [=](const QModelIndex& index) -> bool { return processSourceIndex(index); }); - - // kind of hack since we have to visit col=1 which has QModelIndex() parent - if (m_sourceRootIndex.isValid()) - processSourceIndex(m_sourceRootIndex.sibling(m_sourceRootIndex.row(), 1)); -} - -void ProxyModelStrategy::onDataChanged(SessionModel* source, ComponentProxyModel* proxy) -{ - Q_UNUSED(source); - Q_UNUSED(proxy); - // we do not expect here change of model layout -} - -const ProxyModelStrategy::map_t& ProxyModelStrategy::sourceToProxy() -{ - return m_sourceToProxy; -} - -const ProxyModelStrategy::map_t& ProxyModelStrategy::proxySourceParent() -{ - return m_proxySourceParent; -} - -void ProxyModelStrategy::setRootIndex(const QModelIndex& sourceRootIndex) -{ - m_sourceRootIndex = QPersistentModelIndex(sourceRootIndex); -} - -//! Method to ask proxy to create an index using friendship of ProxyModelStrategy -//! and ComponentProxyModel. - -QModelIndex ProxyModelStrategy::createProxyIndex(int nrow, int ncol, void* adata) -{ - ASSERT(m_proxy); - return m_proxy->createIndex(nrow, ncol, adata); -} - -//! Builds one-to-one mapping for source and proxy. - -bool IndentityProxyStrategy::processSourceIndex(const QModelIndex& index) -{ - QPersistentModelIndex proxyIndex = - createProxyIndex(index.row(), index.column(), index.internalPointer()); - m_sourceToProxy.insert(QPersistentModelIndex(index), proxyIndex); - - QPersistentModelIndex sourceParent; - if (index.parent().isValid()) - sourceParent = index.parent(); - - m_proxySourceParent.insert(proxyIndex, sourceParent); - - return true; -} diff --git a/GUI/Model/Component/ProxyModelStrategy.h b/GUI/Model/Component/ProxyModelStrategy.h deleted file mode 100644 index c418dd247ca..00000000000 --- a/GUI/Model/Component/ProxyModelStrategy.h +++ /dev/null @@ -1,62 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/Model/Component/ProxyModelStrategy.h -//! @brief Defines class ProxyModelStrategy -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#ifndef BORNAGAIN_GUI_MODEL_COMPONENT_PROXYMODELSTRATEGY_H -#define BORNAGAIN_GUI_MODEL_COMPONENT_PROXYMODELSTRATEGY_H - -#include <QPersistentModelIndex> - -class SessionModel; -class ComponentProxyModel; -class SessionItem; - -//! Base class for proxy strategies in ComponentProxyModel. - -class ProxyModelStrategy { -public: - using map_t = QMap<QPersistentModelIndex, QPersistentModelIndex>; - - ProxyModelStrategy(); - virtual ~ProxyModelStrategy() = default; - - void buildModelMap(SessionModel* source, ComponentProxyModel* proxy); - virtual void onDataChanged(SessionModel* source, ComponentProxyModel* proxy); - - const map_t& sourceToProxy(); - const map_t& proxySourceParent(); - - void setRootIndex(const QModelIndex& sourceRootIndex); - -protected: - QModelIndex createProxyIndex(int nrow, int ncol, void* adata); - virtual bool processSourceIndex(const QModelIndex& index) = 0; - - //!< Mapping of proxy model indices to indices in source model - QMap<QPersistentModelIndex, QPersistentModelIndex> m_sourceToProxy; - //!< Mapping of proxy model indices to indices of parent in source model - QMap<QPersistentModelIndex, QPersistentModelIndex> m_proxySourceParent; - - QPersistentModelIndex m_sourceRootIndex; - SessionModel* m_source; - ComponentProxyModel* m_proxy; -}; - -//! Strategy for ComponentProxyModel which makes it identical to source model. - -class IndentityProxyStrategy : public ProxyModelStrategy { -protected: - bool processSourceIndex(const QModelIndex& index) override; -}; - -#endif // BORNAGAIN_GUI_MODEL_COMPONENT_PROXYMODELSTRATEGY_H diff --git a/GUI/View/PropertyEditor/ComponentTreeView.cpp b/GUI/View/PropertyEditor/ComponentTreeView.cpp deleted file mode 100644 index 667f95f41a7..00000000000 --- a/GUI/View/PropertyEditor/ComponentTreeView.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/View/PropertyEditor/ComponentTreeView.cpp -//! @brief Implements class ComponentTreeView -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#include "GUI/View/PropertyEditor/ComponentTreeView.h" -#include "GUI/Model/Component/ComponentProxyModel.h" -#include "GUI/Model/Session/SessionModel.h" -#include "GUI/View/PropertyEditor/CustomEventFilters.h" -#include "GUI/View/PropertyEditor/SessionModelDelegate.h" -#include "GUI/View/Tool/StyleUtils.h" -#include <QAction> -#include <QBoxLayout> -#include <QMenu> -#include <QStandardItemModel> -#include <QTreeView> - -ComponentTreeView::ComponentTreeView(QWidget* parent) - : QWidget(parent) - , m_tree(new QTreeView) - , m_delegate(new SessionModelDelegate(this)) - , m_proxyModel(new ComponentProxyModel(this)) - , m_placeHolderModel(new QStandardItemModel(this)) - , m_eventFilter(new RightMouseButtonEater) -{ - auto* layout = new QVBoxLayout; - - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(m_tree); - - setLayout(layout); - - QStringList labels = {"Name", "Value"}; - m_placeHolderModel->setHorizontalHeaderLabels(labels); - - GUI::Util::Style::setPropertyStyle(m_tree); - m_tree->setRootIsDecorated(false); - m_tree->setModel(m_placeHolderModel); - m_tree->setItemDelegate(m_delegate); - - // provide one click editing, but still keeping custom context menu alive - m_tree->setEditTriggers(QAbstractItemView::AllEditTriggers); - m_tree->viewport()->installEventFilter(m_eventFilter.get()); - - // custom context menu setup - m_tree->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_tree, &QTreeView::customContextMenuRequested, this, - &ComponentTreeView::onCustomContextMenuRequested); - - setShowHeader(true); -} - -void ComponentTreeView::setItem(SessionItem* item) -{ - if (!item) { - setModel(nullptr); - return; - } - setModel(item->model()); - setRootIndex(item->index()); - m_tree->expandAll(); -} - -void ComponentTreeView::clearEditor() -{ - m_tree->setModel(m_placeHolderModel); -} - -void ComponentTreeView::setModel(SessionModel* model) -{ - m_proxyModel->setSessionModel(model); - if (model) - m_tree->setModel(m_proxyModel); - else - m_tree->setModel(m_placeHolderModel); -} - -void ComponentTreeView::setRootIndex(const QModelIndex& index) -{ - if (QWidget* editor = m_tree->indexWidget(m_tree->currentIndex())) - m_delegate->closeEditor(editor, QAbstractItemDelegate::NoHint); - ASSERT(m_proxyModel); - m_proxyModel->setRootIndex(index); - m_tree->setRootIndex(m_proxyModel->mapFromSource(index)); -} - -void ComponentTreeView::setShowHeader(bool show) -{ - m_tree->setHeaderHidden(!show); -} - -void ComponentTreeView::onCustomContextMenuRequested(const QPoint& pos) -{ - auto point = m_tree->mapToGlobal(pos); - auto treeIndex = m_tree->indexAt(pos); - if (!treeIndex.isValid()) - return; - - auto index = m_proxyModel->mapToSource(treeIndex); - - auto* item = static_cast<SessionItem*>(index.internalPointer()); - if (item->value().type() != QVariant::Double) - return; - - const bool sc_editor = item->editorType() == "ScientificDouble"; - - // Creates right-mouse-click context menu on top of ComponentTreeView - // which will allow user to switch between scientific notation and the notation - // with a specified number of decimals. - QMenu menu; - QAction* scientificAction = menu.addAction("Scientific presentation"); - scientificAction->setCheckable(true); - auto* doubleMenu = menu.addMenu("Double presentation"); - - // To select scientific notation - scientificAction->setChecked(sc_editor); - connect(scientificAction, &QAction::triggered, [&]() { - if (scientificAction->isChecked()) - item->setEditorType("ScientificDouble"); - else - item->setEditorType("Default"); - }); - - // to select number of decimals - const int nmaxdigits = 8; - for (int i = 1; i <= nmaxdigits; ++i) { - auto* action = doubleMenu->addAction(QString("%1 digits").arg(i)); - if (!sc_editor && item->decimals() == i) - action->setChecked(true); - connect(action, &QAction::triggered, [i, &item] { - item->setEditorType("Default"); - item->setDecimals(i); - }); - } - menu.exec(point); -} diff --git a/GUI/View/PropertyEditor/ComponentTreeView.h b/GUI/View/PropertyEditor/ComponentTreeView.h deleted file mode 100644 index ac1f96a39c7..00000000000 --- a/GUI/View/PropertyEditor/ComponentTreeView.h +++ /dev/null @@ -1,57 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file GUI/View/PropertyEditor/ComponentTreeView.h -//! @brief Defines class ComponentTreeView -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#ifndef BORNAGAIN_GUI_VIEW_PROPERTYEDITOR_COMPONENTTREEVIEW_H -#define BORNAGAIN_GUI_VIEW_PROPERTYEDITOR_COMPONENTTREEVIEW_H - -#include <QWidget> -#include <memory> - -class QTreeView; -class SessionModel; -class SessionModelDelegate; -class ComponentProxyModel; -class QModelIndex; -class SessionItem; -class QStandardItemModel; -class RightMouseButtonEater; - -//! Component property tree for SessionItems. -//! Shows only PropertyItems and current items of GroupProperties. - -class ComponentTreeView : public QWidget { - Q_OBJECT -public: - ComponentTreeView(QWidget* parent = nullptr); - - void setItem(SessionItem* item); - void clearEditor(); - - void setShowHeader(bool show); - -private slots: - void onCustomContextMenuRequested(const QPoint& pos); - -private: - void setModel(SessionModel* model); - void setRootIndex(const QModelIndex& index); - - QTreeView* m_tree; - SessionModelDelegate* m_delegate; - ComponentProxyModel* m_proxyModel; - QStandardItemModel* m_placeHolderModel; - std::unique_ptr<RightMouseButtonEater> m_eventFilter; -}; - -#endif // BORNAGAIN_GUI_VIEW_PROPERTYEDITOR_COMPONENTTREEVIEW_H diff --git a/Tests/Unit/GUI/TestComponentProxyModel.cpp b/Tests/Unit/GUI/TestComponentProxyModel.cpp deleted file mode 100644 index 297f38a187f..00000000000 --- a/Tests/Unit/GUI/TestComponentProxyModel.cpp +++ /dev/null @@ -1,381 +0,0 @@ -#include "GUI/Model/Component/ComponentProxyModel.h" -#include "GUI/Model/Component/ComponentProxyStrategy.h" -#include "GUI/Model/Sample/FormFactorItems.h" -#include "GUI/Model/Sample/LayerItem.h" -#include "GUI/Model/Sample/MultiLayerItem.h" -#include "GUI/Model/Sample/ParticleItem.h" -#include "GUI/Model/Sample/ParticleLayoutItem.h" -#include "GUI/Model/Session/ModelUtils.h" -#include "GUI/Model/Types/VectorItem.h" -#include "Tests/GTestWrapper/google_test.h" -#include "Tests/Unit/GUI/Utils.h" -#include <QSignalSpy> - -class TestComponentProxyModel : public ::testing::Test { -}; - -//! Empty proxy model. - -TEST_F(TestComponentProxyModel, emptyModel) -{ - ComponentProxyModel proxy; - EXPECT_EQ(proxy.rowCount(QModelIndex()), 0); - EXPECT_EQ(proxy.columnCount(QModelIndex()), static_cast<int>(SessionFlags::MAX_COLUMNS)); - EXPECT_TRUE(proxy.sourceModel() == nullptr); -} - -//! Set empty model to proxy. - -TEST_F(TestComponentProxyModel, setModel) -{ - SessionModel model("TestModel"); - ComponentProxyModel proxy; - - QSignalSpy spy(&proxy, &ComponentProxyModel::modelReset); - proxy.setSessionModel(&model); - - EXPECT_EQ(spy.count(), 1); - EXPECT_EQ(proxy.rowCount(QModelIndex()), 0); - EXPECT_EQ(proxy.columnCount(QModelIndex()), static_cast<int>(SessionFlags::MAX_COLUMNS)); - EXPECT_EQ(proxy.sourceModel(), &model); -} - -//! Set model to proxy. Model already contains simple item. - -TEST_F(TestComponentProxyModel, setModelWithItem) -{ - SessionModel model("TestModel"); - model.insertItem<PropertyItem>(); - - ComponentProxyModel proxy; - proxy.setSessionModel(&model); - - EXPECT_EQ(model.rowCount(QModelIndex()), 1); - EXPECT_EQ(model.columnCount(QModelIndex()), static_cast<int>(SessionFlags::MAX_COLUMNS)); - EXPECT_EQ(proxy.rowCount(QModelIndex()), 1); - EXPECT_EQ(proxy.columnCount(QModelIndex()), static_cast<int>(SessionFlags::MAX_COLUMNS)); -} - -//! Set model to proxy. Model already contains VectorItem. - -TEST_F(TestComponentProxyModel, setModelWithVector) -{ - const int ncols = static_cast<int>(SessionFlags::MAX_COLUMNS); - - SessionModel model("TestModel"); - auto* item = model.insertItem<VectorItem>(); - item->setX(1.0); - item->setY(2.0); - item->setZ(3.0); - - ComponentProxyModel proxy; - proxy.setSessionModel(&model); - - // rows, cols of root index - EXPECT_EQ(model.rowCount(QModelIndex()), 1); - EXPECT_EQ(model.columnCount(QModelIndex()), ncols); - EXPECT_EQ(proxy.rowCount(QModelIndex()), 1); - EXPECT_EQ(proxy.columnCount(QModelIndex()), ncols); - - // mapFromSource, mapToSource for VectorItem - QModelIndex sourceVector = model.index(0, 0, QModelIndex()); - QModelIndex proxyVector = proxy.index(0, 0, QModelIndex()); - EXPECT_TRUE(sourceVector != proxyVector); - EXPECT_TRUE(sourceVector.internalPointer() == proxyVector.internalPointer()); - EXPECT_EQ(proxyVector, proxy.mapFromSource(sourceVector)); - EXPECT_EQ(sourceVector, proxy.mapToSource(proxyVector)); - - // rows, cols of VectorItem - EXPECT_EQ(model.rowCount(sourceVector), 3); // x,y,z - EXPECT_EQ(model.columnCount(sourceVector), ncols); - EXPECT_EQ(proxy.rowCount(proxyVector), 3); // x,y,z - EXPECT_EQ(proxy.columnCount(proxyVector), ncols); - - // second col for VectorItem - QModelIndex sourceVector1 = model.index(0, 1, QModelIndex()); - QModelIndex proxyVector1 = proxy.index(0, 1, QModelIndex()); - EXPECT_TRUE(sourceVector1 != proxyVector1); - EXPECT_TRUE(sourceVector1.internalPointer() == proxyVector1.internalPointer()); - EXPECT_EQ(proxyVector1, proxy.mapFromSource(sourceVector1)); - EXPECT_EQ(sourceVector1, proxy.mapToSource(proxyVector1)); - EXPECT_EQ(model.rowCount(sourceVector1), 0); - EXPECT_EQ(model.columnCount(sourceVector1), 0); - EXPECT_EQ(proxy.rowCount(proxyVector1), 0); - EXPECT_EQ(proxy.columnCount(proxyVector1), 0); - - // mapFromSource, mapToSource for P_X - QModelIndex sourceX = model.index(0, 0, sourceVector); - QModelIndex proxyX = proxy.index(0, 0, proxyVector); - EXPECT_TRUE(sourceX != proxyX); - EXPECT_TRUE(sourceX.internalPointer() == proxyX.internalPointer()); - EXPECT_EQ(proxyX, proxy.mapFromSource(sourceX)); - EXPECT_EQ(sourceX, proxy.mapToSource(proxyX)); - EXPECT_TRUE(model.parent(sourceX) == sourceVector); - EXPECT_TRUE(proxy.parent(proxyX) == proxyVector); - - // rows, cols of P_X - EXPECT_EQ(model.rowCount(sourceX), 0); - EXPECT_EQ(model.columnCount(sourceX), ncols); - EXPECT_EQ(proxy.rowCount(proxyX), 0); - EXPECT_EQ(proxy.columnCount(proxyX), ncols); - - // second col for P_X - QModelIndex sourceX1 = model.index(0, 1, sourceVector); - QModelIndex proxyX1 = proxy.index(0, 1, proxyVector); - EXPECT_TRUE(sourceX1 != proxyX1); - EXPECT_TRUE(sourceX1.internalPointer() == proxyX1.internalPointer()); - EXPECT_EQ(proxyX1, proxy.mapFromSource(sourceX1)); - EXPECT_EQ(sourceX1, proxy.mapToSource(proxyX1)); - EXPECT_EQ(model.rowCount(sourceX1), 0); - EXPECT_EQ(model.columnCount(sourceX1), 0); - EXPECT_EQ(proxy.rowCount(proxyX1), 0); - EXPECT_EQ(proxy.columnCount(proxyX1), 0); - - EXPECT_TRUE(sourceX.sibling(sourceX.row(), 1) == sourceX1); - EXPECT_TRUE(proxyX.sibling(proxyX.row(), 1) == proxyX1); - - // mapFromSource, mapToSource for P_Z - QModelIndex sourceZ = model.index(2, 0, sourceVector); - QModelIndex proxyZ = proxy.index(2, 0, proxyVector); - EXPECT_TRUE(sourceZ != proxyZ); - EXPECT_TRUE(sourceZ.internalPointer() == proxyZ.internalPointer()); - EXPECT_EQ(proxyZ, proxy.mapFromSource(sourceZ)); - EXPECT_EQ(sourceZ, proxy.mapToSource(proxyZ)); - - // rows, cols of P_Z - EXPECT_EQ(model.rowCount(sourceZ), 0); - EXPECT_EQ(model.columnCount(sourceZ), ncols); - EXPECT_EQ(proxy.rowCount(proxyZ), 0); - EXPECT_EQ(proxy.columnCount(proxyZ), ncols); -} - -//! Set model to proxy. Model already contains two PropertyItems. Checking data() method. - -TEST_F(TestComponentProxyModel, displayRole) -{ - SessionModel model("TestModel"); - auto* item1 = model.insertItem<PropertyItem>(); - item1->setValue(1.0); - auto* item2 = model.insertItem<PropertyItem>(); - item2->setValue(2.0); - - EXPECT_EQ(model.data(model.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 1.0); - EXPECT_EQ(model.data(model.index(1, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 2.0); - - ComponentProxyModel proxy; - proxy.setSessionModel(&model); - - EXPECT_EQ(proxy.data(proxy.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 1.0); - EXPECT_EQ(proxy.data(proxy.index(1, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 2.0); -} - -//! Set model with item to proxy. Changing the data on source and checking change propagation. - -TEST_F(TestComponentProxyModel, setData) -{ - SessionModel model("TestModel"); - auto* item = model.insertItem<PropertyItem>(); - item->setValue(1.0); - - ComponentProxyModel proxy; - proxy.setSessionModel(&model); - - // checking initial data - EXPECT_EQ(model.data(model.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 1.0); - EXPECT_EQ(proxy.data(proxy.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 1.0); - - // changing data in source and listening - QSignalSpy spySource(&model, &SessionModel::dataChanged); - QSignalSpy spyProxy(&proxy, &ComponentProxyModel::dataChanged); - EXPECT_TRUE(model.setData(model.index(0, 1, QModelIndex()), 2.0, Qt::DisplayRole)); - EXPECT_EQ(item->value().toDouble(), 2.0); - - // checking signaling of source - EXPECT_EQ(spySource.count(), 1); - QList<QVariant> arguments = spySource.takeFirst(); - EXPECT_EQ(arguments.size(), 3); - EXPECT_EQ(arguments[0].toModelIndex(), model.index(0, 0, QModelIndex())); - EXPECT_EQ(arguments[1].toModelIndex(), model.index(0, 1, QModelIndex())); - - // checking signaling of proxy - EXPECT_EQ(spyProxy.count(), 1); - EXPECT_EQ(proxy.data(proxy.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 2.0); - - // changing data in proxy - EXPECT_TRUE(proxy.setData(proxy.index(0, 1, QModelIndex()), 3.0, Qt::DisplayRole)); - EXPECT_EQ(item->value().toDouble(), 3.0); - EXPECT_EQ(spySource.count(), 1); // ?, sould be 2 - EXPECT_EQ(spyProxy.count(), 2); - EXPECT_EQ(model.data(model.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 3.0); - EXPECT_EQ(proxy.data(proxy.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 3.0); -} - -//! Checks norification of proxy model then source inserts rows. - -TEST_F(TestComponentProxyModel, insertRows) -{ - SessionModel model("TestModel"); - - ComponentProxyModel proxy; - proxy.setSessionModel(&model); - - EXPECT_FALSE(model.hasChildren(QModelIndex())); - EXPECT_FALSE(proxy.hasChildren(QModelIndex())); - - QSignalSpy spyProxy(&proxy, &ComponentProxyModel::layoutChanged); - - // inserting item in the source - model.insertItem<PropertyItem>(); - EXPECT_EQ(spyProxy.count(), 1); - EXPECT_EQ(proxy.rowCount(QModelIndex()), 1); -} - -//! Checking the mapping of ComponentProxyStrategy in the case of ParticleItem inserted in -//! the source. - -TEST_F(TestComponentProxyModel, componentStrategy) -{ - SessionModel model("TestModel"); - - ComponentProxyModel proxy; - proxy.setProxyStrategy(new ComponentProxyStrategy); - proxy.setSessionModel(&model); - - // inserting particle - auto* item = model.insertItem<ParticleItem>(); - auto* group = item->formFactorItem(); - SessionItem* ffItem = item->formFactor(); - EXPECT_TRUE(ffItem->parent() == group); - EXPECT_TRUE(ffItem->hasModelType<CylinderItem>()); - - // original indices - QModelIndex particleIndex = model.indexOfItem(item); - QModelIndex groupIndex = model.indexOfItem(group); - QModelIndex ffIndex = model.indexOfItem(ffItem); - QModelIndex radiusIndex = model.indexOfItem(dynamic_cast<CylinderItem*>(ffItem)->radiusItem()); - - // proxy indices - QModelIndex particleProxyIndex = proxy.mapFromSource(particleIndex); - EXPECT_TRUE(particleProxyIndex.isValid()); - - // Properties of CylinderItem should belong to group property - QModelIndex groupProxyIndex = proxy.mapFromSource(groupIndex); - EXPECT_TRUE(groupProxyIndex.isValid()); - EXPECT_TRUE(groupProxyIndex.parent() == particleProxyIndex); - EXPECT_EQ(proxy.rowCount(groupProxyIndex), 2); // ff radius and height - EXPECT_EQ(proxy.columnCount(groupProxyIndex), 2); - - // CylinderItem shouldn't exist anymore in proxy - QModelIndex ffProxyIndex = proxy.mapFromSource(ffIndex); - EXPECT_FALSE(ffProxyIndex.isValid()); - - QModelIndex radiusProxyIndex = proxy.mapFromSource(radiusIndex); - EXPECT_TRUE(radiusProxyIndex.isValid()); - EXPECT_TRUE(radiusProxyIndex.parent() == groupProxyIndex); -} - -//! Checking the mapping of ComponentProxyStrategy in the case of ParticleItem inserted in -//! the source. We are changing Particle's form factor back and forth and checking for change -//! in GroupProperty. - -TEST_F(TestComponentProxyModel, componentStrategyFormFactorChanges) -{ - SessionModel model("TestModel"); - - ComponentProxyModel proxy; - proxy.setProxyStrategy(new ComponentProxyStrategy); - proxy.setSessionModel(&model); - - // inserting particle - auto* item = model.insertItem<ParticleItem>(); - auto* group = item->formFactorItem(); - SessionItem* ffItem = item->formFactor(); - EXPECT_TRUE(ffItem->parent() == group); - EXPECT_TRUE(ffItem->hasModelType<CylinderItem>()); - - // changing form factor type - group->setCurrentType(FullSphereItem::M_TYPE); - - QModelIndex groupProxyIndex = proxy.mapFromSource(model.indexOfItem(group)); - EXPECT_EQ(proxy.rowCount(groupProxyIndex), 1); // sphere radius - EXPECT_EQ(proxy.columnCount(groupProxyIndex), 2); - - // changing back to Cylinder - group->setCurrentType(CylinderItem::M_TYPE); - groupProxyIndex = proxy.mapFromSource(model.indexOfItem(group)); - EXPECT_EQ(proxy.rowCount(groupProxyIndex), 2); // cylinder radius, length - EXPECT_EQ(proxy.columnCount(groupProxyIndex), 2); -} - -//! Checking setRootIndex: proxy model should contain only items corresponding -//! to rootIndex and its children. Adding simple PropertyItem. - -TEST_F(TestComponentProxyModel, setRootPropertyItem) -{ - const int ncols = static_cast<int>(SessionFlags::MAX_COLUMNS); - SessionModel model("TestModel"); - - ComponentProxyModel proxy; - proxy.setProxyStrategy(new ComponentProxyStrategy); - proxy.setSessionModel(&model); - - // inserting simple property item - auto* item = model.insertItem<PropertyItem>(); - item->setValue(42.0); - proxy.setRootIndex(model.indexOfItem(item)); - - EXPECT_EQ(model.rowCount(QModelIndex()), 1); - EXPECT_EQ(model.columnCount(QModelIndex()), ncols); - EXPECT_EQ(proxy.rowCount(QModelIndex()), 1); - EXPECT_EQ(proxy.columnCount(QModelIndex()), ncols); - - EXPECT_TRUE(proxy.index(0, 0, QModelIndex()) - == proxy.mapFromSource(model.index(0, 0, QModelIndex()))); - EXPECT_TRUE(proxy.index(0, 1, QModelIndex()) - == proxy.mapFromSource(model.index(0, 1, QModelIndex()))); - EXPECT_TRUE(model.index(0, 0, QModelIndex()) - == proxy.mapToSource(proxy.index(0, 0, QModelIndex()))); - EXPECT_TRUE(proxy.index(0, 1, QModelIndex()).isValid()); - EXPECT_TRUE(model.index(0, 1, QModelIndex()) - == proxy.mapToSource(proxy.index(0, 1, QModelIndex()))); - - EXPECT_EQ(model.data(model.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 42.0); - EXPECT_EQ(proxy.data(proxy.index(0, 1, QModelIndex()), Qt::DisplayRole).toDouble(), 42.0); -} - -//! Checking setRootIndex: proxy model should contain only items corresponding -//! to rootIndex and its children. Adding MultiLayer with two layers and setting rootIndex -//! to one of the layer. - -TEST_F(TestComponentProxyModel, setRootIndexLayer) -{ - - SessionModel model("TestModel"); - - ComponentProxyModel proxy; - proxy.setProxyStrategy(new ComponentProxyStrategy); - proxy.setSessionModel(&model); - - // inserting multilayer with two layers - auto* multilayer = model.insertItem<MultiLayerItem>(); - auto* layer1 = model.insertItem<LayerItem>(multilayer); - auto* layout = model.insertItem<ParticleLayoutItem>(layer1); - model.insertItem<LayerItem>(multilayer); - - proxy.setRootIndex(model.indexOfItem(layer1)); - EXPECT_EQ(proxy.rowCount(QModelIndex()), 1); - EXPECT_EQ(proxy.columnCount(QModelIndex()), 2); - - QModelIndex multilayerProxyIndex = proxy.mapFromSource(model.indexOfItem(multilayer)); - EXPECT_FALSE(multilayerProxyIndex.isValid()); - - QModelIndex layerProxyIndex = proxy.mapFromSource(model.indexOfItem(layer1)); - EXPECT_EQ(proxy.rowCount(layerProxyIndex), 5); // thickness, material, slices, roughness, color - EXPECT_EQ(proxy.columnCount(layerProxyIndex), 2); - EXPECT_TRUE(layerProxyIndex.isValid()); - EXPECT_TRUE(layerProxyIndex.parent() == QModelIndex()); - - // ParticleLayout should be excluded from proxy tree - QModelIndex layoutProxyIndex = proxy.mapFromSource(model.indexOfItem(layout)); - EXPECT_FALSE(layoutProxyIndex.isValid()); -} diff --git a/Tests/Unit/GUI/TestComponentUtils.cpp b/Tests/Unit/GUI/TestComponentUtils.cpp deleted file mode 100644 index 4d05f4cc9f5..00000000000 --- a/Tests/Unit/GUI/TestComponentUtils.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "GUI/Model/Component/ComponentUtils.h" -#include "GUI/Model/Sample/FormFactorItems.h" -#include "GUI/Model/Sample/ParticleItem.h" -#include "GUI/Model/Session/SessionModel.h" -#include "GUI/Model/Types/VectorItem.h" -#include "Tests/GTestWrapper/google_test.h" - -class TestComponentUtils : public ::testing::Test { -}; - -//! Testing component items of particle item. - -TEST_F(TestComponentUtils, componentItems) -{ - SessionModel model("TestModel"); - - auto* particle = model.insertItem<ParticleItem>(); - SessionItem* group = particle->formFactorItem(); - SessionItem* ffItem = particle->formFactor(); - auto* ffCylinder = dynamic_cast<CylinderItem*>(ffItem); - EXPECT_NE(ffCylinder, nullptr); - - auto itemList = GUI::Model::ComponentUtils::componentItems(*particle); - EXPECT_EQ(itemList.size(), 6); - EXPECT_TRUE(itemList.contains(particle->abundanceItem())); - EXPECT_TRUE(itemList.contains(particle->positionItem())); - EXPECT_TRUE(itemList.contains(group)); - EXPECT_TRUE(itemList.contains(ffCylinder->radiusItem())); - EXPECT_TRUE(itemList.contains(ffCylinder->heightItem())); - // the 6th is material item (holds material identifier) -} - -TEST_F(TestComponentUtils, componentItemsFFChange) -{ - SessionModel model("TestModel"); - - auto* particle = model.insertItem<ParticleItem>(); - SessionItem* group = particle->formFactorItem(); - - particle->setFormFactorType<FullSphereItem>(); - auto* sphereItem = dynamic_cast<FullSphereItem*>(particle->formFactor()); - - auto itemList = GUI::Model::ComponentUtils::componentItems(*particle); - EXPECT_EQ(itemList.size(), 5); - EXPECT_TRUE(itemList.contains(particle->abundanceItem())); - EXPECT_TRUE(itemList.contains(particle->positionItem())); - EXPECT_TRUE(itemList.contains(group)); - EXPECT_TRUE(itemList.contains(sphereItem->radiusItem())); - // the 5th is material item (holds material identifier) -} diff --git a/Tests/Unit/GUI/TestProxyModelStrategy.cpp b/Tests/Unit/GUI/TestProxyModelStrategy.cpp deleted file mode 100644 index 3175f48a4ef..00000000000 --- a/Tests/Unit/GUI/TestProxyModelStrategy.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include "GUI/Model/Component/ComponentProxyModel.h" -#include "GUI/Model/Component/ComponentProxyStrategy.h" -#include "GUI/Model/Group/PropertyItem.h" -#include "GUI/Model/Sample/FormFactorItems.h" -#include "GUI/Model/Sample/ParticleItem.h" -#include "GUI/Model/Session/ModelUtils.h" -#include "GUI/Model/Session/SessionModel.h" -#include "GUI/Model/Types/VectorItem.h" -#include "Tests/GTestWrapper/google_test.h" - -class TestProxyModelStrategy : public ::testing::Test { -}; - -//! Checking the mapping in the case of PropertyItem inserted in the source. - -TEST_F(TestProxyModelStrategy, identityStrategy) -{ - SessionModel model("TestModel"); - ComponentProxyModel proxy; - IndentityProxyStrategy strategy; - - EXPECT_EQ(strategy.sourceToProxy().size(), 0); - EXPECT_EQ(strategy.proxySourceParent().size(), 0); - - // building the map of empty source - strategy.buildModelMap(&model, &proxy); - EXPECT_EQ(strategy.sourceToProxy().size(), 0); - EXPECT_EQ(strategy.proxySourceParent().size(), 0); - - // building map when simple item - auto* item = model.insertItem<PropertyItem>(); - strategy.buildModelMap(&model, &proxy); - EXPECT_EQ(strategy.sourceToProxy().size(), 2); - EXPECT_EQ(strategy.proxySourceParent().size(), 2); - - // Checking of persistent indices of source and proxy - auto it = strategy.sourceToProxy().begin(); - // index of source, col=0 - EXPECT_EQ(it.key().row(), 0); - EXPECT_EQ(it.key().column(), 0); - EXPECT_EQ(it.key().internalPointer(), item); - // index of proxy, col=0 - EXPECT_EQ(it.value().row(), 0); - EXPECT_EQ(it.value().column(), 0); - EXPECT_EQ(it.value().internalPointer(), item); - ++it; - // index of source, col=1 - EXPECT_EQ(it.key().row(), 0); - EXPECT_EQ(it.key().column(), 1); - EXPECT_EQ(it.key().internalPointer(), item); - // index of proxy, col=1 - EXPECT_EQ(it.value().row(), 0); - EXPECT_EQ(it.value().column(), 1); - EXPECT_EQ(it.value().internalPointer(), item); - - // Checking parent of proxy - it = strategy.proxySourceParent().begin(); - EXPECT_EQ(it.key().row(), 0); - EXPECT_EQ(it.key().column(), 0); - EXPECT_EQ(it.key().internalPointer(), item); - EXPECT_TRUE(it.value() == QModelIndex()); -} - -//! Checking the mapping in the case of ParticleItem inserted in the source. - -TEST_F(TestProxyModelStrategy, identityStrategyParticle) -{ - SessionModel model("TestModel"); - ComponentProxyModel proxy; - IndentityProxyStrategy strategy; - - auto* item = model.insertItem<ParticleItem>(); - - // building the map of source - strategy.buildModelMap(&model, &proxy); - SessionItem* group = item->formFactorItem(); - SessionItem* ffItem = item->formFactor(); - EXPECT_TRUE(ffItem->parent() == group); - EXPECT_TRUE(ffItem->hasModelType<CylinderItem>()); - - // Checking "real" parent of proxy index related to form factor. - // For identity model we are testing, it has to be just group property. - auto ffProxyIndex = strategy.sourceToProxy().value(model.indexOfItem(ffItem)); - auto parentOfProxy = strategy.proxySourceParent().value(ffProxyIndex); - EXPECT_TRUE(parentOfProxy == model.indexOfItem(group)); - - // Checking "real" parent of Cylinders radius. It has to be CylinderItem - auto* ffCylinder = dynamic_cast<CylinderItem*>(ffItem); - EXPECT_NE(ffCylinder, nullptr); - SessionItem* radiusItem = ffCylinder->radiusItem(); - auto radiusProxyIndex = strategy.sourceToProxy().value(model.indexOfItem(radiusItem)); - parentOfProxy = strategy.proxySourceParent().value(radiusProxyIndex); - EXPECT_TRUE(parentOfProxy == model.indexOfItem(ffItem)); -} - -//! Checking the mapping of ComponentProxyStrategy in the case of ParticleItem inserted in -//! the source. - -TEST_F(TestProxyModelStrategy, componentStrategyParticle) -{ - SessionModel model("TestModel"); - ComponentProxyModel proxy; - ComponentProxyStrategy strategy; - - auto* item = model.insertItem<ParticleItem>(); - - // building the map of source - strategy.buildModelMap(&model, &proxy); - SessionItem* group = item->formFactorItem(); - SessionItem* ffItem = item->formFactor(); - EXPECT_TRUE(ffItem->parent() == group); - EXPECT_TRUE(ffItem->hasModelType<CylinderItem>()); - auto* ffCylinder = dynamic_cast<CylinderItem*>(ffItem); - - // original indices - QModelIndex particleIndex = model.indexOfItem(item); - QModelIndex groupIndex = model.indexOfItem(group); - QModelIndex ffIndex = model.indexOfItem(ffItem); - QModelIndex radiusIndex = model.indexOfItem(ffCylinder->radiusItem()); - - // proxy indices - QModelIndex particleProxyIndex = strategy.sourceToProxy().value(particleIndex); - QModelIndex groupProxyIndex = strategy.sourceToProxy().value(groupIndex); - QModelIndex ffProxyIndex = strategy.sourceToProxy().value(ffIndex); - QModelIndex radiusProxyIndex = strategy.sourceToProxy().value(radiusIndex); - EXPECT_TRUE(particleProxyIndex.isValid()); - EXPECT_TRUE(groupProxyIndex.isValid()); - EXPECT_FALSE(ffProxyIndex.isValid()); // ff is excluded from hierarchy - EXPECT_TRUE(radiusProxyIndex.isValid()); - - // Checking "real" parents of indices - EXPECT_TRUE(strategy.proxySourceParent().value(ffProxyIndex) == QModelIndex()); - EXPECT_TRUE(strategy.proxySourceParent().value(radiusProxyIndex) == groupIndex); - EXPECT_TRUE(strategy.proxySourceParent().value(groupProxyIndex) == particleIndex); -} - -//! Checking setRootIndex: proxy model should contain only items corresponding -//! to rootIndex and its children. - -TEST_F(TestProxyModelStrategy, setRootIndex) -{ - SessionModel model("TestModel"); - ComponentProxyModel proxy; - ComponentProxyStrategy strategy; - - auto* item = model.insertItem<ParticleItem>(); - SessionItem* group = item->formFactorItem(); - SessionItem* ffItem = item->formFactor(); - auto* ffCylinder = dynamic_cast<CylinderItem*>(ffItem); - EXPECT_NE(ffCylinder, nullptr); - - QModelIndex particleIndex = model.indexOfItem(item); - QModelIndex groupIndex = model.indexOfItem(group); - QModelIndex ffIndex = model.indexOfItem(ffItem); - QModelIndex radiusIndex = model.indexOfItem(ffCylinder->radiusItem()); - - // building the map of source, groupItem will be rootIndex - strategy.setRootIndex(model.indexOfItem(group)); - strategy.buildModelMap(&model, &proxy); - - // proxy indices - QModelIndex particleProxyIndex = strategy.sourceToProxy().value(particleIndex); - QModelIndex groupProxyIndex = strategy.sourceToProxy().value(groupIndex); - QModelIndex ffProxyIndex = strategy.sourceToProxy().value(ffIndex); - QModelIndex radiusProxyIndex = strategy.sourceToProxy().value(radiusIndex); - EXPECT_FALSE(particleProxyIndex.isValid()); // particle is not in a tree - EXPECT_TRUE(groupProxyIndex.isValid()); - EXPECT_EQ(groupProxyIndex.row(), 0); - EXPECT_EQ(groupProxyIndex.column(), 0); - EXPECT_TRUE(groupProxyIndex.parent() == QModelIndex()); - EXPECT_FALSE(ffProxyIndex.isValid()); // ff is excluded from hierarchy - EXPECT_TRUE(radiusProxyIndex.isValid()); - - // checking that new parent of groupItem is root - EXPECT_TRUE(strategy.proxySourceParent().value(groupProxyIndex) == QModelIndex()); - EXPECT_TRUE(strategy.proxySourceParent().value(ffProxyIndex) == QModelIndex()); - EXPECT_TRUE(strategy.proxySourceParent().value(radiusProxyIndex) == groupIndex); -} -- GitLab