My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
groupdef.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  *
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
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.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17 
18 #include <ctype.h>
19 #include <qregexp.h>
20 #include "groupdef.h"
21 #include "classdef.h"
22 #include "filedef.h"
23 #include "classlist.h"
24 #include "outputlist.h"
25 #include "namespacedef.h"
26 #include "language.h"
27 #include "util.h"
28 #include "memberlist.h"
29 #include "message.h"
30 #include "membergroup.h"
31 #include "doxygen.h"
32 #include "pagedef.h"
33 #include "docparser.h"
34 #include "searchindex.h"
35 #include "dot.h"
36 #include "vhdldocgen.h"
37 #include "layout.h"
38 #include "arguments.h"
39 #include "entry.h"
40 #include "membername.h"
41 #include "dirdef.h"
42 #include "config.h"
43 
44 //---------------------------------------------------------------------------
45 
46 GroupDef::GroupDef(const char *df,int dl,const char *na,const char *t,
47  const char *refFileName) : Definition(df,dl,1,na)
48 {
49  fileList = new FileList;
50  classSDict = new ClassSDict(17);
51  groupList = new GroupList;
53  pageDict = new PageSDict(17);
54  exampleDict = new PageSDict(17);
55  dirList = new DirList;
58  if (refFileName)
59  {
60  fileName=stripExtension(refFileName);
61  }
62  else
63  {
64  fileName = convertNameToFile(QCString("group_")+na);
65  }
66  setGroupTitle( t );
69 
71 
72  visited = 0;
73  groupScope = 0;
74  m_subGrouping=Config_getBool(SUBGROUPING);
75 }
76 
78 {
79  delete fileList;
80  delete classSDict;
81  delete groupList;
82  delete namespaceSDict;
83  delete pageDict;
84  delete exampleDict;
85  delete allMemberList;
87  delete memberGroupSDict;
88  delete dirList;
89 }
90 
91 void GroupDef::setGroupTitle( const char *t )
92 {
93  if ( t && qstrlen(t) )
94  {
95  title = t;
96  titleSet = TRUE;
97  }
98  else
99  {
100  title = name();
101  title.at(0)=toupper(title.at(0));
102  titleSet = FALSE;
103  }
104 }
105 
106 
108 {
110  MemberGroup *mg;
111  for (;(mg=mgli.current());++mgli)
112  {
114  }
115 }
116 
118 {
121  MemberGroup *mg;
122  for (;(mg=mgli.current());++mgli)
123  {
125  }
126 
127  QListIterator<MemberList> mli(m_memberLists);
128  MemberList *ml;
129  for (mli.toFirst();(ml=mli.current());++mli)
130  {
132  {
134  }
135  }
136 }
137 
138 void GroupDef::addFile(const FileDef *def)
139 {
140  static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
141  if (def->isHidden()) return;
142  updateLanguage(def);
143  if (sortBriefDocs)
144  fileList->inSort(def);
145  else
146  fileList->append(def);
147 }
148 
150 {
151  static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
152  if (cd->isHidden()) return FALSE;
153  updateLanguage(cd);
154  QCString qn = cd->name();
155  if (classSDict->find(qn)==0)
156  {
157  //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs);
158  if (sortBriefDocs)
159  {
160  classSDict->inSort(qn,cd);
161  }
162  else
163  {
164  int i=qn.findRev("::");
165  if (i==-1) i=qn.find('.');
166  bool found=FALSE;
167  //printf("i=%d\n",i);
168  if (i!=-1)
169  {
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);
174  if (j!=-1)
175  {
176  while (j<(int)classSDict->count() &&
177  classSDict->at(j)->qualifiedName().left(i)==scope)
178  {
179  //printf("skipping over %s\n",classSDict->at(j)->qualifiedName().data());
180  j++;
181  }
182  //printf("Found scope at index %d\n",j);
183  classSDict->insertAt(j,qn,cd);
184  found=TRUE;
185  }
186  }
187  if (!found) // no insertion point found -> just append
188  {
189  classSDict->append(qn,cd);
190  }
191  }
192  return TRUE;
193  }
194  return FALSE;
195 }
196 
198 {
199  static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
200  if (def->isHidden()) return FALSE;
201  updateLanguage(def);
202  if (namespaceSDict->find(def->name())==0)
203  {
204  if (sortBriefDocs)
205  namespaceSDict->inSort(def->name(),def);
206  else
207  namespaceSDict->append(def->name(),def);
208  return TRUE;
209  }
210  return FALSE;
211 }
212 
213 void GroupDef::addDir(const DirDef *def)
214 {
215  if (def->isHidden()) return;
216  if (Config_getBool(SORT_BRIEF_DOCS))
217  dirList->inSort(def);
218  else
219  dirList->append(def);
220 }
221 
223 {
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);
228 }
229 
231 {
232  if (def->isHidden()) return;
233  exampleDict->append(def->name(),def);
234 }
235 
236 
238 {
239  QListIterator<MemberList> mli(m_memberLists);
240  MemberList *ml;
241  for (mli.toFirst();(ml=mli.current());++mli)
242  {
244  {
246  }
247  }
248 
249  //printf("GroupDef::addMembersToMemberGroup() memberGroupList=%d\n",memberGroupList->count());
251  MemberGroup *mg;
252  for (;(mg=mgli.current());++mgli)
253  {
254  mg->setInGroup(TRUE);
255  }
256 }
257 
258 
259 bool GroupDef::insertMember(MemberDef *md,bool docOnly)
260 {
261  if (md->isHidden()) return FALSE;
262  updateLanguage(md);
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);
268  MemberInfo *srcMi;
269  for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
270  {
271  MemberDef *srcMd = srcMi->memberDef;
272  if (srcMd==md) return FALSE; // already added before!
273 
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
278 
279  ArgumentList *srcMdAl = srcMd->argumentList();
280  ArgumentList *mdAl = md->argumentList();
281  ArgumentList *tSrcMdAl = srcMd->templateArguments();
282  ArgumentList *tMdAl = md->templateArguments();
283 
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,
290  TRUE
291  ) && // matching parameters
292  sameScope // both are found in the same scope
293  )
294  {
295  if (srcMd->getGroupAlias()==0)
296  {
297  md->setGroupAlias(srcMd);
298  }
299  else if (md!=srcMd->getGroupAlias())
300  {
301  md->setGroupAlias(srcMd->getGroupAlias());
302  }
303  return FALSE; // member is the same as one that is already added
304  }
305  }
306  mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
307  }
308  else
309  {
310  mni = new MemberNameInfo(md->name());
311  mni->append(new MemberInfo(md,md->protection(),md->virtualness(),FALSE));
313  }
314  //printf("Added member!\n");
315  allMemberList->append(md);
316  switch(md->memberType())
317  {
318  case MemberType_Variable:
319  if (!docOnly)
320  {
322  }
324  break;
325  case MemberType_Function:
326  if (!docOnly)
327  {
329  }
331  break;
332  case MemberType_Typedef:
333  if (!docOnly)
334  {
336  }
338  break;
340  if (!docOnly)
341  {
343  }
345  break;
346  case MemberType_EnumValue:
347  if (!docOnly)
348  {
350  }
352  break;
353  case MemberType_Define:
354  if (!docOnly)
355  {
357  }
359  break;
360  case MemberType_Signal:
361  if (!docOnly)
362  {
364  }
366  break;
367  case MemberType_Slot:
368  if (md->protection()==Public)
369  {
370  if (!docOnly)
371  {
373  }
375  }
376  else if (md->protection()==Protected)
377  {
378  if (!docOnly)
379  {
381  }
383  }
384  else
385  {
386  if (!docOnly)
387  {
389  }
391  }
392  break;
393  case MemberType_Event:
394  if (!docOnly)
395  {
397  }
399  break;
400  case MemberType_Property:
401  if (!docOnly)
402  {
404  }
406  break;
407  case MemberType_Friend:
408  if (!docOnly)
409  {
411  }
413  break;
414  default:
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() : "",
419  name().data());
420  }
421  return TRUE;
422 }
423 
425 {
426  // fprintf(stderr, "GroupDef(%s)::removeMember( %s )\n", title.data(), md->name().data());
428  if (mni)
429  {
430  MemberNameInfoIterator mnii(*mni);
431  while( mnii.current() )
432  {
433  if( mnii.current()->memberDef == md )
434  {
435  mni->remove(mnii.current());
436  break;
437  }
438  ++mnii;
439  }
440  if( mni->isEmpty() )
441  {
443  }
444 
446  switch(md->memberType())
447  {
448  case MemberType_Variable:
451  break;
452  case MemberType_Function:
455  break;
456  case MemberType_Typedef:
459  break;
463  break;
464  case MemberType_EnumValue:
467  break;
468  case MemberType_Define:
471  break;
472  case MemberType_Signal:
475  break;
476  case MemberType_Slot:
477  if (md->protection()==Public)
478  {
481  }
482  else if (md->protection()==Protected)
483  {
486  }
487  else
488  {
491  }
492  break;
493  case MemberType_Event:
496  break;
497  case MemberType_Property:
500  break;
501  case MemberType_Friend:
504  break;
505  default:
506  err("GroupDef::removeMember(): unexpected member remove in file!\n");
507  }
508  }
509 }
510 
511 bool GroupDef::findGroup(const GroupDef *def) const
512 {
513  if (this==def)
514  {
515  return TRUE;
516  }
517  else if (groupList)
518  {
520  GroupDef *gd;
521  for (;(gd=it.current());++it)
522  {
523  if (gd->findGroup(def))
524  {
525  return TRUE;
526  }
527  }
528  }
529  return FALSE;
530 }
531 
532 void GroupDef::addGroup(const GroupDef *def)
533 {
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);
537  //else
538  groupList->append(def);
539 }
540 
542 {
543  GroupList *groups = partOfGroups();
544  return groups!=0 && groups->count()!=0;
545 }
546 
548 {
549  return fileList->count()+
550  classSDict->count()+
552  groupList->count()+
553  allMemberList->count()+
554  pageDict->count()+
555  exampleDict->count();
556 }
557 
560 {
561  //printf("GroupDef::computeAnchors()\n");
563 }
564 
566 {
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(
573  LayoutDocEntry *lde;
574  for (eli.toFirst();(lde=eli.current());++eli)
575  {
576  switch (lde->kind())
577  {
579  {
580  if (classSDict)
581  {
583  ClassDef *cd;
584  for (ci.toFirst();(cd=ci.current());++ci)
585  {
586  if (cd->isLinkableInProject())
587  {
588  tagFile << " <class kind=\"" << cd->compoundTypeString()
589  << "\">" << convertToXML(cd->name()) << "</class>" << endl;
590  }
591  }
592  }
593  }
594  break;
596  {
597  if (namespaceSDict)
598  {
600  NamespaceDef *nd;
601  for (ni.toFirst();(nd=ni.current());++ni)
602  {
603  if (nd->isLinkableInProject())
604  {
605  tagFile << " <namespace>" << convertToXML(nd->name())
606  << "</namespace>" << endl;
607  }
608  }
609  }
610  }
611  break;
613  {
614  if (fileList)
615  {
616  QListIterator<FileDef> it(*fileList);
617  FileDef *fd;
618  for (;(fd=it.current());++it)
619  {
620  if (fd->isLinkableInProject())
621  {
622  tagFile << " <file>" << convertToXML(fd->name()) << "</file>" << endl;
623  }
624  }
625  }
626  }
627  break;
629  {
630  if (pageDict)
631  {
633  PageDef *pd=0;
634  for (pdi.toFirst();(pd=pdi.current());++pdi)
635  {
636  QCString pageName = pd->getOutputFileBase();
637  if (pd->isLinkableInProject())
638  {
639  tagFile << " <page>" << convertToXML(pageName) << "</page>" << endl;
640  }
641  }
642  }
643  }
644  break;
646  {
647  if (dirList)
648  {
649  QListIterator<DirDef> it(*dirList);
650  DirDef *dd;
651  for (;(dd=it.current());++it)
652  {
653  if (dd->isLinkableInProject())
654  {
655  tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;
656  }
657  }
658  }
659  }
660  break;
662  {
663  if (groupList)
664  {
665  QListIterator<GroupDef> it(*groupList);
666  GroupDef *gd;
667  for (;(gd=it.current());++it)
668  {
669  if (gd->isVisible())
670  {
671  tagFile << " <subgroup>" << convertToXML(gd->name()) << "</subgroup>" << endl;
672  }
673  }
674  }
675  }
676  break;
678  {
680  MemberList * ml = getMemberList(lmd->type);
681  if (ml)
682  {
683  ml->writeTagFile(tagFile);
684  }
685  }
686  break;
688  {
689  if (memberGroupSDict)
690  {
692  MemberGroup *mg;
693  for (;(mg=mgli.current());++mgli)
694  {
695  mg->writeTagFile(tagFile);
696  }
697  }
698  }
699  break;
700  default:
701  break;
702  }
703  }
704  writeDocAnchorsToTagFile(tagFile);
705  tagFile << " </compound>" << endl;
706 }
707 
708 void GroupDef::writeDetailedDescription(OutputList &ol,const QCString &title)
709 {
710  if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
711  || !documentation().isEmpty() || !inbodyDocumentation().isEmpty()
712  )
713  {
714  if (pageDict->count()!=countMembers()) // not only pages -> classical layout
715  {
716  ol.pushGeneratorState();
718  ol.writeRuler();
719  ol.popGeneratorState();
720  ol.pushGeneratorState();
722  ol.writeAnchor(0,"details");
723  ol.popGeneratorState();
724  ol.startGroupHeader();
725  ol.parseText(title);
726  ol.endGroupHeader();
727  }
728 
729  // repeat brief description
730  if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
731  {
732  ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
733  }
734  // write separator between brief and details
735  if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) &&
736  !documentation().isEmpty())
737  {
738  ol.pushGeneratorState();
741  // ol.newParagraph(); // FIXME:PARA
742  ol.enableAll();
745  ol.writeString("\n\n");
746  ol.popGeneratorState();
747  }
748 
749  // write detailed documentation
750  if (!documentation().isEmpty())
751  {
752  ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
753  }
754 
755  // write inbody documentation
756  if (!inbodyDocumentation().isEmpty())
757  {
758  ol.generateDoc(inbodyFile(),inbodyLine(),this,0,inbodyDocumentation()+"\n",TRUE,FALSE);
759  }
760  }
761 }
762 
764 {
765  if (!briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
766  {
767  DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
768  briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
769  if (rootNode && !rootNode->isEmpty())
770  {
771  ol.startParagraph();
772  ol.writeDoc(rootNode,this,0);
773  ol.pushGeneratorState();
775  ol.writeString(" \n");
777 
778  if (Config_getBool(REPEAT_BRIEF) ||
779  !documentation().isEmpty()
780  )
781  {
783  ol.startTextLink(0,"details");
785  ol.endTextLink();
786  }
787  ol.popGeneratorState();
788  ol.endParagraph();
789  }
790  delete rootNode;
791  }
792 }
793 
795 {
796  if (Config_getBool(HAVE_DOT) /*&& Config_getBool(GROUP_GRAPHS)*/ )
797  {
798  DotGroupCollaboration graph(this);
799  if (!graph.isTrivial())
800  {
801  msg("Generating dependency graph for group %s\n",qualifiedName().data());
802  ol.pushGeneratorState();
804  //ol.startParagraph();
807  ol.endGroupCollaboration(graph);
808  //ol.endParagraph();
809  ol.popGeneratorState();
810  }
811  }
812 }
813 
814 void GroupDef::writeFiles(OutputList &ol,const QCString &title)
815 {
816  // write list of files
817  if (fileList->count()>0)
818  {
819  ol.startMemberHeader("files");
820  ol.parseText(title);
821  ol.endMemberHeader();
822  ol.startMemberList();
823  QListIterator<FileDef> it(*fileList);
824  FileDef *fd;
825  for (;(fd=it.current());++it)
826  {
827  if (!fd->hasDocumentation()) continue;
830  ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");
831  ol.insertMemberAlign();
832  ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
833  ol.endMemberItem();
834  if (!fd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
835  {
837  ol.generateDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
839  }
840  ol.endMemberDeclaration(0,0);
841  }
842  ol.endMemberList();
843  }
844 }
845 
846 void GroupDef::writeNamespaces(OutputList &ol,const QCString &title)
847 {
848  // write list of namespaces
849  namespaceSDict->writeDeclaration(ol,title);
850 }
851 
852 void GroupDef::writeNestedGroups(OutputList &ol,const QCString &title)
853 {
854  // write list of groups
855  int count=0;
856  if (groupList->count()>0)
857  {
858  QListIterator<GroupDef> it(*groupList);
859  GroupDef *gd;
860  for (;(gd=it.current());++it)
861  {
862  if (gd->isVisible()) count++;
863  }
864  }
865  if (count>0)
866  {
867  ol.startMemberHeader("groups");
868  ol.parseText(title);
869  ol.endMemberHeader();
870  ol.startMemberList();
871  if (Config_getBool(SORT_GROUP_NAMES))
872  {
873  groupList->sort();
874  }
875  QListIterator<GroupDef> it(*groupList);
876  GroupDef *gd;
877  for (;(gd=it.current());++it)
878  {
879  if (gd->isVisible())
880  {
881  if (!gd->hasDocumentation()) continue;
884  //ol.docify(theTranslator->trGroup(FALSE,TRUE));
885  //ol.docify(" ");
886  ol.insertMemberAlign();
888  ol.endMemberItem();
889  if (!gd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
890  {
892  ol.generateDoc(briefFile(),briefLine(),gd,0,gd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
894  }
895  ol.endMemberDeclaration(0,0);
896  }
897  }
898  ol.endMemberList();
899  }
900 }
901 
902 void GroupDef::writeDirs(OutputList &ol,const QCString &title)
903 {
904  // write list of directories
905  if (dirList->count()>0)
906  {
907  ol.startMemberHeader("dirs");
908  ol.parseText(title);
909  ol.endMemberHeader();
910  ol.startMemberList();
911  QListIterator<DirDef> it(*dirList);
912  DirDef *dd;
913  for (;(dd=it.current());++it)
914  {
915  if (!dd->hasDocumentation()) continue;
918  ol.parseText(theTranslator->trDir(FALSE,TRUE));
919  ol.insertMemberAlign();
921  ol.endMemberItem();
922  if (!dd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
923  {
925  ol.generateDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
927  }
928  ol.endMemberDeclaration(0,0);
929  }
930 
931  ol.endMemberList();
932  }
933 }
934 
935 void GroupDef::writeClasses(OutputList &ol,const QCString &title)
936 {
937  // write list of classes
938  classSDict->writeDeclaration(ol,0,title,FALSE);
939 }
940 
942 {
944 }
945 
947 {
948  PageDef *pd=0;
950  for (pdi.toFirst();(pd=pdi.current());++pdi)
951  {
952  if (!pd->isReference())
953  {
954  SectionInfo *si=0;
955  if (!pd->title().isEmpty() && !pd->name().isEmpty() &&
956  (si=Doxygen::sectionDict->find(pd->name()))!=0)
957  {
959  ol.docify(si->title);
961  }
962  ol.startTextBlock();
963  ol.generateDoc(pd->docFile(),pd->docLine(),pd,0,pd->documentation()+pd->inbodyDocumentation(),TRUE,FALSE,0,TRUE,FALSE);
964  ol.endTextBlock();
965  }
966  }
967 }
968 
970 {
971  /* write user defined member groups */
972  if (memberGroupSDict)
973  {
975  /* write user defined member groups */
977  MemberGroup *mg;
978  for (;(mg=mgli.current());++mgli)
979  {
980  mg->writeDeclarations(ol,0,0,0,this);
981  }
982  }
983 }
984 
986 {
987  ol.startMemberSections();
988 }
989 
991 {
992  ol.endMemberSections();
993 }
994 
996 {
997  //printf("** GroupDef::startMemberDocumentation()\n");
998  if (Config_getBool(SEPARATE_MEMBER_PAGES))
999  {
1000  ol.pushGeneratorState();
1003  }
1004 }
1005 
1007 {
1008  //printf("** GroupDef::endMemberDocumentation()\n");
1009  if (Config_getBool(SEPARATE_MEMBER_PAGES))
1010  {
1011  ol.popGeneratorState();
1013  }
1014 }
1015 
1017 {
1018  // write Author section (Man only)
1019  ol.pushGeneratorState();
1021  ol.startGroupHeader();
1022  ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
1023  ol.endGroupHeader();
1025  ol.popGeneratorState();
1026 }
1027 
1029 {
1030  ol.pushGeneratorState();
1032  QListIterator<LayoutDocEntry> eli(
1034  LayoutDocEntry *lde;
1035  bool first=TRUE;
1036  SrcLangExt lang = getLanguage();
1037  for (eli.toFirst();(lde=eli.current());++eli)
1038  {
1041  (lde->kind()==LayoutDocEntry::GroupFiles && fileList->count()>0) ||
1042  (lde->kind()==LayoutDocEntry::GroupNestedGroups && groupList->count()>0) ||
1043  (lde->kind()==LayoutDocEntry::GroupDirs && dirList->count()>0)
1044  )
1045  {
1047  QCString label = lde->kind()==LayoutDocEntry::GroupClasses ? "nested-classes" :
1048  lde->kind()==LayoutDocEntry::GroupNamespaces ? "namespaces" :
1049  lde->kind()==LayoutDocEntry::GroupFiles ? "files" :
1050  lde->kind()==LayoutDocEntry::GroupNestedGroups ? "groups" :
1051  "dirs";
1052  ol.writeSummaryLink(0,label,ls->title(lang),first);
1053  first=FALSE;
1054  }
1055  else if (lde->kind()==LayoutDocEntry::MemberDecl)
1056  {
1058  MemberList * ml = getMemberList(lmd->type);
1059  if (ml && ml->declVisible())
1060  {
1061  ol.writeSummaryLink(0,MemberList::listTypeAsString(ml->listType()),lmd->title(lang),first);
1062  first=FALSE;
1063  }
1064  }
1065  }
1066  if (!first)
1067  {
1068  ol.writeString(" </div>\n");
1069  }
1070  ol.popGeneratorState();
1071 }
1072 
1074 {
1075  //static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
1076  ol.pushGeneratorState();
1078 
1079  ol.startHeaderSection();
1080  writeSummaryLinks(ol);
1082  ol.pushGeneratorState();
1084  ol.parseText(title);
1085  ol.popGeneratorState();
1086  addGroupListToTitle(ol,this);
1087  ol.pushGeneratorState();
1090  ol.popGeneratorState();
1091  ol.pushGeneratorState();
1094  ol.parseText(title);
1095  ol.popGeneratorState();
1096  ol.endHeaderSection();
1097  ol.startContents();
1098 
1100  {
1101  Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
1102  static QRegExp we("[a-zA-Z_][-a-zA-Z_0-9]*");
1103  int i=0,p=0,l=0;
1104  while ((i=we.match(title,p,&l))!=-1) // foreach word in the title
1105  {
1106  Doxygen::searchIndex->addWord(title.mid(i,l),TRUE);
1107  p=i+l;
1108  }
1109  }
1110 
1112 
1113  //---------------------------------------- start flexible part -------------------------------
1114 
1115  SrcLangExt lang=getLanguage();
1116  QListIterator<LayoutDocEntry> eli(
1118  LayoutDocEntry *lde;
1119  for (eli.toFirst();(lde=eli.current());++eli)
1120  {
1121  switch (lde->kind())
1122  {
1125  break;
1128  break;
1130  {
1132  writeClasses(ol,ls->title(lang));
1133  }
1134  break;
1136  {
1137  writeInlineClasses(ol);
1138  }
1139  break;
1141  {
1143  writeNamespaces(ol,ls->title(lang));
1144  }
1145  break;
1147  writeMemberGroups(ol);
1148  break;
1150  {
1152  writeMemberDeclarations(ol,lmd->type,lmd->title(lang));
1153  }
1154  break;
1157  break;
1159  {
1161  writeDetailedDescription(ol,ls->title(lang));
1162  }
1163  break;
1166  break;
1168  {
1170  writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
1171  }
1172  break;
1175  break;
1177  {
1179  writeNestedGroups(ol,ls->title(lang));
1180  }
1181  break;
1184  break;
1186  {
1188  writeDirs(ol,ls->title(lang));
1189  }
1190  break;
1192  {
1194  writeFiles(ol,ls->title(lang));
1195  }
1196  break;
1198  writeGroupGraph(ol);
1199  break;
1201  writeAuthorSection(ol);
1202  break;
1225  err("Internal inconsistency: member %d should not be part of "
1226  "LayoutDocManager::Group entry list\n",lde->kind());
1227  break;
1228  }
1229  }
1230 
1231  //---------------------------------------- end flexible part -------------------------------
1232 
1233  endFile(ol);
1234 
1235  ol.popGeneratorState();
1236 
1237  if (Config_getBool(SEPARATE_MEMBER_PAGES))
1238  {
1239  allMemberList->sort();
1240  writeMemberPages(ol);
1241  }
1242 
1243 }
1244 
1246 {
1247  ol.pushGeneratorState();
1249 
1250  QListIterator<MemberList> mli(m_memberLists);
1251  MemberList *ml;
1252  for (mli.toFirst();(ml=mli.current());++mli)
1253  {
1255  {
1256  ml->writeDocumentationPage(ol,name(),this);
1257  }
1258  }
1259 
1260  ol.popGeneratorState();
1261 }
1262 
1264 {
1265  static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
1266 
1267  ol.writeString(" <div class=\"navtab\">\n");
1268  ol.writeString(" <table>\n");
1269 
1271  MemberDef *md;
1272  for (mli.toFirst();(md=mli.current());++mli)
1273  {
1274  if (md->getGroupDef()==this && md->isLinkable() && !md->isEnumValue())
1275  {
1276  ol.writeString(" <tr><td class=\"navtab\">");
1277  if (md->isLinkableInProject())
1278  {
1279  if (md==currentMd) // selected item => highlight
1280  {
1281  ol.writeString("<a class=\"qindexHL\" ");
1282  }
1283  else
1284  {
1285  ol.writeString("<a class=\"qindex\" ");
1286  }
1287  ol.writeString("href=\"");
1288  if (createSubDirs) ol.writeString("../../");
1290  ol.writeString("\">");
1291  ol.writeString(convertToHtml(md->localName()));
1292  ol.writeString("</a>");
1293  }
1294  ol.writeString("</td></tr>\n");
1295  }
1296  }
1297 
1298  ol.writeString(" </table>\n");
1299  ol.writeString(" </div>\n");
1300 }
1301 
1302 
1303 
1304 //---- helper functions ------------------------------------------------------
1305 
1307 {
1308  QListIterator<Grouping> gli(*root->groups);
1309  Grouping *g;
1310  for (;(g=gli.current());++gli)
1311  {
1312  GroupDef *gd=0;
1313  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1314  {
1315  if (gd->addClass(cd))
1316  {
1317  cd->makePartOfGroup(gd);
1318  }
1319  //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle());
1320  }
1321  }
1322 }
1323 
1325 {
1326  //printf("root->groups->count()=%d\n",root->groups->count());
1327  QListIterator<Grouping> gli(*root->groups);
1328  Grouping *g;
1329  for (;(g=gli.current());++gli)
1330  {
1331  GroupDef *gd=0;
1332  //printf("group `%s'\n",s->data());
1333  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1334  {
1335  if (gd->addNamespace(nd)) nd->makePartOfGroup(gd);
1336  //printf("Namespace %s: in group %s\n",nd->name().data(),s->data());
1337  }
1338  }
1339 }
1340 
1341 void addDirToGroups(Entry *root,DirDef *dd)
1342 {
1343  //printf("*** root->groups->count()=%d\n",root->groups->count());
1344  QListIterator<Grouping> gli(*root->groups);
1345  Grouping *g;
1346  for (;(g=gli.current());++gli)
1347  {
1348  GroupDef *gd=0;
1349  //printf("group `%s'\n",g->groupname.data());
1350  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1351  {
1352  gd->addDir(dd);
1353  dd->makePartOfGroup(gd);
1354  //printf("Dir %s: in group %s\n",dd->name().data(),g->groupname.data());
1355  }
1356  }
1357 }
1358 
1359 void addGroupToGroups(Entry *root,GroupDef *subGroup)
1360 {
1361  //printf("addGroupToGroups for %s groups=%d\n",root->name.data(),
1362  // root->groups?root->groups->count():-1);
1363  QListIterator<Grouping> gli(*root->groups);
1364  Grouping *g;
1365  for (;(g=gli.current());++gli)
1366  {
1367  GroupDef *gd=0;
1368  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1369  {
1370  if (gd==subGroup)
1371  {
1372  warn(root->fileName,root->startLine,"Refusing to add group %s to itself",
1373  gd->name().data());
1374  }
1375  else if (subGroup->findGroup(gd))
1376  {
1377  warn(root->fileName,root->startLine,"Refusing to add group %s to group %s, since the latter is already a "
1378  "subgroup of the former\n", subGroup->name().data(),gd->name().data());
1379  }
1380  else if (!gd->findGroup(subGroup))
1381  {
1382  gd->addGroup(subGroup);
1383  subGroup->makePartOfGroup(gd);
1384  }
1385  }
1386  }
1387 }
1388 
1391 {
1392  //printf("addMemberToGroups: Root %p = %s, md %p=%s groups=%d\n",
1393  // root, root->name.data(), md, md->name().data(), root->groups->count() );
1394  QListIterator<Grouping> gli(*root->groups);
1395  Grouping *g;
1396 
1397  // Search entry's group list for group with highest pri.
1399  GroupDef *fgd=0;
1400  for (;(g=gli.current());++gli)
1401  {
1402  GroupDef *gd=0;
1403  if (!g->groupname.isEmpty() &&
1404  (gd=Doxygen::groupSDict->find(g->groupname)) &&
1405  g->pri >= pri)
1406  {
1407  if (fgd && gd!=fgd && g->pri==pri)
1408  {
1409  warn(root->fileName.data(), root->startLine,
1410  "Member %s found in multiple %s groups! "
1411  "The member will be put in group %s, and not in group %s",
1412  md->name().data(), Grouping::getGroupPriName( pri ),
1413  gd->name().data(), fgd->name().data()
1414  );
1415  }
1416 
1417  fgd = gd;
1418  pri = g->pri;
1419  }
1420  }
1421  //printf("fgd=%p\n",fgd);
1422 
1423  // put member into group defined by this entry?
1424  if (fgd)
1425  {
1426  GroupDef *mgd = md->getGroupDef();
1427  //printf("mgd=%p\n",mgd);
1428  bool insertit = FALSE;
1429  if (mgd==0)
1430  {
1431  insertit = TRUE;
1432  }
1433  else if (mgd!=fgd)
1434  {
1435  bool moveit = FALSE;
1436 
1437  // move member from one group to another if
1438  // - the new one has a higher priority
1439  // - the new entry has the same priority, but with docs where the old one had no docs
1440  if (md->getGroupPri()<pri)
1441  {
1442  moveit = TRUE;
1443  }
1444  else
1445  {
1446  if (md->getGroupPri()==pri)
1447  {
1448  if (!root->doc.isEmpty() && !md->getGroupHasDocs())
1449  {
1450  moveit = TRUE;
1451  }
1452  else if (!root->doc.isEmpty() && md->getGroupHasDocs())
1453  {
1455  "Member documentation for %s found several times in %s groups!\n"
1456  "%s:%d: The member will remain in group %s, and won't be put into group %s",
1457  md->name().data(), Grouping::getGroupPriName( pri ),
1458  root->fileName.data(), root->startLine,
1459  mgd->name().data(),
1460  fgd->name().data()
1461  );
1462  }
1463  }
1464  }
1465 
1466  if (moveit)
1467  {
1468  //printf("removeMember\n");
1469  mgd->removeMember(md);
1470  insertit = TRUE;
1471  }
1472  }
1473 
1474  if (insertit)
1475  {
1476  //printf("insertMember found at %s line %d: %s: related %s\n",
1477  // md->getDefFileName().data(),md->getDefLine(),
1478  // md->name().data(),root->relates.data());
1479  bool success = fgd->insertMember(md);
1480  if (success)
1481  {
1482  //printf("insertMember successful\n");
1483  md->setGroupDef(fgd,pri,root->fileName,root->startLine,
1484  !root->doc.isEmpty());
1486  if (cd)
1487  {
1488  cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0);
1489  }
1490  }
1491  }
1492  }
1493 }
1494 
1495 
1497 {
1498  QListIterator<Grouping> gli(*root->groups);
1499  Grouping *g;
1500  for (;(g=gli.current());++gli)
1501  {
1502  GroupDef *gd=0;
1503  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1504  {
1505  gd->addExample(eg);
1506  eg->makePartOfGroup(gd);
1507  //printf("Example %s: in group %s\n",eg->name().data(),s->data());
1508  }
1509  }
1510 }
1511 
1513 {
1514  return fileName;
1515 }
1516 
1518 {
1519  {
1520  QList<ListItemInfo> *xrefItems = xrefListItems();
1521  addRefItem(xrefItems,
1523  theTranslator->trGroup(TRUE,TRUE),
1524  getOutputFileBase(),name(),
1525  0,
1526  0
1527  );
1528  }
1530  MemberGroup *mg;
1531  for (;(mg=mgli.current());++mgli)
1532  {
1533  mg->addListReferences(this);
1534  }
1535  QListIterator<MemberList> mli(m_memberLists);
1536  MemberList *ml;
1537  for (mli.toFirst();(ml=mli.current());++mli)
1538  {
1540  {
1541  ml->addListReferences(this);
1542  }
1543  }
1544 }
1545 
1547 {
1548  m_memberLists.setAutoDelete(TRUE);
1549  QListIterator<MemberList> mli(m_memberLists);
1550  MemberList *ml;
1551  for (mli.toFirst();(ml=mli.current());++mli)
1552  {
1553  if (ml->listType()==lt)
1554  {
1555  return ml;
1556  }
1557  }
1558  // not found, create a new member list
1559  ml = new MemberList(lt);
1560  m_memberLists.append(ml);
1561  ml->setInGroup(TRUE);
1562  return ml;
1563 }
1564 
1566 {
1567  static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
1568  static bool sortMemberDocs = Config_getBool(SORT_MEMBER_DOCS);
1569  MemberList *ml = createMemberList(lt);
1570  ml->setNeedsSorting(
1571  ((ml->listType()&MemberListType_declarationLists) && sortBriefDocs) ||
1572  ((ml->listType()&MemberListType_documentationLists) && sortMemberDocs));
1573  ml->append(md);
1574 }
1575 
1577 {
1578  QListIterator<MemberList> mli(m_memberLists);
1579  MemberList *ml;
1580  for (;(ml=mli.current());++mli)
1581  {
1582  if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
1583  }
1584 }
1585 
1587 {
1588  QListIterator<MemberList> mli(m_memberLists);
1589  MemberList *ml;
1590  for (;(ml=mli.current());++mli)
1591  {
1592  if (ml->listType()==lt)
1593  {
1594  return ml;
1595  }
1596  }
1597  return 0;
1598 }
1599 
1601 {
1602  static bool optimizeVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
1603 
1604  MemberList * ml = getMemberList(lt);
1605  if (optimizeVhdl && ml)
1606  {
1607  VhdlDocGen::writeVhdlDeclarations(ml,ol,this,0,0,0);
1608  return;
1609  }
1610  if (ml)
1611  {
1612  ml->writeDeclarations(ol,0,0,0,this,title,0);
1613  }
1614 }
1615 
1617 {
1618  MemberList * ml = getMemberList(lt);
1619  if (ml) ml->writeDocumentation(ol,name(),this,title);
1620 }
1621 
1623 {
1624  MemberList *ml = getMemberList(lt);
1625  if (ml) ml->remove(md);
1626 }
1627 
1629 {
1630  groupList->sort();
1631 }
1632 
1634 {
1635  return !isReference() && isLinkable();
1636 }
1637 
1639 {
1640  return hasUserDocumentation();
1641 }
1642 
1643 // let the "programming language" for a group depend on what is inserted into it.
1644 // First item that has an associated languages determines the language for the whole group.
1646 {
1648  {
1649  setLanguage(d->getLanguage());
1650  }
1651 }
1652 
1654 {
1655  static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
1656  return ((!briefDescription().isEmpty() && repeatBrief) ||
1657  !documentation().isEmpty());
1658 }
1659