1 /******************************************************************************
5 * Copyright (C) 1997-2014 by Dimitri van Heesch.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
23 #include "classlist.h"
24 #include "outputlist.h"
25 #include "namespacedef.h"
28 #include "memberlist.h"
30 #include "membergroup.h"
33 #include "docparser.h"
34 #include "searchindex.h"
36 #include "vhdldocgen.h"
38 #include "arguments.h"
40 #include "membername.h"
44 //---------------------------------------------------------------------------
46 GroupDef::GroupDef(const char *df,int dl,const char *na,const char *t,
47 const char *refFileName) : Definition(df,dl,1,na)
49 fileList = new FileList;
50 classSDict = new ClassSDict(17);
51 groupList = new GroupList;
52 namespaceSDict = new NamespaceSDict(17);
53 pageDict = new PageSDict(17);
54 exampleDict = new PageSDict(17);
55 dirList = new DirList;
56 allMemberNameInfoSDict = new MemberNameInfoSDict(17);
57 allMemberNameInfoSDict->setAutoDelete(TRUE);
60 fileName=stripExtension(refFileName);
64 fileName = (QCString)"group_"+na;
67 memberGroupSDict = new MemberGroupSDict;
68 memberGroupSDict->setAutoDelete(TRUE);
70 allMemberList = new MemberList(MemberListType_allMembersList);
81 delete namespaceSDict;
85 delete allMemberNameInfoSDict;
86 delete memberGroupSDict;
90 void GroupDef::setGroupTitle( const char *t )
92 if ( t && qstrlen(t) )
100 title.at(0)=toupper(title.at(0));
106 void GroupDef::distributeMemberGroupDocumentation()
108 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
110 for (;(mg=mgli.current());++mgli)
112 mg->distributeMemberGroupDocumentation();
116 void GroupDef::findSectionsInDocumentation()
118 docFindSections(documentation(),this,0,docFile());
119 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
121 for (;(mg=mgli.current());++mgli)
123 mg->findSectionsInDocumentation();
126 QListIterator<MemberList> mli(m_memberLists);
128 for (mli.toFirst();(ml=mli.current());++mli)
130 if (ml->listType()&MemberListType_declarationLists)
132 ml->findSectionsInDocumentation();
137 void GroupDef::addFile(const FileDef *def)
139 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
140 if (def->isHidden()) return;
143 fileList->inSort(def);
145 fileList->append(def);
148 bool GroupDef::addClass(const ClassDef *cd)
150 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
151 if (cd->isHidden()) return FALSE;
153 if (classSDict->find(cd->qualifiedName())==0)
155 QCString qn = cd->qualifiedName();
156 //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs);
159 classSDict->inSort(cd->qualifiedName(),cd);
163 int i=qn.findRev("::");
164 if (i==-1) i=qn.find('.');
166 //printf("i=%d\n",i);
169 // add nested classes (e.g. A::B, A::C) after their parent (A) in
170 // order of insertion
171 QCString scope = qn.left(i);
172 int j=classSDict->findAt(scope);
175 while (j<(int)classSDict->count() &&
176 classSDict->at(j)->qualifiedName().left(i)==scope)
178 //printf("skipping over %s\n",classSDict->at(j)->qualifiedName().data());
181 //printf("Found scope at index %d\n",j);
182 classSDict->insertAt(j,cd->qualifiedName(),cd);
186 if (!found) // no insertion point found -> just append
188 classSDict->append(cd->qualifiedName(),cd);
196 bool GroupDef::addNamespace(const NamespaceDef *def)
198 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
199 if (def->isHidden()) return FALSE;
201 if (namespaceSDict->find(def->name())==0)
204 namespaceSDict->inSort(def->name(),def);
206 namespaceSDict->append(def->name(),def);
212 void GroupDef::addDir(const DirDef *def)
214 if (def->isHidden()) return;
215 if (Config_getBool("SORT_BRIEF_DOCS"))
216 dirList->inSort(def);
218 dirList->append(def);
221 void GroupDef::addPage(PageDef *def)
223 if (def->isHidden()) return;
224 //printf("Making page %s part of a group\n",def->name.data());
225 pageDict->append(def->name(),def);
226 def->makePartOfGroup(this);
229 void GroupDef::addExample(const PageDef *def)
231 if (def->isHidden()) return;
232 exampleDict->append(def->name(),def);
236 void GroupDef::addMembersToMemberGroup()
238 QListIterator<MemberList> mli(m_memberLists);
240 for (mli.toFirst();(ml=mli.current());++mli)
242 if (ml->listType()&MemberListType_declarationLists)
244 ::addMembersToMemberGroup(ml,&memberGroupSDict,this);
248 //printf("GroupDef::addMembersToMemberGroup() memberGroupList=%d\n",memberGroupList->count());
249 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
251 for (;(mg=mgli.current());++mgli)
253 mg->setInGroup(TRUE);
258 bool GroupDef::insertMember(MemberDef *md,bool docOnly)
260 if (md->isHidden()) return FALSE;
262 //printf("GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data());
263 MemberNameInfo *mni=0;
264 if ((mni=(*allMemberNameInfoSDict)[md->name()]))
265 { // member with this name already found
266 MemberNameInfoIterator srcMnii(*mni);
268 for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
270 MemberDef *srcMd = srcMi->memberDef;
271 if (srcMd==md) return FALSE; // already added before!
273 bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace
274 // both inside a file => definition and declaration do not have to be in the same file
275 (srcMd->getOuterScope()->definitionType()==Definition::TypeFile &&
276 md->getOuterScope()->definitionType()==Definition::TypeFile);
278 ArgumentList *srcMdAl = srcMd->argumentList();
279 ArgumentList *mdAl = md->argumentList();
280 ArgumentList *tSrcMdAl = srcMd->templateArguments();
281 ArgumentList *tMdAl = md->templateArguments();
283 if (srcMd->isFunction() && md->isFunction() && // both are a function
284 ((tSrcMdAl==0 && tMdAl==0) ||
285 (tSrcMdAl!=0 && tMdAl!=0 && tSrcMdAl->count()==tMdAl->count())
286 ) && // same number of template arguments
287 matchArguments2(srcMd->getOuterScope(),srcMd->getFileDef(),srcMdAl,
288 md->getOuterScope(),md->getFileDef(),mdAl,
290 ) && // matching parameters
291 sameScope // both are found in the same scope
294 if (srcMd->getGroupAlias()==0)
296 md->setGroupAlias(srcMd);
298 else if (md!=srcMd->getGroupAlias())
300 md->setGroupAlias(srcMd->getGroupAlias());
302 return FALSE; // member is the same as one that is already added
305 mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
309 mni = new MemberNameInfo(md->name());
310 mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
311 allMemberNameInfoSDict->append(mni->memberName(),mni);
313 //printf("Added member!\n");
314 allMemberList->append(md);
315 switch(md->memberType())
317 case MemberType_Variable:
320 addMemberToList(MemberListType_decVarMembers,md);
322 addMemberToList(MemberListType_docVarMembers,md);
324 case MemberType_Function:
327 addMemberToList(MemberListType_decFuncMembers,md);
329 addMemberToList(MemberListType_docFuncMembers,md);
331 case MemberType_Typedef:
334 addMemberToList(MemberListType_decTypedefMembers,md);
336 addMemberToList(MemberListType_docTypedefMembers,md);
338 case MemberType_Enumeration:
341 addMemberToList(MemberListType_decEnumMembers,md);
343 addMemberToList(MemberListType_docEnumMembers,md);
345 case MemberType_EnumValue:
348 addMemberToList(MemberListType_decEnumValMembers,md);
350 addMemberToList(MemberListType_docEnumValMembers,md);
352 case MemberType_Define:
355 addMemberToList(MemberListType_decDefineMembers,md);
357 addMemberToList(MemberListType_docDefineMembers,md);
359 case MemberType_Signal:
362 addMemberToList(MemberListType_decSignalMembers,md);
364 addMemberToList(MemberListType_docSignalMembers,md);
366 case MemberType_Slot:
367 if (md->protection()==Public)
371 addMemberToList(MemberListType_decPubSlotMembers,md);
373 addMemberToList(MemberListType_docPubSlotMembers,md);
375 else if (md->protection()==Protected)
379 addMemberToList(MemberListType_decProSlotMembers,md);
381 addMemberToList(MemberListType_docProSlotMembers,md);
387 addMemberToList(MemberListType_decPriSlotMembers,md);
389 addMemberToList(MemberListType_docPriSlotMembers,md);
392 case MemberType_Event:
395 addMemberToList(MemberListType_decEventMembers,md);
397 addMemberToList(MemberListType_docEventMembers,md);
399 case MemberType_Property:
402 addMemberToList(MemberListType_decPropMembers,md);
404 addMemberToList(MemberListType_docPropMembers,md);
406 case MemberType_Friend:
409 addMemberToList(MemberListType_decFriendMembers,md);
411 addMemberToList(MemberListType_docFriendMembers,md);
414 err("GroupDef::insertMembers(): "
415 "member `%s' (typeid=%d) with scope `%s' inserted in group scope `%s'!\n",
416 md->name().data(),md->memberType(),
417 md->getClassDef() ? md->getClassDef()->name().data() : "",
423 void GroupDef::removeMember(MemberDef *md)
425 // fprintf(stderr, "GroupDef(%s)::removeMember( %s )\n", title.data(), md->name().data());
426 MemberNameInfo *mni = allMemberNameInfoSDict->find(md->name());
429 MemberNameInfoIterator mnii(*mni);
430 while( mnii.current() )
432 if( mnii.current()->memberDef == md )
434 mni->remove(mnii.current());
441 allMemberNameInfoSDict->remove(md->name());
444 removeMemberFromList(MemberListType_allMembersList,md);
445 switch(md->memberType())
447 case MemberType_Variable:
448 removeMemberFromList(MemberListType_decVarMembers,md);
449 removeMemberFromList(MemberListType_docVarMembers,md);
451 case MemberType_Function:
452 removeMemberFromList(MemberListType_decFuncMembers,md);
453 removeMemberFromList(MemberListType_docFuncMembers,md);
455 case MemberType_Typedef:
456 removeMemberFromList(MemberListType_decTypedefMembers,md);
457 removeMemberFromList(MemberListType_docTypedefMembers,md);
459 case MemberType_Enumeration:
460 removeMemberFromList(MemberListType_decEnumMembers,md);
461 removeMemberFromList(MemberListType_docEnumMembers,md);
463 case MemberType_EnumValue:
464 removeMemberFromList(MemberListType_decEnumValMembers,md);
465 removeMemberFromList(MemberListType_docEnumValMembers,md);
467 case MemberType_Define:
468 removeMemberFromList(MemberListType_decDefineMembers,md);
469 removeMemberFromList(MemberListType_docDefineMembers,md);
471 case MemberType_Signal:
472 removeMemberFromList(MemberListType_decSignalMembers,md);
473 removeMemberFromList(MemberListType_docSignalMembers,md);
475 case MemberType_Slot:
476 if (md->protection()==Public)
478 removeMemberFromList(MemberListType_decPubSlotMembers,md);
479 removeMemberFromList(MemberListType_docPubSlotMembers,md);
481 else if (md->protection()==Protected)
483 removeMemberFromList(MemberListType_decProSlotMembers,md);
484 removeMemberFromList(MemberListType_docProSlotMembers,md);
488 removeMemberFromList(MemberListType_decPriSlotMembers,md);
489 removeMemberFromList(MemberListType_docPriSlotMembers,md);
492 case MemberType_Event:
493 removeMemberFromList(MemberListType_decEventMembers,md);
494 removeMemberFromList(MemberListType_docEventMembers,md);
496 case MemberType_Property:
497 removeMemberFromList(MemberListType_decPropMembers,md);
498 removeMemberFromList(MemberListType_docPropMembers,md);
500 case MemberType_Friend:
501 removeMemberFromList(MemberListType_decFriendMembers,md);
502 removeMemberFromList(MemberListType_docFriendMembers,md);
505 err("GroupDef::removeMember(): unexpected member remove in file!\n");
510 bool GroupDef::containsGroup(const GroupDef *def)
512 return this==def || groupList->find(def) >= 0;
515 void GroupDef::addGroup(const GroupDef *def)
517 //printf("adding group `%s' to group `%s'\n",def->name().data(),name().data());
518 //if (Config_getBool("SORT_MEMBER_DOCS"))
519 // groupList->inSort(def);
521 groupList->append(def);
524 bool GroupDef::isASubGroup() const
526 GroupList *groups = partOfGroups();
527 return groups!=0 && groups->count()!=0;
530 int GroupDef::countMembers() const
532 return fileList->count()+
534 namespaceSDict->count()+
536 allMemberList->count()+
538 exampleDict->count();
541 /*! Compute the HTML anchor names for all members in the group */
542 void GroupDef::computeAnchors()
544 //printf("GroupDef::computeAnchors()\n");
545 setAnchors(allMemberList);
548 void GroupDef::writeDetailedDescription(OutputList &ol,const QCString &title)
550 if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
551 || !documentation().isEmpty() || !inbodyDocumentation().isEmpty()
554 if (pageDict->count()!=countMembers()) // not only pages -> classical layout
556 ol.pushGeneratorState();
557 ol.disable(OutputGenerator::Html);
559 ol.popGeneratorState();
560 ol.pushGeneratorState();
561 ol.disableAllBut(OutputGenerator::Html);
562 ol.writeAnchor(0,"details");
563 ol.popGeneratorState();
564 ol.startGroupHeader();
569 // repeat brief description
570 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
572 ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
574 // write separator between brief and details
575 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") &&
576 !documentation().isEmpty())
578 ol.pushGeneratorState();
579 ol.disable(OutputGenerator::Man);
580 ol.disable(OutputGenerator::RTF);
581 // ol.newParagraph(); // FIXME:PARA
583 ol.disableAllBut(OutputGenerator::Man);
584 ol.enable(OutputGenerator::Latex);
585 ol.writeString("\n\n");
586 ol.popGeneratorState();
589 // write detailed documentation
590 if (!documentation().isEmpty())
592 ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
595 // write inbody documentation
596 if (!inbodyDocumentation().isEmpty())
598 ol.generateDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE);
603 void GroupDef::writeBriefDescription(OutputList &ol)
605 if (!briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
607 DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
608 briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
609 if (rootNode && !rootNode->isEmpty())
612 ol.writeDoc(rootNode,this,0);
613 ol.pushGeneratorState();
614 ol.disable(OutputGenerator::RTF);
615 ol.writeString(" \n");
616 ol.enable(OutputGenerator::RTF);
618 if (Config_getBool("REPEAT_BRIEF") ||
619 !documentation().isEmpty()
622 ol.disableAllBut(OutputGenerator::Html);
623 ol.startTextLink(0,"details");
624 ol.parseText(theTranslator->trMore());
627 ol.popGeneratorState();
634 void GroupDef::writeGroupGraph(OutputList &ol)
636 if (Config_getBool("HAVE_DOT") /*&& Config_getBool("GROUP_GRAPHS")*/ )
638 DotGroupCollaboration graph(this);
639 if (!graph.isTrivial())
641 msg("Generating dependency graph for group %s\n",qualifiedName().data());
642 ol.pushGeneratorState();
643 ol.disable(OutputGenerator::Man);
644 //ol.startParagraph();
645 ol.startGroupCollaboration();
646 ol.parseText(theTranslator->trCollaborationDiagram(title));
647 ol.endGroupCollaboration(graph);
649 ol.popGeneratorState();
654 void GroupDef::writeFiles(OutputList &ol,const QCString &title)
656 // write list of files
657 if (fileList->count()>0)
659 ol.startMemberHeader("files");
661 ol.endMemberHeader();
662 ol.startMemberList();
663 QListIterator<FileDef> it(*fileList);
665 for (;(fd=it.current());++it)
667 ol.startMemberDeclaration();
668 ol.startMemberItem(fd->getOutputFileBase(),0);
669 ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");
670 ol.insertMemberAlign();
671 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
672 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
674 Doxygen::tagFile << " <file>" << convertToXML(fd->name()) << "</file>" << endl;
677 if (!fd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
679 ol.startMemberDescription(fd->getOutputFileBase());
680 ol.generateDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
681 ol.endMemberDescription();
683 ol.endMemberDeclaration(0,0);
689 void GroupDef::writeNamespaces(OutputList &ol,const QCString &title)
691 // write list of namespaces
692 namespaceSDict->writeDeclaration(ol,title);
695 void GroupDef::writeNestedGroups(OutputList &ol,const QCString &title)
697 // write list of groups
699 if (groupList->count()>0)
701 QListIterator<GroupDef> it(*groupList);
703 for (;(gd=it.current());++it)
705 if (gd->isVisible()) count++;
710 ol.startMemberHeader("groups");
712 ol.endMemberHeader();
713 ol.startMemberList();
714 if (Config_getBool("SORT_GROUP_NAMES"))
718 QListIterator<GroupDef> it(*groupList);
720 for (;(gd=it.current());++it)
724 ol.startMemberDeclaration();
725 ol.startMemberItem(gd->getOutputFileBase(),0);
726 //ol.docify(theTranslator->trGroup(FALSE,TRUE));
728 ol.insertMemberAlign();
729 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),0,gd->groupTitle());
730 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
732 Doxygen::tagFile << " <subgroup>" << convertToXML(gd->name()) << "</subgroup>" << endl;
735 if (!gd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
737 ol.startMemberDescription(gd->getOutputFileBase());
738 ol.generateDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
739 ol.endMemberDescription();
741 ol.endMemberDeclaration(0,0);
748 void GroupDef::writeDirs(OutputList &ol,const QCString &title)
750 // write list of directories
751 if (dirList->count()>0)
753 ol.startMemberHeader("dirs");
755 ol.endMemberHeader();
756 ol.startMemberList();
757 QListIterator<DirDef> it(*dirList);
759 for (;(dd=it.current());++it)
761 ol.startMemberDeclaration();
762 ol.startMemberItem(dd->getOutputFileBase(),0);
763 ol.parseText(theTranslator->trDir(FALSE,TRUE));
764 ol.insertMemberAlign();
765 ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),0,dd->shortName());
767 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
769 Doxygen::tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;
771 if (!dd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
773 ol.startMemberDescription(dd->getOutputFileBase());
774 ol.generateDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
775 ol.endMemberDescription();
777 ol.endMemberDeclaration(0,0);
784 void GroupDef::writeClasses(OutputList &ol,const QCString &title)
786 // write list of classes
787 classSDict->writeDeclaration(ol,0,title,FALSE);
790 void GroupDef::writeInlineClasses(OutputList &ol)
792 classSDict->writeDocumentation(ol);
795 void GroupDef::writePageDocumentation(OutputList &ol)
798 PageSDict::Iterator pdi(*pageDict);
799 for (pdi.toFirst();(pd=pdi.current());++pdi)
801 if (!pd->isReference())
803 QCString pageName = pd->getOutputFileBase();
805 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
807 Doxygen::tagFile << " <page>" << convertToXML(pageName) << "</page>" << endl;
811 if (!pd->title().isEmpty() && !pd->name().isEmpty() &&
812 (si=Doxygen::sectionDict->find(pd->name()))!=0)
814 ol.startSection(si->label,si->title,SectionInfo::Subsection);
815 ol.docify(si->title);
816 ol.endSection(si->label,SectionInfo::Subsection);
819 ol.generateDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE,0,TRUE,FALSE);
825 void GroupDef::writeMemberGroups(OutputList &ol)
827 /* write user defined member groups */
828 if (memberGroupSDict)
830 memberGroupSDict->sort();
831 /* write user defined member groups */
832 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
834 for (;(mg=mgli.current());++mgli)
836 mg->writeDeclarations(ol,0,0,0,this);
841 void GroupDef::startMemberDeclarations(OutputList &ol)
843 ol.startMemberSections();
846 void GroupDef::endMemberDeclarations(OutputList &ol)
848 ol.endMemberSections();
851 void GroupDef::startMemberDocumentation(OutputList &ol)
853 //printf("** GroupDef::startMemberDocumentation()\n");
854 if (Config_getBool("SEPARATE_MEMBER_PAGES"))
856 ol.pushGeneratorState();
857 ol.disable(OutputGenerator::Html);
858 Doxygen::suppressDocWarnings = TRUE;
862 void GroupDef::endMemberDocumentation(OutputList &ol)
864 //printf("** GroupDef::endMemberDocumentation()\n");
865 if (Config_getBool("SEPARATE_MEMBER_PAGES"))
867 ol.popGeneratorState();
868 Doxygen::suppressDocWarnings = FALSE;
872 void GroupDef::writeAuthorSection(OutputList &ol)
874 // write Author section (Man only)
875 ol.pushGeneratorState();
876 ol.disableAllBut(OutputGenerator::Man);
877 ol.startGroupHeader();
878 ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
880 ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME")));
881 ol.popGeneratorState();
884 void GroupDef::writeSummaryLinks(OutputList &ol)
886 ol.pushGeneratorState();
887 ol.disableAllBut(OutputGenerator::Html);
888 QListIterator<LayoutDocEntry> eli(
889 LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
892 SrcLangExt lang = getLanguage();
893 for (eli.toFirst();(lde=eli.current());++eli)
895 if ((lde->kind()==LayoutDocEntry::GroupClasses && classSDict->declVisible()) ||
896 (lde->kind()==LayoutDocEntry::GroupNamespaces && namespaceSDict->declVisible()) ||
897 (lde->kind()==LayoutDocEntry::GroupFiles && fileList->count()>0) ||
898 (lde->kind()==LayoutDocEntry::GroupNestedGroups && groupList->count()>0) ||
899 (lde->kind()==LayoutDocEntry::GroupDirs && dirList->count()>0)
902 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
903 QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" :
904 lde->kind()==LayoutDocEntry::GroupNamespaces ? "namespaces" :
905 lde->kind()==LayoutDocEntry::GroupFiles ? "files" :
906 lde->kind()==LayoutDocEntry::GroupNestedGroups ? "groups" :
908 ol.writeSummaryLink(0,label,ls->title(lang),first);
911 else if (lde->kind()==LayoutDocEntry::MemberDecl)
913 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
914 MemberList * ml = getMemberList(lmd->type);
915 if (ml && ml->declVisible())
917 ol.writeSummaryLink(0,MemberList::listTypeAsString(ml->listType()),lmd->title(lang),first);
924 ol.writeString(" </div>\n");
926 ol.popGeneratorState();
929 void GroupDef::writeDocumentation(OutputList &ol)
931 //static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
932 ol.pushGeneratorState();
933 startFile(ol,getOutputFileBase(),name(),title,HLI_None);
935 ol.startHeaderSection();
936 writeSummaryLinks(ol);
937 ol.startTitleHead(getOutputFileBase());
938 ol.pushGeneratorState();
939 ol.disable(OutputGenerator::Man);
941 ol.popGeneratorState();
942 addGroupListToTitle(ol,this);
943 ol.endTitleHead(getOutputFileBase(),title);
944 ol.endHeaderSection();
947 if (Doxygen::searchIndex)
949 Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
950 static QRegExp we("[a-zA-Z_][-a-zA-Z_0-9]*");
952 while ((i=we.match(title,p,&l))!=-1) // foreach word in the title
954 Doxygen::searchIndex->addWord(title.mid(i,l),TRUE);
959 Doxygen::indexList->addIndexItem(this,0,0,title);
961 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
963 Doxygen::tagFile << " <compound kind=\"group\">" << endl;
964 Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl;
965 Doxygen::tagFile << " <title>" << convertToXML(title) << "</title>" << endl;
966 Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
970 //---------------------------------------- start flexible part -------------------------------
972 SrcLangExt lang=getLanguage();
973 QListIterator<LayoutDocEntry> eli(
974 LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
976 for (eli.toFirst();(lde=eli.current());++eli)
980 case LayoutDocEntry::BriefDesc:
981 writeBriefDescription(ol);
983 case LayoutDocEntry::MemberDeclStart:
984 startMemberDeclarations(ol);
986 case LayoutDocEntry::GroupClasses:
988 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
989 writeClasses(ol,ls->title(lang));
992 case LayoutDocEntry::GroupInlineClasses:
994 writeInlineClasses(ol);
997 case LayoutDocEntry::GroupNamespaces:
999 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1000 writeNamespaces(ol,ls->title(lang));
1003 case LayoutDocEntry::MemberGroups:
1004 writeMemberGroups(ol);
1006 case LayoutDocEntry::MemberDecl:
1008 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
1009 writeMemberDeclarations(ol,lmd->type,lmd->title(lang));
1012 case LayoutDocEntry::MemberDeclEnd:
1013 endMemberDeclarations(ol);
1015 case LayoutDocEntry::DetailedDesc:
1017 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1018 writeDetailedDescription(ol,ls->title(lang));
1021 case LayoutDocEntry::MemberDefStart:
1022 startMemberDocumentation(ol);
1024 case LayoutDocEntry::MemberDef:
1026 LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
1027 writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
1030 case LayoutDocEntry::MemberDefEnd:
1031 endMemberDocumentation(ol);
1033 case LayoutDocEntry::GroupNestedGroups:
1035 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1036 writeNestedGroups(ol,ls->title(lang));
1039 case LayoutDocEntry::GroupPageDocs:
1040 writePageDocumentation(ol);
1042 case LayoutDocEntry::GroupDirs:
1044 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1045 writeDirs(ol,ls->title(lang));
1048 case LayoutDocEntry::GroupFiles:
1050 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1051 writeFiles(ol,ls->title(lang));
1054 case LayoutDocEntry::GroupGraph:
1055 writeGroupGraph(ol);
1057 case LayoutDocEntry::AuthorSection:
1058 writeAuthorSection(ol);
1060 case LayoutDocEntry::ClassIncludes:
1061 case LayoutDocEntry::ClassInheritanceGraph:
1062 case LayoutDocEntry::ClassNestedClasses:
1063 case LayoutDocEntry::ClassCollaborationGraph:
1064 case LayoutDocEntry::ClassAllMembersLink:
1065 case LayoutDocEntry::ClassUsedFiles:
1066 case LayoutDocEntry::ClassInlineClasses:
1067 case LayoutDocEntry::NamespaceNestedNamespaces:
1068 case LayoutDocEntry::NamespaceNestedConstantGroups:
1069 case LayoutDocEntry::NamespaceClasses:
1070 case LayoutDocEntry::NamespaceInlineClasses:
1071 case LayoutDocEntry::FileClasses:
1072 case LayoutDocEntry::FileNamespaces:
1073 case LayoutDocEntry::FileConstantGroups:
1074 case LayoutDocEntry::FileIncludes:
1075 case LayoutDocEntry::FileIncludeGraph:
1076 case LayoutDocEntry::FileIncludedByGraph:
1077 case LayoutDocEntry::FileSourceLink:
1078 case LayoutDocEntry::FileInlineClasses:
1079 case LayoutDocEntry::DirSubDirs:
1080 case LayoutDocEntry::DirFiles:
1081 case LayoutDocEntry::DirGraph:
1082 err("Internal inconsistency: member %d should not be part of "
1083 "LayoutDocManager::Group entry list\n",lde->kind());
1088 //---------------------------------------- end flexible part -------------------------------
1092 ol.popGeneratorState();
1094 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
1096 writeDocAnchorsToTagFile();
1097 Doxygen::tagFile << " </compound>" << endl;
1100 if (Config_getBool("SEPARATE_MEMBER_PAGES"))
1102 allMemberList->sort();
1103 writeMemberPages(ol);
1108 void GroupDef::writeMemberPages(OutputList &ol)
1110 ol.pushGeneratorState();
1111 ol.disableAllBut(OutputGenerator::Html);
1113 QListIterator<MemberList> mli(m_memberLists);
1115 for (mli.toFirst();(ml=mli.current());++mli)
1117 if (ml->listType()&MemberListType_documentationLists)
1119 ml->writeDocumentationPage(ol,name(),this);
1123 ol.popGeneratorState();
1126 void GroupDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
1128 static bool createSubDirs=Config_getBool("CREATE_SUBDIRS");
1130 ol.writeString(" <div class=\"navtab\">\n");
1131 ol.writeString(" <table>\n");
1133 MemberListIterator mli(*allMemberList);
1135 for (mli.toFirst();(md=mli.current());++mli)
1137 if (md->getGroupDef()==this && md->isLinkable() && !md->isEnumValue())
1139 ol.writeString(" <tr><td class=\"navtab\">");
1140 if (md->isLinkableInProject())
1142 if (md==currentMd) // selected item => highlight
1144 ol.writeString("<a class=\"qindexHL\" ");
1148 ol.writeString("<a class=\"qindex\" ");
1150 ol.writeString("href=\"");
1151 if (createSubDirs) ol.writeString("../../");
1152 ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
1153 ol.writeString("\">");
1154 ol.writeString(convertToHtml(md->localName()));
1155 ol.writeString("</a>");
1157 ol.writeString("</td></tr>\n");
1161 ol.writeString(" </table>\n");
1162 ol.writeString(" </div>\n");
1167 //---- helper functions ------------------------------------------------------
1169 void addClassToGroups(Entry *root,ClassDef *cd)
1171 QListIterator<Grouping> gli(*root->groups);
1173 for (;(g=gli.current());++gli)
1176 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1178 if (gd->addClass(cd))
1180 cd->makePartOfGroup(gd);
1182 //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle());
1187 void addNamespaceToGroups(Entry *root,NamespaceDef *nd)
1189 //printf("root->groups->count()=%d\n",root->groups->count());
1190 QListIterator<Grouping> gli(*root->groups);
1192 for (;(g=gli.current());++gli)
1195 //printf("group `%s'\n",s->data());
1196 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1198 if (gd->addNamespace(nd)) nd->makePartOfGroup(gd);
1199 //printf("Namespace %s: in group %s\n",nd->name().data(),s->data());
1204 void addDirToGroups(Entry *root,DirDef *dd)
1206 //printf("*** root->groups->count()=%d\n",root->groups->count());
1207 QListIterator<Grouping> gli(*root->groups);
1209 for (;(g=gli.current());++gli)
1212 //printf("group `%s'\n",g->groupname.data());
1213 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1216 dd->makePartOfGroup(gd);
1217 //printf("Dir %s: in group %s\n",dd->name().data(),g->groupname.data());
1222 void addGroupToGroups(Entry *root,GroupDef *subGroup)
1224 //printf("addGroupToGroups for %s groups=%d\n",root->name.data(),
1225 // root->groups?root->groups->count():-1);
1226 QListIterator<Grouping> gli(*root->groups);
1228 for (;(g=gli.current());++gli)
1231 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)) &&
1232 !gd->containsGroup(subGroup) )
1234 gd->addGroup(subGroup);
1235 subGroup->makePartOfGroup(gd);
1237 else if (gd==subGroup)
1239 warn(root->fileName,root->startLine,"Trying to add group %s to itself!",
1245 /*! Add a member to the group with the highest priority */
1246 void addMemberToGroups(Entry *root,MemberDef *md)
1248 //printf("addMemberToGroups: Root %p = %s, md %p=%s groups=%d\n",
1249 // root, root->name.data(), md, md->name().data(), root->groups->count() );
1250 QListIterator<Grouping> gli(*root->groups);
1253 // Search entry's group list for group with highest pri.
1254 Grouping::GroupPri_t pri = Grouping::GROUPING_LOWEST;
1256 for (;(g=gli.current());++gli)
1259 if (!g->groupname.isEmpty() &&
1260 (gd=Doxygen::groupSDict->find(g->groupname)) &&
1263 if (fgd && gd!=fgd && g->pri==pri)
1265 warn(root->fileName.data(), root->startLine,
1266 "Member %s found in multiple %s groups! "
1267 "The member will be put in group %s, and not in group %s",
1268 md->name().data(), Grouping::getGroupPriName( pri ),
1269 gd->name().data(), fgd->name().data()
1277 //printf("fgd=%p\n",fgd);
1279 // put member into group defined by this entry?
1282 GroupDef *mgd = md->getGroupDef();
1283 //printf("mgd=%p\n",mgd);
1284 bool insertit = FALSE;
1291 bool moveit = FALSE;
1293 // move member from one group to another if
1294 // - the new one has a higher priority
1295 // - the new entry has the same priority, but with docs where the old one had no docs
1296 if (md->getGroupPri()<pri)
1302 if (md->getGroupPri()==pri)
1304 if (!root->doc.isEmpty() && !md->getGroupHasDocs())
1308 else if (!root->doc.isEmpty() && md->getGroupHasDocs())
1310 warn(md->getGroupFileName(),md->getGroupStartLine(),
1311 "Member documentation for %s found several times in %s groups!\n"
1312 "%s:%d: The member will remain in group %s, and won't be put into group %s",
1313 md->name().data(), Grouping::getGroupPriName( pri ),
1314 root->fileName.data(), root->startLine,
1324 //printf("removeMember\n");
1325 mgd->removeMember(md);
1332 //printf("insertMember found at %s line %d: %s: related %s\n",
1333 // md->getDefFileName().data(),md->getDefLine(),
1334 // md->name().data(),root->relates.data());
1335 bool success = fgd->insertMember(md);
1338 //printf("insertMember successful\n");
1339 md->setGroupDef(fgd,pri,root->fileName,root->startLine,
1340 !root->doc.isEmpty());
1341 ClassDef *cd = md->getClassDefOfAnonymousType();
1344 cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0);
1352 void addExampleToGroups(Entry *root,PageDef *eg)
1354 QListIterator<Grouping> gli(*root->groups);
1356 for (;(g=gli.current());++gli)
1359 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1362 eg->makePartOfGroup(gd);
1363 //printf("Example %s: in group %s\n",eg->name().data(),s->data());
1368 QCString GroupDef::getOutputFileBase() const
1376 return convertNameToFile(fileName);
1380 void GroupDef::addListReferences()
1383 QList<ListItemInfo> *xrefItems = xrefListItems();
1384 addRefItem(xrefItems,
1385 getOutputFileBase(),
1386 theTranslator->trGroup(TRUE,TRUE),
1387 getOutputFileBase(),name(),
1391 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
1393 for (;(mg=mgli.current());++mgli)
1395 mg->addListReferences(this);
1397 QListIterator<MemberList> mli(m_memberLists);
1399 for (mli.toFirst();(ml=mli.current());++mli)
1401 if (ml->listType()&MemberListType_documentationLists)
1403 ml->addListReferences(this);
1408 MemberList *GroupDef::createMemberList(MemberListType lt)
1410 m_memberLists.setAutoDelete(TRUE);
1411 QListIterator<MemberList> mli(m_memberLists);
1413 for (mli.toFirst();(ml=mli.current());++mli)
1415 if (ml->listType()==lt)
1420 // not found, create a new member list
1421 ml = new MemberList(lt);
1422 m_memberLists.append(ml);
1423 ml->setInGroup(TRUE);
1427 void GroupDef::addMemberToList(MemberListType lt,MemberDef *md)
1429 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
1430 static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS");
1431 MemberList *ml = createMemberList(lt);
1432 ml->setNeedsSorting(
1433 ((ml->listType()&MemberListType_declarationLists) && sortBriefDocs) ||
1434 ((ml->listType()&MemberListType_documentationLists) && sortMemberDocs));
1438 void GroupDef::sortMemberLists()
1440 QListIterator<MemberList> mli(m_memberLists);
1442 for (;(ml=mli.current());++mli)
1444 if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
1448 MemberList *GroupDef::getMemberList(MemberListType lt) const
1450 QListIterator<MemberList> mli(m_memberLists);
1452 for (;(ml=mli.current());++mli)
1454 if (ml->listType()==lt)
1462 void GroupDef::writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title)
1464 static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
1466 MemberList * ml = getMemberList(lt);
1467 if (optimizeVhdl && ml)
1469 VhdlDocGen::writeVhdlDeclarations(ml,ol,this,0,0,0);
1474 ml->writeDeclarations(ol,0,0,0,this,title,0,definitionType());
1478 void GroupDef::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title)
1480 MemberList * ml = getMemberList(lt);
1481 if (ml) ml->writeDocumentation(ol,name(),this,title);
1484 void GroupDef::removeMemberFromList(MemberListType lt,MemberDef *md)
1486 MemberList *ml = getMemberList(lt);
1487 if (ml) ml->remove(md);
1490 void GroupDef::sortSubGroups()
1495 bool GroupDef::isLinkableInProject() const
1497 return !isReference() && isLinkable();
1500 bool GroupDef::isLinkable() const
1502 return hasUserDocumentation();
1505 // let the "programming language" for a group depend on what is inserted into it.
1506 // First item that has an associated languages determines the language for the whole group.
1507 void GroupDef::updateLanguage(const Definition *d)
1509 if (getLanguage()==SrcLangExt_Unknown && d->getLanguage()!=SrcLangExt_Unknown)
1511 setLanguage(d->getLanguage());