summaryrefslogtreecommitdiffstats
path: root/src/dot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dot.cpp')
-rw-r--r--src/dot.cpp406
1 files changed, 248 insertions, 158 deletions
diff --git a/src/dot.cpp b/src/dot.cpp
index 79c1320..1b506b1 100644
--- a/src/dot.cpp
+++ b/src/dot.cpp
@@ -31,6 +31,7 @@
#include <qdir.h>
#include <qfile.h>
#include <qtextstream.h>
+#include <md5.h>
//--------------------------------------------------------------------
@@ -1382,7 +1383,86 @@ void writeDotGraph(DotNode *root,
}
}
-static void findMaximalDotGraph(DotNode *root,
+/*! 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
+ )
+{
+ //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);
+ 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
+ );
+ }
+ pn->write(md5stream,gt,format,TRUE,FALSE,distance,backArrows);
+ }
+ }
+ char md5_sig[16];
+ QCString sigStr(33);
+ md5_buffer(buf.ascii(),buf.length(),md5_sig);
+ md5_sig_to_string(md5_sig,sigStr.data(),33);
+ //printf("md5: %s | file: %s\n",sigStr,baseName.data());
+ return sigStr;
+}
+
+/*! 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;
+}
+
+static bool findMaximalDotGraph(DotNode *root,
int maxDist,
const QCString &baseName,
QDir &thisDir,
@@ -1402,6 +1482,10 @@ static void findMaximalDotGraph(DotNode *root,
int maxDotGraphHeight = Config_getInt("MAX_DOT_GRAPH_HEIGHT");
int lastFit=minDistance;
+ QCString md5 = computeMd5Signature(root,gt,format,lrRank,
+ renderParents,maxDistance,backArrows);
+ if (!checkAndUpdateMd5Signature(baseName,md5)) return FALSE;
+
// 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)
@@ -1417,7 +1501,7 @@ static void findMaximalDotGraph(DotNode *root,
if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
{
err("Problems running dot. Check your installation!\n");
- return;
+ return FALSE;
}
// extract bounding box from the result
@@ -1461,6 +1545,7 @@ static void findMaximalDotGraph(DotNode *root,
lastFit,
backArrows
);
+ return TRUE;
}
QCString DotClassGraph::diskName() const
@@ -1520,105 +1605,108 @@ QCString DotClassGraph::writeGraph(QTextStream &out,
}
baseName = convertNameToFile(diskName());
- findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),baseName,
- thisDir,m_graphType,format,!isTBRank,m_graphType==DotNode::Inheritance);
- if (format==BITMAP) // run dot to create a bitmap image
+ if (findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),baseName,
+ thisDir,m_graphType,format,!isTBRank,m_graphType==DotNode::Inheritance))
{
- QCString dotArgs(maxCmdLine);
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- QCString imgName = baseName+"."+imgExt;
- dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
- imgExt.data(),baseName.data(),imgName.data());
- if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
- {
- err("Error: Problems running dot. Check your installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- checkDotResult(imgName);
- if (generateImageMap)
+
+ if (format==BITMAP) // run dot to create a bitmap image
{
- // run dot again to create an image map
- dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",baseName.data(),baseName.data());
+ QCString dotArgs(maxCmdLine);
+ QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString imgName = baseName+"."+imgExt;
+ dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
+ imgExt.data(),baseName.data(),imgName.data());
if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
{
err("Error: Problems running dot. Check your installation!\n");
QDir::setCurrent(oldDir);
return baseName;
}
- QCString mapLabel = convertNameToFile(m_startNode->m_label+"_"+mapName);
- out << "<p><center><img src=\"" << baseName << "."
+ checkDotResult(imgName);
+ if (generateImageMap)
+ {
+ // run dot again to create an image map
+ dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",baseName.data(),baseName.data());
+ if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
+ {
+ err("Error: Problems running dot. Check your installation!\n");
+ QDir::setCurrent(oldDir);
+ return baseName;
+ }
+ QCString mapLabel = convertNameToFile(m_startNode->m_label+"_"+mapName);
+ out << "<p><center><img src=\"" << baseName << "."
<< imgExt << "\" border=\"0\" usemap=\"#"
<< mapLabel << "\" alt=\"";
- switch (m_graphType)
+ switch (m_graphType)
+ {
+ case DotNode::Collaboration:
+ out << "Collaboration graph";
+ break;
+ //case Interface:
+ // out << "Interface dependency 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");
+ 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
+ {
+ QCString dotArgs(maxCmdLine);
+ dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",baseName.data(),baseName.data());
+ if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
{
- case DotNode::Collaboration:
- out << "Collaboration graph";
- break;
- //case Interface:
- // out << "Interface dependency graph";
- // break;
- case DotNode::Inheritance:
- out << "Inheritance graph";
- break;
- default:
- ASSERT(0);
- break;
+ err("Error: Problems running dot. Check your installation!\n");
+ QDir::setCurrent(oldDir);
+ return baseName;
}
- out << "\"></center>" << endl;
- QString tmpstr;
- QTextOStream tmpout(&tmpstr);
- convertMapFile(tmpout,baseName+".map");
- if (!tmpstr.isEmpty())
+ int width,height;
+ if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
{
- out << "<map name=\"" << mapLabel << "\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
+ err("Error: Could not extract bounding box from .eps!\n");
+ QDir::setCurrent(oldDir);
+ return baseName;
}
- thisDir.remove(baseName+".map");
- }
- }
- else if (format==EPS) // run dot to create a .eps image
- {
- QCString dotArgs(maxCmdLine);
- dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",baseName.data(),baseName.data());
- if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
- {
- err("Error: Problems running dot. Check your 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;
- }
- 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)
+ if (Config_getBool("USE_PDFLATEX"))
{
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
+ 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 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";
}
- 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");
}
- if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
QDir::setCurrent(oldDir);
return baseName;
@@ -1763,101 +1851,103 @@ QCString DotInclDepGraph::writeGraph(QTextStream &out,
QCString mapName=m_startNode->m_label.copy();
if (m_inverse) mapName+="dep";
- findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),
+ if (findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),
baseName,thisDir,DotNode::Dependency,format,
- FALSE,FALSE,!m_inverse);
-
- if (format==BITMAP)
+ FALSE,FALSE,!m_inverse)
+ )
{
- // run dot to create a bitmap image
- QCString dotArgs(maxCmdLine);
- QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
- QCString imgName=baseName+"."+imgExt;
- dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
- imgExt.data(),baseName.data(),imgName.data());
- if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
- {
- err("Problems running dot. Check your installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
- }
- checkDotResult(imgName);
-
- if (generateImageMap)
+ if (format==BITMAP)
{
- // run dot again to create an image map
- dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",
- baseName.data(),baseName.data());
+ // run dot to create a bitmap image
+ QCString dotArgs(maxCmdLine);
+ QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ QCString imgName=baseName+"."+imgExt;
+ dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
+ imgExt.data(),baseName.data(),imgName.data());
if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
{
err("Problems running dot. Check your installation!\n");
QDir::setCurrent(oldDir);
return baseName;
}
+ checkDotResult(imgName);
- out << "<p><center><img src=\"" << baseName << "."
+ if (generateImageMap)
+ {
+ // run dot again to create an image map
+ dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",
+ baseName.data(),baseName.data());
+ if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
+ {
+ err("Problems running dot. Check your installation!\n");
+ QDir::setCurrent(oldDir);
+ return baseName;
+ }
+
+ out << "<p><center><img src=\"" << baseName << "."
<< imgExt << "\" border=\"0\" usemap=\"#"
<< mapName << "_map\" alt=\"";
- if (m_inverse) out << "Included by dependency graph"; else out << "Include dependency graph";
- out << "\">";
- out << "</center>" << endl;
- QString tmpstr;
- QTextOStream tmpout(&tmpstr);
- convertMapFile(tmpout,baseName+".map");
- if (!tmpstr.isEmpty())
- {
- out << "<map name=\"" << mapName << "_map\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
+ if (m_inverse) out << "Included by dependency graph"; else out << "Include dependency graph";
+ out << "\">";
+ out << "</center>" << endl;
+ QString tmpstr;
+ QTextOStream tmpout(&tmpstr);
+ convertMapFile(tmpout,baseName+".map");
+ if (!tmpstr.isEmpty())
+ {
+ out << "<map name=\"" << mapName << "_map\">" << endl;
+ out << tmpstr;
+ out << "</map>" << endl;
+ }
+ thisDir.remove(baseName+".map");
}
- thisDir.remove(baseName+".map");
}
- }
- else if (format==EPS)
- {
- // run dot to create a .eps image
- QCString dotArgs(maxCmdLine);
- dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",
- baseName.data(),baseName.data());
- if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
+ else if (format==EPS)
{
- err("Problems running dot. Check your 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;
- }
- 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)
+ // run dot to create a .eps image
+ QCString dotArgs(maxCmdLine);
+ dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",
+ baseName.data(),baseName.data());
+ if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
{
- err("Error: Problems running epstopdf. Check your TeX installation!\n");
- QDir::setCurrent(oldDir);
- return baseName;
+ err("Problems running dot. Check your 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;
+ }
+ 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 maxWidth = 420; /* approx. page width in points */
+
+ out << "\\begin{figure}[H]\n"
+ "\\begin{center}\n"
+ "\\leavevmode\n"
+ //"\\setlength{\\epsfxsize}{" << QMIN(width/2,maxWidth) << "pt}\n"
+ //"\\epsfbox{" << baseName << ".eps}\n"
+ "\\includegraphics[width=" << QMIN(width/2,maxWidth)
+ << "pt]{" << baseName << "}\n"
+ "\\end{center}\n"
+ "\\end{figure}\n";
}
- int maxWidth = 420; /* approx. page width in points */
-
- out << "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n"
- //"\\setlength{\\epsfxsize}{" << QMIN(width/2,maxWidth) << "pt}\n"
- //"\\epsfbox{" << baseName << ".eps}\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");
+ if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
+ }
QDir::setCurrent(oldDir);
return baseName;