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