dot.h 14.6 KB
Newer Older
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1 2
/******************************************************************************
 *
3
 * 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
4 5
 *
 *
Dimitri van Heesch's avatar
Dimitri van Heesch committed
6
 * Copyright (C) 1997-2014 by Dimitri van Heesch.
Dimitri van Heesch's avatar
Dimitri van Heesch committed
7 8 9 10 11 12 13
 *
 * 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.
 *
Dimitri van Heesch's avatar
Dimitri van Heesch committed
14 15
 * Documents produced by Doxygen are derivative works derived from the
 * input used in their production; they are not affected by this license.
Dimitri van Heesch's avatar
Dimitri van Heesch committed
16 17 18
 *
 */

19 20 21
#ifndef _DOT_H
#define _DOT_H

Dimitri van Heesch's avatar
Dimitri van Heesch committed
22 23
#include <qlist.h>
#include <qdict.h>
24 25 26 27
#include <qwaitcondition.h>
#include <qmutex.h>
#include <qqueue.h>
#include <qthread.h>
Dimitri van Heesch's avatar
Dimitri van Heesch committed
28
#include "sortdict.h"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
29 30 31

class ClassDef;
class FileDef;
32
class FTextStream;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
33
class DotNodeList;
34
class ClassSDict;
35
class MemberDef;
36
class Definition;
37
class DirDef;
38 39
class GroupDef;
class DotGroupCollaboration;
40
class DotRunnerQueue;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
41

42 43
enum GraphOutputFormat    { GOF_BITMAP, GOF_EPS };
enum EmbeddedOutputFormat { EOF_Html, EOF_LaTeX, EOF_Rtf, EOF_DocBook };
44

Dimitri van Heesch's avatar
Dimitri van Heesch committed
45
/** Attributes of an edge of a dot graph */
Dimitri van Heesch's avatar
Dimitri van Heesch committed
46 47
struct EdgeInfo
{
48
  enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5 };
Dimitri van Heesch's avatar
Dimitri van Heesch committed
49 50 51 52 53 54 55 56 57 58
  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;
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
59
/** A node in a dot graph */
Dimitri van Heesch's avatar
Dimitri van Heesch committed
60 61 62
class DotNode
{
  public:
63
    enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph };
64 65 66
    enum TruncState { Unknown, Truncated, Untruncated };
    DotNode(int n,const char *lab,const char *tip,const char *url,
            bool rootNode=FALSE,ClassDef *cd=0);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
67 68
   ~DotNode();
    void addChild(DotNode *n,
69
                  int edgeColor=EdgeInfo::Purple,
Dimitri van Heesch's avatar
Dimitri van Heesch committed
70 71 72 73 74 75
                  int edgeStyle=EdgeInfo::Solid,
                  const char *edgeLab=0,
                  const char *edgeURL=0,
                  int edgeLabCol=-1
                 );
    void addParent(DotNode *n);
76
    void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
77 78
    void removeChild(DotNode *n);
    void removeParent(DotNode *n);
79
    int findParent( DotNode *n );
80
    void write(FTextStream &t,GraphType gt,GraphOutputFormat f,
81
               bool topDown,bool toChildren,bool backArrows,bool reNumber);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
82 83
    int  m_subgraphId;
    void clearWriteFlag();
84
    void writeXML(FTextStream &t,bool isClassGraph);
85
    void writeDocbook(FTextStream &t,bool isClassGraph);
86
    void writeDEF(FTextStream &t);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
87 88
    QCString label() const { return m_label; }
    int  number() const { return m_number; }
89 90
    bool isVisible() const { return m_visible; }
    TruncState isTruncated() const { return m_truncated; }
91
    int distance() const { return m_distance; }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
92 93 94

  private:
    void colorConnectedNodes(int curColor);
95
    void writeBox(FTextStream &t,GraphType gt,GraphOutputFormat f,
96
                  bool hasNonReachableChildren, bool reNumber=FALSE);
97
    void writeArrow(FTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn,
98
                    EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE);
99
    void setDistance(int distance);
100
    const DotNode   *findDocNode() const; // only works for acyclic graphs!
101 102
    void markAsVisible(bool b=TRUE) { m_visible=b; }
    void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
103
    int              m_number;
104
    QCString         m_label;     //!< label text
105
    QCString         m_tooltip;   //!< node's tooltip
106
    QCString         m_url;       //!< url of the node (format: remote$local)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
107 108 109 110 111
    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
112
    bool             m_hasDoc;    //!< used to mark a node as documented
Dimitri van Heesch's avatar
Dimitri van Heesch committed
113
    bool             m_isRoot;    //!< indicates if this is a root node
114
    ClassDef *       m_classDef;  //!< class representing this node (can be 0)
115 116
    bool             m_visible;   //!< is the node visible in the output
    TruncState       m_truncated; //!< does the node have non-visible children/parents
117
    int              m_distance;  //!< shortest path to the root node
118 119 120 121 122

    friend class DotGfxHierarchyTable;
    friend class DotClassGraph;
    friend class DotInclDepGraph;
    friend class DotNodeList;
123
    friend class DotCallGraph;
124 125
    friend class DotGroupCollaboration;

126 127 128 129
    friend QCString computeMd5Signature(
                      DotNode *root, GraphType gt,
                      GraphOutputFormat f, 
                      bool lrRank, bool renderParents,
130
                      bool backArrows,
Dimitri van Heesch's avatar
Dimitri van Heesch committed
131
                      const QCString &title,
132
                      QCString &graphStr
133
                     );
Dimitri van Heesch's avatar
Dimitri van Heesch committed
134
};
135 136

inline int DotNode::findParent( DotNode *n )
137 138 139 140 141
{
    if( !m_parents )
        return -1;
    return m_parents->find(n);
}
Dimitri van Heesch's avatar
Dimitri van Heesch committed
142

Dimitri van Heesch's avatar
Dimitri van Heesch committed
143
/** Represents a graphical class hierarchy */
Dimitri van Heesch's avatar
Dimitri van Heesch committed
144 145 146 147 148
class DotGfxHierarchyTable
{
  public:
    DotGfxHierarchyTable();
   ~DotGfxHierarchyTable();
149
    void writeGraph(FTextStream &t,const char *path, const char *fileName) const;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
150 151
  
  private:
152
    void addHierarchy(DotNode *n,ClassDef *cd,bool hide);
153
    void addClassList(ClassSDict *cl);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
154 155 156 157 158 159 160

    QList<DotNode> *m_rootNodes; 
    QDict<DotNode> *m_usedNodes; 
    static int      m_curNodeNumber;
    DotNodeList    *m_rootSubgraphs;
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
161
/** Representation of a class inheritance or dependency graph */
Dimitri van Heesch's avatar
Dimitri van Heesch committed
162
class DotClassGraph
Dimitri van Heesch's avatar
Dimitri van Heesch committed
163 164
{
  public:
165
    DotClassGraph(ClassDef *cd,DotNode::GraphType t);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
166
   ~DotClassGraph();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
167
    bool isTrivial() const;
168
    bool isTooBig() const;
169 170
    QCString writeGraph(FTextStream &t,GraphOutputFormat gf,EmbeddedOutputFormat ef,
                    const char *path, const char *fileName, const char *relPath,
171
                    bool TBRank=TRUE,bool imageMap=TRUE,int graphId=-1) const;
172

173
    void writeXML(FTextStream &t);
174
    void writeDocbook(FTextStream &t);
175
    void writeDEF(FTextStream &t);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
176 177 178
    QCString diskName() const;

  private:
179
    void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance);
180
    bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents);
181
    void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
182
    void addClass(ClassDef *cd,DotNode *n,int prot,const char *label,
183
                  const char *usedName,const char *templSpec,
184
                  bool base,int distance);
185

186 187 188 189 190
    DotNode        *   m_startNode;
    QDict<DotNode> *   m_usedNodes;
    static int         m_curNodeNumber;
    DotNode::GraphType m_graphType;
    QCString           m_diskName;
191
    bool               m_lrRank;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
192 193
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
194
/** Representation of an include dependency graph */
Dimitri van Heesch's avatar
Dimitri van Heesch committed
195 196 197
class DotInclDepGraph
{
  public:
198
    DotInclDepGraph(FileDef *fd,bool inverse);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
199
   ~DotInclDepGraph();
200
    QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef,
201
                    const char *path,const char *fileName,const char *relPath,
202
                    bool writeImageMap=TRUE,int graphId=-1) const;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
203
    bool isTrivial() const;
204
    bool isTooBig() const;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
205
    QCString diskName() const;
206
    void writeXML(FTextStream &t);
207
    void writeDocbook(FTextStream &t);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
208
  private:
209
    void buildGraph(DotNode *n,FileDef *fd,int distance);
210 211 212
    void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes);
    void determineTruncatedNodes(QList<DotNode> &queue);

Dimitri van Heesch's avatar
Dimitri van Heesch committed
213 214 215 216
    DotNode        *m_startNode;
    QDict<DotNode> *m_usedNodes;
    static int      m_curNodeNumber;
    QCString        m_diskName;
217
    bool            m_inverse;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
218
};
219

Dimitri van Heesch's avatar
Dimitri van Heesch committed
220
/** Representation of an call graph */
221 222 223
class DotCallGraph
{
  public:
224
    DotCallGraph(MemberDef *md,bool inverse);
225
   ~DotCallGraph();
226
    QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef,
227
                        const char *path,const char *fileName,
228 229
                        const char *relPath,bool writeImageMap=TRUE,
                        int graphId=-1) const;
230
    void buildGraph(DotNode *n,MemberDef *md,int distance);
231
    bool isTrivial() const;
232
    bool isTooBig() const;
233 234
    void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes);
    void determineTruncatedNodes(QList<DotNode> &queue);
235 236 237 238 239
    
  private:
    DotNode        *m_startNode;
    static int      m_curNodeNumber;
    QDict<DotNode> *m_usedNodes;
240
    bool            m_inverse;
241
    QCString        m_diskName;
242
    Definition *    m_scope;
243 244
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
245
/** Representation of an directory dependency graph */
246 247 248 249 250
class DotDirDeps
{
  public:
    DotDirDeps(DirDef *dir);
   ~DotDirDeps();
251
    bool isTrivial() const;
252
    QCString writeGraph(FTextStream &out,
253 254
                        GraphOutputFormat gf,
                        EmbeddedOutputFormat ef,
255
                        const char *path,
256
                        const char *fileName,
257
                        const char *relPath,
258 259
                        bool writeImageMap=TRUE,
                        int graphId=-1) const;
260 261
  private:
    DirDef *m_dir;
262 263
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
264
/** Representation of a group collaboration graph */
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
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;
298
        void write( FTextStream &t ) const;
299 300 301 302
    };

    DotGroupCollaboration(GroupDef* gd);
    ~DotGroupCollaboration();
303
    QCString writeGraph(FTextStream &t, GraphOutputFormat gf,EmbeddedOutputFormat ef,
304
                    const char *path,const char *fileName,const char *relPath,
305
                    bool writeImageMap=TRUE,int graphId=-1) const;
306
    void buildGraph(GroupDef* gd);
307 308 309 310
    bool isTrivial() const;
  private :
    void addCollaborationMember( Definition* def, QCString& url, EdgeType eType );
    void addMemberList( class MemberList* ml );
Dimitri van Heesch's avatar
Dimitri van Heesch committed
311
    void writeGraphHeader(FTextStream &t,const QCString &title) const;
312 313 314 315 316 317 318 319 320 321
    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;
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
322
/** Helper class to run dot from doxygen.
323 324 325 326
 */
class DotRunner
{
  public:
327 328 329 330 331 332
    struct CleanupItem
    {
      QCString path;
      QCString file;
    };

333
    /** Creates a runner for a dot \a file. */
334 335
    DotRunner(const QCString &file,const QCString &fontPath,bool checkResult,
        const QCString &imageName = QCString());
336 337 338 339 340 341

    /** Adds an additional job to the run.
     *  Performing multiple jobs one file can be faster.
     */
    void addJob(const char *format,const char *output);

342 343
    void addPostProcessing(const char *cmd,const char *args);

344 345
    void preventCleanUp() { m_cleanUp = FALSE; }

346 347
    /** Runs dot for all jobs added. */
    bool run();
348 349
    CleanupItem cleanup() const { return m_cleanupItem; }

350 351
  private:
    QList<QCString> m_jobs;
352 353
    QCString m_postArgs;
    QCString m_postCmd;
354
    QCString m_file;
355 356 357 358
    QCString m_path;
    bool m_checkResult;
    QCString m_imageName;
    bool m_cleanUp;
359
    CleanupItem m_cleanupItem;
360 361
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
362
/** Helper class to insert a set of map file into an output file */
363
class DotFilePatcher
364 365 366 367 368 369 370 371 372
{
  public:
    struct Map
    {
      QCString mapFile;
      QCString relPath;
      bool     urlOnly;
      QCString context;
      QCString label;
373
      bool     zoomable;
374
      int      graphId;
375
    };
376
    DotFilePatcher(const char *patchFile);
377 378 379 380
    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);
381 382
    int addSVGConversion(const QCString &relPath,bool urlOnly,
                         const QCString &context,bool zoomable,int graphId);
383 384
    int addSVGObject(const QCString &baseName, const QCString &figureName,
                     const QCString &relPath);
385
    bool run();
386
    QCString file() const;
387 388 389 390 391 392

  private:
    QList<Map> m_maps;
    QCString m_patchFile;
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
393
/** Queue of dot jobs to run. */
394 395 396 397 398 399 400 401 402 403 404 405
class DotRunnerQueue
{
  public:
    void enqueue(DotRunner *runner);
    DotRunner *dequeue();
    uint count() const;
  private:
    QWaitCondition  m_bufferNotEmpty;
    QQueue<DotRunner> m_queue;
    mutable QMutex  m_mutex;
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
406
/** Worker thread to execute a dot run */
407 408 409
class DotWorkerThread : public QThread
{
  public:
410
    DotWorkerThread(DotRunnerQueue *queue);
411
    void run();
412
    void cleanup();
413 414
  private:
    DotRunnerQueue *m_queue;
415
    QList<DotRunner::CleanupItem> m_cleanupItems;
416 417
};

Dimitri van Heesch's avatar
Dimitri van Heesch committed
418
/** Singleton that manages dot relation actions */
419 420 421 422 423 424 425 426 427 428
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);
429
    int addSVGConversion(const QCString &file,const QCString &relPath,
430
               bool urlOnly,const QCString &context,bool zoomable,int graphId);
431 432
    int addSVGObject(const QCString &file,const QCString &baseName,
                     const QCString &figureNAme,const QCString &relPath);
433 434 435 436 437 438
    bool run();

  private:
    DotManager();
    virtual ~DotManager();
    QList<DotRunner>       m_dotRuns;
439
    SDict<DotFilePatcher> m_dotMaps;
440 441 442
    static DotManager     *m_theInstance;
    DotRunnerQueue        *m_queue;
    QList<DotWorkerThread> m_workers;
443 444 445
};


446
/** Generated a graphs legend page */
447
void generateGraphLegend(const char *path);
448

Dimitri van Heesch's avatar
Dimitri van Heesch committed
449 450
void writeDotGraphFromFile(const char *inFile,const char *outDir,
                           const char *outFile,GraphOutputFormat format);
451 452
void writeDotImageMapFromFile(FTextStream &t,
                              const QCString& inFile, const QCString& outDir,
453
                              const QCString& relPath,const QCString& baseName,
454
                              const QCString& context,int graphId=-1);
455

456
void writeDotDirDepGraph(FTextStream &t,DirDef *dd);
457

458
#endif