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 | |
33 | class Node |
34 | { |
35 | friend QDebug operator<<(QDebug dbg, const Node &n); |
36 | public: |
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 | |
82 | private: |
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 | |
94 | inline 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 | |