diff --git a/GUI/coregui/Models/ModelMapper.cpp b/GUI/coregui/Models/ModelMapper.cpp index 44b5dfa9d0b5bd5c682b178dd45209310c2b58c6..0fec1c3b1da4c6de5d91776b31a4c942999b538a 100644 --- a/GUI/coregui/Models/ModelMapper.cpp +++ b/GUI/coregui/Models/ModelMapper.cpp @@ -75,13 +75,13 @@ void ModelMapper::setOnAnyChildChange(std::function<void (SessionItem *)> f, voi //! Cancells all subscribtion of given caller void ModelMapper::unsubscribe(void *caller) { - qDebug() << "XXX" << m_onPropertyChange.size(); -// m_onPropertyChange.erase(std::remove_if(m_onPropertyChange.begin(), m_onPropertyChange.end(), -// [](call_str_t const & x) -> bool { Q_UNUSED(x); return true; }), -// m_onPropertyChange.end()); - - clean_container(m_onPropertyChange); - qDebug() << "XXX 1.2" << m_onPropertyChange.size(); + clean_container(m_onValueChange, caller); + clean_container(m_onPropertyChange, caller); + clean_container(m_onChildPropertyChange, caller); + clean_container(m_onParentChange, caller); + clean_container(m_onChildrenChange, caller); + clean_container(m_onSiblingsChange, caller); + clean_container(m_onAnyChildChange, caller); } void ModelMapper::setModel(SessionModel *model) diff --git a/GUI/coregui/Models/ModelMapper.h b/GUI/coregui/Models/ModelMapper.h index 8f0fbf6807bba9b0b32da0f5ab677ac3a146fc4c..57e48a522ff729cc3780c3c7679daacda830c8e8 100644 --- a/GUI/coregui/Models/ModelMapper.h +++ b/GUI/coregui/Models/ModelMapper.h @@ -76,14 +76,8 @@ public slots: void onRowRemoved(const QModelIndex & parent, int first, int last); private: - template<class U> - void clean_container(U& v) { - v.erase(std::remove_if(v.begin(), v.end(), - [](call_str_t const & x) -> bool { Q_UNUSED(x); return true; }), - v.end()); - - } - + //! removes all callbacks related to given caller + template<class U> void clean_container(U& v, void *caller); void setModel(SessionModel *model); int nestlingDepth(SessionItem* item, int level = 0); @@ -117,4 +111,13 @@ private: QModelIndex m_aboutToDelete; }; + +template<class U> +inline void ModelMapper::clean_container(U& v, void *caller) { + v.erase(std::remove_if(v.begin(), v.end(), + [caller](typename U::value_type const &x) -> bool { return (x.second == caller ? true : false); }), + v.end()); +} + + #endif diff --git a/Tests/UnitTests/TestGUI/TestMapperForItem.h b/Tests/UnitTests/TestGUI/TestMapperForItem.h index 9b89ac1a6154767cc0945b9f9fd98df090efd4fe..1a5ae46a3c5ca37b8f8cac86544c9c4d05d583d9 100644 --- a/Tests/UnitTests/TestGUI/TestMapperForItem.h +++ b/Tests/UnitTests/TestGUI/TestMapperForItem.h @@ -10,20 +10,15 @@ #include <QtTest> -//! Test if ModelMapper reports correctly (number of callbacks, -//! names of properties and reporting items) -class TestMapperForItem : public QObject { - Q_OBJECT - +//! Test Widget which logs calling activity of ModelMapper +class Widget { public: - TestMapperForItem(QObject *parent = 0) - : QObject(parent) - , m_onPropertyChangeCount(0) + Widget() + : m_onPropertyChangeCount(0) , m_onChildPropertyChangeCount(0) , m_onParentChangeCount(0) , m_onChildrenChangeCount(0) , m_onSiblingsChangeCount(0) - , m_mapped_item(0) { } void clear() @@ -33,91 +28,48 @@ public: m_onParentChangeCount = 0; m_onChildrenChangeCount = 0; m_onSiblingsChangeCount = 0; - m_mapped_item = 0; m_reported_items.clear(); m_reported_names.clear(); } - void setItem(SessionItem *item) + void subscribe(ModelMapper *mapper, bool with_subscription = false) { clear(); - m_mapped_item = item; - m_mapper.reset(new ModelMapper); - m_mapper->setItem(item); - m_mapper->setOnPropertyChange( - [this] (QString name) - { - onPropertyChange(name); - }); - - m_mapper->setOnChildPropertyChange( - [this](SessionItem* item, QString name) - { - onChildPropertyChange(item, name); - }); + void *caller = (with_subscription ? this : 0); - m_mapper->setOnParentChange( - [this](SessionItem *parent) { - onParentChange(parent); - }); - - - m_mapper->setOnChildrenChange( - [this](SessionItem*) - { - onChildrenChange(); - }); - - m_mapper->setOnSiblingsChange( - [this]() - { - onSiblingsChange(); - }); - - } - - void setItemSubscribe(SessionItem *item) - { - clear(); - m_mapped_item = item; - m_mapper.reset(new ModelMapper); - m_mapper->setItem(item); - - m_mapper->setOnPropertyChange( + mapper->setOnPropertyChange( [this] (QString name) { onPropertyChange(name); - }, this); + }, caller); - m_mapper->setOnChildPropertyChange( + mapper->setOnChildPropertyChange( [this](SessionItem* item, QString name) { onChildPropertyChange(item, name); - }, this); + }, caller); - m_mapper->setOnParentChange( + mapper->setOnParentChange( [this](SessionItem *parent) { onParentChange(parent); - }, this); + }, caller); - m_mapper->setOnChildrenChange( + mapper->setOnChildrenChange( [this](SessionItem*) { onChildrenChange(); - }, this); + }, caller); - m_mapper->setOnSiblingsChange( + mapper->setOnSiblingsChange( [this]() { onSiblingsChange(); - }, this); + }, caller); } - -private: void onPropertyChange(const QString &name) { m_reported_names.append(name); @@ -147,157 +99,189 @@ private: m_onSiblingsChangeCount++; } + void unsubscribe(ModelMapper *mapper) { + mapper->unsubscribe(this); + } + int m_onPropertyChangeCount; int m_onChildPropertyChangeCount; int m_onParentChangeCount; int m_onChildrenChangeCount; int m_onSiblingsChangeCount; - SessionItem *m_mapped_item; QList<SessionItem *> m_reported_items; QStringList m_reported_names; +}; + + +//! Test if ModelMapper reports correctly (number of callbacks, +//! names of properties and reporting items) +class TestMapperForItem : public QObject { + Q_OBJECT + +public: + TestMapperForItem(QObject *parent = 0) + : QObject(parent) + , m_mapped_item(0) + { } + + void setItem(SessionItem *item, Widget *widget, bool with_subscription = false) + { + m_mapped_item = item; + m_mapper.reset(new ModelMapper); + m_mapper->setItem(item); + widget->subscribe(m_mapper.get(), with_subscription); + } + +private: + SessionItem *m_mapped_item; std::unique_ptr<ModelMapper> m_mapper; private slots: - + void test_initialCondition(); void test_onPropertyChange(); void test_onParentChange(); void test_onChildrenChange(); void test_onSiblingsChange(); - void test_Subscription(); }; +inline void TestMapperForItem::test_initialCondition() +{ + Widget w; + QCOMPARE(w.m_onPropertyChangeCount, 0); + QCOMPARE(w.m_onChildPropertyChangeCount, 0); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 0); + QCOMPARE(w.m_onSiblingsChangeCount, 0); + QVERIFY(w.m_reported_items.isEmpty()); + QVERIFY(w.m_reported_names.isEmpty()); + QVERIFY(m_mapped_item == nullptr); + QVERIFY(!m_mapper); +} + inline void TestMapperForItem::test_onPropertyChange() { + Widget w; SampleModel model; SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType); SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer)); - // check initial state of our test class - QCOMPARE(m_onPropertyChangeCount, 0); - QCOMPARE(m_onChildPropertyChangeCount, 0); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 0); - QCOMPARE(m_onSiblingsChangeCount, 0); - QVERIFY(m_mapped_item == nullptr); - QVERIFY(m_reported_items.isEmpty()); - QVERIFY(m_reported_names.isEmpty()); - // Mapper is looking on child; set property of child - setItem(layer); - layer->setItemValue(LayerItem::P_THICKNESS, 1.0); - QCOMPARE(m_onPropertyChangeCount, 1); - QCOMPARE(m_onChildPropertyChangeCount, 0); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 0); - QCOMPARE(m_onSiblingsChangeCount, 0); + setItem(layer, &w); QVERIFY(m_mapped_item == layer); - QVERIFY(m_reported_items.isEmpty()); - QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == LayerItem::P_THICKNESS)); + + layer->setItemValue(LayerItem::P_THICKNESS, 1.0); + QCOMPARE(w.m_onPropertyChangeCount, 1); + QCOMPARE(w.m_onChildPropertyChangeCount, 0); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 0); + QCOMPARE(w.m_onSiblingsChangeCount, 0); + QVERIFY(w.m_reported_items.isEmpty()); + QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == LayerItem::P_THICKNESS)); // Mapper is looking on child; set property of parent; - setItem(layer); - multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 1.0); - QCOMPARE(m_onPropertyChangeCount, 0); - QCOMPARE(m_onChildPropertyChangeCount, 0); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 0); - QCOMPARE(m_onSiblingsChangeCount, 0); + setItem(layer, &w); QVERIFY(m_mapped_item == layer); - QVERIFY(m_reported_items.isEmpty()); - QVERIFY(m_reported_names.isEmpty()); + multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 1.0); + QCOMPARE(w.m_onPropertyChangeCount, 0); + QCOMPARE(w.m_onChildPropertyChangeCount, 0); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 0); + QCOMPARE(w.m_onSiblingsChangeCount, 0); + QVERIFY(w.m_reported_items.isEmpty()); + QVERIFY(w.m_reported_names.isEmpty()); // Mapper is looking on parent; set property of child; - setItem(multilayer); - layer->setItemValue(LayerItem::P_THICKNESS, 2.0); - QCOMPARE(m_onPropertyChangeCount, 0); - QCOMPARE(m_onChildPropertyChangeCount, 1); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 0); - QCOMPARE(m_onSiblingsChangeCount, 0); + setItem(multilayer, &w); QVERIFY(m_mapped_item == multilayer); - QVERIFY( (m_reported_items.size() == 1) && (m_reported_items[0] == layer)); - QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == LayerItem::P_THICKNESS)); + layer->setItemValue(LayerItem::P_THICKNESS, 2.0); + QCOMPARE(w.m_onPropertyChangeCount, 0); + QCOMPARE(w.m_onChildPropertyChangeCount, 1); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 0); + QCOMPARE(w.m_onSiblingsChangeCount, 0); + QVERIFY( (w.m_reported_items.size() == 1) && (w.m_reported_items[0] == layer)); + QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == LayerItem::P_THICKNESS)); // Mapper is looking on parent; set property of parent; - setItem(multilayer); - multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 2.0); - QCOMPARE(m_onPropertyChangeCount, 1); - QCOMPARE(m_onChildPropertyChangeCount, 0); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 0); - QCOMPARE(m_onSiblingsChangeCount, 0); + setItem(multilayer, &w); QVERIFY(m_mapped_item == multilayer); - QVERIFY(m_reported_items.isEmpty()); - QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == MultiLayerItem::P_CROSS_CORR_LENGTH)); + multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 2.0); + QCOMPARE(w.m_onPropertyChangeCount, 1); + QCOMPARE(w.m_onChildPropertyChangeCount, 0); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 0); + QCOMPARE(w.m_onSiblingsChangeCount, 0); + QVERIFY(w.m_reported_items.isEmpty()); + QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == MultiLayerItem::P_CROSS_CORR_LENGTH)); } inline void TestMapperForItem::test_onParentChange() { - clear(); + Widget w; SampleModel model; SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType); SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer)); // SessionItem *layer = model.insertNewItem(Constants::LayerType); // Mapper is looking on child; changing child's parent - setItem(layer); + setItem(layer, &w); + QVERIFY(m_mapped_item == layer); multilayer->takeRow(layer->parentRow()); // model.moveParameterizedItem(layer, multilayer); // FIXME check onParentChange while moving an item - QCOMPARE(m_onPropertyChangeCount, 0); - QCOMPARE(m_onChildPropertyChangeCount, 0); - QCOMPARE(m_onParentChangeCount, 1); - QCOMPARE(m_onChildrenChangeCount, 0); - QVERIFY(m_mapped_item == layer); - //QVERIFY((m_reported_items.size() == 1) && (m_reported_items[0] == nullptr)); - QVERIFY(m_reported_names.isEmpty()); + QCOMPARE(w.m_onPropertyChangeCount, 0); + QCOMPARE(w.m_onChildPropertyChangeCount, 0); + QCOMPARE(w.m_onParentChangeCount, 1); + QCOMPARE(w.m_onChildrenChangeCount, 0); + //QVERIFY((w.m_reported_items.size() == 1) && (w.m_reported_items[0] == nullptr)); + QVERIFY(w.m_reported_names.isEmpty()); } inline void TestMapperForItem::test_onChildrenChange() { - clear(); + Widget w; SampleModel model; SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType); // Mapper is looking on parent; adding new child to parent - setItem(multilayer); + setItem(multilayer, &w); + QVERIFY(m_mapped_item == multilayer); model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer)); - QCOMPARE(m_onPropertyChangeCount, 0); - QCOMPARE(m_onChildPropertyChangeCount, 2); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 1); - QCOMPARE(m_onSiblingsChangeCount, 0); - QVERIFY(m_mapped_item == multilayer); - QCOMPARE(m_reported_items.size(), 2); - QCOMPARE(m_reported_names.size(), 2); + QCOMPARE(w.m_onPropertyChangeCount, 0); + QCOMPARE(w.m_onChildPropertyChangeCount, 2); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 1); + QCOMPARE(w.m_onSiblingsChangeCount, 0); + QCOMPARE(w.m_reported_items.size(), 2); + QCOMPARE(w.m_reported_names.size(), 2); } inline void TestMapperForItem::test_onSiblingsChange() { - clear(); + Widget w; SampleModel model; SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType); SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer)); // Mapper is looking on child; adding another child to parent - setItem(layer); + setItem(layer, &w); + QVERIFY(m_mapped_item == layer); SessionItem *layer2 = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer)); Q_UNUSED(layer2); - QCOMPARE(m_onPropertyChangeCount, 0); - QCOMPARE(m_onChildPropertyChangeCount, 0); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 0); - QCOMPARE(m_onSiblingsChangeCount, 1); - QVERIFY(m_mapped_item == layer); - QVERIFY(m_reported_items.isEmpty()); - QVERIFY(m_reported_names.isEmpty()); + QCOMPARE(w.m_onPropertyChangeCount, 0); + QCOMPARE(w.m_onChildPropertyChangeCount, 0); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 0); + QCOMPARE(w.m_onSiblingsChangeCount, 1); + QVERIFY(w.m_reported_items.isEmpty()); + QVERIFY(w.m_reported_names.isEmpty()); multilayer->takeItem(1, MultiLayerItem::T_LAYERS); - QCOMPARE(m_onSiblingsChangeCount, 2); + QCOMPARE(w.m_onSiblingsChangeCount, 2); // FIXME // multilayer->takeRow(layer2->parentRow()); @@ -306,28 +290,29 @@ inline void TestMapperForItem::test_onSiblingsChange() inline void TestMapperForItem::test_Subscription() { + Widget w; SampleModel model; SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType); SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer)); // Mapper is looking on child; set property of child - setItemSubscribe(layer); - layer->setItemValue(LayerItem::P_THICKNESS, 1.0); - QCOMPARE(m_onPropertyChangeCount, 1); - QCOMPARE(m_onChildPropertyChangeCount, 0); - QCOMPARE(m_onParentChangeCount, 0); - QCOMPARE(m_onChildrenChangeCount, 0); - QCOMPARE(m_onSiblingsChangeCount, 0); + setItem(layer, &w, true); QVERIFY(m_mapped_item == layer); - QVERIFY(m_reported_items.isEmpty()); - QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == LayerItem::P_THICKNESS)); + layer->setItemValue(LayerItem::P_THICKNESS, 1.0); + QCOMPARE(w.m_onPropertyChangeCount, 1); + QCOMPARE(w.m_onChildPropertyChangeCount, 0); + QCOMPARE(w.m_onParentChangeCount, 0); + QCOMPARE(w.m_onChildrenChangeCount, 0); + QCOMPARE(w.m_onSiblingsChangeCount, 0); + QVERIFY(w.m_reported_items.isEmpty()); + QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == LayerItem::P_THICKNESS)); layer->setItemValue(LayerItem::P_THICKNESS, 2.0); - QCOMPARE(m_onPropertyChangeCount, 2); + QCOMPARE(w.m_onPropertyChangeCount, 2); - m_mapper->unsubscribe(this); + w.unsubscribe(m_mapper.get()); layer->setItemValue(LayerItem::P_THICKNESS, 3.0); - QCOMPARE(m_onPropertyChangeCount, 2); + QCOMPARE(w.m_onPropertyChangeCount, 2); }