diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-08 06:36:54 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-08 06:36:54 -0800 |
commit | cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb (patch) | |
tree | 7f31b77ace4359e85dc3d3f66c853858c0bca7a4 /src/groupdef.cpp | |
download | doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.tar.gz doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.tar.bz2 doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.zip |
Imported Upstream version 1.8.2upstream/1.8.2
Diffstat (limited to 'src/groupdef.cpp')
-rw-r--r-- | src/groupdef.cpp | 1506 |
1 files changed, 1506 insertions, 0 deletions
diff --git a/src/groupdef.cpp b/src/groupdef.cpp new file mode 100644 index 0000000..0174077 --- /dev/null +++ b/src/groupdef.cpp @@ -0,0 +1,1506 @@ +/****************************************************************************** + * + * $Id: groupdef.cpp,v 1.29 2001/03/19 19:27:40 root Exp $ + * + * Copyright (C) 1997-2012 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#include <ctype.h> +#include <qregexp.h> +#include "qtbc.h" +#include "groupdef.h" +#include "classdef.h" +#include "filedef.h" +#include "classlist.h" +#include "outputlist.h" +#include "namespacedef.h" +#include "language.h" +#include "util.h" +#include "memberlist.h" +#include "message.h" +#include "membergroup.h" +#include "doxygen.h" +#include "pagedef.h" +#include "docparser.h" +#include "searchindex.h" +#include "dot.h" +#include "vhdldocgen.h" +#include "layout.h" +#include "arguments.h" +#include "entry.h" + +//--------------------------------------------------------------------------- + +GroupDef::GroupDef(const char *df,int dl,const char *na,const char *t, + const char *refFileName) : Definition(df,dl,na) +{ + fileList = new FileList; + classSDict = new ClassSDict(17); + groupList = new GroupList; + namespaceSDict = new NamespaceSDict(17); + pageDict = new PageSDict(17); + exampleDict = new PageSDict(17); + dirList = new DirList; + allMemberNameInfoSDict = new MemberNameInfoSDict(17); + if (refFileName) + { + fileName=stripExtension(refFileName); + } + else + { + fileName = (QCString)"group_"+na; + } + setGroupTitle( t ); + memberGroupSDict = new MemberGroupSDict; + memberGroupSDict->setAutoDelete(TRUE); + + allMemberList = new MemberList(MemberList::allMembersList); + + visited = 0; + groupScope = 0; +} + +GroupDef::~GroupDef() +{ + delete fileList; + delete classSDict; + delete groupList; + delete namespaceSDict; + delete pageDict; + delete exampleDict; + delete allMemberList; + delete allMemberNameInfoSDict; + delete memberGroupSDict; + delete dirList; +} + +void GroupDef::setGroupTitle( const char *t ) +{ + if ( t && strlen(t) ) + { + title = t; + titleSet = TRUE; + } + else + { + title = name(); + title.at(0)=toupper(title.at(0)); + titleSet = FALSE; + } +} + + +void GroupDef::distributeMemberGroupDocumentation() +{ + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->distributeMemberGroupDocumentation(); + } +} + +void GroupDef::findSectionsInDocumentation() +{ + docFindSections(documentation(),this,0,docFile()); + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->findSectionsInDocumentation(); + } + + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()&MemberList::declarationLists) + { + ml->findSectionsInDocumentation(); + } + } +} + +void GroupDef::addFile(const FileDef *def) +{ + static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); + if (def->isHidden()) return; + updateLanguage(def); + if (sortBriefDocs) + fileList->inSort(def); + else + fileList->append(def); +} + +bool GroupDef::addClass(const ClassDef *cd) +{ + static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); + if (cd->isHidden()) return FALSE; + updateLanguage(cd); + if (classSDict->find(cd->qualifiedName())==0) + { + QCString qn = cd->qualifiedName(); + //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs); + if (sortBriefDocs) + { + classSDict->inSort(cd->qualifiedName(),cd); + } + else + { + int i=qn.findRev("::"); + if (i==-1) i=qn.find('.'); + bool found=FALSE; + //printf("i=%d\n",i); + if (i!=-1) + { + // add nested classes (e.g. A::B, A::C) after their parent (A) in + // order of insertion + QCString scope = qn.left(i); + int j=classSDict->findAt(scope); + if (j!=-1) + { + while (j<(int)classSDict->count() && + classSDict->at(j)->qualifiedName().left(i)==scope) + { + //printf("skipping over %s\n",classSDict->at(j)->qualifiedName().data()); + j++; + } + //printf("Found scope at index %d\n",j); + classSDict->insertAt(j,cd->qualifiedName(),cd); + found=TRUE; + } + } + if (!found) // no insertion point found -> just append + { + classSDict->append(cd->qualifiedName(),cd); + } + } + return TRUE; + } + return FALSE; +} + +bool GroupDef::addNamespace(const NamespaceDef *def) +{ + static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); + if (def->isHidden()) return FALSE; + updateLanguage(def); + if (namespaceSDict->find(def->name())==0) + { + if (sortBriefDocs) + namespaceSDict->inSort(def->name(),def); + else + namespaceSDict->append(def->name(),def); + return TRUE; + } + return FALSE; +} + +void GroupDef::addDir(const DirDef *def) +{ + if (def->isHidden()) return; + if (Config_getBool("SORT_BRIEF_DOCS")) + dirList->inSort(def); + else + dirList->append(def); +} + +void GroupDef::addPage(PageDef *def) +{ + if (def->isHidden()) return; + //printf("Making page %s part of a group\n",def->name.data()); + pageDict->append(def->name(),def); + def->makePartOfGroup(this); +} + +void GroupDef::addExample(const PageDef *def) +{ + if (def->isHidden()) return; + exampleDict->append(def->name(),def); +} + + +void GroupDef::addMembersToMemberGroup() +{ + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()&MemberList::declarationLists) + { + ::addMembersToMemberGroup(ml,&memberGroupSDict,this); + } + } + + //printf("GroupDef::addMembersToMemberGroup() memberGroupList=%d\n",memberGroupList->count()); + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->setInGroup(TRUE); + } +} + + +bool GroupDef::insertMember(MemberDef *md,bool docOnly) +{ + if (md->isHidden()) return FALSE; + updateLanguage(md); + //printf("GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data()); + MemberNameInfo *mni=0; + if ((mni=(*allMemberNameInfoSDict)[md->name()])) + { // member with this name already found + MemberNameInfoIterator srcMnii(*mni); + MemberInfo *srcMi; + for ( ; (srcMi=srcMnii.current()) ; ++srcMnii ) + { + MemberDef *srcMd = srcMi->memberDef; + if (srcMd==md) return FALSE; // already added before! + + bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace + // both inside a file => definition and declaration do not have to be in the same file + (srcMd->getOuterScope()->definitionType()==Definition::TypeFile && + md->getOuterScope()->definitionType()==Definition::TypeFile); + + LockingPtr<ArgumentList> srcMdAl = srcMd->argumentList(); + LockingPtr<ArgumentList> mdAl = md->argumentList(); + LockingPtr<ArgumentList> tSrcMdAl = srcMd->templateArguments(); + LockingPtr<ArgumentList> tMdAl = md->templateArguments(); + + if (srcMd->isFunction() && md->isFunction() && // both are a function + ((tSrcMdAl.pointer()==0 && tMdAl.pointer()==0) || + (tSrcMdAl.pointer()!=0 && tMdAl.pointer()!=0 && tSrcMdAl->count()==tMdAl->count()) + ) && // same number of template arguments + matchArguments2(srcMd->getOuterScope(),srcMd->getFileDef(),srcMdAl.pointer(), + md->getOuterScope(),md->getFileDef(),mdAl.pointer(), + TRUE + ) && // matching parameters + sameScope // both are found in the same scope + ) + { + if (srcMd->getGroupAlias()==0) + { + md->setGroupAlias(srcMd); + } + else + { + md->setGroupAlias(srcMd->getGroupAlias()); + } + return FALSE; // member is the same as one that is already added + } + } + mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE)); + } + else + { + mni = new MemberNameInfo(md->name()); + mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE)); + allMemberNameInfoSDict->append(mni->memberName(),mni); + } + //printf("Added member!\n"); + allMemberList->append(md); + switch(md->memberType()) + { + case MemberDef::Variable: + if (!docOnly) + { + addMemberToList(MemberList::decVarMembers,md); + } + addMemberToList(MemberList::docVarMembers,md); + break; + case MemberDef::Function: + if (!docOnly) + { + addMemberToList(MemberList::decFuncMembers,md); + } + addMemberToList(MemberList::docFuncMembers,md); + break; + case MemberDef::Typedef: + if (!docOnly) + { + addMemberToList(MemberList::decTypedefMembers,md); + } + addMemberToList(MemberList::docTypedefMembers,md); + break; + case MemberDef::Enumeration: + if (!docOnly) + { + addMemberToList(MemberList::decEnumMembers,md); + } + addMemberToList(MemberList::docEnumMembers,md); + break; + case MemberDef::EnumValue: + if (!docOnly) + { + addMemberToList(MemberList::decEnumValMembers,md); + } + addMemberToList(MemberList::docEnumValMembers,md); + break; + case MemberDef::Define: + if (!docOnly) + { + addMemberToList(MemberList::decDefineMembers,md); + } + addMemberToList(MemberList::docDefineMembers,md); + break; + case MemberDef::Signal: + if (!docOnly) + { + addMemberToList(MemberList::decSignalMembers,md); + } + addMemberToList(MemberList::docSignalMembers,md); + break; + case MemberDef::Slot: + if (md->protection()==Public) + { + if (!docOnly) + { + addMemberToList(MemberList::decPubSlotMembers,md); + } + addMemberToList(MemberList::docPubSlotMembers,md); + } + else if (md->protection()==Protected) + { + if (!docOnly) + { + addMemberToList(MemberList::decProSlotMembers,md); + } + addMemberToList(MemberList::docProSlotMembers,md); + } + else + { + if (!docOnly) + { + addMemberToList(MemberList::decPriSlotMembers,md); + } + addMemberToList(MemberList::docPriSlotMembers,md); + } + break; + case MemberDef::Event: + if (!docOnly) + { + addMemberToList(MemberList::decEventMembers,md); + } + addMemberToList(MemberList::docEventMembers,md); + break; + case MemberDef::Property: + if (!docOnly) + { + addMemberToList(MemberList::decPropMembers,md); + } + addMemberToList(MemberList::docPropMembers,md); + break; + case MemberDef::Friend: + if (!docOnly) + { + addMemberToList(MemberList::decFriendMembers,md); + } + addMemberToList(MemberList::docFriendMembers,md); + break; + default: + err("GroupDef::insertMembers(): " + "member `%s' (typeid=%d) with scope `%s' inserted in group scope `%s'!\n", + md->name().data(),md->memberType(), + md->getClassDef() ? md->getClassDef()->name().data() : "", + name().data()); + } + return TRUE; +} + +void GroupDef::removeMember(MemberDef *md) +{ + // fprintf(stderr, "GroupDef(%s)::removeMember( %s )\n", title.data(), md->name().data()); + MemberNameInfo *mni = allMemberNameInfoSDict->find(md->name()); + if (mni) + { + MemberNameInfoIterator mnii(*mni); + while( mnii.current() ) + { + if( mnii.current()->memberDef == md ) + { + mni->remove(mnii.current()); + break; + } + ++mnii; + } + if( mni->isEmpty() ) + { + allMemberNameInfoSDict->remove(md->name()); + delete mni; + } + + removeMemberFromList(MemberList::allMembersList,md); + switch(md->memberType()) + { + case MemberDef::Variable: + removeMemberFromList(MemberList::decVarMembers,md); + removeMemberFromList(MemberList::docVarMembers,md); + break; + case MemberDef::Function: + removeMemberFromList(MemberList::decFuncMembers,md); + removeMemberFromList(MemberList::docFuncMembers,md); + break; + case MemberDef::Typedef: + removeMemberFromList(MemberList::decTypedefMembers,md); + removeMemberFromList(MemberList::docTypedefMembers,md); + break; + case MemberDef::Enumeration: + removeMemberFromList(MemberList::decEnumMembers,md); + removeMemberFromList(MemberList::docEnumMembers,md); + break; + case MemberDef::EnumValue: + removeMemberFromList(MemberList::decEnumValMembers,md); + removeMemberFromList(MemberList::docEnumValMembers,md); + break; + case MemberDef::Define: + removeMemberFromList(MemberList::decDefineMembers,md); + removeMemberFromList(MemberList::docDefineMembers,md); + break; + case MemberDef::Signal: + removeMemberFromList(MemberList::decSignalMembers,md); + removeMemberFromList(MemberList::docSignalMembers,md); + break; + case MemberDef::Slot: + if (md->protection()==Public) + { + removeMemberFromList(MemberList::decPubSlotMembers,md); + removeMemberFromList(MemberList::docPubSlotMembers,md); + } + else if (md->protection()==Protected) + { + removeMemberFromList(MemberList::decProSlotMembers,md); + removeMemberFromList(MemberList::docProSlotMembers,md); + } + else + { + removeMemberFromList(MemberList::decPriSlotMembers,md); + removeMemberFromList(MemberList::docPriSlotMembers,md); + } + break; + case MemberDef::Event: + removeMemberFromList(MemberList::decEventMembers,md); + removeMemberFromList(MemberList::docEventMembers,md); + break; + case MemberDef::Property: + removeMemberFromList(MemberList::decPropMembers,md); + removeMemberFromList(MemberList::docPropMembers,md); + break; + case MemberDef::Friend: + removeMemberFromList(MemberList::decFriendMembers,md); + removeMemberFromList(MemberList::docFriendMembers,md); + break; + default: + err("GroupDef::removeMember(): unexpected member remove in file!\n"); + } + } +} + +bool GroupDef::containsGroup(const GroupDef *def) +{ + return this==def || groupList->find(def) >= 0; +} + +void GroupDef::addGroup(const GroupDef *def) +{ + //printf("adding group `%s' to group `%s'\n",def->name().data(),name().data()); + //if (Config_getBool("SORT_MEMBER_DOCS")) + // groupList->inSort(def); + //else + groupList->append(def); +} + +bool GroupDef::isASubGroup() const +{ + LockingPtr<GroupList> groups = partOfGroups(); + return groups!=0 && groups->count()!=0; +} + +int GroupDef::countMembers() const +{ + return fileList->count()+ + classSDict->count()+ + namespaceSDict->count()+ + groupList->count()+ + allMemberList->count()+ + pageDict->count()+ + exampleDict->count(); +} + +/*! Compute the HTML anchor names for all members in the group */ +void GroupDef::computeAnchors() +{ + //printf("GroupDef::computeAnchors()\n"); + setAnchors(0,'a',allMemberList); +} + +void GroupDef::writeDetailedDescription(OutputList &ol,const QCString &title) +{ + if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) + || !documentation().isEmpty() || !inbodyDocumentation().isEmpty() + ) + { + if (pageDict->count()!=countMembers()) // not only pages -> classical layout + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + ol.writeRuler(); + ol.popGeneratorState(); + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + ol.writeAnchor(0,"details"); + ol.popGeneratorState(); + ol.startGroupHeader(); + ol.parseText(title); + ol.endGroupHeader(); + } + + // repeat brief description + if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) + { + ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); + } + // write separator between brief and details + if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") && + !documentation().isEmpty()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::RTF); + // ol.newParagraph(); // FIXME:PARA + ol.enableAll(); + ol.disableAllBut(OutputGenerator::Man); + ol.writeString("\n\n"); + ol.popGeneratorState(); + } + + // write detailed documentation + if (!documentation().isEmpty()) + { + ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + } + + // write inbody documentation + if (!inbodyDocumentation().isEmpty()) + { + ol.parseDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE); + } + } +} + +void GroupDef::writeBriefDescription(OutputList &ol) +{ + if (!briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC")) + { + ol.startParagraph(); + ol.parseDoc(briefFile(),briefLine(),this,0, + briefDescription(),TRUE,FALSE,0,TRUE,FALSE); + ol.pushGeneratorState(); + ol.disable(OutputGenerator::RTF); + ol.writeString(" \n"); + ol.enable(OutputGenerator::RTF); + + if (Config_getBool("REPEAT_BRIEF") || + !documentation().isEmpty() + ) + { + ol.disableAllBut(OutputGenerator::Html); + ol.startTextLink(0,"details"); + ol.parseText(theTranslator->trMore()); + ol.endTextLink(); + } + ol.popGeneratorState(); + ol.endParagraph(); + } +} + +void GroupDef::writeGroupGraph(OutputList &ol) +{ + if (Config_getBool("HAVE_DOT") /*&& Config_getBool("GROUP_GRAPHS")*/ ) + { + DotGroupCollaboration graph(this); + if (!graph.isTrivial()) + { + msg("Generating dependency graph for group %s\n",qualifiedName().data()); + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + //ol.startParagraph(); + ol.startGroupCollaboration(); + ol.parseText(theTranslator->trCollaborationDiagram(title)); + ol.endGroupCollaboration(graph); + //ol.endParagraph(); + ol.popGeneratorState(); + } + } +} + +void GroupDef::writeFiles(OutputList &ol,const QCString &title) +{ + // write list of files + if (fileList->count()>0) + { + ol.startMemberHeader("files"); + ol.parseText(title); + ol.endMemberHeader(); + ol.startMemberList(); + FileDef *fd=fileList->first(); + while (fd) + { + ol.startMemberDeclaration(); + ol.startMemberItem(fd->getOutputFileBase(),0); + ol.docify(theTranslator->trFile(FALSE,TRUE)+" "); + ol.insertMemberAlign(); + ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name()); + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <file>" << convertToXML(fd->name()) << "</file>" << endl; + } + ol.endMemberItem(); + if (!fd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC")) + { + ol.startMemberDescription(fd->getOutputFileBase()); + ol.parseDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.endMemberDescription(); + } + ol.endMemberDeclaration(0,0); + fd=fileList->next(); + } + ol.endMemberList(); + } +} + +void GroupDef::writeNamespaces(OutputList &ol,const QCString &title) +{ + // write list of namespaces + namespaceSDict->writeDeclaration(ol,title); +} + +void GroupDef::writeNestedGroups(OutputList &ol,const QCString &title) +{ + // write list of groups + int count=0; + if (groupList->count()>0) + { + GroupDef *gd=groupList->first(); + while (gd) + { + if (gd->isVisible()) count++; + gd=groupList->next(); + } + } + if (count>0) + { + ol.startMemberHeader("groups"); + ol.parseText(title); + ol.endMemberHeader(); + ol.startMemberList(); + if (Config_getBool("SORT_GROUP_NAMES")) + { + groupList->sort(); + } + GroupDef *gd=groupList->first(); + while (gd) + { + if (gd->isVisible()) + { + ol.startMemberDeclaration(); + ol.startMemberItem(gd->getOutputFileBase(),0); + //ol.docify(theTranslator->trGroup(FALSE,TRUE)); + //ol.docify(" "); + ol.insertMemberAlign(); + ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),0,gd->groupTitle()); + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <subgroup>" << convertToXML(gd->name()) << "</subgroup>" << endl; + } + ol.endMemberItem(); + if (!gd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC")) + { + ol.startMemberDescription(gd->getOutputFileBase()); + ol.parseDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.endMemberDescription(); + } + ol.endMemberDeclaration(0,0); + } + gd=groupList->next(); + } + ol.endMemberList(); + } +} + +void GroupDef::writeDirs(OutputList &ol,const QCString &title) +{ + // write list of directories + if (dirList->count()>0) + { + ol.startMemberHeader("dirs"); + ol.parseText(title); + ol.endMemberHeader(); + ol.startMemberList(); + DirDef *dd=dirList->first(); + while (dd) + { + ol.startMemberDeclaration(); + ol.startMemberItem(dd->getOutputFileBase(),0); + ol.parseText(theTranslator->trDir(FALSE,TRUE)); + ol.insertMemberAlign(); + ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),0,dd->shortName()); + ol.endMemberItem(); + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl; + } + if (!dd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC")) + { + ol.startMemberDescription(dd->getOutputFileBase()); + ol.parseDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE); + ol.endMemberDescription(); + } + ol.endMemberDeclaration(0,0); + dd=dirList->next(); + } + + ol.endMemberList(); + } +} + +void GroupDef::writeClasses(OutputList &ol,const QCString &title) +{ + // write list of classes + classSDict->writeDeclaration(ol,0,title,FALSE); +} + +void GroupDef::writeInlineClasses(OutputList &ol) +{ + classSDict->writeDocumentation(ol); +} + +void GroupDef::writePageDocumentation(OutputList &ol) +{ + PageDef *pd=0; + PageSDict::Iterator pdi(*pageDict); + for (pdi.toFirst();(pd=pdi.current());++pdi) + { + if (!pd->isReference()) + { + QCString pageName = pd->getOutputFileBase(); + + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <page>" << convertToXML(pageName) << "</page>" << endl; + } + + SectionInfo *si=0; + if (!pd->title().isEmpty() && !pd->name().isEmpty() && + (si=Doxygen::sectionDict[pd->name()])!=0) + { + ol.startSection(si->label,si->title,SectionInfo::Subsection); + ol.docify(si->title); + ol.endSection(si->label,SectionInfo::Subsection); + } + ol.startTextBlock(); + ol.parseDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE,0,TRUE,FALSE); + ol.endTextBlock(); + } + } +} + +void GroupDef::writeMemberGroups(OutputList &ol) +{ + /* write user defined member groups */ + if (memberGroupSDict) + { + memberGroupSDict->sort(); + /* write user defined member groups */ + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->writeDeclarations(ol,0,0,0,this); + } + } +} + +void GroupDef::startMemberDeclarations(OutputList &ol) +{ + ol.startMemberSections(); +} + +void GroupDef::endMemberDeclarations(OutputList &ol) +{ + ol.endMemberSections(); +} + +void GroupDef::startMemberDocumentation(OutputList &ol) +{ + //printf("** GroupDef::startMemberDocumentation()\n"); + if (Config_getBool("SEPARATE_MEMBER_PAGES")) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + Doxygen::suppressDocWarnings = TRUE; + } +} + +void GroupDef::endMemberDocumentation(OutputList &ol) +{ + //printf("** GroupDef::endMemberDocumentation()\n"); + if (Config_getBool("SEPARATE_MEMBER_PAGES")) + { + ol.popGeneratorState(); + Doxygen::suppressDocWarnings = FALSE; + } +} + +void GroupDef::writeAuthorSection(OutputList &ol) +{ + // write Author section (Man only) + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Man); + ol.startGroupHeader(); + ol.parseText(theTranslator->trAuthor(TRUE,TRUE)); + ol.endGroupHeader(); + ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME"))); + ol.popGeneratorState(); +} + +void GroupDef::writeSummaryLinks(OutputList &ol) +{ + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Group)); + LayoutDocEntry *lde; + bool first=TRUE; + SrcLangExt lang = getLanguage(); + for (eli.toFirst();(lde=eli.current());++eli) + { + if ((lde->kind()==LayoutDocEntry::GroupClasses && classSDict->declVisible()) || + (lde->kind()==LayoutDocEntry::GroupNamespaces && namespaceSDict->declVisible()) || + (lde->kind()==LayoutDocEntry::GroupFiles && fileList->count()>0) || + (lde->kind()==LayoutDocEntry::GroupNestedGroups && groupList->count()>0) || + (lde->kind()==LayoutDocEntry::GroupDirs && dirList->count()>0) + ) + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" : + lde->kind()==LayoutDocEntry::GroupNamespaces ? "namespaces" : + lde->kind()==LayoutDocEntry::GroupFiles ? "files" : + lde->kind()==LayoutDocEntry::GroupNestedGroups ? "groups" : + "dirs"; + ol.writeSummaryLink(0,label,ls->title(lang),first); + first=FALSE; + } + else if (lde->kind()==LayoutDocEntry::MemberDecl) + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + MemberList * ml = getMemberList(lmd->type); + if (ml && ml->declVisible()) + { + ol.writeSummaryLink(0,ml->listTypeAsString(),lmd->title(lang),first); + first=FALSE; + } + } + } + if (!first) + { + ol.writeString(" </div>\n"); + } + ol.popGeneratorState(); +} + +void GroupDef::writeDocumentation(OutputList &ol) +{ + //static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW"); + ol.pushGeneratorState(); + startFile(ol,getOutputFileBase(),name(),title,HLI_None); + + ol.startHeaderSection(); + writeSummaryLinks(ol); + ol.startTitleHead(getOutputFileBase()); + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.parseText(title); + ol.popGeneratorState(); + ol.endTitleHead(getOutputFileBase(),title); + addGroupListToTitle(ol,this); + ol.endHeaderSection(); + ol.startContents(); + + if (Doxygen::searchIndex) + { + Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); + static QRegExp we("[a-zA-Z_][-a-zA-Z_0-9]*"); + int i=0,p=0,l=0; + while ((i=we.match(title,p,&l))!=-1) // foreach word in the title + { + Doxygen::searchIndex->addWord(title.mid(i,l),TRUE); + p=i+l; + } + } + + Doxygen::indexList.addIndexItem(this,0,title); + + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <compound kind=\"group\">" << endl; + Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; + Doxygen::tagFile << " <title>" << convertToXML(title) << "</title>" << endl; + Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl; + } + + + //---------------------------------------- start flexible part ------------------------------- + + SrcLangExt lang=getLanguage(); + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Group)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + switch (lde->kind()) + { + case LayoutDocEntry::BriefDesc: + writeBriefDescription(ol); + break; + case LayoutDocEntry::MemberDeclStart: + startMemberDeclarations(ol); + break; + case LayoutDocEntry::GroupClasses: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeClasses(ol,ls->title(lang)); + } + break; + case LayoutDocEntry::GroupInlineClasses: + { + writeInlineClasses(ol); + } + break; + case LayoutDocEntry::GroupNamespaces: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeNamespaces(ol,ls->title(lang)); + } + break; + case LayoutDocEntry::MemberGroups: + writeMemberGroups(ol); + break; + case LayoutDocEntry::MemberDecl: + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + writeMemberDeclarations(ol,lmd->type,lmd->title(lang)); + } + break; + case LayoutDocEntry::MemberDeclEnd: + endMemberDeclarations(ol); + break; + case LayoutDocEntry::DetailedDesc: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeDetailedDescription(ol,ls->title(lang)); + } + break; + case LayoutDocEntry::MemberDefStart: + startMemberDocumentation(ol); + break; + case LayoutDocEntry::MemberDef: + { + LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; + writeMemberDocumentation(ol,lmd->type,lmd->title(lang)); + } + break; + case LayoutDocEntry::MemberDefEnd: + endMemberDocumentation(ol); + break; + case LayoutDocEntry::GroupNestedGroups: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeNestedGroups(ol,ls->title(lang)); + } + break; + case LayoutDocEntry::GroupPageDocs: + writePageDocumentation(ol); + break; + case LayoutDocEntry::GroupDirs: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeDirs(ol,ls->title(lang)); + } + break; + case LayoutDocEntry::GroupFiles: + { + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeFiles(ol,ls->title(lang)); + } + break; + case LayoutDocEntry::GroupGraph: + writeGroupGraph(ol); + break; + case LayoutDocEntry::AuthorSection: + writeAuthorSection(ol); + break; + case LayoutDocEntry::ClassIncludes: + case LayoutDocEntry::ClassInheritanceGraph: + case LayoutDocEntry::ClassNestedClasses: + case LayoutDocEntry::ClassCollaborationGraph: + case LayoutDocEntry::ClassAllMembersLink: + case LayoutDocEntry::ClassUsedFiles: + case LayoutDocEntry::ClassInlineClasses: + case LayoutDocEntry::NamespaceNestedNamespaces: + case LayoutDocEntry::NamespaceClasses: + case LayoutDocEntry::NamespaceInlineClasses: + case LayoutDocEntry::FileClasses: + case LayoutDocEntry::FileNamespaces: + case LayoutDocEntry::FileIncludes: + case LayoutDocEntry::FileIncludeGraph: + case LayoutDocEntry::FileIncludedByGraph: + case LayoutDocEntry::FileSourceLink: + case LayoutDocEntry::FileInlineClasses: + case LayoutDocEntry::DirSubDirs: + case LayoutDocEntry::DirFiles: + case LayoutDocEntry::DirGraph: + err("Internal inconsistency: member %d should not be part of " + "LayoutDocManager::Group entry list\n",lde->kind()); + break; + } + } + + //---------------------------------------- end flexible part ------------------------------- + + endFile(ol); + + ol.popGeneratorState(); + + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + writeDocAnchorsToTagFile(); + Doxygen::tagFile << " </compound>" << endl; + } + + if (Config_getBool("SEPARATE_MEMBER_PAGES")) + { + allMemberList->sort(); + writeMemberPages(ol); + } + +} + +void GroupDef::writeMemberPages(OutputList &ol) +{ + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()&MemberList::documentationLists) + { + ml->writeDocumentationPage(ol,name(),this); + } + } + + ol.popGeneratorState(); +} + +void GroupDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const +{ + static bool createSubDirs=Config_getBool("CREATE_SUBDIRS"); + + ol.writeString(" <div class=\"navtab\">\n"); + ol.writeString(" <table>\n"); + + MemberListIterator mli(*allMemberList); + MemberDef *md; + for (mli.toFirst();(md=mli.current());++mli) + { + if (md->getGroupDef()==this && md->isLinkable()) + { + ol.writeString(" <tr><td class=\"navtab\">"); + if (md->isLinkableInProject()) + { + if (md==currentMd) // selected item => highlight + { + ol.writeString("<a class=\"qindexHL\" "); + } + else + { + ol.writeString("<a class=\"qindex\" "); + } + ol.writeString("href=\""); + if (createSubDirs) ol.writeString("../../"); + ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); + ol.writeString("\">"); + ol.writeString(convertToHtml(md->localName())); + ol.writeString("</a>"); + } + ol.writeString("</td></tr>\n"); + } + } + + ol.writeString(" </table>\n"); + ol.writeString(" </div>\n"); +} + + + +//---- helper functions ------------------------------------------------------ + +void addClassToGroups(Entry *root,ClassDef *cd) +{ + QListIterator<Grouping> gli(*root->groups); + Grouping *g; + for (;(g=gli.current());++gli) + { + GroupDef *gd=0; + if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname))) + { + if (gd->addClass(cd)) + { + cd->makePartOfGroup(gd); + } + //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle()); + } + } +} + +void addNamespaceToGroups(Entry *root,NamespaceDef *nd) +{ + //printf("root->groups->count()=%d\n",root->groups->count()); + QListIterator<Grouping> gli(*root->groups); + Grouping *g; + for (;(g=gli.current());++gli) + { + GroupDef *gd=0; + //printf("group `%s'\n",s->data()); + if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname))) + { + if (gd->addNamespace(nd)) nd->makePartOfGroup(gd); + //printf("Namespace %s: in group %s\n",nd->name().data(),s->data()); + } + } +} + +void addDirToGroups(Entry *root,DirDef *dd) +{ + //printf("*** root->groups->count()=%d\n",root->groups->count()); + QListIterator<Grouping> gli(*root->groups); + Grouping *g; + for (;(g=gli.current());++gli) + { + GroupDef *gd=0; + //printf("group `%s'\n",g->groupname.data()); + if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname))) + { + gd->addDir(dd); + dd->makePartOfGroup(gd); + //printf("Dir %s: in group %s\n",dd->name().data(),g->groupname.data()); + } + } +} + +void addGroupToGroups(Entry *root,GroupDef *subGroup) +{ + //printf("addGroupToGroups for %s groups=%d\n",root->name.data(), + // root->groups?root->groups->count():-1); + QListIterator<Grouping> gli(*root->groups); + Grouping *g; + for (;(g=gli.current());++gli) + { + GroupDef *gd=0; + if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)) && + !gd->containsGroup(subGroup) ) + { + gd->addGroup(subGroup); + subGroup->makePartOfGroup(gd); + } + else if (gd==subGroup) + { + warn(root->fileName,root->startLine,"Trying to add group %s to itself!", + gd->name().data()); + } + } +} + +/*! Add a member to the group with the highest priority */ +void addMemberToGroups(Entry *root,MemberDef *md) +{ + //printf("addMemberToGroups: Root %p = %s, md %p=%s groups=%d\n", + // root, root->name.data(), md, md->name().data(), root->groups->count() ); + QListIterator<Grouping> gli(*root->groups); + Grouping *g; + + // Search entry's group list for group with highest pri. + Grouping::GroupPri_t pri = Grouping::GROUPING_LOWEST; + GroupDef *fgd=0; + for (;(g=gli.current());++gli) + { + GroupDef *gd=0; + if (!g->groupname.isEmpty() && + (gd=Doxygen::groupSDict->find(g->groupname)) && + g->pri >= pri) + { + if (fgd && gd!=fgd && g->pri==pri) + { + warn(root->fileName.data(), root->startLine, + "warning: Member %s found in multiple %s groups! " + "The member will be put in group %s, and not in group %s", + md->name().data(), Grouping::getGroupPriName( pri ), + gd->name().data(), fgd->name().data() + ); + } + + fgd = gd; + pri = g->pri; + } + } + //printf("fgd=%p\n",fgd); + + // put member into group defined by this entry? + if (fgd) + { + GroupDef *mgd = md->getGroupDef(); + //printf("mgd=%p\n",mgd); + bool insertit = FALSE; + if (mgd==0) + { + insertit = TRUE; + } + else if (mgd!=fgd) + { + bool moveit = FALSE; + + // move member from one group to another if + // - the new one has a higher priority + // - the new entry has the same priority, but with docs where the old one had no docs + if (md->getGroupPri()<pri) + { + moveit = TRUE; + } + else + { + if (md->getGroupPri()==pri) + { + if (!root->doc.isEmpty() && !md->getGroupHasDocs()) + { + moveit = TRUE; + } + else if (!root->doc.isEmpty() && md->getGroupHasDocs()) + { + warn(md->getGroupFileName(),md->getGroupStartLine(), + "warning: Member documentation for %s found several times in %s groups!\n" + "%s:%d: The member will remain in group %s, and won't be put into group %s", + md->name().data(), Grouping::getGroupPriName( pri ), + root->fileName.data(), root->startLine, + mgd->name().data(), + fgd->name().data() + ); + } + } + } + + if (moveit) + { + //printf("removeMember\n"); + mgd->removeMember(md); + insertit = TRUE; + } + } + + if (insertit) + { + //printf("insertMember found at %s line %d: %s: related %s\n", + // md->getDefFileName().data(),md->getDefLine(), + // md->name().data(),root->relates.data()); + bool success = fgd->insertMember(md); + if (success) + { + //printf("insertMember successful\n"); + md->setGroupDef(fgd,pri,root->fileName,root->startLine, + !root->doc.isEmpty()); + ClassDef *cd = md->getClassDefOfAnonymousType(); + if (cd) + { + cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0); + } + } + } + } +} + + +void addExampleToGroups(Entry *root,PageDef *eg) +{ + QListIterator<Grouping> gli(*root->groups); + Grouping *g; + for (;(g=gli.current());++gli) + { + GroupDef *gd=0; + if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname))) + { + gd->addExample(eg); + eg->makePartOfGroup(gd); + //printf("Example %s: in group %s\n",eg->name().data(),s->data()); + } + } +} + +QCString GroupDef::getOutputFileBase() const +{ + if (isReference()) + { + return fileName; + } + else + { + return convertNameToFile(fileName); + } +} + +void GroupDef::addListReferences() +{ + { + LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems(); + addRefItem(xrefItems.pointer(), + getOutputFileBase(), + theTranslator->trGroup(TRUE,TRUE), + getOutputFileBase(),name(), + 0 + ); + } + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->addListReferences(this); + } + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()&MemberList::documentationLists) + { + ml->addListReferences(this); + } + } +} + +MemberList *GroupDef::createMemberList(MemberList::ListType lt) +{ + m_memberLists.setAutoDelete(TRUE); + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if (ml->listType()==lt) + { + return ml; + } + } + // not found, create a new member list + ml = new MemberList(lt); + m_memberLists.append(ml); + ml->setInGroup(TRUE); + return ml; +} + +void GroupDef::addMemberToList(MemberList::ListType lt,MemberDef *md) +{ + static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); + static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS"); + MemberList *ml = createMemberList(lt); + ml->setNeedsSorting( + ((ml->listType()&MemberList::declarationLists) && sortBriefDocs) || + ((ml->listType()&MemberList::documentationLists) && sortMemberDocs)); + ml->append(md); +} + +void GroupDef::sortMemberLists() +{ + MemberList *ml = m_memberLists.first(); + while (ml) + { + if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); } + ml = m_memberLists.next(); + } +} + + +MemberList *GroupDef::getMemberList(MemberList::ListType lt) const +{ + GroupDef *that = (GroupDef*)this; + MemberList *ml = that->m_memberLists.first(); + while (ml) + { + if (ml->listType()==lt) + { + return ml; + } + ml = that->m_memberLists.next(); + } + return 0; +} + +void GroupDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title) +{ + static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + + MemberList * ml = getMemberList(lt); + if (optimizeVhdl && ml) + { + VhdlDocGen::writeVhdlDeclarations(ml,ol,this,0,0,0); + return; + } + if (ml) + { + ml->writeDeclarations(ol,0,0,0,this,title,0); + } +} + +void GroupDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title) +{ + MemberList * ml = getMemberList(lt); + if (ml) ml->writeDocumentation(ol,name(),this,title); +} + +void GroupDef::removeMemberFromList(MemberList::ListType lt,MemberDef *md) +{ + MemberList *ml = getMemberList(lt); + if (ml) ml->remove(md); +} + +void GroupDef::sortSubGroups() +{ + groupList->sort(); +} + +bool GroupDef::isLinkableInProject() const +{ + return !isReference() && isLinkable(); +} + +bool GroupDef::isLinkable() const +{ + return hasUserDocumentation(); +} + +// let the "programming language" for a group depend on what is inserted into it. +// First item that has an associated languages determines the language for the whole group. +void GroupDef::updateLanguage(const Definition *d) +{ + if (getLanguage()==SrcLangExt_Unknown && d->getLanguage()!=SrcLangExt_Unknown) + { + setLanguage(d->getLanguage()); + } +} + |