File indexing completed on 2024-05-19 15:27:47
0001 /* This file is part of KGraphViewer. 0002 Copyright (C) 2006-2007 Gael de Chalendar <kleag@free.fr> 0003 0004 KGraphViewer is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public 0006 License as published by the Free Software Foundation, version 2. 0007 0008 This program is distributed in the hope that it will be useful, 0009 but WITHOUT ANY WARRANTY; without even the implied warranty of 0010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0011 General Public License for more details. 0012 0013 You should have received a copy of the GNU General Public License 0014 along with this program; if not, write to the Free Software 0015 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0016 02110-1301, USA 0017 */ 0018 0019 #include "DotGraphParsingHelper.h" 0020 #include "dotdefaults.h" 0021 #include "dotgrammar.h" 0022 #include "dotgraph.h" 0023 //#include "graphsubgraph.h" 0024 #include "graphedge.h" 0025 #include "graphnode.h" 0026 #include "kgraphviewerlib_debug.h" 0027 0028 #include <boost/spirit/include/classic_confix.hpp> 0029 #include <boost/spirit/include/classic_core.hpp> 0030 #include <boost/spirit/include/classic_distinct.hpp> 0031 #include <boost/spirit/include/classic_loops.hpp> 0032 #include <boost/throw_exception.hpp> 0033 0034 #include <iostream> 0035 0036 #include <QDebug> 0037 0038 #include <QFile> 0039 #include <QUuid> 0040 0041 using namespace std; 0042 0043 extern KGraphViewer::DotGraphParsingHelper *phelper; 0044 0045 namespace KGraphViewer 0046 { 0047 #define KGV_MAX_ITEMS_TO_LOAD std::numeric_limits<int>::max() 0048 0049 DotGraphParsingHelper::DotGraphParsingHelper() 0050 : attrid() 0051 , valid() 0052 , attributed() 0053 , subgraphid() 0054 , uniq(0) 0055 , attributes() 0056 , graphAttributes() 0057 , nodesAttributes() 0058 , edgesAttributes() 0059 , graphAttributesStack() 0060 , nodesAttributesStack() 0061 , edgesAttributesStack() 0062 , edgebounds() 0063 , z(0) 0064 , maxZ(0) 0065 , graph(nullptr) 0066 , gs(nullptr) 0067 , gn(nullptr) 0068 , ge(nullptr) 0069 { 0070 } 0071 0072 void DotGraphParsingHelper::setgraphelementattributes(GraphElement *ge, const AttributesMap &attributes) 0073 { 0074 AttributesMap::const_iterator it, it_end; 0075 it = attributes.begin(); 0076 it_end = attributes.end(); 0077 for (; it != it_end; it++) { 0078 // qCDebug(KGRAPHVIEWERLIB_LOG) << " " << QString::fromStdString((*it).first) << "\t=\t'" << QString::fromStdString((*it).second) <<"'"; 0079 if ((*it).first == "label") { 0080 QString label = QString::fromUtf8((*it).second.c_str()); 0081 label.replace("\\n", "\n"); 0082 (*ge).attributes()["label"] = label; 0083 } else { 0084 (*ge).attributes()[QString::fromStdString((*it).first)] = QString::fromStdString((*it).second); 0085 } 0086 } 0087 0088 DotRenderOpVec ops = ge->renderOperations(); 0089 if (attributes.find("_draw_") != attributes.end()) { 0090 parse_renderop((attributes.find("_draw_"))->second, ops); 0091 // qCDebug(KGRAPHVIEWERLIB_LOG) << "element renderOperations size is now " << ge->renderOperations().size(); 0092 } 0093 if (attributes.find("_ldraw_") != attributes.end()) { 0094 parse_renderop(attributes.find("_ldraw_")->second, ops); 0095 // qCDebug(KGRAPHVIEWERLIB_LOG) << "element renderOperations size is now " << ge->renderOperations().size(); 0096 } 0097 if (attributes.find("_hldraw_") != attributes.end()) { 0098 parse_renderop(attributes.find("_hldraw_")->second, ops); 0099 // qCDebug(KGRAPHVIEWERLIB_LOG) << "element renderOperations size is now " << ge->renderOperations().size(); 0100 } 0101 if (attributes.find("_tldraw_") != attributes.end()) { 0102 parse_renderop(attributes.find("_tldraw_")->second, ops); 0103 // qCDebug(KGRAPHVIEWERLIB_LOG) << "element renderOperations size is now " << ge->renderOperations().size(); 0104 } 0105 ge->setRenderOperations(ops); 0106 } 0107 0108 void DotGraphParsingHelper::setgraphattributes() 0109 { 0110 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Attributes for graph are : "; 0111 setgraphelementattributes(graph, graphAttributes); 0112 } 0113 0114 void DotGraphParsingHelper::setsubgraphattributes() 0115 { 0116 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Attributes for subgraph are : "; 0117 gs->setZ(z); 0118 // qCDebug(KGRAPHVIEWERLIB_LOG) << "z="<<gs->z(); 0119 setgraphelementattributes(gs, graphAttributes); 0120 } 0121 0122 void DotGraphParsingHelper::setnodeattributes() 0123 { 0124 // qCDebug(KGRAPHVIEWERLIB_LOG) << "setnodeattributes with z = " << z; 0125 0126 if (gn == nullptr) { 0127 // qCDebug(KGRAPHVIEWERLIB_LOG) << "gn is null"; 0128 return; 0129 } 0130 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Attributes for node " << gn->id() << " are : "; 0131 gn->setZ(z + 1); 0132 // qCDebug(KGRAPHVIEWERLIB_LOG) << "z="<<gn->z(); 0133 setgraphelementattributes(gn, nodesAttributes); 0134 } 0135 0136 void DotGraphParsingHelper::setedgeattributes() 0137 { 0138 // qCDebug(KGRAPHVIEWERLIB_LOG) << "setedgeattributeswith z = " << z; 0139 0140 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Attributes for edge " << ge->fromNode()->id() << "->" << ge->toNode()->id() << " are : "; 0141 ge->setZ(z + 1); 0142 // qCDebug(KGRAPHVIEWERLIB_LOG) << "z="<<ge->z(); 0143 setgraphelementattributes(ge, edgesAttributes); 0144 0145 DotRenderOpVec ops = ge->renderOperations(); 0146 if (edgesAttributes.find("_tdraw_") != edgesAttributes.end()) { 0147 parse_renderop(edgesAttributes["_tdraw_"], ops); 0148 // qCDebug(KGRAPHVIEWERLIB_LOG) << "edge renderOperations size is now " << ge->renderOperations().size(); 0149 DotRenderOpVec::const_iterator it, it_end; 0150 it = ops.constBegin(); 0151 it_end = ops.constEnd(); 0152 for (; it != it_end; it++) 0153 ge->arrowheads().push_back(*it); 0154 } 0155 if (edgesAttributes.find("_hdraw_") != edgesAttributes.end()) { 0156 parse_renderop(edgesAttributes["_hdraw_"], ops); 0157 // qCDebug(KGRAPHVIEWERLIB_LOG) << "edge renderOperations size is now " << ge->renderOperations().size(); 0158 DotRenderOpVec::const_iterator it, it_end; 0159 it = ops.constBegin(); 0160 it_end = ops.constEnd(); 0161 for (; it != it_end; it++) 0162 ge->arrowheads().push_back(*it); 0163 } 0164 ge->setRenderOperations(ops); 0165 } 0166 0167 void DotGraphParsingHelper::setattributedlist() 0168 { 0169 // // qCDebug(KGRAPHVIEWERLIB_LOG) << "Setting attributes list for " << QString::fromStdString(attributed); 0170 if (attributed == "graph") { 0171 if (attributes.find("bb") != attributes.end()) { 0172 std::vector<int> v; 0173 parse_integers(attributes["bb"].c_str(), v); 0174 if (v.size() >= 4) { 0175 // qCDebug(KGRAPHVIEWERLIB_LOG) << "setting width and height to " << v[2] << v[3]; 0176 graph->width(v[2]); 0177 graph->height(v[3]); 0178 } 0179 } 0180 AttributesMap::const_iterator it, it_end; 0181 it = attributes.begin(); 0182 it_end = attributes.end(); 0183 for (; it != it_end; it++) { 0184 // qCDebug(KGRAPHVIEWERLIB_LOG) << " " << QString::fromStdString((*it).first) << " = " << QString::fromStdString((*it).second); 0185 graphAttributes[(*it).first] = (*it).second; 0186 } 0187 } else if (attributed == "node") { 0188 AttributesMap::const_iterator it, it_end; 0189 it = attributes.begin(); 0190 it_end = attributes.end(); 0191 for (; it != it_end; it++) { 0192 // qCDebug(KGRAPHVIEWERLIB_LOG) << " " << QString::fromStdString((*it).first) << " = " << QString::fromStdString((*it).second); 0193 nodesAttributes[(*it).first] = (*it).second; 0194 } 0195 } else if (attributed == "edge") { 0196 AttributesMap::const_iterator it, it_end; 0197 it = attributes.begin(); 0198 it_end = attributes.end(); 0199 for (; it != it_end; it++) { 0200 // qCDebug(KGRAPHVIEWERLIB_LOG) << " " << QString::fromStdString((*it).first) << " = " << QString::fromStdString((*it).second); 0201 edgesAttributes[(*it).first] = (*it).second; 0202 } 0203 } 0204 attributes.clear(); 0205 } 0206 0207 void DotGraphParsingHelper::createnode(const std::string &nodeid) 0208 { 0209 QString id = QString::fromStdString(nodeid); 0210 // qCDebug(KGRAPHVIEWERLIB_LOG) << id; 0211 gn = dynamic_cast<GraphNode *>(graph->elementNamed(id)); 0212 if (gn == nullptr && graph->nodes().size() < KGV_MAX_ITEMS_TO_LOAD) { 0213 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Creating a new node" << z << (void*)gs; 0214 gn = new GraphNode(); 0215 gn->setId(id); 0216 // gn->label(QString::fromStdString(nodeid)); 0217 if (z > 0 && gs) { 0218 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Adding node" << id << "in subgraph" << gs->id(); 0219 gs->content().push_back(gn); 0220 } else { 0221 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Adding node" << id; 0222 graph->nodes()[id] = gn; 0223 } 0224 } 0225 edgebounds.clear(); 0226 } 0227 0228 void DotGraphParsingHelper::createsubgraph() 0229 { 0230 // qCDebug(KGRAPHVIEWERLIB_LOG) ; 0231 if (phelper) { 0232 std::string str = phelper->subgraphid; 0233 if (str.empty()) { 0234 std::ostringstream oss; 0235 oss << "kgv_id_" << phelper->uniq++; 0236 str = oss.str(); 0237 } 0238 // qCDebug(KGRAPHVIEWERLIB_LOG) << QString::fromStdString(str); 0239 if (graph->subgraphs().find(QString::fromStdString(str)) == graph->subgraphs().end()) { 0240 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Creating a new subgraph"; 0241 gs = new GraphSubgraph(); 0242 gs->setId(QString::fromStdString(str)); 0243 // gs->label(QString::fromStdString(str)); 0244 graph->subgraphs().insert(QString::fromStdString(str), gs); 0245 // qCDebug(KGRAPHVIEWERLIB_LOG) << "there is now"<<graph->subgraphs().size()<<"subgraphs in" << graph; 0246 } else { 0247 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Found existing subgraph"; 0248 gs = *(graph->subgraphs().find(QString::fromStdString(str))); 0249 } 0250 phelper->subgraphid = ""; 0251 } 0252 } 0253 0254 void DotGraphParsingHelper::createedges() 0255 { 0256 // qCDebug(KGRAPHVIEWERLIB_LOG); 0257 std::string node1Name, node2Name; 0258 node1Name = edgebounds.front(); 0259 edgebounds.pop_front(); 0260 while (!edgebounds.empty()) { 0261 node2Name = edgebounds.front(); 0262 edgebounds.pop_front(); 0263 0264 if (graph->nodes().size() >= KGV_MAX_ITEMS_TO_LOAD || graph->edges().size() >= KGV_MAX_ITEMS_TO_LOAD) { 0265 return; 0266 } 0267 // qCDebug(KGRAPHVIEWERLIB_LOG) << QString::fromStdString(node1Name) << ", " << QString::fromStdString(node2Name); 0268 ge = new GraphEdge(); 0269 GraphElement *gn1 = graph->elementNamed(QString::fromStdString(node1Name)); 0270 if (gn1 == nullptr) { 0271 // qCDebug(KGRAPHVIEWERLIB_LOG) << "new node 1"; 0272 gn1 = new GraphNode(); 0273 gn1->setId(QString::fromStdString(node1Name)); 0274 graph->nodes()[QString::fromStdString(node1Name)] = dynamic_cast<GraphNode *>(gn1); 0275 } 0276 GraphElement *gn2 = graph->elementNamed(QString::fromStdString(node2Name)); 0277 if (gn2 == nullptr) { 0278 // qCDebug(KGRAPHVIEWERLIB_LOG) << "new node 2"; 0279 gn2 = new GraphNode(); 0280 gn2->setId(QString::fromStdString(node2Name)); 0281 graph->nodes()[QString::fromStdString(node2Name)] = dynamic_cast<GraphNode *>(gn2); 0282 } 0283 // qCDebug(KGRAPHVIEWERLIB_LOG) << "Found gn1="<<gn1<<" and gn2=" << gn2; 0284 if (gn1 == nullptr || gn2 == nullptr) { 0285 qCWarning(KGRAPHVIEWERLIB_LOG) << "Unable to find or create edge bound(s) gn1=" << gn1 << "; gn2=" << gn2; 0286 } 0287 ge->setFromNode(gn1); 0288 ge->setToNode(gn2); 0289 // qCDebug(KGRAPHVIEWERLIB_LOG) << ge->fromNode()->id() << " -> " << ge->toNode()->id(); 0290 setedgeattributes(); 0291 // qCDebug(KGRAPHVIEWERLIB_LOG) << ge->id(); 0292 if (ge->id().isEmpty()) { 0293 ge->setId(QString::fromStdString(node1Name) + QString::fromStdString(node2Name) + QUuid::createUuid().toString().remove('{').remove('}').remove('-')); 0294 } 0295 // qCDebug(KGRAPHVIEWERLIB_LOG) << ge->id(); 0296 // qCDebug(KGRAPHVIEWERLIB_LOG) << "num before=" << graph->edges().size(); 0297 graph->edges().insert(ge->id(), ge); 0298 // qCDebug(KGRAPHVIEWERLIB_LOG) << "num after=" << graph->edges().size(); 0299 0300 node1Name = node2Name; 0301 } 0302 edgebounds.clear(); 0303 } 0304 0305 void DotGraphParsingHelper::finalactions() 0306 { 0307 GraphEdgeMap::iterator it, it_end; 0308 it = graph->edges().begin(); 0309 it_end = graph->edges().end(); 0310 for (; it != it_end; it++) { 0311 (*it)->setZ(maxZ + 1); 0312 } 0313 } 0314 0315 }