summaryrefslogtreecommitdiffstats
path: root/src/dot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dot.cpp')
-rw-r--r--src/dot.cpp3097
1 files changed, 0 insertions, 3097 deletions
diff --git a/src/dot.cpp b/src/dot.cpp
deleted file mode 100644
index c501a39..0000000
--- a/src/dot.cpp
+++ /dev/null
@@ -1,3097 +0,0 @@
-/*****************************************************************************
- *
- *
- *
- *
- * Copyright (C) 1997-2005 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.
- *
- */
-
-#include <stdlib.h>
-
-#include "dot.h"
-#include "doxygen.h"
-#include "message.h"
-#include "util.h"
-#include "config.h"
-#include "language.h"
-#include "defargs.h"
-#include "docparser.h"
-#include "debug.h"
-#include "pagedef.h"
-
-#include <qdir.h>
-#include <qfile.h>
-#include <qtextstream.h>
-#include <md5.h>
-
-
-//--------------------------------------------------------------------
-
-static const int maxCmdLine = 40960;
-
-/*! mapping from protection levels to color names */
-static const char *edgeColorMap[] =
-{
- "midnightblue", // Public
- "darkgreen", // Protected
- "firebrick4", // Private
- "darkorchid3", // "use" relation
- "grey75", // Undocumented
- "orange" // template relation
-};
-
-static const char *arrowStyle[] =
-{
- "empty", // Public
- "empty", // Protected
- "empty", // Private
- "open", // "use" relation
- 0, // Undocumented
- 0 // template relation
-};
-
-static const char *edgeStyleMap[] =
-{
- "solid", // inheritance
- "dashed" // usage
-};
-
-static void writeGraphHeader(QTextStream &t)
-{
- t << "digraph G" << endl;
- t << "{" << endl;
- if (Config_getBool("DOT_TRANSPARENT"))
- {
- t << " bgcolor=\"transparent\";" << endl;
- }
- t << " edge [fontname=\"Helvetica\",fontsize=10,"
- "labelfontname=\"Helvetica\",labelfontsize=10];\n";
- t << " node [fontname=\"Helvetica\",fontsize=10,shape=record];\n";
-}
-
-static void writeGraphFooter(QTextStream &t)
-{
- t << "}" << endl;
-}
-
-/*! converts the rectangles in a server site image map into a client
- * site image map.
- * \param t the stream to which the result is written.
- * \param mapName the name of the map file.
- * \param relPath the relative path to the root of the output directory
- * (used in case CREATE_SUBDIRS is enabled).
- * \param urlOnly if FALSE the url field in the map contains an external
- * references followed by a $ and then the URL.
- * \returns TRUE if succesful.
- */
-static bool convertMapFile(QTextStream &t,const char *mapName,
- const QCString relPath, bool urlOnly=FALSE)
-{
- QFile f(mapName);
- if (!f.open(IO_ReadOnly))
- {
- err("Error opening map file %s for inclusion in the docs!\n",mapName);
- return FALSE;
- }
- const int maxLineLen=1024;
- char buf[maxLineLen];
- char url[maxLineLen];
- char ref[maxLineLen];
- int x1,y1,x2,y2;
- while (!f.atEnd())
- {
- bool isRef = FALSE;
- int numBytes = f.readLine(buf,maxLineLen);
- buf[numBytes-1]='\0';
- //printf("ReadLine `%s'\n",buf);
- if (strncmp(buf,"rect",4)==0)
- {
- // obtain the url and the coordinates in the order used by graphviz-1.5
- sscanf(buf,"rect %s %d,%d %d,%d",url,&x1,&y1,&x2,&y2);
-
- if ( strcmp(url,"\\ref") == 0 )
- {
- isRef = TRUE;
- sscanf(buf,"rect %s %s %d,%d %d,%d",ref,url,&x1,&y1,&x2,&y2);
- }
-
- // later versions of graphviz corrected the y coordinate order
- // the rule is that y2>=y1, so test and switch if needed
- if (y2<y1)
- {
- int temp=y2;
- y2=y1;
- y1=temp;
- }
- // there shouldn't be any need for this for known versions of graphviz
- // but it can't do any harm to check that x follows the rules as well
- if (x2<x1)
- {
- int temp=x2;
- x2=x1;
- x1=temp;
- }
- if (urlOnly)
- {
- t << "<area href=\"";
-
- if ( isRef )
- {
- // handle doxygen \ref tag URL reference
- QCString *dest;
- DocRef *df = new DocRef( (DocNode*) 0, url );
- if (!df->ref().isEmpty())
- {
- if ((dest=Doxygen::tagDestinationDict[df->ref()])) t << *dest << "/";
- }
- if (!df->file().isEmpty()) t << relPath << df->file() << Doxygen::htmlFileExtension;
- if (!df->anchor().isEmpty()) t << "#" << df->anchor();
- }
- else
- {
- t << url;
- }
- t << "\" shape=\"rect\" coords=\""
- << x1 << "," << y1 << "," << x2 << "," << y2 << "\""
- << " alt=\"\">" << endl;
- }
- else // name and external reference are separated by a $
- {
- char *refPtr = url;
- char *urlPtr = strchr(url,'$');
- //printf("url=`%s'\n",url);
- if (urlPtr)
- {
- QCString *dest;
- *urlPtr++='\0';
- //printf("refPtr=`%s' urlPtr=`%s'\n",refPtr,urlPtr);
- //printf("Found url=%s coords=%d,%d,%d,%d\n",url,x1,y1,x2,y2);
- t << "<area ";
- if (*refPtr!='\0')
- {
- t << "doxygen=\"" << refPtr << ":";
- if ((dest=Doxygen::tagDestinationDict[refPtr])) t << *dest << "/";
- t << "\" ";
- }
- t << "href=\"" << relPath;
- if (*refPtr!='\0')
- {
- if ((dest=Doxygen::tagDestinationDict[refPtr])) t << *dest << "/";
- }
- t << urlPtr << "\" shape=\"rect\" coords=\""
- << x1 << "," << y1 << "," << x2 << "," << y2 << "\""
- << " alt=\"\">" << endl;
- }
- }
- }
- }
-
- return TRUE;
-}
-
-static QArray<int> * s_newNumber = new QArray<int>();
-static int s_max_newNumber=0;
-
-inline int reNumberNode(int number, bool doReNumbering)
-{
- if (!doReNumbering)
- {
- return number;
- }
- else
- {
- int s = s_newNumber->size();
- if (number>=s)
- {
- int ns=0;
- ns = s * 3 / 2 + 5; // new size
- if (number>=ns) // number still doesn't fit
- {
- ns = number * 3 / 2 + 5;
- }
- s_newNumber->resize(ns);
- for (int i=s;i<ns;i++) // clear new part of the array
- {
- s_newNumber->at(i)=0;
- }
- }
- int i = s_newNumber->at(number);
- if (i == 0) // not yet mapped
- {
- i = ++s_max_newNumber; // start from 1
- s_newNumber->at(number) = i;
- }
- return i;
- }
-}
-
-static void resetReNumbering()
-{
- s_max_newNumber=0;
- s_newNumber->resize(s_max_newNumber);
-}
-
-static bool readBoundingBoxDot(const char *fileName,int *width,int *height)
-{
- QFile f(fileName);
- if (!f.open(IO_ReadOnly)) return FALSE;
- const int maxLineLen=1024;
- char buf[maxLineLen];
- while (!f.atEnd())
- {
- int numBytes = f.readLine(buf,maxLineLen);
- buf[numBytes-1]='\0';
- if (strncmp(buf,"\tgraph [bb",10)==0)
- {
- int x,y;
- if (sscanf(buf,"\tgraph [bb= \"%d,%d,%d,%d\"];",&x,&y,width,height)!=4)
- {
- return FALSE;
- }
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static bool readBoundingBoxEPS(const char *fileName,int *width,int *height)
-{
- QFile f(fileName);
- if (!f.open(IO_ReadOnly)) return FALSE;
- const int maxLineLen=1024;
- char buf[maxLineLen];
- while (!f.atEnd())
- {
- int numBytes = f.readLine(buf,maxLineLen);
- buf[numBytes-1]='\0';
- if (strncmp(buf,"%%BoundingBox: ",15)==0)
- {
- int x,y;
- if (sscanf(buf,"%%%%BoundingBox: %d %d %d %d",&x,&y,width,height)!=4)
- {
- return FALSE;
- }
- return TRUE;
- }
- }
- return FALSE;
-}
-
-#if 0
-/*! returns TRUE if class cd is a leaf (i.e. has no visible children)
- */
-static bool isLeaf(ClassDef *cd)
-{
- BaseClassList *bcl = cd->subClasses();
- if (bcl->count()>0) // class has children, check their visibility
- {
- BaseClassListIterator bcli(*bcl);
- BaseClassDef *bcd;
- for ( ; (bcd=bcli.current()); ++bcli )
- {
- ClassDef *bClass = bcd->classDef;
- //if (bClass->isLinkable() || !isLeaf(bClass)) return FALSE;
-
- // if class is not a leaf
- if (!isLeaf(bClass)) return FALSE;
- // or class is not documented in this project
- if (!Config_getBool("ALLEXTERNALS") && !bClass->isLinkableInProject()) return FALSE;
- // or class is not documented and all ALLEXTERNALS = YES
- if (Config_getBool("ALLEXTERNALS") && !bClass->isLinkable()) return FALSE;
- }
- }
- return TRUE;
-}
-#endif
-
-// since dot silently reproduces the input file when it does not
-// support the PNG format, we need to check the result.
-static void checkDotResult(const QCString &imgName)
-{
- if (Config_getEnum("DOT_IMAGE_FORMAT")=="png")
- {
- QFile f(imgName);
- if (f.open(IO_ReadOnly))
- {
- char data[4];
- if (f.readBlock(data,4)==4)
- {
- if (!(data[1]=='P' && data[2]=='N' && data[3]=='G'))
- {
- err("Error! Image `%s' produced by dot is not a valid PNG!\n"
- "You should either select a different format "
- "(DOT_IMAGE_FORMAT in the config file) or install a more "
- "recent version of graphviz (1.7+)\n",imgName.data()
- );
- }
- }
- else
- {
- err("Error: Could not read image `%s' generated by dot!\n",imgName.data());
- }
- }
- else
- {
- err("Error: Could not open image `%s' generated by dot!\n",imgName.data());
- }
- }
-}
-
-/*! Checks if a file "baseName".md5 exists. If so the contents
- * are compared with \a md5. If equal FALSE is returned. If the .md5
- * file does not exist or its contents are not equal to \a md5,
- * a new .md5 is generated with the \a md5 string as contents.
- */
-static bool checkAndUpdateMd5Signature(const QCString &baseName,const QCString &md5)
-{
- QFile f(baseName+".md5");
- if (f.open(IO_ReadOnly))
- {
- // read checksum
- QCString md5stored(33);
- int bytesRead=f.readBlock(md5stored.data(),32);
- // compare checksum
- if (bytesRead==32 && md5==md5stored)
- {
- // bail out if equal
- return FALSE;
- }
- }
- f.close();
- // create checksum file
- if (f.open(IO_WriteOnly))
- {
- f.writeBlock(md5.data(),32);
- f.close();
- }
- return TRUE;
-}
-
-//--------------------------------------------------------------------
-
-class DotNodeList : public QList<DotNode>
-{
- public:
- DotNodeList() : QList<DotNode>() {}
- ~DotNodeList() {}
- int compareItems(GCI item1,GCI item2)
- {
- return stricmp(((DotNode *)item1)->m_label,((DotNode *)item2)->m_label);
- }
-};
-
-//--------------------------------------------------------------------
-
-DotRunner::DotRunner(const char *file) : m_file(file)
-{
- m_jobs.setAutoDelete(TRUE);
-}
-
-void DotRunner::addJob(const char *format,const char *output)
-{
- QCString args = QCString("-T")+format+" -o \""+output+"\"";
- m_jobs.append(new QCString(args));
-}
-
-bool DotRunner::run()
-{
- QListIterator<QCString> li(m_jobs);
- QCString *s;
- if (Config_getBool("DOT_MULTI_TARGETS"))
- {
- QCString dotArgs="\""+m_file+"\"";
- for (li.toFirst();(s=li.current());++li)
- {
- dotArgs+=' ';
- dotArgs+=*s;
- }
- if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
- {
- goto error;
- }
- }
- else
- {
- for (li.toFirst();(s=li.current());++li)
- {
- QCString dotArgs="\""+m_file+"\" "+*s;
- if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
- {
- goto error;
- }
- }
- }
- return TRUE;
-error:
- err("Problems running dot. Check your installation!\n");
- return FALSE;
-}
-
-//--------------------------------------------------------------------
-
-
-/*! helper function that deletes all nodes in a connected graph, given
- * one of the graph's nodes
- */
-static void deleteNodes(DotNode *node,SDict<DotNode> *skipNodes=0)
-{
- //printf("deleteNodes skipNodes=%p\n",skipNodes);
- static DotNodeList deletedNodes;
- deletedNodes.setAutoDelete(TRUE);
- node->deleteNode(deletedNodes,skipNodes); // collect nodes to be deleted.
- deletedNodes.clear(); // actually remove the nodes.
-}
-
-DotNode::DotNode(int n,const char *lab,const char *url,int distance,
- bool isRoot,ClassDef *cd)
- : m_number(n), m_label(lab), m_url(url), m_isRoot(isRoot), m_classDef(cd)
-{
- m_children = 0;
- m_edgeInfo = 0;
- m_parents = 0;
- m_subgraphId =-1;
- m_deleted = FALSE;
- m_written = FALSE;
- m_hasDoc = FALSE;
- m_distance = distance;
-}
-
-DotNode::~DotNode()
-{
- delete m_children;
- delete m_parents;
- delete m_edgeInfo;
-}
-
-void DotNode::setDistance(int distance)
-{
- if (distance<m_distance) m_distance=distance;
-}
-
-void DotNode::addChild(DotNode *n,
- int edgeColor,
- int edgeStyle,
- const char *edgeLab,
- const char *edgeURL,
- int edgeLabCol
- )
-{
- if (m_children==0)
- {
- m_children = new QList<DotNode>;
- m_edgeInfo = new QList<EdgeInfo>;
- m_edgeInfo->setAutoDelete(TRUE);
- }
- m_children->append(n);
- EdgeInfo *ei = new EdgeInfo;
- ei->m_color = edgeColor;
- ei->m_style = edgeStyle;
- ei->m_label = edgeLab;
- ei->m_url = edgeURL;
- if (edgeLabCol==-1)
- ei->m_labColor=edgeColor;
- else
- ei->m_labColor=edgeLabCol;
- m_edgeInfo->append(ei);
-}
-
-void DotNode::addParent(DotNode *n)
-{
- if (m_parents==0)
- {
- m_parents = new QList<DotNode>;
- }
- m_parents->append(n);
-}
-
-void DotNode::removeChild(DotNode *n)
-{
- if (m_children) m_children->remove(n);
-}
-
-void DotNode::removeParent(DotNode *n)
-{
- if (m_parents) m_parents->remove(n);
-}
-
-void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes)
-{
- if (m_deleted) return; // avoid recursive loops in case the graph has cycles
- m_deleted=TRUE;
- if (m_parents!=0) // delete all parent nodes of this node
- {
- QListIterator<DotNode> dnlip(*m_parents);
- DotNode *pn;
- for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
- {
- //pn->removeChild(this);
- pn->deleteNode(deletedList,skipNodes);
- }
- }
- if (m_children!=0) // delete all child nodes of this node
- {
- QListIterator<DotNode> dnlic(*m_children);
- DotNode *cn;
- for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
- {
- //cn->removeParent(this);
- cn->deleteNode(deletedList,skipNodes);
- }
- }
- // add this node to the list of deleted nodes.
- //printf("skipNodes=%p find(%p)=%p\n",skipNodes,this,skipNodes ? skipNodes->find((int)this) : 0);
- if (skipNodes==0 || skipNodes->find((char*)this)==0)
- {
- //printf("deleting\n");
- deletedList.append(this);
- }
-}
-
-static QCString convertLabel(const QCString &l)
-{
- QCString result;
- const char *p=l.data();
- char c;
- while ((c=*p++))
- {
- switch(c)
- {
- case '\\': result+="\\\\"; break;
- case '\n': result+="\\n"; break;
- case '<': result+="\\<"; break;
- case '>': result+="\\>"; break;
- case '|': result+="\\|"; break;
- case '"': result+="\\\""; break;
- default: result+=c; break;
- }
- }
- return result;
-}
-
-static void writeBoxMemberList(QTextStream &t,char prot,MemberList &ml,ClassDef *scope)
-{
- MemberListIterator mlia(ml);
- MemberDef *mma;
- for (mlia.toFirst();(mma = mlia.current());++mlia)
- {
- if (mma->getClassDef() == scope)
- {
- t << prot << " " << convertLabel(mma->name());
- if (!mma->isObjCMethod() && mma->isFunction()) t << "()";
- t << "\\l";
- }
- }
- // write member groups within the memberlist
- MemberGroupList *mgl = ml.getMemberGroupList();
- if (mgl)
- {
- MemberGroupListIterator mgli(*mgl);
- MemberGroup *mg;
- for (mgli.toFirst();(mg=mgli.current());++mgli)
- {
- if (mg->members())
- {
- writeBoxMemberList(t,prot,*mg->members(),scope);
- }
- }
- }
-}
-
-void DotNode::writeBox(QTextStream &t,
- GraphType gt,
- GraphOutputFormat /*format*/,
- bool hasNonReachableChildren,
- bool reNumber)
-{
- const char *labCol =
- m_url.isEmpty() ? "grey75" : // non link
- (
- (hasNonReachableChildren) ? "red" : "black"
- );
- t << " Node" << reNumberNode(m_number,reNumber) << " [label=\"";
-
- if (m_classDef && Config_getBool("UML_LOOK") &&
- (gt==Inheritance || gt==Collaboration))
- {
- t << "{" << convertLabel(m_label);
- t << "\\n|";
- writeBoxMemberList(t,'+',m_classDef->pubAttribs,m_classDef);
- writeBoxMemberList(t,'+',m_classDef->pubStaticAttribs,m_classDef);
- writeBoxMemberList(t,'~',m_classDef->pacAttribs,m_classDef);
- writeBoxMemberList(t,'~',m_classDef->pacStaticAttribs,m_classDef);
- writeBoxMemberList(t,'#',m_classDef->proAttribs,m_classDef);
- writeBoxMemberList(t,'#',m_classDef->proStaticAttribs,m_classDef);
- writeBoxMemberList(t,'-',m_classDef->priAttribs,m_classDef);
- writeBoxMemberList(t,'-',m_classDef->priStaticAttribs,m_classDef);
- t << "|";
- writeBoxMemberList(t,'+',m_classDef->pubMethods,m_classDef);
- writeBoxMemberList(t,'+',m_classDef->pubStaticMethods,m_classDef);
- writeBoxMemberList(t,'+',m_classDef->pubSlots,m_classDef);
- writeBoxMemberList(t,'~',m_classDef->pacMethods,m_classDef);
- writeBoxMemberList(t,'~',m_classDef->pacStaticMethods,m_classDef);
- writeBoxMemberList(t,'#',m_classDef->proMethods,m_classDef);
- writeBoxMemberList(t,'#',m_classDef->proStaticMethods,m_classDef);
- writeBoxMemberList(t,'#',m_classDef->proSlots,m_classDef);
- writeBoxMemberList(t,'-',m_classDef->priMethods,m_classDef);
- writeBoxMemberList(t,'-',m_classDef->priStaticMethods,m_classDef);
- writeBoxMemberList(t,'-',m_classDef->priSlots,m_classDef);
- if (m_classDef->memberGroupSDict)
- {
- MemberGroupSDict::Iterator mgdi(*m_classDef->memberGroupSDict);
- MemberGroup *mg;
- for (mgdi.toFirst();(mg=mgdi.current());++mgdi)
- {
- if (mg->members())
- {
- writeBoxMemberList(t,'*',*mg->members(),m_classDef);
- }
- }
- }
- t << "}";
- }
- else // old look
- {
- t << convertLabel(m_label);
- }
- t << "\",height=0.2,width=0.4";
- if (m_isRoot)
- {
- t << ",color=\"white\", fillcolor=\"black\", style=\"filled\" fontcolor=\"white\"";
- }
- else
- {
- if (!Config_getBool("DOT_TRANSPARENT"))
- {
- t << ",color=\"" << labCol << "\", fillcolor=\"white\", style=\"filled\"";
- }
- else
- {
- t << ",color=\"" << labCol << "\"";
- }
- if (!m_url.isEmpty())
- {
- int anchorPos = m_url.findRev('#');
- if (anchorPos==-1)
- {
- t << ",URL=\"" << m_url << Doxygen::htmlFileExtension << "\"";
- }
- else
- {
- t << ",URL=\"" << m_url.left(anchorPos) << Doxygen::htmlFileExtension
- << m_url.right(m_url.length()-anchorPos) << "\"";
- }
- }
- }
- t << "];" << endl;
-}
-
-void DotNode::writeArrow(QTextStream &t,
- GraphType gt,
- GraphOutputFormat format,
- DotNode *cn,
- EdgeInfo *ei,
- bool topDown,
- bool pointBack,
- bool reNumber
- )
-{
- t << " Node";
- if (topDown) t << reNumberNode(cn->number(),reNumber); else t << reNumberNode(m_number,reNumber);
- t << " -> Node";
- if (topDown) t << reNumberNode(m_number,reNumber); else t << reNumberNode(cn->number(),reNumber);
- t << " [";
- if (pointBack) t << "dir=back,";
- t << "color=\"" << edgeColorMap[ei->m_color]
- << "\",fontsize=10,style=\"" << edgeStyleMap[ei->m_style] << "\"";
- if (!ei->m_label.isEmpty())
- {
- t << ",label=\"" << convertLabel(ei->m_label) << "\"";
- }
- if (Config_getBool("UML_LOOK") &&
- arrowStyle[ei->m_color] &&
- (gt==Inheritance || gt==Collaboration)
- )
- {
- if (pointBack)
- t << ",arrowtail=\"" <<arrowStyle[ei->m_color] << "\"";
- else
- t << ",arrowhead=\"" << arrowStyle[ei->m_color] << "\"";
- }
-
- if (format==BITMAP) t << ",fontname=\"Helvetica\"";
- t << "];" << endl;
-}
-
-void DotNode::write(QTextStream &t,
- GraphType gt,
- GraphOutputFormat format,
- bool topDown,
- bool toChildren,
- int distance,
- bool backArrows,
- bool reNumber
- )
-{
- //printf("DotNode::write(%d) name=%s this=%p written=%d\n",distance,m_label.data(),this,m_written);
- if (m_written) return; // node already written to the output
- if (m_distance>distance) return;
- QList<DotNode> *nl = toChildren ? m_children : m_parents;
- bool hasNonReachableChildren=FALSE;
- if (m_distance==distance && nl)
- {
- QListIterator<DotNode> dnli(*nl);
- DotNode *cn;
- for (dnli.toFirst();(cn=dnli.current());++dnli)
- {
- if (cn->m_distance>distance) hasNonReachableChildren=TRUE;
- }
- }
- writeBox(t,gt,format,hasNonReachableChildren,reNumber);
- m_written=TRUE;
- if (nl)
- {
- if (toChildren)
- {
- QListIterator<DotNode> dnli1(*nl);
- QListIterator<EdgeInfo> dnli2(*m_edgeInfo);
- DotNode *cn;
- for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2)
- {
- if (cn->m_distance<=distance)
- {
- //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",cn->label().data());
- writeArrow(t,gt,format,cn,dnli2.current(),topDown,backArrows,reNumber);
- }
- cn->write(t,gt,format,topDown,toChildren,distance,backArrows,reNumber);
- }
- }
- else // render parents
- {
- QListIterator<DotNode> dnli(*nl);
- DotNode *pn;
- for (dnli.toFirst();(pn=dnli.current());++dnli)
- {
- if (pn->m_distance<=distance)
- {
- //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",pn->label().data());
- writeArrow(t,
- gt,
- format,
- pn,
- pn->m_edgeInfo->at(pn->m_children->findRef(this)),
- FALSE,
- backArrows,
- reNumber
- );
- }
- pn->write(t,gt,format,TRUE,FALSE,distance,backArrows,reNumber);
- }
- }
- }
- //printf("end DotNode::write(%d) name=%s\n",distance,m_label.data());
-}
-
-void DotNode::writeXML(QTextStream &t,bool isClassGraph)
-{
- t << " <node id=\"" << m_number << "\">" << endl;
- t << " <label>" << convertToXML(m_label) << "</label>" << endl;
- if (!m_url.isEmpty())
- {
- QCString url(m_url);
- char *refPtr = url.data();
- char *urlPtr = strchr(url.data(),'$');
- if (urlPtr)
- {
- *urlPtr++='\0';
- t << " <link refid=\"" << convertToXML(urlPtr) << "\"";
- if (*refPtr!='\0')
- {
- t << " external=\"" << convertToXML(refPtr) << "\"";
- }
- t << "/>" << endl;
- }
- }
- if (m_children)
- {
- QListIterator<DotNode> nli(*m_children);
- QListIterator<EdgeInfo> eli(*m_edgeInfo);
- DotNode *childNode;
- EdgeInfo *edgeInfo;
- for (;(childNode=nli.current());++nli,++eli)
- {
- edgeInfo=eli.current();
- t << " <childnode refid=\"" << childNode->m_number << "\" relation=\"";
- if (isClassGraph)
- {
- switch(edgeInfo->m_color)
- {
- case EdgeInfo::Blue: t << "public-inheritance"; break;
- case EdgeInfo::Green: t << "protected-inheritance"; break;
- case EdgeInfo::Red: t << "private-inheritance"; break;
- case EdgeInfo::Purple: t << "usage"; break;
- case EdgeInfo::Orange: t << "template-instance"; break;
- case EdgeInfo::Grey: ASSERT(0); break;
- }
- }
- else // include graph
- {
- t << "include";
- }
- t << "\">" << endl;
- if (!edgeInfo->m_label.isEmpty())
- {
- int p=0;
- int ni;
- while ((ni=edgeInfo->m_label.find("\\n",p))!=-1)
- {
- t << " <edgelabel>"
- << convertToXML(edgeInfo->m_label.mid(p,ni-p))
- << "</edgelabel>" << endl;
- p=ni+2;
- }
- t << " <edgelabel>"
- << convertToXML(edgeInfo->m_label.right(edgeInfo->m_label.length()-p))
- << "</edgelabel>" << endl;
- }
- t << " </childnode>" << endl;
- }
- }
- t << " </node>" << endl;
-}
-
-
-void DotNode::writeDEF(QTextStream &t)
-{
- char* nodePrefix = " node-";
-
- t << " node = {" << endl;
- t << nodePrefix << "id = " << m_number << ';' << endl;
- t << nodePrefix << "label = '" << m_label << "';" << endl;
-
- if (!m_url.isEmpty())
- {
- QCString url(m_url);
- char *refPtr = url.data();
- char *urlPtr = strchr(url.data(),'$');
- if (urlPtr)
- {
- *urlPtr++='\0';
- t << nodePrefix << "link = {" << endl << " "
- << nodePrefix << "link-id = '" << urlPtr << "';" << endl;
-
- if (*refPtr!='\0')
- {
- t << " " << nodePrefix << "link-external = '"
- << refPtr << "';" << endl;
- }
- t << " };" << endl;
- }
- }
- if (m_children)
- {
- QListIterator<DotNode> nli(*m_children);
- QListIterator<EdgeInfo> eli(*m_edgeInfo);
- DotNode *childNode;
- EdgeInfo *edgeInfo;
- for (;(childNode=nli.current());++nli,++eli)
- {
- edgeInfo=eli.current();
- t << " node-child = {" << endl;
- t << " child-id = '" << childNode->m_number << "';" << endl;
- t << " relation = ";
-
- switch(edgeInfo->m_color)
- {
- case EdgeInfo::Blue: t << "public-inheritance"; break;
- case EdgeInfo::Green: t << "protected-inheritance"; break;
- case EdgeInfo::Red: t << "private-inheritance"; break;
- case EdgeInfo::Purple: t << "usage"; break;
- case EdgeInfo::Orange: t << "template-instance"; break;
- case EdgeInfo::Grey: ASSERT(0); break;
- }
- t << ';' << endl;
-
- if (!edgeInfo->m_label.isEmpty())
- {
- t << " edgelabel = <<_EnD_oF_dEf_TeXt_" << endl
- << edgeInfo->m_label << endl
- << "_EnD_oF_dEf_TeXt_;" << endl;
- }
- t << " }; /* node-child */" << endl;
- } /* for (;childNode...) */
- }
- t << " }; /* node */" << endl;
-}
-
-
-void DotNode::clearWriteFlag()
-{
- m_written=FALSE;
- if (m_parents!=0)
- {
- QListIterator<DotNode> dnlip(*m_parents);
- DotNode *pn;
- for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
- {
- if (pn->m_written)
- {
- pn->clearWriteFlag();
- }
- }
- }
- if (m_children!=0)
- {
- QListIterator<DotNode> dnlic(*m_children);
- DotNode *cn;
- for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
- {
- if (cn->m_written)
- {
- cn->clearWriteFlag();
- }
- }
- }
-}
-
-void DotNode::colorConnectedNodes(int curColor)
-{
- if (m_children)
- {
- QListIterator<DotNode> dnlic(*m_children);
- DotNode *cn;
- for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
- {
- if (cn->m_subgraphId==-1) // uncolored child node
- {
- cn->m_subgraphId=curColor;
- cn->colorConnectedNodes(curColor);
- //printf("coloring node %s (%p): %d\n",cn->m_label.data(),cn,cn->m_subgraphId);
- }
- }
- }
-
- if (m_parents)
- {
- QListIterator<DotNode> dnlip(*m_parents);
- DotNode *pn;
- for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
- {
- if (pn->m_subgraphId==-1) // uncolored parent node
- {
- pn->m_subgraphId=curColor;
- pn->colorConnectedNodes(curColor);
- //printf("coloring node %s (%p): %d\n",pn->m_label.data(),pn,pn->m_subgraphId);
- }
- }
- }
-}
-
-const DotNode *DotNode::findDocNode() const
-{
- if (!m_url.isEmpty()) return this;
- //printf("findDocNode(): `%s'\n",m_label.data());
- if (m_parents)
- {
- QListIterator<DotNode> dnli(*m_parents);
- DotNode *pn;
- for (dnli.toFirst();(pn=dnli.current());++dnli)
- {
- if (!pn->m_hasDoc)
- {
- pn->m_hasDoc=TRUE;
- const DotNode *dn = pn->findDocNode();
- if (dn) return dn;
- }
- }
- }
- if (m_children)
- {
- QListIterator<DotNode> dnli(*m_children);
- DotNode *cn;
- for (dnli.toFirst();(cn=dnli.current());++dnli)
- {
- if (!cn->m_hasDoc)
- {
- cn->m_hasDoc=TRUE;
- const DotNode *dn = cn->findDocNode();
- if (dn) return dn;
- }
- }
- }
- return 0;
-}
-
-//--------------------------------------------------------------------
-
-int DotGfxHierarchyTable::m_curNodeNumber;
-
-void DotGfxHierarchyTable::writeGraph(QTextStream &out,const char *path)
-{
- //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name);
- //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count());
- if (m_rootSubgraphs->count()==0) return;
-
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Error: Output dir %s does not exist!\n",path); exit(1);
- }
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(d.absPath());
- QDir thisDir;
-
- // put each connected subgraph of the hierarchy in a row of the HTML output
- out << "<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" << endl;
-
- QListIterator<DotNode> dnli(*m_rootSubgraphs);
- DotNode *n;
- int count=0;
- for (dnli.toFirst();(n=dnli.current());++dnli)
- {
- QCString baseName;
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- baseName.sprintf("inherit_graph_%d",count++);
- baseName = convertNameToFile(baseName);
- QCString imgName=baseName+"."+ imgExt;
- QCString mapName=baseName+".map";
- QListIterator<DotNode> dnli2(*m_rootNodes);
- DotNode *node;
-
- // compute md5 checksum of the graph were are about to generate
- QString buf;
- QTextStream md5stream(&buf,IO_WriteOnly);
- for (dnli2.toFirst();(node=dnli2.current());++dnli2)
- {
- if (node->m_subgraphId==n->m_subgraphId)
- {
- node->clearWriteFlag();
- }
- }
- for (dnli2.toFirst();(node=dnli2.current());++dnli2)
- {
- if (node->m_subgraphId==n->m_subgraphId)
- {
- node->write(md5stream,DotNode::Hierarchy,BITMAP,FALSE,TRUE,1000,TRUE,TRUE);
- }
- }
- resetReNumbering();
- uchar md5_sig[16];
- QCString sigStr(33);
- MD5Buffer((const unsigned char *)buf.ascii(),buf.length(),md5_sig);
- MD5SigToString(md5_sig,sigStr.data(),33);
- if (checkAndUpdateMd5Signature(baseName,sigStr) ||
- !QFileInfo(mapName).exists())
- {
- // image was new or has changed
- QCString dotName=baseName+".dot";
- QFile f(dotName);
- if (!f.open(IO_WriteOnly)) return;
- QTextStream t(&f);
- writeGraphHeader(t);
- t << " rankdir=LR;" << endl;
- for (dnli2.toFirst();(node=dnli2.current());++dnli2)
- {
- if (node->m_subgraphId==n->m_subgraphId)
- {
- node->clearWriteFlag();
- }
- }
- for (dnli2.toFirst();(node=dnli2.current());++dnli2)
- {
- if (node->m_subgraphId==n->m_subgraphId)
- {
- node->write(t,DotNode::Hierarchy,BITMAP,FALSE,TRUE,1000,TRUE,TRUE);
- }
- }
- writeGraphFooter(t);
- f.close();
- resetReNumbering();
-
- DotRunner dotRun(dotName);
- dotRun.addJob(imgExt,imgName);
- dotRun.addJob("imap",mapName);
- if (!dotRun.run())
- {
- out << "</table>" << endl;
- return;
- }
-
- checkDotResult(imgName);
- if (Config_getBool("DOT_CLEANUP")) thisDir.remove(dotName);
- }
- // write image and map in a table row
- QCString mapLabel = convertNameToFile(n->m_label);
- out << "<tr><td><img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#"
- << mapLabel << "_map\">" << endl;
- out << "<map name=\"" << mapLabel << "_map\">" << endl;
- convertMapFile(out,mapName,"");
- out << "</map></td></tr>" << endl;
- //thisDir.remove(mapName);
- }
- out << "</table>" << endl;
-
- QDir::setCurrent(oldDir);
-}
-
-void DotGfxHierarchyTable::addHierarchy(DotNode *n,ClassDef *cd,bool hideSuper)
-{
- //printf("addHierarchy `%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count());
- BaseClassListIterator bcli(*cd->subClasses());
- BaseClassDef *bcd;
- for ( ; (bcd=bcli.current()) ; ++bcli )
- {
- ClassDef *bClass=bcd->classDef;
- //printf(" Trying sub class=`%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count());
- if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses()))
- {
- DotNode *bn;
- //printf(" Node `%s' Found visible class=`%s'\n",n->m_label.data(),
- // bClass->name().data());
- if ((bn=m_usedNodes->find(bClass->name()))) // node already present
- {
- if (n->m_children==0 || n->m_children->findRef(bn)==-1) // no arrow yet
- {
- n->addChild(bn,bcd->prot);
- bn->addParent(n);
- //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n",
- // n->m_label.data(),
- // bn->m_label.data(),
- // bn->m_children ? bn->m_children->count() : 0,
- // bn->m_parents ? bn->m_parents->count() : 0
- // );
- }
- //else
- //{
- // printf(" Class already has an arrow!\n");
- //}
- }
- else
- {
- QCString tmp_url="";
- if (bClass->isLinkable() && !bClass->isHidden())
- {
- tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase();
- }
- bn = new DotNode(m_curNodeNumber++,
- bClass->displayName(),
- tmp_url.data()
- );
- n->addChild(bn,bcd->prot);
- bn->addParent(n);
- //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n",
- // n->m_label.data(),
- // bn->m_label.data(),
- // bn->m_children ? bn->m_children->count() : 0,
- // bn->m_parents ? bn->m_parents->count() : 0
- // );
- //printf(" inserting %s (%p)\n",bClass->name().data(),bn);
- m_usedNodes->insert(bClass->name(),bn); // add node to the used list
- }
- if (!bClass->visited && !hideSuper && bClass->subClasses()->count()>0)
- {
- bool wasVisited=bClass->visited;
- bClass->visited=TRUE;
- addHierarchy(bn,bClass,wasVisited);
- }
- }
- }
- //printf("end addHierarchy\n");
-}
-
-void DotGfxHierarchyTable::addClassList(ClassSDict *cl)
-{
- ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
- for (cli.toLast();(cd=cli.current());--cli)
- {
- //printf("Trying %s subClasses=%d\n",cd->name().data(),cd->subClasses()->count());
- if (!hasVisibleRoot(cd->baseClasses()) &&
- cd->isVisibleInHierarchy()
- ) // root node in the forest
- {
- QCString tmp_url="";
- if (cd->isLinkable() && !cd->isHidden())
- {
- tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
- }
- //printf("Inserting root class %s\n",cd->name().data());
- DotNode *n = new DotNode(m_curNodeNumber++,
- cd->displayName(),
- tmp_url.data());
-
- //m_usedNodes->clear();
- m_usedNodes->insert(cd->name(),n);
- m_rootNodes->insert(0,n);
- if (!cd->visited && cd->subClasses()->count()>0)
- {
- addHierarchy(n,cd,cd->visited);
- cd->visited=TRUE;
- }
- }
- }
-}
-
-DotGfxHierarchyTable::DotGfxHierarchyTable()
-{
- m_curNodeNumber=0;
- m_rootNodes = new QList<DotNode>;
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->setAutoDelete(TRUE);
- m_rootSubgraphs = new DotNodeList;
-
- // build a graph with each class as a node and the inheritance relations
- // as edges
- initClassHierarchy(&Doxygen::classSDict);
- initClassHierarchy(&Doxygen::hiddenClasses);
- addClassList(&Doxygen::classSDict);
- addClassList(&Doxygen::hiddenClasses);
- // m_usedNodes now contains all nodes in the graph
-
- // color the graph into a set of independent subgraphs
- bool done=FALSE;
- int curColor=0;
- QListIterator<DotNode> dnli(*m_rootNodes);
- while (!done) // there are still nodes to color
- {
- DotNode *n;
- done=TRUE; // we are done unless there are still uncolored nodes
- for (dnli.toLast();(n=dnli.current());--dnli)
- {
- if (n->m_subgraphId==-1) // not yet colored
- {
- //printf("Starting at node %s (%p): %d\n",n->m_label.data(),n,curColor);
- done=FALSE; // still uncolored nodes
- n->m_subgraphId=curColor;
- n->colorConnectedNodes(curColor);
- curColor++;
- const DotNode *dn=n->findDocNode();
- if (dn!=0)
- m_rootSubgraphs->inSort(dn);
- else
- m_rootSubgraphs->inSort(n);
- }
- }
- }
-
- //printf("Number of independent subgraphs: %d\n",curColor);
- //QListIterator<DotNode> dnli2(*m_rootSubgraphs);
- //DotNode *n;
- //for (dnli2.toFirst();(n=dnli2.current());++dnli2)
- //{
- // printf("Node %s color=%d (c=%d,p=%d)\n",
- // n->m_label.data(),n->m_subgraphId,
- // n->m_children?n->m_children->count():0,
- // n->m_parents?n->m_parents->count():0);
- //}
-}
-
-DotGfxHierarchyTable::~DotGfxHierarchyTable()
-{
- //printf("DotGfxHierarchyTable::~DotGfxHierarchyTable\n");
-
- //QDictIterator<DotNode> di(*m_usedNodes);
- //DotNode *n;
- //for (;(n=di.current());++di)
- //{
- // printf("Node %p: %s\n",n,n->label().data());
- //}
-
- delete m_rootNodes;
- delete m_usedNodes;
- delete m_rootSubgraphs;
-}
-
-//--------------------------------------------------------------------
-
-int DotClassGraph::m_curNodeNumber = 0;
-
-void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot,
- const char *label,int distance,const char *usedName,const char *templSpec,bool base)
-{
- if (Config_getBool("HIDE_UNDOC_CLASSES") && !cd->isLinkable()) return;
-
- int edgeStyle = (label || prot==EdgeInfo::Orange) ? EdgeInfo::Dashed : EdgeInfo::Solid;
- QCString className;
- if (usedName) // name is a typedef
- {
- className=usedName;
- }
- else if (templSpec) // name has a template part
- {
- className=insertTemplateSpecifierInScope(cd->name(),templSpec);
- }
- else // just a normal name
- {
- className=cd->displayName();
- }
- //printf("DotClassGraph::addClass(class=`%s',parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n",
- // className.data(),n->m_label.data(),prot,label,distance,usedName,templSpec,base);
- DotNode *bn = m_usedNodes->find(className);
- if (bn) // class already inserted
- {
- if (base)
- {
- n->addChild(bn,prot,edgeStyle,label);
- bn->addParent(n);
- }
- else
- {
- bn->addChild(n,prot,edgeStyle,label);
- n->addParent(bn);
- }
- bn->setDistance(distance);
- //printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data());
- }
- else // new class
- {
- QCString displayName=className;
- if (Config_getBool("HIDE_SCOPE_NAMES")) displayName=stripScope(displayName);
- QCString tmp_url;
- if (cd->isLinkable() && !cd->isHidden())
- {
- tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
- }
- bn = new DotNode(m_curNodeNumber++,
- displayName,
- tmp_url.data(),
- distance,
- FALSE, // rootNode
- cd
- );
- if (distance>m_maxDistance) m_maxDistance=distance;
- if (base)
- {
- n->addChild(bn,prot,edgeStyle,label);
- bn->addParent(n);
- }
- else
- {
- bn->addChild(n,prot,edgeStyle,label);
- n->addParent(bn);
- }
- m_usedNodes->insert(className,bn);
- //printf(" add new child node `%s' to %s hidden=%d url=%s\n",
- // className.data(),n->m_label.data(),cd->isHidden(),tmp_url.data());
-
- // we use <=, i.s.o < to cause one more level than intended which is used to
- // detect truncated nodes
- if (distance<=m_recDepth) buildGraph(cd,bn,distance+1,base);
- }
-}
-
-void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,int distance,bool base)
-{
- //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n",
- // cd->name().data(),distance,base);
- // ---- Add inheritance relations
-
- if (m_graphType == DotNode::Inheritance || m_graphType==DotNode::Collaboration)
- {
- BaseClassListIterator bcli(base ? *cd->baseClasses() : *cd->subClasses());
- BaseClassDef *bcd;
- for ( ; (bcd=bcli.current()) ; ++bcli )
- {
- //printf("-------- inheritance relation %s->%s templ=`%s'\n",
- // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data());
- addClass(bcd->classDef,n,bcd->prot,0,distance,bcd->usedName,
- bcd->templSpecifiers,base);
- }
- }
- if (m_graphType == DotNode::Collaboration)
- {
- // ---- Add usage relations
-
- UsesClassDict *dict =
- base ? cd->usedImplementationClasses() :
- cd->usedByImplementationClasses()
- ;
- if (dict)
- {
- UsesClassDictIterator ucdi(*dict);
- UsesClassDef *ucd;
- for (;(ucd=ucdi.current());++ucdi)
- {
- //if (base)
- //{
- // printf("%s uses %s\n",cd->name().data(),ucd->classDef->name().data());
- //}
- //else
- //{
- // printf("%s is used by %s\n",cd->name().data(),ucd->classDef->name().data());
- //}
- //printf("drawing\n");
- QCString label;
- QDictIterator<void> dvi(*ucd->accessors);
- const char *s;
- bool first=TRUE;
- for (;(s=dvi.currentKey());++dvi)
- {
- if (first)
- {
- label=s;
- first=FALSE;
- }
- else
- {
- label+=QCString("\n")+s;
- }
- }
- addClass(ucd->classDef,n,EdgeInfo::Purple,label,distance,0,
- ucd->templSpecifiers,base);
- }
- }
- }
-
- // ---- Add template instantiation relations
-
- if (Config_getBool("TEMPLATE_RELATIONS"))
- {
- if (base) // template relations for base classes
- {
- ClassDef *templMaster=cd->templateMaster();
- if (templMaster)
- {
- QDictIterator<ClassDef> cli(*templMaster->getTemplateInstances());
- ClassDef *templInstance;
- for (;(templInstance=cli.current());++cli)
- {
- if (templInstance==cd)
- {
- addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),distance,0,
- 0,TRUE);
- }
- }
- }
- }
- else // template relations for super classes
- {
- QDict<ClassDef> *templInstances = cd->getTemplateInstances();
- if (templInstances)
- {
- QDictIterator<ClassDef> cli(*templInstances);
- ClassDef *templInstance;
- for (;(templInstance=cli.current());++cli)
- {
- addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),distance,0,
- 0,FALSE);
- }
- }
- }
- }
-}
-
-DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t,int maxRecursionDepth)
-{
- //printf("--------------- DotClassGraph::DotClassGraph `%s'\n",cd->displayName().data());
- m_graphType = t;
- m_maxDistance = 0;
- m_recDepth = maxRecursionDepth;
- QCString tmp_url="";
- if (cd->isLinkable() && !cd->isHidden())
- {
- tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
- }
- QCString className = cd->displayName();
- //if (cd->templateArguments())
- //{
- // className+=tempArgListToString(cd->templateArguments());
- //}
- m_startNode = new DotNode(m_curNodeNumber++,
- className,
- tmp_url.data(),
- 0, // distance
- TRUE, // is a root node
- cd
- );
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->insert(className,m_startNode);
-
- //ClassSDict::Iterator cli(Doxygen::classSDict);
- //ClassDef *icd;
- //for (cli.toFirst();(icd=cli.current());++cli) icd->initTemplateMapping();
-
- //printf("Root node %s\n",cd->name().data());
- if (m_recDepth>0)
- {
- buildGraph(cd,m_startNode,1,TRUE);
- if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,1,FALSE);
- }
- m_diskName = cd->getFileBase().copy();
-}
-
-bool DotClassGraph::isTrivial() const
-{
- if (m_graphType==DotNode::Inheritance)
- return m_startNode->m_children==0 && m_startNode->m_parents==0;
- else
- return m_startNode->m_children==0;
-}
-
-DotClassGraph::~DotClassGraph()
-{
- deleteNodes(m_startNode);
- delete m_usedNodes;
-}
-
-void writeDotGraph(DotNode *root,
- DotNode::GraphType gt,
- GraphOutputFormat format,
- const QCString &baseName,
- bool lrRank,
- bool renderParents,
- int distance,
- bool backArrows,
- bool reNumber
- )
-{
- // generate the graph description for dot
- //printf("writeDotGraph(%s,%d,lrRank=%d)\n",baseName.data(),backArrows,lrRank);
- QFile f;
- f.setName(baseName+".dot");
- if (f.open(IO_WriteOnly))
- {
- QTextStream t(&f);
- writeGraphHeader(t);
- if (lrRank)
- {
- t << " rankdir=LR;" << endl;
- }
- root->clearWriteFlag();
- root->write(t,gt,format,gt!=DotNode::CallGraph,TRUE,distance,backArrows,reNumber);
- if (renderParents && root->m_parents)
- {
- //printf("rendering parents!\n");
- QListIterator<DotNode> dnli(*root->m_parents);
- DotNode *pn;
- for (dnli.toFirst();(pn=dnli.current());++dnli)
- {
- if (pn->m_distance<=distance)
- {
- root->writeArrow(t,
- gt,
- format,
- pn,
- pn->m_edgeInfo->at(pn->m_children->findRef(root)),
- FALSE,
- backArrows,
- reNumber
- );
- }
- pn->write(t,gt,format,TRUE,FALSE,distance,backArrows,reNumber);
- }
- }
- writeGraphFooter(t);
- f.close();
- }
-}
-
-/*! Computes a 16 byte md5 checksum for a given dot graph.
- * The md5 checksum is returned as a 32 character ASCII string.
- */
-QCString computeMd5Signature(DotNode *root,
- DotNode::GraphType gt,
- GraphOutputFormat format,
- bool lrRank,
- bool renderParents,
- int distance,
- bool backArrows
- )
-{
- bool reNumber=TRUE;
-
- //printf("computeMd5Signature\n");
- QString buf;
- QTextStream md5stream(&buf,IO_WriteOnly);
- if (lrRank)
- {
- md5stream << "rankdir=LR;" << endl;
- }
- root->clearWriteFlag();
- root->write(md5stream,gt,format,gt!=DotNode::CallGraph,TRUE,distance,backArrows,reNumber);
- if (renderParents && root->m_parents)
- {
- QListIterator<DotNode> dnli(*root->m_parents);
- DotNode *pn;
- for (dnli.toFirst();(pn=dnli.current());++dnli)
- {
- if (pn->m_distance<=distance)
- {
- root->writeArrow(md5stream,
- gt,
- format,
- pn,
- pn->m_edgeInfo->at(pn->m_children->findRef(root)),
- FALSE,
- backArrows,
- reNumber
- );
- }
- pn->write(md5stream,gt,format,TRUE,FALSE,distance,backArrows,reNumber);
- }
- }
- uchar md5_sig[16];
- QCString sigStr(33);
- MD5Buffer((const unsigned char *)buf.ascii(),buf.length(),md5_sig);
- MD5SigToString(md5_sig,sigStr.data(),33);
- if (reNumber)
- {
- resetReNumbering();
- }
- //printf("md5: %s | file: %s\n",sigStr,baseName.data());
- return sigStr;
-}
-
-static bool findMaximalDotGraph(DotNode *root,
- int maxDist,
- const QCString &baseName,
- QDir &thisDir,
- DotNode::GraphType gt,
- GraphOutputFormat format,
- bool lrRank /*=FALSE*/,
- bool renderParents /*=FALSE*/,
- bool backArrows /*=TRUE*/
- )
-{
- bool reNumber=TRUE;
- int minDistance=1; // min distance that shows only direct children.
- int curDistance; //=QMIN(2,maxDist); // current distance to try
- int maxDistance=maxDist; // max distance that show whole graph
- int width=0;
- int height=0;
- int maxDotGraphWidth = Config_getInt("MAX_DOT_GRAPH_WIDTH");
- int maxDotGraphHeight = Config_getInt("MAX_DOT_GRAPH_HEIGHT");
- int lastFit=minDistance;
-
- // binary search for the maximal inheritance depth that fits in a reasonable
- // sized image (dimensions: Config_getInt("MAX_DOT_GRAPH_WIDTH"), Config_getInt("MAX_DOT_GRAPH_HEIGHT"))
- while (minDistance<=maxDistance)
- {
- curDistance = (minDistance+maxDistance)/2;
-
- writeDotGraph(root,gt,format,baseName,lrRank,renderParents,
- curDistance,backArrows,reNumber);
-
- // create annotated dot file
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob("dot",baseName+"_tmp.dot");
- if (!dotRun.run())
- {
- return FALSE;
- }
-
- // extract bounding box from the result
- readBoundingBoxDot(baseName+"_tmp.dot",&width,&height);
- width = width *96/72; // 96 pixels/inch, 72 points/inch
- height = height*96/72; // 96 pixels/inch, 72 points/inch
- //printf("Found bounding box (%d,%d) max (%d,%d)\n",width,height,
- // Config_getInt("MAX_DOT_GRAPH_WIDTH"),Config_getInt("MAX_DOT_GRAPH_HEIGHT"));
-
- // remove temporary dot file
- thisDir.remove(baseName+"_tmp.dot");
-
- bool graphFits=(width<maxDotGraphWidth && height<maxDotGraphHeight);
- if (graphFits) // graph is small enough
- {
- lastFit=curDistance;
- minDistance=curDistance+1;
- //printf("Image fits [%d-%d]\n",minDistance,maxDistance);
- }
- else // graph does not fit anymore with curDistance
- {
- //printf("Image does not fit [%d-%d]\n",minDistance,maxDistance);
- maxDistance=curDistance-1;
- }
- }
- //printf("lastFit=%d\n",lastFit);
-
- bool hasLRRank = (lrRank ||
- (minDistance==1 &&
- width>Config_getInt("MAX_DOT_GRAPH_WIDTH") &&
- !Config_getBool("UML_LOOK")
- )
- );
-
- writeDotGraph(root,
- gt,
- format,
- baseName,
- hasLRRank,
- renderParents,
- lastFit,
- backArrows,
- reNumber
- );
- if (reNumber)
- {
- resetReNumbering();
- }
- return TRUE;
-}
-
-QCString DotClassGraph::diskName() const
-{
- QCString result=m_diskName.copy();
- switch (m_graphType)
- {
- case DotNode::Collaboration:
- result+="_coll_graph";
- break;
- //case Interface:
- // result+="_intf_graph";
- // break;
- case DotNode::Inheritance:
- result+="_inherit_graph";
- break;
- default:
- ASSERT(0);
- break;
- }
- return result;
-}
-
-QCString DotClassGraph::writeGraph(QTextStream &out,
- GraphOutputFormat format,
- const char *path,
- const char *relPath,
- bool isTBRank,
- bool generateImageMap)
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Error: Output dir %s does not exist!\n",path); exit(1);
- }
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(d.absPath());
- QDir thisDir;
-
- QCString baseName;
- QCString mapName;
- switch (m_graphType)
- {
- case DotNode::Collaboration:
- mapName="coll_map";
- break;
- //case Interface:
- // mapName="intf_map";
- // break;
- case DotNode::Inheritance:
- mapName="inherit_map";
- break;
- default:
- ASSERT(0);
- break;
- }
- baseName = convertNameToFile(diskName());
-
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- QCString md5 = computeMd5Signature(m_startNode, // root
- m_graphType, // gt
- format, // format
- !isTBRank, // lrRank
- m_graphType==DotNode::Inheritance, // renderParent
- QMIN(m_recDepth,m_maxDistance), // maxDist
- TRUE // backArrows
- );
- if (checkAndUpdateMd5Signature(baseName,md5) ||
- !QFileInfo(baseName+".map").exists()
- )
- {
- findMaximalDotGraph(m_startNode, // root
- QMIN(m_recDepth,m_maxDistance), // maxDist
- baseName, // baseName
- thisDir, // thisDir
- m_graphType, // gt
- format, // format
- !isTBRank, // lrRank
- m_graphType==DotNode::Inheritance, // renderParents
- TRUE // backArrows
- );
- if (format==BITMAP) // run dot to create a bitmap image
- {
- QCString dotArgs(maxCmdLine);
- QCString imgName = baseName+"."+imgExt;
-
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob(imgExt,imgName);
- if (generateImageMap) dotRun.addJob("imap",baseName+".map");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
-
- checkDotResult(imgName);
- }
- else if (format==EPS) // run dot to create a .eps image
- {
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob("ps",baseName+".eps");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
-
- if (Config_getBool("USE_PDFLATEX"))
- {
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- baseName.data(),baseName.data());
- if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
- {
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- }
-
- }
- if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
- }
-
- if (format==BITMAP && generateImageMap) // run dot to create a image map
- {
- QCString mapLabel = convertNameToFile(m_startNode->m_label+"_"+mapName);
- out << "<p><center><img src=\"" << relPath << baseName << "."
- << imgExt << "\" border=\"0\" usemap=\"#"
- << mapLabel << "\" alt=\"";
- switch (m_graphType)
- {
- case DotNode::Collaboration:
- out << "Collaboration graph";
- break;
- case DotNode::Inheritance:
- out << "Inheritance graph";
- break;
- default:
- ASSERT(0);
- break;
- }
- out << "\"></center>" << endl;
- QString tmpstr;
- QTextOStream tmpout(&tmpstr);
- convertMapFile(tmpout,baseName+".map",relPath);
- if (!tmpstr.isEmpty())
- {
- out << "<map name=\"" << mapLabel << "\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
- }
- //thisDir.remove(baseName+".map");
- }
- else if (format==EPS) // run dot to create a .eps image
- {
- int width,height;
- if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
- {
- err("Error: Could not extract bounding box from .eps!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- int maxWidth = 420; /* approx. page width in points */
- out << "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
- }
-
- QDir::setCurrent(oldDir);
- return baseName;
-}
-
-//--------------------------------------------------------------------
-
-void DotClassGraph::writeXML(QTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeXML(t,TRUE);
- }
-}
-
-void DotClassGraph::writeDEF(QTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeDEF(t);
- }
-}
-
-//--------------------------------------------------------------------
-
-int DotInclDepGraph::m_curNodeNumber = 0;
-
-void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd,int distance)
-{
- QList<IncludeInfo> *includeFiles =
- m_inverse ? fd->includedByFileList() : fd->includeFileList();
- QListIterator<IncludeInfo> ili(*includeFiles);
- IncludeInfo *ii;
- for (;(ii=ili.current());++ili)
- {
- FileDef *bfd = ii->fileDef;
- QCString in = ii->includeName;
- //printf(">>>> in=`%s' bfd=%p\n",ii->includeName.data(),bfd);
- bool doc=TRUE,src=FALSE;
- if (bfd)
- {
- in = bfd->absFilePath();
- doc = bfd->isLinkable() && bfd->isHidden();
- src = bfd->generateSourceFile();
- }
- if (doc || src || !Config_getBool("HIDE_UNDOC_RELATIONS"))
- {
- QCString url="";
- if (bfd) url=bfd->getOutputFileBase().copy();
- if (!doc && src)
- {
- url+="-source";
- }
- DotNode *bn = m_usedNodes->find(in);
- if (bn) // file is already a node in the graph
- {
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- bn->setDistance(distance);
- }
- else
- {
- QCString tmp_url;
- if (bfd) tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString();
- bn = new DotNode(
- m_curNodeNumber++,
- ii->includeName,
- tmp_url,
- distance
- );
- if (distance>m_maxDistance) m_maxDistance=distance;
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- m_usedNodes->insert(in,bn);
-
- // we use <=, i.s.o < to cause one more level than intended which is used to
- // detect truncated nodes
- if (bfd && distance<=m_recDepth) buildGraph(bn,bfd,distance+1);
- }
- }
- }
-}
-
-DotInclDepGraph::DotInclDepGraph(FileDef *fd,int maxRecursionDepth,bool inverse)
-{
- m_maxDistance = 0;
- m_recDepth = maxRecursionDepth;
- m_inverse = inverse;
- ASSERT(fd!=0);
- m_diskName = fd->getFileBase().copy();
- QCString tmp_url=fd->getReference()+"$"+fd->getFileBase();
- m_startNode = new DotNode(m_curNodeNumber++,
- fd->docName(),
- tmp_url.data(),
- 0, // distance
- TRUE // root node
- );
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->insert(fd->absFilePath(),m_startNode);
- buildGraph(m_startNode,fd,1);
-}
-
-DotInclDepGraph::~DotInclDepGraph()
-{
- deleteNodes(m_startNode);
- delete m_usedNodes;
-}
-
-QCString DotInclDepGraph::diskName() const
-{
- QCString result=m_diskName.copy();
- if (m_inverse) result+="_dep";
- result+="_incl";
- return convertNameToFile(result);
-}
-
-QCString DotInclDepGraph::writeGraph(QTextStream &out,
- GraphOutputFormat format,
- const char *path,
- const char *relPath,
- bool generateImageMap
- )
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Error: Output dir %s does not exist!\n",path); exit(1);
- }
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(d.absPath());
- QDir thisDir;
-
- QCString baseName=m_diskName;
- if (m_inverse) baseName+="_dep";
- baseName+="_incl";
- baseName=convertNameToFile(baseName);
- QCString mapName=m_startNode->m_label.copy();
- if (m_inverse) mapName+="dep";
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
-
- QCString md5 = computeMd5Signature(m_startNode, // root
- DotNode::CallGraph, // gt
- format, // format
- TRUE, // lrRank
- FALSE, // renderParents
- QMIN(m_recDepth,m_maxDistance), // maxDist
- FALSE // backArrows
- );
- if (checkAndUpdateMd5Signature(baseName,md5) ||
- !QFileInfo(baseName+".map").exists()
- )
- {
- findMaximalDotGraph(m_startNode, // root
- QMIN(m_recDepth,m_maxDistance), // maxDist
- baseName, // baseName
- thisDir, // thisDir
- DotNode::CallGraph, // gt
- format, // format
- TRUE, // lrRank
- FALSE, // renderParents
- m_inverse // backArrows
- );
- if (format==BITMAP)
- {
- // run dot to create a bitmap image
- QCString dotArgs(maxCmdLine);
- QCString imgName=baseName+"."+imgExt;
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob(imgExt,imgName);
- if (generateImageMap) dotRun.addJob("imap",baseName+".map");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
- checkDotResult(imgName);
- }
- else if (format==EPS)
- {
- // run dot to create a .eps image
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob("ps",baseName+".eps");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
- if (Config_getBool("USE_PDFLATEX"))
- {
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- baseName.data(),baseName.data());
- if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
- {
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- }
- }
- }
-
- if (format==BITMAP && generateImageMap)
- {
- out << "<p><center><img src=\"" << relPath << baseName << "."
- << imgExt << "\" border=\"0\" usemap=\"#"
- << mapName << "_map\" alt=\"";
- out << "\">";
- out << "</center>" << endl;
- QString tmpstr;
- QTextOStream tmpout(&tmpstr);
- convertMapFile(tmpout,baseName+".map",relPath);
- if (!tmpstr.isEmpty())
- {
- out << "<map name=\"" << mapName << "_map\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
- }
- //thisDir.remove(baseName+".map");
- }
- else if (format==EPS)
- {
- int width,height;
- if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
- {
- err("Error: Could not extract bounding box from .eps!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- int maxWidth = 420; /* approx. page width in points */
-
- out << "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
- }
-
- if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
-
- QDir::setCurrent(oldDir);
- return baseName;
-}
-
-bool DotInclDepGraph::isTrivial() const
-{
- return m_startNode->m_children==0;
-}
-
-void DotInclDepGraph::writeXML(QTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeXML(t,FALSE);
- }
-}
-
-//-------------------------------------------------------------
-
-int DotCallGraph::m_curNodeNumber = 0;
-
-DotCallGraph::DotCallGraph(MemberDef *md,int maxRecursionDepth)
-{
- m_maxDistance = 0;
- m_recDepth = maxRecursionDepth;
- m_diskName = md->getOutputFileBase()+"_"+md->anchor();
- m_scope = md->getOuterScope();
- QCString uniqueId;
- uniqueId = md->getReference()+"$"+
- md->getOutputFileBase()+"#"+md->anchor();
- QCString name;
- if (Config_getBool("HIDE_SCOPE_NAMES"))
- {
- name = md->name();
- }
- else
- {
- name = md->qualifiedName();
- }
- m_startNode = new DotNode(m_curNodeNumber++,
- linkToText(name,FALSE),
- uniqueId.data(),
- 0, // distance
- TRUE // root node
- );
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->insert(uniqueId,m_startNode);
- buildGraph(m_startNode,md,1);
-}
-
-DotCallGraph::~DotCallGraph()
-{
- deleteNodes(m_startNode);
- delete m_usedNodes;
-}
-
-QCString DotCallGraph::writeGraph(QTextStream &out, GraphOutputFormat format,
- const char *path,const char *relPath,bool generateImageMap)
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Error: Output dir %s does not exist!\n",path); exit(1);
- }
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(d.absPath());
- QDir thisDir;
-
- QCString baseName=m_diskName+"_cgraph";
- QCString mapName=baseName;
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
-
- QCString md5 = computeMd5Signature(m_startNode, // root
- DotNode::CallGraph, // gt
- format, // format
- TRUE, // lrRank
- FALSE, // renderParents
- QMIN(m_recDepth,m_maxDistance), // maxDist
- FALSE // backArrows
- );
- if (checkAndUpdateMd5Signature(baseName,md5) ||
- !QFileInfo(baseName+".map").exists()
- )
- {
- findMaximalDotGraph(m_startNode, // root
- QMIN(m_recDepth,m_maxDistance), // maxDist
- baseName, // baseName
- thisDir, // thisDir
- DotNode::CallGraph, // gt
- format, // format
- TRUE, // lrRank
- FALSE, // renderParents
- FALSE // backArrows
- );
- if (format==BITMAP)
- {
- // run dot to create a bitmap image
- QCString dotArgs(maxCmdLine);
- QCString imgName=baseName+"."+imgExt;
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob(imgExt,imgName);
- if (generateImageMap) dotRun.addJob("imap",baseName+".map");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
- checkDotResult(imgName);
- }
- else if (format==EPS)
- {
- // run dot to create a .eps image
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob("ps",baseName+".eps");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
- if (Config_getBool("USE_PDFLATEX"))
- {
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- baseName.data(),baseName.data());
- if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
- {
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- }
- }
- }
-
- if (format==BITMAP && generateImageMap)
- {
- out << "<p><center><img src=\"" << relPath << baseName << "."
- << imgExt << "\" border=\"0\" usemap=\"#"
- << mapName << "_map\" alt=\"";
- out << "\">";
- out << "</center>" << endl;
- QString tmpstr;
- QTextOStream tmpout(&tmpstr);
- convertMapFile(tmpout,baseName+".map",relPath);
- if (!tmpstr.isEmpty())
- {
- out << "<map name=\"" << mapName << "_map\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
- }
- //thisDir.remove(baseName+".map");
- }
- else if (format==EPS)
- {
- int width,height;
- if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
- {
- err("Error: Could not extract bounding box from .eps!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- int maxWidth = 420; /* approx. page width in points */
-
- out << "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
- }
-
- if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
-
- QDir::setCurrent(oldDir);
- return baseName;
-}
-
-void DotCallGraph::buildGraph(DotNode *n,MemberDef *md,int distance)
-{
- MemberSDict *refs = md->getReferencesMembers();
- if (refs)
- {
- MemberSDict::Iterator mri(*refs);
- MemberDef *rmd;
- for (;(rmd=mri.current());++mri)
- {
- if (rmd->isFunction())
- {
- QCString uniqueId;
- uniqueId=rmd->getReference()+"$"+
- rmd->getOutputFileBase()+"#"+rmd->anchor();
- DotNode *bn = m_usedNodes->find(uniqueId);
- if (bn) // file is already a node in the graph
- {
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- bn->setDistance(distance);
- }
- else
- {
- QCString name;
- if (Config_getBool("HIDE_SCOPE_NAMES"))
- {
- name = rmd->getOuterScope()==m_scope ?
- rmd->name() : rmd->qualifiedName();
- }
- else
- {
- name = rmd->qualifiedName();
- }
- bn = new DotNode(
- m_curNodeNumber++,
- linkToText(name,FALSE),
- uniqueId,
- distance
- );
- if (distance>m_maxDistance) m_maxDistance=distance;
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- m_usedNodes->insert(uniqueId,bn);
-
- // we use <=, i.s.o < to cause one more level than intended which is used to
- // detect truncated nodes
- if (distance<=m_recDepth) buildGraph(bn,rmd,distance+1);
- }
- }
- }
- }
-}
-
-bool DotCallGraph::isTrivial() const
-{
- return m_startNode->m_children==0;
-}
-
-//-------------------------------------------------------------
-
-DotDirDeps::DotDirDeps(DirDef *dir) : m_dir(dir)
-{
-}
-
-DotDirDeps::~DotDirDeps()
-{
-}
-
-QCString DotDirDeps::writeGraph(QTextStream &out,
- GraphOutputFormat format,
- const char *path,
- const char *relPath,
- bool generateImageMap)
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Error: Output dir %s does not exist!\n",path); exit(1);
- }
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(d.absPath());
- QDir thisDir;
-
- QCString baseName=m_dir->getOutputFileBase()+"_dep";
- QCString mapName=baseName;
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
-
- // todo: create check, update md5 checksum
- {
- QFile f(baseName+".dot");
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot create file %s.dot for writing!\n",baseName.data());
- }
- QTextStream t(&f);
- m_dir->writeDepGraph(t);
- f.close();
-
- if (format==BITMAP)
- {
- // run dot to create a bitmap image
- QCString dotArgs(maxCmdLine);
- QCString imgName=baseName+"."+imgExt;
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob(imgExt,imgName);
- if (generateImageMap) dotRun.addJob("imap",baseName+".map");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
- checkDotResult(imgName);
- }
- else if (format==EPS)
- {
- // run dot to create a .eps image
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob("ps",baseName+".eps");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
- if (Config_getBool("USE_PDFLATEX"))
- {
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- baseName.data(),baseName.data());
- if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
- {
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- }
- }
- }
-
- if (format==BITMAP && generateImageMap)
- {
- out << "<p><center><img src=\"" << relPath << baseName << "."
- << imgExt << "\" border=\"0\" usemap=\"#"
- << mapName << "_map\" alt=\"";
- out << m_dir->displayName();
- out << "\">";
- out << "</center>" << endl;
- QString tmpstr;
- QTextOStream tmpout(&tmpstr);
- convertMapFile(tmpout,baseName+".map",relPath,TRUE);
- if (!tmpstr.isEmpty())
- {
- out << "<map name=\"" << mapName << "_map\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
- }
- else
- {
- //printf("Map is empty!\n");
- }
- //thisDir.remove(baseName+".map");
- }
- else if (format==EPS)
- {
- int width,height;
- if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
- {
- err("Error: Could not extract bounding box from .eps!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- int maxWidth = 420; /* approx. page width in points */
-
- out << "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
- }
-
- if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
-
- QDir::setCurrent(oldDir);
- return baseName;
-
-
-}
-
-bool DotDirDeps::isTrivial() const
-{
- return m_dir->depGraphIsTrivial();
-}
-
-//-------------------------------------------------------------
-
-void generateGraphLegend(const char *path)
-{
- QFile dotFile((QCString)path+"/graph_legend.dot");
- if (!dotFile.open(IO_WriteOnly))
- {
- err("Could not open file %s for writing\n",
- convertToQCString(dotFile.name()).data());
- return;
- }
- QTextStream dotText(&dotFile);
- writeGraphHeader(dotText);
- dotText << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"black\",style=\"filled\" fontcolor=\"white\"];\n";
- dotText << " Node10 -> Node9 [dir=back,color=\"midnightblue\",fontsize=10,style=\"solid\",fontname=\"Helvetica\"];\n";
- dotText << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node11 -> Node10 [dir=back,color=\"midnightblue\",fontsize=10,style=\"solid\",fontname=\"Helvetica\"];\n";
- dotText << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node13 -> Node9 [dir=back,color=\"darkgreen\",fontsize=10,style=\"solid\",fontname=\"Helvetica\"];\n";
- dotText << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node14 -> Node9 [dir=back,color=\"firebrick4\",fontsize=10,style=\"solid\",fontname=\"Helvetica\"];\n";
- dotText << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node15 -> Node9 [dir=back,color=\"midnightblue\",fontsize=10,style=\"solid\",fontname=\"Helvetica\"];\n";
- dotText << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"grey75\"];\n";
- dotText << " Node16 -> Node9 [dir=back,color=\"midnightblue\",fontsize=10,style=\"solid\",fontname=\"Helvetica\"];\n";
- dotText << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node17 -> Node16 [dir=back,color=\"orange\",fontsize=10,style=\"dashed\",label=\"< int >\",fontname=\"Helvetica\"];\n";
- dotText << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
- dotText << " Node18 -> Node9 [dir=back,color=\"darkorchid3\",fontsize=10,style=\"dashed\",label=\"m_usedClass\",fontname=\"Helvetica\"];\n";
- dotText << " Node18 [shape=\"box\",label=\"Used\",fontsize=10,height=0.2,width=0.4,fontname=\"Helvetica\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n";
- writeGraphFooter(dotText);
- dotFile.close();
-
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Error: Output dir %s does not exist!\n",path); exit(1);
- }
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(d.absPath());
-
- // run dot to generate the a bitmap image from the graph
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- QCString imgName = "graph_legend."+imgExt;
-
- DotRunner dotRun("graph_legend.dot");
- dotRun.addJob(imgExt,imgName);
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return;
- }
- checkDotResult(imgName);
- QDir::setCurrent(oldDir);
-}
-
-
-void writeDotGraphFromFile(const char *inFile,const char *outDir,
- const char *outFile,GraphOutputFormat format)
-{
- QCString absOutFile = outDir;
-#ifdef _WIN32
- absOutFile+='\\';
-#else
- absOutFile+='/';
-#endif
- absOutFile+=outFile;
-
- // chdir to the output dir, so dot can find the font file.
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(outDir);
- //printf("Going to dir %s\n",QDir::currentDirPath().data());
-
- //{ // copy input file to output dir.
- // QFile inf(inFile,IO_ReadOnly);
- // QFileInfo infinfo(inf);
- // uint s = infinfo.size();
- // QByteArray a(s);
- // inf.readBlock(a.data(),s);
- // QFile outf(outDir,IO_WriteOnly);
- // outf.writeBlock(a.data(),s);
- //}
-
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- QCString imgName = (QCString)outFile+"."+imgExt;
-
- DotRunner dotRun(inFile);
- if (format==BITMAP)
- dotRun.addJob(imgExt,imgName);
- else // format==EPS
- dotRun.addJob("ps",QCString(outFile)+".eps");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return;
- }
- // Added by Nils Strom
- if ( (format==EPS) && (Config_getBool("USE_PDFLATEX")) )
- {
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- outFile,outFile);
- if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
- {
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- }
- }
-
- if (format==BITMAP) checkDotResult(imgName);
-
- QDir::setCurrent(oldDir);
-}
-
-
-/*! Marco Dalla Gasperina [marcodg@attbi.com] added this to allow
- * dotfiles to generate image maps.
- * \param inFile just the basename part of the filename
- * \param outDir output directory
- * \param relPath relative path the to root of the output dir
- * \returns a string which is the HTML image map (without the \<map\>\</map\>)
- */
-QString getDotImageMapFromFile(const QString& inFile, const QString& outDir,
- const QCString &relPath)
-{
- QString outFile = inFile + ".map";
-
- // chdir to the output dir, so dot can find the font file.
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the html output directory (i.e. path)
- QDir::setCurrent(outDir);
- //printf("Going to dir %s\n",QDir::currentDirPath().data());
-
- DotRunner dotRun(inFile);
- dotRun.addJob("imap",outFile);
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return "";
- }
-
- QString result;
- QTextOStream tmpout(&result);
- convertMapFile(tmpout, outFile, relPath ,TRUE);
- QDir().remove(outFile);
-// printf("result=%s\n",result.data());
-
- QDir::setCurrent(oldDir);
- return result;
-}
-// end MDG mods
-
-//-------------------------------------------------------------
-
-DotGroupCollaboration::DotGroupCollaboration(GroupDef* gd)
-{
- m_curNodeId = 0;
- QCString tmp_url = gd->getReference()+"$"+gd->getOutputFileBase();
- m_usedNodes = new QDict<DotNode>(1009);
- m_rootNode = new DotNode(m_curNodeId++, gd->groupTitle(), tmp_url, 0, TRUE );
- m_usedNodes->insert(gd->name(), m_rootNode );
- m_edges.setAutoDelete(TRUE);
-
- m_diskName = gd->getOutputFileBase();
-
- buildGraph( gd, 0 );
-}
-
-DotGroupCollaboration::~DotGroupCollaboration()
-{
- delete m_usedNodes;
-}
-
-void DotGroupCollaboration::buildGraph(GroupDef* gd,int)
-{
- QCString tmp_url;
- //===========================
- // hierarchy.
-
- // Write parents
- if ( gd->partOfGroups() )
- {
- GroupListIterator gli(*gd->partOfGroups());
- GroupDef *d;
- for (gli.toFirst();(d=gli.current());++gli)
- {
- DotNode* nnode = m_usedNodes->find(d->name());
- if ( !nnode )
- { // add node
- tmp_url = d->getReference()+"$"+d->getOutputFileBase();
- nnode = new DotNode(m_curNodeId++, d->groupTitle(), tmp_url );
- m_usedNodes->insert(d->name(), nnode );
- }
- tmp_url = "";
- addEdge( nnode, m_rootNode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url );
- }
- }
-
- // Add subgroups
- if ( gd->getSubGroups() && gd->getSubGroups()->count() )
- {
- QListIterator<GroupDef> defli(*gd->getSubGroups());
- GroupDef *def;
- for (;(def=defli.current());++defli)
- {
- DotNode* nnode = m_usedNodes->find(def->name());
- if ( !nnode )
- { // add node
- tmp_url = def->getReference()+"$"+def->getOutputFileBase();
- nnode = new DotNode(m_curNodeId++, def->groupTitle(), tmp_url );
- m_usedNodes->insert(def->name(), nnode );
- }
- tmp_url = "";
- addEdge( m_rootNode, nnode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url );
- }
- }
-
- //=======================
- // Write collaboration
-
- // Add members
- addMemberList( gd->getMembers() );
-
- // Add classes
- if ( gd->getClasses() && gd->getClasses()->count() )
- {
- ClassSDict::Iterator defli(*gd->getClasses());
- ClassDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass );
- }
- }
-
- // Add namespaces
- if ( gd->getNamespaces() && gd->getNamespaces()->count() )
- {
- NamespaceSDict::Iterator defli(*gd->getNamespaces());
- NamespaceDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace );
- }
- }
-
- // Add files
- if ( gd->getFiles() && gd->getFiles()->count() )
- {
- QListIterator<FileDef> defli(*gd->getFiles());
- FileDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile );
- }
- }
-
- // Add pages
- if ( gd->getPages() && gd->getPages()->count() )
- {
- PageSDict::Iterator defli(*gd->getPages());
- PageDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages );
- }
- }
-
- // Add directories
- if ( gd->getDirs() && gd->getDirs()->count() )
- {
- QListIterator<DirDef> defli(*gd->getDirs());
- DirDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir );
- }
- }
-}
-
-void DotGroupCollaboration::addMemberList( MemberList* ml )
-{
- if ( !( ml && ml->count()) ) return;
- MemberListIterator defli(*ml);
- MemberDef *def;
- for (;(def=defli.current());++defli)
- {
- QCString tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension
- +"#"+def->anchor();
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tmember );
- }
-}
-
-DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge(
- DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType,
- const QCString& _label, const QCString& _url )
-{
- // search a existing link.
- QListIterator<Edge> lli(m_edges);
- Edge* newEdge = 0;
- for ( lli.toFirst(); (newEdge=lli.current()); ++lli)
- {
- if ( newEdge->pNStart==_pNStart &&
- newEdge->pNEnd==_pNEnd &&
- newEdge->eType==_eType
- )
- { // edge already found
- break;
- }
- }
- if ( newEdge==0 ) // new link
- {
- newEdge = new Edge(_pNStart,_pNEnd,_eType);
- m_edges.append( newEdge );
- }
-
- if (!_label.isEmpty())
- {
- newEdge->links.append(new Link(_label,_url));
- }
-
- return newEdge;
-}
-
-void DotGroupCollaboration::addCollaborationMember(
- Definition* def, QCString& url, EdgeType eType )
-{
- // Create group nodes
- if ( !def->partOfGroups() )
- return;
- GroupListIterator gli(*def->partOfGroups());
- GroupDef *d;
- QCString tmp_str;
- for (;(d=gli.current());++gli)
- {
- DotNode* nnode = m_usedNodes->find(d->name());
- if ( nnode != m_rootNode )
- {
- if ( nnode==0 )
- { // add node
- tmp_str = d->getReference()+"$"+d->getOutputFileBase();
- nnode = new DotNode(m_curNodeId++, d->groupTitle(), tmp_str );
- m_usedNodes->insert(d->name(), nnode );
- }
- tmp_str = def->qualifiedName();
- addEdge( m_rootNode, nnode, eType, tmp_str, url );
- }
- }
-}
-
-
-QCString DotGroupCollaboration::writeGraph( QTextStream &t, GraphOutputFormat format,
- const char *path, const char *relPath,
- bool writeImageMap)
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Error: Output dir %s does not exist!\n",path);
- exit(1);
- }
- QCString oldDir = convertToQCString(QDir::currentDirPath());
- // go to the output directory (i.e. path)
- QDir::setCurrent(d.absPath());
- QDir thisDir;
- QCString baseName = m_diskName;
-
- QFile dotfile(baseName+".dot");
- if (dotfile.open(IO_WriteOnly))
- {
- QTextStream tdot(&dotfile);
- writeGraphHeader(tdot);
-
- // clean write flags
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *pn;
- for (dni.toFirst();(pn=dni.current());++dni)
- pn->clearWriteFlag();
-
- // write other nodes.
- for (dni.toFirst();(pn=dni.current());++dni)
- {
- pn->write(tdot,DotNode::Inheritance,format,TRUE,FALSE,1,FALSE,FALSE);
- }
-
- // write edges
- QListIterator<Edge> eli(m_edges);
- Edge* edge;
- for (eli.toFirst();(edge=eli.current());++eli)
- {
- edge->write( tdot, m_curNodeId );
- }
-
- writeGraphFooter(tdot);
- dotfile.close();
- }
-
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- if (format==BITMAP) // run dot to create a bitmap image
- {
- QCString dotArgs(maxCmdLine);
- QCString imgName = baseName+"."+imgExt;
- QCString mapName=baseName+".map";
-
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob(imgExt,imgName);
- if (writeImageMap) dotRun.addJob("imap",mapName);
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
-
- if (writeImageMap)
- {
- QCString mapLabel = convertNameToFile(baseName);
- t << "<center><table><tr><td><img src=\"" << relPath << imgName
- << "\" border=\"0\" alt=\"\" usemap=\"#"
- << mapLabel << "_map\">" << endl;
- t << "<map name=\"" << mapLabel << "_map\">" << endl;
- convertMapFile(t,mapName,relPath);
- t << "</map></td></tr></table></center>" << endl;
- thisDir.remove(mapName);
- }
- }
- else if (format==EPS)
- {
- DotRunner dotRun(baseName+".dot");
- dotRun.addJob("ps",baseName+".eps");
- if (!dotRun.run())
- {
- QDir::setCurrent(oldDir);
- return baseName;
- }
-
- if (Config_getBool("USE_PDFLATEX"))
- {
- QCString epstopdfArgs(maxCmdLine);
- epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- baseName.data(),baseName.data());
- if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
- {
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- }
- int width,height;
- if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
- {
- err("Error: Could not extract bounding box from .eps!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- int maxWidth = 420; /* approx. page width in points */
- t << "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- "\\includegraphics[width=" << QMIN(width/2,maxWidth)
- << "pt]{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
- }
- if (Config_getBool("DOT_CLEANUP"))
- {
- thisDir.remove(baseName+".dot");
- }
-
- QDir::setCurrent(oldDir);
-
- return baseName;
-}
-
-void DotGroupCollaboration::Edge::write( QTextStream &t, int& )
-{
- const char* linkTypeColor[] = {
- "darkorchid3"
- ,"orange"
- ,"blueviolet"
- ,"darkgreen"
- ,"firebrick4"
- ,"grey75"
- ,"midnightblue"
- };
- QCString arrowStyle = "dir=\"none\", style=\"dashed\"";
- t << " Node" << pNStart->number();
- t << "->";
- t << "Node" << pNEnd->number();
-
- t << " [shape=plaintext";
- if (links.count()>0) // there are links
- {
- t << ", ";
- // HTML-like edge labels crash on my Mac with Graphviz 2.0! and
- // are not supported by older version of dot.
- //
- //t << label=<<TABLE BORDER=\"0\" CELLBORDER=\"0\">";
- //QListIterator<Link> lli(links);
- //Link *link;
- //for( lli.toFirst(); (link=lli.current()); ++lli)
- //{
- // t << "<TR><TD";
- // if ( !link->url.isEmpty() )
- // t << " HREF=\"" << link->url << "\"";
- // t << ">" << link->label << "</TD></TR>";
- //}
- //t << "</TABLE>>";
-
- t << "label=\"";
- QListIterator<Link> lli(links);
- Link *link;
- bool first=TRUE;
- for( lli.toFirst(); (link=lli.current()); ++lli)
- {
- if (first) first=FALSE; else t << "\\n";
- t << convertLabel(link->label);
- }
- t << "\"";
-
- }
- switch( eType )
- {
- case thierarchy :
- arrowStyle = "dir=\"back\", style=\"solid\"";
- default :
- t << ", color=\"" << linkTypeColor[(int)eType] << "\"";
- break;
- }
- t << ", " << arrowStyle;
- t << "];" << endl;
-}
-
-bool DotGroupCollaboration::isTrivial() const
-{
- return m_usedNodes->count() <= 1;
-}
-
-void DotGroupCollaboration::writeGraphHeader(QTextStream &t)
-{
- t << "digraph structs" << endl;
- t << "{" << endl;
- if (Config_getBool("DOT_TRANSPARENT"))
- {
- t << " bgcolor=\"transparent\";" << endl;
- }
- t << " edge [fontname=\"Helvetica\",fontsize=8,"
- "labelfontname=\"Helvetica\",labelfontsize=8];\n";
- t << " node [fontname=\"Helvetica\",fontsize=10,shape=record];\n";
- t << "rankdir=LR;\n";
-}