From 0bf554bbf8815974f75da513ddc2e4ccc52448c4 Mon Sep 17 00:00:00 2001 From: Matt Trescott Date: Thu, 23 Mar 2023 20:59:03 -0400 Subject: [PATCH] Support hierarchical groups in RTF and use the same model for pages --- src/index.cpp | 8 --- src/pagedef.cpp | 24 +++++--- src/rtfdocvisitor.cpp | 12 ++-- src/rtfdocvisitor.h | 3 +- src/rtfgen.cpp | 128 +++++++++++++++++++++++++----------------- src/rtfgen.h | 3 +- 6 files changed, 103 insertions(+), 75 deletions(-) diff --git a/src/index.cpp b/src/index.cpp index bb483ae6840..c1d6741a18c 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -4455,14 +4455,6 @@ static void writeIndex(OutputList &ol) if (Doxygen::mainPage) { ol.startIndexSection(IndexSection::isMainPage); - if (mainPageHasTitle()) - { - ol.parseText(Doxygen::mainPage->title()); - } - else - { - ol.parseText(/*projPrefix+*/theTranslator->trMainPage()); - } ol.endIndexSection(IndexSection::isMainPage); } const auto &index = Index::instance(); diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 1eacf5dd218..a18fe38f389 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -240,18 +240,24 @@ void PageDefImpl::writeDocumentation(OutputList &ol) ol.pushGeneratorState(); //2.{ ol.disable(OutputType::Man); - if (hasTitle() && !name().isEmpty() && si!=0) + QCString title; + if (this == Doxygen::mainPage.get() && !hasTitle()) + title = theTranslator->trMainPage(); + else + title = m_title; + + if (!title.isEmpty() && !name().isEmpty() && si!=0) { ol.startPageDoc(si->title()); //ol.startSection(si->label,si->title,si->type); - startTitle(ol,getOutputFileBase(),this); - ol.generateDoc(docFile(),getStartBodyLine(),this,0,si->title(),TRUE,FALSE, - QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); - //stringToSearchIndex(getOutputFileBase(), - // theTranslator->trPage(TRUE,TRUE)+" "+si->title, - // si->title); - //ol.endSection(si->label,si->type); - endTitle(ol,getOutputFileBase(),name()); + ol.startHeaderSection(); + ol.startTitleHead(getOutputFileBase()); + ol.parseText(title); + ol.endTitleHead(getOutputFileBase(),title); + ol.endHeaderSection(); + + /*ol.generateDoc(docFile(),getStartBodyLine(),this,0,si->title(),TRUE,FALSE, + QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));*/ } else ol.startPageDoc(""); diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index 28803883b08..4e547768d24 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -55,8 +55,8 @@ static QCString align(const DocHtmlCell &cell) } RTFDocVisitor::RTFDocVisitor(TextStream &t,OutputCodeList &ci, - const QCString &langExt) - : m_t(t), m_ci(ci), m_langExt(langExt) + const QCString &langExt, int hierarchyLevel) + : m_t(t), m_ci(ci), m_langExt(langExt), m_hierarchyLevel(hierarchyLevel) { } @@ -859,7 +859,9 @@ void RTFDocVisitor::operator()(const DocSection &s) m_t << "{{" // start section << rtf_Style_Reset; QCString heading; - int level = std::min(s.level()+1,4); + int level = std::min(s.level()+2+m_hierarchyLevel,4); + if (level <= 0) + level = 1; heading.sprintf("Heading%d",level); // set style m_t << rtf_Style[heading.str()].reference() << "\n"; @@ -1166,7 +1168,9 @@ void RTFDocVisitor::operator()(const DocHtmlHeader &header) m_t << "{" // start section << rtf_Style_Reset; QCString heading; - int level = std::min(header.level(),5); + int level = std::min(header.level()+m_hierarchyLevel,5); + if (level <= 0) + level = 1; heading.sprintf("Heading%d",level); // set style m_t << rtf_Style[heading.str()].reference(); diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h index 8df1e980f1d..26e006dde18 100644 --- a/src/rtfdocvisitor.h +++ b/src/rtfdocvisitor.h @@ -31,7 +31,7 @@ class TextStream; class RTFDocVisitor : public DocVisitor { public: - RTFDocVisitor(TextStream &t,OutputCodeList &ci,const QCString &langExt); + RTFDocVisitor(TextStream &t,OutputCodeList &ci,const QCString &langExt, int hierarchyLevel = 0); //-------------------------------------- // visitor functions for leaf nodes @@ -146,6 +146,7 @@ class RTFDocVisitor : public DocVisitor static const int maxIndentLevels = 13; int m_indentLevel = 0; + int m_hierarchyLevel = 0; struct RTFListItemInfo { bool isEnum = false; diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 2fa9df0f6b7..692b7ff49fa 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -605,15 +605,17 @@ void RTFGenerator::beginRTFSection() { m_t << "\\sect\\sbkpage\n"; } + int level = 2 + m_hierarchyLevel; - m_t << rtf_Style["Heading2"].reference() << "\n"; + m_t << rtf_Style[QCString().sprintf("Heading%d", level).str()].reference() << "\n"; } -void RTFGenerator::startFile(const QCString &name,const QCString &,const QCString &,int,int) +void RTFGenerator::startFile(const QCString &name,const QCString &,const QCString &,int,int hierarchyLevel) { //setEncoding(QCString().sprintf("CP%s",theTranslator->trRTFansicp())); QCString fileName=name; m_relPath = relativePathToRoot(fileName); + m_hierarchyLevel = hierarchyLevel; if (!fileName.endsWith(".rtf")) fileName+=".rtf"; startPlainFile(fileName); @@ -806,21 +808,45 @@ void RTFGenerator::startIndexSection(IndexSection is) } break; case IndexSection::isPageDocumentation: - { - //Page Documentation - beginRTFChapter(); - } break; case IndexSection::isPageDocumentation2: - { - m_t << "{\\tc \\v "; - } break; case IndexSection::isEndIndex: break; } } +static void includeSubGroupsRecursive(TextStream &t, const GroupDef *gd) +{ + t << "\\par " << rtf_Style_Reset << "\n"; + t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; + t << gd->getOutputFileBase(); + t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; + for (const auto &subgd : gd->getSubGroups()) + { + if (!subgd->isReference() && subgd->partOfGroups().front() == gd) + { + includeSubGroupsRecursive(t, subgd); + } + } +} + +static void includeSubPagesRecursive(TextStream &t, const PageDef *pd) +{ + t << "\\par " << rtf_Style_Reset << "\n"; + t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; + t << pd->getOutputFileBase(); + t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; + for (const auto &subpd : pd->getSubPages()) + { + if (!subpd->isReference()) + { + includeSubPagesRecursive(t, subpd); + } + } +} + + void RTFGenerator::endIndexSection(IndexSection is) { bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); @@ -921,14 +947,6 @@ void RTFGenerator::endIndexSection(IndexSection is) break; case IndexSection::isMainPage: m_t << "\\par " << rtf_Style_Reset << "\n"; - if (!mainPageHasTitle()) - { - m_t << "{\\tc \\v " << theTranslator->trMainPage() << "}\n"; - } - else - { - m_t << "{\\tc \\v " << substitute(Doxygen::mainPage->title(),"%","") << "}\n"; - } m_t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; //if (Config_getBool(GENERATE_TREEVIEW)) m_t << "main"; else m_t << "index"; m_t << "index"; @@ -995,21 +1013,12 @@ void RTFGenerator::endIndexSection(IndexSection is) break; case IndexSection::isModuleDocumentation: { - bool first=true; m_t << "{\\tc \\v " << theTranslator->trModuleDocumentation() << "}\n"; for (const auto &gd : *Doxygen::groupLinkedMap) { - if (!gd->isReference()) + if (!gd->isReference() && !gd->isASubGroup()) { - m_t << "\\par " << rtf_Style_Reset << "\n"; - if (!first) - { - beginRTFSection(); - } - first=false; - m_t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - m_t << gd->getOutputFileBase(); - m_t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; + includeSubGroupsRecursive(m_t, gd.get()); } } } @@ -1164,13 +1173,20 @@ void RTFGenerator::endIndexSection(IndexSection is) } break; case IndexSection::isPageDocumentation: - break; - case IndexSection::isPageDocumentation2: { - m_t << "}"; m_t << "\\par " << rtf_Style_Reset << "\n"; + for (const auto &pd : *Doxygen::pageLinkedMap) + { + if (!pd->getGroupDef() && !pd->isReference() && !pd->hasParentPage() + && Doxygen::mainPage.get() != pd.get()) + { + includeSubPagesRecursive(m_t, pd.get()); + } + } } break; + case IndexSection::isPageDocumentation2: + break; case IndexSection::isEndIndex: beginRTFChapter(); m_t << rtf_Style["Heading1"].reference(); @@ -1183,14 +1199,6 @@ void RTFGenerator::endIndexSection(IndexSection is) } } -void RTFGenerator::writePageLink(const QCString &name,bool first) -{ - if (first) m_t << "\\par " << rtf_Style_Reset << "\n"; - m_t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - m_t << name; - m_t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; -} - void RTFGenerator::lastIndexPage() { DBG_RTF(m_t << "{\\comment Beginning Body of RTF Document}\n") @@ -1427,7 +1435,8 @@ void RTFGenerator::startSubsection() m_t << "\n"; DBG_RTF(m_t << "{\\comment Begin SubSection}\n") m_t << rtf_Style_Reset; - m_t << rtf_Style["Heading3"].reference() << "\n"; + int level = 3 + m_hierarchyLevel; + m_t << rtf_Style_Reset << rtf_Style[QCString().sprintf("Heading%d", level).str()].reference() << "\n"; } void RTFGenerator::endSubsection() @@ -1442,7 +1451,8 @@ void RTFGenerator::startSubsubsection() m_t << "\n"; DBG_RTF(m_t << "{\\comment Begin SubSubSection}\n") m_t << "{\n"; - m_t << rtf_Style_Reset << rtf_Style["Heading4"].reference() << "\n"; + int level = 4 + m_hierarchyLevel; + m_t << rtf_Style_Reset << rtf_Style[QCString().sprintf("Heading%d", level).str()].reference() << "\n"; } void RTFGenerator::endSubsubsection() @@ -1548,9 +1558,11 @@ void RTFGenerator::endPageRef(const QCString &clname, const QCString &anchor) void RTFGenerator::startTitleHead(const QCString &) { DBG_RTF(m_t << "{\\comment startTitleHead}\n") - + int level = 2 + m_hierarchyLevel; + QCString heading; + heading.sprintf("Heading%d", level); // beginRTFSection(); - m_t << rtf_Style_Reset << rtf_Style["Heading2"].reference() << "\n"; + m_t << rtf_Style_Reset << rtf_Style[heading.str()].reference() << "\n"; } void RTFGenerator::endTitleHead(const QCString &fileName,const QCString &name) @@ -1560,7 +1572,8 @@ void RTFGenerator::endTitleHead(const QCString &fileName,const QCString &name) if (!name.isEmpty()) { // make table of contents entry - m_t << "{\\tc\\tcl2 \\v "; + int level = 2 + m_hierarchyLevel; + m_t << "{\\tc\\tcl" << level << " \\v "; docify(name); m_t << "}\n"; @@ -1587,7 +1600,8 @@ void RTFGenerator::startGroupHeader(int extraIndent) DBG_RTF(m_t << "{\\comment startGroupHeader}\n") //newParagraph(); m_t << rtf_Style_Reset; - if (extraIndent==2) + extraIndent += m_hierarchyLevel; + if (extraIndent>=2) { m_t << rtf_Style["Heading5"].reference(); } @@ -1623,7 +1637,15 @@ void RTFGenerator::startMemberDoc(const QCString &clname, addIndexItem(memname,clname); addIndexItem(clname,memname); } - m_t << rtf_Style_Reset << rtf_Style[showInline ? "Heading5" : "Heading4"].reference(); + + int level = 4 + m_hierarchyLevel; + if (showInline) + ++level; + if (level > 5) + level = 5; + if (level < 1) + level = 1; + m_t << rtf_Style_Reset << rtf_Style[QCString().sprintf("Heading%d", level).str()].reference(); //styleStack.push(rtf_Style_Heading4); m_t << "{\n"; //printf("RTFGenerator::startMemberDoc() '%s'\n",rtf_Style["Heading4"].reference()); @@ -1777,13 +1799,15 @@ void RTFGenerator::startSection(const QCString &,const QCString &title,SectionTy int num=4; switch(type) { - case SectionType::Page: num=2; break; - case SectionType::Section: num=3; break; - case SectionType::Subsection: num=4; break; - case SectionType::Subsubsection: num=4; break; - case SectionType::Paragraph: num=4; break; + case SectionType::Page: num=2+m_hierarchyLevel; break; + case SectionType::Section: num=3+m_hierarchyLevel; break; + case SectionType::Subsection: num=4+m_hierarchyLevel; break; + case SectionType::Subsubsection: num=4+m_hierarchyLevel; break; + case SectionType::Paragraph: num=4+m_hierarchyLevel; break; default: ASSERT(0); break; } + if (num > 5) + num = 5; QCString heading; heading.sprintf("Heading%d",num); // set style @@ -2590,7 +2614,7 @@ void RTFGenerator::writeDoc(const IDocNodeAST *ast,const Definition *ctx,const M auto astImpl = dynamic_cast(ast); if (astImpl) { - RTFDocVisitor visitor(m_t,*m_codeList,ctx?ctx->getDefFileExtension():QCString("")); + RTFDocVisitor visitor(m_t,*m_codeList,ctx?ctx->getDefFileExtension():QCString(""),m_hierarchyLevel); std::visit(visitor,astImpl->root); } m_omitParagraph = TRUE; diff --git a/src/rtfgen.h b/src/rtfgen.h index 494326a00de..5d0c52b338d 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -99,7 +99,7 @@ class RTFGenerator : public OutputGenerator void endPageDoc() {} void startIndexSection(IndexSection); void endIndexSection(IndexSection); - void writePageLink(const QCString &,bool); + void writePageLink(const QCString &,bool) {}; void startProjectNumber(); void endProjectNumber(); void writeStyleInfo(int part); @@ -322,6 +322,7 @@ class RTFGenerator : public OutputGenerator bool m_omitParagraph = false; // should a the next paragraph command be ignored? int m_numCols = 0; // number of columns in a table QCString m_relPath; + int m_hierarchyLevel = 0; // RTF does not really have a additive indent...manually set list level. static const int maxIndentLevels = 13;