Skip to content

Commit fe818bf

Browse files
author
Dimitri van Heesch
committed
Added graphical hierarchy support to template engine
1 parent 3ebc431 commit fe818bf

File tree

12 files changed

+557
-394
lines changed

12 files changed

+557
-394
lines changed

src/context.cpp

Lines changed: 302 additions & 271 deletions
Large diffs are not rendered by default.

src/context.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ struct MemberInfo;
5151
class MemberGroup;
5252
class MemberGroupSDict;
5353
class MemberGroupList;
54+
class DotNode;
55+
class DotGfxHierarchyTable;
5456

5557
//----------------------------------------------------
5658

@@ -419,6 +421,26 @@ class ClassIndexContext : public RefCountedContext, public TemplateStructIntf
419421

420422
//----------------------------------------------------
421423

424+
class InheritanceGraphContext : public RefCountedContext, public TemplateStructIntf
425+
{
426+
public:
427+
static InheritanceGraphContext *alloc(DotGfxHierarchyTable *hierarchy,DotNode *n,int id)
428+
{ return new InheritanceGraphContext(hierarchy,n,id); }
429+
430+
// TemplateStructIntf methods
431+
virtual TemplateVariant get(const char *name) const;
432+
virtual int addRef() { return RefCountedContext::addRef(); }
433+
virtual int release() { return RefCountedContext::release(); }
434+
435+
private:
436+
InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id);
437+
~InheritanceGraphContext();
438+
class Private;
439+
Private *p;
440+
};
441+
442+
//----------------------------------------------------
443+
422444
class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStructIntf
423445
{
424446
public:
@@ -485,8 +507,8 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf
485507
{
486508
public:
487509
static NestingNodeContext *alloc(const NestingNodeContext *parent,Definition *def,
488-
int index,int level,bool addClasses)
489-
{ return new NestingNodeContext(parent,def,index,level,addClasses); }
510+
int index,int level,bool addClasses,bool inherit,bool hideSuper)
511+
{ return new NestingNodeContext(parent,def,index,level,addClasses,inherit,hideSuper); }
490512

491513
QCString id() const;
492514

@@ -497,7 +519,7 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf
497519

498520
private:
499521
NestingNodeContext(const NestingNodeContext *parent,
500-
Definition *,int index,int level,bool addClasses);
522+
Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper);
501523
~NestingNodeContext();
502524
class Private;
503525
Private *p;
@@ -527,6 +549,8 @@ class NestingContext : public RefCountedContext, public TemplateListIntf
527549
void addPages(const PageSDict &pages,bool rootOnly);
528550
void addModules(const GroupSDict &modules);
529551
void addModules(const GroupList &modules);
552+
void addClassHierarchy(const ClassSDict &clDict,bool rootOnly);
553+
void addDerivedClasses(const BaseClassList *bcl,bool hideSuper);
530554

531555
private:
532556
NestingContext(const NestingNodeContext *parent,int level);

src/dot.cpp

Lines changed: 108 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -772,18 +772,18 @@ static bool checkDeliverables(const QCString &file1,
772772

773773
//--------------------------------------------------------------------
774774

775-
/** Class representing a list of DotNode objects. */
776-
class DotNodeList : public QList<DotNode>
775+
inline int DotNode::findParent( DotNode *n )
777776
{
778-
public:
779-
DotNodeList() : QList<DotNode>() {}
780-
~DotNodeList() {}
781-
private:
782-
int compareValues(const DotNode *n1,const DotNode *n2) const
783-
{
784-
return qstricmp(n1->m_label,n2->m_label);
785-
}
786-
};
777+
if ( !m_parents ) return -1;
778+
return m_parents->find(n);
779+
}
780+
781+
//--------------------------------------------------------------------
782+
783+
int DotNodeList::compareValues(const DotNode *n1,const DotNode *n2) const
784+
{
785+
return qstricmp(n1->m_label,n2->m_label);
786+
}
787787

788788
//--------------------------------------------------------------------
789789

@@ -1908,7 +1908,7 @@ void DotNode::write(FTextStream &t,
19081908
bool reNumber
19091909
)
19101910
{
1911-
//printf("DotNode::write(%d) name=%s this=%p written=%d\n",distance,m_label.data(),this,m_written);
1911+
//printf("DotNode::write(%d) name=%s this=%p written=%d visible=%d\n",m_distance,m_label.data(),this,m_written,m_visible);
19121912
if (m_written) return; // node already written to the output
19131913
if (!m_visible) return; // node is not visible
19141914
writeBox(t,gt,format,m_truncated==Truncated,reNumber);
@@ -2261,12 +2261,106 @@ const DotNode *DotNode::findDocNode() const
22612261

22622262
int DotGfxHierarchyTable::m_curNodeNumber;
22632263

2264+
void DotGfxHierarchyTable::createGraph(DotNode *n,FTextStream &out,
2265+
const char *path,const char *fileName,int id) const
2266+
{
2267+
QDir d(path);
2268+
QCString baseName;
2269+
QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
2270+
baseName.sprintf("inherit_graph_%d",id);
2271+
QCString imgName = baseName+"."+ imgExt;
2272+
QCString mapName = baseName+".map";
2273+
QCString absImgName = QCString(d.absPath().data())+"/"+imgName;
2274+
QCString absMapName = QCString(d.absPath().data())+"/"+mapName;
2275+
QCString absBaseName = QCString(d.absPath().data())+"/"+baseName;
2276+
QListIterator<DotNode> dnli2(*m_rootNodes);
2277+
DotNode *node;
2278+
2279+
// compute md5 checksum of the graph were are about to generate
2280+
QGString theGraph;
2281+
FTextStream md5stream(&theGraph);
2282+
writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy());
2283+
md5stream << " rankdir=\"LR\";" << endl;
2284+
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
2285+
{
2286+
if (node->m_subgraphId==n->m_subgraphId)
2287+
{
2288+
node->clearWriteFlag();
2289+
}
2290+
}
2291+
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
2292+
{
2293+
if (node->m_subgraphId==n->m_subgraphId)
2294+
{
2295+
node->write(md5stream,DotNode::Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE,TRUE);
2296+
}
2297+
}
2298+
writeGraphFooter(md5stream);
2299+
resetReNumbering();
2300+
uchar md5_sig[16];
2301+
QCString sigStr(33);
2302+
MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
2303+
MD5SigToString(md5_sig,sigStr.data(),33);
2304+
bool regenerate=FALSE;
2305+
if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
2306+
!checkDeliverables(absImgName,absMapName))
2307+
{
2308+
regenerate=TRUE;
2309+
// image was new or has changed
2310+
QCString dotName=absBaseName+".dot";
2311+
QFile f(dotName);
2312+
if (!f.open(IO_WriteOnly)) return;
2313+
FTextStream t(&f);
2314+
t << theGraph;
2315+
f.close();
2316+
resetReNumbering();
2317+
2318+
DotRunner *dotRun = new DotRunner(dotName,d.absPath().data(),TRUE,absImgName);
2319+
dotRun->addJob(imgExt,absImgName);
2320+
dotRun->addJob(MAP_CMD,absMapName);
2321+
DotManager::instance()->addRun(dotRun);
2322+
}
2323+
else
2324+
{
2325+
removeDotGraph(absBaseName+".dot");
2326+
}
2327+
Doxygen::indexList->addImageFile(imgName);
2328+
// write image and map in a table row
2329+
QCString mapLabel = escapeCharsInString(n->m_label,FALSE);
2330+
if (imgExt=="svg") // vector graphics
2331+
{
2332+
if (regenerate || !writeSVGFigureLink(out,QCString(),baseName,absImgName))
2333+
{
2334+
if (regenerate)
2335+
{
2336+
DotManager::instance()->addSVGConversion(absImgName,QCString(),
2337+
FALSE,QCString(),FALSE,0);
2338+
}
2339+
int mapId = DotManager::instance()->addSVGObject(fileName,baseName,
2340+
absImgName,QCString());
2341+
out << "<!-- SVG " << mapId << " -->" << endl;
2342+
}
2343+
}
2344+
else // normal bitmap
2345+
{
2346+
out << "<img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#"
2347+
<< mapLabel << "\"/>" << endl;
2348+
2349+
if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel))
2350+
{
2351+
int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(),
2352+
FALSE,QCString(),mapLabel);
2353+
out << "<!-- MAP " << mapId << " -->" << endl;
2354+
}
2355+
}
2356+
}
2357+
22642358
void DotGfxHierarchyTable::writeGraph(FTextStream &out,
22652359
const char *path,const char *fileName) const
22662360
{
22672361
//printf("DotGfxHierarchyTable::writeGraph(%s)\n",name);
22682362
//printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count());
2269-
2363+
22702364
if (m_rootSubgraphs->count()==0) return;
22712365

22722366
QDir d(path);
@@ -2284,97 +2378,8 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out,
22842378
int count=0;
22852379
for (dnli.toFirst();(n=dnli.current());++dnli)
22862380
{
2287-
QCString baseName;
2288-
QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
2289-
baseName.sprintf("inherit_graph_%d",count++);
2290-
//baseName = convertNameToFile(baseName);
2291-
QCString imgName = baseName+"."+ imgExt;
2292-
QCString mapName = baseName+".map";
2293-
QCString absImgName = QCString(d.absPath().data())+"/"+imgName;
2294-
QCString absMapName = QCString(d.absPath().data())+"/"+mapName;
2295-
QCString absBaseName = QCString(d.absPath().data())+"/"+baseName;
2296-
QListIterator<DotNode> dnli2(*m_rootNodes);
2297-
DotNode *node;
2298-
2299-
// compute md5 checksum of the graph were are about to generate
2300-
QGString theGraph;
2301-
FTextStream md5stream(&theGraph);
2302-
writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy());
2303-
md5stream << " rankdir=\"LR\";" << endl;
2304-
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
2305-
{
2306-
if (node->m_subgraphId==n->m_subgraphId)
2307-
{
2308-
node->clearWriteFlag();
2309-
}
2310-
}
2311-
for (dnli2.toFirst();(node=dnli2.current());++dnli2)
2312-
{
2313-
if (node->m_subgraphId==n->m_subgraphId)
2314-
{
2315-
node->write(md5stream,DotNode::Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE,TRUE);
2316-
}
2317-
}
2318-
writeGraphFooter(md5stream);
2319-
resetReNumbering();
2320-
uchar md5_sig[16];
2321-
QCString sigStr(33);
2322-
MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
2323-
MD5SigToString(md5_sig,sigStr.data(),33);
2324-
bool regenerate=FALSE;
2325-
if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
2326-
!checkDeliverables(absImgName,absMapName))
2327-
{
2328-
regenerate=TRUE;
2329-
// image was new or has changed
2330-
QCString dotName=absBaseName+".dot";
2331-
QFile f(dotName);
2332-
if (!f.open(IO_WriteOnly)) return;
2333-
FTextStream t(&f);
2334-
t << theGraph;
2335-
f.close();
2336-
resetReNumbering();
2337-
2338-
DotRunner *dotRun = new DotRunner(dotName,d.absPath().data(),TRUE,absImgName);
2339-
dotRun->addJob(imgExt,absImgName);
2340-
dotRun->addJob(MAP_CMD,absMapName);
2341-
DotManager::instance()->addRun(dotRun);
2342-
}
2343-
else
2344-
{
2345-
removeDotGraph(absBaseName+".dot");
2346-
}
2347-
Doxygen::indexList->addImageFile(imgName);
2348-
// write image and map in a table row
2349-
QCString mapLabel = escapeCharsInString(n->m_label,FALSE);
23502381
out << "<tr><td>";
2351-
if (imgExt=="svg") // vector graphics
2352-
{
2353-
if (regenerate || !writeSVGFigureLink(out,QCString(),baseName,absImgName))
2354-
{
2355-
if (regenerate)
2356-
{
2357-
DotManager::instance()->addSVGConversion(absImgName,QCString(),
2358-
FALSE,QCString(),FALSE,0);
2359-
}
2360-
int mapId = DotManager::instance()->addSVGObject(fileName,baseName,
2361-
absImgName,QCString());
2362-
out << "<!-- SVG " << mapId << " -->" << endl;
2363-
}
2364-
}
2365-
else // normal bitmap
2366-
{
2367-
out << "<img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#"
2368-
<< mapLabel << "\"/>" << endl;
2369-
2370-
if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel))
2371-
{
2372-
int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(),
2373-
FALSE,QCString(),mapLabel);
2374-
out << "<!-- MAP " << mapId << " -->" << endl;
2375-
}
2376-
}
2377-
2382+
createGraph(n,out,path,fileName,count++);
23782383
out << "</td></tr>" << endl;
23792384
}
23802385
out << "</table>" << endl;

src/dot.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class DotNode
122122
friend class DotNodeList;
123123
friend class DotCallGraph;
124124
friend class DotGroupCollaboration;
125+
friend class DotInheritanceGraph;
125126

126127
friend QCString computeMd5Signature(
127128
DotNode *root, GraphType gt,
@@ -133,12 +134,15 @@ class DotNode
133134
);
134135
};
135136

136-
inline int DotNode::findParent( DotNode *n )
137+
/** Class representing a list of DotNode objects. */
138+
class DotNodeList : public QList<DotNode>
137139
{
138-
if( !m_parents )
139-
return -1;
140-
return m_parents->find(n);
141-
}
140+
public:
141+
DotNodeList() : QList<DotNode>() {}
142+
~DotNodeList() {}
143+
private:
144+
int compareValues(const DotNode *n1,const DotNode *n2) const;
145+
};
142146

143147
/** Represents a graphical class hierarchy */
144148
class DotGfxHierarchyTable
@@ -147,6 +151,8 @@ class DotGfxHierarchyTable
147151
DotGfxHierarchyTable();
148152
~DotGfxHierarchyTable();
149153
void writeGraph(FTextStream &t,const char *path, const char *fileName) const;
154+
void createGraph(DotNode *rootNode,FTextStream &t,const char *path,const char *fileName,int id) const;
155+
const DotNodeList *subGraphs() const { return m_rootSubgraphs; }
150156

151157
private:
152158
void addHierarchy(DotNode *n,ClassDef *cd,bool hide);

0 commit comments

Comments
 (0)