Doxygen
Loading...
Searching...
No Matches
ftvhelp.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * ftvhelp.cpp,v 1.0 2000/09/06 16:09:00
3 *
4 * Copyright (C) 1997-2015 by Dimitri van Heesch.
5 *
6 * Permission to use, copy, modify, and distribute this software and its
7 * documentation under the terms of the GNU General Public License is hereby
8 * granted. No representations are made about the suitability of this software
9 * for any purpose. It is provided "as is" without express or implied warranty.
10 * See the GNU General Public License for more details.
11 *
12 * Documents produced by Doxygen are derivative works derived from the
13 * input used in their production; they are not affected by this license.
14 *
15 * Original version contributed by Kenney Wong <kwong@ea.com>
16 * Modified by Dimitri van Heesch
17 *
18 * Folder Tree View for offline help on browsers that do not support HTML Help.
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <algorithm>
24
25#include "ftvhelp.h"
26#include "config.h"
27#include "message.h"
28#include "doxygen.h"
29#include "language.h"
30#include "htmlgen.h"
31#include "layout.h"
32#include "pagedef.h"
33#include "docparser.h"
34#include "htmldocvisitor.h"
35#include "filedef.h"
36#include "classdef.h"
37#include "util.h"
38#include "resourcemgr.h"
39#include "portable.h"
40#include "outputlist.h"
41#include "threadpool.h"
42
43static int folderId=1;
44
45
46struct FTVNode;
47using FTVNodePtr = std::shared_ptr<FTVNode>;
48using FTVNodeWeakPtr = std::weak_ptr<FTVNode>;
49using FTVNodes = std::vector<FTVNodePtr>;
50
51struct FTVNode
52{
53 FTVNode(bool dir,const QCString &r,const QCString &f,const QCString &a,
54 const QCString &n,bool sepIndex,bool navIndex,const Definition *df)
55 : isLast(TRUE), isDir(dir), ref(r), file(f), anchor(a), name(n),
56 separateIndex(sepIndex), addToNavIndex(navIndex),
57 def(df) {}
58 int computeTreeDepth(int level) const;
59 int numNodesAtLevel(int level,int maxLevel) const;
60 bool isLast;
61 bool isDir;
66 int index = 0;
72};
73
74int FTVNode::computeTreeDepth(int level) const
75{
76 int maxDepth=level;
77 for (const auto &n : children)
78 {
79 if (!n->children.empty())
80 {
81 int d = n->computeTreeDepth(level+1);
82 if (d>maxDepth) maxDepth=d;
83 }
84 }
85 return maxDepth;
86}
87
88int FTVNode::numNodesAtLevel(int level,int maxLevel) const
89{
90 int num=0;
91 if (level<maxLevel)
92 {
93 num++; // this node
94 for (const auto &n : children)
95 {
96 num+=n->numNodesAtLevel(level+1,maxLevel);
97 }
98 }
99 return num;
100}
101
102//----------------------------------------------------------------------------
103
105{
106 Private(bool TLI) : topLevelIndex(TLI) { indentNodes.resize(1); }
107 std::vector<FTVNodes> indentNodes;
108 int indent = 0;
110
111 void generateTree(TextStream &t,const FTVNodes &nl,int level,int maxLevel,int &index);
112 void generateLink(TextStream &t,const FTVNodePtr &n);
113};
114
115/*! Constructs an ftv help object.
116 * The object has to be \link initialize() initialized\endlink before it can
117 * be used.
118 */
119FTVHelp::FTVHelp(bool TLI) : p(std::make_unique<Private>(TLI)) {}
120FTVHelp::~FTVHelp() = default;
121
122/*! This will create a folder tree view table of contents file (tree.js).
123 * \sa finalize()
124 */
126{
127}
128
129/*! Finalizes the FTV help. This will finish and close the
130 * contents file (index.js).
131 * \sa initialize()
132 */
134{
136}
137
138/*! Increase the level of the contents hierarchy.
139 * This will start a new sublist in contents file.
140 * \sa decContentsDepth()
141 */
143{
144 //printf("%p: incContentsDepth() indent=%d\n",this,p->indent);
145 p->indent++;
146 p->indentNodes.resize(p->indent+1);
147}
148
149/*! Decrease the level of the contents hierarchy.
150 * This will end the current sublist.
151 * \sa incContentsDepth()
152 */
154{
155 //printf("%p: decContentsDepth() indent=%d\n",this,p->indent);
156 ASSERT(p->indent>0);
157 if (p->indent>0)
158 {
159 p->indent--;
160 auto &nl = p->indentNodes[p->indent];
161 if (!nl.empty())
162 {
163 auto &parent = nl.back();
164 auto &children = p->indentNodes[p->indent+1];
165 for (const auto &child : children)
166 {
167 parent->children.push_back(child);
168 }
169 children.clear();
170 }
171 }
172}
173
174/*! Add a list item to the contents file.
175 * \param isDir TRUE if the item is a directory, FALSE if it is a text
176 * \param name the name of the item.
177 * \param ref the URL of to the item.
178 * \param file the file containing the definition of the item
179 * \param anchor the anchor within the file.
180 * \param separateIndex put the entries in a separate index file
181 * \param addToNavIndex add this entry to the quick navigation index
182 * \param def Definition corresponding to this entry
183 */
185 const QCString &name,
186 const QCString &ref,
187 const QCString &file,
188 const QCString &anchor,
189 bool separateIndex,
190 bool addToNavIndex,
191 const Definition *def
192 )
193{
194 //printf("%p: p->indent=%d addContentsItem(%d,%s,%s,%s,%s)\n",(void*)this,p->indent,isDir,qPrint(name),qPrint(ref),qPrint(file),qPrint(anchor));
195 auto &nl = p->indentNodes[p->indent];
196 if (!nl.empty())
197 {
198 nl.back()->isLast=FALSE;
199 }
200 auto newNode = std::make_shared<FTVNode>(isDir,ref,file,anchor,name,separateIndex,addToNavIndex,def);
201 nl.push_back(newNode);
202 newNode->index = static_cast<int>(nl.size()-1);
203 if (p->indent>0)
204 {
205 auto &pnl = p->indentNodes[p->indent-1];
206 if (!pnl.empty())
207 {
208 newNode->parent = pnl.back();
209 }
210 }
211}
212
213static QCString node2URL(const FTVNodePtr &n,bool overruleFile=FALSE,bool srcLink=FALSE)
214{
215 QCString url = n->file;
216 if (!url.isEmpty() && url.at(0)=='!') // relative URL
217 {
218 // remove leading !
219 url = url.mid(1);
220 }
221 else if (!url.isEmpty() && url.at(0)=='^') // absolute URL
222 {
223 // skip, keep ^ in the output
224 }
225 else // local file (with optional anchor)
226 {
227 if (overruleFile && n->def && n->def->definitionType()==Definition::TypeFile)
228 {
229 const FileDef *fd = toFileDef(n->def);
230 if (srcLink)
231 {
232 url = fd->getSourceFileBase();
233 }
234 else
235 {
236 url = fd->getOutputFileBase();
237 }
238 }
240 if (!n->anchor.isEmpty()) url+="#"+n->anchor;
241 }
242 return url;
243}
244
245static QCString generateIndentLabel(const FTVNodePtr &n,int level)
246{
247 QCString result;
248 auto parent = n->parent.lock();
249 if (parent)
250 {
251 result=generateIndentLabel(parent,level+1);
252 }
253 result+=QCString().setNum(n->index)+"_";
254 return result;
255}
256
257static void generateIndent(TextStream &t, const FTVNodePtr &n,bool opened)
258{
259 int indent=0;
260 auto parent = n->parent.lock();
261 while (parent) { indent++; parent=parent->parent.lock(); }
262 if (n->isDir)
263 {
264 const char *ARROW_DOWN = "<span class=\"arrowhead opened\"></span>";
265 const char *ARROW_RIGHT = "<span class=\"arrowhead closed\"></span>";
266 QCString dir = opened ? ARROW_DOWN : ARROW_RIGHT;
267 t << "<span style=\"width:" << (indent*16) << "px;display:inline-block;\">&#160;</span>"
268 << "<span id=\"arr_" << generateIndentLabel(n,0) << "\" class=\"arrow\" ";
269 t << "onclick=\"dynsection.toggleFolder('" << generateIndentLabel(n,0) << "')\"";
270 t << ">" << dir
271 << "</span>";
272 }
273 else
274 {
275 t << "<span style=\"width:" << ((indent+1)*16) << "px;display:inline-block;\">&#160;</span>";
276 }
277}
278
280{
281 //printf("FTVHelp::generateLink(ref=%s,file=%s,anchor=%s\n",
282 // qPrint(n->ref),qPrint(n->file),qPrint(n->anchor));
283 bool setTarget = FALSE;
284 if (n->file.isEmpty()) // no link
285 {
286 t << "<b>" << convertToHtml(n->name) << "</b>";
287 }
288 else // link into other frame
289 {
290 if (!n->ref.isEmpty()) // link to entity imported via tag file
291 {
292 t << "<a class=\"elRef\" ";
293 QCString result = externalLinkTarget();
294 if (result != "") setTarget = TRUE;
295 t << result;
296 }
297 else // local link
298 {
299 t << "<a class=\"el\" ";
300 }
301 t << "href=\"";
302 t << externalRef("",n->ref,TRUE);
303 t << node2URL(n);
304 if (!setTarget)
305 {
306 if (topLevelIndex)
307 t << "\" target=\"basefrm\">";
308 else
309 t << "\" target=\"_self\">";
310 }
311 else
312 {
313 t << "\">";
314 }
315 t << convertToHtml(n->name);
316 t << "</a>";
317 if (!n->ref.isEmpty())
318 {
319 t << "&#160;[external]";
320 }
321 }
322}
323
324static void generateBriefDoc(TextStream &t,const Definition *def)
325{
326 QCString brief = def->briefDescription(TRUE);
327 //printf("*** %p: generateBriefDoc(%s)='%s'\n",def,qPrint(def->name()),qPrint(brief));
328 if (!brief.isEmpty())
329 {
330 auto parser { createDocParser() };
331 auto ast { validatingParseDoc(*parser.get(),
332 def->briefFile(),def->briefLine(),
333 def,nullptr,brief,FALSE,FALSE,
334 QCString(),TRUE,TRUE,Config_getBool(MARKDOWN_SUPPORT)) };
335 const DocNodeAST *astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
336 if (astImpl)
337 {
339 OutputCodeList htmlList;
340 htmlList.add<HtmlCodeGenerator>(&t,relPath);
341 HtmlDocVisitor visitor(t,htmlList,def);
342 std::visit(visitor,astImpl->root);
343 }
344 }
345}
346
347static char compoundIcon(const ClassDef *cd)
348{
349 char icon='C';
350 if (cd->getLanguage() == SrcLangExt::Slice)
351 {
353 {
354 icon='I';
355 }
356 else if (cd->compoundType()==ClassDef::Struct)
357 {
358 icon='S';
359 }
360 else if (cd->compoundType()==ClassDef::Exception)
361 {
362 icon='E';
363 }
364 }
365 return icon;
366}
367
368void FTVHelp::Private::generateTree(TextStream &t, const FTVNodes &nl,int level,int maxLevel,int &index)
369{
370 for (const auto &n : nl)
371 {
372 t << "<tr id=\"row_" << generateIndentLabel(n,0) << "\"";
373 if ((index&1)==0) // even row
374 t << " class=\"even\"";
375 else
376 t << " class=\"odd\"";
377 if (level>=maxLevel) // item invisible by default
378 t << " style=\"display:none;\"";
379 else // item visible by default
380 index++;
381 t << "><td class=\"entry\">";
382 bool nodeOpened = level+1<maxLevel;
383 generateIndent(t,n,nodeOpened);
384 if (n->isDir)
385 {
386 if (n->def && n->def->definitionType()==Definition::TypeGroup)
387 {
388 // no icon
389 }
390 else if (n->def && n->def->definitionType()==Definition::TypePage)
391 {
392 // no icon
393 }
394 else if (n->def && n->def->definitionType()==Definition::TypeNamespace)
395 {
396 if ((n->def->getLanguage() == SrcLangExt::Slice) || (n->def->getLanguage() == SrcLangExt::Fortran))
397 {
398 t << "<span class=\"icona\"><span class=\"icon\">M</span></span>";
399 }
400 else if ((n->def->getLanguage() == SrcLangExt::Java) || (n->def->getLanguage() == SrcLangExt::VHDL))
401 {
402 t << "<span class=\"icona\"><span class=\"icon\">P</span></span>";
403 }
404 else
405 {
406 t << "<span class=\"icona\"><span class=\"icon\">N</span></span>";
407 }
408 }
409 else if (n->def && n->def->definitionType()==Definition::TypeModule)
410 {
411 t << "<span class=\"icona\"><span class=\"icon\">M</span></span>";
412 }
413 else if (n->def && n->def->definitionType()==Definition::TypeClass)
414 {
415 char icon=compoundIcon(toClassDef(n->def));
416 t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>";
417 }
418 else
419 {
420 t << "<span id=\"img_" << generateIndentLabel(n,0) << "\" class=\"iconfolder"
421 << "\" onclick=\"dynsection.toggleFolder('" << generateIndentLabel(n,0)
422 << "')\"><div class=\"folder-icon"
423 << (nodeOpened ? " open" : "")
424 << "\"></div></span>";
425 }
426 generateLink(t,n);
427 t << "</td><td class=\"desc\">";
428 if (n->def)
429 {
430 generateBriefDoc(t,n->def);
431 }
432 t << "</td></tr>\n";
433 folderId++;
434 generateTree(t,n->children,level+1,maxLevel,index);
435 }
436 else // leaf node
437 {
438 const FileDef *srcRef=nullptr;
439 if (n->def && n->def->definitionType()==Definition::TypeFile &&
440 (toFileDef(n->def))->generateSourceFile())
441 {
442 srcRef = toFileDef(n->def);
443 }
444 if (srcRef)
445 {
446 QCString fn=srcRef->getSourceFileBase();
448 t << "<a href=\"" << fn << "\">";
449 }
450 if (n->def && n->def->definitionType()==Definition::TypeGroup)
451 {
452 // no icon
453 }
454 else if (n->def && n->def->definitionType()==Definition::TypePage)
455 {
456 // no icon
457 }
458 else if (n->def && n->def->definitionType()==Definition::TypeNamespace)
459 {
460 if ((n->def->getLanguage() == SrcLangExt::Slice) || (n->def->getLanguage() == SrcLangExt::Fortran))
461 {
462 t << "<span class=\"icona\"><span class=\"icon\">M</span></span>";
463 }
464 else if ((n->def->getLanguage() == SrcLangExt::Java) || (n->def->getLanguage() == SrcLangExt::VHDL))
465 {
466 t << "<span class=\"icona\"><span class=\"icon\">P</span></span>";
467 }
468 else
469 {
470 t << "<span class=\"icona\"><span class=\"icon\">N</span></span>";
471 }
472 }
473 else if (n->def && n->def->definitionType()==Definition::TypeModule)
474 {
475 t << "<span class=\"icona\"><span class=\"icon\">M</span></span>";
476 }
477 else if (n->def && n->def->definitionType()==Definition::TypeClass)
478 {
479 char icon=compoundIcon(toClassDef(n->def));
480 t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>";
481 }
482 else if (n->def && n->def->definitionType()==Definition::TypeConcept)
483 {
484 t << "<span class=\"icona\"><span class=\"icon\">R</span></span>";
485 }
486 else if (n->def && n->def->definitionType()==Definition::TypeDir)
487 {
488 t << "<span class=\"iconfolder\"><div class=\"folder-icon\"></div></span>";
489 }
490 else
491 {
492 t << "<span class=\"icondoc\"><div class=\"doc-icon\"></div></span>";
493 }
494 if (srcRef)
495 {
496 t << "</a>";
497 }
498 generateLink(t,n);
499 t << "</td><td class=\"desc\">";
500 if (n->def)
501 {
502 generateBriefDoc(t,n->def);
503 }
504 t << "</td></tr>\n";
505 }
506 }
507}
508
509//-----------------------------------------------------------
510
512{
513 NavIndexEntry(const QCString &u,const QCString &p) : url(u), path(p) {}
516};
517
518class NavIndexEntryList : public std::vector<NavIndexEntry>
519{
520};
521
522static QCString pathToNode(const FTVNodePtr &leaf,const FTVNodePtr &n)
523{
524 QCString result;
525 auto parent = n->parent.lock();
526 if (parent)
527 {
528 result+=pathToNode(leaf,parent);
529 }
530 result+=QCString().setNum(n->index);
531 if (leaf!=n) result+=",";
532 return result;
533}
534
535static bool dupOfParent(const FTVNodePtr &n)
536{
537 auto parent = n->parent.lock();
538 if (!parent) return FALSE;
539 if (n->file==parent->file) return TRUE;
540 return FALSE;
541}
542
543static void generateJSLink(TextStream &t,const FTVNodePtr &n)
544{
545 if (n->file.isEmpty()) // no link
546 {
547 t << "\"" << convertToJSString(n->name) << "\", null, ";
548 }
549 else // link into other page
550 {
551 QCString result = n->name;
552 if (Config_getBool(HIDE_SCOPE_NAMES)) result=stripScope(result);
553 t << "\"" << convertToJSString(result) << "\", \"";
554 t << externalRef("",n->ref,TRUE);
555 t << node2URL(n);
556 t << "\", ";
557 }
558}
559
561{
562 QCString varId = fileId;
563 int i=varId.findRev('/');
564 if (i>=0) varId = varId.mid(i+1);
565 return substitute(varId,"-","_");
566}
567
568
570{
571 JSTreeFile(const QCString &fi,const FTVNodePtr &n) : fileId(fi), node(n) {}
574};
575
576using JSTreeFiles = std::vector<JSTreeFile>;
577
578static void collectJSTreeFiles(const FTVNodes &nl,JSTreeFiles &files)
579{
580 QCString htmlOutput = Config_getString(HTML_OUTPUT);
581 for (const auto &n : nl)
582 {
583 if (n->separateIndex) // add new file if there are children
584 {
585 if (!n->children.empty())
586 {
587 QCString fileId = n->file;
588 files.emplace_back(fileId,n);
589 collectJSTreeFiles(n->children,files);
590 }
591 }
592 else // traverse without adding a new file
593 {
594 collectJSTreeFiles(n->children,files);
595 }
596 }
597}
598
599static std::mutex g_navIndexMutex;
600
602 const FTVNodes &nl,int level,bool &first)
603{
604 QCString htmlOutput = Config_getString(HTML_OUTPUT);
605 QCString indentStr;
606 indentStr.fill(' ',level*2);
607
608 bool found=FALSE;
609 for (const auto &n : nl)
610 {
611 // terminate previous entry
612 if (!first) t << ",\n";
613 first=FALSE;
614
615 // start entry
616 if (!found)
617 {
618 t << "[\n";
619 }
620 found=TRUE;
621
622 if (n->addToNavIndex) // add entry to the navigation index
623 {
624 std::lock_guard lock(g_navIndexMutex);
625 if (n->def && n->def->definitionType()==Definition::TypeFile)
626 {
627 const FileDef *fd = toFileDef(n->def);
628 bool src = false;
629 bool doc = fileVisibleInIndex(fd,src);
630 if (doc)
631 {
632 navIndex.emplace_back(node2URL(n,TRUE,FALSE),pathToNode(n,n));
633 }
634 if (src)
635 {
636 navIndex.emplace_back(node2URL(n,TRUE,TRUE),pathToNode(n,n));
637 }
638 }
639 else
640 {
641 navIndex.emplace_back(node2URL(n),pathToNode(n,n));
642 }
643 }
644
645 if (n->separateIndex) // store items in a separate file for dynamic loading
646 {
647 t << indentStr << " [ ";
648 generateJSLink(t,n);
649 if (!n->children.empty()) // write children to separate file for dynamic loading
650 {
651 QCString fileId = n->file;
652 if (!n->anchor.isEmpty())
653 {
654 fileId+="_"+n->anchor;
655 }
656 if (dupOfParent(n))
657 {
658 fileId+="_dup";
659 }
660 t << "\"" << fileId << "\" ]";
661 }
662 else // no children
663 {
664 t << "null ]";
665 }
666 }
667 else // show items in this file
668 {
669 bool firstChild=TRUE;
670 t << indentStr << " [ ";
671 generateJSLink(t,n);
672 bool emptySection = !generateJSTree(navIndex,t,n->children,level+1,firstChild);
673 if (emptySection)
674 t << "null ]";
675 else
676 t << "\n" << indentStr << " ] ]";
677 }
678 }
679 return found;
680}
681
682static void generateJSTreeFiles(NavIndexEntryList &navIndex,TextStream &t,const FTVNodes &nodeList)
683{
684 QCString htmlOutput = Config_getString(HTML_OUTPUT);
685
686 auto getVarName = [](const FTVNodePtr n)
687 {
688 QCString fileId = n->file;
689 if (!n->anchor.isEmpty()) fileId+="_"+n->anchor;
690 if (dupOfParent(n)) fileId+="_dup";
691 return fileId;
692 };
693
694 auto generateJSFile = [&](const JSTreeFile &tf)
695 {
696 QCString fileId = getVarName(tf.node);
697 QCString fileName = htmlOutput+"/"+fileId+".js";
698 std::ofstream ff = Portable::openOutputStream(fileName);
699 if (ff.is_open())
700 {
701 bool firstChild = true;
702 TextStream tt(&ff);
703 tt << "var " << convertFileId2Var(fileId) << " =\n";
704 generateJSTree(navIndex,tt,tf.node->children,1,firstChild);
705 tt << "\n];";
706 }
707 };
708
709 JSTreeFiles jsTreeFiles;
710 collectJSTreeFiles(nodeList,jsTreeFiles);
711
712 std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
713 if (numThreads>1) // multi threaded version
714 {
715 ThreadPool threadPool(numThreads);
716 std::vector< std::future<void> > results;
717 for (const auto &tf : jsTreeFiles)
718 {
719 results.emplace_back(threadPool.queue([&](){ generateJSFile(tf); }));
720 }
721 // wait for the results
722 for (auto &f : results) f.get();
723 }
724 else // single threaded version
725 {
726 for (const auto &tf : jsTreeFiles)
727 {
728 generateJSFile(tf);
729 }
730 }
731}
732
733static void generateJSNavTree(const FTVNodes &nodeList)
734{
735 QCString htmlOutput = Config_getString(HTML_OUTPUT);
736 std::ofstream f = Portable::openOutputStream(htmlOutput+"/navtreedata.js");
737 NavIndexEntryList navIndex;
738 if (f.is_open())
739 {
740 TextStream t(&f);
741 //TextStream tidx(&fidx);
742 //tidx << "var NAVTREEINDEX =\n";
743 //tidx << "{\n";
745 t << "var NAVTREE =\n";
746 t << "[\n";
747 t << " [ ";
748 QCString projName = Config_getString(PROJECT_NAME);
749 if (projName.isEmpty())
750 {
751 if (mainPageHasTitle()) // Use title of main page as root
752 {
753 t << "\"" << convertToJSString(Doxygen::mainPage->title()) << "\", ";
754 }
755 else // Use default section title as root
756 {
757 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::MainPage);
758 t << "\"" << convertToJSString(lne->title()) << "\", ";
759 }
760 }
761 else // use PROJECT_NAME as root tree element
762 {
763 t << "\"" << convertToJSString(projName) << "\", ";
764 }
765 t << "\"index" << Doxygen::htmlFileExtension << "\", ";
766
767 // add special entry for index page
768 navIndex.emplace_back("index"+Doxygen::htmlFileExtension,"");
769 // related page index is written as a child of index.html, so add this as well
770 navIndex.emplace_back("pages"+Doxygen::htmlFileExtension,"");
771
772 bool first=TRUE;
773 generateJSTree(navIndex,t,nodeList,1,first);
774 generateJSTreeFiles(navIndex,t,nodeList);
775
776 if (first)
777 t << "]\n";
778 else
779 t << "\n ] ]\n";
780 t << "];\n\n";
781
782 // write the navigation index (and sub-indices)
783 std::stable_sort(navIndex.begin(),navIndex.end(),[](const auto &n1,const auto &n2)
784 { return !n1.url.isEmpty() && (n2.url.isEmpty() || (n1.url<n2.url)); });
785
786 int subIndex=0;
787 int elemCount=0;
788 const int maxElemCount=250;
789 std::ofstream tsidx = Portable::openOutputStream(htmlOutput+"/navtreeindex0.js");
790 if (tsidx.is_open())
791 {
792 t << "var NAVTREEINDEX =\n";
793 t << "[\n";
794 tsidx << "var NAVTREEINDEX" << subIndex << " =\n";
795 tsidx << "{\n";
796 first=TRUE;
797 auto it = navIndex.begin();
798 while (it!=navIndex.end())
799 {
800 const NavIndexEntry &e = *it;
801 if (elemCount==0)
802 {
803 if (!first)
804 {
805 t << ",\n";
806 }
807 else
808 {
809 first=FALSE;
810 }
811 t << "\"" << e.url << "\"";
812 }
813 tsidx << "\"" << e.url << "\":[" << e.path << "]";
814 ++it;
815 if (it!=navIndex.end() && elemCount<maxElemCount-1) tsidx << ","; // not last entry
816 tsidx << "\n";
817
818 elemCount++;
819 if (it!=navIndex.end() && elemCount>=maxElemCount) // switch to new sub-index
820 {
821 tsidx << "};\n";
822 elemCount=0;
823 tsidx.close();
824 subIndex++;
825 QCString fileName = htmlOutput+"/navtreeindex"+QCString().setNum(subIndex)+".js";
826 tsidx = Portable::openOutputStream(fileName);
827 if (!tsidx.is_open()) break;
828 tsidx << "var NAVTREEINDEX" << subIndex << " =\n";
829 tsidx << "{\n";
830 }
831 }
832 tsidx << "};\n";
833 t << "\n];\n";
834 }
835 t << "\nvar SYNCONMSG = '" << theTranslator->trPanelSynchronisationTooltip(FALSE) << "';";
836 t << "\nvar SYNCOFFMSG = '" << theTranslator->trPanelSynchronisationTooltip(TRUE) << "';";
837 }
838
839 auto &mgr = ResourceMgr::instance();
840 {
841 std::ofstream fn = Portable::openOutputStream(htmlOutput+"/navtree.js");
842 if (fn.is_open())
843 {
844 TextStream t(&fn);
845 t << substitute(mgr.getAsString("navtree.js"),"$PROJECTID",getProjectId());
846 }
847 }
848}
849
850//-----------------------------------------------------------
851
852// new style scripts
854{
855 QCString htmlOutput = Config_getString(HTML_OUTPUT);
856
857 // generate navtree.js & navtreeindex.js
858 generateJSNavTree(p->indentNodes[0]);
859}
860
861// write tree inside page
863{
864 int preferredNumEntries = Config_getInt(HTML_INDEX_NUM_ENTRIES);
865 t << "<div class=\"directory\">\n";
866 int d=1, depth=1;
867 for (const auto &n : p->indentNodes[0])
868 {
869 if (!n->children.empty())
870 {
871 d = n->computeTreeDepth(2);
872 if (d>depth) depth=d;
873 }
874 }
875 int preferredDepth = depth;
876 // write level selector
877 if (depth>1)
878 {
879 t << "<div class=\"levels\">[";
880 t << theTranslator->trDetailLevel();
881 t << " ";
882 for (int i=1;i<=depth;i++)
883 {
884 t << "<span onclick=\"javascript:dynsection.toggleLevel(" << i << ");\">" << i << "</span>";
885 }
886 t << "]</div>";
887
888 if (preferredNumEntries>0)
889 {
890 preferredDepth=1;
891 for (int i=1;i<=depth;i++)
892 {
893 int num=0;
894 for (const auto &n : p->indentNodes[0])
895 {
896 num+=n->numNodesAtLevel(0,i);
897 }
898 if (num<=preferredNumEntries)
899 {
900 preferredDepth=i;
901 }
902 else
903 {
904 break;
905 }
906 }
907 }
908 }
909 //printf("preferred depth=%d\n",preferredDepth);
910
911 if (!p->indentNodes[0].empty())
912 {
913 t << "<table class=\"directory\">\n";
914 int index=0;
915 p->generateTree(t,p->indentNodes[0],0,preferredDepth,index);
916 t << "</table>\n";
917 }
918
919 t << "</div><!-- directory -->\n";
920}
921
922// write old style index.html and tree.html
A abstract class representing of a compound symbol.
Definition classdef.h:104
@ Interface
Definition classdef.h:112
@ Exception
Definition classdef.h:115
virtual CompoundType compoundType() const =0
Returns the type of compound this is, i.e.
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
virtual int briefLine() const =0
virtual QCString briefDescription(bool abbreviate=FALSE) const =0
virtual QCString getSourceFileBase() const =0
virtual QCString briefFile() const =0
virtual QCString getOutputFileBase() const =0
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1460
DocNodeVariant root
Definition docnode.h:1481
static std::unique_ptr< PageDef > mainPage
Definition doxygen.h:101
static QCString htmlFileExtension
Definition doxygen.h:122
std::unique_ptr< Private > p
Definition ftvhelp.h:68
void generateTreeView()
Definition ftvhelp.cpp:923
void addContentsItem(bool isDir, const QCString &name, const QCString &ref, const QCString &file, const QCString &anchor, bool separateIndex, bool addToNavIndex, const Definition *def)
Definition ftvhelp.cpp:184
void decContentsDepth()
Definition ftvhelp.cpp:153
void finalize()
Definition ftvhelp.cpp:133
void initialize()
Definition ftvhelp.cpp:125
FTVHelp(bool LTI)
Definition ftvhelp.cpp:119
void incContentsDepth()
Definition ftvhelp.cpp:142
void generateTreeViewScripts()
Definition ftvhelp.cpp:853
void generateTreeViewInline(TextStream &t)
Definition ftvhelp.cpp:862
A model of a file symbol.
Definition filedef.h:99
Generator for HTML code fragments.
Definition htmlgen.h:25
Concrete visitor implementation for HTML output.
static LayoutDocManager & instance()
Returns a reference to this singleton.
Definition layout.cpp:1435
LayoutNavEntry * rootNavEntry() const
returns the (invisible) root of the navigation tree.
Definition layout.cpp:1446
Definition ftvhelp.cpp:519
Class representing a list of different code generators.
Definition outputlist.h:164
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:194
This is an alternative implementation of QCString.
Definition qcstring.h:101
void fill(char c, int len=-1)
Fills a string with a predefined character.
Definition qcstring.h:180
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString & setNum(short n)
Definition qcstring.h:444
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
static ResourceMgr & instance()
Returns the one and only instance of this class.
Text streaming class that buffers data.
Definition textstream.h:36
Class managing a pool of worker threads.
Definition threadpool.h:48
auto queue(F &&f, Args &&... args) -> std::future< decltype(f(args...))>
Queue the callable function f for the threads to execute.
Definition threadpool.h:77
ClassDef * toClassDef(Definition *d)
#define Config_getInt(name)
Definition config.h:34
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1324
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:55
IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf, const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &input, bool indexWords, bool isExample, const QCString &exampleName, bool singleLine, bool linkFromIndex, bool markdownSupport)
FileDef * toFileDef(Definition *d)
Definition filedef.cpp:1895
static void generateLink(yyscan_t yyscanner, OutputCodeList &ol, const QCString &lname)
static bool dupOfParent(const FTVNodePtr &n)
Definition ftvhelp.cpp:535
static bool generateJSTree(NavIndexEntryList &navIndex, TextStream &t, const FTVNodes &nl, int level, bool &first)
Definition ftvhelp.cpp:601
static int folderId
Definition ftvhelp.cpp:43
static void generateJSLink(TextStream &t, const FTVNodePtr &n)
Definition ftvhelp.cpp:543
static QCString node2URL(const FTVNodePtr &n, bool overruleFile=FALSE, bool srcLink=FALSE)
Definition ftvhelp.cpp:213
static void generateBriefDoc(TextStream &t, const Definition *def)
Definition ftvhelp.cpp:324
static void collectJSTreeFiles(const FTVNodes &nl, JSTreeFiles &files)
Definition ftvhelp.cpp:578
static char compoundIcon(const ClassDef *cd)
Definition ftvhelp.cpp:347
static std::mutex g_navIndexMutex
Definition ftvhelp.cpp:599
static QCString pathToNode(const FTVNodePtr &leaf, const FTVNodePtr &n)
Definition ftvhelp.cpp:522
std::vector< FTVNodePtr > FTVNodes
Definition ftvhelp.cpp:49
std::weak_ptr< FTVNode > FTVNodeWeakPtr
Definition ftvhelp.cpp:48
static void generateIndent(TextStream &t, const FTVNodePtr &n, bool opened)
Definition ftvhelp.cpp:257
std::shared_ptr< FTVNode > FTVNodePtr
Definition ftvhelp.cpp:47
static void generateJSTreeFiles(NavIndexEntryList &navIndex, TextStream &t, const FTVNodes &nodeList)
Definition ftvhelp.cpp:682
std::vector< JSTreeFile > JSTreeFiles
Definition ftvhelp.cpp:576
static void generateJSNavTree(const FTVNodes &nodeList)
Definition ftvhelp.cpp:733
static QCString convertFileId2Var(const QCString &fileId)
Definition ftvhelp.cpp:560
static QCString generateIndentLabel(const FTVNodePtr &n, int level)
Definition ftvhelp.cpp:245
constexpr auto JAVASCRIPT_LICENSE_TEXT
Definition ftvhelp.h:71
Translator * theTranslator
Definition language.cpp:71
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:665
Portable versions of functions that are platform dependent.
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:477
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
void generateTree(TextStream &t, const FTVNodes &nl, int level, int maxLevel, int &index)
Definition ftvhelp.cpp:368
void generateLink(TextStream &t, const FTVNodePtr &n)
Definition ftvhelp.cpp:279
std::vector< FTVNodes > indentNodes
Definition ftvhelp.cpp:107
Private(bool TLI)
Definition ftvhelp.cpp:106
bool separateIndex
Definition ftvhelp.cpp:69
bool isLast
Definition ftvhelp.cpp:60
const Definition * def
Definition ftvhelp.cpp:71
bool addToNavIndex
Definition ftvhelp.cpp:70
FTVNodeWeakPtr parent
Definition ftvhelp.cpp:68
FTVNodes children
Definition ftvhelp.cpp:67
QCString ref
Definition ftvhelp.cpp:62
int numNodesAtLevel(int level, int maxLevel) const
Definition ftvhelp.cpp:88
QCString anchor
Definition ftvhelp.cpp:64
QCString file
Definition ftvhelp.cpp:63
int computeTreeDepth(int level) const
Definition ftvhelp.cpp:74
QCString name
Definition ftvhelp.cpp:65
bool isDir
Definition ftvhelp.cpp:61
FTVNode(bool dir, const QCString &r, const QCString &f, const QCString &a, const QCString &n, bool sepIndex, bool navIndex, const Definition *df)
Definition ftvhelp.cpp:53
int index
Definition ftvhelp.cpp:66
JSTreeFile(const QCString &fi, const FTVNodePtr &n)
Definition ftvhelp.cpp:571
FTVNodePtr node
Definition ftvhelp.cpp:573
QCString fileId
Definition ftvhelp.cpp:572
Base class for the layout of a navigation item at the top of the HTML pages.
Definition layout.h:156
QCString title() const
Definition layout.h:216
LayoutNavEntry * find(LayoutNavEntry::Kind k, const QCString &file=QCString()) const
Definition layout.cpp:133
Definition ftvhelp.cpp:512
QCString url
Definition ftvhelp.cpp:514
QCString path
Definition ftvhelp.cpp:515
NavIndexEntry(const QCString &u, const QCString &p)
Definition ftvhelp.cpp:513
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:6231
bool mainPageHasTitle()
Definition util.cpp:6760
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:4472
QCString relativePathToRoot(const QCString &name)
Definition util.cpp:4088
bool found
Definition util.cpp:984
bool fileVisibleInIndex(const FileDef *fd, bool &genSourceFile)
Definition util.cpp:6565
QCString stripScope(const QCString &name)
Definition util.cpp:4288
QCString convertToJSString(const QCString &s)
Definition util.cpp:4532
QCString getProjectId()
Definition util.cpp:7287
QCString externalLinkTarget(const bool parent)
Definition util.cpp:6187
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5408
A bunch of utility functions.