1/*
2 * Copyright (C) 2012 Cutehacks AS. All rights reserved.
3 * info@cutehacks.com
4 * http://cutehacks.com
5 *
6 * This file is part of Fly.
7 *
8 * Fly is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Fly is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Fly. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#ifndef NODE_H
23#define NODE_H
24
25#include <QString>
26#include <QHash>
27#include <QList>
28#include <QStack>
29#include <QSharedData>
30#include <QSharedDataPointer>
31#include <QDebug>
32
33class Node
34{
35 friend QDebug operator<<(QDebug dbg, const Node &n);
36public:
37 Node(Node *parent = 0) : m_parent(parent) { appendToParent(); }
38 //Node(const Node &other) : parent(0) { d = other.d; }
39 Node(const QString &type, Node *parent = 0) : m_parent(parent), m_type(type) { appendToParent(); }
40 ~Node() { foreach (Node *child, m_children) delete child; }
41
42 Node *parent() { return m_parent; }
43 Node *child(int i) const { return m_children.at(i); }
44 int childCount() const { return m_children.count(); }
45 int indexOfChild(Node *child) const { return m_children.indexOf(child); }
46 bool hasSiblings() const { return m_parent && (m_parent->childCount() > 1); }
47
48 Node *firstChildOfType(const QString &type) const
49 {
50 foreach(Node *node, m_children)
51 if (node->type() == type)
52 return node;
53 return 0;
54 }
55
56 QList<Node*> decendantsOfType(const QString &type)
57 {
58 QStack<Node*> hierarchy;
59 hierarchy.push(this);
60 QList<Node*> flat;
61 while (!hierarchy.isEmpty()) {
62 Node *current = hierarchy.pop();
63 for (int i = 0; i < current->childCount(); ++i)
64 hierarchy.push(current->child(i));
65 if (current->type() == type)
66 flat.prepend(current);
67 }
68 return flat;
69 }
70
71 void setType(const QString &type) { m_type = type; }
72 QString type() const { return m_type; }
73
74 void setText(const QString &text) { m_text = text; }
75 QString text() const { return m_text; }
76
77 void setAttribute(const QString &name, const QString &value) { m_attributes.insert(name, value); }
78 QString attribute(const QString &name) const { return m_attributes.value(name); }
79
80 QHash<QString,QString> attributes() const { return m_attributes; }
81
82private:
83 void appendChild(Node *child) { m_children.append(child); }
84 void appendToParent() { if (m_parent) m_parent->appendChild(this); }
85
86 Node *m_parent;
87 QList<Node*> m_children;
88
89 QString m_type;
90 QString m_text;
91 QHash<QString, QString> m_attributes;
92};
93
94inline QDebug operator<<(QDebug dbg, const Node &n)
95{
96 dbg << "<";
97 dbg.nospace()<< n.m_type;
98 if (!n.m_attributes.isEmpty())
99 dbg.nospace() << ", " << n.m_attributes;
100 if (!n.m_text.isEmpty())
101 dbg.nospace() << ", " << n.m_text;
102 dbg.space();
103 if (!n.m_children.isEmpty()) {
104 dbg.nospace() << endl;
105 foreach (Node *child, n.m_children)
106 dbg.nospace() << (*child) << endl;
107 }
108 dbg.nospace() << ">";
109 return dbg;
110}
111
112#endif
113