1 /******************************************************************************
5 * Copyright (C) 1997-2015 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 = convertNameToFile(QCString("group_")+na);
67 memberGroupSDict = new MemberGroupSDict;
68 memberGroupSDict->setAutoDelete(TRUE);
70 allMemberList = new MemberList(MemberListType_allMembersList);
74 m_subGrouping=Config_getBool(SUBGROUPING);
82 delete namespaceSDict;
86 delete allMemberNameInfoSDict;
87 delete memberGroupSDict;
91 void GroupDef::setGroupTitle( const char *t )
93 if ( t && qstrlen(t) )
101 title.at(0)=toupper(title.at(0));
107 void GroupDef::distributeMemberGroupDocumentation()
109 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
111 for (;(mg=mgli.current());++mgli)
113 mg->distributeMemberGroupDocumentation();
117 void GroupDef::findSectionsInDocumentation()
119 docFindSections(documentation(),this,0,docFile());
120 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
122 for (;(mg=mgli.current());++mgli)
124 mg->findSectionsInDocumentation();
127 QListIterator<MemberList> mli(m_memberLists);
129 for (mli.toFirst();(ml=mli.current());++mli)
131 if (ml->listType()&MemberListType_declarationLists)
133 ml->findSectionsInDocumentation();
138 void GroupDef::addFile(const FileDef *def)
140 static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
141 if (def->isHidden()) return;
144 fileList->inSort(def);
146 fileList->append(def);
149 bool GroupDef::addClass(const ClassDef *cd)
151 static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
152 if (cd->isHidden()) return FALSE;
154 QCString qn = cd->name();
155 if (classSDict->find(qn)==0)
157 //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs);
160 classSDict->inSort(qn,cd);
164 int i=qn.findRev("::");
165 if (i==-1) i=qn.find('.');
167 //printf("i=%d\n",i);
170 // add nested classes (e.g. A::B, A::C) after their parent (A) in
171 // order of insertion
172 QCString scope = qn.left(i);
173 int j=classSDict->findAt(scope);
176 while (j<(int)classSDict->count() &&
177 classSDict->at(j)->qualifiedName().left(i)==scope)
179 //printf("skipping over %s\n",classSDict->at(j)->qualifiedName().data());
182 //printf("Found scope at index %d\n",j);
183 classSDict->insertAt(j,qn,cd);
187 if (!found) // no insertion point found -> just append
189 classSDict->append(qn,cd);
197 bool GroupDef::addNamespace(const NamespaceDef *def)
199 static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
200 if (def->isHidden()) return FALSE;
202 if (namespaceSDict->find(def->name())==0)
205 namespaceSDict->inSort(def->name(),def);
207 namespaceSDict->append(def->name(),def);
213 void GroupDef::addDir(const DirDef *def)
215 if (def->isHidden()) return;
216 if (Config_getBool(SORT_BRIEF_DOCS))
217 dirList->inSort(def);
219 dirList->append(def);
222 void GroupDef::addPage(PageDef *def)
224 if (def->isHidden()) return;
225 //printf("Making page %s part of a group\n",def->name.data());
226 pageDict->append(def->name(),def);
227 def->makePartOfGroup(this);
230 void GroupDef::addExample(const PageDef *def)
232 if (def->isHidden()) return;
233 exampleDict->append(def->name(),def);
237 void GroupDef::addMembersToMemberGroup()
239 QListIterator<MemberList> mli(m_memberLists);
241 for (mli.toFirst();(ml=mli.current());++mli)
243 if (ml->listType()&MemberListType_declarationLists)
245 ::addMembersToMemberGroup(ml,&memberGroupSDict,this);
249 //printf("GroupDef::addMembersToMemberGroup() memberGroupList=%d\n",memberGroupList->count());
250 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
252 for (;(mg=mgli.current());++mgli)
254 mg->setInGroup(TRUE);
259 bool GroupDef::insertMember(MemberDef *md,bool docOnly)
261 if (md->isHidden()) return FALSE;
263 //printf("GroupDef(%s)::insertMember(%s)\n", title.data(), md->name().data());
264 MemberNameInfo *mni=0;
265 if ((mni=(*allMemberNameInfoSDict)[md->name()]))
266 { // member with this name already found
267 MemberNameInfoIterator srcMnii(*mni);
269 for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
271 MemberDef *srcMd = srcMi->memberDef;
272 if (srcMd==md) return FALSE; // already added before!
274 bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace
275 // both inside a file => definition and declaration do not have to be in the same file
276 (srcMd->getOuterScope()->definitionType()==Definition::TypeFile &&
277 md->getOuterScope()->definitionType()==Definition::TypeFile);
279 ArgumentList *srcMdAl = srcMd->argumentList();
280 ArgumentList *mdAl = md->argumentList();
281 ArgumentList *tSrcMdAl = srcMd->templateArguments();
282 ArgumentList *tMdAl = md->templateArguments();
284 if (srcMd->isFunction() && md->isFunction() && // both are a function
285 ((tSrcMdAl==0 && tMdAl==0) ||
286 (tSrcMdAl!=0 && tMdAl!=0 && tSrcMdAl->count()==tMdAl->count())
287 ) && // same number of template arguments
288 matchArguments2(srcMd->getOuterScope(),srcMd->getFileDef(),srcMdAl,
289 md->getOuterScope(),md->getFileDef(),mdAl,
291 ) && // matching parameters
292 sameScope // both are found in the same scope
295 if (srcMd->getGroupAlias()==0)
297 md->setGroupAlias(srcMd);
299 else if (md!=srcMd->getGroupAlias())
301 md->setGroupAlias(srcMd->getGroupAlias());
303 return FALSE; // member is the same as one that is already added
306 mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
310 mni = new MemberNameInfo(md->name());
311 mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
312 allMemberNameInfoSDict->append(mni->memberName(),mni);
314 //printf("Added member!\n");
315 allMemberList->append(md);
316 switch(md->memberType())
318 case MemberType_Variable:
321 addMemberToList(MemberListType_decVarMembers,md);
323 addMemberToList(MemberListType_docVarMembers,md);
325 case MemberType_Function:
328 addMemberToList(MemberListType_decFuncMembers,md);
330 addMemberToList(MemberListType_docFuncMembers,md);
332 case MemberType_Typedef:
335 addMemberToList(MemberListType_decTypedefMembers,md);
337 addMemberToList(MemberListType_docTypedefMembers,md);
339 case MemberType_Enumeration:
342 addMemberToList(MemberListType_decEnumMembers,md);
344 addMemberToList(MemberListType_docEnumMembers,md);
346 case MemberType_EnumValue:
349 addMemberToList(MemberListType_decEnumValMembers,md);
351 addMemberToList(MemberListType_docEnumValMembers,md);
353 case MemberType_Define:
356 addMemberToList(MemberListType_decDefineMembers,md);
358 addMemberToList(MemberListType_docDefineMembers,md);
360 case MemberType_Signal:
363 addMemberToList(MemberListType_decSignalMembers,md);
365 addMemberToList(MemberListType_docSignalMembers,md);
367 case MemberType_Slot:
368 if (md->protection()==Public)
372 addMemberToList(MemberListType_decPubSlotMembers,md);
374 addMemberToList(MemberListType_docPubSlotMembers,md);
376 else if (md->protection()==Protected)
380 addMemberToList(MemberListType_decProSlotMembers,md);
382 addMemberToList(MemberListType_docProSlotMembers,md);
388 addMemberToList(MemberListType_decPriSlotMembers,md);
390 addMemberToList(MemberListType_docPriSlotMembers,md);
393 case MemberType_Event:
396 addMemberToList(MemberListType_decEventMembers,md);
398 addMemberToList(MemberListType_docEventMembers,md);
400 case MemberType_Property:
403 addMemberToList(MemberListType_decPropMembers,md);
405 addMemberToList(MemberListType_docPropMembers,md);
407 case MemberType_Friend:
410 addMemberToList(MemberListType_decFriendMembers,md);
412 addMemberToList(MemberListType_docFriendMembers,md);
415 err("GroupDef::insertMembers(): "
416 "member `%s' (typeid=%d) with scope `%s' inserted in group scope `%s'!\n",
417 md->name().data(),md->memberType(),
418 md->getClassDef() ? md->getClassDef()->name().data() : "",
424 void GroupDef::removeMember(MemberDef *md)
426 // fprintf(stderr, "GroupDef(%s)::removeMember( %s )\n", title.data(), md->name().data());
427 MemberNameInfo *mni = allMemberNameInfoSDict->find(md->name());
430 MemberNameInfoIterator mnii(*mni);
431 while( mnii.current() )
433 if( mnii.current()->memberDef == md )
435 mni->remove(mnii.current());
442 allMemberNameInfoSDict->remove(md->name());
445 removeMemberFromList(MemberListType_allMembersList,md);
446 switch(md->memberType())
448 case MemberType_Variable:
449 removeMemberFromList(MemberListType_decVarMembers,md);
450 removeMemberFromList(MemberListType_docVarMembers,md);
452 case MemberType_Function:
453 removeMemberFromList(MemberListType_decFuncMembers,md);
454 removeMemberFromList(MemberListType_docFuncMembers,md);
456 case MemberType_Typedef:
457 removeMemberFromList(MemberListType_decTypedefMembers,md);
458 removeMemberFromList(MemberListType_docTypedefMembers,md);
460 case MemberType_Enumeration:
461 removeMemberFromList(MemberListType_decEnumMembers,md);
462 removeMemberFromList(MemberListType_docEnumMembers,md);
464 case MemberType_EnumValue:
465 removeMemberFromList(MemberListType_decEnumValMembers,md);
466 removeMemberFromList(MemberListType_docEnumValMembers,md);
468 case MemberType_Define:
469 removeMemberFromList(MemberListType_decDefineMembers,md);
470 removeMemberFromList(MemberListType_docDefineMembers,md);
472 case MemberType_Signal:
473 removeMemberFromList(MemberListType_decSignalMembers,md);
474 removeMemberFromList(MemberListType_docSignalMembers,md);
476 case MemberType_Slot:
477 if (md->protection()==Public)
479 removeMemberFromList(MemberListType_decPubSlotMembers,md);
480 removeMemberFromList(MemberListType_docPubSlotMembers,md);
482 else if (md->protection()==Protected)
484 removeMemberFromList(MemberListType_decProSlotMembers,md);
485 removeMemberFromList(MemberListType_docProSlotMembers,md);
489 removeMemberFromList(MemberListType_decPriSlotMembers,md);
490 removeMemberFromList(MemberListType_docPriSlotMembers,md);
493 case MemberType_Event:
494 removeMemberFromList(MemberListType_decEventMembers,md);
495 removeMemberFromList(MemberListType_docEventMembers,md);
497 case MemberType_Property:
498 removeMemberFromList(MemberListType_decPropMembers,md);
499 removeMemberFromList(MemberListType_docPropMembers,md);
501 case MemberType_Friend:
502 removeMemberFromList(MemberListType_decFriendMembers,md);
503 removeMemberFromList(MemberListType_docFriendMembers,md);
506 err("GroupDef::removeMember(): unexpected member remove in file!\n");
511 bool GroupDef::findGroup(const GroupDef *def) const
519 GroupListIterator it(*groupList);
521 for (;(gd=it.current());++it)
523 if (gd->findGroup(def))
532 void GroupDef::addGroup(const GroupDef *def)
534 //printf("adding group `%s' to group `%s'\n",def->name().data(),name().data());
535 //if (Config_getBool(SORT_MEMBER_DOCS))
536 // groupList->inSort(def);
538 groupList->append(def);
541 bool GroupDef::isASubGroup() const
543 GroupList *groups = partOfGroups();
544 return groups!=0 && groups->count()!=0;
547 int GroupDef::countMembers() const
549 return fileList->count()+
551 namespaceSDict->count()+
553 allMemberList->count()+
555 exampleDict->count();
558 /*! Compute the HTML anchor names for all members in the group */
559 void GroupDef::computeAnchors()
561 //printf("GroupDef::computeAnchors()\n");
562 setAnchors(allMemberList);
565 void GroupDef::writeTagFile(FTextStream &tagFile)
567 tagFile << " <compound kind=\"group\">" << endl;
568 tagFile << " <name>" << convertToXML(name()) << "</name>" << endl;
569 tagFile << " <title>" << convertToXML(title) << "</title>" << endl;
570 tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
571 QListIterator<LayoutDocEntry> eli(
572 LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
574 for (eli.toFirst();(lde=eli.current());++eli)
578 case LayoutDocEntry::GroupClasses:
582 SDict<ClassDef>::Iterator ci(*classSDict);
584 for (ci.toFirst();(cd=ci.current());++ci)
586 if (cd->isLinkableInProject())
588 tagFile << " <class kind=\"" << cd->compoundTypeString()
589 << "\">" << convertToXML(cd->name()) << "</class>" << endl;
595 case LayoutDocEntry::GroupNamespaces:
599 SDict<NamespaceDef>::Iterator ni(*namespaceSDict);
601 for (ni.toFirst();(nd=ni.current());++ni)
603 if (nd->isLinkableInProject())
605 tagFile << " <namespace>" << convertToXML(nd->name())
606 << "</namespace>" << endl;
612 case LayoutDocEntry::GroupFiles:
616 QListIterator<FileDef> it(*fileList);
618 for (;(fd=it.current());++it)
620 if (fd->isLinkableInProject())
622 tagFile << " <file>" << convertToXML(fd->name()) << "</file>" << endl;
628 case LayoutDocEntry::GroupPageDocs:
632 PageSDict::Iterator pdi(*pageDict);
634 for (pdi.toFirst();(pd=pdi.current());++pdi)
636 QCString pageName = pd->getOutputFileBase();
637 if (pd->isLinkableInProject())
639 tagFile << " <page>" << convertToXML(pageName) << "</page>" << endl;
645 case LayoutDocEntry::GroupDirs:
649 QListIterator<DirDef> it(*dirList);
651 for (;(dd=it.current());++it)
653 if (dd->isLinkableInProject())
655 tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;
661 case LayoutDocEntry::GroupNestedGroups:
665 QListIterator<GroupDef> it(*groupList);
667 for (;(gd=it.current());++it)
671 tagFile << " <subgroup>" << convertToXML(gd->name()) << "</subgroup>" << endl;
677 case LayoutDocEntry::MemberDecl:
679 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
680 MemberList * ml = getMemberList(lmd->type);
683 ml->writeTagFile(tagFile);
687 case LayoutDocEntry::MemberGroups:
689 if (memberGroupSDict)
691 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
693 for (;(mg=mgli.current());++mgli)
695 mg->writeTagFile(tagFile);
704 writeDocAnchorsToTagFile(tagFile);
705 tagFile << " </compound>" << endl;
708 void GroupDef::writeDetailedDescription(OutputList &ol,const QCString &title)
710 if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
711 || !documentation().isEmpty() || !inbodyDocumentation().isEmpty()
714 ol.pushGeneratorState();
715 if (pageDict->count()!=countMembers()) // not only pages -> classical layout
717 ol.pushGeneratorState();
718 ol.disable(OutputGenerator::Html);
720 ol.popGeneratorState();
721 ol.pushGeneratorState();
722 ol.disableAllBut(OutputGenerator::Html);
723 ol.writeAnchor(0,"details");
724 ol.popGeneratorState();
728 ol.disableAllBut(OutputGenerator::Man); // always print title for man page
730 ol.startGroupHeader();
733 ol.popGeneratorState();
735 // repeat brief description
736 if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
738 ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
740 // write separator between brief and details
741 if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) &&
742 !documentation().isEmpty())
744 ol.pushGeneratorState();
745 ol.disable(OutputGenerator::Man);
746 ol.disable(OutputGenerator::RTF);
747 // ol.newParagraph(); // FIXME:PARA
749 ol.disableAllBut(OutputGenerator::Man);
750 ol.enable(OutputGenerator::Latex);
751 ol.writeString("\n\n");
752 ol.popGeneratorState();
755 // write detailed documentation
756 if (!documentation().isEmpty())
758 ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
761 // write inbody documentation
762 if (!inbodyDocumentation().isEmpty())
764 ol.generateDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE);
769 void GroupDef::writeBriefDescription(OutputList &ol)
771 if (hasBriefDescription())
773 DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
774 briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
775 if (rootNode && !rootNode->isEmpty())
778 ol.pushGeneratorState();
779 ol.disableAllBut(OutputGenerator::Man);
780 ol.writeString(" - ");
781 ol.popGeneratorState();
782 ol.writeDoc(rootNode,this,0);
783 ol.pushGeneratorState();
784 ol.disable(OutputGenerator::RTF);
785 ol.writeString(" \n");
786 ol.enable(OutputGenerator::RTF);
788 if (Config_getBool(REPEAT_BRIEF) ||
789 !documentation().isEmpty()
792 ol.disableAllBut(OutputGenerator::Html);
793 ol.startTextLink(0,"details");
794 ol.parseText(theTranslator->trMore());
797 ol.popGeneratorState();
805 void GroupDef::writeGroupGraph(OutputList &ol)
807 if (Config_getBool(HAVE_DOT) /*&& Config_getBool(GROUP_GRAPHS)*/ )
809 DotGroupCollaboration graph(this);
810 if (!graph.isTrivial())
812 msg("Generating dependency graph for group %s\n",qualifiedName().data());
813 ol.pushGeneratorState();
814 ol.disable(OutputGenerator::Man);
815 //ol.startParagraph();
816 ol.startGroupCollaboration();
817 ol.parseText(theTranslator->trCollaborationDiagram(title));
818 ol.endGroupCollaboration(graph);
820 ol.popGeneratorState();
825 void GroupDef::writeFiles(OutputList &ol,const QCString &title)
827 // write list of files
828 if (fileList->count()>0)
830 ol.startMemberHeader("files");
832 ol.endMemberHeader();
833 ol.startMemberList();
834 QListIterator<FileDef> it(*fileList);
836 for (;(fd=it.current());++it)
838 if (!fd->hasDocumentation()) continue;
839 ol.startMemberDeclaration();
840 ol.startMemberItem(fd->getOutputFileBase(),0);
841 ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");
842 ol.insertMemberAlign();
843 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
845 if (!fd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
847 ol.startMemberDescription(fd->getOutputFileBase());
848 ol.generateDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
849 ol.endMemberDescription();
851 ol.endMemberDeclaration(0,0);
857 void GroupDef::writeNamespaces(OutputList &ol,const QCString &title)
859 // write list of namespaces
860 namespaceSDict->writeDeclaration(ol,title);
863 void GroupDef::writeNestedGroups(OutputList &ol,const QCString &title)
865 // write list of groups
867 if (groupList->count()>0)
869 QListIterator<GroupDef> it(*groupList);
871 for (;(gd=it.current());++it)
873 if (gd->isVisible()) count++;
878 ol.startMemberHeader("groups");
880 ol.endMemberHeader();
881 ol.startMemberList();
882 if (Config_getBool(SORT_GROUP_NAMES))
886 QListIterator<GroupDef> it(*groupList);
888 for (;(gd=it.current());++it)
892 if (!gd->hasDocumentation()) continue;
893 ol.startMemberDeclaration();
894 ol.startMemberItem(gd->getOutputFileBase(),0);
895 //ol.docify(theTranslator->trGroup(FALSE,TRUE));
897 ol.insertMemberAlign();
898 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),0,gd->groupTitle());
900 if (!gd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
902 ol.startMemberDescription(gd->getOutputFileBase());
903 ol.generateDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
904 ol.endMemberDescription();
906 ol.endMemberDeclaration(0,0);
913 void GroupDef::writeDirs(OutputList &ol,const QCString &title)
915 // write list of directories
916 if (dirList->count()>0)
918 ol.startMemberHeader("dirs");
920 ol.endMemberHeader();
921 ol.startMemberList();
922 QListIterator<DirDef> it(*dirList);
924 for (;(dd=it.current());++it)
926 if (!dd->hasDocumentation()) continue;
927 ol.startMemberDeclaration();
928 ol.startMemberItem(dd->getOutputFileBase(),0);
929 ol.parseText(theTranslator->trDir(FALSE,TRUE));
930 ol.insertMemberAlign();
931 ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),0,dd->shortName());
933 if (!dd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
935 ol.startMemberDescription(dd->getOutputFileBase());
936 ol.generateDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
937 ol.endMemberDescription();
939 ol.endMemberDeclaration(0,0);
946 void GroupDef::writeClasses(OutputList &ol,const QCString &title)
948 // write list of classes
949 classSDict->writeDeclaration(ol,0,title,FALSE);
952 void GroupDef::writeInlineClasses(OutputList &ol)
954 classSDict->writeDocumentation(ol);
957 void GroupDef::writePageDocumentation(OutputList &ol)
960 PageSDict::Iterator pdi(*pageDict);
961 for (pdi.toFirst();(pd=pdi.current());++pdi)
963 if (!pd->isReference())
966 if (!pd->title().isEmpty() && !pd->name().isEmpty() &&
967 (si=Doxygen::sectionDict->find(pd->name()))!=0)
969 ol.startSection(si->label,si->title,SectionInfo::Subsection);
970 ol.docify(si->title);
971 ol.endSection(si->label,SectionInfo::Subsection);
974 ol.generateDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE,0,TRUE,FALSE);
980 void GroupDef::writeMemberGroups(OutputList &ol)
982 /* write user defined member groups */
983 if (memberGroupSDict)
985 memberGroupSDict->sort();
986 /* write user defined member groups */
987 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
989 for (;(mg=mgli.current());++mgli)
991 mg->writeDeclarations(ol,0,0,0,this);
996 void GroupDef::startMemberDeclarations(OutputList &ol)
998 ol.startMemberSections();
1001 void GroupDef::endMemberDeclarations(OutputList &ol)
1003 ol.endMemberSections();
1006 void GroupDef::startMemberDocumentation(OutputList &ol)
1008 //printf("** GroupDef::startMemberDocumentation()\n");
1009 if (Config_getBool(SEPARATE_MEMBER_PAGES))
1011 ol.pushGeneratorState();
1012 ol.disable(OutputGenerator::Html);
1013 Doxygen::suppressDocWarnings = TRUE;
1017 void GroupDef::endMemberDocumentation(OutputList &ol)
1019 //printf("** GroupDef::endMemberDocumentation()\n");
1020 if (Config_getBool(SEPARATE_MEMBER_PAGES))
1022 ol.popGeneratorState();
1023 Doxygen::suppressDocWarnings = FALSE;
1027 void GroupDef::writeAuthorSection(OutputList &ol)
1029 // write Author section (Man only)
1030 ol.pushGeneratorState();
1031 ol.disableAllBut(OutputGenerator::Man);
1032 ol.startGroupHeader();
1033 ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
1034 ol.endGroupHeader();
1035 ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString(PROJECT_NAME)));
1036 ol.popGeneratorState();
1039 void GroupDef::writeSummaryLinks(OutputList &ol)
1041 ol.pushGeneratorState();
1042 ol.disableAllBut(OutputGenerator::Html);
1043 QListIterator<LayoutDocEntry> eli(
1044 LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
1045 LayoutDocEntry *lde;
1047 SrcLangExt lang = getLanguage();
1048 for (eli.toFirst();(lde=eli.current());++eli)
1050 if ((lde->kind()==LayoutDocEntry::GroupClasses && classSDict->declVisible()) ||
1051 (lde->kind()==LayoutDocEntry::GroupNamespaces && namespaceSDict->declVisible()) ||
1052 (lde->kind()==LayoutDocEntry::GroupFiles && fileList->count()>0) ||
1053 (lde->kind()==LayoutDocEntry::GroupNestedGroups && groupList->count()>0) ||
1054 (lde->kind()==LayoutDocEntry::GroupDirs && dirList->count()>0)
1057 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1058 QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" :
1059 lde->kind()==LayoutDocEntry::GroupNamespaces ? "namespaces" :
1060 lde->kind()==LayoutDocEntry::GroupFiles ? "files" :
1061 lde->kind()==LayoutDocEntry::GroupNestedGroups ? "groups" :
1063 ol.writeSummaryLink(0,label,ls->title(lang),first);
1066 else if (lde->kind()==LayoutDocEntry::MemberDecl)
1068 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
1069 MemberList * ml = getMemberList(lmd->type);
1070 if (ml && ml->declVisible())
1072 ol.writeSummaryLink(0,MemberList::listTypeAsString(ml->listType()),lmd->title(lang),first);
1079 ol.writeString(" </div>\n");
1081 ol.popGeneratorState();
1084 void GroupDef::writeDocumentation(OutputList &ol)
1086 //static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
1087 ol.pushGeneratorState();
1088 startFile(ol,getOutputFileBase(),name(),title,HLI_Modules);
1090 ol.startHeaderSection();
1091 writeSummaryLinks(ol);
1092 ol.startTitleHead(getOutputFileBase());
1093 ol.pushGeneratorState();
1094 ol.disable(OutputGenerator::Man);
1095 ol.parseText(title);
1096 ol.popGeneratorState();
1097 addGroupListToTitle(ol,this);
1098 ol.pushGeneratorState();
1099 ol.disable(OutputGenerator::Man);
1100 ol.endTitleHead(getOutputFileBase(),title);
1101 ol.popGeneratorState();
1102 ol.pushGeneratorState();
1103 ol.disableAllBut(OutputGenerator::Man);
1104 ol.endTitleHead(getOutputFileBase(),name());
1105 ol.popGeneratorState();
1106 ol.endHeaderSection();
1109 if (Doxygen::searchIndex)
1111 Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
1112 static QRegExp we("[a-zA-Z_][-a-zA-Z_0-9]*");
1114 while ((i=we.match(title,p,&l))!=-1) // foreach word in the title
1116 Doxygen::searchIndex->addWord(title.mid(i,l),TRUE);
1121 Doxygen::indexList->addIndexItem(this,0,0,title);
1123 //---------------------------------------- start flexible part -------------------------------
1125 SrcLangExt lang=getLanguage();
1126 QListIterator<LayoutDocEntry> eli(
1127 LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
1128 LayoutDocEntry *lde;
1129 for (eli.toFirst();(lde=eli.current());++eli)
1131 switch (lde->kind())
1133 case LayoutDocEntry::BriefDesc:
1134 writeBriefDescription(ol);
1136 case LayoutDocEntry::MemberDeclStart:
1137 startMemberDeclarations(ol);
1139 case LayoutDocEntry::GroupClasses:
1141 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1142 writeClasses(ol,ls->title(lang));
1145 case LayoutDocEntry::GroupInlineClasses:
1147 writeInlineClasses(ol);
1150 case LayoutDocEntry::GroupNamespaces:
1152 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1153 writeNamespaces(ol,ls->title(lang));
1156 case LayoutDocEntry::MemberGroups:
1157 writeMemberGroups(ol);
1159 case LayoutDocEntry::MemberDecl:
1161 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
1162 writeMemberDeclarations(ol,lmd->type,lmd->title(lang));
1165 case LayoutDocEntry::MemberDeclEnd:
1166 endMemberDeclarations(ol);
1168 case LayoutDocEntry::DetailedDesc:
1170 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1171 writeDetailedDescription(ol,ls->title(lang));
1174 case LayoutDocEntry::MemberDefStart:
1175 startMemberDocumentation(ol);
1177 case LayoutDocEntry::MemberDef:
1179 LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
1180 writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
1183 case LayoutDocEntry::MemberDefEnd:
1184 endMemberDocumentation(ol);
1186 case LayoutDocEntry::GroupNestedGroups:
1188 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1189 writeNestedGroups(ol,ls->title(lang));
1192 case LayoutDocEntry::GroupPageDocs:
1193 writePageDocumentation(ol);
1195 case LayoutDocEntry::GroupDirs:
1197 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1198 writeDirs(ol,ls->title(lang));
1201 case LayoutDocEntry::GroupFiles:
1203 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1204 writeFiles(ol,ls->title(lang));
1207 case LayoutDocEntry::GroupGraph:
1208 writeGroupGraph(ol);
1210 case LayoutDocEntry::AuthorSection:
1211 writeAuthorSection(ol);
1213 case LayoutDocEntry::ClassIncludes:
1214 case LayoutDocEntry::ClassInheritanceGraph:
1215 case LayoutDocEntry::ClassNestedClasses:
1216 case LayoutDocEntry::ClassCollaborationGraph:
1217 case LayoutDocEntry::ClassAllMembersLink:
1218 case LayoutDocEntry::ClassUsedFiles:
1219 case LayoutDocEntry::ClassInlineClasses:
1220 case LayoutDocEntry::NamespaceNestedNamespaces:
1221 case LayoutDocEntry::NamespaceNestedConstantGroups:
1222 case LayoutDocEntry::NamespaceClasses:
1223 case LayoutDocEntry::NamespaceInlineClasses:
1224 case LayoutDocEntry::FileClasses:
1225 case LayoutDocEntry::FileNamespaces:
1226 case LayoutDocEntry::FileConstantGroups:
1227 case LayoutDocEntry::FileIncludes:
1228 case LayoutDocEntry::FileIncludeGraph:
1229 case LayoutDocEntry::FileIncludedByGraph:
1230 case LayoutDocEntry::FileSourceLink:
1231 case LayoutDocEntry::FileInlineClasses:
1232 case LayoutDocEntry::DirSubDirs:
1233 case LayoutDocEntry::DirFiles:
1234 case LayoutDocEntry::DirGraph:
1235 err("Internal inconsistency: member %d should not be part of "
1236 "LayoutDocManager::Group entry list\n",lde->kind());
1241 //---------------------------------------- end flexible part -------------------------------
1245 ol.popGeneratorState();
1247 if (Config_getBool(SEPARATE_MEMBER_PAGES))
1249 allMemberList->sort();
1250 writeMemberPages(ol);
1255 void GroupDef::writeMemberPages(OutputList &ol)
1257 ol.pushGeneratorState();
1258 ol.disableAllBut(OutputGenerator::Html);
1260 QListIterator<MemberList> mli(m_memberLists);
1262 for (mli.toFirst();(ml=mli.current());++mli)
1264 if (ml->listType()&MemberListType_documentationLists)
1266 ml->writeDocumentationPage(ol,name(),this);
1270 ol.popGeneratorState();
1273 void GroupDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
1275 static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
1277 ol.writeString(" <div class=\"navtab\">\n");
1278 ol.writeString(" <table>\n");
1280 MemberListIterator mli(*allMemberList);
1282 for (mli.toFirst();(md=mli.current());++mli)
1284 if (md->getGroupDef()==this && md->isLinkable() && !md->isEnumValue())
1286 ol.writeString(" <tr><td class=\"navtab\">");
1287 if (md->isLinkableInProject())
1289 if (md==currentMd) // selected item => highlight
1291 ol.writeString("<a class=\"qindexHL\" ");
1295 ol.writeString("<a class=\"qindex\" ");
1297 ol.writeString("href=\"");
1298 if (createSubDirs) ol.writeString("../../");
1299 ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
1300 ol.writeString("\">");
1301 ol.writeString(convertToHtml(md->localName()));
1302 ol.writeString("</a>");
1304 ol.writeString("</td></tr>\n");
1308 ol.writeString(" </table>\n");
1309 ol.writeString(" </div>\n");
1314 //---- helper functions ------------------------------------------------------
1316 void addClassToGroups(Entry *root,ClassDef *cd)
1318 QListIterator<Grouping> gli(*root->groups);
1320 for (;(g=gli.current());++gli)
1323 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1325 if (gd->addClass(cd))
1327 cd->makePartOfGroup(gd);
1329 //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle());
1334 void addNamespaceToGroups(Entry *root,NamespaceDef *nd)
1336 //printf("root->groups->count()=%d\n",root->groups->count());
1337 QListIterator<Grouping> gli(*root->groups);
1339 for (;(g=gli.current());++gli)
1342 //printf("group `%s'\n",s->data());
1343 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1345 if (gd->addNamespace(nd)) nd->makePartOfGroup(gd);
1346 //printf("Namespace %s: in group %s\n",nd->name().data(),s->data());
1351 void addDirToGroups(Entry *root,DirDef *dd)
1353 //printf("*** root->groups->count()=%d\n",root->groups->count());
1354 QListIterator<Grouping> gli(*root->groups);
1356 for (;(g=gli.current());++gli)
1359 //printf("group `%s'\n",g->groupname.data());
1360 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1363 dd->makePartOfGroup(gd);
1364 //printf("Dir %s: in group %s\n",dd->name().data(),g->groupname.data());
1369 void addGroupToGroups(Entry *root,GroupDef *subGroup)
1371 //printf("addGroupToGroups for %s groups=%d\n",root->name.data(),
1372 // root->groups?root->groups->count():-1);
1373 QListIterator<Grouping> gli(*root->groups);
1375 for (;(g=gli.current());++gli)
1378 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1382 warn(root->fileName,root->startLine,"Refusing to add group %s to itself",
1385 else if (subGroup->findGroup(gd))
1387 warn(root->fileName,root->startLine,"Refusing to add group %s to group %s, since the latter is already a "
1388 "subgroup of the former\n", subGroup->name().data(),gd->name().data());
1390 else if (!gd->findGroup(subGroup))
1392 gd->addGroup(subGroup);
1393 subGroup->makePartOfGroup(gd);
1399 /*! Add a member to the group with the highest priority */
1400 void addMemberToGroups(Entry *root,MemberDef *md)
1402 //printf("addMemberToGroups: Root %p = %s, md %p=%s groups=%d\n",
1403 // root, root->name.data(), md, md->name().data(), root->groups->count() );
1404 QListIterator<Grouping> gli(*root->groups);
1407 // Search entry's group list for group with highest pri.
1408 Grouping::GroupPri_t pri = Grouping::GROUPING_LOWEST;
1410 for (;(g=gli.current());++gli)
1413 if (!g->groupname.isEmpty() &&
1414 (gd=Doxygen::groupSDict->find(g->groupname)) &&
1417 if (fgd && gd!=fgd && g->pri==pri)
1419 warn(root->fileName.data(), root->startLine,
1420 "Member %s found in multiple %s groups! "
1421 "The member will be put in group %s, and not in group %s",
1422 md->name().data(), Grouping::getGroupPriName( pri ),
1423 gd->name().data(), fgd->name().data()
1431 //printf("fgd=%p\n",fgd);
1433 // put member into group defined by this entry?
1436 GroupDef *mgd = md->getGroupDef();
1437 //printf("mgd=%p\n",mgd);
1438 bool insertit = FALSE;
1445 bool moveit = FALSE;
1447 // move member from one group to another if
1448 // - the new one has a higher priority
1449 // - the new entry has the same priority, but with docs where the old one had no docs
1450 if (md->getGroupPri()<pri)
1456 if (md->getGroupPri()==pri)
1458 if (!root->doc.isEmpty() && !md->getGroupHasDocs())
1462 else if (!root->doc.isEmpty() && md->getGroupHasDocs())
1464 warn(md->getGroupFileName(),md->getGroupStartLine(),
1465 "Member documentation for %s found several times in %s groups!\n"
1466 "%s:%d: The member will remain in group %s, and won't be put into group %s",
1467 md->name().data(), Grouping::getGroupPriName( pri ),
1468 root->fileName.data(), root->startLine,
1478 //printf("removeMember\n");
1479 mgd->removeMember(md);
1486 //printf("insertMember found at %s line %d: %s: related %s\n",
1487 // md->getDefFileName().data(),md->getDefLine(),
1488 // md->name().data(),root->relates.data());
1489 bool success = fgd->insertMember(md);
1492 //printf("insertMember successful\n");
1493 md->setGroupDef(fgd,pri,root->fileName,root->startLine,
1494 !root->doc.isEmpty());
1495 ClassDef *cd = md->getClassDefOfAnonymousType();
1498 cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0);
1506 void addExampleToGroups(Entry *root,PageDef *eg)
1508 QListIterator<Grouping> gli(*root->groups);
1510 for (;(g=gli.current());++gli)
1513 if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1516 eg->makePartOfGroup(gd);
1517 //printf("Example %s: in group %s\n",eg->name().data(),s->data());
1522 QCString GroupDef::getOutputFileBase() const
1527 void GroupDef::addListReferences()
1530 QList<ListItemInfo> *xrefItems = xrefListItems();
1531 addRefItem(xrefItems,
1532 getOutputFileBase(),
1533 theTranslator->trGroup(TRUE,TRUE),
1534 getOutputFileBase(),name(),
1539 MemberGroupSDict::Iterator mgli(*memberGroupSDict);
1541 for (;(mg=mgli.current());++mgli)
1543 mg->addListReferences(this);
1545 QListIterator<MemberList> mli(m_memberLists);
1547 for (mli.toFirst();(ml=mli.current());++mli)
1549 if (ml->listType()&MemberListType_documentationLists)
1551 ml->addListReferences(this);
1556 MemberList *GroupDef::createMemberList(MemberListType lt)
1558 m_memberLists.setAutoDelete(TRUE);
1559 QListIterator<MemberList> mli(m_memberLists);
1561 for (mli.toFirst();(ml=mli.current());++mli)
1563 if (ml->listType()==lt)
1568 // not found, create a new member list
1569 ml = new MemberList(lt);
1570 m_memberLists.append(ml);
1571 ml->setInGroup(TRUE);
1575 void GroupDef::addMemberToList(MemberListType lt,MemberDef *md)
1577 static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
1578 static bool sortMemberDocs = Config_getBool(SORT_MEMBER_DOCS);
1579 MemberList *ml = createMemberList(lt);
1580 ml->setNeedsSorting(
1581 ((ml->listType()&MemberListType_declarationLists) && sortBriefDocs) ||
1582 ((ml->listType()&MemberListType_documentationLists) && sortMemberDocs));
1586 void GroupDef::sortMemberLists()
1588 QListIterator<MemberList> mli(m_memberLists);
1590 for (;(ml=mli.current());++mli)
1592 if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
1596 MemberList *GroupDef::getMemberList(MemberListType lt) const
1598 QListIterator<MemberList> mli(m_memberLists);
1600 for (;(ml=mli.current());++mli)
1602 if (ml->listType()==lt)
1610 void GroupDef::writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title)
1612 static bool optimizeVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
1614 MemberList * ml = getMemberList(lt);
1615 if (optimizeVhdl && ml)
1617 VhdlDocGen::writeVhdlDeclarations(ml,ol,this,0,0,0);
1622 ml->writeDeclarations(ol,0,0,0,this,title,0);
1626 void GroupDef::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title)
1628 MemberList * ml = getMemberList(lt);
1629 if (ml) ml->writeDocumentation(ol,name(),this,title);
1632 void GroupDef::removeMemberFromList(MemberListType lt,MemberDef *md)
1634 MemberList *ml = getMemberList(lt);
1635 if (ml) ml->remove(md);
1638 void GroupDef::sortSubGroups()
1643 bool GroupDef::isLinkableInProject() const
1645 return !isReference() && isLinkable();
1648 bool GroupDef::isLinkable() const
1650 return hasUserDocumentation();
1653 // let the "programming language" for a group depend on what is inserted into it.
1654 // First item that has an associated languages determines the language for the whole group.
1655 void GroupDef::updateLanguage(const Definition *d)
1657 if (getLanguage()==SrcLangExt_Unknown && d->getLanguage()!=SrcLangExt_Unknown)
1659 setLanguage(d->getLanguage());
1663 bool GroupDef::hasDetailedDescription() const
1665 static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
1666 return ((!briefDescription().isEmpty() && repeatBrief) ||
1667 !documentation().isEmpty());