1 /*
2 This file is part of Rocs.
3 SPDX-FileCopyrightText: 2006-2007 Gael de Chalendar <kleag@free.fr>
4 SPDX-FileCopyrightText: 2012-2014 Andreas Cord-Landwehr <cordlandwehr@kde.org>
5 SPDX-License-Identifier: GPL-2.0-only
6 */
7
8
9 #include "dotgrammarhelper.h"
10 #include "dotgrammar.h"
11 #include "graphdocument.h"
12 #include "node.h"
13 #include "edge.h"
14 #include "logging_p.h"
15
16 #include <QFile>
17
18 extern DotParser::DotGraphParsingHelper* phelper;
19
20 using namespace GraphTheory;
21
22 namespace DotParser
23 {
24
DotGraphParsingHelper()25 DotGraphParsingHelper::DotGraphParsingHelper():
26 attributeId(),
27 valid(),
28 attributed(),
29 unprocessedAttributes(),
30 graphAttributes(),
31 nodeAttributes(),
32 edgeAttributes(),
33 graphAttributeStack(),
34 nodeAttributeStack(),
35 edgeAttributeStack(),
36 edgebounds(),
37 currentNode(),
38 currentEdge(),
39 nodeMap()
40 {
41 }
42
setObjectAttributes(QObject * graphElement,const AttributesMap & attributes)43 void DotGraphParsingHelper::setObjectAttributes(QObject *graphElement, const AttributesMap &attributes)
44 {
45 AttributesMap::const_iterator iter;
46 iter = attributes.constBegin();
47 for (; iter != attributes.constEnd(); ++iter) {
48 if (iter.key() == "label" && strcmp(graphElement->metaObject()->className(), "Edge") == 0) {
49 QString label = iter.value();
50 label.replace("\\n", "\n");
51 graphElement->setProperty("name", label);
52 } else {
53 graphElement->setProperty(iter.key().toUtf8(), iter.value());
54 }
55 }
56 }
57
setDocumentAttributes()58 void DotGraphParsingHelper::setDocumentAttributes()
59 {
60 setObjectAttributes(document.data(), graphAttributes);
61 }
62
setSubGraphAttributes()63 void DotGraphParsingHelper::setSubGraphAttributes()
64 {
65 // not implemented
66 }
67
setNodeAttributes()68 void DotGraphParsingHelper::setNodeAttributes()
69 {
70 if (!currentNode) {
71 return;
72 }
73 AttributesMap::ConstIterator iter;
74 iter = nodeAttributes.constBegin();
75 for (; iter != nodeAttributes.constEnd(); ++iter) {
76 if (!currentNode->dynamicProperties().contains(iter.key())) {
77 currentNode->type()->addDynamicProperty(iter.key());
78 }
79 QString key = iter.key(); // do not overwrite labels
80 if (key == "name") {
81 key = "dot_name";
82 }
83 currentNode->setDynamicProperty(key, iter.value());
84 }
85 }
86
setEdgeAttributes()87 void DotGraphParsingHelper::setEdgeAttributes()
88 {
89 if (!currentEdge) {
90 return;
91 }
92 AttributesMap::ConstIterator iter;
93 iter = edgeAttributes.constBegin();
94 for (; iter != edgeAttributes.constEnd(); ++iter) {
95 if (!currentEdge->dynamicProperties().contains(iter.key())) {
96 currentEdge->type()->addDynamicProperty(iter.key());
97 }
98 currentEdge->setDynamicProperty(iter.key(), iter.value());
99 }
100 }
101
applyAttributedList()102 void DotGraphParsingHelper::applyAttributedList()
103 {
104 if (attributed == "graph") {
105 if (unprocessedAttributes.find("bb") != unprocessedAttributes.end()) {
106 std::vector< int > v;
107 parseIntegers(unprocessedAttributes["bb"].toStdString().c_str(), v);
108 // if (v.size() >= 4) {
109 // qCDebug(GRAPHTHEORY_FILEFORMAT) << "setting width and height to " << v[2] << v[3];
110 // }
111 }
112 AttributesMap::const_iterator it, it_end;
113 it = unprocessedAttributes.constBegin();
114 it_end = unprocessedAttributes.constEnd();
115 for (; it != it_end; it++) {
116 graphAttributes[it.key()] = it.value();
117 }
118 } else if (attributed == "node") {
119 AttributesMap::const_iterator it, it_end;
120 it = unprocessedAttributes.constBegin();
121 it_end = unprocessedAttributes.constEnd();
122 for (; it != it_end; it++) {
123 nodeAttributes[it.key()] = it.value();
124 }
125 } else if (attributed == "edge") {
126 AttributesMap::const_iterator it, it_end;
127 it = unprocessedAttributes.constBegin();
128 it_end = unprocessedAttributes.constEnd();
129 for (; it != it_end; it++) {
130 edgeAttributes[it.key()] = it.value();
131 }
132 }
133 unprocessedAttributes.clear();
134 }
135
createNode(const QString & name)136 void DotGraphParsingHelper::createNode(const QString &name)
137 {
138 edgebounds.clear(); //TODO explain meaning of this
139
140 if (nodeMap.contains(name)) {
141 qCCritical(GRAPHTHEORY_FILEFORMAT) << "Omitting data element, identifying label is already used: "<< name;
142 return;
143 }
144 currentNode = GraphTheory::Node::create(document);
145 if (!currentNode->type()->dynamicProperties().contains("name")) {
146 currentNode->type()->addDynamicProperty("name");
147 }
148 currentNode->setDynamicProperty("name", name);
149 nodeMap.insert(name, currentNode);
150 }
151
createSubGraph()152 void DotGraphParsingHelper::createSubGraph()
153 {
154 // currently not implemented
155 }
156
setSubGraphId(const QString & identifier)157 void DotGraphParsingHelper::setSubGraphId(const QString &identifier)
158 {
159 Q_UNUSED(identifier);
160 // currently not implemented
161 }
162
leaveSubGraph()163 void DotGraphParsingHelper::leaveSubGraph()
164 {
165 // currently not implemented
166 }
167
createEdge()168 void DotGraphParsingHelper::createEdge()
169 {
170 QString fromId, toId;
171
172 if (edgebounds.isEmpty()) {
173 return;
174 }
175 fromId = edgebounds.first();
176 edgebounds.removeFirst();
177 while (!edgebounds.isEmpty()) {
178 toId = edgebounds.first();
179 edgebounds.removeFirst();
180
181 // if necessary create from id
182 if (!nodeMap.contains(fromId)) {
183 NodePtr from = Node::create(document);
184 from->setDynamicProperty("name", fromId);
185 if (from->dynamicProperties().contains("name")) {
186 from->type()->addDynamicProperty("name");
187 }
188 nodeMap.insert(fromId, from);
189 currentNode = from;
190 setNodeAttributes();
191 }
192 NodePtr from = nodeMap[fromId];
193
194 // if necessary create to node
195 if (!nodeMap.contains(toId)) {
196 NodePtr to = Node::create(document);
197 if (to->dynamicProperties().contains("name")) {
198 to->type()->addDynamicProperty("name");
199 }
200 to->setDynamicProperty("name", toId);
201 nodeMap.insert(toId, to);
202 currentNode = to;
203 setNodeAttributes();
204 }
205 NodePtr to = nodeMap[toId];
206
207 currentEdge = Edge::create(from, to);
208 // qCDebug(GRAPHTHEORY_FILEFORMAT) << "Creating new edge: " << from->identifier() << " -> " << to->identifier();
209 setEdgeAttributes();
210
211 fromId = toId;
212 }
213 edgebounds.clear();
214 }
215
216 }
217