groupdef.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * $Id: groupdef.cpp,v 1.29 2001/03/19 19:27:40 root Exp $
00004  *
00005  * Copyright (C) 1997-2008 by Dimitri van Heesch.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and its
00008  * documentation under the terms of the GNU General Public License is hereby 
00009  * granted. No representations are made about the suitability of this software 
00010  * for any purpose. It is provided "as is" without express or implied warranty.
00011  * See the GNU General Public License for more details.
00012  *
00013  * Documents produced by Doxygen are derivative works derived from the
00014  * input used in their production; they are not affected by this license.
00015  *
00016  */
00017 
00018 #include <ctype.h>
00019 #include <qregexp.h>
00020 #include "qtbc.h"
00021 #include "groupdef.h"
00022 #include "classdef.h"
00023 #include "filedef.h"
00024 #include "classlist.h"
00025 #include "outputlist.h"
00026 #include "namespacedef.h"
00027 #include "language.h"
00028 #include "util.h"
00029 #include "memberlist.h"
00030 #include "message.h"
00031 #include "membergroup.h"
00032 #include "doxygen.h"
00033 #include "pagedef.h"
00034 #include "docparser.h"
00035 #include "searchindex.h"
00036 #include "dot.h"
00037 #include "vhdldocgen.h"
00038 
00039 GroupDef::GroupDef(const char *df,int dl,const char *na,const char *t,
00040                    const char *refFileName) : Definition(df,dl,na)
00041 {
00042   fileList = new FileList;
00043   classSDict = new ClassSDict(17);
00044   groupList = new GroupList;
00045   namespaceSDict = new NamespaceSDict(17);
00046   pageDict = new PageSDict(17);
00047   exampleDict = new PageSDict(17);
00048   dirList = new DirList;
00049   allMemberNameInfoSDict = new MemberNameInfoSDict(17);
00050   if (refFileName)
00051   {
00052     fileName=stripExtension(refFileName);
00053   }
00054   else
00055   {
00056     fileName = (QCString)"group_"+na;
00057   }
00058   setGroupTitle( t );
00059   memberGroupSDict = new MemberGroupSDict;
00060   memberGroupSDict->setAutoDelete(TRUE);
00061 
00062   allMemberList = new MemberList(MemberList::allMembersList);
00063 #if 0
00064 
00065   decDefineMembers.setInGroup(TRUE);
00066   decProtoMembers.setInGroup(TRUE);
00067   decTypedefMembers.setInGroup(TRUE);
00068   decEnumMembers.setInGroup(TRUE);
00069   decEnumValMembers.setInGroup(TRUE);
00070   decFuncMembers.setInGroup(TRUE);
00071   decVarMembers.setInGroup(TRUE);
00072 
00073   docDefineMembers.setInGroup(TRUE);
00074   docProtoMembers.setInGroup(TRUE);
00075   docTypedefMembers.setInGroup(TRUE);
00076   docEnumMembers.setInGroup(TRUE);
00077   docEnumValMembers.setInGroup(TRUE);
00078   docFuncMembers.setInGroup(TRUE);
00079   docVarMembers.setInGroup(TRUE);
00080 #endif
00081 
00082   visited = 0;
00083   groupScope = 0;
00084 }
00085 
00086 GroupDef::~GroupDef()
00087 {
00088   delete fileList;
00089   delete classSDict;
00090   delete groupList;
00091   delete namespaceSDict;
00092   delete pageDict;
00093   delete exampleDict;
00094   delete allMemberList;
00095   delete allMemberNameInfoSDict;
00096   delete memberGroupSDict;
00097   delete dirList;
00098 }
00099 
00100 void GroupDef::setGroupTitle( const char *t )
00101 {
00102   if ( t && strlen(t) )
00103   {
00104     title = t;
00105     titleSet = TRUE;
00106   }
00107   else
00108   {
00109     title = name();
00110     title.at(0)=toupper(title.at(0));
00111     titleSet = FALSE;
00112   }
00113 }
00114 
00115 
00116 void GroupDef::distributeMemberGroupDocumentation()
00117 {
00118   MemberGroupSDict::Iterator mgli(*memberGroupSDict);
00119   MemberGroup *mg;
00120   for (;(mg=mgli.current());++mgli)
00121   {
00122     mg->distributeMemberGroupDocumentation();
00123   }
00124 }
00125 
00126 void GroupDef::findSectionsInDocumentation()
00127 {
00128   docFindSections(documentation(),this,0,docFile());
00129   MemberGroupSDict::Iterator mgli(*memberGroupSDict);
00130   MemberGroup *mg;
00131   for (;(mg=mgli.current());++mgli)
00132   {
00133     mg->findSectionsInDocumentation();
00134   }
00135 
00136   QListIterator<MemberList> mli(m_memberLists);
00137   MemberList *ml;
00138   for (mli.toFirst();(ml=mli.current());++mli)
00139   {
00140     if (ml->listType()&MemberList::declarationLists)
00141     {
00142       ml->findSectionsInDocumentation();
00143     }
00144   }
00145 #if 0
00146   decDefineMembers.findSectionsInDocumentation();
00147   decProtoMembers.findSectionsInDocumentation();
00148   decTypedefMembers.findSectionsInDocumentation();
00149   decEnumMembers.findSectionsInDocumentation();
00150   decFuncMembers.findSectionsInDocumentation();
00151   decVarMembers.findSectionsInDocumentation();
00152 #endif
00153 }
00154 
00155 void GroupDef::addFile(const FileDef *def)
00156 {
00157   if (def->isHidden()) return;
00158   if (Config_getBool("SORT_BRIEF_DOCS"))
00159     fileList->inSort(def);
00160   else
00161     fileList->append(def);
00162 }
00163 
00164 bool GroupDef::addClass(const ClassDef *cd)
00165 {
00166   if (cd->isHidden()) return FALSE;
00167   if (classSDict->find(cd->name())==0)
00168   {
00169     if (Config_getBool("SORT_BRIEF_DOCS"))
00170       classSDict->inSort(cd->name(),cd);
00171     else
00172       classSDict->append(cd->name(),cd);
00173     return TRUE;
00174   }
00175   return FALSE;
00176 }
00177 
00178 bool GroupDef::addNamespace(const NamespaceDef *def)
00179 {
00180   if (def->isHidden()) return FALSE;
00181   if (namespaceSDict->find(def->name())==0)
00182   {
00183     if (Config_getBool("SORT_BRIEF_DOCS"))
00184       namespaceSDict->inSort(def->name(),def);  
00185     else
00186       namespaceSDict->append(def->name(),def);
00187     return TRUE;
00188   }
00189   return FALSE;
00190 }
00191 
00192 void GroupDef::addDir(const DirDef *def)
00193 {
00194   if (def->isHidden()) return;
00195   if (Config_getBool("SORT_BRIEF_DOCS"))
00196     dirList->inSort(def);  
00197   else
00198     dirList->append(def);
00199 }
00200 
00201 void GroupDef::addPage(PageDef *def)
00202 {
00203   if (def->isHidden()) return;
00204   //printf("Making page %s part of a group\n",def->name.data());
00205   pageDict->append(def->name(),def);
00206   def->makePartOfGroup(this);
00207 }
00208 
00209 void GroupDef::addExample(const PageDef *def)
00210 {
00211   if (def->isHidden()) return;
00212   exampleDict->append(def->name(),def);
00213 }
00214 
00215 
00216 void GroupDef::addMembersToMemberGroup()
00217 {
00218   QListIterator<MemberList> mli(m_memberLists);
00219   MemberList *ml;
00220   for (mli.toFirst();(ml=mli.current());++mli)
00221   {
00222     if (ml->listType()&MemberList::declarationLists)
00223     {
00224       ::addMembersToMemberGroup(ml,&memberGroupSDict,this);
00225     }
00226   }
00227 #if 0
00228   ::addMembersToMemberGroup(&decDefineMembers,&memberGroupSDict,this);
00229   ::addMembersToMemberGroup(&decProtoMembers,&memberGroupSDict,this);
00230   ::addMembersToMemberGroup(&decTypedefMembers,&memberGroupSDict,this);
00231   ::addMembersToMemberGroup(&decEnumMembers,&memberGroupSDict,this);
00232   ::addMembersToMemberGroup(&decEnumValMembers,&memberGroupSDict,this);
00233   ::addMembersToMemberGroup(&decFuncMembers,&memberGroupSDict,this);
00234   ::addMembersToMemberGroup(&decVarMembers,&memberGroupSDict,this);
00235 #endif
00236 
00237   //printf("GroupDef::addMembersToMemberGroup() memberGroupList=%d\n",memberGroupList->count());
00238   MemberGroupSDict::Iterator mgli(*memberGroupSDict);
00239   MemberGroup *mg;
00240   for (;(mg=mgli.current());++mgli)
00241   {
00242     mg->setInGroup(TRUE);
00243   }
00244 }
00245 
00246 
00247 bool GroupDef::insertMember(MemberDef *md,bool docOnly)
00248 {
00249   if (md->isHidden()) return FALSE;
00250   //printf("GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data());
00251   MemberNameInfo *mni=0;
00252   if ((mni=(*allMemberNameInfoSDict)[md->name()]))
00253   { // member with this name already found
00254     MemberNameInfoIterator srcMnii(*mni); 
00255     MemberInfo *srcMi;
00256     for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
00257     {
00258       MemberDef *srcMd = srcMi->memberDef;
00259       if (srcMd==md) return FALSE; // already added before!
00260 
00261       bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace
00262           // both inside a file => definition and declaration do not have to be in the same file
00263            (srcMd->getOuterScope()->definitionType()==Definition::TypeFile &&
00264             md->getOuterScope()->definitionType()==Definition::TypeFile); 
00265 
00266       LockingPtr<ArgumentList> srcMdAl = srcMd->argumentList();
00267       LockingPtr<ArgumentList> mdAl    = md->argumentList();
00268       
00269       if (srcMd->isFunction() && md->isFunction() && 
00270           matchArguments2(srcMd->getOuterScope(),srcMd->getFileDef(),srcMdAl.pointer(),
00271                           md->getOuterScope(),md->getFileDef(),mdAl.pointer(),
00272                           TRUE
00273                          ) &&
00274           sameScope
00275          )
00276       {
00277         if (srcMd->getGroupAlias()==0) 
00278         {
00279           md->setGroupAlias(srcMd); 
00280         }
00281         else
00282         {
00283           md->setGroupAlias(srcMd->getGroupAlias()); 
00284         }
00285         return FALSE; // member is the same as one that is already added
00286       }
00287     }
00288     mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
00289   }
00290   else
00291   {
00292     mni = new MemberNameInfo(md->name());
00293     mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
00294     allMemberNameInfoSDict->append(mni->memberName(),mni);
00295   }
00296   //printf("Added member!\n");
00297   allMemberList->append(md); 
00298   switch(md->memberType())
00299   {
00300     case MemberDef::Variable:     
00301       if (!docOnly)
00302       {
00303         addMemberToList(MemberList::decVarMembers,md);
00304       }
00305       addMemberToList(MemberList::docVarMembers,md);
00306       break;
00307     case MemberDef::Function: 
00308       if (!docOnly)
00309       {
00310         addMemberToList(MemberList::decFuncMembers,md);
00311       }
00312       addMemberToList(MemberList::docFuncMembers,md);
00313       break;
00314     case MemberDef::Typedef:      
00315       if (!docOnly)
00316       {
00317         addMemberToList(MemberList::decTypedefMembers,md);
00318       }
00319       addMemberToList(MemberList::docTypedefMembers,md);
00320       break;
00321     case MemberDef::Enumeration:  
00322       if (!docOnly)
00323       {
00324         addMemberToList(MemberList::decEnumMembers,md);
00325       }
00326       addMemberToList(MemberList::docEnumMembers,md);
00327       break;
00328     case MemberDef::EnumValue:    
00329       if (!docOnly)
00330       {
00331         addMemberToList(MemberList::decEnumValMembers,md);
00332       }
00333       addMemberToList(MemberList::docEnumValMembers,md);
00334       break;
00335     case MemberDef::Prototype:    
00336       if (!docOnly)
00337       {
00338         addMemberToList(MemberList::decProtoMembers,md);
00339       }
00340       addMemberToList(MemberList::docProtoMembers,md);
00341       break;
00342     case MemberDef::Define:       
00343       if (!docOnly)
00344       {
00345         addMemberToList(MemberList::decDefineMembers,md);
00346       }
00347       addMemberToList(MemberList::docDefineMembers,md);
00348       break;
00349     case MemberDef::Signal:       
00350       if (!docOnly)
00351       {
00352         addMemberToList(MemberList::decSignalMembers,md);
00353       }
00354       addMemberToList(MemberList::docSignalMembers,md);
00355       break;
00356     case MemberDef::Slot:       
00357       if (md->protection()==Public)
00358       {
00359         if (!docOnly)
00360         {
00361           addMemberToList(MemberList::decPubSlotMembers,md);
00362         }
00363         addMemberToList(MemberList::docPubSlotMembers,md);
00364       }
00365       else if (md->protection()==Protected)
00366       {
00367         if (!docOnly)
00368         {
00369           addMemberToList(MemberList::decProSlotMembers,md);
00370         }
00371         addMemberToList(MemberList::docProSlotMembers,md);
00372       }
00373       else
00374       {
00375         if (!docOnly)
00376         {
00377           addMemberToList(MemberList::decPriSlotMembers,md);
00378         }
00379         addMemberToList(MemberList::docPriSlotMembers,md);
00380       }
00381       break;
00382     case MemberDef::Event:       
00383       if (!docOnly)
00384       {
00385         addMemberToList(MemberList::decEventMembers,md);
00386       }
00387       addMemberToList(MemberList::docEventMembers,md);
00388       break;
00389     case MemberDef::Property:       
00390       if (!docOnly)
00391       {
00392         addMemberToList(MemberList::decPropMembers,md);
00393       }
00394       addMemberToList(MemberList::docPropMembers,md);
00395       break;
00396     case MemberDef::Friend:       
00397       if (!docOnly)
00398       {
00399         addMemberToList(MemberList::decFriendMembers,md);
00400       }
00401       addMemberToList(MemberList::docFriendMembers,md);
00402       break;
00403     default:
00404       err("GroupDef::insertMembers(): "
00405            "member `%s' (typeid=%d) with scope `%s' inserted in group scope `%s'!\n",
00406            md->name().data(),md->memberType(),
00407            md->getClassDef() ? md->getClassDef()->name().data() : "",
00408            name().data());
00409   }
00410   return TRUE;
00411 }
00412 
00413 void GroupDef::removeMember(MemberDef *md)
00414 {
00415   // fprintf(stderr, "GroupDef(%s)::removeMember( %s )\n", title.data(), md->name().data());
00416   MemberNameInfo *mni = allMemberNameInfoSDict->find(md->name());
00417   if (mni)
00418   {
00419     MemberNameInfoIterator mnii(*mni);
00420     while( mnii.current() )
00421     {
00422       if( mnii.current()->memberDef == md )
00423       {
00424         mni->remove(mnii.current());
00425         break;
00426       }
00427       ++mnii;
00428     }
00429     if( mni->isEmpty() )
00430     {
00431       allMemberNameInfoSDict->remove(md->name());
00432       delete mni;
00433     }
00434 
00435     removeMemberFromList(MemberList::allMembersList,md);
00436     switch(md->memberType())
00437     {
00438       case MemberDef::Variable:
00439         removeMemberFromList(MemberList::decVarMembers,md);
00440         removeMemberFromList(MemberList::docVarMembers,md);
00441         break;
00442       case MemberDef::Function: 
00443         removeMemberFromList(MemberList::decFuncMembers,md);
00444         removeMemberFromList(MemberList::docFuncMembers,md);
00445         break;
00446       case MemberDef::Typedef:      
00447         removeMemberFromList(MemberList::decTypedefMembers,md);
00448         removeMemberFromList(MemberList::docTypedefMembers,md);
00449         break;
00450       case MemberDef::Enumeration:  
00451         removeMemberFromList(MemberList::decEnumMembers,md);
00452         removeMemberFromList(MemberList::docEnumMembers,md);
00453         break;
00454       case MemberDef::EnumValue:    
00455         removeMemberFromList(MemberList::decEnumValMembers,md);
00456         removeMemberFromList(MemberList::docEnumValMembers,md);
00457         break;
00458       case MemberDef::Prototype:    
00459         removeMemberFromList(MemberList::decProtoMembers,md);
00460         removeMemberFromList(MemberList::docProtoMembers,md);
00461         break;
00462       case MemberDef::Define:       
00463         removeMemberFromList(MemberList::decDefineMembers,md);
00464         removeMemberFromList(MemberList::docDefineMembers,md);
00465         break;
00466       case MemberDef::Signal:       
00467         removeMemberFromList(MemberList::decSignalMembers,md);
00468         removeMemberFromList(MemberList::docSignalMembers,md);
00469         break;
00470       case MemberDef::Slot:       
00471         if (md->protection()==Public)
00472         {
00473           removeMemberFromList(MemberList::decPubSlotMembers,md);
00474           removeMemberFromList(MemberList::docPubSlotMembers,md);
00475         }
00476         else if (md->protection()==Protected)
00477         {
00478           removeMemberFromList(MemberList::decProSlotMembers,md);
00479           removeMemberFromList(MemberList::docProSlotMembers,md);
00480         }
00481         else
00482         {
00483           removeMemberFromList(MemberList::decPriSlotMembers,md);
00484           removeMemberFromList(MemberList::docPriSlotMembers,md);
00485         }
00486         break;
00487       case MemberDef::Event:       
00488         removeMemberFromList(MemberList::decEventMembers,md);
00489         removeMemberFromList(MemberList::docEventMembers,md);
00490         break;
00491       case MemberDef::Property:       
00492         removeMemberFromList(MemberList::decPropMembers,md);
00493         removeMemberFromList(MemberList::docPropMembers,md);
00494         break;
00495       case MemberDef::Friend:       
00496         removeMemberFromList(MemberList::decFriendMembers,md);
00497         removeMemberFromList(MemberList::docFriendMembers,md);
00498         break;
00499       default:
00500         err("GroupDef::removeMember(): unexpected member remove in file!\n");
00501     }
00502   }
00503 }
00504 
00505 bool GroupDef::containsGroup(const GroupDef *def)
00506 {
00507     return this==def || groupList->find(def) >= 0;
00508 }
00509 
00510 void GroupDef::addGroup(const GroupDef *def)
00511 {
00512   //printf("adding group `%s' to group `%s'\n",def->name().data(),name().data());
00513   //if (Config_getBool("SORT_MEMBER_DOCS"))
00514   //  groupList->inSort(def);
00515   //else
00516   groupList->append(def);
00517 }
00518 
00519 bool GroupDef::isASubGroup() const
00520 {
00521   LockingPtr<GroupList> groups = partOfGroups();
00522   return groups!=0 && groups->count()!=0;
00523 }
00524 
00525 int GroupDef::countMembers() const
00526 {
00527   return fileList->count()+
00528          classSDict->count()+
00529          namespaceSDict->count()+
00530          groupList->count()+
00531          allMemberList->count()+
00532          pageDict->count()+
00533          exampleDict->count();
00534 }
00535 
00537 void GroupDef::computeAnchors()
00538 {
00539   //printf("GroupDef::computeAnchors()\n");
00540   setAnchors(0,'a',allMemberList);
00541 }
00542 
00543 void GroupDef::writeDetailedDocumentation(OutputList &ol)
00544 {
00545   if (!briefDescription().isEmpty() || !documentation().isEmpty())
00546   {
00547     
00548     if (pageDict->count()!=countMembers()) // classical layout
00549     {
00550       ol.writeRuler();
00551       ol.pushGeneratorState();
00552       ol.disable(OutputGenerator::Latex);
00553       ol.disable(OutputGenerator::RTF);
00554       ol.writeAnchor(0,"_details");
00555       ol.popGeneratorState();
00556       ol.startGroupHeader();
00557       ol.parseText(theTranslator->trDetailedDescription());
00558       ol.endGroupHeader();
00559 
00560       // repeat brief description
00561       if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
00562       {
00563         ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
00564         ol.newParagraph();
00565       }
00566     }
00567 
00568     // write documentation
00569     if (!documentation().isEmpty())
00570     {
00571       ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
00572     }
00573   }
00574 }
00575 
00576 
00577 void GroupDef::writeDocumentation(OutputList &ol)
00578 {
00579   bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");  
00580   bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");  
00581   ol.pushGeneratorState();
00582   startFile(ol,getOutputFileBase(),name(),title);
00583   startTitle(ol,getOutputFileBase());
00584   ol.parseText(title);
00585   addGroupListToTitle(ol,this);
00586   endTitle(ol,getOutputFileBase(),title);
00587 
00588   if (Config_getBool("SEARCHENGINE"))
00589   {
00590     Doxygen::searchIndex->setCurrentDoc(title,getOutputFileBase());
00591     static QRegExp we("[a-zA-Z_][a-zA-Z_0-9]*");
00592     int i=0,p=0,l=0;
00593     while ((i=we.match(title,p,&l))!=-1) // foreach word in the title
00594     {
00595       Doxygen::searchIndex->addWord(title.mid(i,l),TRUE);
00596       p=i+l;
00597     }
00598   }
00599 
00600   if (Config_getBool("HAVE_DOT") && Config_getBool("GROUP_GRAPHS") )
00601   {
00602     DotGroupCollaboration graph(this);
00603     if (!graph.isTrivial())
00604     {
00605       msg("Generating dependency graph for group %s\n",qualifiedName().data());
00606       ol.pushGeneratorState();
00607       ol.disable(OutputGenerator::Man);
00608       ol.newParagraph();
00609       ol.startGroupCollaboration();
00610       ol.parseText(theTranslator->trCollaborationDiagram(title));
00611       ol.endGroupCollaboration(graph);
00612       ol.popGeneratorState();
00613     }
00614   }
00615 
00616 
00617   if (Config_getBool("DETAILS_AT_TOP"))
00618   {
00619     writeDetailedDocumentation(ol);
00620     ol.newParagraph();
00621   }
00622   else if (!briefDescription().isEmpty())
00623   {
00624     ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE);
00625     ol.writeString(" \n");
00626     ol.pushGeneratorState();
00627     ol.disable(OutputGenerator::Latex);
00628     ol.disable(OutputGenerator::RTF);
00629     ol.disable(OutputGenerator::Man);
00630     ol.startTextLink(0,"_details");
00631     ol.parseText(theTranslator->trMore());
00632     ol.endTextLink();
00633     ol.enableAll();
00634     ol.disableAllBut(OutputGenerator::Man);
00635     ol.newParagraph();
00636     ol.popGeneratorState();
00637   }
00638 
00639   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00640   {
00641     Doxygen::tagFile << "  <compound kind=\"group\">" << endl;
00642     Doxygen::tagFile << "    <name>" << convertToXML(name()) << "</name>" << endl;
00643     Doxygen::tagFile << "    <title>" << convertToXML(title) << "</title>" << endl;
00644     Doxygen::tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
00645   }
00646   
00647   ol.startMemberSections();
00648 
00649   // write list of files
00650   if (fileList->count()>0)
00651   {
00652     ol.startMemberHeader();
00653     ol.parseText(theTranslator->trFile(TRUE,FALSE));
00654     ol.endMemberHeader();
00655     ol.startMemberList();
00656     FileDef *fd=fileList->first();
00657     while (fd)
00658     {
00659       ol.startMemberItem(0);
00660       ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");
00661       ol.insertMemberAlign();
00662       ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
00663       if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00664       {
00665         Doxygen::tagFile << "    <file>" << convertToXML(fd->name()) << "</file>" << endl;
00666       }
00667       ol.endMemberItem();
00668       if (!fd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
00669       {
00670         ol.startMemberDescription();
00671         ol.parseDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE);
00672         ol.endMemberDescription();
00673         ol.newParagraph();
00674       }
00675       fd=fileList->next();
00676     }
00677     ol.endMemberList();
00678   }
00679 
00680   // write list of namespaces
00681   namespaceSDict->writeDeclaration(ol);
00682 
00683   // write list of groups
00684   if (groupList->count()>0)
00685   {
00686     ol.startMemberHeader();
00687     ol.parseText(theTranslator->trModules());
00688     ol.endMemberHeader();
00689     ol.startMemberList();
00690     GroupDef *gd=groupList->first();
00691     while (gd)
00692     {
00693       ol.startMemberItem(0);
00694       //ol.docify(theTranslator->trGroup(FALSE,TRUE));
00695       //ol.docify(" ");
00696       ol.insertMemberAlign();
00697       ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),0,gd->groupTitle());
00698       if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00699       {
00700         Doxygen::tagFile << "    <subgroup>" << convertToXML(gd->name()) << "</subgroup>" << endl;
00701       }
00702       ol.endMemberItem();
00703       if (!gd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
00704       {
00705         ol.startMemberDescription();
00706         ol.parseDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE);
00707         ol.endMemberDescription();
00708         ol.newParagraph();
00709       }
00710       gd=groupList->next();
00711     }
00712     ol.endMemberList();
00713   }
00714 
00715   // write list of directories
00716   if (dirList->count()>0)
00717   {
00718     ol.startMemberHeader();
00719     ol.parseText(theTranslator->trDirectories());
00720     ol.endMemberHeader();
00721     ol.startMemberList();
00722     DirDef *dd=dirList->first();
00723     while (dd)
00724     {
00725       ol.startMemberItem(0);
00726       ol.parseText(theTranslator->trDir(FALSE,TRUE));
00727       ol.insertMemberAlign();
00728       ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),0,dd->shortName());
00729       ol.endMemberItem();
00730       if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00731       {
00732         Doxygen::tagFile << "    <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;
00733       }
00734       if (!dd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
00735       {
00736         ol.startMemberDescription();
00737         ol.parseDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE);
00738         ol.endMemberDescription();
00739         ol.newParagraph();
00740       }
00741       dd=dirList->next();
00742     }
00743 
00744     ol.endMemberList();
00745   }
00746   
00747   // write list of classes
00748   classSDict->writeDeclaration(ol);
00749 
00750   // write list of members
00751   if (allMemberList->count()>0)
00752   {
00753     /* write user defined member groups */
00754     MemberGroupSDict::Iterator mgli(*memberGroupSDict);
00755     MemberGroup *mg;
00756     for (;(mg=mgli.current());++mgli)
00757     {
00758       mg->writeDeclarations(ol,0,0,0,this);
00759     }
00760 
00761     writeMemberDeclarations(ol,MemberList::decDefineMembers,theTranslator->trDefines());
00762     writeMemberDeclarations(ol,MemberList::decProtoMembers,theTranslator->trFuncProtos());
00763     writeMemberDeclarations(ol,MemberList::decTypedefMembers,theTranslator->trTypedefs());
00764     writeMemberDeclarations(ol,MemberList::decEnumMembers,theTranslator->trEnumerations());
00765     writeMemberDeclarations(ol,MemberList::decEnumValMembers,theTranslator->trEnumerationValues());
00766     writeMemberDeclarations(ol,MemberList::decFuncMembers,
00767                  fortranOpt ? theTranslator->trSubprograms()  : 
00768                  vhdlOpt    ? VhdlDocGen::trFunctionAndProc() :
00769                               theTranslator->trFunctions());
00770     writeMemberDeclarations(ol,MemberList::decVarMembers,theTranslator->trVariables());
00771     writeMemberDeclarations(ol,MemberList::decSignalMembers,theTranslator->trSignals());
00772     writeMemberDeclarations(ol,MemberList::decPubSlotMembers,theTranslator->trPublicSlots());
00773     writeMemberDeclarations(ol,MemberList::decProSlotMembers,theTranslator->trProtectedSlots());
00774     writeMemberDeclarations(ol,MemberList::decPriSlotMembers,theTranslator->trPrivateSlots());
00775     writeMemberDeclarations(ol,MemberList::decEventMembers,theTranslator->trEvents());
00776     writeMemberDeclarations(ol,MemberList::decPropMembers,theTranslator->trProperties());
00777     writeMemberDeclarations(ol,MemberList::decFriendMembers,theTranslator->trFriends());
00778   }
00779   ol.endMemberSections();
00780 
00781   if (!Config_getBool("DETAILS_AT_TOP"))
00782   {
00783     writeDetailedDocumentation(ol);
00784   }
00785 
00786   PageDef *pd=0;
00787   PageSDict::Iterator pdi(*pageDict);
00788   for (pdi.toFirst();(pd=pdi.current());++pdi)
00789   {
00790     if (!pd->isReference())
00791     {
00792       QCString pageName = pd->getOutputFileBase();
00793 
00794       if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00795       {
00796         Doxygen::tagFile << "    <page>" << convertToXML(pageName) << "</page>" << endl;
00797       }
00798 
00799       SectionInfo *si=0;
00800       if (!pd->title().isEmpty() && !pd->name().isEmpty() &&
00801           (si=Doxygen::sectionDict[pd->name()])!=0)
00802       {
00803         ol.startSection(si->label,si->title,SectionInfo::Subsection);
00804         ol.docify(si->title);
00805         ol.endSection(si->label,SectionInfo::Subsection);
00806       }
00807       ol.startTextBlock();
00808       ol.parseDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation(),TRUE,FALSE);
00809       ol.endTextBlock();
00810     }
00811   }
00812 
00813   writeMemberDocumentation(ol);
00814 
00815   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
00816   {
00817     writeDocAnchorsToTagFile();
00818     Doxygen::tagFile << "  </compound>" << endl;
00819   }
00820 
00821   endFile(ol); 
00822   ol.popGeneratorState();
00823 
00824   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
00825   {
00826     allMemberList->sort();
00827     writeMemberPages(ol);
00828   }
00829 
00830 }
00831 
00832 void GroupDef::writeMemberDocumentation(OutputList &ol)
00833 {
00834   bool  fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
00835   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
00836   {
00837     ol.disable(OutputGenerator::Html);
00838   }
00839   
00840   writeMemberDocumentation(ol,MemberList::docDefineMembers,theTranslator->trDefineDocumentation());
00841   writeMemberDocumentation(ol,MemberList::docProtoMembers,theTranslator->trFunctionPrototypeDocumentation());
00842   writeMemberDocumentation(ol,MemberList::docTypedefMembers,theTranslator->trTypedefDocumentation());
00843   writeMemberDocumentation(ol,MemberList::docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
00844   writeMemberDocumentation(ol,MemberList::docEnumValMembers,theTranslator->trEnumerationValueDocumentation());
00845   writeMemberDocumentation(ol,MemberList::docFuncMembers,fortranOpt?theTranslator->trSubprogramDocumentation():theTranslator->trFunctionDocumentation());
00846   writeMemberDocumentation(ol,MemberList::docVarMembers,theTranslator->trVariableDocumentation());
00847   writeMemberDocumentation(ol,MemberList::docSignalMembers,theTranslator->trSignals());   // todo: add trSignalDocumentation()
00848   writeMemberDocumentation(ol,MemberList::docPubSlotMembers,theTranslator->trPublicSlots()); // todo: add trSlotDocumentation()
00849   writeMemberDocumentation(ol,MemberList::docProSlotMembers,theTranslator->trProtectedSlots()); // todo: add trSlotDocumentation()
00850   writeMemberDocumentation(ol,MemberList::docPriSlotMembers,theTranslator->trPrivateSlots()); // todo: add trSlotDocumentation()
00851   writeMemberDocumentation(ol,MemberList::docEventMembers,theTranslator->trEvents());     // todo: add trEventDocumentation()
00852   writeMemberDocumentation(ol,MemberList::docPropMembers,theTranslator->trProperties());  // todo: add trPropertyDocumentation()
00853   writeMemberDocumentation(ol,MemberList::docFriendMembers,theTranslator->trFriends());   // todo: add trFriendDocumentation()
00854 
00855   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
00856   {
00857     ol.enable(OutputGenerator::Html);
00858   }
00859 }
00860 
00861 void GroupDef::writeMemberPages(OutputList &ol)
00862 {
00863   ol.pushGeneratorState();
00864   ol.disableAllBut(OutputGenerator::Html);
00865   
00866   QListIterator<MemberList> mli(m_memberLists);
00867   MemberList *ml;
00868   for (mli.toFirst();(ml=mli.current());++mli)
00869   {
00870     if (ml->listType()&MemberList::documentationLists)
00871     {
00872        ml->writeDocumentationPage(ol,name(),this);
00873     }
00874   }
00875 #if 0
00876   docDefineMembers.writeDocumentationPage(ol,name(),this);
00877   docProtoMembers.writeDocumentationPage(ol,name(),this);
00878   docTypedefMembers.writeDocumentationPage(ol,name(),this);
00879   docEnumMembers.writeDocumentationPage(ol,name(),this);
00880   docFuncMembers.writeDocumentationPage(ol,name(),this);
00881   docVarMembers.writeDocumentationPage(ol,name(),this);
00882 #endif
00883 
00884   ol.popGeneratorState();
00885 }
00886 
00887 void GroupDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
00888 {
00889   static bool createSubDirs=Config_getBool("CREATE_SUBDIRS");
00890 
00891   ol.writeString("      <div class=\"navtab\">\n");
00892   ol.writeString("        <table>\n");
00893 
00894   MemberListIterator mli(*allMemberList);
00895   MemberDef *md;
00896   for (mli.toFirst();(md=mli.current());++mli)
00897   {
00898     if (md->getGroupDef()==this && md->isLinkable())
00899     {
00900       ol.writeString("          <tr><td class=\"navtab\">");
00901       if (md->isLinkableInProject())
00902       {
00903         if (md==currentMd) // selected item => highlight
00904         {
00905           ol.writeString("<a class=\"qindexHL\" ");
00906         }
00907         else
00908         {
00909           ol.writeString("<a class=\"qindex\" ");
00910         }
00911         ol.writeString("href=\"");
00912         if (createSubDirs) ol.writeString("../../");
00913         ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
00914         ol.writeString("\">");
00915         ol.writeString(md->localName());
00916         ol.writeString("</a>");
00917       }
00918       ol.writeString("</td></tr>\n");
00919     }
00920   }
00921 
00922   ol.writeString("        </table>\n");
00923   ol.writeString("      </div>\n");
00924 }
00925 
00926 
00927 
00928 //---- helper functions ------------------------------------------------------
00929 
00930 void addClassToGroups(Entry *root,ClassDef *cd)
00931 {
00932   QListIterator<Grouping> gli(*root->groups);
00933   Grouping *g;
00934   for (;(g=gli.current());++gli)
00935   {
00936     GroupDef *gd=0;
00937     if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
00938     {
00939       if (gd->addClass(cd)) cd->makePartOfGroup(gd);
00940       //printf("Compound %s: in group %s\n",cd->name().data(),s->data());
00941     }
00942   }
00943 }
00944 
00945 void addNamespaceToGroups(Entry *root,NamespaceDef *nd)
00946 {
00947   //printf("root->groups->count()=%d\n",root->groups->count());
00948   QListIterator<Grouping> gli(*root->groups);
00949   Grouping *g;
00950   for (;(g=gli.current());++gli)
00951   {
00952     GroupDef *gd=0;
00953     //printf("group `%s'\n",s->data());
00954     if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
00955     {
00956       if (gd->addNamespace(nd)) nd->makePartOfGroup(gd);
00957       //printf("Namespace %s: in group %s\n",nd->name().data(),s->data());
00958     }
00959   }
00960 }
00961 
00962 void addDirToGroups(Entry *root,DirDef *dd)
00963 {
00964   //printf("*** root->groups->count()=%d\n",root->groups->count());
00965   QListIterator<Grouping> gli(*root->groups);
00966   Grouping *g;
00967   for (;(g=gli.current());++gli)
00968   {
00969     GroupDef *gd=0;
00970     //printf("group `%s'\n",g->groupname.data());
00971     if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
00972     {
00973       gd->addDir(dd);
00974       dd->makePartOfGroup(gd);
00975       //printf("Dir %s: in group %s\n",dd->name().data(),g->groupname.data());
00976     }
00977   }
00978 }
00979 
00980 void addGroupToGroups(Entry *root,GroupDef *subGroup)
00981 {
00982   //printf("addGroupToGroups for %s groups=%d\n",root->name.data(),
00983   //    root->groups?root->groups->count():-1);
00984   QListIterator<Grouping> gli(*root->groups);
00985   Grouping *g;
00986   for (;(g=gli.current());++gli)
00987   {
00988     GroupDef *gd=0;
00989     if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)) &&
00990         !gd->containsGroup(subGroup) )
00991     {
00992       gd->addGroup(subGroup);
00993       subGroup->makePartOfGroup(gd);
00994     }
00995     else if (gd==subGroup)
00996     {
00997       warn(root->fileName,root->startLine,"Trying to add group %s to itself!",
00998           gd->name().data());
00999     }
01000   }
01001 }
01002 
01004 void addMemberToGroups(Entry *root,MemberDef *md)
01005 {
01006   //printf("addMemberToGroups:  Root %p = %s, md %p=%s groups=%d\n", 
01007   //    root, root->name.data(), md, md->name().data(), root->groups->count() );
01008   QListIterator<Grouping> gli(*root->groups);
01009   Grouping *g;
01010 
01011   // Search entry's group list for group with highest pri.
01012   Grouping::GroupPri_t pri = Grouping::GROUPING_LOWEST;
01013   GroupDef *fgd=0;
01014   for (;(g=gli.current());++gli)
01015   {
01016     GroupDef *gd=0;
01017     if (!g->groupname.isEmpty() &&
01018         (gd=Doxygen::groupSDict->find(g->groupname)) &&
01019         g->pri >= pri)
01020     {
01021       if (fgd && gd!=fgd && g->pri==pri) 
01022       {
01023          warn(root->fileName.data(), root->startLine,
01024            "Warning: Member %s found in multiple %s groups! "
01025            "The member will be put in group %s, and not in group %s",
01026            md->name().data(), Grouping::getGroupPriName( pri ),
01027            gd->name().data(), fgd->name().data()
01028           );
01029       }
01030 
01031       fgd = gd;
01032       pri = g->pri;
01033     }
01034   }
01035   //printf("fgd=%p\n",fgd);
01036 
01037   // put member into group defined by this entry?
01038   if (fgd)
01039   {
01040     GroupDef *mgd = md->getGroupDef();
01041     //printf("mgd=%p\n",mgd);
01042     bool insertit = FALSE;
01043     if (mgd==0)
01044     {
01045       insertit = TRUE;
01046     }
01047     else if (mgd!=fgd)
01048     {
01049       bool moveit = FALSE;
01050 
01051       // move member from one group to another if 
01052       // - the new one has a higher priority
01053       // - the new entry has the same priority, but with docs where the old one had no docs
01054       if (md->getGroupPri()<pri)
01055       {
01056         moveit = TRUE;
01057       }
01058       else
01059       {
01060         if (md->getGroupPri()==pri)
01061         {
01062           if (!root->doc.isEmpty() && !md->getGroupHasDocs())
01063           {
01064             moveit = TRUE;
01065           }
01066           else if (!root->doc.isEmpty() && md->getGroupHasDocs())
01067           {
01068             warn(md->getGroupFileName(),md->getGroupStartLine(),
01069                 "Warning: Member documentation for %s found several times in %s groups!\n"
01070                 "%s:%d: The member will remain in group %s, and won't be put into group %s",
01071                 md->name().data(), Grouping::getGroupPriName( pri ),
01072                 root->fileName.data(), root->startLine,
01073                 mgd->name().data(),
01074                 fgd->name().data()
01075                 );
01076           }
01077         }
01078       }
01079 
01080       if (moveit)
01081       {
01082         //printf("removeMember\n");
01083         mgd->removeMember(md);
01084         insertit = TRUE;
01085       }
01086     }
01087 
01088     if (insertit)
01089     {
01090       //printf("insertMember found at %s line %d\n",md->getDefFileName().data(),md->getDefLine());
01091       bool success = fgd->insertMember(md);
01092       if (success)
01093       {
01094         //printf("insertMember successful\n");
01095         md->setGroupDef(fgd,pri,root->fileName,root->startLine,
01096                         !root->doc.isEmpty());
01097         ClassDef *cd = md->getClassDefOfAnonymousType();
01098         if (cd) cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0);
01099       }
01100     }
01101   }
01102 }
01103 
01104 
01105 void addExampleToGroups(Entry *root,PageDef *eg)
01106 {
01107   QListIterator<Grouping> gli(*root->groups);
01108   Grouping *g;
01109   for (;(g=gli.current());++gli)
01110   {
01111     GroupDef *gd=0;
01112     if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
01113     {
01114       gd->addExample(eg);
01115       eg->makePartOfGroup(gd);
01116       //printf("Example %s: in group %s\n",eg->name().data(),s->data());
01117     }
01118   }
01119 }
01120 
01121 QCString GroupDef::getOutputFileBase() const 
01122 { 
01123   if (isReference())
01124   {
01125     return fileName;
01126   }
01127   else
01128   {
01129     return convertNameToFile(fileName); 
01130   }
01131 }
01132 
01133 void GroupDef::addListReferences()
01134 {
01135   {
01136     LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems();
01137     addRefItem(xrefItems.pointer(),
01138              theTranslator->trGroup(TRUE,TRUE),
01139              getOutputFileBase(),name()
01140             );
01141   }
01142   MemberGroupSDict::Iterator mgli(*memberGroupSDict);
01143   MemberGroup *mg;
01144   for (;(mg=mgli.current());++mgli)
01145   {
01146     mg->addListReferences(this);
01147   }
01148   QListIterator<MemberList> mli(m_memberLists);
01149   MemberList *ml;
01150   for (mli.toFirst();(ml=mli.current());++mli)
01151   {
01152     if (ml->listType()&MemberList::documentationLists)
01153     {
01154       ml->addListReferences(this);
01155     }
01156   }
01157 #if 0
01158   docDefineMembers.addListReferences(this);
01159   docProtoMembers.addListReferences(this);
01160   docTypedefMembers.addListReferences(this);
01161   docEnumMembers.addListReferences(this);
01162   docFuncMembers.addListReferences(this);
01163   docVarMembers.addListReferences(this);
01164 #endif
01165 }
01166 
01167 MemberList *GroupDef::createMemberList(MemberList::ListType lt)
01168 {
01169   m_memberLists.setAutoDelete(TRUE);
01170   QListIterator<MemberList> mli(m_memberLists);
01171   MemberList *ml;
01172   for (mli.toFirst();(ml=mli.current());++mli)
01173   {
01174     if (ml->listType()==lt)
01175     {
01176       return ml;
01177     }
01178   }
01179   // not found, create a new member list
01180   ml = new MemberList(lt);
01181   m_memberLists.append(ml);
01182   ml->setInGroup(TRUE);
01183   return ml;
01184 }
01185 
01186 void GroupDef::addMemberToList(MemberList::ListType lt,MemberDef *md)
01187 {
01188   static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
01189   static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS");
01190   MemberList *ml = createMemberList(lt);
01191   if (((ml->listType()&MemberList::declarationLists) && sortBriefDocs) ||
01192       ((ml->listType()&MemberList::documentationLists) && sortMemberDocs)
01193      )
01194     ml->inSort(md);
01195   else
01196     ml->append(md);
01197 }
01198 
01199 MemberList *GroupDef::getMemberList(MemberList::ListType lt) const
01200 {
01201   GroupDef *that = (GroupDef*)this;
01202   MemberList *ml = that->m_memberLists.first();
01203   while (ml)
01204   {
01205     if (ml->listType()==lt)
01206     {
01207       return ml;
01208     }
01209     ml = that->m_memberLists.next();
01210   }
01211   return 0;
01212 }
01213 
01214 void GroupDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title)
01215 {
01216   MemberList * ml = getMemberList(lt);
01217   if (ml) ml->writeDeclarations(ol,0,0,0,this,title,0);
01218 }
01219 
01220 void GroupDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title)
01221 {
01222   MemberList * ml = getMemberList(lt);
01223   if (ml) ml->writeDocumentation(ol,name(),this,title);
01224 }
01225 
01226 void GroupDef::removeMemberFromList(MemberList::ListType lt,MemberDef *md)
01227 {
01228     MemberList *ml = getMemberList(lt);
01229     if (ml) ml->remove(md); 
01230 }
01231 



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