diff options
Diffstat (limited to 'src/dot.h')
-rw-r--r-- | src/dot.h | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/src/dot.h b/src/dot.h new file mode 100644 index 0000000..c66dc6d --- /dev/null +++ b/src/dot.h @@ -0,0 +1,459 @@ +/****************************************************************************** + * + * $Id: dot.h,v 1.14 2001/03/19 19:27:40 root Exp $ + * + * + * Copyright (C) 1997-2012 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef _DOT_H +#define _DOT_H + +#include "qtbc.h" +#include <qlist.h> +#include <qdict.h> +#include <qwaitcondition.h> +#include <qmutex.h> +#include <qqueue.h> +#include <qthread.h> +#include "sortdict.h" + +class ClassDef; +class FileDef; +class FTextStream; +class DotNodeList; +class ClassSDict; +class MemberDef; +class Definition; +class DirDef; +class GroupDef; +class DotGroupCollaboration; +class DotRunnerQueue; + +enum GraphOutputFormat { BITMAP , EPS }; + +/** Attributes of an edge of a dot graph */ +struct EdgeInfo +{ + enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5 }; + enum Styles { Solid=0, Dashed=1 }; + EdgeInfo() : m_color(0), m_style(0), m_labColor(0) {} + ~EdgeInfo() {} + int m_color; + int m_style; + QCString m_label; + QCString m_url; + int m_labColor; +}; + +/** A node in a dot graph */ +class DotNode +{ + public: + enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph }; + enum TruncState { Unknown, Truncated, Untruncated }; + DotNode(int n,const char *lab,const char *tip,const char *url, + bool rootNode=FALSE,ClassDef *cd=0); + ~DotNode(); + void addChild(DotNode *n, + int edgeColor=EdgeInfo::Purple, + int edgeStyle=EdgeInfo::Solid, + const char *edgeLab=0, + const char *edgeURL=0, + int edgeLabCol=-1 + ); + void addParent(DotNode *n); + void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0); + void removeChild(DotNode *n); + void removeParent(DotNode *n); + int findParent( DotNode *n ); + void write(FTextStream &t,GraphType gt,GraphOutputFormat f, + bool topDown,bool toChildren,bool backArrows,bool reNumber); + int m_subgraphId; + void clearWriteFlag(); + void writeXML(FTextStream &t,bool isClassGraph); + void writeDEF(FTextStream &t); + QCString label() const { return m_label; } + int number() const { return m_number; } + bool isVisible() const { return m_visible; } + TruncState isTruncated() const { return m_truncated; } + int distance() const { return m_distance; } + + private: + void colorConnectedNodes(int curColor); + void writeBox(FTextStream &t,GraphType gt,GraphOutputFormat f, + bool hasNonReachableChildren, bool reNumber=FALSE); + void writeArrow(FTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn, + EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE); + void setDistance(int distance); + const DotNode *findDocNode() const; // only works for acyclic graphs! + void markAsVisible(bool b=TRUE) { m_visible=b; } + void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } + int m_number; + QCString m_label; //!< label text + QCString m_tooltip; //!< node's tooltip + QCString m_url; //!< url of the node (format: remote$local) + QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows) + QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows) + QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child + bool m_deleted; //!< used to mark a node as deleted + bool m_written; //!< used to mark a node as written + bool m_hasDoc; //!< used to mark a node as documented + bool m_isRoot; //!< indicates if this is a root node + ClassDef * m_classDef; //!< class representing this node (can be 0) + bool m_visible; //!< is the node visible in the output + TruncState m_truncated; //!< does the node have non-visible children/parents + int m_distance; //!< shortest path to the root node + + friend class DotGfxHierarchyTable; + friend class DotClassGraph; + friend class DotInclDepGraph; + friend class DotNodeList; + friend class DotCallGraph; + friend class DotGroupCollaboration; + + friend QCString computeMd5Signature( + DotNode *root, GraphType gt, + GraphOutputFormat f, + bool lrRank, bool renderParents, + bool backArrows, + const QCString &title, + QCString &graphStr + ); +}; + +inline int DotNode::findParent( DotNode *n ) +{ + if( !m_parents ) + return -1; + return m_parents->find(n); +} + +/** Represents a graphical class hierarchy */ +class DotGfxHierarchyTable +{ + public: + DotGfxHierarchyTable(); + ~DotGfxHierarchyTable(); + void writeGraph(FTextStream &t,const char *path, const char *fileName) const; + + private: + void addHierarchy(DotNode *n,ClassDef *cd,bool hide); + void addClassList(ClassSDict *cl); + + QList<DotNode> *m_rootNodes; + QDict<DotNode> *m_usedNodes; + static int m_curNodeNumber; + DotNodeList *m_rootSubgraphs; +}; + +/** Representation of a class inheritance or dependency graph */ +class DotClassGraph +{ + public: + DotClassGraph(ClassDef *cd,DotNode::GraphType t); + ~DotClassGraph(); + bool isTrivial() const; + bool isTooBig() const; + QCString writeGraph(FTextStream &t,GraphOutputFormat f,const char *path, + const char *fileName, const char *relPath, + bool TBRank=TRUE,bool imageMap=TRUE,int graphId=-1) const; + + void writeXML(FTextStream &t); + void writeDEF(FTextStream &t); + QCString diskName() const; + + private: + void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance); + bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents); + void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); + void addClass(ClassDef *cd,DotNode *n,int prot,const char *label, + const char *usedName,const char *templSpec, + bool base,int distance); + + DotNode * m_startNode; + QDict<DotNode> * m_usedNodes; + static int m_curNodeNumber; + DotNode::GraphType m_graphType; + QCString m_diskName; + bool m_lrRank; +}; + +/** Representation of an include dependency graph */ +class DotInclDepGraph +{ + public: + DotInclDepGraph(FileDef *fd,bool inverse); + ~DotInclDepGraph(); + QCString writeGraph(FTextStream &t, GraphOutputFormat f, + const char *path,const char *fileName,const char *relPath, + bool writeImageMap=TRUE,int graphId=-1) const; + bool isTrivial() const; + bool isTooBig() const; + QCString diskName() const; + void writeXML(FTextStream &t); + + private: + void buildGraph(DotNode *n,FileDef *fd,int distance); + void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes); + void determineTruncatedNodes(QList<DotNode> &queue); + + DotNode *m_startNode; + QDict<DotNode> *m_usedNodes; + static int m_curNodeNumber; + QCString m_diskName; + int m_maxDistance; + bool m_inverse; +}; + +/** Representation of an call graph */ +class DotCallGraph +{ + public: + DotCallGraph(MemberDef *md,bool inverse); + ~DotCallGraph(); + QCString writeGraph(FTextStream &t, GraphOutputFormat f, + const char *path,const char *fileName, + const char *relPath,bool writeImageMap=TRUE, + int graphId=-1) const; + void buildGraph(DotNode *n,MemberDef *md,int distance); + bool isTrivial() const; + bool isTooBig() const; + void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); + void determineTruncatedNodes(QList<DotNode> &queue); + + private: + DotNode *m_startNode; + static int m_curNodeNumber; + QDict<DotNode> *m_usedNodes; + int m_maxDistance; + int m_recDepth; + bool m_inverse; + QCString m_diskName; + Definition * m_scope; +}; + +/** Representation of an directory dependency graph */ +class DotDirDeps +{ + public: + DotDirDeps(DirDef *dir); + ~DotDirDeps(); + bool isTrivial() const; + QCString writeGraph(FTextStream &out, + GraphOutputFormat format, + const char *path, + const char *fileName, + const char *relPath, + bool writeImageMap=TRUE, + int graphId=-1) const; + private: + DirDef *m_dir; +}; + +/** Representation of a group collaboration graph */ +class DotGroupCollaboration +{ + public : + enum EdgeType + { tmember = 0, + tclass, + tnamespace, + tfile, + tpages, + tdir, + thierarchy + }; + + class Link + { + public: + Link(const QCString lab,const QCString &u) : label(lab), url(u) {} + QCString label; + QCString url; + }; + + class Edge + { + public : + Edge(DotNode *start,DotNode *end,EdgeType type) + : pNStart(start), pNEnd(end), eType(type) + { links.setAutoDelete(TRUE); } + + DotNode* pNStart; + DotNode* pNEnd; + EdgeType eType; + + QList<Link> links; + void write( FTextStream &t ) const; + }; + + DotGroupCollaboration(GroupDef* gd); + ~DotGroupCollaboration(); + QCString writeGraph(FTextStream &t, GraphOutputFormat format, + const char *path,const char *fileName,const char *relPath, + bool writeImageMap=TRUE,int graphId=-1) const; + void buildGraph(GroupDef* gd); + bool isTrivial() const; + private : + void addCollaborationMember( Definition* def, QCString& url, EdgeType eType ); + void addMemberList( class MemberList* ml ); + void writeGraphHeader(FTextStream &t,const QCString &title) const; + Edge* addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType, + const QCString& _label, const QCString& _url ); + + DotNode *m_rootNode; + int m_curNodeId; + QDict<DotNode> *m_usedNodes; + QCString m_diskName; + QList<Edge> m_edges; +}; + +/** Helper class to run dot from doxygen. + */ +class DotRunner +{ + public: + struct CleanupItem + { + QCString path; + QCString file; + }; + + /** Creates a runner for a dot \a file. */ + DotRunner(const QCString &file,const QCString &fontPath,bool checkResult, + const QCString &imageName = QCString()); + + /** Adds an additional job to the run. + * Performing multiple jobs one file can be faster. + */ + void addJob(const char *format,const char *output); + + void addPostProcessing(const char *cmd,const char *args); + + void preventCleanUp() { m_cleanUp = FALSE; } + + /** Runs dot for all jobs added. */ + bool run(); + CleanupItem cleanup() const { return m_cleanupItem; } + + private: + QList<QCString> m_jobs; + QCString m_postArgs; + QCString m_postCmd; + QCString m_file; + QCString m_path; + bool m_checkResult; + QCString m_imageName; + bool m_cleanUp; + CleanupItem m_cleanupItem; +}; + +/** Helper class to insert a set of map file into an output file */ +class DotFilePatcher +{ + public: + struct Map + { + QCString mapFile; + QCString relPath; + bool urlOnly; + QCString context; + QCString label; + bool zoomable; + int graphId; + }; + DotFilePatcher(const char *patchFile); + int addMap(const QCString &mapFile,const QCString &relPath, + bool urlOnly,const QCString &context,const QCString &label); + int addFigure(const QCString &baseName, + const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &relPath,bool urlOnly, + const QCString &context,bool zoomable,int graphId); + int addSVGObject(const QCString &baseName, const QCString &figureName, + const QCString &relPath); + bool run(); + QCString file() const; + + private: + QList<Map> m_maps; + QCString m_patchFile; +}; + +/** Queue of dot jobs to run. */ +class DotRunnerQueue +{ + public: + void enqueue(DotRunner *runner); + DotRunner *dequeue(); + uint count() const; + private: + QWaitCondition m_bufferNotEmpty; + QQueue<DotRunner> m_queue; + mutable QMutex m_mutex; +}; + +/** Worker thread to execute a dot run */ +class DotWorkerThread : public QThread +{ + public: + DotWorkerThread(int id,DotRunnerQueue *queue); + void run(); + void cleanup(); + private: + int m_id; + DotRunnerQueue *m_queue; + QList<DotRunner::CleanupItem> m_cleanupItems; +}; + +/** Singleton that manages dot relation actions */ +class DotManager +{ + public: + static DotManager *instance(); + void addRun(DotRunner *run); + int addMap(const QCString &file,const QCString &mapFile, + const QCString &relPath,bool urlOnly, + const QCString &context,const QCString &label); + int addFigure(const QCString &file,const QCString &baseName, + const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &file,const QCString &relPath, + bool urlOnly,const QCString &context,bool zoomable,int graphId); + int addSVGObject(const QCString &file,const QCString &baseName, + const QCString &figureNAme,const QCString &relPath); + bool run(); + + private: + DotManager(); + virtual ~DotManager(); + QList<DotRunner> m_dotRuns; + SDict<DotFilePatcher> m_dotMaps; + static DotManager *m_theInstance; + DotRunnerQueue *m_queue; + QList<DotWorkerThread> m_workers; +}; + + +/** Generated a graphs legend page */ +void generateGraphLegend(const char *path); + +void writeDotGraphFromFile(const char *inFile,const char *outDir, + const char *outFile,GraphOutputFormat format); +void writeDotImageMapFromFile(FTextStream &t, + const QCString& inFile, const QCString& outDir, + const QCString& relPath,const QCString& baseName, + const QCString& context,int graphId=-1); + +void writeDotDirDepGraph(FTextStream &t,DirDef *dd); + +#endif |