26 #include <qwaitcondition.h>
51 #define MAP_CMD "cmapx"
54 #define FONTNAME getDotFontName()
55 #define FONTSIZE getDotFontSize()
60 "<svg id=\"main\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" onload=\"init(evt)\">\n"
61 "<style type=\"text/css\"><![CDATA[\n"
62 ".edge:hover path { stroke: red; }\n"
63 ".edge:hover polygon { stroke: red; fill: red; }\n"
65 "<script type=\"text/javascript\"><![CDATA[\n"
66 "var edges = document.getElementsByTagName('g');\n"
67 "if (edges && edges.length) {\n"
68 " for (var i=0;i<edges.length;i++) {\n"
69 " if (edges[i].id.substr(0,4)=='edge') {\n"
70 " edges[i].setAttribute('class','edge');\n"
76 " <circle id=\"rim\" cx=\"0\" cy=\"0\" r=\"7\"/>\n"
77 " <circle id=\"rim2\" cx=\"0\" cy=\"0\" r=\"3.5\"/>\n"
78 " <g id=\"zoomPlus\">\n"
79 " <use xlink:href=\"#rim\" fill=\"#404040\">\n"
80 " <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomplus.mouseover\" end=\"zoomplus.mouseout\"/>\n"
82 " <path d=\"M-4,0h8M0,-4v8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n"
84 " <g id=\"zoomMin\">\n"
85 " <use xlink:href=\"#rim\" fill=\"#404040\">\n"
86 " <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomminus.mouseover\" end=\"zoomminus.mouseout\"/>\n"
88 " <path d=\"M-4,0h8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n"
90 " <g id=\"dirArrow\">\n"
91 " <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
93 " <g id=\"resetDef\">\n"
94 " <use xlink:href=\"#rim2\" fill=\"#404040\">\n"
95 " <set attributeName=\"fill\" to=\"#808080\" begin=\"reset.mouseover\" end=\"reset.mouseout\"/>\n"
100 "<script type=\"text/javascript\">\n"
105 " <g id=\"navigator\" transform=\"translate(0 0)\" fill=\"#404254\">\n"
106 " <rect fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\".5\" x=\"0\" y=\"0\" width=\"60\" height=\"60\"/>\n"
108 " <use id=\"zoomplus\" xlink:href=\"#zoomPlus\" x=\"17\" y=\"9\" onmousedown=\"handleZoom(evt,'in')\"/>\n"
110 " <use id=\"zoomminus\" xlink:href=\"#zoomMin\" x=\"42\" y=\"9\" onmousedown=\"handleZoom(evt,'out')\"/>\n"
112 " <use id=\"reset\" xlink:href=\"#resetDef\" x=\"30\" y=\"36\" onmousedown=\"handleReset()\"/>\n"
114 " <g id=\"arrowUp\" xlink:href=\"#dirArrow\" transform=\"translate(30 24)\" onmousedown=\"handlePan(0,-1)\">\n"
115 " <use xlink:href=\"#rim\" fill=\"#404040\">\n"
116 " <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowUp.mouseover\" end=\"arrowUp.mouseout\"/>\n"
118 " <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
121 " <g id=\"arrowRight\" xlink:href=\"#dirArrow\" transform=\"rotate(90) translate(36 -43)\" onmousedown=\"handlePan(1,0)\">\n"
122 " <use xlink:href=\"#rim\" fill=\"#404040\">\n"
123 " <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowRight.mouseover\" end=\"arrowRight.mouseout\"/>\n"
125 " <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
128 " <g id=\"arrowDown\" xlink:href=\"#dirArrow\" transform=\"rotate(180) translate(-30 -48)\" onmousedown=\"handlePan(0,1)\">\n"
129 " <use xlink:href=\"#rim\" fill=\"#404040\">\n"
130 " <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowDown.mouseover\" end=\"arrowDown.mouseout\"/>\n"
132 " <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
135 " <g id=\"arrowLeft\" xlink:href=\"#dirArrow\" transform=\"rotate(270) translate(-36 17)\" onmousedown=\"handlePan(-1,0)\">\n"
136 " <use xlink:href=\"#rim\" fill=\"#404040\">\n"
137 " <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowLeft.mouseover\" end=\"arrowLeft.mouseout\"/>\n"
139 " <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
143 " <svg viewBox=\"0 0 15 15\" width=\"100%\" height=\"30px\" preserveAspectRatio=\"xMaxYMin meet\">\n"
144 " <g id=\"arrow_out\" transform=\"scale(0.3 0.3)\">\n"
145 " <a xlink:href=\"$orgname\" target=\"_base\">\n"
146 " <rect id=\"button\" ry=\"5\" rx=\"5\" y=\"6\" x=\"6\" height=\"38\" width=\"38\"\n"
147 " fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\"1.0\"/>\n"
148 " <path id=\"arrow\"\n"
149 " d=\"M 11.500037,31.436501 C 11.940474,20.09759 22.043105,11.32322 32.158766,21.979434 L 37.068811,17.246167 C 37.068811,17.246167 37.088388,32 37.088388,32 L 22.160133,31.978069 C 22.160133,31.978069 26.997745,27.140456 26.997745,27.140456 C 18.528582,18.264221 13.291696,25.230495 11.500037,31.436501 z\"\n"
150 " style=\"fill:#404040;\"/>\n"
236 if (dotFontName.isEmpty())
239 dotFontName=
"Helvetica";
247 if (dotFontSize<4) dotFontSize=4;
257 t <<
"\"Dot Graph\"";
267 t <<
" // INTERACTIVE_SVG=YES\n";
271 t <<
" bgcolor=\"transparent\";" <<
endl;
273 t <<
" edge [fontname=\"" <<
FONTNAME <<
"\","
275 "labelfontname=\"" <<
FONTNAME <<
"\","
276 "labelfontsize=\"" <<
FONTSIZE <<
"\"];\n";
277 t <<
" node [fontname=\"" <<
FONTNAME <<
"\","
278 "fontsize=\"" << FONTSIZE <<
"\",shape=record];\n";
286 static QCString
replaceRef(
const QCString &buf,
const QCString relPath,
287 bool urlOnly,
const QCString &context,
const QCString &target=QCString())
290 QCString href =
"href";
293 int indexS = buf.find(
"href=\""), indexE;
294 if (indexS>5 && buf.find(
"xlink:href=\"")!=-1)
298 href.prepend(
"xlink:");
301 if (indexS>=0 && (indexE=buf.find(
'"',indexS+len))!=-1)
303 QCString link = buf.mid(indexS+len,indexE-indexS-len);
307 if (link.left(5)==
"\\ref " || link.left(5)==
"@ref ")
313 if (!df->
file().isEmpty())
315 if (!df->
anchor().isEmpty())
316 result +=
"#" + df->
anchor();
322 result = href+
"=\"" + link +
"\"";
327 int marker = link.find(
'$');
330 QCString ref = link.left(marker);
331 QCString url = link.mid(marker+1);
342 result = href+
"=\"" + link +
"\"";
345 if (!target.isEmpty())
347 result+=
" target=\""+target+
"\"";
349 QCString leftPart = buf.left(indexS);
350 QCString rightPart = buf.mid(indexE+1);
351 return leftPart + result + rightPart;
371 const QCString relPath,
bool urlOnly=FALSE,
372 const QCString &context=QCString())
375 if (!f.open(IO_ReadOnly))
377 err(
"problems opening map file %s for inclusion in the docs!\n"
378 "If you installed Graphviz/dot after a previous failing run, \n"
379 "try deleting the output directory and rerun doxygen.\n",mapName);
382 const int maxLineLen=10240;
385 QCString buf(maxLineLen);
386 int numBytes = f.readLine(buf.rawData(),maxLineLen);
389 buf.resize(numBytes+1);
391 if (buf.left(5)==
"<area")
404 ASSERT(g_dotFontPath.isEmpty());
407 QCString spath = path;
408 if (!newFontPath.isEmpty() && !spath.isEmpty())
412 else if (newFontPath.isEmpty() && !spath.isEmpty())
426 if (g_dotFontPath.isEmpty())
439 QCString bb = isEps ? QCString(
"%%PageBoundingBox:") : QCString(
"/MediaBox [");
441 if (!f.open(IO_ReadOnly|IO_Raw))
446 const int maxLineLen=1024;
447 char buf[maxLineLen];
450 int numBytes = f.readLine(buf,maxLineLen-1);
454 const char *p = strstr(buf,bb);
458 if (sscanf(p+bb.length(),
"%d %d %d %d",&x,&y,width,height)!=4)
472 err(
"Failed to extract bounding box from generated diagram file %s\n",fileName);
477 const QCString &figureName)
479 int width=400,height=550;
500 out <<
"\\nopagebreak\n"
501 "\\begin{figure}[H]\n"
504 if (width>maxWidth || height>maxHeight)
507 if (width*maxHeight>height*maxWidth)
509 out <<
"\\includegraphics[width=" << maxWidth <<
"pt]";
513 out <<
"\\includegraphics[height=" << maxHeight <<
"pt]";
518 out <<
"\\includegraphics[width=" << width <<
"pt]";
521 out <<
"{" << baseName <<
"}\n"
530 static bool readSVGSize(
const QCString &fileName,
int *width,
int *height)
534 if (!f.open(IO_ReadOnly))
538 const int maxLineLen=4096;
539 char buf[maxLineLen];
540 while (!f.atEnd() && !found)
542 int numBytes = f.readLine(buf,maxLineLen-1);
546 if (qstrncmp(buf,
"<!--zoomable ",13)==0)
550 sscanf(buf,
"<!--zoomable %d",height);
554 else if (sscanf(buf,
"<svg width=\"%dpt\" height=\"%dpt\"",width,height)==2)
571 out <<
"<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
577 const QCString &baseName,
const QCString &absImgName)
579 int width=600,height=600;
590 if (height>600) height=600;
591 out <<
"<div class=\"zoom\">";
594 out <<
"<iframe scrolling=\"no\" frameborder=\"0\" src=\""
595 << relPath << baseName <<
".svg\" width=\"100%\" height=\"" << height <<
"\">";
601 out <<
"<iframe scrolling=\"no\" frameborder=\"0\" src=\""
602 << relPath << baseName <<
".svg\" width=\""
603 << ((width*96+48)/72) <<
"\" height=\""
604 << ((height*96+48)/72) <<
"\">";
622 if (qstrcmp(imgExt,
"png")==0)
628 if (fread(data,1,4,f)==4)
630 if (!(data[1]==
'P' && data[2]==
'N' && data[3]==
'G'))
632 err(
"Image `%s' produced by dot is not a valid PNG!\n"
633 "You should either select a different format "
634 "(DOT_IMAGE_FORMAT in the config file) or install a more "
635 "recent version of graphviz (1.7+)\n",imgName
641 err(
"Could not read image `%s' generated by dot!\n",imgName);
647 err(
"Could not open image `%s' generated by dot!\n",imgName);
653 const QCString &relPath,
const QCString &mapLabel)
655 QFileInfo fi(mapFile);
656 if (fi.exists() && fi.size()>0)
661 if (!tmpstr.isEmpty())
663 out <<
"<map name=\"" << mapLabel <<
"\" id=\"" << mapLabel <<
"\">" <<
endl;
665 out <<
"</map>" <<
endl;
692 QFile f(baseName+
".md5");
693 if (f.open(IO_ReadOnly))
696 QCString md5stored(33);
697 int bytesRead=f.readBlock(md5stored.rawData(),32);
700 if (bytesRead==32 && md5==md5stored)
708 if (f.open(IO_WriteOnly))
710 f.writeBlock(md5.data(),32);
717 const QCString &file2=QCString())
721 if (!file1.isEmpty())
724 file1Ok = (fi.exists() && fi.size()>0);
726 if (!file2.isEmpty())
729 file2Ok = (fi.exists() && fi.size()>0);
731 return file1Ok && file2Ok;
752 bool checkResult,
const QCString &imageName)
754 m_file(file), m_path(path),
755 m_checkResult(checkResult), m_imageName(imageName),
762 m_jobs.setAutoDelete(TRUE);
767 QCString args = QCString(
"-T")+format+
" -o \""+output+
"\"";
782 QListIterator<DotConstString> li(
m_jobs);
787 for (li.toFirst();(s=li.current());++li)
799 for (li.toFirst();(s=li.current());++li)
810 err(
"Problems running '%s' as a post-processing step for dot output\n",
m_postCmd.
data());
826 err(
"Problems running dot: exit code=%d, command='%s', arguments='%s'\n",
834 : m_patchFile(patchFile)
836 m_maps.setAutoDelete(TRUE);
845 bool urlOnly,
const QCString &context,
const QCString &label)
861 const QCString &figureName,
bool heightCheck)
867 map->
label = baseName;
875 const QCString &context,
bool zoomable,
890 const QCString &absImgName,
891 const QCString &relPath)
897 map->
label = baseName;
914 interactiveSVG = interactiveSVG && map->
zoomable;
920 QString tmpName = QString::fromUtf8(
m_patchFile+
".tmp");
921 QString patchFile = QString::fromUtf8(
m_patchFile);
922 if (!QDir::current().rename(patchFile,tmpName))
924 err(
"Failed to rename file %s to %s!\n",
m_patchFile.data(),tmpName.data());
929 if (!fi.open(IO_ReadOnly))
931 err(
"problem opening file %s for patching!\n",tmpName.data());
932 QDir::current().rename(tmpName,patchFile);
935 if (!fo.open(IO_WriteOnly))
937 err(
"problem opening file %s for patching!\n",
m_patchFile.data());
938 QDir::current().rename(tmpName,patchFile);
942 const int maxLineLen=100*1024;
945 bool insideHeader=FALSE;
946 bool replacedHeader=FALSE;
947 bool foundSize=FALSE;
950 QCString line(maxLineLen);
951 int numBytes = fi.readLine(line.rawData(),maxLineLen);
956 line.resize(numBytes+1);
960 ASSERT(numBytes<maxLineLen);
965 if (line.find(
"<svg")!=-1 && !replacedHeader)
968 count = sscanf(line.data(),
"<svg width=\"%dpt\" height=\"%dpt\"",&width,&height);
970 foundSize = count==2 && (width>500 || height>450);
971 if (foundSize) insideHeader=TRUE;
973 else if (insideHeader && !replacedHeader && line.find(
"<title>")!=-1)
978 t <<
"<!--zoomable " << height <<
" -->\n";
980 t <<
"var viewWidth = " << width <<
";\n";
981 t <<
"var viewHeight = " << height <<
";\n";
984 t <<
"var sectionId = 'dynsection-" << graphId <<
"';\n";
987 t <<
"<script xlink:href=\"" << relPath <<
"svgpan.js\"/>\n";
988 t <<
"<svg id=\"graph\" class=\"graph\">\n";
989 t <<
"<g id=\"viewport\">\n";
995 if (!insideHeader || !foundSize)
1003 else if ((i=line.find(
"<!-- SVG"))!=-1 || (i=line.find(
"[!-- SVG"))!=-1)
1008 int n = sscanf(line.data()+i+1,
"!-- SVG %d",&mapId);
1009 if (n==1 && mapId>=0 && mapId<(
int)
m_maps.count())
1011 int e = QMAX(line.find(
"--]"),line.find(
"-->"));
1017 err(
"Problem extracting size from SVG file %s\n",map->mapFile.data());
1019 if (e!=-1) t << line.mid(e+3);
1027 else if ((i=line.find(
"<!-- MAP"))!=-1)
1031 int n = sscanf(line.data()+i,
"<!-- MAP %d",&mapId);
1032 if (n==1 && mapId>=0 && mapId<(
int)
m_maps.count())
1037 t <<
"<map name=\"" << map->
label <<
"\" id=\"" << map->
label <<
"\">" <<
endl;
1039 t <<
"</map>" <<
endl;
1047 else if ((i=line.find(
"% FIG"))!=-1)
1050 int n = sscanf(line.data()+i+2,
"FIG %d",&mapId);
1052 if (n==1 && mapId>=0 && mapId<(
int)
m_maps.count())
1059 err(
"problem writing FIG %d figure!\n",mapId);
1065 err(
"Found invalid bounding FIG %d in file %s!\n",mapId,
m_patchFile.data());
1076 if (isSVGFile && interactiveSVG && replacedHeader)
1085 if (!fi.open(IO_ReadOnly))
1087 err(
"problem opening file %s for reading!\n",tmpName.data());
1090 if (!fo.open(IO_WriteOnly))
1092 err(
"problem opening file %s for writing!\n",orgName.data());
1098 QCString line(maxLineLen);
1099 int numBytes = fi.readLine(line.rawData(),maxLineLen);
1104 line.resize(numBytes+1);
1112 QDir::current().remove(tmpName);
1120 QMutexLocker locker(&
m_mutex);
1127 QMutexLocker locker(&
m_mutex);
1139 QMutexLocker locker(&
m_mutex);
1169 for (;(ci=it.current());++it)
1197 if (numThreads==0) numThreads = QMAX(2,QThread::idealThreadCount()+1);
1198 for (i=0;i<numThreads;i++)
1202 if (thread->isRunning())
1226 const QCString &relPath,
bool urlOnly,
const QCString &context,
1227 const QCString &label)
1235 return map->
addMap(mapFile,relPath,urlOnly,context,label);
1239 const QCString &figureName,
bool heightCheck)
1247 return map->
addFigure(baseName,figureName,heightCheck);
1251 bool urlOnly,
const QCString &context,
bool zoomable,
1264 const QCString &absImgName,
const QCString &relPath)
1279 if (numDotRuns+numDotMaps>1)
1283 msg(
"Generating dot graphs in single threaded mode...\n");
1287 msg(
"Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numDotMaps,
m_workers.count()));
1315 for (li.toFirst();(dr=li.current());++li)
1317 msg(
"Running dot for graph %d/%d\n",prev,numDotRuns);
1324 for (li.toFirst();(dr=li.current());++li)
1334 msg(
"Running dot for graph %d/%d\n",prev,numDotRuns);
1339 while ((
int)numDotRuns>=prev)
1341 msg(
"Running dot for graph %d/%d\n",prev,numDotRuns);
1374 for (di.toFirst();(map=di.current());++di)
1376 if (map->
file().right(4)==
".svg")
1378 msg(
"Patching output file %d/%d\n",i,numDotMaps);
1379 if (!map->
run())
return FALSE;
1383 for (di.toFirst();(map=di.current());++di)
1385 if (map->
file().right(4)!=
".svg")
1387 msg(
"Patching output file %d/%d\n",i,numDotMaps);
1388 if (!map->
run())
return FALSE;
1405 deletedNodes.setAutoDelete(TRUE);
1407 deletedNodes.clear();
1426 , m_truncated(Unknown)
1441 const char *edgeLab,
1442 const char *edgeURL,
1457 ei->
m_url = edgeURL;
1490 QListIterator<DotNode> dnlip(*
m_parents);
1492 for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
1502 for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
1510 if (skipNodes==0 || skipNodes->
find((
char*)
this)==0)
1513 deletedList.append(
this);
1525 QCString bBefore(
"\\_/<({[: =-+@%#~?$");
1526 QCString bAfter(
">]),:;|");
1527 const char *p=l.data();
1528 if (p==0)
return result;
1538 QCString replacement;
1541 case '\\': replacement=
"\\\\";
break;
1542 case '\n': replacement=
"\\n";
break;
1543 case '<': replacement=
"\\<";
break;
1544 case '>': replacement=
"\\>";
break;
1545 case '|': replacement=
"\\|";
break;
1546 case '{': replacement=
"\\{";
break;
1547 case '}': replacement=
"\\}";
break;
1548 case '"': replacement=
"\\\"";
break;
1549 default: cs[0]=c; replacement=cs;
break;
1555 result+=replacement;
1556 foldLen = (3*foldLen+sinceLast+2)/4;
1559 else if ((pc!=
':' || c!=
':') && charsLeft>foldLen/3 && sinceLast>foldLen && bBefore.contains(c))
1562 result+=replacement;
1563 foldLen = (foldLen+sinceLast+1)/2;
1566 else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 &&
1567 !isupper(c) && isupper(*p))
1569 result+=replacement;
1571 foldLen = (foldLen+sinceLast+1)/2;
1574 else if (charsLeft>foldLen/3 && sinceLast>foldLen && bAfter.contains(c) && (c!=
':' || *p!=
':'))
1576 result+=replacement;
1578 foldLen = (foldLen+sinceLast+1)/2;
1583 result+=replacement;
1595 const char *p=tooltip.data();
1596 if (p==0)
return result;
1602 case '"': result+=
"\\\"";
break;
1603 default: result+=c;
break;
1611 bool isStatic=FALSE,
const QDict<void> *skipNames=0)
1619 for (mlia.toFirst();(mma = mlia.current());++mlia)
1622 (skipNames==0 || skipNames->find(mma->
name())==0))
1629 for (mlia.toFirst();(mma = mlia.current());++mlia)
1632 (skipNames==0 || skipNames->find(mma->
name())==0))
1635 if (limit>0 && (totalCount>limit*3/2 && count>=limit))
1657 for (mgli.toFirst();(mg=mgli.current());++mgli)
1670 if (!s.isEmpty() && (s[0]==
'-' || s[0]==
'+' || s[0]==
'~' || s[0]==
'#'))
1683 bool hasNonReachableChildren
1686 const char *labCol =
1687 m_url.isEmpty() ?
"grey75" :
1689 (hasNonReachableChildren) ?
"red" :
"black"
1691 t <<
" Node" <<
m_number <<
" [label=\"";
1698 QDict<void> arrowNames(17);
1704 for (li.toFirst();(ei=li.current());++li)
1708 int li=ei->
m_label.find(
'\n');
1711 while ((li=ei->
m_label.find(
'\n',p))!=-1)
1714 arrowNames.insert(lab,(
void*)0x8);
1718 arrowNames.insert(lab,(
void*)0x8);
1759 for (mgdi.toFirst();(mg=mgdi.current());++mgdi)
1773 t <<
"\",height=0.2,width=0.4";
1776 t <<
",color=\"black\", fillcolor=\"grey75\", style=\"filled\", fontcolor=\"black\"";
1781 if (!dotTransparent)
1783 t <<
",color=\"" << labCol <<
"\", fillcolor=\"";
1785 t <<
"\", style=\"filled\"";
1789 t <<
",color=\"" << labCol <<
"\"";
1791 if (!
m_url.isEmpty())
1793 int anchorPos =
m_url.findRev(
'#');
1801 <<
m_url.right(
m_url.length()-anchorPos) <<
"\"";
1836 bool umlUseArrow = aStyle==
"odiamond";
1838 if (pointBack && !umlUseArrow) t <<
"dir=\"back\",";
1840 <<
"\",fontsize=\"" <<
FONTSIZE <<
"\",";
1851 bool rev = pointBack;
1852 if (umlUseArrow) rev=!rev;
1881 QListIterator<DotNode> dnli1(*nl);
1884 for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2)
1889 writeArrow(t,gt,format,cn,dnli2.current(),topDown,backArrows);
1891 cn->
write(t,gt,format,topDown,toChildren,backArrows);
1896 QListIterator<DotNode> dnli(*nl);
1898 for (dnli.toFirst();(pn=dnli.current());++dnli)
1912 pn->
write(t,gt,format,TRUE,FALSE,backArrows);
1923 if (!
m_url.isEmpty())
1925 QCString url(
m_url);
1926 const char *refPtr = url.data();
1927 char *urlPtr = strchr(url.rawData(),
'$');
1931 t <<
" <link refid=\"" <<
convertToXML(urlPtr) <<
"\"";
1945 for (;(childNode=nli.current());++nli,++eli)
1947 edgeInfo=eli.current();
1948 t <<
" <childnode refid=\"" << childNode->
m_number <<
"\" relation=\"";
1967 if (!edgeInfo->
m_label.isEmpty())
1971 while ((ni=edgeInfo->
m_label.find(
'\n',p))!=-1)
1975 <<
"</edgelabel>" << endl;
1980 <<
"</edgelabel>" <<
endl;
1982 t <<
" </childnode>" <<
endl;
1985 t <<
" </node>" <<
endl;
1992 if (!
m_url.isEmpty())
1994 QCString url(
m_url);
1995 const char *refPtr = url.data();
1996 char *urlPtr = strchr(url.rawData(),
'$');
2000 t <<
" <link refid=\"" <<
convertToXML(urlPtr) <<
"\"";
2014 for (;(childNode=nli.current());++nli,++eli)
2016 edgeInfo=eli.current();
2017 t <<
" <childnode refid=\"" << childNode->
m_number <<
"\" relation=\"";
2036 if (!edgeInfo->
m_label.isEmpty())
2040 while ((ni=edgeInfo->
m_label.find(
'\n',p))!=-1)
2044 <<
"</edgelabel>" << endl;
2049 <<
"</edgelabel>" <<
endl;
2051 t <<
" </childnode>" <<
endl;
2054 t <<
" </node>" <<
endl;
2060 const char* nodePrefix =
" node-";
2062 t <<
" node = {" <<
endl;
2064 t << nodePrefix <<
"label = '" <<
m_label <<
"';" <<
endl;
2066 if (!
m_url.isEmpty())
2068 QCString url(
m_url);
2069 const char *refPtr = url.data();
2070 char *urlPtr = strchr(url.rawData(),
'$');
2074 t << nodePrefix <<
"link = {" << endl <<
" "
2075 << nodePrefix <<
"link-id = '" << urlPtr <<
"';" <<
endl;
2079 t <<
" " << nodePrefix <<
"link-external = '"
2080 << refPtr <<
"';" <<
endl;
2091 for (;(childNode=nli.current());++nli,++eli)
2093 edgeInfo=eli.current();
2094 t <<
" node-child = {" <<
endl;
2095 t <<
" child-id = '" << childNode->
m_number <<
"';" <<
endl;
2096 t <<
" relation = ";
2110 if (!edgeInfo->
m_label.isEmpty())
2112 t <<
" edgelabel = <<_EnD_oF_dEf_TeXt_" << endl
2114 <<
"_EnD_oF_dEf_TeXt_;" <<
endl;
2116 t <<
" }; /* node-child */" <<
endl;
2119 t <<
" }; /* node */" <<
endl;
2128 QListIterator<DotNode> dnlip(*
m_parents);
2130 for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
2142 for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
2158 for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
2172 QListIterator<DotNode> dnlip(*
m_parents);
2174 for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
2194 for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
2203 if (!
m_url.isEmpty())
return this;
2207 QListIterator<DotNode> dnli(*
m_parents);
2209 for (dnli.toFirst();(pn=dnli.current());++dnli)
2223 for (dnli.toFirst();(cn=dnli.current());++dnli)
2239 const char *path,
const char *fileName,
int id)
const
2245 baseName.sprintf(
"inherit_graph_%d",
id);
2246 QCString imgName = baseName+
"."+ imgExt;
2247 QCString mapName = baseName+
".map";
2248 QCString absImgName = QCString(d.absPath().data())+
"/"+imgName;
2249 QCString absMapName = QCString(d.absPath().data())+
"/"+mapName;
2250 QCString absBaseName = QCString(d.absPath().data())+
"/"+baseName;
2258 md5stream <<
" rankdir=\"LR\";" <<
endl;
2259 for (dnli2.toFirst();(node=dnli2.current());++dnli2)
2266 for (dnli2.toFirst();(node=dnli2.current());++dnli2)
2275 QCString sigStr(33);
2276 MD5Buffer((
const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
2277 MD5SigToString(md5_sig,sigStr.rawData(),33);
2278 bool regenerate=FALSE;
2284 QCString dotName=absBaseName+
".dot";
2286 if (!f.open(IO_WriteOnly))
return;
2292 dotRun->
addJob(imgFmt,absImgName);
2310 FALSE,QCString(),FALSE,0);
2313 absImgName,QCString());
2314 out <<
"<!-- SVG " << mapId <<
" -->" <<
endl;
2319 out <<
"<img src=\"" << imgName <<
"\" border=\"0\" alt=\"\" usemap=\"#"
2320 << mapLabel <<
"\"/>" <<
endl;
2322 if (regenerate || !
insertMapFile(out,absMapName,QCString(),mapLabel))
2325 FALSE,QCString(),mapLabel);
2326 out <<
"<!-- MAP " << mapId <<
" -->" <<
endl;
2332 const char *path,
const char *fileName)
const
2343 err(
"Output dir %s does not exist!\n",path); exit(1);
2347 out <<
"<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" <<
endl;
2352 for (dnli.toFirst();(n=dnli.current());++dnli)
2356 out <<
"</td></tr>" <<
endl;
2358 out <<
"</table>" <<
endl;
2368 for ( ; (bcd=bcli.current()) ; ++bcli )
2397 QCString tmp_url=
"";
2401 if (!bClass->
anchor().isEmpty())
2403 tmp_url+=
"#"+bClass->
anchor();
2425 bool wasVisited=bClass->
visited;
2439 for (cli.toLast();(cd=cli.current());--cli)
2452 QCString tmp_url=
"";
2456 if (!cd->
anchor().isEmpty())
2458 tmp_url+=
"#"+cd->
anchor();
2503 for (dnli.toLast();(n=dnli.current());--dnli)
2525 for (dnli2.toFirst();(n=dnli2.current());++dnli2)
2555 const char *label,
const char *usedName,
const char *templSpec,
bool base,
int distance)
2563 className=
"anonymous:";
2585 n->
addChild(bn,prot,edgeStyle,label);
2590 bn->
addChild(n,prot,edgeStyle,label);
2598 QCString displayName=className;
2604 if (!cd->
anchor().isEmpty())
2606 tmp_url+=
"#"+cd->
anchor();
2619 n->
addChild(bn,prot,edgeStyle,label);
2624 bn->
addChild(n,prot,edgeStyle,label);
2638 while (queue.count()>0)
2643 bool truncated = FALSE;
2648 for (li.toFirst();(dn=li.current());++li)
2658 QListIterator<DotNode> li(*n->
m_parents);
2660 for (li.toFirst();(dn=li.current());++li)
2674 int maxNodes,
bool includeParents)
2676 QList<DotNode> childQueue;
2677 QList<DotNode> parentQueue;
2678 QArray<int> childTreeWidth;
2679 QArray<int> parentTreeWidth;
2680 childQueue.append(rootNode);
2681 if (includeParents) parentQueue.append(rootNode);
2682 bool firstNode=TRUE;
2684 while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0)
2686 static int maxDistance =
Config_getInt(MAX_DOT_GRAPH_DEPTH);
2687 if (childQueue.count()>0)
2689 DotNode *n = childQueue.take(0);
2691 if (!n->
isVisible() && distance<=maxDistance)
2695 int oldSize=(int)childTreeWidth.size();
2696 if (distance>oldSize)
2698 childTreeWidth.resize(QMAX(childTreeWidth.size(),(uint)distance));
2699 int i;
for (i=oldSize;i<distance;i++) childTreeWidth[i]=0;
2701 childTreeWidth[distance-1]+=n->
label().length();
2710 for (li.toFirst();(dn=li.current());++li)
2712 childQueue.append(dn);
2717 if (includeParents && parentQueue.count()>0)
2719 DotNode *n = parentQueue.take(0);
2726 int oldSize = (int)parentTreeWidth.size();
2727 if (distance>oldSize)
2729 parentTreeWidth.resize(QMAX(parentTreeWidth.size(),(uint)distance));
2730 int i;
for (i=oldSize;i<distance;i++) parentTreeWidth[i]=0;
2732 parentTreeWidth[distance-1]+=n->
label().length();
2739 QListIterator<DotNode> li(*n->
m_parents);
2741 for (li.toFirst();(dn=li.current());++li)
2743 parentQueue.append(dn);
2751 int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size());
2753 for (i=0;i<childTreeWidth.size();i++)
2755 if (childTreeWidth.at(i)>maxWidth) maxWidth=childTreeWidth.at(i);
2757 for (i=0;i<parentTreeWidth.size();i++)
2759 if (parentTreeWidth.at(i)>maxWidth) maxWidth=parentTreeWidth.at(i);
2762 return maxWidth>80 && maxHeight<12;
2770 static bool templateRelations =
Config_getBool(TEMPLATE_RELATIONS);
2782 for ( ; (bcd=bcli.current()) ; ++bcli )
2803 for (;(ucd=ucdi.current());++ucdi)
2806 QDictIterator<void> dvi(*ucd->
accessors);
2811 for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
2820 label+=QCString(
"\n")+s;
2823 if (count==maxLabels) label+=
"\n...";
2830 if (templateRelations && base)
2837 for (;(ccd=ccdi.current());++ccdi)
2840 QDictIterator<void> dvi(*ccd->
accessors);
2845 for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
2854 label+=QCString(
"\n")+s;
2857 if (count==maxLabels) label+=
"\n...";
2867 if (templateRelations)
2876 for (;(templInstance=cli.current());++cli)
2878 if (templInstance==cd)
2891 QDictIterator<ClassDef> cli(*templInstances);
2893 for (;(templInstance=cli.current());++cli)
2914 QCString tmp_url=
"";
2918 if (!cd->
anchor().isEmpty())
2920 tmp_url+=
"#"+cd->
anchor();
2952 QList<DotNode> openNodeQueue;
2978 return numNodes>=maxNodes;
2996 const QCString &title,
3006 md5stream <<
" rankdir=\"LR\";" <<
endl;
3009 root->
write(md5stream,
3017 QListIterator<DotNode> dnli(*root->
m_parents);
3019 for (dnli.toFirst();(pn=dnli.current());++dnli)
3032 pn->
write(md5stream,
3043 QCString sigStr(33);
3044 MD5Buffer((
const unsigned char *)buf.data(),buf.length(),md5_sig);
3045 MD5SigToString(md5_sig,sigStr.rawData(),33);
3046 graphStr=buf.data();
3053 const QCString &baseName,
3058 const QCString &title=QCString()
3064 root,gt,format,lrRank,renderParents,
3065 backArrows,title,theGraph);
3066 QFile f(baseName+
".dot");
3067 if (f.open(IO_WriteOnly))
3079 const char *fileName,
3080 const char *relPath,
3082 bool generateImageMap,
3089 err(
"Output dir %s does not exist!\n",path); exit(1);
3102 mapName=
"inherit_map";
3113 QCString absBaseName = d.absPath().utf8()+
"/"+baseName;
3114 QCString absDotName = absBaseName+
".dot";
3115 QCString absMapName = absBaseName+
".map";
3116 QCString absPdfName = absBaseName+
".pdf";
3117 QCString absEpsName = absBaseName+
".eps";
3118 QCString absImgName = absBaseName+
"."+imgExt;
3120 bool regenerate = FALSE;
3131 usePDFLatex ? absPdfName : absEpsName,
3132 graphFormat==
GOF_BITMAP && generateImageMap ? absMapName : QCString())
3139 d.absPath().data(),TRUE,absImgName);
3140 dotRun->
addJob(imgFmt,absImgName);
3145 else if (graphFormat==
GOF_EPS)
3150 dotRun->
addJob(
"pdf",absPdfName);
3154 dotRun->
addJob(
"ps",absEpsName);
3163 out <<
"<para>" <<
endl;
3164 out <<
" <figure>" <<
endl;
3169 out <<
"Collaboration graph";
3172 out <<
"Inheritance graph";
3178 out <<
"</title>" <<
endl;
3179 out <<
" <mediaobject>" <<
endl;
3180 out <<
" <imageobject>" <<
endl;
3181 out <<
" <imagedata";
3182 out <<
" width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName <<
"." << imgExt <<
"\">";
3183 out <<
"</imagedata>" <<
endl;
3184 out <<
" </imageobject>" <<
endl;
3185 out <<
" </mediaobject>" <<
endl;
3186 out <<
" </figure>" <<
endl;
3187 out <<
"</para>" <<
endl;
3189 else if (graphFormat==
GOF_BITMAP && generateImageMap)
3195 out <<
"<div class=\"center\">";
3203 out <<
"<!-- SVG " << mapId <<
" -->" <<
endl;
3205 out <<
"</div>" <<
endl;
3209 out <<
"<div class=\"center\">";
3210 out <<
"<img src=\"" << relPath << baseName <<
"."
3211 << imgExt <<
"\" border=\"0\" usemap=\"#"
3212 << mapLabel <<
"\" alt=\"";
3216 out <<
"Collaboration graph";
3219 out <<
"Inheritance graph";
3226 out <<
"</div>" <<
endl;
3227 if (regenerate || !
insertMapFile(out,absMapName,relPath,mapLabel))
3230 FALSE,QCString(),mapLabel);
3231 out <<
"<!-- MAP " << mapId <<
" -->" <<
endl;
3235 else if (graphFormat==
GOF_EPS)
3240 out <<
endl <<
"% FIG " << figId <<
endl;
3254 for (;(node=dni.current());++dni)
3264 for (;(node=dni.current());++dni)
3274 for (;(node=dni.current());++dni)
3284 QList<IncludeInfo> *includeFiles =
3288 QListIterator<IncludeInfo> ili(*includeFiles);
3290 for (;(ii=ili.current());++ili)
3295 bool doc=TRUE,src=FALSE;
3323 tmp_url=doc || src ? bfd->
getReference()+
"$"+url : QCString();
3348 while (queue.count()>0 && maxNodes>0)
3350 static int maxDistance =
Config_getInt(MAX_DOT_GRAPH_DEPTH);
3361 for (li.toFirst();(dn=li.current());++li)
3372 while (queue.count()>0)
3377 bool truncated = FALSE;
3382 for (li.toFirst();(dn=li.current());++li)
3421 int maxNodes = nodes;
3426 QList<DotNode> openNodeQueue;
3429 openNodeQueue.clear();
3444 const char *fileName,
3445 const char *relPath,
3446 bool generateImageMap,
3454 err(
"Output dir %s does not exist!\n",path); exit(1);
3472 QCString absBaseName = d.absPath().utf8()+
"/"+baseName;
3473 QCString absDotName = absBaseName+
".dot";
3474 QCString absMapName = absBaseName+
".map";
3475 QCString absPdfName = absBaseName+
".pdf";
3476 QCString absEpsName = absBaseName+
".eps";
3477 QCString absImgName = absBaseName+
"."+imgExt;
3479 bool regenerate = FALSE;
3490 usePDFLatex ? absPdfName : absEpsName,
3491 graphFormat==
GOF_BITMAP && generateImageMap ? absMapName : QCString())
3499 dotRun->
addJob(imgFmt,absImgName);
3503 else if (graphFormat==
GOF_EPS)
3508 dotRun->
addJob(
"pdf",absPdfName);
3512 dotRun->
addJob(
"ps",absEpsName);
3521 out <<
"<para>" <<
endl;
3522 out <<
" <figure>" <<
endl;
3523 out <<
" <title>Dependency diagram";
3524 out <<
"</title>" <<
endl;
3525 out <<
" <mediaobject>" <<
endl;
3526 out <<
" <imageobject>" <<
endl;
3527 out <<
" <imagedata";
3528 out <<
" width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName <<
"." << imgExt <<
"\">";
3529 out <<
"</imagedata>" <<
endl;
3530 out <<
" </imageobject>" <<
endl;
3531 out <<
" </mediaobject>" <<
endl;
3532 out <<
" </figure>" <<
endl;
3533 out <<
"</para>" <<
endl;
3535 else if (graphFormat==
GOF_BITMAP && generateImageMap)
3539 out <<
"<div class=\"center\">";
3547 out <<
"<!-- SVG " << mapId <<
" -->" <<
endl;
3549 out <<
"</div>" <<
endl;
3553 out <<
"<div class=\"center\"><img src=\"" << relPath << baseName <<
"." << imgExt <<
"\" border=\"0\" usemap=\"#" << mapName <<
"\" alt=\"\"/>";
3554 out <<
"</div>" <<
endl;
3556 QCString absMapName = absBaseName+
".map";
3557 if (regenerate || !
insertMapFile(out,absMapName,relPath,mapName))
3560 FALSE,QCString(),mapName);
3561 out <<
"<!-- MAP " << mapId <<
" -->" <<
endl;
3565 else if (graphFormat==
GOF_EPS)
3570 out <<
endl <<
"% FIG " << figId <<
endl;
3587 return numNodes>=maxNodes;
3594 for (;(node=dni.current());++dni)
3604 for (;(node=dni.current());++dni)
3619 for (;(rmd=mri.current());++mri)
3667 while (queue.count()>0 && maxNodes>0)
3669 static int maxDistance =
Config_getInt(MAX_DOT_GRAPH_DEPTH);
3680 for (li.toFirst();(dn=li.current());++li)
3691 while (queue.count()>0)
3696 bool truncated = FALSE;
3701 for (li.toFirst();(dn=li.current());++li)
3750 int maxNodes = nodes;
3755 QList<DotNode> openNodeQueue;
3758 openNodeQueue.clear();
3771 const char *path,
const char *fileName,
3772 const char *relPath,
bool generateImageMap,
int
3779 err(
"Output dir %s does not exist!\n",path); exit(1);
3784 QCString mapName = baseName;
3788 QCString absBaseName = d.absPath().utf8()+
"/"+baseName;
3789 QCString absDotName = absBaseName+
".dot";
3790 QCString absMapName = absBaseName+
".map";
3791 QCString absPdfName = absBaseName+
".pdf";
3792 QCString absEpsName = absBaseName+
".eps";
3793 QCString absImgName = absBaseName+
"."+imgExt;
3795 bool regenerate = FALSE;
3806 usePDFLatex ? absPdfName : absEpsName,
3807 graphFormat==
GOF_BITMAP && generateImageMap ? absMapName : QCString())
3815 dotRun->
addJob(imgFmt,absImgName);
3820 else if (graphFormat==
GOF_EPS)
3826 dotRun->
addJob(
"pdf",absPdfName);
3830 dotRun->
addJob(
"ps",absEpsName);
3840 out <<
"<para>" <<
endl;
3841 out <<
" <figure>" <<
endl;
3842 out <<
" <title>Call diagram";
3843 out <<
"</title>" <<
endl;
3844 out <<
" <mediaobject>" <<
endl;
3845 out <<
" <imageobject>" <<
endl;
3846 out <<
" <imagedata";
3847 out <<
" width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName <<
"." << imgExt <<
"\">";
3848 out <<
"</imagedata>" <<
endl;
3849 out <<
" </imageobject>" <<
endl;
3850 out <<
" </mediaobject>" <<
endl;
3851 out <<
" </figure>" <<
endl;
3852 out <<
"</para>" <<
endl;
3854 else if (graphFormat==
GOF_BITMAP && generateImageMap)
3858 out <<
"<div class=\"center\">";
3866 out <<
"<!-- SVG " << mapId <<
" -->" <<
endl;
3868 out <<
"</div>" <<
endl;
3872 out <<
"<div class=\"center\"><img src=\"" << relPath << baseName <<
"."
3873 << imgExt <<
"\" border=\"0\" usemap=\"#"
3874 << mapName <<
"\" alt=\"";
3876 out <<
"</div>" <<
endl;
3878 if (regenerate || !
insertMapFile(out,absMapName,relPath,mapName))
3881 FALSE,QCString(),mapName);
3882 out <<
"<!-- MAP " << mapId <<
" -->" <<
endl;
3886 else if (graphFormat==
GOF_EPS)
3891 out <<
endl <<
"% FIG " << figId <<
endl;
3908 return numNodes>=maxNodes;
3926 const char *fileName,
3927 const char *relPath,
3928 bool generateImageMap,
3930 bool linkRelations)
const
3936 err(
"Output dir %s does not exist!\n",path); exit(1);
3945 QCString absBaseName = d.absPath().utf8()+
"/"+baseName;
3946 QCString absDotName = absBaseName+
".dot";
3947 QCString absMapName = absBaseName+
".map";
3948 QCString absPdfName = absBaseName+
".pdf";
3949 QCString absEpsName = absBaseName+
".eps";
3950 QCString absImgName = absBaseName+
"."+imgExt;
3958 QCString sigStr(33);
3959 MD5Buffer((
const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
3960 MD5SigToString(md5_sig,sigStr.rawData(),33);
3961 bool regenerate=FALSE;
3964 usePDFLatex ? absPdfName : absEpsName,
3965 graphFormat==
GOF_BITMAP && generateImageMap ? absMapName : QCString())
3970 QFile f(absDotName);
3971 if (!f.open(IO_WriteOnly))
3973 err(
"Cannot create file %s.dot for writing!\n",baseName.data());
3976 t << theGraph.data();
3983 dotRun->
addJob(imgFmt,absImgName);
3987 else if (graphFormat==
GOF_EPS)
3992 dotRun->
addJob(
"pdf",absPdfName);
3996 dotRun->
addJob(
"ps",absEpsName);
4005 out <<
"<para>" <<
endl;
4006 out <<
" <figure>" <<
endl;
4007 out <<
" <title>Directory Dependency diagram";
4008 out <<
"</title>" <<
endl;
4009 out <<
" <mediaobject>" <<
endl;
4010 out <<
" <imageobject>" <<
endl;
4011 out <<
" <imagedata";
4012 out <<
" width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName <<
"." << imgExt <<
"\">";
4013 out <<
"</imagedata>" <<
endl;
4014 out <<
" </imageobject>" <<
endl;
4015 out <<
" </mediaobject>" <<
endl;
4016 out <<
" </figure>" <<
endl;
4017 out <<
"</para>" <<
endl;
4019 else if (graphFormat==
GOF_BITMAP && generateImageMap)
4023 out <<
"<div class=\"center\">";
4031 out <<
"<!-- SVG " << mapId <<
" -->" <<
endl;
4033 out <<
"</div>" <<
endl;
4037 out <<
"<div class=\"center\"><img src=\"" << relPath << baseName <<
"."
4038 << imgExt <<
"\" border=\"0\" usemap=\"#"
4039 << mapName <<
"\" alt=\"";
4042 out <<
"</div>" <<
endl;
4044 if (regenerate || !
insertMapFile(out,absMapName,relPath,mapName))
4047 TRUE,QCString(),mapName);
4048 out <<
"<!-- MAP " << mapId <<
" -->" <<
endl;
4052 else if (graphFormat==
GOF_EPS)
4057 out <<
endl <<
"% FIG " << figId <<
endl;
4078 err(
"Output dir %s does not exist!\n",path); exit(1);
4084 md5stream <<
" Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" <<
FONTNAME <<
"\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n";
4085 md5stream <<
" Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"solid\",fontname=\"" << FONTNAME <<
"\"];\n";
4086 md5stream <<
" Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"black\",URL=\"$classPublicBase" <<
Doxygen::htmlFileExtension <<
"\"];\n";
4087 md5stream <<
" Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"solid\",fontname=\"" << FONTNAME <<
"\"];\n";
4088 md5stream <<
" Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension <<
"\"];\n";
4089 md5stream <<
" Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"solid\",fontname=\"" << FONTNAME <<
"\"];\n";
4090 md5stream <<
" Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension <<
"\"];\n";
4091 md5stream <<
" Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"solid\",fontname=\"" << FONTNAME <<
"\"];\n";
4092 md5stream <<
" Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension <<
"\"];\n";
4093 md5stream <<
" Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"solid\",fontname=\"" << FONTNAME <<
"\"];\n";
4094 md5stream <<
" Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"grey75\"];\n";
4095 md5stream <<
" Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"solid\",fontname=\"" << FONTNAME <<
"\"];\n";
4096 md5stream <<
" Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension <<
"\"];\n";
4097 md5stream <<
" Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"dashed\",label=\"< int >\",fontname=\"" << FONTNAME <<
"\"];\n";
4098 md5stream <<
" Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension <<
"\"];\n";
4099 md5stream <<
" Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" <<
FONTSIZE <<
"\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << FONTNAME <<
"\"];\n";
4100 md5stream <<
" Node18 [shape=\"box\",label=\"Used\",fontsize=\"" <<
FONTSIZE <<
"\",height=0.2,width=0.4,fontname=\"" << FONTNAME <<
"\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension <<
"\"];\n";
4103 QCString sigStr(33);
4104 MD5Buffer((
const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
4105 MD5SigToString(md5_sig,sigStr.rawData(),33);
4106 QCString absBaseName = (QCString)path+
"/graph_legend";
4107 QCString absDotName = absBaseName+
".dot";
4110 QCString imgName =
"graph_legend."+imgExt;
4111 QCString absImgName = absBaseName+
"."+imgExt;
4115 QFile dotFile(absDotName);
4116 if (!dotFile.open(IO_WriteOnly))
4118 err(
"Could not open file %s for writing\n",dotFile.name().data());
4123 dotText << theGraph;
4129 dotRun->
addJob(imgFmt,absImgName);
4143 absImgName,QCString());
4154 err(
"Output dir %s does not exist!\n",outDir); exit(1);
4159 QCString imgName = (QCString)outFile+
"."+imgExt;
4160 QCString absImgName = d.absPath().utf8()+
"/"+imgName;
4161 QCString absOutFile = d.absPath().utf8()+
"/"+outFile;
4163 DotRunner dotRun(inFile,d.absPath().data(),FALSE,absImgName);
4165 dotRun.
addJob(imgFmt,absImgName);
4170 dotRun.addJob(
"pdf",absOutFile+
".pdf");
4174 dotRun.addJob(
"ps",absOutFile+
".eps");
4178 dotRun.preventCleanUp();
4201 const QCString &inFile,
const QCString &outDir,
4202 const QCString &relPath,
const QCString &baseName,
4203 const QCString &context,
int graphId)
4209 err(
"Output dir %s does not exist!\n",outDir.data()); exit(1);
4212 QCString mapName = baseName+
".map";
4215 QCString imgName = baseName+
"."+imgExt;
4216 QCString absOutFile = d.absPath().utf8()+
"/"+mapName;
4218 DotRunner dotRun(inFile,d.absPath().data(),FALSE);
4220 dotRun.preventCleanUp();
4230 QCString svgName=outDir+
"/"+baseName+
".svg";
4238 t <<
"<img src=\"" << relPath << imgName <<
"\" alt=\""
4239 << imgName <<
"\" border=\"0\" usemap=\"#" << mapName <<
"\"/>" <<
endl
4240 <<
"<map name=\"" << mapName <<
"\" id=\"" << mapName <<
"\">";
4244 t <<
"</map>" <<
endl;
4246 d.remove(absOutFile);
4289 for (gli.toFirst();(d=gli.current());++gli)
4310 for (;(def=defli.current());++defli)
4315 tmp_url = def->getReference()+
"$"+def->getOutputFileBase();
4316 QCString tooltip = def->briefDescriptionAsTooltip();
4337 for (;(def=defli.current());++defli)
4340 if (!def->anchor().isEmpty())
4342 tmp_url+=
"#"+def->anchor();
4353 for (;(def=defli.current());++defli)
4363 QListIterator<FileDef> defli(*gd->
getFiles());
4365 for (;(def=defli.current());++defli)
4377 for (;(def=defli.current());++defli)
4387 QListIterator<DirDef> defli(*gd->
getDirs());
4389 for (;(def=defli.current());++defli)
4399 if ( !( ml && ml->
count()) )
return;
4402 for (;(def=defli.current());++defli)
4412 const QCString& _label,
const QCString& _url )
4415 QListIterator<Edge> lli(
m_edges);
4417 for ( lli.toFirst(); (newEdge=lli.current()); ++lli)
4419 if ( newEdge->
pNStart==_pNStart &&
4420 newEdge->
pNEnd==_pNEnd &&
4421 newEdge->
eType==_eType
4429 newEdge =
new Edge(_pNStart,_pNEnd,_eType);
4433 if (!_label.isEmpty())
4435 newEdge->
links.append(
new Link(_label,_url));
4450 for (;(d=gli.current());++gli)
4457 tmp_str = d->getReference()+
"$"+d->getOutputFileBase();
4458 QCString tooltip = d->briefDescriptionAsTooltip();
4472 const char *path,
const char *fileName,
const char *relPath,
4473 bool writeImageMap,
int graphId)
const
4479 err(
"Output dir %s does not exist!\n",path); exit(1);
4490 for (dni.toFirst();(pn=dni.current());++dni)
4496 for (dni.toFirst();(pn=dni.current());++dni)
4502 QListIterator<Edge> eli(
m_edges);
4504 for (eli.toFirst();(edge=eli.current());++eli)
4506 edge->
write( md5stream );
4511 QCString sigStr(33);
4512 MD5Buffer((
const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
4513 MD5SigToString(md5_sig,sigStr.rawData(),33);
4517 QCString imgName = baseName+
"."+imgExt;
4518 QCString absPath = d.absPath().data();
4519 QCString absBaseName = absPath+
"/"+baseName;
4520 QCString absDotName = absBaseName+
".dot";
4521 QCString absImgName = absBaseName+
"."+imgExt;
4522 QCString absMapName = absBaseName+
".map";
4523 QCString absPdfName = absBaseName+
".pdf";
4524 QCString absEpsName = absBaseName+
".eps";
4525 bool regenerate=FALSE;
4528 usePDFLatex ? absPdfName : absEpsName,
4529 graphFormat==
GOF_BITMAP ? absMapName : QCString())
4534 QFile dotfile(absDotName);
4535 if (dotfile.open(IO_WriteOnly))
4545 dotRun->
addJob(imgFmt,absImgName);
4550 else if (graphFormat==
GOF_EPS)
4555 dotRun->
addJob(
"pdf",absPdfName);
4559 dotRun->
addJob(
"ps",absEpsName);
4567 t <<
"<para>" <<
endl;
4568 t <<
" <figure>" <<
endl;
4569 t <<
" <title>Group Collaboration diagram";
4570 t <<
"</title>" <<
endl;
4571 t <<
" <mediaobject>" <<
endl;
4572 t <<
" <imageobject>" <<
endl;
4574 t <<
" width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName <<
"." << imgExt <<
"\">";
4575 t <<
"</imagedata>" <<
endl;
4576 t <<
" </imageobject>" <<
endl;
4577 t <<
" </mediaobject>" <<
endl;
4578 t <<
" </figure>" <<
endl;
4579 t <<
"</para>" <<
endl;
4581 else if (graphFormat==
GOF_BITMAP && writeImageMap)
4584 t <<
"<center><table><tr><td>";
4588 t <<
"<div class=\"center\">";
4596 t <<
"<!-- SVG " << mapId <<
" -->" <<
endl;
4598 t <<
"</div>" <<
endl;
4602 t <<
"<img src=\"" << relPath << imgName
4603 <<
"\" border=\"0\" alt=\"\" usemap=\"#"
4604 << mapLabel <<
"\"/>" <<
endl;
4605 if (regenerate || !
insertMapFile(t,absMapName,relPath,mapLabel))
4608 FALSE,QCString(),mapLabel);
4609 t <<
"<!-- MAP " << mapId <<
" -->" <<
endl;
4612 t <<
"</td></tr></table></center>" <<
endl;
4614 else if (graphFormat==
GOF_EPS)
4619 t <<
endl <<
"% FIG " << figId <<
endl;
4629 const char* linkTypeColor[] = {
4638 QCString arrowStyle =
"dir=\"none\", style=\"dashed\"";
4643 t <<
" [shape=plaintext";
4644 if (
links.count()>0)
4663 QListIterator<Link> lli(
links);
4667 const int maxLabels = 10;
4668 for( lli.toFirst(); (link=lli.current()) && count<maxLabels; ++lli,++count)
4670 if (first) first=FALSE;
else t <<
"\\n";
4673 if (count==maxLabels) t <<
"\\n...";
4680 arrowStyle =
"dir=\"back\", style=\"solid\"";
4683 t <<
", color=\"" << linkTypeColor[(int)
eType] <<
"\"";
4686 t <<
", " << arrowStyle;
4696 const QCString &title)
const
4699 if (title.isEmpty())
4701 t <<
"\"Dot Graph\"";
4711 t <<
" bgcolor=\"transparent\";" <<
endl;
4713 t <<
" edge [fontname=\"" <<
FONTNAME <<
"\",fontsize=\"" <<
FONTSIZE <<
"\","
4714 "labelfontname=\"" <<
FONTNAME <<
"\",labelfontsize=\"" <<
FONTSIZE <<
"\"];\n";
4715 t <<
" node [fontname=\"" <<
FONTNAME <<
"\",fontsize=\"" << FONTSIZE <<
"\",shape=record];\n";
4716 t <<
" rankdir=LR;\n";
4721 t <<
"digraph \"" << dd->
displayName() <<
"\" {\n";
4724 t <<
" bgcolor=transparent;\n";
4726 t <<
" compound=true\n";
4727 t <<
" node [ fontsize=\"" <<
FONTSIZE <<
"\", fontname=\"" <<
FONTNAME <<
"\"];\n";
4728 t <<
" edge [ labelfontsize=\"" <<
FONTSIZE <<
"\", labelfontname=\"" << FONTNAME <<
"\"];\n";
4730 QDict<DirDef> dirsInGraph(257);
4736 t <<
" graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\""
4738 <<
"\" fontname=\"" << FONTNAME <<
"\", fontsize=\"" <<
FONTSIZE <<
"\", URL=\"";
4745 t <<
" graph [ bgcolor=\"#eeeeff\", pencolor=\"black\", label=\"\""
4752 QListIterator<DirDef> sdi(dd->
subDirs());
4754 for (sdi.toFirst();(sdir=sdi.current());++sdi)
4756 t <<
" " << sdir->getOutputFileBase() <<
" [shape=box label=\""
4757 << sdir->shortName() <<
"\"";
4758 if (sdir->isCluster())
4760 t <<
" color=\"red\"";
4764 t <<
" color=\"black\"";
4766 t <<
" fillcolor=\"white\" style=\"filled\"";
4767 t <<
" URL=\"" << sdir->getOutputFileBase()
4770 dirsInGraph.insert(sdir->getOutputFileBase(),sdir);
4777 << dd->
shortName() <<
"\", style=\"filled\", fillcolor=\"#eeeeff\","
4787 QDictIterator<UsedDir> udi(*dd->
usedDirs());
4790 for (udi.toFirst();(udir=udi.current());++udi)
4793 const DirDef *usedDir=udir->dir();
4804 if (dir!=usedDir && dir->
parent()==usedDir->
parent() &&
4814 t <<
" fillcolor=\"white\" style=\"filled\"";
4816 t <<
" color=\"red\"";
4829 QDictIterator<DirDef> di(dirsInGraph);
4830 for (di.toFirst();(dir=di.current());++di)
4832 QDictIterator<UsedDir> udi(*dir->
usedDirs());
4834 for (udi.toFirst();(udir=udi.current());++udi)
4836 const DirDef *usedDir=udir->dir();
4837 if ((dir!=dd || !udir->inherited()) &&
4838 (usedDir!=dd || !udir->inherited()) &&
4842 QCString relationName;
4850 int nrefs = udir->filePairs().count();
4853 t <<
" [headlabel=\"" << nrefs <<
"\", labeldistance=1.5";