FInished test for the Tree structure classes

This commit is contained in:
Marcel Otte 2018-01-12 20:36:46 +01:00
parent bbc0734ae5
commit e997802305
6 changed files with 153 additions and 115 deletions

View File

@ -12,6 +12,10 @@ public:
virtual ~Tree(); virtual ~Tree();
const std::shared_ptr<TreeNode<T>> getRoot() { return root; } const std::shared_ptr<TreeNode<T>> getRoot() { return root; }
const std::shared_ptr<TreeNode<T>> getFirst() {
if(root->getChildren()->size() > 0) return root->getChildren()->at(0);
return nullptr;
}
void nodeDataChanged(std::shared_ptr<TreeNode<T>> node); void nodeDataChanged(std::shared_ptr<TreeNode<T>> node);
void treeChanged(std::shared_ptr<TreeNode<T>> node); void treeChanged(std::shared_ptr<TreeNode<T>> node);

View File

@ -4,7 +4,7 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <list> #include <deque>
#include <algorithm> #include <algorithm>
template <class T> template <class T>
@ -12,8 +12,7 @@ class TreeNode;
enum class TreeWalkStrategy { enum class TreeWalkStrategy {
depthFirst, depthFirst,
breadthFirst, breadthFirst
mixture
}; };
template <class T> template <class T>
class TreeNode : public std::enable_shared_from_this<TreeNode<T>> class TreeNode : public std::enable_shared_from_this<TreeNode<T>>
@ -30,15 +29,15 @@ public:
const std::shared_ptr<TreeNode<T>> next(TreeWalkStrategy walkStrategy = TreeWalkStrategy::depthFirst); const std::shared_ptr<TreeNode<T>> next(TreeWalkStrategy walkStrategy = TreeWalkStrategy::depthFirst);
const std::shared_ptr<TreeNode<T>> getRoot(); const std::shared_ptr<TreeNode<T>> getRoot();
void move(std::shared_ptr<TreeNode<T>> to); //as child void move(const std::shared_ptr<TreeNode<T> > &to); //as child
void moveChildren(std::shared_ptr<TreeNode<T>> to); //all children but not the 'executing' element void moveChildren(const std::shared_ptr<TreeNode<T> > &to); //all children but not the 'executing' element
void addChild(std::shared_ptr<TreeNode<T>> child); void addChild(const std::shared_ptr<TreeNode<T> > &child);
void addChildren(std::shared_ptr<TreeNode<T>> nodeWithChildren); void addChildren(const std::shared_ptr<TreeNode<T> > &nodeWithChildren);
bool removeChild(std::shared_ptr<TreeNode<T>> child); void removeChild(const std::shared_ptr<TreeNode<T> > &child);
bool remove(); void remove();
void addChildObject(std::shared_ptr<T> obj); void addChildObject(const std::shared_ptr<T> &obj);
uint getDistanceFromRoot(); uint getDistanceFromRoot();
@ -48,7 +47,7 @@ public:
std::shared_ptr<T> getData() const; std::shared_ptr<T> getData() const;
void setData(const std::shared_ptr<T> &value); void setData(const std::shared_ptr<T> &value);
std::list<std::shared_ptr<TreeNode<T>> > getChildren() const; std::shared_ptr<std::deque<std::shared_ptr<TreeNode<T> > > > getChildren() const;
void setDataChangedSignal(std::function<void(std::shared_ptr<TreeNode<T>>)> f) void setDataChangedSignal(std::function<void(std::shared_ptr<TreeNode<T>>)> f)
{ {
@ -72,7 +71,7 @@ private:
std::shared_ptr<TreeNode<T>> nextOnSameLevel(); std::shared_ptr<TreeNode<T>> nextOnSameLevel();
std::shared_ptr<TreeNode<T>> parent; std::shared_ptr<TreeNode<T>> parent;
std::shared_ptr<T> data; std::shared_ptr<T> data;
std::list<std::shared_ptr<TreeNode<T>>> children; std::shared_ptr<std::deque<std::shared_ptr<TreeNode<T>>>> children;
}; };
template <class T> template <class T>
@ -81,6 +80,7 @@ TreeNode<T>::TreeNode()
this->data = nullptr; this->data = nullptr;
this->nodeDataChanged = nullptr; this->nodeDataChanged = nullptr;
this->treeChanged = nullptr; this->treeChanged = nullptr;
this->children = std::make_shared<std::deque<std::shared_ptr<TreeNode<T>>>>();
} }
template <class T> template <class T>
@ -105,7 +105,7 @@ template<class T>
std::shared_ptr<TreeNode<T> > TreeNode<T>::rcopy() std::shared_ptr<TreeNode<T> > TreeNode<T>::rcopy()
{ {
auto n = std::make_shared<TreeNode<T>>(std::make_shared<T>(*this->getData())); auto n = std::make_shared<TreeNode<T>>(std::make_shared<T>(*this->getData()));
for(auto c : this->getChildren()) for(auto c : *children)
n->addChild(c->rcopy()); n->addChild(c->rcopy());
return n; return n;
} }
@ -114,9 +114,9 @@ template <class T>
const std::shared_ptr<TreeNode<T>> TreeNode<T>::nextSibling() const std::shared_ptr<TreeNode<T>> TreeNode<T>::nextSibling()
{ {
if (parent != nullptr) { if (parent != nullptr) {
auto l = parent->getChildren(); auto l = *(parent->getChildren());
auto it = std::find(l.begin(), l.end(), this->shared_from_this()); auto it = std::find(l.begin(), l.end(), this->shared_from_this());
if (it != l.end() && ++it != l.end()) if (it != l.end() && it+1 != l.end())
return *(++it); //next sibling... return *(++it); //next sibling...
else else
return nullptr; return nullptr;
@ -128,41 +128,9 @@ const std::shared_ptr<TreeNode<T>> TreeNode<T>::nextSibling()
template <class T> template <class T>
const std::shared_ptr<TreeNode<T>> TreeNode<T>::next(TreeWalkStrategy walkStrategy) const std::shared_ptr<TreeNode<T>> TreeNode<T>::next(TreeWalkStrategy walkStrategy)
{ {
if (walkStrategy == TreeWalkStrategy::mixture) if (walkStrategy == TreeWalkStrategy::depthFirst)
// choose node, work through all siblings, choose next node, but don't change branches more than one parent away, except branch is at an end. if (getChildren()->size() > 0)
if (parent != nullptr) { return getChildren()->front();
if (nextSibling() != nullptr) // next sibling
return nextSibling();
else // find next children
{
for (auto n : parent->getChildren())
if (n->getChildren().size() > 0)
return n->getChildren().front();
//return n->getChildren().first();
auto siblingOfParent = parent->nextSibling();
while (siblingOfParent != nullptr && siblingOfParent->getChildren().size() == 0) {
if (siblingOfParent->nextSibling() == nullptr)
siblingOfParent = siblingOfParent->getParent();
else
siblingOfParent = siblingOfParent->nextSibling();
}
if (siblingOfParent != nullptr)
return siblingOfParent->getChildren().front();
//return siblingOfParent->getChildren().first();
else
return nullptr;
}
} else {
if (getChildren().size() > 0)
return getChildren().front();
//return getChildren().first();
else
return nullptr;
}
else if (walkStrategy == TreeWalkStrategy::depthFirst)
if (getChildren().size() > 0)
return getChildren().front();
//return getChildren().first();
else { else {
auto node = this->shared_from_this(); auto node = this->shared_from_this();
while (node->nextSibling() == nullptr && node->getParent() != nullptr) while (node->nextSibling() == nullptr && node->getParent() != nullptr)
@ -173,10 +141,9 @@ const std::shared_ptr<TreeNode<T>> TreeNode<T>::next(TreeWalkStrategy walkStrate
if (parent != nullptr) { if (parent != nullptr) {
auto nextOnLvl = nextOnSameLevel(); auto nextOnLvl = nextOnSameLevel();
if (nextOnLvl == nullptr){ if (nextOnLvl == nullptr){
for (auto n : parent->getChildren()) for (auto n : *(parent->getChildren()))
if (n->getChildren().size() > 0) if (n->getChildren()->size() > 0)
return n->getChildren().front(); return n->getChildren()->front();
//return n->getChildren().first();
} }
else return nextOnLvl; else return nextOnLvl;
} }
@ -193,78 +160,77 @@ const std::shared_ptr<TreeNode<T>> TreeNode<T>::getRoot()
} }
template <class T> template <class T>
void TreeNode<T>::move(std::shared_ptr<TreeNode<T>> to) void TreeNode<T>::move(const std::shared_ptr<TreeNode<T>> &to)
{ {
this->getParent()->getChildren().remove(this->shared_from_this()); this->getParent()->removeChild(this->shared_from_this());
//this->getParent()->getChildren().removeOne(std::shared_ptr<EditorNode>(this)); to->getChildren()->push_back(this->shared_from_this());
to->getChildren().push_back(this->shared_from_this());
//to->getChildren().append(std::shared_ptr<EditorNode>(this));
fireTreeChanged(); fireTreeChanged();
} }
template <class T> template <class T>
void TreeNode<T>::moveChildren(std::shared_ptr<TreeNode<T>> to) void TreeNode<T>::moveChildren(const std::shared_ptr<TreeNode<T>> &to)
{ {
for (auto child : getChildren()) for (auto child : getChildren().get())
child->move(to); child->move(to);
fireTreeChanged(); fireTreeChanged();
} }
template <class T> template <class T>
void TreeNode<T>::addChild(std::shared_ptr<TreeNode<T>> child) void TreeNode<T>::addChild(const std::shared_ptr<TreeNode<T>>& child)
{ {
this->getChildren()->push_back(child);
this->getChildren().push_back(child);
child->setParent(this->shared_from_this()); child->setParent(this->shared_from_this());
fireTreeChanged(); fireTreeChanged();
} }
template <class T> template <class T>
void TreeNode<T>::addChildren(std::shared_ptr<TreeNode<T>> nodeWithChildren) void TreeNode<T>::addChildren(const std::shared_ptr<TreeNode<T>>& nodeWithChildren)
{ {
for(std::shared_ptr<TreeNode<T>> child : nodeWithChildren->getChildren()) for(std::shared_ptr<TreeNode<T>> child : nodeWithChildren->getChildren().get())
{ {
this->getChildren().push_back(child); this->getChildren()->push_back(child);
child->setParent(this->shared_from_this()); child->setParent(this->shared_from_this());
} }
fireTreeChanged(); fireTreeChanged();
} }
template <class T> template <class T>
bool TreeNode<T>::removeChild(std::shared_ptr<TreeNode<T>> child) void TreeNode<T>::removeChild(const std::shared_ptr<TreeNode<T>>& child)
{ {
this->getChildren().remove(child); auto it = children->begin();
bool ret = true; //this->getChildren().removeOne(child); while ( *it != child && it != children->end())
if (ret) fireTreeChanged(); ++it;
return ret; children->erase(it);
fireTreeChanged();
} }
template <class T> template <class T>
bool TreeNode<T>::remove() void TreeNode<T>::remove()
{ {
bool worked = true;
if (children.size() > 0) { if (children->size() > 0) {
for (auto node : children) { for (auto node : *children) {
worked &= node->remove(); node->remove();
} }
} }
if (worked && parent != nullptr) {
parent->getChildren().remove(this->shared_from_this()); if (parent != nullptr) {
//worked &= parent->getChildren().removeOne(std::shared_ptr<EditorNode>(this)); auto n = this->shared_from_this();
auto it = getParent()->getChildren()->begin();
while ( *it != n && it != getParent()->getChildren()->end())
++it;
fireTreeChanged();
parent->getChildren()->erase(it);
} }
if (worked) fireTreeChanged();
return worked;
} }
template<class T> template<class T>
void TreeNode<T>::addChildObject(std::shared_ptr<T> obj) void TreeNode<T>::addChildObject(const std::shared_ptr<T> &obj)
{ {
auto node = std::make_shared<TreeNode<T>>(obj); auto node = std::make_shared<TreeNode<T>>(obj);
this->addChild(node); this->addChild(node);
} }
@ -289,12 +255,12 @@ std::shared_ptr<T> TreeNode<T>::getData() const
template <class T> template <class T>
void TreeNode<T>::setData(const std::shared_ptr<T> &value) void TreeNode<T>::setData(const std::shared_ptr<T> &value)
{ {
fireNodeDataChanged();
data = value; data = value;
fireNodeDataChanged();
} }
template <class T> template <class T>
std::list<std::shared_ptr<TreeNode<T>>> TreeNode<T>::getChildren() const std::shared_ptr<std::deque<std::shared_ptr<TreeNode<T>>>> TreeNode<T>::getChildren() const
{ {
return children; return children;
} }
@ -329,9 +295,8 @@ std::shared_ptr<TreeNode<T>> TreeNode<T>::nextOnSameLevel()
auto node = this->getParent(); auto node = this->getParent();
auto pnode = this->shared_from_this(); auto pnode = this->shared_from_this();
while (lvl > 0 && node != nullptr) { while (lvl > 0 && node != nullptr) {
if (node != pnode->getParent() && node->getChildren().size() > 0) { if (node != pnode && node != pnode->getParent() && node->getChildren()->size() > 0) {
node = node->getChildren().front(); node = node->getChildren()->front();
//node = node->getChildren().first();
--lvl; --lvl;
} else { } else {
pnode = node; pnode = node;
@ -342,9 +307,11 @@ std::shared_ptr<TreeNode<T>> TreeNode<T>::nextOnSameLevel()
node = node->getParent(); node = node->getParent();
++lvl; ++lvl;
} }
else return nullptr;
} }
} }
} }
if (lvl != 0) return nullptr;
return node; return node;
} }

View File

@ -1,16 +1,11 @@
set(HEADERS editorelementdata.h set(HEADERS
guidededitorelementview.h
flowlayout.h flowlayout.h
EditorElementValue.h
StructureField.h StructureField.h
) )
set(SOURCES guidededitorelementview.cpp set(SOURCES
editorelementdata.cpp
guidededitorview.cpp
flowlayout.cpp flowlayout.cpp
EditorElementValue.cpp
StructureField.cpp StructureField.cpp
) )

View File

@ -37,7 +37,7 @@ void GuidedEditorElementView::render()
title->setText(QString::fromStdString(reference->getData()->getName())); title->setText(QString::fromStdString(reference->getData()->getName()));
layout->addWidget(title); layout->addWidget(title);
if (reference->getChildren().size() == 0) { if (reference->getChildren()->size() == 0) {
// need global information about showing syntax, and other hints // need global information about showing syntax, and other hints
if (false ){// reference->getData()->isMultiLine()) { if (false ){// reference->getData()->isMultiLine()) {
@ -51,7 +51,7 @@ void GuidedEditorElementView::render()
subContainer = new QWidget(this); subContainer = new QWidget(this);
FlowLayout* flayout = new FlowLayout(subContainer); FlowLayout* flayout = new FlowLayout(subContainer);
//create and render subelementviews! this is DEPTH_FIRST!!! TODO: make this breadth first! //create and render subelementviews! this is DEPTH_FIRST!!! TODO: make this breadth first!
for (std::shared_ptr<TreeNode<Field>> node : reference->getChildren()) { for (std::shared_ptr<TreeNode<Field>> node : reference->getChildren().get()) {
GuidedEditorElementView* view = new GuidedEditorElementView(subContainer); GuidedEditorElementView* view = new GuidedEditorElementView(subContainer);
view->setReference(node); view->setReference(node);
flayout->addWidget(view); flayout->addWidget(view);

View File

@ -5,15 +5,15 @@
void MainWindow::doSomething() void MainWindow::doSomething()
{ {
std::cout<<"sending nullptr"<<std::endl; std::cout<<"sending nullptr"<<std::endl;
this->editor->addElement(nullptr); //this->editor->addElement(nullptr);
std::cout<<"sent nullptr"<<std::endl; std::cout<<"sent nullptr"<<std::endl;
} }
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
{ {
editor = new GuidedEditorView(this); //editor = new GuidedEditorView(this);
this->setCentralWidget(editor); //this->setCentralWidget(editor);
dockWidget = new QDockWidget(this); dockWidget = new QDockWidget(this);
this->addDockWidget(Qt::LeftDockWidgetArea, dockWidget); this->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);

View File

@ -9,7 +9,16 @@ class TreeTest: public ::testing::Test {
protected: protected:
virtual void SetUp(){ virtual void SetUp(){
for(int i = 0; i < 5; ++i) { for(int i = 0; i < 5; ++i) {
t2.getRoot()->addChildObject(std::make_shared<std::string>("blah")); t2.getRoot()->addChildObject(std::make_shared<std::string>("a"+std::to_string(i)));
}
for(int i = 0; i < 5; ++i) {
t3.getRoot()->addChildObject(std::make_shared<std::string>("a"+std::to_string(i)));
}
for(int i = 0; i < 5; ++i) {
t3.getRoot()->getChildren()->at(2)->addChildObject(std::make_shared<std::string>("b" + std::to_string(i)));
}
for(int i = 0; i < 3; ++i) {
t3.getRoot()->getChildren()->at(4)->addChildObject(std::make_shared<std::string>("c" + std::to_string(i)));
} }
} }
@ -23,19 +32,82 @@ class TreeTest: public ::testing::Test {
TEST_F(TreeTest, IsEmptyInitially) { TEST_F(TreeTest, IsEmptyInitially) {
EXPECT_EQ(0, t.getRoot()->getDistanceFromRoot()); EXPECT_EQ(0, t.getRoot()->getDistanceFromRoot());
EXPECT_EQ(0, t.getRoot()->getChildren().size()); EXPECT_EQ(0, t.getRoot()->getChildren()->size());
} }
TEST_F(TreeTest, blah) { TEST_F(TreeTest, AddingOneLayer) {
EXPECT_EQ(5, t2.getRoot()->getChildren().size()); EXPECT_EQ(5, t2.getRoot()->getChildren()->size());
auto last = t2.getRoot()->getChildren().back(); auto last = t2.getRoot()->getChildren()->back();
EXPECT_EQ(1, last->getDistanceFromRoot()); EXPECT_EQ(1, last->getDistanceFromRoot());
} }
TEST_F(TreeTest, AddingTwoLayers) {
EXPECT_EQ(2, t3.getRoot()->getChildren()->at(2)->getChildren()->at(2)->getDistanceFromRoot());
}
TEST(sample_test_case, sample_test)
{ TEST_F(TreeTest, RemovalSingleNode) {
EXPECT_EQ(1, 1); auto node = t3.getRoot()->getChildren()->at(2)->getChildren()->at(2);
node->remove();
EXPECT_EQ(4, t3.getRoot()->getChildren()->at(2)->getChildren()->size());
}
TEST_F(TreeTest, RecursiveRemoval) {
auto node = t3.getRoot()->getChildren()->at(2);
node->remove();
EXPECT_EQ(4, t3.getRoot()->getChildren()->size());
}
TEST_F(TreeTest, SingleMovement) {
auto node = t3.getRoot()->getChildren()->at(2)->getChildren()->at(3);
auto to = t3.getRoot()->getChildren()->at(3);
node->move(to);
EXPECT_EQ(1, to->getChildren()->size());
}
TEST_F(TreeTest, RecursiveMovement) {
auto node = t3.getRoot()->getChildren()->at(2);
auto to = t3.getRoot()->getChildren()->at(3);
node->move(to);
EXPECT_EQ(1, to->getChildren()->size());
EXPECT_EQ(5, to->getChildren()->at(0)->getChildren()->size());
}
TEST_F(TreeTest, Copy) {
auto node = t3.getRoot()->getChildren()->at(2);
auto newnode = node->copy();
EXPECT_EQ(0, newnode->getChildren()->size());
}
TEST_F(TreeTest, RecursiveCopy) {
auto node = t3.getRoot()->getChildren()->at(2);
auto newnode = node->rcopy();
EXPECT_EQ(5, newnode->getChildren()->size());
}
TEST_F(TreeTest, TraverseTreeDepth) {
EXPECT_EQ(5, t3.getRoot()->getChildren()->size());
EXPECT_EQ(5, t3.getRoot()->getChildren()->at(2)->getChildren()->size());
std::string expectedResult = " a0 a1 a2 b0 b1 b2 b3 b4 a3 a4 c0 c1 c2";
std::string result = "";
TreeWalkStrategy walk = TreeWalkStrategy::depthFirst;
auto node = t3.getFirst();
while (node != nullptr) {
result = result + " " + node->getData()->c_str();
node = node->next(walk);
}
std::cout << result <<std::endl;
EXPECT_EQ(expectedResult, result);
}
TEST_F(TreeTest, TraverseTreeBreadth) {
EXPECT_EQ(5, t3.getRoot()->getChildren()->size());
EXPECT_EQ(5, t3.getRoot()->getChildren()->at(2)->getChildren()->size());
std::string expectedResult = " a0 a1 a2 a3 a4 b0 b1 b2 b3 b4 c0 c1 c2";
std::string result = "";
TreeWalkStrategy walk = TreeWalkStrategy::breadthFirst;
auto node = t3.getFirst();
while (node != nullptr) {
result = result + " " + node->getData()->c_str();
node = node->next(walk);
}
std::cout << result <<std::endl;
EXPECT_EQ(expectedResult, result);
} }