diff --git a/GUI/coregui/Models/SessionItem.cpp b/GUI/coregui/Models/SessionItem.cpp index 7c0228f31837f121926973841cc3b7152ae94499..1b0df3debdb057f03f94d173e038b2fbd1e8ae88 100644 --- a/GUI/coregui/Models/SessionItem.cpp +++ b/GUI/coregui/Models/SessionItem.cpp @@ -188,6 +188,16 @@ QVector<QString> SessionItem::acceptableDefaultItemTypes() const SessionItem* SessionItem::getItem(const QString& tag, int row) const { const QString tagName = tag.isEmpty() ? defaultTag() : tag; + + if (!m_tags->isValid(tagName)) + return nullptr; + + if (m_tags->childCount(tagName) == 0) + return nullptr; + + if (row < 0 || row >= m_tags->childCount(tagName)) + return nullptr; + int index = m_tags->indexFromTagRow(tagName, row); if (index <0 || index >= m_children.size()) throw GUIHelpers::Error("SessionItem::getItem() -> Invalid row for tag"); diff --git a/GUI/coregui/Models/SessionModel.cpp b/GUI/coregui/Models/SessionModel.cpp index c173bafb8b764aaefde236c4baed666c291a429d..a46fa2829ec5be1ec869e0efeed92326beb3bb06 100644 --- a/GUI/coregui/Models/SessionModel.cpp +++ b/GUI/coregui/Models/SessionModel.cpp @@ -366,18 +366,18 @@ void SessionModel::writeTo(QXmlStreamWriter* writer, SessionItem* parent) //! Move given parameterized item to the new_parent at given row. If new_parent is not defined, //! use root_item as a new parent. + SessionItem* SessionModel::moveParameterizedItem(SessionItem* item, SessionItem* new_parent, int row, const QString &tag) { if (!new_parent) new_parent = m_root_item; + const QString tagName = tag.isEmpty() ? new_parent->defaultTag() : tag; - if (new_parent) { - if (!new_parent->sessionItemTags()->isValid(tagName, item->modelType())) - return 0; - return 0; - } + if (!new_parent->sessionItemTags()->isValid(tagName, item->modelType())) + return 0; + if (item->parent() == new_parent) { // take care of indexes when moving item within same parent int previousIndex = item->parent()->getItems(tagName).indexOf(item); @@ -387,18 +387,18 @@ SessionItem* SessionModel::moveParameterizedItem(SessionItem* item, SessionItem* row--; } } - SessionItem* stuff = item->parent()->takeRow(item->parent()->rowOfChild(item)); - if(!new_parent->insertItem(row, stuff, tagName)) { - int max = new_parent->sessionItemTags()->childMax(tagName); - int childCount = new_parent->sessionItemTags()->childCount(tagName); - if (max == childCount && childCount == 1) { - SessionItem* old = new_parent->takeItem(0, tagName); - new_parent->insertItem(row, stuff, tagName); - m_root_item->insertItem(-1, old); - } - m_root_item->insertItem(-1, stuff); + + if (new_parent->sessionItemTags()->maximumReached(tagName)) { + SessionItem* prev = new_parent->takeItem(0, tagName); + m_root_item->insertItem(-1, prev); } - return stuff; + + // removing item from previous parent + item->parent()->takeRow(item->parent()->rowOfChild(item)); + + new_parent->insertItem(row, item, tagName); + + return item; } //! Copy given item to the new_parent at given row. Item indended for copying can belong to diff --git a/Tests/UnitTests/GUI/TestGUI.cpp b/Tests/UnitTests/GUI/TestGUI.cpp index 2f8049e00acde606e71933777e54a4f4c0a49fe8..2b82f6f777f8450b6a33ef399efc14e741dba201 100644 --- a/Tests/UnitTests/GUI/TestGUI.cpp +++ b/Tests/UnitTests/GUI/TestGUI.cpp @@ -4,46 +4,46 @@ #include <QAbstractItemModel> #include "Comparators.h" -//#include "TestComboProperty.h" -//#include "TestComponentProxyModel.h" -//#include "TestComponentUtils.h" -////#include "TestDetectorItems.h" -//#include "TestExternalProperty.h" -//#include "TestFitParameterModel.h" -//#include "TestFormFactorItems.h" -//#include "TestFTDistributionItems.h" -//#include "TestGroupItem.h" -//#include "TestGUICoreObjectCorrespondence.h" -//#include "TestGUIHelpers.h" -//#include "TestIntensityDataItem.h" -//#include "TestLayerItems.h" -//#include "TestLayerRoughnessItems.h" -////#include "TestLinkInstrument.h" -//#include "TestMapperCases.h" -//#include "TestMapperForItem.h" -//#include "TestMaterialModel.h" -//#include "TestMaterialPropertyController.h" -//#include "TestModelUtils.h" -////#include "TestOutputDataIOService.h" -//#include "TestParaCrystalItems.h" -//#include "TestParameterTreeUtils.h" -////#include "TestParticleCoreShell.h" -//#include "TestParticleDistributionItem.h" -//#include "TestParticleItem.h" -////#include "TestProjectDocument.h" -//#include "TestProjectUtils.h" -//#include "TestPropertyRepeater.h" -//#include "TestProxyModelStrategy.h" -////#include "TestSaveService.h" -//#include "TestSessionItemController.h" +#include "TestComboProperty.h" +#include "TestComponentProxyModel.h" +#include "TestComponentUtils.h" +#include "TestDetectorItems.h" +#include "TestExternalProperty.h" +#include "TestFitParameterModel.h" +#include "TestFormFactorItems.h" +#include "TestFTDistributionItems.h" +#include "TestGroupItem.h" +#include "TestGUICoreObjectCorrespondence.h" +#include "TestGUIHelpers.h" +#include "TestIntensityDataItem.h" +#include "TestLayerItems.h" +#include "TestLayerRoughnessItems.h" +#include "TestLinkInstrument.h" +#include "TestMapperCases.h" +#include "TestMapperForItem.h" +#include "TestMaterialModel.h" +#include "TestMaterialPropertyController.h" +#include "TestModelUtils.h" +#include "TestOutputDataIOService.h" +#include "TestParaCrystalItems.h" +#include "TestParameterTreeUtils.h" +#include "TestParticleCoreShell.h" +#include "TestParticleDistributionItem.h" +#include "TestParticleItem.h" +#include "TestProjectDocument.h" +#include "TestProjectUtils.h" +#include "TestPropertyRepeater.h" +#include "TestProxyModelStrategy.h" +#include "TestSaveService.h" +#include "TestSessionItemController.h" #include "TestSessionItem.h" -//#include "TestSessionItemUtils.h" +#include "TestSessionItemUtils.h" #include "TestSessionModel.h" -//#include "TestSessionXML.h" -//#include "TestTranslations.h" -//#include "TestUpdateTimer.h" -//#include "TestSessionItemData.h" -//#include "TestSessionItemTags.h" +#include "TestSessionXML.h" +#include "TestTranslations.h" +#include "TestUpdateTimer.h" +#include "TestSessionItemData.h" +#include "TestSessionItemTags.h" int main(int argc, char** argv) { QCoreApplication app(argc, argv); diff --git a/Tests/UnitTests/GUI/TestParticleCoreShell.h b/Tests/UnitTests/GUI/TestParticleCoreShell.h index f59b5ebd09258f264a15223ed2678640f92377e2..418c1d7ec3458e0cb323e5d8360ae56f4bc84f31 100644 --- a/Tests/UnitTests/GUI/TestParticleCoreShell.h +++ b/Tests/UnitTests/GUI/TestParticleCoreShell.h @@ -18,6 +18,40 @@ public: TestParticleCoreShell::~TestParticleCoreShell() = default; +TEST_F(TestParticleCoreShell, test_moveCoreAndShell) +{ + SampleModel model; + SessionItem* coreshell = model.insertNewItem(Constants::ParticleCoreShellType); + SessionItem* particle1 = model.insertNewItem(Constants::ParticleType); + SessionItem* particle2 = model.insertNewItem(Constants::ParticleType); + SessionItem* particle3 = model.insertNewItem(Constants::ParticleType); + + // empty coreshell particle + EXPECT_EQ(particle1->parent(), model.rootItem()); + EXPECT_EQ(particle2->parent(), model.rootItem()); + EXPECT_EQ(particle3->parent(), model.rootItem()); + EXPECT_EQ(coreshell->getItem(ParticleCoreShellItem::T_CORE), nullptr); + EXPECT_EQ(coreshell->getItem(ParticleCoreShellItem::T_SHELL), nullptr); + + // adding core + model.moveParameterizedItem(particle1, coreshell, -1, ParticleCoreShellItem::T_CORE); + EXPECT_EQ(particle1->parent(), coreshell); + EXPECT_EQ(coreshell->getItem(ParticleCoreShellItem::T_CORE), particle1); + + // adding shell + model.moveParameterizedItem(particle2, coreshell, -1, ParticleCoreShellItem::T_SHELL); + EXPECT_EQ(particle2->parent(), coreshell); + EXPECT_EQ(coreshell->getItem(ParticleCoreShellItem::T_SHELL), particle2); + + // adding another core, previous one should deattach + model.moveParameterizedItem(particle3, coreshell, -1, ParticleCoreShellItem::T_CORE); + EXPECT_EQ(particle3->parent(), coreshell); + EXPECT_EQ(coreshell->getItem(ParticleCoreShellItem::T_CORE), particle3); +// EXPECT_EQ(particle1->parent(), model.rootItem()); + +} + + //! Checking that adding and removing core/shell leads to enabling/disabling of their position //! and abundance properties. diff --git a/Tests/UnitTests/GUI/TestSessionItem.h b/Tests/UnitTests/GUI/TestSessionItem.h index ae1d9b0a86ddf4c0e6dcfed2518f4f63b08dc2c6..8f3135446e2666bdb2b80ec1a02fa7fb2552212a 100644 --- a/Tests/UnitTests/GUI/TestSessionItem.h +++ b/Tests/UnitTests/GUI/TestSessionItem.h @@ -68,6 +68,10 @@ TEST_F(TestSessionItem, singleTagAndItems) // register empty string returns false EXPECT_FALSE(item->registerTag("")); + // getting non-existing items from tag + EXPECT_TRUE(item->getItem(tag1) == nullptr); + EXPECT_TRUE(item->getItems(tag1) == QVector<SessionItem*>()); + // inserting single item SessionItem* child = new SessionItem(modelType); EXPECT_TRUE(item->insertItem(0, child, tag1)); @@ -97,7 +101,7 @@ TEST_F(TestSessionItem, singleTagAndItems) EXPECT_EQ(item->getItems(tag1), expected); EXPECT_EQ(item->getItem(tag1, 0), child1); EXPECT_EQ(item->getItem(tag1, 1), child); - EXPECT_THROW(item->getItem(tag1, 2), GUIHelpers::Error); + EXPECT_EQ(item->getItem(tag1, 2), nullptr); // adding third item at the end SessionItem* child2 = new SessionItem(modelType); @@ -223,6 +227,7 @@ TEST_F(TestSessionItem, takeRow) auto taken1 = item->takeRow(1); EXPECT_EQ(taken1, expected1.at(1)); + EXPECT_TRUE(taken1->parent() == nullptr); delete taken1; auto taken2 = item->takeRow(maxItems1-1); // one item less already diff --git a/Tests/UnitTests/GUI/TestSessionModel.h b/Tests/UnitTests/GUI/TestSessionModel.h index e84570ca1c110da9041cf82a18879f40b871290d..d1daf1cdf0ec710a90f54731a924c6afd6454aee 100644 --- a/Tests/UnitTests/GUI/TestSessionModel.h +++ b/Tests/UnitTests/GUI/TestSessionModel.h @@ -6,6 +6,7 @@ #include "SessionModel.h" #include "SessionItemTags.h" #include "google_test.h" +#include "MaskItems.h" #include <QXmlStreamWriter> #include <QSignalSpy> #include <memory> @@ -148,7 +149,69 @@ TEST_F(TestSessionModel, test_copyParameterizedItem) EXPECT_EQ(jobItem->sessionItemTags()->childCount(JobItem::T_INSTRUMENT), 1); } -TEST_F(TestSessionModel, moveItemDifferentParent) +TEST_F(TestSessionModel, moveItemFromRoot) { + SessionModel model("TestModel"); + auto poly = model.insertNewItem(Constants::PolygonMaskType); + auto point = model.insertNewItem(Constants::PolygonPointType); + + EXPECT_EQ(poly->parent(), model.rootItem()); + EXPECT_EQ(point->parent(), model.rootItem()); + EXPECT_EQ(model.rootItem()->numberOfChildren(), 2); + + // moving from rootItem to poly + auto moved = model.moveParameterizedItem(point, poly); + EXPECT_EQ(model.rootItem()->numberOfChildren(), 1); + EXPECT_EQ(moved, point); + EXPECT_EQ(point->parent(), poly); + EXPECT_EQ(poly->getItem(), point); + + // moving from poly to rootItem + moved = model.moveParameterizedItem(point, 0); + EXPECT_EQ(model.rootItem()->numberOfChildren(), 2); + EXPECT_EQ(moved, point); + EXPECT_EQ(point->parent(), model.rootItem()); + EXPECT_EQ(poly->getItem(), nullptr); +} + +TEST_F(TestSessionModel, moveBetweenParents) +{ + SessionModel model("TestModel"); + auto poly1 = model.insertNewItem(Constants::PolygonMaskType); + auto point11 = model.insertNewItem(Constants::PolygonPointType, model.indexOfItem(poly1)); + auto point12 = model.insertNewItem(Constants::PolygonPointType, model.indexOfItem(poly1)); + auto poly2 = model.insertNewItem(Constants::PolygonMaskType); + + EXPECT_EQ(point11->parent(), poly1); + EXPECT_EQ(point12->parent(), poly1); + EXPECT_EQ(poly1->getItem(), point11); + + auto moved = model.moveParameterizedItem(point11, poly2); + EXPECT_EQ(moved, point11); + EXPECT_EQ(point11->parent(), poly2); + EXPECT_EQ(poly1->getItem(), point12); +} +TEST_F(TestSessionModel, moveWithinSameParent) +{ + SessionModel model("TestModel"); + auto poly = model.insertNewItem(Constants::PolygonMaskType); + auto pA = model.insertNewItem(Constants::PolygonPointType, model.indexOfItem(poly)); + auto pB = model.insertNewItem(Constants::PolygonPointType, model.indexOfItem(poly)); + auto pC = model.insertNewItem(Constants::PolygonPointType, model.indexOfItem(poly)); + auto pD = model.insertNewItem(Constants::PolygonPointType, model.indexOfItem(poly)); + auto pE = model.insertNewItem(Constants::PolygonPointType, model.indexOfItem(poly)); + + // 0 pA -> pA + // 1 pB -> pC + // 2 pC -> pB + // 3 pD -> pD + // 4 pE -> pE + + model.moveParameterizedItem(pB, poly, 3); + EXPECT_EQ(poly->getItems().indexOf(pA), 0); + EXPECT_EQ(poly->getItems().indexOf(pB), 2); + EXPECT_EQ(poly->getItems().indexOf(pC), 1); + EXPECT_EQ(poly->getItems().indexOf(pD), 3); + EXPECT_EQ(poly->getItems().indexOf(pE), 4); }