My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
DotClassGraph Class Reference

#include <dot.h>

Public Member Functions

 DotClassGraph (ClassDef *cd, DotNode::GraphType t)
 
 ~DotClassGraph ()
 
bool isTrivial () const
 
bool isTooBig () const
 
QCString writeGraph (FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, const char *path, const char *fileName, const char *relPath, bool TBRank=TRUE, bool imageMap=TRUE, int graphId=-1) const
 
void writeXML (FTextStream &t)
 
void writeDocbook (FTextStream &t)
 
void writeDEF (FTextStream &t)
 

Static Public Member Functions

static void resetNumbering ()
 

Private Member Functions

void buildGraph (ClassDef *cd, DotNode *n, bool base, int distance)
 
bool determineVisibleNodes (DotNode *rootNode, int maxNodes, bool includeParents)
 
void determineTruncatedNodes (QList< DotNode > &queue, bool includeParents)
 
void addClass (ClassDef *cd, DotNode *n, int prot, const char *label, const char *usedName, const char *templSpec, bool base, int distance)
 

Private Attributes

DotNodem_startNode
 
QDict< DotNode > * m_usedNodes
 
DotNode::GraphType m_graphType
 
QCString m_collabFileName
 
QCString m_inheritFileName
 
bool m_lrRank
 

Static Private Attributes

static int m_curNodeNumber = 0
 

Detailed Description

Representation of a class inheritance or dependency graph

Definition at line 169 of file dot.h.

Constructor & Destructor Documentation

DotClassGraph::DotClassGraph ( ClassDef cd,
DotNode::GraphType  t 
)

Definition at line 2910 of file dot.cpp.

References ClassDef::anchor(), Definition::briefDescriptionAsTooltip(), buildGraph(), ClassDef::collaborationGraphFileName(), Config_getInt, determineTruncatedNodes(), determineVisibleNodes(), ClassDef::displayName(), ClassDef::getOutputFileBase(), ClassDef::getReference(), DotNode::Inheritance, ClassDef::inheritanceGraphFileName(), Definition::isHidden(), ClassDef::isLinkable(), m_collabFileName, m_curNodeNumber, m_graphType, m_inheritFileName, m_lrRank, m_startNode, m_usedNodes, and DotNode::setDistance().

{
//printf("--------------- DotClassGraph::DotClassGraph `%s'\n",cd->displayName().data());
QCString tmp_url="";
if (cd->isLinkable() && !cd->isHidden())
{
tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
if (!cd->anchor().isEmpty())
{
tmp_url+="#"+cd->anchor();
}
}
QCString className = cd->displayName();
QCString tooltip = cd->briefDescriptionAsTooltip();
className,
tooltip,
tmp_url.data(),
TRUE, // is a root node
cd
);
m_usedNodes = new QDict<DotNode>(1009);
m_usedNodes->insert(className,m_startNode);
//printf("Root node %s\n",cd->name().data());
//if (m_recDepth>0)
//{
buildGraph(cd,m_startNode,TRUE,1);
//}
static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES);
//int directChildNodes = 1;
//if (m_startNode->m_children!=0)
// directChildNodes+=m_startNode->m_children->count();
//if (t==DotNode::Inheritance && m_startNode->m_parents!=0)
// directChildNodes+=m_startNode->m_parents->count();
//if (directChildNodes>maxNodes) maxNodes=directChildNodes;
//openNodeQueue.append(m_startNode);
QList<DotNode> openNodeQueue;
openNodeQueue.append(m_startNode);
}
DotClassGraph::~DotClassGraph ( )

Definition at line 2981 of file dot.cpp.

References deleteNodes(), m_startNode, and m_usedNodes.

Member Function Documentation

void DotClassGraph::addClass ( ClassDef cd,
DotNode n,
int  prot,
const char *  label,
const char *  usedName,
const char *  templSpec,
bool  base,
int  distance 
)
private

Definition at line 2554 of file dot.cpp.

References DotNode::addChild(), DotNode::addParent(), ClassDef::anchor(), Definition::briefDescriptionAsTooltip(), buildGraph(), Config_getBool, EdgeInfo::Dashed, ClassDef::displayName(), ClassDef::getOutputFileBase(), ClassDef::getReference(), insertTemplateSpecifierInScope(), ClassDef::isAnonymous(), Definition::isHidden(), ClassDef::isLinkable(), m_curNodeNumber, m_usedNodes, Definition::name(), EdgeInfo::Orange, EdgeInfo::Orange2, DotNode::setDistance(), EdgeInfo::Solid, and stripScope().

Referenced by buildGraph().

{
if (Config_getBool(HIDE_UNDOC_CLASSES) && !cd->isLinkable()) return;
int edgeStyle = (label || prot==EdgeInfo::Orange || prot==EdgeInfo::Orange2) ? EdgeInfo::Dashed : EdgeInfo::Solid;
QCString className;
if (cd->isAnonymous())
{
className="anonymous:";
className+=label;
}
else 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();
if (!cd->anchor().isEmpty())
{
tmp_url+="#"+cd->anchor();
}
}
QCString tooltip = cd->briefDescriptionAsTooltip();
displayName,
tooltip,
tmp_url.data(),
FALSE, // rootNode
cd
);
if (base)
{
n->addChild(bn,prot,edgeStyle,label);
bn->addParent(n);
}
else
{
bn->addChild(n,prot,edgeStyle,label);
n->addParent(bn);
}
bn->setDistance(distance);
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());
buildGraph(cd,bn,base,distance+1);
}
}
void DotClassGraph::buildGraph ( ClassDef cd,
DotNode n,
bool  base,
int  distance 
)
private

Definition at line 2768 of file dot.cpp.

References UsesClassDef::accessors, ConstraintClassDef::accessors, addClass(), ClassDef::baseClasses(), UsesClassDef::classDef, BaseClassDef::classDef, ConstraintClassDef::classDef, DotNode::Collaboration, Config_getBool, ClassDef::getTemplateInstances(), DotNode::Inheritance, m_graphType, EdgeInfo::Orange, EdgeInfo::Orange2, BaseClassDef::prot, EdgeInfo::Purple, ClassDef::subClasses(), ClassDef::templateMaster(), ClassDef::templateTypeConstraints(), UsesClassDef::templSpecifiers, BaseClassDef::templSpecifiers, ClassDef::usedByImplementationClasses(), ClassDef::usedImplementationClasses(), and BaseClassDef::usedName.

Referenced by addClass(), and DotClassGraph().

{
static bool templateRelations = Config_getBool(TEMPLATE_RELATIONS);
//printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n",
// cd->name().data(),distance,base);
// ---- Add inheritance relations
{
BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses();
if (bcl)
{
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,bcd->usedName,
bcd->templSpecifiers,base,distance);
}
}
}
{
// ---- Add usage relations
UsesClassDict *dict =
;
if (dict)
{
UsesClassDictIterator ucdi(*dict);
for (;(ucd=ucdi.current());++ucdi)
{
QCString label;
QDictIterator<void> dvi(*ucd->accessors);
const char *s;
bool first=TRUE;
int count=0;
int maxLabels=10;
for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
{
if (first)
{
label=s;
first=FALSE;
}
else
{
label+=QCString("\n")+s;
}
}
if (count==maxLabels) label+="\n...";
//printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data());
ucd->templSpecifiers,base,distance);
}
}
}
if (templateRelations && base)
{
if (dict)
{
for (;(ccd=ccdi.current());++ccdi)
{
QCString label;
QDictIterator<void> dvi(*ccd->accessors);
const char *s;
bool first=TRUE;
int count=0;
int maxLabels=10;
for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
{
if (first)
{
label=s;
first=FALSE;
}
else
{
label+=QCString("\n")+s;
}
}
if (count==maxLabels) label+="\n...";
//printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data());
0,TRUE,distance);
}
}
}
// ---- Add template instantiation relations
if (templateRelations)
{
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(),0,
0,TRUE,distance);
}
}
}
}
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(),0,
0,FALSE,distance);
}
}
}
}
}
void DotClassGraph::determineTruncatedNodes ( QList< DotNode > &  queue,
bool  includeParents 
)
private

Definition at line 2636 of file dot.cpp.

References DotNode::isTruncated(), DotNode::isVisible(), DotNode::m_children, DotNode::m_parents, DotNode::markAsTruncated(), and DotNode::Unknown.

Referenced by DotClassGraph().

{
while (queue.count()>0)
{
DotNode *n = queue.take(0);
{
bool truncated = FALSE;
if (n->m_children)
{
QListIterator<DotNode> li(*n->m_children);
DotNode *dn;
for (li.toFirst();(dn=li.current());++li)
{
if (!dn->isVisible())
truncated = TRUE;
else
queue.append(dn);
}
}
if (n->m_parents && includeParents)
{
QListIterator<DotNode> li(*n->m_parents);
DotNode *dn;
for (li.toFirst();(dn=li.current());++li)
{
if (!dn->isVisible())
truncated = TRUE;
else
queue.append(dn);
}
}
n->markAsTruncated(truncated);
}
}
}
bool DotClassGraph::determineVisibleNodes ( DotNode rootNode,
int  maxNodes,
bool  includeParents 
)
private

Definition at line 2673 of file dot.cpp.

References Config_getBool, Config_getInt, DotNode::distance(), DotNode::isVisible(), DotNode::label(), DotNode::m_children, DotNode::m_parents, and DotNode::markAsVisible().

Referenced by DotClassGraph().

{
QList<DotNode> childQueue;
QList<DotNode> parentQueue;
QArray<int> childTreeWidth;
QArray<int> parentTreeWidth;
childQueue.append(rootNode);
if (includeParents) parentQueue.append(rootNode);
bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop
// despite being marked visible in the child loop
while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0)
{
static int maxDistance = Config_getInt(MAX_DOT_GRAPH_DEPTH);
if (childQueue.count()>0)
{
DotNode *n = childQueue.take(0);
int distance = n->distance();
if (!n->isVisible() && distance<=maxDistance) // not yet processed
{
if (distance>0)
{
int oldSize=(int)childTreeWidth.size();
if (distance>oldSize)
{
childTreeWidth.resize(QMAX(childTreeWidth.size(),(uint)distance));
int i; for (i=oldSize;i<distance;i++) childTreeWidth[i]=0;
}
childTreeWidth[distance-1]+=n->label().length();
}
maxNodes--;
// add direct children
if (n->m_children)
{
QListIterator<DotNode> li(*n->m_children);
DotNode *dn;
for (li.toFirst();(dn=li.current());++li)
{
childQueue.append(dn);
}
}
}
}
if (includeParents && parentQueue.count()>0)
{
DotNode *n = parentQueue.take(0);
if ((!n->isVisible() || firstNode) && n->distance()<=maxDistance) // not yet processed
{
firstNode=FALSE;
int distance = n->distance();
if (distance>0)
{
int oldSize = (int)parentTreeWidth.size();
if (distance>oldSize)
{
parentTreeWidth.resize(QMAX(parentTreeWidth.size(),(uint)distance));
int i; for (i=oldSize;i<distance;i++) parentTreeWidth[i]=0;
}
parentTreeWidth[distance-1]+=n->label().length();
}
maxNodes--;
// add direct parents
if (n->m_parents)
{
QListIterator<DotNode> li(*n->m_parents);
DotNode *dn;
for (li.toFirst();(dn=li.current());++li)
{
parentQueue.append(dn);
}
}
}
}
}
if (Config_getBool(UML_LOOK)) return FALSE; // UML graph are always top to bottom
int maxWidth=0;
int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size());
uint i;
for (i=0;i<childTreeWidth.size();i++)
{
if (childTreeWidth.at(i)>maxWidth) maxWidth=childTreeWidth.at(i);
}
for (i=0;i<parentTreeWidth.size();i++)
{
if (parentTreeWidth.at(i)>maxWidth) maxWidth=parentTreeWidth.at(i);
}
//printf("max tree width=%d, max tree height=%d\n",maxWidth,maxHeight);
return maxWidth>80 && maxHeight<12; // used metric to decide to render the tree
// from left to right instead of top to bottom,
// with the idea to render very wide trees in
// left to right order.
}
bool DotClassGraph::isTooBig ( ) const

Definition at line 2969 of file dot.cpp.

References Config_getInt, DotNode::Inheritance, DotNode::m_children, m_graphType, DotNode::m_parents, and m_startNode.

Referenced by ClassContext::Private::hasInheritanceDiagram(), and ClassDef::writeInheritanceGraph().

{
static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES);
int numNodes = 0;
numNodes+= m_startNode->m_children ? m_startNode->m_children->count() : 0;
{
numNodes+= m_startNode->m_parents ? m_startNode->m_parents->count() : 0;
}
return numNodes>=maxNodes;
}
bool DotClassGraph::isTrivial ( ) const
void DotClassGraph::resetNumbering ( )
static

Definition at line 2905 of file dot.cpp.

References m_curNodeNumber.

Referenced by resetDotNodeNumbering().

{
}
void DotClassGraph::writeDEF ( FTextStream t)

Definition at line 3270 of file dot.cpp.

References m_usedNodes, and DotNode::writeDEF().

Referenced by generateDEFForClass().

{
QDictIterator<DotNode> dni(*m_usedNodes);
DotNode *node;
for (;(node=dni.current());++dni)
{
node->writeDEF(t);
}
}
void DotClassGraph::writeDocbook ( FTextStream t)

Definition at line 3260 of file dot.cpp.

References m_usedNodes, and DotNode::writeDocbook().

{
QDictIterator<DotNode> dni(*m_usedNodes);
DotNode *node;
for (;(node=dni.current());++dni)
{
node->writeDocbook(t,TRUE);
}
}
QCString DotClassGraph::writeGraph ( FTextStream t,
GraphOutputFormat  gf,
EmbeddedOutputFormat  ef,
const char *  path,
const char *  fileName,
const char *  relPath,
bool  TBRank = TRUE,
bool  imageMap = TRUE,
int  graphId = -1 
) const

Definition at line 3075 of file dot.cpp.

References DotManager::addFigure(), IndexList::addImageFile(), DotRunner::addJob(), DotManager::addMap(), DotManager::addRun(), DotManager::addSVGConversion(), DotManager::addSVGObject(), checkDeliverables(), DotNode::Collaboration, Config_getBool, Config_getEnum, endl(), EOF_DocBook, err(), escapeCharsInString(), getDotImageExtension(), GOF_BITMAP, GOF_EPS, Doxygen::indexList, DotNode::Inheritance, insertMapFile(), DotManager::instance(), DotNode::label(), m_collabFileName, m_graphType, m_inheritFileName, DotNode::m_label, m_lrRank, m_startNode, MAP_CMD, removeDotGraph(), updateDotGraph(), writeSVGFigureLink(), and writeVecGfxFigure().

Referenced by ClassContext::Private::collaborationDiagram(), RTFGenerator::endDotGraph(), LatexGenerator::endDotGraph(), HtmlGenerator::endDotGraph(), and ClassContext::Private::inheritanceDiagram().

{
QDir d(path);
// store the original directory
if (!d.exists())
{
err("Output dir %s does not exist!\n",path); exit(1);
}
static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
QCString baseName;
QCString mapName;
switch (m_graphType)
{
mapName="coll_map";
baseName=m_collabFileName;
break;
mapName="inherit_map";
break;
default:
ASSERT(0);
break;
}
// derive target file names from baseName
QCString imgExt = getDotImageExtension();
QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
QCString absBaseName = d.absPath().utf8()+"/"+baseName;
QCString absDotName = absBaseName+".dot";
QCString absMapName = absBaseName+".map";
QCString absPdfName = absBaseName+".pdf";
QCString absEpsName = absBaseName+".eps";
QCString absImgName = absBaseName+"."+imgExt;
bool regenerate = FALSE;
absBaseName,
graphFormat,
TRUE,
) ||
!checkDeliverables(graphFormat==GOF_BITMAP ? absImgName :
usePDFLatex ? absPdfName : absEpsName,
graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString())
)
{
regenerate=TRUE;
if (graphFormat==GOF_BITMAP) // run dot to create a bitmap image
{
DotRunner *dotRun = new DotRunner(absDotName,
d.absPath().data(),TRUE,absImgName);
dotRun->addJob(imgFmt,absImgName);
if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
}
else if (graphFormat==GOF_EPS) // run dot to create a .eps image
{
DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
if (usePDFLatex)
{
dotRun->addJob("pdf",absPdfName);
}
else
{
dotRun->addJob("ps",absEpsName);
}
}
}
Doxygen::indexList->addImageFile(baseName+"."+imgExt);
if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook)
{
out << "<para>" << endl;
out << " <figure>" << endl;
out << " <title>";
switch (m_graphType)
{
out << "Collaboration graph";
break;
out << "Inheritance graph";
break;
default:
ASSERT(0);
break;
}
out << "</title>" << endl;
out << " <mediaobject>" << endl;
out << " <imageobject>" << endl;
out << " <imagedata";
out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName << "." << imgExt << "\">";
out << "</imagedata>" << endl;
out << " </imageobject>" << endl;
out << " </mediaobject>" << endl;
out << " </figure>" << endl;
out << "</para>" << endl;
}
else if (graphFormat==GOF_BITMAP && generateImageMap) // produce HTML to include the image
{
QCString mapLabel = escapeCharsInString(m_startNode->m_label,FALSE)+"_"+
escapeCharsInString(mapName,FALSE);
if (imgExt=="svg") // add link to SVG file without map file
{
out << "<div class=\"center\">";
if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file
{
if (regenerate)
{
DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString(),TRUE,graphId);
}
int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath);
out << "<!-- SVG " << mapId << " -->" << endl;
}
out << "</div>" << endl;
}
else // add link to bitmap file with image map
{
out << "<div class=\"center\">";
out << "<img src=\"" << relPath << baseName << "."
<< imgExt << "\" border=\"0\" usemap=\"#"
<< mapLabel << "\" alt=\"";
switch (m_graphType)
{
out << "Collaboration graph";
break;
out << "Inheritance graph";
break;
default:
ASSERT(0);
break;
}
out << "\"/>";
out << "</div>" << endl;
if (regenerate || !insertMapFile(out,absMapName,relPath,mapLabel))
{
int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath,
FALSE,QCString(),mapLabel);
out << "<!-- MAP " << mapId << " -->" << endl;
}
}
}
else if (graphFormat==GOF_EPS) // produce tex to include the .eps image
{
if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
{
int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE /*TRUE*/);
out << endl << "% FIG " << figId << endl;
}
}
if (!regenerate) removeDotGraph(absDotName);
return baseName;
}
void DotClassGraph::writeXML ( FTextStream t)

Definition at line 3250 of file dot.cpp.

References m_usedNodes, and DotNode::writeXML().

Referenced by generateXMLForClass().

{
QDictIterator<DotNode> dni(*m_usedNodes);
DotNode *node;
for (;(node=dni.current());++dni)
{
node->writeXML(t,TRUE);
}
}

Member Data Documentation

QCString DotClassGraph::m_collabFileName
private

Definition at line 197 of file dot.h.

Referenced by DotClassGraph(), and writeGraph().

int DotClassGraph::m_curNodeNumber = 0
staticprivate

Definition at line 195 of file dot.h.

Referenced by addClass(), DotClassGraph(), and resetNumbering().

DotNode::GraphType DotClassGraph::m_graphType
private

Definition at line 196 of file dot.h.

Referenced by buildGraph(), DotClassGraph(), isTooBig(), isTrivial(), and writeGraph().

QCString DotClassGraph::m_inheritFileName
private

Definition at line 198 of file dot.h.

Referenced by DotClassGraph(), and writeGraph().

bool DotClassGraph::m_lrRank
private

Definition at line 199 of file dot.h.

Referenced by DotClassGraph(), and writeGraph().

DotNode* DotClassGraph::m_startNode
private

Definition at line 193 of file dot.h.

Referenced by DotClassGraph(), isTooBig(), isTrivial(), writeGraph(), and ~DotClassGraph().

QDict<DotNode>* DotClassGraph::m_usedNodes
private

Definition at line 194 of file dot.h.

Referenced by addClass(), DotClassGraph(), writeDEF(), writeDocbook(), writeXML(), and ~DotClassGraph().


The documentation for this class was generated from the following files: