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();
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 treeChanged(std::shared_ptr<TreeNode<T>> node);

View File

@ -4,7 +4,7 @@
#include <iostream>
#include <memory>
#include <functional>
#include <list>
#include <deque>
#include <algorithm>
template <class T>
@ -12,8 +12,7 @@ class TreeNode;
enum class TreeWalkStrategy {
depthFirst,
breadthFirst,
mixture
breadthFirst
};
template <class 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>> getRoot();
void move(std::shared_ptr<TreeNode<T>> to); //as child
void moveChildren(std::shared_ptr<TreeNode<T>> to); //all children but not the 'executing' element
void move(const std::shared_ptr<TreeNode<T> > &to); //as child
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 addChildren(std::shared_ptr<TreeNode<T>> nodeWithChildren);
bool removeChild(std::shared_ptr<TreeNode<T>> child);
bool remove();
void addChild(const std::shared_ptr<TreeNode<T> > &child);
void addChildren(const std::shared_ptr<TreeNode<T> > &nodeWithChildren);
void removeChild(const std::shared_ptr<TreeNode<T> > &child);
void remove();
void addChildObject(std::shared_ptr<T> obj);
void addChildObject(const std::shared_ptr<T> &obj);
uint getDistanceFromRoot();
@ -48,7 +47,7 @@ public:
std::shared_ptr<T> getData() const;
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)
{
@ -72,7 +71,7 @@ private:
std::shared_ptr<TreeNode<T>> nextOnSameLevel();
std::shared_ptr<TreeNode<T>> parent;
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>
@ -81,6 +80,7 @@ TreeNode<T>::TreeNode()
this->data = nullptr;
this->nodeDataChanged = nullptr;
this->treeChanged = nullptr;
this->children = std::make_shared<std::deque<std::shared_ptr<TreeNode<T>>>>();
}
template <class T>
@ -105,7 +105,7 @@ template<class T>
std::shared_ptr<TreeNode<T> > TreeNode<T>::rcopy()
{
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());
return n;
}
@ -114,9 +114,9 @@ template <class T>
const std::shared_ptr<TreeNode<T>> TreeNode<T>::nextSibling()
{
if (parent != nullptr) {
auto l = parent->getChildren();
auto l = *(parent->getChildren());
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...
else
return nullptr;
@ -128,41 +128,9 @@ const std::shared_ptr<TreeNode<T>> TreeNode<T>::nextSibling()
template <class T>
const std::shared_ptr<TreeNode<T>> TreeNode<T>::next(TreeWalkStrategy walkStrategy)
{
if (walkStrategy == TreeWalkStrategy::mixture)
// 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 (parent != nullptr) {
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();
if (walkStrategy == TreeWalkStrategy::depthFirst)
if (getChildren()->size() > 0)
return getChildren()->front();
else {
auto node = this->shared_from_this();
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) {
auto nextOnLvl = nextOnSameLevel();
if (nextOnLvl == nullptr){
for (auto n : parent->getChildren())
if (n->getChildren().size() > 0)
return n->getChildren().front();
//return n->getChildren().first();
for (auto n : *(parent->getChildren()))
if (n->getChildren()->size() > 0)
return n->getChildren()->front();
}
else return nextOnLvl;
}
@ -193,78 +160,77 @@ const std::shared_ptr<TreeNode<T>> TreeNode<T>::getRoot()
}
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()->getChildren().removeOne(std::shared_ptr<EditorNode>(this));
to->getChildren().push_back(this->shared_from_this());
//to->getChildren().append(std::shared_ptr<EditorNode>(this));
this->getParent()->removeChild(this->shared_from_this());
to->getChildren()->push_back(this->shared_from_this());
fireTreeChanged();
}
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);
fireTreeChanged();
}
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());
fireTreeChanged();
}
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());
}
fireTreeChanged();
}
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);
bool ret = true; //this->getChildren().removeOne(child);
if (ret) fireTreeChanged();
return ret;
auto it = children->begin();
while ( *it != child && it != children->end())
++it;
children->erase(it);
fireTreeChanged();
}
template <class T>
bool TreeNode<T>::remove()
void TreeNode<T>::remove()
{
bool worked = true;
if (children.size() > 0) {
for (auto node : children) {
worked &= node->remove();
if (children->size() > 0) {
for (auto node : *children) {
node->remove();
}
}
if (worked && parent != nullptr) {
parent->getChildren().remove(this->shared_from_this());
//worked &= parent->getChildren().removeOne(std::shared_ptr<EditorNode>(this));
if (parent != nullptr) {
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>
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);
this->addChild(node);
}
@ -289,12 +255,12 @@ std::shared_ptr<T> TreeNode<T>::getData() const
template <class T>
void TreeNode<T>::setData(const std::shared_ptr<T> &value)
{
fireNodeDataChanged();
data = value;
fireNodeDataChanged();
}
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;
}
@ -329,9 +295,8 @@ std::shared_ptr<TreeNode<T>> TreeNode<T>::nextOnSameLevel()
auto node = this->getParent();
auto pnode = this->shared_from_this();
while (lvl > 0 && node != nullptr) {
if (node != pnode->getParent() && node->getChildren().size() > 0) {
node = node->getChildren().front();
//node = node->getChildren().first();
if (node != pnode && node != pnode->getParent() && node->getChildren()->size() > 0) {
node = node->getChildren()->front();
--lvl;
} else {
pnode = node;
@ -342,9 +307,11 @@ std::shared_ptr<TreeNode<T>> TreeNode<T>::nextOnSameLevel()
node = node->getParent();
++lvl;
}
else return nullptr;
}
}
}
if (lvl != 0) return nullptr;
return node;
}

View File

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

View File

@ -37,7 +37,7 @@ void GuidedEditorElementView::render()
title->setText(QString::fromStdString(reference->getData()->getName()));
layout->addWidget(title);
if (reference->getChildren().size() == 0) {
if (reference->getChildren()->size() == 0) {
// need global information about showing syntax, and other hints
if (false ){// reference->getData()->isMultiLine()) {
@ -51,7 +51,7 @@ void GuidedEditorElementView::render()
subContainer = new QWidget(this);
FlowLayout* flayout = new FlowLayout(subContainer);
//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);
view->setReference(node);
flayout->addWidget(view);

View File

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

View File

@ -9,7 +9,16 @@ class TreeTest: public ::testing::Test {
protected:
virtual void SetUp(){
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) {
EXPECT_EQ(0, t.getRoot()->getDistanceFromRoot());
EXPECT_EQ(0, t.getRoot()->getChildren().size());
EXPECT_EQ(0, t.getRoot()->getChildren()->size());
}
TEST_F(TreeTest, blah) {
EXPECT_EQ(5, t2.getRoot()->getChildren().size());
auto last = t2.getRoot()->getChildren().back();
TEST_F(TreeTest, AddingOneLayer) {
EXPECT_EQ(5, t2.getRoot()->getChildren()->size());
auto last = t2.getRoot()->getChildren()->back();
EXPECT_EQ(1, last->getDistanceFromRoot());
}
TEST(sample_test_case, sample_test)
{
EXPECT_EQ(1, 1);
TEST_F(TreeTest, AddingTwoLayers) {
EXPECT_EQ(2, t3.getRoot()->getChildren()->at(2)->getChildren()->at(2)->getDistanceFromRoot());
}
TEST_F(TreeTest, RemovalSingleNode) {
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);
}