1 /******************************************************************************
3 * $Id: groupdef.cpp,v 1.29 2001/03/19 19:27:40 root Exp $
5 * Copyright (C) 1997-2012 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.
24 #include "classlist.h"
25 #include "outputlist.h"
26 #include "namespacedef.h"
29 #include "memberlist.h"
31 #include "membergroup.h"
34 #include "docparser.h"
35 #include "searchindex.h"
37 #include "vhdldocgen.h"
39 #include "arguments.h"
42 //---------------------------------------------------------------------------
44 GroupDef::GroupDef(const char *df,int dl,const char *na,const char *t,
45 const char *refFileName) : Definition(df,dl,na)
47 fileList = new FileList;
48 classSDict = new ClassSDict(17);
49 groupList = new GroupList;
50 namespaceSDict = new NamespaceSDict(17);
51 pageDict = new PageSDict(17);
52 exampleDict = new PageSDict(17);
53 dirList = new DirList;
54 allMemberNameInfoSDict = new MemberNameInfoSDict(17);
57 fileName=stripExtension(refFileName);
61 fileName = (QCString)"group_"+na;
64 memberGroupSDict = new MemberGroupSDict;
65 memberGroupSDict->setAutoDelete(TRUE);
67 allMemberList = new MemberList(MemberList::allMembersList);
78 delete namespaceSDict;
82 delete allMemberNameInfoSDict;
83 delete memberGroupSDict;
87 void GroupDef::setGroupTitle( const char *t )
97 title.at(0)=toupper(title.at(0));
103 void GroupDef::distributeMemberGroupDocumentation()
105 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
107 for (;(mg=mgli.current());++mgli)
109 mg->distributeMemberGroupDocumentation();
113 void GroupDef::findSectionsInDocumentation()
115 docFindSections(documentation(),this,0,docFile());
116 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
118 for (;(mg=mgli.current());++mgli)
120 mg->findSectionsInDocumentation();
123 QListIterator<MemberList> mli(m_memberLists);
125 for (mli.toFirst();(ml=mli.current());++mli)
127 if (ml->listType()&MemberList::declarationLists)
129 ml->findSectionsInDocumentation();
134 void GroupDef::addFile(const FileDef *def)
136 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
137 if (def->isHidden()) return;
140 fileList->inSort(def);
142 fileList->append(def);
145 bool GroupDef::addClass(const ClassDef *cd)
147 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
148 if (cd->isHidden()) return FALSE;
150 if (classSDict->find(cd->qualifiedName())==0)
152 QCString qn = cd->qualifiedName();
153 //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs);
156 classSDict->inSort(cd->qualifiedName(),cd);
160 int i=qn.findRev("::");
161 if (i==-1) i=qn.find('.');
163 //printf("i=%d\n",i);
166 // add nested classes (e.g. A::B, A::C) after their parent (A) in
167 // order of insertion
168 QCString scope = qn.left(i);
169 int j=classSDict->findAt(scope);
172 while (j<(int)classSDict->count() &&
173 classSDict->at(j)->qualifiedName().left(i)==scope)
175 //printf("skipping over %s\n",classSDict->at(j)->qualifiedName().data());
178 //printf("Found scope at index %d\n",j);
179 classSDict->insertAt(j,cd->qualifiedName(),cd);
183 if (!found) // no insertion point found -> just append
185 classSDict->append(cd->qualifiedName(),cd);
193 bool GroupDef::addNamespace(const NamespaceDef *def)
195 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
196 if (def->isHidden()) return FALSE;
198 if (namespaceSDict->find(def->name())==0)
201 namespaceSDict->inSort(def->name(),def);
203 namespaceSDict->append(def->name(),def);
209 void GroupDef::addDir(const DirDef *def)
211 if (def->isHidden()) return;
212 if (Config_getBool("SORT_BRIEF_DOCS"))
213 dirList->inSort(def);
215 dirList->append(def);
218 void GroupDef::addPage(PageDef *def)
220 if (def->isHidden()) return;
221 //printf("Making page %s part of a group\n",def->name.data());
222 pageDict->append(def->name(),def);
223 def->makePartOfGroup(this);
226 void GroupDef::addExample(const PageDef *def)
228 if (def->isHidden()) return;
229 exampleDict->append(def->name(),def);
233 void GroupDef::addMembersToMemberGroup()
235 QListIterator<MemberList> mli(m_memberLists);
237 for (mli.toFirst();(ml=mli.current());++mli)
239 if (ml->listType()&MemberList::declarationLists)
241 ::addMembersToMemberGroup(ml,&memberGroupSDict,this);
245 //printf("GroupDef::addMembersToMemberGroup() memberGroupList=%d\n",memberGroupList->count());
246 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
248 for (;(mg=mgli.current());++mgli)
250 mg->setInGroup(TRUE);
255 bool GroupDef::insertMember(MemberDef *md,bool docOnly)
257 if (md->isHidden()) return FALSE;
259 //printf("GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data());
260 MemberNameInfo *mni=0;
261 if ((mni=(*allMemberNameInfoSDict)[md->name()]))
262 { // member with this name already found
263 MemberNameInfoIterator srcMnii(*mni);
265 for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
267 MemberDef *srcMd = srcMi->memberDef;
268 if (srcMd==md) return FALSE; // already added before!
270 bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace
271 // both inside a file => definition and declaration do not have to be in the same file
272 (srcMd->getOuterScope()->definitionType()==Definition::TypeFile &&
273 md->getOuterScope()->definitionType()==Definition::TypeFile);
275 LockingPtr<ArgumentList> srcMdAl = srcMd->argumentList();
276 LockingPtr<ArgumentList> mdAl = md->argumentList();
277 LockingPtr<ArgumentList> tSrcMdAl = srcMd->templateArguments();
278 LockingPtr<ArgumentList> tMdAl = md->templateArguments();
280 if (srcMd->isFunction() && md->isFunction() && // both are a function
281 ((tSrcMdAl.pointer()==0 && tMdAl.pointer()==0) ||
282 (tSrcMdAl.pointer()!=0 && tMdAl.pointer()!=0 && tSrcMdAl->count()==tMdAl->count())
283 ) && // same number of template arguments
284 matchArguments2(srcMd->getOuterScope(),srcMd->getFileDef(),srcMdAl.pointer(),
285 md->getOuterScope(),md->getFileDef(),mdAl.pointer(),
287 ) && // matching parameters
288 sameScope // both are found in the same scope
291 if (srcMd->getGroupAlias()==0)
293 md->setGroupAlias(srcMd);
297 md->setGroupAlias(srcMd->getGroupAlias());
299 return FALSE; // member is the same as one that is already added
302 mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
306 mni = new MemberNameInfo(md->name());
307 mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
308 allMemberNameInfoSDict->append(mni->memberName(),mni);
310 //printf("Added member!\n");
311 allMemberList->append(md);
312 switch(md->memberType())
314 case MemberDef::Variable:
317 addMemberToList(MemberList::decVarMembers,md);
319 addMemberToList(MemberList::docVarMembers,md);
321 case MemberDef::Function:
324 addMemberToList(MemberList::decFuncMembers,md);
326 addMemberToList(MemberList::docFuncMembers,md);
328 case MemberDef::Typedef:
331 addMemberToList(MemberList::decTypedefMembers,md);
333 addMemberToList(MemberList::docTypedefMembers,md);
335 case MemberDef::Enumeration:
338 addMemberToList(MemberList::decEnumMembers,md);
340 addMemberToList(MemberList::docEnumMembers,md);
342 case MemberDef::EnumValue:
345 addMemberToList(MemberList::decEnumValMembers,md);
347 addMemberToList(MemberList::docEnumValMembers,md);
349 case MemberDef::Define:
352 addMemberToList(MemberList::decDefineMembers,md);
354 addMemberToList(MemberList::docDefineMembers,md);
356 case MemberDef::Signal:
359 addMemberToList(MemberList::decSignalMembers,md);
361 addMemberToList(MemberList::docSignalMembers,md);
363 case MemberDef::Slot:
364 if (md->protection()==Public)
368 addMemberToList(MemberList::decPubSlotMembers,md);
370 addMemberToList(MemberList::docPubSlotMembers,md);
372 else if (md->protection()==Protected)
376 addMemberToList(MemberList::decProSlotMembers,md);
378 addMemberToList(MemberList::docProSlotMembers,md);
384 addMemberToList(MemberList::decPriSlotMembers,md);
386 addMemberToList(MemberList::docPriSlotMembers,md);
389 case MemberDef::Event:
392 addMemberToList(MemberList::decEventMembers,md);
394 addMemberToList(MemberList::docEventMembers,md);
396 case MemberDef::Property:
399 addMemberToList(MemberList::decPropMembers,md);
401 addMemberToList(MemberList::docPropMembers,md);
403 case MemberDef::Friend:
406 addMemberToList(MemberList::decFriendMembers,md);
408 addMemberToList(MemberList::docFriendMembers,md);
411 err("GroupDef::insertMembers(): "
412 "member `%s' (typeid=%d) with scope `%s' inserted in group scope `%s'!\n",
413 md->name().data(),md->memberType(),
414 md->getClassDef() ? md->getClassDef()->name().data() : "",
420 void GroupDef::removeMember(MemberDef *md)
422 // fprintf(stderr, "GroupDef(%s)::removeMember( %s )\n", title.data(), md->name().data());
423 MemberNameInfo *mni = allMemberNameInfoSDict->find(md->name());
426 MemberNameInfoIterator mnii(*mni);
427 while( mnii.current() )
429 if( mnii.current()->memberDef == md )
431 mni->remove(mnii.current());
438 allMemberNameInfoSDict->remove(md->name());
442 removeMemberFromList(MemberList::allMembersList,md);
443 switch(md->memberType())
445 case MemberDef::Variable:
446 removeMemberFromList(MemberList::decVarMembers,md);
447 removeMemberFromList(MemberList::docVarMembers,md);
449 case MemberDef::Function:
450 removeMemberFromList(MemberList::decFuncMembers,md);
451 removeMemberFromList(MemberList::docFuncMembers,md);
453 case MemberDef::Typedef:
454 removeMemberFromList(MemberList::decTypedefMembers,md);
455 removeMemberFromList(MemberList::docTypedefMembers,md);
457 case MemberDef::Enumeration:
458 removeMemberFromList(MemberList::decEnumMembers,md);
459 removeMemberFromList(MemberList::docEnumMembers,md);
461 case MemberDef::EnumValue:
462 removeMemberFromList(MemberList::decEnumValMembers,md);
463 removeMemberFromList(MemberList::docEnumValMembers,md);
465 case MemberDef::Define:
466 removeMemberFromList(MemberList::decDefineMembers,md);
467 removeMemberFromList(MemberList::docDefineMembers,md);
469 case MemberDef::Signal:
470 removeMemberFromList(MemberList::decSignalMembers,md);
471 removeMemberFromList(MemberList::docSignalMembers,md);
473 case MemberDef::Slot:
474 if (md->protection()==Public)
476 removeMemberFromList(MemberList::decPubSlotMembers,md);
477 removeMemberFromList(MemberList::docPubSlotMembers,md);
479 else if (md->protection()==Protected)
481 removeMemberFromList(MemberList::decProSlotMembers,md);
482 removeMemberFromList(MemberList::docProSlotMembers,md);
486 removeMemberFromList(MemberList::decPriSlotMembers,md);
487 removeMemberFromList(MemberList::docPriSlotMembers,md);
490 case MemberDef::Event:
491 removeMemberFromList(MemberList::decEventMembers,md);
492 removeMemberFromList(MemberList::docEventMembers,md);
494 case MemberDef::Property:
495 removeMemberFromList(MemberList::decPropMembers,md);
496 removeMemberFromList(MemberList::docPropMembers,md);
498 case MemberDef::Friend:
499 removeMemberFromList(MemberList::decFriendMembers,md);
500 removeMemberFromList(MemberList::docFriendMembers,md);
503 err("GroupDef::removeMember(): unexpected member remove in file!\n");
508 bool GroupDef::containsGroup(const GroupDef *def)
510 return this==def || groupList->find(def) >= 0;
513 void GroupDef::addGroup(const GroupDef *def)
515 //printf("adding group `%s' to group `%s'\n",def->name().data(),name().data());
516 //if (Config_getBool("SORT_MEMBER_DOCS"))
517 // groupList->inSort(def);
519 groupList->append(def);
522 bool GroupDef::isASubGroup() const
524 LockingPtr<GroupList> groups = partOfGroups();
525 return groups!=0 && groups->count()!=0;
528 int GroupDef::countMembers() const
530 return fileList->count()+
532 namespaceSDict->count()+
534 allMemberList->count()+
536 exampleDict->count();
539 /*! Compute the HTML anchor names for all members in the group */
540 void GroupDef::computeAnchors()
542 //printf("GroupDef::computeAnchors()\n");
543 setAnchors(0,'a',allMemberList);
546 void GroupDef::writeDetailedDescription(OutputList &ol,const QCString &title)
548 if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
549 || !documentation().isEmpty() || !inbodyDocumentation().isEmpty()
552 if (pageDict->count()!=countMembers()) // not only pages -> classical layout
554 ol.pushGeneratorState();
555 ol.disable(OutputGenerator::Html);
557 ol.popGeneratorState();
558 ol.pushGeneratorState();
559 ol.disableAllBut(OutputGenerator::Html);
560 ol.writeAnchor(0,"details");
561 ol.popGeneratorState();
562 ol.startGroupHeader();
567 // repeat brief description
568 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
570 ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
572 // write separator between brief and details
573 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") &&
574 !documentation().isEmpty())
576 ol.pushGeneratorState();
577 ol.disable(OutputGenerator::Man);
578 ol.disable(OutputGenerator::RTF);
579 // ol.newParagraph(); // FIXME:PARA
581 ol.disableAllBut(OutputGenerator::Man);
582 ol.writeString("\n\n");
583 ol.popGeneratorState();
586 // write detailed documentation
587 if (!documentation().isEmpty())
589 ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
592 // write inbody documentation
593 if (!inbodyDocumentation().isEmpty())
595 ol.parseDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE);
600 void GroupDef::writeBriefDescription(OutputList &ol)
602 if (!briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
605 ol.parseDoc(briefFile(),briefLine(),this,0,
606 briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
607 ol.pushGeneratorState();
608 ol.disable(OutputGenerator::RTF);
609 ol.writeString(" \n");
610 ol.enable(OutputGenerator::RTF);
612 if (Config_getBool("REPEAT_BRIEF") ||
613 !documentation().isEmpty()
616 ol.disableAllBut(OutputGenerator::Html);
617 ol.startTextLink(0,"details");
618 ol.parseText(theTranslator->trMore());
621 ol.popGeneratorState();
626 void GroupDef::writeGroupGraph(OutputList &ol)
628 if (Config_getBool("HAVE_DOT") /*&& Config_getBool("GROUP_GRAPHS")*/ )
630 DotGroupCollaboration graph(this);
631 if (!graph.isTrivial())
633 msg("Generating dependency graph for group %s\n",qualifiedName().data());
634 ol.pushGeneratorState();
635 ol.disable(OutputGenerator::Man);
636 //ol.startParagraph();
637 ol.startGroupCollaboration();
638 ol.parseText(theTranslator->trCollaborationDiagram(title));
639 ol.endGroupCollaboration(graph);
641 ol.popGeneratorState();
646 void GroupDef::writeFiles(OutputList &ol,const QCString &title)
648 // write list of files
649 if (fileList->count()>0)
651 ol.startMemberHeader("files");
653 ol.endMemberHeader();
654 ol.startMemberList();
655 FileDef *fd=fileList->first();
658 ol.startMemberDeclaration();
659 ol.startMemberItem(fd->getOutputFileBase(),0);
660 ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");
661 ol.insertMemberAlign();
662 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
663 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
665 Doxygen::tagFile << " <file>" << convertToXML(fd->name()) << "</file>" << endl;
668 if (!fd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
670 ol.startMemberDescription(fd->getOutputFileBase());
671 ol.parseDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
672 ol.endMemberDescription();
674 ol.endMemberDeclaration(0,0);
681 void GroupDef::writeNamespaces(OutputList &ol,const QCString &title)
683 // write list of namespaces
684 namespaceSDict->writeDeclaration(ol,title);
687 void GroupDef::writeNestedGroups(OutputList &ol,const QCString &title)
689 // write list of groups
691 if (groupList->count()>0)
693 GroupDef *gd=groupList->first();
696 if (gd->isVisible()) count++;
697 gd=groupList->next();
702 ol.startMemberHeader("groups");
704 ol.endMemberHeader();
705 ol.startMemberList();
706 if (Config_getBool("SORT_GROUP_NAMES"))
710 GroupDef *gd=groupList->first();
715 ol.startMemberDeclaration();
716 ol.startMemberItem(gd->getOutputFileBase(),0);
717 //ol.docify(theTranslator->trGroup(FALSE,TRUE));
719 ol.insertMemberAlign();
720 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),0,gd->groupTitle());
721 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
723 Doxygen::tagFile << " <subgroup>" << convertToXML(gd->name()) << "</subgroup>" << endl;
726 if (!gd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
728 ol.startMemberDescription(gd->getOutputFileBase());
729 ol.parseDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
730 ol.endMemberDescription();
732 ol.endMemberDeclaration(0,0);
734 gd=groupList->next();
740 void GroupDef::writeDirs(OutputList &ol,const QCString &title)
742 // write list of directories
743 if (dirList->count()>0)
745 ol.startMemberHeader("dirs");
747 ol.endMemberHeader();
748 ol.startMemberList();
749 DirDef *dd=dirList->first();
752 ol.startMemberDeclaration();
753 ol.startMemberItem(dd->getOutputFileBase(),0);
754 ol.parseText(theTranslator->trDir(FALSE,TRUE));
755 ol.insertMemberAlign();
756 ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),0,dd->shortName());
758 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
760 Doxygen::tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;
762 if (!dd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
764 ol.startMemberDescription(dd->getOutputFileBase());
765 ol.parseDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
766 ol.endMemberDescription();
768 ol.endMemberDeclaration(0,0);
776 void GroupDef::writeClasses(OutputList &ol,const QCString &title)
778 // write list of classes
779 classSDict->writeDeclaration(ol,0,title,FALSE);
782 void GroupDef::writeInlineClasses(OutputList &ol)
784 classSDict->writeDocumentation(ol);
787 void GroupDef::writePageDocumentation(OutputList &ol)
790 PageSDict::Iterator pdi(*pageDict);
791 for (pdi.toFirst();(pd=pdi.current());++pdi)
793 if (!pd->isReference())
795 QCString pageName = pd->getOutputFileBase();
797 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
799 Doxygen::tagFile << " <page>" << convertToXML(pageName) << "</page>" << endl;
803 if (!pd->title().isEmpty() && !pd->name().isEmpty() &&
804 (si=Doxygen::sectionDict[pd->name()])!=0)
806 ol.startSection(si->label,si->title,SectionInfo::Subsection);
807 ol.docify(si->title);
808 ol.endSection(si->label,SectionInfo::Subsection);
811 ol.parseDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE,0,TRUE,FALSE);
817 void GroupDef::writeMemberGroups(OutputList &ol)
819 /* write user defined member groups */
820 if (memberGroupSDict)
822 memberGroupSDict->sort();
823 /* write user defined member groups */
824 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
826 for (;(mg=mgli.current());++mgli)
828 mg->writeDeclarations(ol,0,0,0,this);
833 void GroupDef::startMemberDeclarations(OutputList &ol)
835 ol.startMemberSections();
838 void GroupDef::endMemberDeclarations(OutputList &ol)
840 ol.endMemberSections();
843 void GroupDef::startMemberDocumentation(OutputList &ol)
845 //printf("** GroupDef::startMemberDocumentation()\n");
846 if (Config_getBool("SEPARATE_MEMBER_PAGES"))
848 ol.pushGeneratorState();
849 ol.disable(OutputGenerator::Html);
850 Doxygen::suppressDocWarnings = TRUE;
854 void GroupDef::endMemberDocumentation(OutputList &ol)
856 //printf("** GroupDef::endMemberDocumentation()\n");
857 if (Config_getBool("SEPARATE_MEMBER_PAGES"))
859 ol.popGeneratorState();
860 Doxygen::suppressDocWarnings = FALSE;
864 void GroupDef::writeAuthorSection(OutputList &ol)
866 // write Author section (Man only)
867 ol.pushGeneratorState();
868 ol.disableAllBut(OutputGenerator::Man);
869 ol.startGroupHeader();
870 ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
872 ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME")));
873 ol.popGeneratorState();
876 void GroupDef::writeSummaryLinks(OutputList &ol)
878 ol.pushGeneratorState();
879 ol.disableAllBut(OutputGenerator::Html);
880 QListIterator<LayoutDocEntry> eli(
881 LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
884 SrcLangExt lang = getLanguage();
885 for (eli.toFirst();(lde=eli.current());++eli)
887 if ((lde->kind()==LayoutDocEntry::GroupClasses && classSDict->declVisible()) ||
888 (lde->kind()==LayoutDocEntry::GroupNamespaces && namespaceSDict->declVisible()) ||
889 (lde->kind()==LayoutDocEntry::GroupFiles && fileList->count()>0) ||
890 (lde->kind()==LayoutDocEntry::GroupNestedGroups && groupList->count()>0) ||
891 (lde->kind()==LayoutDocEntry::GroupDirs && dirList->count()>0)
894 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
895 QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" :
896 lde->kind()==LayoutDocEntry::GroupNamespaces ? "namespaces" :
897 lde->kind()==LayoutDocEntry::GroupFiles ? "files" :
898 lde->kind()==LayoutDocEntry::GroupNestedGroups ? "groups" :
900 ol.writeSummaryLink(0,label,ls->title(lang),first);
903 else if (lde->kind()==LayoutDocEntry::MemberDecl)
905 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
906 MemberList * ml = getMemberList(lmd->type);
907 if (ml && ml->declVisible())
909 ol.writeSummaryLink(0,ml->listTypeAsString(),lmd->title(lang),first);
916 ol.writeString(" </div>\n");
918 ol.popGeneratorState();
921 void GroupDef::writeDocumentation(OutputList &ol)
923 //static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
924 ol.pushGeneratorState();
925 startFile(ol,getOutputFileBase(),name(),title,HLI_None);
927 ol.startHeaderSection();
928 writeSummaryLinks(ol);
929 ol.startTitleHead(getOutputFileBase());
930 ol.pushGeneratorState();
931 ol.disable(OutputGenerator::Man);
933 ol.popGeneratorState();
934 ol.endTitleHead(getOutputFileBase(),title);
935 addGroupListToTitle(ol,this);
936 ol.endHeaderSection();
939 if (Doxygen::searchIndex)
941 Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
942 static QRegExp we("[a-zA-Z_][-a-zA-Z_0-9]*");
944 while ((i=we.match(title,p,&l))!=-1) // foreach word in the title
946 Doxygen::searchIndex->addWord(title.mid(i,l),TRUE);
951 Doxygen::indexList.addIndexItem(this,0,title);
953 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
955 Doxygen::tagFile << " <compound kind=\"group\">" << endl;
956 Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl;
957 Doxygen::tagFile << " <title>" << convertToXML(title) << "</title>" << endl;
958 Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
962 //---------------------------------------- start flexible part -------------------------------
964 SrcLangExt lang=getLanguage();
965 QListIterator<LayoutDocEntry> eli(
966 LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
968 for (eli.toFirst();(lde=eli.current());++eli)
972 case LayoutDocEntry::BriefDesc:
973 writeBriefDescription(ol);
975 case LayoutDocEntry::MemberDeclStart:
976 startMemberDeclarations(ol);
978 case LayoutDocEntry::GroupClasses:
980 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
981 writeClasses(ol,ls->title(lang));
984 case LayoutDocEntry::GroupInlineClasses:
986 writeInlineClasses(ol);
989 case LayoutDocEntry::GroupNamespaces:
991 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
992 writeNamespaces(ol,ls->title(lang));
995 case LayoutDocEntry::MemberGroups:
996 writeMemberGroups(ol);
998 case LayoutDocEntry::MemberDecl:
1000 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
1001 writeMemberDeclarations(ol,lmd->type,lmd->title(lang));
1004 case LayoutDocEntry::MemberDeclEnd:
1005 endMemberDeclarations(ol);
1007 case LayoutDocEntry::DetailedDesc:
1009 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1010 writeDetailedDescription(ol,ls->title(lang));
1013 case LayoutDocEntry::MemberDefStart:
1014 startMemberDocumentation(ol);
1016 case LayoutDocEntry::MemberDef:
1018 LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
1019 writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
1022 case LayoutDocEntry::MemberDefEnd:
1023 endMemberDocumentation(ol);
1025 case LayoutDocEntry::GroupNestedGroups:
1027 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1028 writeNestedGroups(ol,ls->title(lang));
1031 case LayoutDocEntry::GroupPageDocs:
1032 writePageDocumentation(ol);
1034 case LayoutDocEntry::GroupDirs:
1036 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1037 writeDirs(ol,ls->title(lang));
1040 case LayoutDocEntry::GroupFiles:
1042 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1043 writeFiles(ol,ls->title(lang));
1046 case LayoutDocEntry::GroupGraph:
1047 writeGroupGraph(ol);
1049 case LayoutDocEntry::AuthorSection:
1050 writeAuthorSection(ol);
1052 case LayoutDocEntry::ClassIncludes:
1053 case LayoutDocEntry::ClassInheritanceGraph:
1054 case LayoutDocEntry::ClassNestedClasses:
1055 case LayoutDocEntry::ClassCollaborationGraph:
1056 case LayoutDocEntry::ClassAllMembersLink:
1057 case LayoutDocEntry::ClassUsedFiles:
1058 case LayoutDocEntry::ClassInlineClasses:
1059 case LayoutDocEntry::NamespaceNestedNamespaces:
1060 case LayoutDocEntry::NamespaceClasses:
1061 case LayoutDocEntry::NamespaceInlineClasses:
1062 case LayoutDocEntry::FileClasses:
1063 case LayoutDocEntry::FileNamespaces:
1064 case LayoutDocEntry::FileIncludes:
1065 case LayoutDocEntry::FileIncludeGraph:
1066 case LayoutDocEntry::FileIncludedByGraph:
1067 case LayoutDocEntry::FileSourceLink:
1068 case LayoutDocEntry::FileInlineClasses:
1069 case LayoutDocEntry::DirSubDirs:
1070 case LayoutDocEntry::DirFiles:
1071 case LayoutDocEntry::DirGraph:
1072 err("Internal inconsistency: member %d should not be part of "
1073 "LayoutDocManager::Group entry list\n",lde->kind());
1078 //---------------------------------------- end flexible part -------------------------------
1082 ol.popGeneratorState();
1084 if (!Config_getString("GENERATE_TAGFILE").isEmpty())
1086 writeDocAnchorsToTagFile();
1087 Doxygen::tagFile << " </compound>" << endl;
1090 if (Config_getBool("SEPARATE_MEMBER_PAGES"))
1092 allMemberList->sort();
1093 writeMemberPages(ol);
1098 void GroupDef::writeMemberPages(OutputList &ol)
1100 ol.pushGeneratorState();
1101 ol.disableAllBut(OutputGenerator::Html);
1103 QListIterator<MemberList> mli(m_memberLists);
1105 for (mli.toFirst();(ml=mli.current());++mli)
1107 if (ml->listType()&MemberList::documentationLists)
1109 ml->writeDocumentationPage(ol,name(),this);
1113 ol.popGeneratorState();
1116 void GroupDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
1118 static bool createSubDirs=Config_getBool("CREATE_SUBDIRS");
1120 ol.writeString(" <div class=\"navtab\">\n");
1121 ol.writeString(" <table>\n");
1123 MemberListIterator mli(*allMemberList);
1125 for (mli.toFirst();(md=mli.current());++mli)
1127 if (md->getGroupDef()==this && md->isLinkable())
1129 ol.writeString(" <tr><td class=\"navtab\">");
1130 if (md->isLinkableInProject())
1132 if (md==currentMd) // selected item => highlight
1134 ol.writeString("<a class=\"qindexHL\" ");
1138 ol.writeString("<a class=\"qindex\" ");
1140 ol.writeString("href=\"");
1141 if (createSubDirs) ol.writeString("../../");
1142 ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
1143 ol.writeString("\">");
1144 ol.writeString(convertToHtml(md->localName()));
1145 ol.writeString("</a>");
1147 ol.writeString("</td></tr>\n");
1151 ol.writeString(" </table>\n");
1152 ol.writeString(" </div>\n");
1157 //---- helper functions ------------------------------------------------------
1159 void addClassToGroups(Entry *root,ClassDef *cd)
1161 QListIterator<Grouping> gli(*root->groups);
1163 for (;(g=gli.current());++gli)
1166 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1168 if (gd->addClass(cd))
1170 cd->makePartOfGroup(gd);
1172 //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle());
1177 void addNamespaceToGroups(Entry *root,NamespaceDef *nd)
1179 //printf("root->groups->count()=%d\n",root->groups->count());
1180 QListIterator<Grouping> gli(*root->groups);
1182 for (;(g=gli.current());++gli)
1185 //printf("group `%s'\n",s->data());
1186 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1188 if (gd->addNamespace(nd)) nd->makePartOfGroup(gd);
1189 //printf("Namespace %s: in group %s\n",nd->name().data(),s->data());
1194 void addDirToGroups(Entry *root,DirDef *dd)
1196 //printf("*** root->groups->count()=%d\n",root->groups->count());
1197 QListIterator<Grouping> gli(*root->groups);
1199 for (;(g=gli.current());++gli)
1202 //printf("group `%s'\n",g->groupname.data());
1203 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1206 dd->makePartOfGroup(gd);
1207 //printf("Dir %s: in group %s\n",dd->name().data(),g->groupname.data());
1212 void addGroupToGroups(Entry *root,GroupDef *subGroup)
1214 //printf("addGroupToGroups for %s groups=%d\n",root->name.data(),
1215 // root->groups?root->groups->count():-1);
1216 QListIterator<Grouping> gli(*root->groups);
1218 for (;(g=gli.current());++gli)
1221 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)) &&
1222 !gd->containsGroup(subGroup) )
1224 gd->addGroup(subGroup);
1225 subGroup->makePartOfGroup(gd);
1227 else if (gd==subGroup)
1229 warn(root->fileName,root->startLine,"Trying to add group %s to itself!",
1235 /*! Add a member to the group with the highest priority */
1236 void addMemberToGroups(Entry *root,MemberDef *md)
1238 //printf("addMemberToGroups: Root %p = %s, md %p=%s groups=%d\n",
1239 // root, root->name.data(), md, md->name().data(), root->groups->count() );
1240 QListIterator<Grouping> gli(*root->groups);
1243 // Search entry's group list for group with highest pri.
1244 Grouping::GroupPri_t pri = Grouping::GROUPING_LOWEST;
1246 for (;(g=gli.current());++gli)
1249 if (!g->groupname.isEmpty() &&
1250 (gd=Doxygen::groupSDict->find(g->groupname)) &&
1253 if (fgd && gd!=fgd && g->pri==pri)
1255 warn(root->fileName.data(), root->startLine,
1256 "warning: Member %s found in multiple %s groups! "
1257 "The member will be put in group %s, and not in group %s",
1258 md->name().data(), Grouping::getGroupPriName( pri ),
1259 gd->name().data(), fgd->name().data()
1267 //printf("fgd=%p\n",fgd);
1269 // put member into group defined by this entry?
1272 GroupDef *mgd = md->getGroupDef();
1273 //printf("mgd=%p\n",mgd);
1274 bool insertit = FALSE;
1281 bool moveit = FALSE;
1283 // move member from one group to another if
1284 // - the new one has a higher priority
1285 // - the new entry has the same priority, but with docs where the old one had no docs
1286 if (md->getGroupPri()<pri)
1292 if (md->getGroupPri()==pri)
1294 if (!root->doc.isEmpty() && !md->getGroupHasDocs())
1298 else if (!root->doc.isEmpty() && md->getGroupHasDocs())
1300 warn(md->getGroupFileName(),md->getGroupStartLine(),
1301 "warning: Member documentation for %s found several times in %s groups!\n"
1302 "%s:%d: The member will remain in group %s, and won't be put into group %s",
1303 md->name().data(), Grouping::getGroupPriName( pri ),
1304 root->fileName.data(), root->startLine,
1314 //printf("removeMember\n");
1315 mgd->removeMember(md);
1322 //printf("insertMember found at %s line %d: %s: related %s\n",
1323 // md->getDefFileName().data(),md->getDefLine(),
1324 // md->name().data(),root->relates.data());
1325 bool success = fgd->insertMember(md);
1328 //printf("insertMember successful\n");
1329 md->setGroupDef(fgd,pri,root->fileName,root->startLine,
1330 !root->doc.isEmpty());
1331 ClassDef *cd = md->getClassDefOfAnonymousType();
1334 cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0);
1342 void addExampleToGroups(Entry *root,PageDef *eg)
1344 QListIterator<Grouping> gli(*root->groups);
1346 for (;(g=gli.current());++gli)
1349 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1352 eg->makePartOfGroup(gd);
1353 //printf("Example %s: in group %s\n",eg->name().data(),s->data());
1358 QCString GroupDef::getOutputFileBase() const
1366 return convertNameToFile(fileName);
1370 void GroupDef::addListReferences()
1373 LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems();
1374 addRefItem(xrefItems.pointer(),
1375 getOutputFileBase(),
1376 theTranslator->trGroup(TRUE,TRUE),
1377 getOutputFileBase(),name(),
1381 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
1383 for (;(mg=mgli.current());++mgli)
1385 mg->addListReferences(this);
1387 QListIterator<MemberList> mli(m_memberLists);
1389 for (mli.toFirst();(ml=mli.current());++mli)
1391 if (ml->listType()&MemberList::documentationLists)
1393 ml->addListReferences(this);
1398 MemberList *GroupDef::createMemberList(MemberList::ListType lt)
1400 m_memberLists.setAutoDelete(TRUE);
1401 QListIterator<MemberList> mli(m_memberLists);
1403 for (mli.toFirst();(ml=mli.current());++mli)
1405 if (ml->listType()==lt)
1410 // not found, create a new member list
1411 ml = new MemberList(lt);
1412 m_memberLists.append(ml);
1413 ml->setInGroup(TRUE);
1417 void GroupDef::addMemberToList(MemberList::ListType lt,MemberDef *md)
1419 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
1420 static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS");
1421 MemberList *ml = createMemberList(lt);
1422 ml->setNeedsSorting(
1423 ((ml->listType()&MemberList::declarationLists) && sortBriefDocs) ||
1424 ((ml->listType()&MemberList::documentationLists) && sortMemberDocs));
1428 void GroupDef::sortMemberLists()
1430 MemberList *ml = m_memberLists.first();
1433 if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
1434 ml = m_memberLists.next();
1439 MemberList *GroupDef::getMemberList(MemberList::ListType lt) const
1441 GroupDef *that = (GroupDef*)this;
1442 MemberList *ml = that->m_memberLists.first();
1445 if (ml->listType()==lt)
1449 ml = that->m_memberLists.next();
1454 void GroupDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title)
1456 static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
1458 MemberList * ml = getMemberList(lt);
1459 if (optimizeVhdl && ml)
1461 VhdlDocGen::writeVhdlDeclarations(ml,ol,this,0,0,0);
1466 ml->writeDeclarations(ol,0,0,0,this,title,0);
1470 void GroupDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title)
1472 MemberList * ml = getMemberList(lt);
1473 if (ml) ml->writeDocumentation(ol,name(),this,title);
1476 void GroupDef::removeMemberFromList(MemberList::ListType lt,MemberDef *md)
1478 MemberList *ml = getMemberList(lt);
1479 if (ml) ml->remove(md);
1482 void GroupDef::sortSubGroups()
1487 bool GroupDef::isLinkableInProject() const
1489 return !isReference() && isLinkable();
1492 bool GroupDef::isLinkable() const
1494 return hasUserDocumentation();
1497 // let the "programming language" for a group depend on what is inserted into it.
1498 // First item that has an associated languages determines the language for the whole group.
1499 void GroupDef::updateLanguage(const Definition *d)
1501 if (getLanguage()==SrcLangExt_Unknown && d->getLanguage()!=SrcLangExt_Unknown)
1503 setLanguage(d->getLanguage());