dirdef.cpp

Go to the documentation of this file.
00001 #include <md5.h>
00002 
00003 #include "dirdef.h"
00004 #include "filename.h"
00005 #include "doxygen.h"
00006 #include "util.h"
00007 #include "outputlist.h"
00008 #include "language.h"
00009 #include "message.h"
00010 #include "dot.h"
00011 
00012 //----------------------------------------------------------------------
00013 // method implementation
00014 
00015 static int g_dirCount=0;
00016 
00017 DirDef::DirDef(const char *path) : Definition(path,1,path)
00018 {
00019   // get display name (stipping the paths mentioned in STRIP_FROM_PATH)
00020   m_dispName = stripFromPath(path);
00021   // get short name (last part of path)
00022   m_shortName = path;
00023   if (m_shortName.at(m_shortName.length()-1)=='/')
00024   { // strip trailing /
00025     m_shortName = m_shortName.left(m_shortName.length()-1);
00026   }
00027   int pi=m_shortName.findRev('/');
00028   if (pi!=-1) 
00029   { // remove everything till the last /
00030     m_shortName = m_shortName.mid(pi+1);
00031   }
00032   setLocalName(m_shortName);
00033   
00034   m_fileList   = new FileList;
00035   m_usedDirs   = new QDict<UsedDir>(257);
00036   m_usedDirs->setAutoDelete(TRUE);
00037   m_dirCount   = g_dirCount++;
00038   m_level=-1;
00039   m_parent=0;
00040 }
00041 
00042 DirDef::~DirDef()
00043 {
00044   delete m_fileList;
00045   delete m_usedDirs;
00046 }
00047 
00048 bool DirDef::isLinkableInProject() const 
00049 { 
00050   return !isReference() && Config_getBool("SHOW_DIRECTORIES"); 
00051 }
00052 
00053 bool DirDef::isLinkable() const 
00054 { 
00055   return isReference() || isLinkableInProject(); 
00056 }
00057 
00058 void DirDef::addSubDir(DirDef *subdir)
00059 {
00060   m_subdirs.inSort(subdir);
00061   subdir->setOuterScope(this);
00062   subdir->m_parent=this;
00063 }
00064 
00065 void DirDef::addFile(FileDef *fd)
00066 {
00067   m_fileList->inSort(fd);
00068   fd->setDirDef(this);
00069 }
00070 
00071 static QCString encodeDirName(const QCString &anchor)
00072 {
00073   QCString result;
00074 
00075   // convert to md5 hash
00076   uchar md5_sig[16];
00077   QCString sigStr(33);
00078   MD5Buffer((const unsigned char *)anchor.data(),anchor.length(),md5_sig);
00079   MD5SigToString(md5_sig,sigStr.data(),33);
00080   return sigStr;
00081 
00082   // old algorithm
00083 
00084 //  int l = anchor.length(),i;
00085 //  for (i=0;i<l;i++)
00086 //  {
00087 //    char c = anchor.at(i);
00088 //    if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'))
00089 //    {
00090 //      result+=c;
00091 //    }
00092 //    else
00093 //    {
00094 //      static char hexStr[]="0123456789ABCDEF";
00095 //      char escChar[]={ '_', 0, 0, 0 };
00096 //      escChar[1]=hexStr[c>>4];
00097 //      escChar[2]=hexStr[c&0xf];
00098 //      result+=escChar;
00099 //    }
00100 //  }
00101 //  return result;
00102 }
00103 
00104 QCString DirDef::getOutputFileBase() const
00105 {
00106   return "dir_"+encodeDirName(name());
00107   //return QCString().sprintf("dir_%06d",m_dirCount);
00108 }
00109 
00110 void DirDef::writeDetailedDocumentation(OutputList &ol)
00111 {
00112   if (!briefDescription().isEmpty() || !documentation().isEmpty())
00113   {
00114     ol.writeRuler();
00115     ol.pushGeneratorState();
00116       ol.disable(OutputGenerator::Latex);
00117       ol.disable(OutputGenerator::RTF);
00118     ol.writeAnchor(0,"_details");
00119     ol.popGeneratorState();
00120     ol.startGroupHeader();
00121     ol.parseText(theTranslator->trDetailedDescription());
00122     ol.endGroupHeader();
00123 
00124     // repeat brief description
00125     if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
00126     {
00127       ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
00128       ol.newParagraph();
00129     }
00130 
00131     // write documentation
00132     if (!documentation().isEmpty())
00133     {
00134       ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
00135     }
00136   }
00137 }
00138 
00139 void DirDef::writeDocumentation(OutputList &ol)
00140 {
00141   ol.pushGeneratorState();
00142   
00143   QCString shortTitle=theTranslator->trDirReference(m_shortName);
00144   QCString title=theTranslator->trDirReference(m_dispName);
00145   startFile(ol,getOutputFileBase(),name(),title,HLI_None,TRUE);
00146 
00147   // write navigation path
00148   writeNavigationPath(ol);
00149 
00150   ol.endQuickIndices();
00151   ol.startContents();
00152 
00153   startTitle(ol,getOutputFileBase());
00154   ol.pushGeneratorState();
00155     ol.disableAllBut(OutputGenerator::Html);
00156     ol.parseText(shortTitle);
00157     ol.enableAll();
00158     ol.disable(OutputGenerator::Html);
00159     ol.parseText(title);
00160   ol.popGeneratorState();
00161   endTitle(ol,getOutputFileBase(),title);
00162 
00163   // write brief or details (if DETAILS_AT_TOP)
00164   if (Config_getBool("DETAILS_AT_TOP"))
00165   {
00166     writeDetailedDocumentation(ol);
00167     ol.newParagraph();
00168   }
00169   else if (!briefDescription().isEmpty())
00170   {
00171     ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE);
00172     ol.writeString(" \n");
00173     ol.pushGeneratorState();
00174     ol.disable(OutputGenerator::Latex);
00175     ol.disable(OutputGenerator::RTF);
00176     ol.disable(OutputGenerator::Man);
00177     ol.startTextLink(0,"_details");
00178     ol.parseText(theTranslator->trMore());
00179     ol.endTextLink();
00180     ol.enableAll();
00181     ol.disableAllBut(OutputGenerator::Man);
00182     ol.newParagraph();
00183     ol.popGeneratorState();
00184   }
00185 
00186   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00187   {
00188     Doxygen::tagFile << "  <compound kind=\"dir\">" << endl;
00189     Doxygen::tagFile << "    <name>" << convertToXML(displayName()) << "</name>" << endl;
00190     Doxygen::tagFile << "    <path>" << convertToXML(name()) << "</path>" << endl;
00191     Doxygen::tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
00192   }
00193   
00194   // write graph dependency graph
00195   if (Config_getBool("DIRECTORY_GRAPH") && Config_getBool("HAVE_DOT"))
00196   {
00197     DotDirDeps dirDep(this);
00198     if (!dirDep.isTrivial())
00199     {
00200       msg("Generating dependency graph for directory %s\n",displayName().data());
00201       ol.disable(OutputGenerator::Man);
00202       ol.newParagraph();
00203       ol.startDirDepGraph();
00204       //TODO: ol.parseText(theTranslator->trDirDepGraph());
00205       ol.endDirDepGraph(dirDep);
00206       ol.enableAll();
00207     }
00208   }
00209 
00210   ol.startMemberSections();
00211   // write subdir list
00212   if (m_subdirs.count()>0)
00213   {
00214     ol.startMemberHeader();
00215     ol.parseText(theTranslator->trDir(TRUE,FALSE));
00216     ol.endMemberHeader();
00217     ol.startMemberList();
00218     DirDef *dd=m_subdirs.first();
00219     while (dd)
00220     {
00221       ol.startMemberItem(0);
00222       ol.parseText(theTranslator->trDir(FALSE,TRUE)+" ");
00223       ol.insertMemberAlign();
00224       ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),0,dd->shortName());
00225       ol.endMemberItem();
00226       if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00227       {
00228         Doxygen::tagFile << "    <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;
00229       }
00230       if (!dd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
00231       {
00232         ol.startMemberDescription();
00233         ol.parseDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),
00234             FALSE, // indexWords
00235             FALSE, // isExample
00236             0,     // exampleName
00237             FALSE, // single line
00238             TRUE   // link from index
00239            );
00240         ol.endMemberDescription();
00241         ol.newParagraph();
00242       }
00243       dd=m_subdirs.next();
00244     }
00245 
00246     ol.endMemberList();
00247   }
00248   
00249   // write file list
00250   if (m_fileList->count()>0)
00251   {
00252     ol.startMemberHeader();
00253     ol.parseText(theTranslator->trFile(TRUE,FALSE));
00254     ol.endMemberHeader();
00255     ol.startMemberList();
00256     FileDef *fd=m_fileList->first();
00257     while (fd)
00258     {
00259       ol.startMemberItem(0);
00260       ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");
00261       ol.insertMemberAlign();
00262       if (fd->isLinkable())
00263       {
00264         ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
00265       }
00266       else
00267       {
00268         ol.startBold();
00269         ol.docify(fd->name()); 
00270         ol.endBold();
00271       }
00272       if (fd->generateSourceFile())
00273       {
00274         ol.pushGeneratorState();
00275         ol.disableAllBut(OutputGenerator::Html);
00276         ol.docify(" ");
00277         ol.startTextLink(fd->includeName(),0);
00278         ol.docify("[");
00279         ol.parseText(theTranslator->trCode());
00280         ol.docify("]");
00281         ol.endTextLink();
00282         ol.popGeneratorState();
00283       }
00284       if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00285       {
00286         Doxygen::tagFile << "    <file>" << convertToXML(fd->name()) << "</file>" << endl;
00287       }
00288       ol.endMemberItem();
00289       if (!fd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
00290       {
00291         ol.startMemberDescription();
00292         ol.parseDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),
00293             FALSE, // indexWords
00294             FALSE, // isExample
00295             0,     // exampleName
00296             FALSE, // single line
00297             TRUE   // link from index
00298            );
00299         ol.endMemberDescription();
00300         ol.newParagraph();
00301       }
00302       fd=m_fileList->next();
00303     }
00304     ol.endMemberList();
00305   }
00306   ol.endMemberSections();
00307 
00308   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00309   {
00310     writeDocAnchorsToTagFile();
00311     Doxygen::tagFile << "  </compound>" << endl;
00312   }
00313 
00314 
00315   if (!Config_getBool("DETAILS_AT_TOP"))
00316   {
00317     writeDetailedDocumentation(ol);
00318   }
00319   
00320   endFile(ol); 
00321   ol.popGeneratorState();
00322 }
00323 
00324 #if 0
00325 void DirDef::writePathFragment(OutputList &ol) const
00326 {
00327   if (m_parent)
00328   {
00329     m_parent->writePathFragment(ol);
00330     ol.writeString("&nbsp;/&nbsp;");
00331   }
00332   ol.writeObjectLink(getReference(),getOutputFileBase(),0,shortName());
00333 }
00334 
00335 void DirDef::writeNavigationPath(OutputList &ol)
00336 {
00337   ol.pushGeneratorState();
00338   ol.disableAllBut(OutputGenerator::Html);
00339 
00340   ol.writeString("<div class=\"nav\">\n");
00341   writePathFragment(ol);
00342   ol.writeString("</div>\n");
00343 
00344   ol.popGeneratorState();
00345 }
00346 #endif
00347 
00348 void DirDef::setLevel()
00349 {
00350   if (m_level==-1) // level not set before
00351   {
00352     DirDef *p = parent();
00353     if (p)
00354     {
00355       p->setLevel();
00356       m_level = p->level()+1;
00357     }
00358     else
00359     {
00360       m_level = 0;
00361     }
00362   }
00363 }
00364 
00368 void DirDef::addUsesDependency(DirDef *dir,FileDef *srcFd,
00369                                FileDef *dstFd,bool inherited)
00370 {
00371   if (this==dir) return; // do not add self-dependencies
00372   //static int count=0;
00373   //printf("  %d add dependency %s->%s due to %s->%s\n",
00374   //    count++,shortName().data(),
00375   //    dir->shortName().data(),
00376   //    srcFd->name().data(),
00377   //    dstFd->name().data());
00378 
00379   // levels match => add direct dependency
00380   bool added=FALSE;
00381   UsedDir *usedDir = m_usedDirs->find(dir->getOutputFileBase());
00382   if (usedDir) // dir dependency already present
00383   {
00384      FilePair *usedPair = usedDir->findFilePair(
00385          srcFd->getOutputFileBase()+dstFd->getOutputFileBase());
00386      if (usedPair==0) // new file dependency
00387      {
00388        //printf("  => new file\n");
00389        usedDir->addFileDep(srcFd,dstFd); 
00390        added=TRUE;
00391      }
00392      else
00393      {
00394        // dir & file dependency already added
00395      }
00396   }
00397   else // new directory dependency
00398   {
00399     //printf("  => new file\n");
00400     usedDir = new UsedDir(dir,inherited);
00401     usedDir->addFileDep(srcFd,dstFd); 
00402     m_usedDirs->insert(dir->getOutputFileBase(),usedDir);
00403     added=TRUE;
00404   }
00405   if (added)
00406   {
00407     if (dir->parent())
00408     {
00409       // add relation to parent of used dir
00410       addUsesDependency(dir->parent(),srcFd,dstFd,inherited);
00411     }
00412     if (parent())
00413     {
00414       // add relation for the parent of this dir as well
00415       parent()->addUsesDependency(dir,srcFd,dstFd,TRUE);
00416     }
00417   }
00418 }
00419 
00422 void DirDef::computeDependencies()
00423 {
00424   FileList *fl = m_fileList;
00425   if (fl) 
00426   {
00427     QListIterator<FileDef> fli(*fl);
00428     FileDef *fd;
00429     for (fli.toFirst();(fd=fli.current());++fli) // foreach file in dir dd
00430     {
00431       //printf("  File %s\n",fd->name().data());
00432       //printf("** dir=%s file=%s\n",shortName().data(),fd->name().data());
00433       QList<IncludeInfo> *ifl = fd->includeFileList();
00434       if (ifl)
00435       {
00436         QListIterator<IncludeInfo> ifli(*ifl); 
00437         IncludeInfo *ii;
00438         for (ifli.toFirst();(ii=ifli.current());++ifli) // foreach include file
00439         {
00440           //printf("  > %s\n",ii->includeName.data());
00441           //printf("    #include %s\n",ii->includeName.data());
00442           if (ii->fileDef && ii->fileDef->isLinkable()) // linkable file
00443           {
00444             DirDef *usedDir = ii->fileDef->getDirDef();
00445             if (usedDir)
00446             {
00447               // add dependency: thisDir->usedDir
00448               //static int count=0;
00449               //printf("      %d: add dependency %s->%s\n",count++,name().data(),usedDir->name().data());
00450               addUsesDependency(usedDir,fd,ii->fileDef,FALSE);
00451             }
00452           } 
00453         }
00454       }
00455     }
00456   }
00457 }
00458 
00459 bool DirDef::isParentOf(DirDef *dir) const
00460 {
00461   if (dir->parent()==this) // this is a parent of dir 
00462     return TRUE;
00463   else if (dir->parent()) // repeat for the parent of dir
00464     return isParentOf(dir->parent()); 
00465   else
00466     return FALSE;
00467 }
00468 
00469 bool DirDef::depGraphIsTrivial() const
00470 {
00471   return FALSE;
00472 }
00473 
00474 //----------------------------------------------------------------------
00475 
00476 int FilePairDict::compareItems(GCI item1,GCI item2)
00477 {
00478   FilePair *left  = (FilePair*)item1;
00479   FilePair *right = (FilePair*)item2;
00480   int orderHi = stricmp(left->source()->name(),right->source()->name());
00481   int orderLo = stricmp(left->destination()->name(),right->destination()->name());
00482   return orderHi==0 ? orderLo : orderHi;
00483 }
00484 
00485 //----------------------------------------------------------------------
00486 
00487 UsedDir::UsedDir(DirDef *dir,bool inherited) :
00488    m_dir(dir), m_filePairs(7), m_inherited(inherited)
00489 {
00490   m_filePairs.setAutoDelete(TRUE);
00491 }
00492 
00493 UsedDir::~UsedDir()
00494 {
00495 }
00496 
00497 
00498 void UsedDir::addFileDep(FileDef *srcFd,FileDef *dstFd)
00499 {
00500   m_filePairs.inSort(srcFd->getOutputFileBase()+dstFd->getOutputFileBase(),
00501                      new FilePair(srcFd,dstFd));
00502 }
00503 
00504 FilePair *UsedDir::findFilePair(const char *name)
00505 {
00506   QCString n=name;
00507   return n.isEmpty() ? 0 : m_filePairs.find(n);
00508 }
00509 
00510 DirDef *DirDef::createNewDir(const char *path)
00511 {
00512   ASSERT(path!=0);
00513   DirDef *dir = Doxygen::directories->find(path);
00514   if (dir==0) // new dir
00515   {
00516     //printf("Adding new dir %s\n",path);
00517     dir = new DirDef(path);
00518     //printf("createNewDir %s short=%s\n",path,dir->shortName().data());
00519     Doxygen::directories->inSort(path,dir);
00520   }
00521   return dir;
00522 }
00523 
00524 bool DirDef::matchPath(const QCString &path,QStrList &l)
00525 {
00526   const char *s=l.first();
00527   while (s)
00528   {
00529     QCString prefix = s;
00530     if (stricmp(prefix.left(path.length()),path)==0) // case insensitive compare
00531     {
00532       return TRUE;
00533     }
00534     s = l.next();
00535   }
00536   return FALSE;
00537 }
00538 
00542 DirDef *DirDef::mergeDirectoryInTree(const QCString &path)
00543 {
00544   //printf("DirDef::mergeDirectoryInTree(%s)\n",path.data());
00545   int p=0,i=0;
00546   DirDef *dir=0;
00547   while ((i=path.find('/',p))!=-1)
00548   {
00549     QCString part=path.left(i+1);
00550     if (!matchPath(part,Config_getList("STRIP_FROM_PATH")) && part!="/")
00551     {
00552       dir=createNewDir(part); 
00553     }
00554     p=i+1;
00555   }
00556   return dir;
00557 }
00558 
00559 void DirDef::writeDepGraph(QTextStream &t)
00560 {
00561     writeDotDirDepGraph(t,this);
00562 }
00563 
00564 //----------------------------------------------------------------------
00565 
00566 static void writePartialDirPath(OutputList &ol,const DirDef *root,const DirDef *target)
00567 {
00568   if (target->parent()!=root) 
00569   {
00570     writePartialDirPath(ol,root,target->parent());
00571     ol.writeString("&nbsp;/&nbsp;");
00572   }
00573   ol.writeObjectLink(target->getReference(),target->getOutputFileBase(),0,target->shortName());
00574 }
00575 
00576 static void writePartialFilePath(OutputList &ol,const DirDef *root,const FileDef *fd)
00577 {
00578   if (fd->getDirDef() && fd->getDirDef()!=root)
00579   {
00580     writePartialDirPath(ol,root,fd->getDirDef());
00581     ol.writeString("&nbsp;/&nbsp;");
00582   }
00583   if (fd->isLinkable())
00584   {
00585     ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
00586   }
00587   else
00588   {
00589     ol.startBold();
00590     ol.docify(fd->name());
00591     ol.endBold();
00592   }
00593 }
00594 
00595 void DirRelation::writeDocumentation(OutputList &ol)
00596 {
00597   ol.pushGeneratorState();
00598   ol.disableAllBut(OutputGenerator::Html);
00599 
00600   QCString shortTitle=m_src->shortName()+" &rarr; "+
00601                       m_dst->dir()->shortName()+" Relation";//theTranslator->trDirRelation(m_shortName);
00602   QCString title=m_src->displayName()+" -> "+
00603                  m_dst->dir()->shortName()+" Relation";//theTranslator->trDirRelation(m_dispName);
00604   startFile(ol,getOutputFileBase(),getOutputFileBase(),title);
00605 
00606   // write navigation path
00607   m_src->writeNavigationPath(ol);
00608 
00609   //startTitle(ol,getOutputFileBase());
00610   //  ol.parseText(shortTitle);
00611   //endTitle(ol,getOutputFileBase(),title);
00612   ol.writeString("<h3>"+shortTitle+"</h3>");
00613   
00614   ol.writeString("<table class=\"dirtab\">");
00615   ol.writeString("<tr class=\"dirtab\">");
00616   ol.writeString("<th class=\"dirtab\">File in ");
00617   m_src->writePathFragment(ol);
00618   ol.writeString("</th>");
00619   ol.writeString("<th class=\"dirtab\">Includes file in ");
00620   m_dst->dir()->writePathFragment(ol);
00621   ol.writeString("</th>");
00622   ol.writeString("</tr>");
00623 
00624   SDict<FilePair>::Iterator fpi(m_dst->filePairs());
00625   FilePair *fp;
00626   for (fpi.toFirst();(fp=fpi.current());++fpi)
00627   {
00628     ol.writeString("<tr class=\"dirtab\">");
00629     ol.writeString("<td class=\"dirtab\">");
00630     writePartialFilePath(ol,m_src,fp->source());
00631     ol.writeString("</td>");
00632     ol.writeString("<td class=\"dirtab\">");
00633     writePartialFilePath(ol,m_dst->dir(),fp->destination());
00634     ol.writeString("</td>");
00635     ol.writeString("</tr>");
00636   }
00637   ol.writeString("</table>");
00638   
00639   endFile(ol); 
00640   ol.popGeneratorState();
00641 }
00642 
00643 //----------------------------------------------------------------------
00644 // external functions
00645 
00646 void buildDirectories()
00647 {
00648   // for each input file
00649   FileNameListIterator fnli(*Doxygen::inputNameList); 
00650   FileName *fn;
00651   for (fnli.toFirst();(fn=fnli.current());++fnli)
00652   {
00653     FileNameIterator fni(*fn);
00654     FileDef *fd;
00655     for (;(fd=fni.current());++fni)
00656     {
00657       //printf("buildDirectories %s\n",fd->name().data());
00658       if (fd->getReference().isEmpty() && !fd->isDocumentationFile())
00659       {
00660         DirDef *dir;
00661         if ((dir=Doxygen::directories->find(fd->getPath()))==0) // new directory
00662         {
00663           dir = DirDef::mergeDirectoryInTree(fd->getPath());
00664         }
00665         if (dir) dir->addFile(fd);
00666       }
00667       else
00668       {
00669         // do something for file imported via tag files.
00670       }
00671     }
00672   }
00673 
00674   //DirDef *root = new DirDef("root:");
00675   // compute relations between directories => introduce container dirs.
00676   DirDef *dir;
00677   DirSDict::Iterator sdi(*Doxygen::directories);
00678   for (sdi.toFirst();(dir=sdi.current());++sdi)
00679   {
00680     //printf("New dir %s\n",dir->displayName().data());
00681     QCString name = dir->name();
00682     int i=name.findRev('/',name.length()-2);
00683     if (i>0)
00684     {
00685       DirDef *parent = Doxygen::directories->find(name.left(i+1));
00686       //if (parent==0) parent=root;
00687       if (parent) 
00688       {
00689         parent->addSubDir(dir); 
00690         //printf("DirDef::addSubdir(): Adding subdir\n%s to\n%s\n",
00691         //  dir->displayName().data(), parent->displayName().data());
00692       }
00693     }
00694   }
00695 }
00696 
00697 void computeDirDependencies()
00698 {
00699   DirDef *dir;
00700   DirSDict::Iterator sdi(*Doxygen::directories);
00701   // compute nesting level for each directory
00702   for (sdi.toFirst();(dir=sdi.current());++sdi)
00703   {
00704     dir->setLevel();
00705   }
00706   // compute uses dependencies between directories
00707   for (sdi.toFirst();(dir=sdi.current());++sdi)
00708   {
00709     //printf("computeDependencies for %s: #dirs=%d\n",dir->name().data(),Doxygen::directories.count());
00710     dir->computeDependencies();
00711   }
00712 
00713 #if 0
00714   printf("-------------------------------------------------------------\n");
00715   // print dependencies (for debugging)
00716   for (sdi.toFirst();(dir=sdi.current());++sdi)
00717   {
00718     if (dir->usedDirs())
00719     {
00720       QDictIterator<UsedDir> udi(*dir->usedDirs());
00721       UsedDir *usedDir;
00722       for (udi.toFirst();(usedDir=udi.current());++udi)
00723       {
00724         printf("%s depends on %s due to ",
00725             dir->shortName().data(),usedDir->dir()->shortName().data());
00726         QDictIterator<FileDef> fdi(usedDir->files());
00727         FileDef *fd;
00728         for (fdi.toFirst();(fd=fdi.current());++fdi)
00729         {
00730           printf("%s ",fd->name().data());
00731         }
00732         printf("\n");
00733       }
00734     }
00735   }
00736   printf("^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^\n");
00737 #endif
00738 }
00739 
00740 
00741 void writeDirDependencyGraph(const char *dirName)
00742 {
00743   QString path;
00744   DirDef *dir;
00745   DirSDict::Iterator sdi(*Doxygen::directories);
00746   QFile htmlPage(QCString(dirName)+"/dirdeps.html");
00747   if (htmlPage.open(IO_WriteOnly))
00748   {
00749     QTextStream out(&htmlPage);
00750     out << "<html><body>";
00751     for (sdi.toFirst();(dir=sdi.current());++sdi)
00752     {
00753       path=dirName;
00754       path+="/";
00755       path+=dir->getOutputFileBase();
00756       path+="_dep.dot";
00757       out << "<h4>" << dir->displayName() << "</h4>" << endl;
00758       out << "<img src=\"" << dir->getOutputFileBase() << "_dep.gif\">" << endl;
00759       QFile f(path);
00760       if (f.open(IO_WriteOnly))
00761       {
00762         QTextStream t(&f);
00763         dir->writeDepGraph(t);
00764       }
00765       f.close();
00766 
00767       QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
00768       QCString outFile = QCString(dirName)+"/"+
00769                          dir->getOutputFileBase()+"_dep."+imgExt; 
00770       DotRunner dotRun(path);
00771       dotRun.addJob(imgExt,outFile);
00772       dotRun.run();
00773       
00774       //QCString dotArgs(4096);
00775       //dotArgs.sprintf("%s -Tgif -o %s",path.data(),outFile.data());
00776       //if (portable_system(Config_getString("DOT_PATH")+"dot",dotArgs,FALSE)!=0)
00777       //{
00778       //  err("Problems running dot. Check your installation!\n");
00779       //}
00780     }
00781     out << "</body></html>";
00782   }
00783   htmlPage.close();
00784 }
00785 
00786 void generateDirDocs(OutputList &ol)
00787 {
00788   DirDef *dir;
00789   DirSDict::Iterator sdi(*Doxygen::directories);
00790   for (sdi.toFirst();(dir=sdi.current());++sdi)
00791   {
00792     dir->writeDocumentation(ol);
00793   }
00794   if (Config_getBool("DIRECTORY_GRAPH"))
00795   {
00796     SDict<DirRelation>::Iterator rdi(Doxygen::dirRelations);
00797     DirRelation *dr;
00798     for (rdi.toFirst();(dr=rdi.current());++rdi)
00799     {
00800       dr->writeDocumentation(ol);
00801     }
00802   }
00803 }
00804 



Generated on Mon Mar 31 10:58:34 2008 by  doxygen 1.5.1