FInished test for the Tree structure classes
This commit is contained in:
parent
bbc0734ae5
commit
e997802305
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Reference in New Issue