|
1 /****************************************************************************** |
|
2 * |
|
3 * |
|
4 * |
|
5 * |
|
6 * Copyright (C) 1997-2008 by Dimitri van Heesch. |
|
7 * |
|
8 * Permission to use, copy, modify, and distribute this software and its |
|
9 * documentation under the terms of the GNU General Public License is hereby |
|
10 * granted. No representations are made about the suitability of this software |
|
11 * for any purpose. It is provided "as is" without express or implied warranty. |
|
12 * See the GNU General Public License for more details. |
|
13 * |
|
14 * Documents produced by Doxygen are derivative works derived from the |
|
15 * input used in their production; they are not affected by this license. |
|
16 * |
|
17 */ |
|
18 |
|
19 #ifndef _DOT_H |
|
20 #define _DOT_H |
|
21 |
|
22 #include "qtbc.h" |
|
23 #include <qlist.h> |
|
24 #include <qdict.h> |
|
25 #include "sortdict.h" |
|
26 #include "xmlwriter.h" |
|
27 |
|
28 class ClassDef; |
|
29 class FileDef; |
|
30 class QTextStream; |
|
31 class DotNodeList; |
|
32 class ClassSDict; |
|
33 class MemberDef; |
|
34 class Definition; |
|
35 class DirDef; |
|
36 class GroupDef; |
|
37 class DotGroupCollaboration; |
|
38 |
|
39 enum GraphOutputFormat { BITMAP , EPS }; |
|
40 |
|
41 /** @brief Attributes of an edge of a dot graph */ |
|
42 struct EdgeInfo |
|
43 { |
|
44 enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5 }; |
|
45 enum Styles { Solid=0, Dashed=1 }; |
|
46 EdgeInfo() : m_color(0), m_style(0), m_labColor(0) {} |
|
47 ~EdgeInfo() {} |
|
48 int m_color; |
|
49 int m_style; |
|
50 QCString m_label; |
|
51 QCString m_url; |
|
52 int m_labColor; |
|
53 }; |
|
54 |
|
55 /** @brief A node in a dot graph */ |
|
56 class DotNode |
|
57 { |
|
58 public: |
|
59 enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph }; |
|
60 enum TruncState { Unknown, Truncated, Untruncated }; |
|
61 DotNode(int n,const char *lab,const char *tip,const char *url, |
|
62 bool rootNode=FALSE,ClassDef *cd=0); |
|
63 ~DotNode(); |
|
64 void addChild(DotNode *n, |
|
65 int edgeColor=EdgeInfo::Purple, |
|
66 int edgeStyle=EdgeInfo::Solid, |
|
67 const char *edgeLab=0, |
|
68 const char *edgeURL=0, |
|
69 int edgeLabCol=-1 |
|
70 ); |
|
71 void addParent(DotNode *n); |
|
72 void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0); |
|
73 void removeChild(DotNode *n); |
|
74 void removeParent(DotNode *n); |
|
75 int findParent( DotNode *n ); |
|
76 void write(QTextStream &t,GraphType gt,GraphOutputFormat f, |
|
77 bool topDown,bool toChildren,bool backArrows,bool reNumber); |
|
78 int m_subgraphId; |
|
79 void clearWriteFlag(); |
|
80 void writeXML(QTextStream &t,bool isClassGraph); |
|
81 void writeXML(XmlStream &t, bool isClassGraph); |
|
82 void writeXMLDITA(XmlStream &t, bool isClassGraph); |
|
83 void writeDEF(QTextStream &t); |
|
84 QCString label() const { return m_label; } |
|
85 int number() const { return m_number; } |
|
86 bool isVisible() const { return m_visible; } |
|
87 TruncState isTruncated() const { return m_truncated; } |
|
88 int distance() const { return m_distance; } |
|
89 |
|
90 private: |
|
91 void colorConnectedNodes(int curColor); |
|
92 void writeBox(QTextStream &t,GraphType gt,GraphOutputFormat f, |
|
93 bool hasNonReachableChildren, bool reNumber=FALSE); |
|
94 void writeArrow(QTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn, |
|
95 EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE); |
|
96 void setDistance(int distance); |
|
97 const DotNode *findDocNode() const; // only works for acyclic graphs! |
|
98 void markAsVisible(bool b=TRUE) { m_visible=b; } |
|
99 void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } |
|
100 int m_number; |
|
101 QCString m_label; //!< label text |
|
102 QCString m_tooltip; //!< node's tooltip |
|
103 QCString m_url; //!< url of the node (format: remote$local) |
|
104 QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows) |
|
105 QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows) |
|
106 QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child |
|
107 bool m_deleted; //!< used to mark a node as deleted |
|
108 bool m_written; //!< used to mark a node as written |
|
109 bool m_hasDoc; //!< used to mark a node as documented |
|
110 bool m_isRoot; //!< indicates if this is a root node |
|
111 ClassDef * m_classDef; //!< class representing this node (can be 0) |
|
112 bool m_visible; //!< is the node visible in the output |
|
113 TruncState m_truncated; //!< does the node have non-visible children/parents |
|
114 int m_distance; //!< shortest path to the root node |
|
115 |
|
116 friend class DotGfxHierarchyTable; |
|
117 friend class DotClassGraph; |
|
118 friend class DotInclDepGraph; |
|
119 friend class DotNodeList; |
|
120 friend class DotCallGraph; |
|
121 friend class DotGroupCollaboration; |
|
122 |
|
123 friend QCString computeMd5Signature( |
|
124 DotNode *root, GraphType gt, |
|
125 GraphOutputFormat f, |
|
126 bool lrRank, bool renderParents, |
|
127 bool backArrows, |
|
128 QCString &graphStr |
|
129 ); |
|
130 }; |
|
131 |
|
132 inline int DotNode::findParent( DotNode *n ) |
|
133 { |
|
134 if( !m_parents ) |
|
135 return -1; |
|
136 return m_parents->find(n); |
|
137 } |
|
138 |
|
139 /** @brief Represents a graphical class hierarchy */ |
|
140 class DotGfxHierarchyTable |
|
141 { |
|
142 public: |
|
143 DotGfxHierarchyTable(); |
|
144 ~DotGfxHierarchyTable(); |
|
145 void writeGraph(QTextStream &t,const char *path) const; |
|
146 |
|
147 private: |
|
148 void addHierarchy(DotNode *n,ClassDef *cd,bool hide); |
|
149 void addClassList(ClassSDict *cl); |
|
150 |
|
151 QList<DotNode> *m_rootNodes; |
|
152 QDict<DotNode> *m_usedNodes; |
|
153 static int m_curNodeNumber; |
|
154 DotNodeList *m_rootSubgraphs; |
|
155 }; |
|
156 |
|
157 /** @brief Representation of a class inheritance or dependency graph */ |
|
158 class DotClassGraph |
|
159 { |
|
160 public: |
|
161 DotClassGraph(ClassDef *cd,DotNode::GraphType t); |
|
162 ~DotClassGraph(); |
|
163 bool isTrivial() const; |
|
164 bool isTooBig() const; |
|
165 QCString writeGraph(QTextStream &t,GraphOutputFormat f,const char *path, |
|
166 const char *relPath, bool TBRank=TRUE,bool imageMap=TRUE) const; |
|
167 |
|
168 void writeXML(QTextStream &t); |
|
169 void writeDEF(QTextStream &t); |
|
170 void writeXML(XmlStream &t); |
|
171 void writeXMLDITA(XmlStream &t); |
|
172 QCString diskName() const; |
|
173 |
|
174 private: |
|
175 void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance); |
|
176 bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents); |
|
177 void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); |
|
178 void addClass(ClassDef *cd,DotNode *n,int prot,const char *label, |
|
179 const char *usedName,const char *templSpec, |
|
180 bool base,int distance); |
|
181 |
|
182 DotNode * m_startNode; |
|
183 QDict<DotNode> * m_usedNodes; |
|
184 static int m_curNodeNumber; |
|
185 DotNode::GraphType m_graphType; |
|
186 QCString m_diskName; |
|
187 bool m_lrRank; |
|
188 }; |
|
189 |
|
190 /** @brief Representation of an include dependency graph */ |
|
191 class DotInclDepGraph |
|
192 { |
|
193 public: |
|
194 DotInclDepGraph(FileDef *fd,bool inverse); |
|
195 ~DotInclDepGraph(); |
|
196 QCString writeGraph(QTextStream &t, GraphOutputFormat f,const char *path, |
|
197 const char *relPath, |
|
198 bool writeImageMap=TRUE) const; |
|
199 bool isTrivial() const; |
|
200 bool isTooBig() const; |
|
201 QCString diskName() const; |
|
202 void writeXML(QTextStream &t); |
|
203 void writeXML(XmlStream &t); |
|
204 |
|
205 private: |
|
206 void buildGraph(DotNode *n,FileDef *fd,int distance); |
|
207 void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes); |
|
208 void determineTruncatedNodes(QList<DotNode> &queue); |
|
209 |
|
210 DotNode *m_startNode; |
|
211 QDict<DotNode> *m_usedNodes; |
|
212 static int m_curNodeNumber; |
|
213 QCString m_diskName; |
|
214 int m_maxDistance; |
|
215 bool m_inverse; |
|
216 }; |
|
217 |
|
218 /** @brief Representation of an call graph */ |
|
219 class DotCallGraph |
|
220 { |
|
221 public: |
|
222 DotCallGraph(MemberDef *md,bool inverse); |
|
223 ~DotCallGraph(); |
|
224 QCString writeGraph(QTextStream &t, GraphOutputFormat f, |
|
225 const char *path,const char *relPath,bool writeImageMap=TRUE) const; |
|
226 void buildGraph(DotNode *n,MemberDef *md,int distance); |
|
227 bool isTrivial() const; |
|
228 bool isTooBig() const; |
|
229 void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); |
|
230 void determineTruncatedNodes(QList<DotNode> &queue); |
|
231 |
|
232 private: |
|
233 DotNode *m_startNode; |
|
234 static int m_curNodeNumber; |
|
235 QDict<DotNode> *m_usedNodes; |
|
236 int m_maxDistance; |
|
237 int m_recDepth; |
|
238 bool m_inverse; |
|
239 QCString m_diskName; |
|
240 Definition * m_scope; |
|
241 }; |
|
242 |
|
243 /** @brief Representation of an directory dependency graph */ |
|
244 class DotDirDeps |
|
245 { |
|
246 public: |
|
247 DotDirDeps(DirDef *dir); |
|
248 ~DotDirDeps(); |
|
249 bool isTrivial() const; |
|
250 QCString writeGraph(QTextStream &out, |
|
251 GraphOutputFormat format, |
|
252 const char *path, |
|
253 const char *relPath, |
|
254 bool writeImageMap=TRUE) const; |
|
255 private: |
|
256 DirDef *m_dir; |
|
257 }; |
|
258 |
|
259 /** @brief Representation of a group collaboration graph */ |
|
260 class DotGroupCollaboration |
|
261 { |
|
262 public : |
|
263 enum EdgeType |
|
264 { tmember = 0, |
|
265 tclass, |
|
266 tnamespace, |
|
267 tfile, |
|
268 tpages, |
|
269 tdir, |
|
270 thierarchy |
|
271 }; |
|
272 |
|
273 class Link |
|
274 { |
|
275 public: |
|
276 Link(const QCString lab,const QCString &u) : label(lab), url(u) {} |
|
277 QCString label; |
|
278 QCString url; |
|
279 }; |
|
280 |
|
281 class Edge |
|
282 { |
|
283 public : |
|
284 Edge(DotNode *start,DotNode *end,EdgeType type) |
|
285 : pNStart(start), pNEnd(end), eType(type) |
|
286 { links.setAutoDelete(TRUE); } |
|
287 |
|
288 DotNode* pNStart; |
|
289 DotNode* pNEnd; |
|
290 EdgeType eType; |
|
291 |
|
292 QList<Link> links; |
|
293 void write( QTextStream &t ) const; |
|
294 }; |
|
295 |
|
296 DotGroupCollaboration(GroupDef* gd); |
|
297 ~DotGroupCollaboration(); |
|
298 QCString writeGraph(QTextStream &t, GraphOutputFormat format, |
|
299 const char *path,const char *relPath, |
|
300 bool writeImageMap=TRUE) const; |
|
301 void buildGraph(GroupDef* gd); |
|
302 bool isTrivial() const; |
|
303 private : |
|
304 void addCollaborationMember( Definition* def, QCString& url, EdgeType eType ); |
|
305 void addMemberList( class MemberList* ml ); |
|
306 void writeGraphHeader(QTextStream &t) const; |
|
307 Edge* addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType, |
|
308 const QCString& _label, const QCString& _url ); |
|
309 |
|
310 DotNode *m_rootNode; |
|
311 int m_curNodeId; |
|
312 QDict<DotNode> *m_usedNodes; |
|
313 QCString m_diskName; |
|
314 QList<Edge> m_edges; |
|
315 }; |
|
316 |
|
317 /** @brief Helper class to run dot from doxygen. |
|
318 */ |
|
319 class DotRunner |
|
320 { |
|
321 public: |
|
322 /** Creates a runner for a dot \a file. */ |
|
323 DotRunner(const char *file); |
|
324 |
|
325 /** Adds an additional job to the run. |
|
326 * Performing multiple jobs one file can be faster. |
|
327 */ |
|
328 void addJob(const char *format,const char *output); |
|
329 |
|
330 void addPostProcessing(const char *cmd,const char *args); |
|
331 |
|
332 /** Runs dot for all jobs added. */ |
|
333 bool run(); |
|
334 private: |
|
335 QList<QCString> m_jobs; |
|
336 QCString m_postArgs; |
|
337 QCString m_postCmd; |
|
338 QCString m_file; |
|
339 }; |
|
340 |
|
341 |
|
342 /** Generated a graphs legend page */ |
|
343 void generateGraphLegend(const char *path); |
|
344 |
|
345 void writeDotGraphFromFile(const char *inFile,const char *outDir, |
|
346 const char *outFile,GraphOutputFormat format); |
|
347 QString getDotImageMapFromFile(const QString& inFile, const QString& outDir, |
|
348 const QCString& relPath,const QString &context); |
|
349 |
|
350 void writeDotDirDepGraph(QTextStream &t,DirDef *dd); |
|
351 |
|
352 #endif |