Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
webxmlgenerator.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5
6#include "aggregate.h"
8#include "config.h"
11#include "node.h"
12#include "nodecontext.h"
13#include "propertynode.h"
14#include "qdocdatabase.h"
15#include "quoter.h"
16#include "utilities.h"
17
18#include <QtCore/qxmlstream.h>
19
21
22using namespace Qt::StringLiterals;
23
24static CodeMarker *marker_ = nullptr;
25
27
32
37
39{
40 return "WebXML";
41}
42
44{
45 // As this is meant to be an intermediate format,
46 // use .html for internal references. The name of
47 // the output file is set separately in
48 // beginSubPage() calls.
49 return "html";
50}
51
52/*!
53 Most of the output is generated by QDocIndexFiles and the append() callback.
54 Some pages produce supplementary output while being generated, and that's
55 handled here.
56*/
57qsizetype WebXMLGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker)
58{
59 if (m_supplement && currentWriter)
60 addAtomElements(*currentWriter.data(), atom, relative, marker);
61 return 0;
62}
63
65{
66 QByteArray data;
67 QXmlStreamWriter writer(&data);
68 writer.setAutoFormatting(true);
69 beginSubPage(aggregate, Generator::fileName(aggregate, "webxml"));
70 writer.writeStartDocument();
71 writer.writeStartElement("WebXML");
72 writer.writeStartElement("document");
73
74 generateIndexSections(writer, aggregate);
75
76 writer.writeEndElement(); // document
77 writer.writeEndElement(); // WebXML
78 writer.writeEndDocument();
79
80 out() << data;
81 endSubPage();
82}
83
85{
86 QByteArray data;
87 currentWriter.reset(new QXmlStreamWriter(&data));
88 currentWriter->setAutoFormatting(true);
89 beginSubPage(pn, Generator::fileName(pn, "webxml"));
90 currentWriter->writeStartDocument();
91 currentWriter->writeStartElement("WebXML");
92 currentWriter->writeStartElement("document");
93
94 generateIndexSections(*currentWriter.data(), pn);
95
96 currentWriter->writeEndElement(); // document
97 currentWriter->writeEndElement(); // WebXML
98 currentWriter->writeEndDocument();
99
100 out() << data;
101 endSubPage();
102}
103
104void WebXMLGenerator::generateExampleFilePage(const Node *en, ResolvedFile resolved_file, CodeMarker* /* marker */)
105{
106 // TODO: [generator-insufficient-structural-abstraction]
107
108 QByteArray data;
109 QXmlStreamWriter writer(&data);
110 writer.setAutoFormatting(true);
111 beginSubPage(en, linkForExampleFile(resolved_file.get_query(), "webxml"));
112 writer.writeStartDocument();
113 writer.writeStartElement("WebXML");
114 writer.writeStartElement("document");
115 writer.writeStartElement("page");
116 writer.writeAttribute("name", resolved_file.get_query());
117 writer.writeAttribute("href", linkForExampleFile(resolved_file.get_query()));
118 const QString title = exampleFileTitle(static_cast<const ExampleNode *>(en), resolved_file.get_query());
119 writer.writeAttribute("title", title);
120 writer.writeAttribute("fulltitle", title);
121 writer.writeAttribute("subtitle", resolved_file.get_query());
122 writer.writeStartElement("description");
123
124 if (Config::instance().get(CONFIG_LOCATIONINFO).asBool()) {
125 writer.writeAttribute("path", resolved_file.get_path());
126 writer.writeAttribute("line", "0");
127 writer.writeAttribute("column", "0");
128 }
129
130 Quoter quoter;
131 Doc::quoteFromFile(en->doc().location(), quoter, std::move(resolved_file));
132 QString code = quoter.quoteTo(en->location(), QString(), QString());
133 writer.writeTextElement("code", trimmedTrailing(code, QString(), QString()));
134
135 writer.writeEndElement(); // description
136 writer.writeEndElement(); // page
137 writer.writeEndElement(); // document
138 writer.writeEndElement(); // WebXML
139 writer.writeEndDocument();
140
141 out() << data;
142 endSubPage();
143}
144
145void WebXMLGenerator::generateIndexSections(QXmlStreamWriter &writer, Node *node)
146{
147 marker_ = CodeMarker::markerForFileName(node->location().filePath());
148 auto qdocIndexFiles = QDocIndexFiles::qdocIndexFiles();
149 if (qdocIndexFiles) {
150 qdocIndexFiles->generateIndexSections(writer, node, this);
151 // generateIndexSections does nothing for groups, so handle them explicitly
152 if (node->isGroup())
153 std::ignore = qdocIndexFiles->generateIndexSection(writer, node, this);
154 }
155}
156
157// Handles callbacks from QDocIndexFiles to add documentation to node
158void WebXMLGenerator::append(QXmlStreamWriter &writer, Node *node)
159{
160 Q_ASSERT(marker_);
161
162 writer.writeStartElement("description");
163 if (Config::instance().get(CONFIG_LOCATIONINFO).asBool()) {
164 writer.writeAttribute("path", node->doc().location().filePath());
165 writer.writeAttribute("line", QString::number(node->doc().location().lineNo()));
166 writer.writeAttribute("column", QString::number(node->doc().location().columnNo()));
167 }
168
169 if (node->isTextPageNode())
170 generateRelations(writer, node);
171
172 if (node->isModule()) {
173 writer.writeStartElement("generatedlist");
174 writer.writeAttribute("contents", "classesbymodule");
175 auto *cnn = static_cast<CollectionNode *>(node);
176
177 if (cnn->hasNamespaces()) {
178 writer.writeStartElement("section");
179 writer.writeStartElement("heading");
180 writer.writeAttribute("level", "1");
181 writer.writeCharacters("Namespaces");
182 writer.writeEndElement(); // heading
184 generateAnnotatedList(writer, node, namespaces);
185 writer.writeEndElement(); // section
186 }
187 if (cnn->hasClasses()) {
188 writer.writeStartElement("section");
189 writer.writeStartElement("heading");
190 writer.writeAttribute("level", "1");
191 writer.writeCharacters("Classes");
192 writer.writeEndElement(); // heading
193 NodeMap classes{cnn->getMembers([](const Node *n){ return n->isClassNode(); })};
194 generateAnnotatedList(writer, node, classes);
195 writer.writeEndElement(); // section
196 }
197 writer.writeEndElement(); // generatedlist
198 }
199
200 m_inLink = m_inSectionHeading = m_hasQuotingInformation = false;
201
202 const Atom *atom = node->doc().body().firstAtom();
203 while (atom)
204 atom = addAtomElements(writer, atom, node, marker_);
205
206 QList<Text> alsoList = node->doc().alsoList();
207 supplementAlsoList(node, alsoList);
208
209 if (!alsoList.isEmpty()) {
210 writer.writeStartElement("see-also");
211 for (const auto &item : alsoList) {
212 const auto *atom = item.firstAtom();
213 while (atom)
214 atom = addAtomElements(writer, atom, node, marker_);
215 }
216 writer.writeEndElement(); // see-also
217 }
218
219 if (node->isExample()) {
220 m_supplement = true;
222 m_supplement = false;
223 } else if (node->isGroup()) {
224 auto *cn = static_cast<CollectionNode *>(node);
225 if (!cn->noAutoList())
226 generateAnnotatedList(writer, node, cn->members());
227 }
228
229 writer.writeEndElement(); // description
230}
231
233{
234 // Don't generate nodes that are already processed, or if they're not supposed to
235 // generate output, ie. external, index or images nodes.
236 if (!node->url().isNull() || node->isExternalPage() || node->isIndexNode())
237 return;
238
239 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
240 const NodeContext context = node->createContext();
241 if (!InclusionFilter::isIncluded(policy, context))
242 return;
243
244 if (node->parent()) {
245 if (node->isNamespace() || node->isClassNode() || node->isHeader())
246 generateCppReferencePage(static_cast<Aggregate *>(node), nullptr);
247 else if (node->isCollectionNode()) {
248 if (node->wasSeen()) {
249 // see remarks in base class impl.
250 m_qdb->mergeCollections(static_cast<CollectionNode *>(node));
251 generatePageNode(static_cast<PageNode *>(node), nullptr);
252 }
253 } else if (node->isTextPageNode())
254 generatePageNode(static_cast<PageNode *>(node), nullptr);
255 // else if TODO: anything else?
256 }
257
258 if (node->isAggregate()) {
259 auto *aggregate = static_cast<Aggregate *>(node);
260 for (auto c : aggregate->childNodes()) {
261 if ((c->isAggregate() || c->isTextPageNode() || c->isCollectionNode())
262 && !c->isPrivate())
263 generateDocumentation(c);
264 }
265 }
266}
267
268const Atom *WebXMLGenerator::addAtomElements(QXmlStreamWriter &writer, const Atom *atom,
269 const Node *relative, CodeMarker *marker)
270{
271 bool keepQuoting = false;
272
273 if (!atom)
274 return nullptr;
275
276 switch (atom->type()) {
277 case Atom::AnnotatedList: {
278 const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group);
279 if (cn)
280 generateAnnotatedList(writer, relative, cn->members());
281 } break;
282 case Atom::AutoLink: {
283 const Node *node{nullptr};
284 QString link{};
285
286 if (!m_inLink && !m_inSectionHeading) {
287 link = getAutoLink(atom, relative, &node, Genus::API);
288
289 if (!link.isEmpty() && node && node->isDeprecated()
290 && relative->parent() != node && !relative->isDeprecated()) {
291 link.clear();
292 }
293 }
294
295 startLink(writer, atom, node, link);
296
297 writer.writeCharacters(atom->string());
298
299 if (m_inLink) {
300 writer.writeEndElement(); // link
301 m_inLink = false;
302 }
303
304 break;
305 }
306 case Atom::BaseName:
307 break;
308 case Atom::BriefLeft:
309
310 writer.writeStartElement("brief");
311 switch (relative->nodeType()) {
313 writer.writeCharacters("This property");
314 break;
316 writer.writeCharacters("This variable");
317 break;
318 default:
319 break;
320 }
321 if (relative->isProperty() || relative->isVariable()) {
322 QString str;
323 const Atom *a = atom->next();
324 while (a != nullptr && a->type() != Atom::BriefRight) {
326 str += a->string();
327 a = a->next();
328 }
329 str[0] = str[0].toLower();
330 if (str.endsWith('.'))
331 str.chop(1);
332
333 const QList<QStringView> words = QStringView{str}.split(' ');
334 if (!words.isEmpty()) {
335 QStringView first(words.at(0));
336 if (!(first == u"contains" || first == u"specifies" || first == u"describes"
337 || first == u"defines" || first == u"holds" || first == u"determines"))
338 writer.writeCharacters(" holds ");
339 else
340 writer.writeCharacters(" ");
341 }
342 }
343 break;
344
345 case Atom::BriefRight:
346 if (relative->isProperty() || relative->isVariable())
347 writer.writeCharacters(".");
348
349 writer.writeEndElement(); // brief
350 break;
351
352 case Atom::C:
353 writer.writeStartElement("teletype");
354 if (m_inLink)
355 writer.writeAttribute("type", "normal");
356 else
357 writer.writeAttribute("type", "highlighted");
358
359 writer.writeCharacters(plainCode(atom->string()));
360 writer.writeEndElement(); // teletype
361 break;
362
363 case Atom::Code:
364 if (!m_hasQuotingInformation)
365 writer.writeTextElement(
366 "code", trimmedTrailing(plainCode(atom->string()), QString(), QString()));
367 else
368 keepQuoting = true;
369 break;
370
371 case Atom::CodeBad:
372 writer.writeTextElement("badcode",
373 trimmedTrailing(plainCode(atom->string()), QString(), QString()));
374 break;
375
377 if (m_quoting) {
378 if (quoteCommand == "dots") {
379 writer.writeAttribute("indent", atom->string());
380 writer.writeCharacters("...");
381 } else {
382 writer.writeCharacters(atom->string());
383 }
384 writer.writeEndElement(); // code
385 keepQuoting = true;
386 }
387 break;
388
390 if (m_quoting) {
391 quoteCommand = atom->string();
392 writer.writeStartElement(quoteCommand);
393 }
394 break;
395
397 if (!m_inLink) {
398 QString link = linkForExampleFile(atom->string());
399 if (!link.isEmpty())
400 startLink(writer, atom, relative, link);
401 }
402 } break;
403
405 if (!m_inLink) {
406 QString link = atom->string();
407 if (!link.isEmpty())
408 startLink(writer, atom, nullptr, "images/used-in-examples/" + link);
409 }
410 } break;
411
413 writer.writeStartElement("footnote");
414 break;
415
417 writer.writeEndElement(); // footnote
418 break;
419
421 writer.writeEndElement(); // raw
422 break;
423 case Atom::FormatIf:
424 writer.writeStartElement("raw");
425 writer.writeAttribute("format", atom->string());
426 break;
428 if (atom->string() == ATOM_FORMATTING_BOLD)
429 writer.writeStartElement("bold");
430 else if (atom->string() == ATOM_FORMATTING_ITALIC)
431 writer.writeStartElement("italic");
432 else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
433 writer.writeStartElement("underline");
434 else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
435 writer.writeStartElement("subscript");
436 else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
437 writer.writeStartElement("superscript");
438 else if (atom->string() == ATOM_FORMATTING_TELETYPE || atom->string() == ATOM_FORMATTING_NOTRANSLATE)
439 writer.writeStartElement("teletype");
440 else if (atom->string() == ATOM_FORMATTING_PARAMETER)
441 writer.writeStartElement("argument");
442 else if (atom->string() == ATOM_FORMATTING_INDEX)
443 writer.writeStartElement("index");
444 } break;
445
447 if (atom->string() == ATOM_FORMATTING_BOLD)
448 writer.writeEndElement();
449 else if (atom->string() == ATOM_FORMATTING_ITALIC)
450 writer.writeEndElement();
451 else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
452 writer.writeEndElement();
453 else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
454 writer.writeEndElement();
455 else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
456 writer.writeEndElement();
457 else if (atom->string() == ATOM_FORMATTING_TELETYPE || atom->string() == ATOM_FORMATTING_NOTRANSLATE)
458 writer.writeEndElement();
459 else if (atom->string() == ATOM_FORMATTING_PARAMETER)
460 writer.writeEndElement();
461 else if (atom->string() == ATOM_FORMATTING_INDEX)
462 writer.writeEndElement();
463 else if (atom->string() == ATOM_FORMATTING_TRADEMARK && appendTrademark(atom))
464 writer.writeCharacters(QChar(0x2122)); // 'TM' symbol
465 }
466 if (m_inLink) {
467 writer.writeEndElement(); // link
468 m_inLink = false;
469 }
470 break;
471
473 writer.writeStartElement("generatedlist");
474 writer.writeAttribute("contents", atom->string());
475 writer.writeEndElement();
476 break;
477
478 // TODO: The other generators treat inlineimage and image
479 // simultaneously as the diffirences aren't big. It should be
480 // possible to do the same for webxmlgenerator instead of
481 // repeating the code.
482
483 // TODO: [generator-insufficient-structural-abstraction]
484 case Atom::Image:
485 case Atom::InlineImage: {
486 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
487 if (!maybe_resolved_file) {
488 // TODO: [uncentralized-admonition][failed-resolve-file]
489 relative->location().warning(QStringLiteral("Missing image: %1").arg(atom->string()));
490 } else {
491 ResolvedFile file{*maybe_resolved_file};
492 QString file_name{QFileInfo{file.get_path()}.fileName()};
493
494 // TODO: [uncentralized-output-directory-structure]
495 Config::copyFile(relative->doc().location(), file.get_path(), file_name,
496 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
497
498 writer.writeStartElement(atom->typeString().toLower());
499 const auto &imgPath = "%1/%2"_L1.arg(imagesOutputDir(), file_name);
500 // TODO: [uncentralized-output-directory-structure]
501 writer.writeAttribute("href", imgPath);
502 writer.writeEndElement();
503 // TODO: [uncentralized-output-directory-structure]
504 setImageFileName(relative, imgPath);
505 }
506 break;
507 }
508 case Atom::ImageText:
509 break;
510
512 writer.writeStartElement("para");
513 writer.writeTextElement("bold", "Important:");
514 writer.writeCharacters(" ");
515 break;
516
518 writer.writeStartElement("legalese");
519 break;
520
522 writer.writeEndElement(); // legalese
523 break;
524
525 case Atom::Link:
526 case Atom::LinkNode:
527 if (!m_inLink) {
528 const Node *node = nullptr;
529 QString link = getLink(atom, relative, &node);
530 if (!link.isEmpty())
531 startLink(writer, atom, node, link);
532 }
533 break;
534
535 case Atom::ListLeft:
536 writer.writeStartElement("list");
537
538 if (atom->string() == ATOM_LIST_BULLET)
539 writer.writeAttribute("type", "bullet");
540 else if (atom->string() == ATOM_LIST_TAG)
541 writer.writeAttribute("type", "definition");
542 else if (atom->string() == ATOM_LIST_VALUE) {
543 if (relative->isEnumType())
544 writer.writeAttribute("type", "enum");
545 else
546 writer.writeAttribute("type", "definition");
547 } else {
548 writer.writeAttribute("type", "ordered");
549 if (atom->string() == ATOM_LIST_UPPERALPHA)
550 writer.writeAttribute("start", "A");
551 else if (atom->string() == ATOM_LIST_LOWERALPHA)
552 writer.writeAttribute("start", "a");
553 else if (atom->string() == ATOM_LIST_UPPERROMAN)
554 writer.writeAttribute("start", "I");
555 else if (atom->string() == ATOM_LIST_LOWERROMAN)
556 writer.writeAttribute("start", "i");
557 else // (atom->string() == ATOM_LIST_NUMERIC)
558 writer.writeAttribute("start", "1");
559 }
560 break;
561
563 break;
564 case Atom::ListTagLeft: {
565 writer.writeStartElement("definition");
566
567 writer.writeTextElement(
568 "term", plainCode(marker->markedUpEnumValue(atom->next()->string(), relative)));
569 } break;
570
572 writer.writeEndElement(); // definition
573 break;
574
576 writer.writeStartElement("item");
577 break;
578
580 writer.writeEndElement(); // item
581 break;
582
583 case Atom::ListRight:
584 writer.writeEndElement(); // list
585 break;
586
587 case Atom::NoteLeft:
588 writer.writeStartElement("para");
589 writer.writeTextElement("bold", "Note:");
590 writer.writeCharacters(" ");
591 break;
592
593 // End admonition elements
595 case Atom::NoteRight:
597 writer.writeEndElement(); // para
598 break;
599
600 case Atom::Nop:
601 break;
602
604 case Atom::ParaLeft:
605 writer.writeStartElement("para");
606 break;
607
609 case Atom::ParaRight:
610 writer.writeEndElement(); // para
611 break;
612
614 writer.writeStartElement("quote");
615 break;
616
618 writer.writeEndElement(); // quote
619 break;
620
621 case Atom::RawString:
622 writer.writeCharacters(atom->string());
623 break;
624
626 writer.writeStartElement("section");
627 writer.writeAttribute("id",
628 Utilities::asAsciiPrintable(Text::sectionHeading(atom).toString()));
629 break;
630
632 writer.writeEndElement(); // section
633 break;
634
636 writer.writeStartElement("heading");
637 int unit = atom->string().toInt(); // + hOffset(relative)
638 writer.writeAttribute("level", QString::number(unit));
639 m_inSectionHeading = true;
640 } break;
641
643 writer.writeEndElement(); // heading
644 m_inSectionHeading = false;
645 break;
646
649 break;
650
652 if (m_quoting) {
653 writer.writeStartElement(atom->string());
654 }
655 break;
656
658 if (m_quoting) {
659 writer.writeAttribute("identifier", atom->string());
660 writer.writeEndElement();
661 keepQuoting = true;
662 }
663 break;
664
666 if (m_quoting) {
667 const QString &location = atom->string();
668 writer.writeAttribute("location", location);
669 auto maybe_resolved_file{file_resolver.resolve(location)};
670 // const QString resolved = Doc::resolveFile(Location(), location);
671 if (maybe_resolved_file)
672 writer.writeAttribute("path", (*maybe_resolved_file).get_path());
673 else {
674 // TODO: [uncetnralized-admonition][failed-resolve-file]
675 QString details = std::transform_reduce(
676 file_resolver.get_search_directories().cbegin(),
677 file_resolver.get_search_directories().cend(),
678 u"Searched directories:"_s,
679 std::plus(),
680 [](const DirectoryPath &directory_path) -> QString { return u' ' + directory_path.value(); }
681 );
682
683 relative->location().warning(u"Cannot find file to quote from: %1"_s.arg(location), details);
684 }
685 }
686 break;
687
688 case Atom::String:
689 writer.writeCharacters(atom->string());
690 break;
691 case Atom::TableLeft:
692 writer.writeStartElement("table");
693 if (atom->string().contains("%"))
694 writer.writeAttribute("width", atom->string());
695 break;
696
697 case Atom::TableRight:
698 writer.writeEndElement(); // table
699 break;
700
702 writer.writeStartElement("header");
703 break;
704
706 writer.writeEndElement(); // header
707 break;
708
710 writer.writeStartElement("row");
711 break;
712
714 writer.writeEndElement(); // row
715 break;
716
717 case Atom::TableItemLeft: {
718 writer.writeStartElement("item");
719 QStringList spans = atom->string().split(",");
720 if (spans.size() == 2) {
721 if (spans.at(0) != "1")
722 writer.writeAttribute("colspan", spans.at(0).trimmed());
723 if (spans.at(1) != "1")
724 writer.writeAttribute("rowspan", spans.at(1).trimmed());
725 }
726 } break;
728 writer.writeEndElement(); // item
729 break;
730
732 // Skip to the closing \endtoc atom
733 if (const auto *endtoc = atom->find(Atom::TableOfContentsRight))
734 atom = endtoc;
735 break;
736
737 case Atom::Target:
738 writer.writeStartElement("target");
739 writer.writeAttribute("name", Utilities::asAsciiPrintable(atom->string()));
740 writer.writeEndElement();
741 break;
742
744 writer.writeStartElement("para");
745 writer.writeTextElement("bold", "Warning:");
746 writer.writeCharacters(" ");
747 break;
748
751 writer.writeCharacters(atom->typeString());
752 break;
753 default:
754 break;
755 }
756
757 m_hasQuotingInformation = keepQuoting;
758 return atom->next();
759}
760
761void WebXMLGenerator::startLink(QXmlStreamWriter &writer, const Atom *atom, const Node *node,
762 const QString &link)
763{
764 QString fullName = link;
765 if (node)
766 fullName = node->fullName();
767 if (!fullName.isEmpty() && !link.isEmpty()) {
768 writer.writeStartElement("link");
769 if (atom && !atom->string().isEmpty())
770 writer.writeAttribute("raw", atom->string());
771 else
772 writer.writeAttribute("raw", fullName);
773 writer.writeAttribute("href", link);
774 writer.writeAttribute("type", targetType(node));
775 if (node) {
776 switch (node->nodeType()) {
777 case NodeType::Enum:
778 writer.writeAttribute("enum", fullName);
779 break;
780 case NodeType::Example: {
781 const auto *en = static_cast<const ExampleNode *>(node);
782 const QString fileTitle = atom ? exampleFileTitle(en, atom->string()) : QString();
783 if (!fileTitle.isEmpty()) {
784 writer.writeAttribute("page", fileTitle);
785 break;
786 }
787 }
788 Q_FALLTHROUGH();
789 case NodeType::Page:
790 writer.writeAttribute("page", fullName);
791 break;
792 case NodeType::Property: {
793 const auto *propertyNode = static_cast<const PropertyNode *>(node);
794 if (!propertyNode->getters().empty())
795 writer.writeAttribute("getter", propertyNode->getters().at(0)->fullName());
796 } break;
797 default:
798 break;
799 }
800 }
801 m_inLink = true;
802 }
803}
804
805void WebXMLGenerator::endLink(QXmlStreamWriter &writer)
806{
807 if (m_inLink) {
808 writer.writeEndElement(); // link
809 m_inLink = false;
810 }
811}
812
813void WebXMLGenerator::generateRelations(QXmlStreamWriter &writer, const Node *node)
814{
815 if (node && !node->links().empty()) {
816 std::pair<QString, QString> anchorPair;
817 const Node *linkNode;
818
819 for (auto it = node->links().cbegin(); it != node->links().cend(); ++it) {
820
821 linkNode = m_qdb->findNodeForTarget(it.value().first, node);
822
823 if (!linkNode)
824 linkNode = node;
825
826 if (linkNode == node)
827 anchorPair = it.value();
828 else
829 anchorPair = anchorForNode(linkNode);
830
831 writer.writeStartElement("relation");
832 writer.writeAttribute("href", anchorPair.first);
833 writer.writeAttribute("type", targetType(linkNode));
834
835 switch (it.key()) {
836 case Node::StartLink:
837 writer.writeAttribute("meta", "start");
838 break;
839 case Node::NextLink:
840 writer.writeAttribute("meta", "next");
841 break;
842 case Node::PreviousLink:
843 writer.writeAttribute("meta", "previous");
844 break;
845 case Node::ContentsLink:
846 writer.writeAttribute("meta", "contents");
847 break;
848 default:
849 writer.writeAttribute("meta", "");
850 }
851 writer.writeAttribute("description", anchorPair.second);
852 writer.writeEndElement(); // link
853 }
854 }
855}
856
857void WebXMLGenerator::generateAnnotatedList(QXmlStreamWriter &writer, const Node *relative,
858 const NodeMap &nodeMap)
859{
860 generateAnnotatedList(writer, relative, nodeMap.values());
861}
862
863void WebXMLGenerator::generateAnnotatedList(QXmlStreamWriter &writer, const Node *relative,
864 const NodeList &nodeList)
865{
866 writer.writeStartElement("table");
867 writer.writeAttribute("width", "100%");
868
869 for (const auto *node : nodeList) {
870 writer.writeStartElement("row");
871 writer.writeStartElement("item");
872 writer.writeStartElement("para");
873 const QString link = linkForNode(node, relative);
874 startLink(writer, node->doc().body().firstAtom(), node, link);
875 endLink(writer);
876 writer.writeEndElement(); // para
877 writer.writeEndElement(); // item
878
879 writer.writeStartElement("item");
880 writer.writeStartElement("para");
881 writer.writeCharacters(node->doc().briefText().toString());
882 writer.writeEndElement(); // para
883 writer.writeEndElement(); // item
884 writer.writeEndElement(); // row
885 }
886 writer.writeEndElement(); // table
887}
888
890{
891 return Generator::fileBase(node);
892}
893
894QT_END_NAMESPACE
#define ATOM_LIST_BULLET
Definition atom.h:215
#define ATOM_FORMATTING_TELETYPE
Definition atom.h:210
#define ATOM_LIST_LOWERALPHA
Definition atom.h:218
#define ATOM_FORMATTING_UNDERLINE
Definition atom.h:213
#define ATOM_LIST_UPPERALPHA
Definition atom.h:221
#define ATOM_FORMATTING_NOTRANSLATE
Definition atom.h:205
#define ATOM_LIST_TAG
Definition atom.h:216
#define ATOM_LIST_LOWERROMAN
Definition atom.h:219
#define ATOM_FORMATTING_SUBSCRIPT
Definition atom.h:208
#define ATOM_FORMATTING_BOLD
Definition atom.h:201
#define ATOM_FORMATTING_TRADEMARK
Definition atom.h:211
#define ATOM_LIST_VALUE
Definition atom.h:217
#define ATOM_FORMATTING_ITALIC
Definition atom.h:203
#define ATOM_LIST_UPPERROMAN
Definition atom.h:222
#define ATOM_FORMATTING_SUPERSCRIPT
Definition atom.h:209
#define ATOM_FORMATTING_INDEX
Definition atom.h:202
#define ATOM_FORMATTING_PARAMETER
Definition atom.h:206
The Atom class is the fundamental unit for representing documents internally.
Definition atom.h:19
AtomType type() const
Return the type of this atom.
Definition atom.h:151
@ CaptionLeft
Definition atom.h:29
@ ListTagLeft
Definition atom.h:65
@ TableRight
Definition atom.h:95
@ GeneratedList
Definition atom.h:50
@ BriefRight
Definition atom.h:27
@ CodeQuoteArgument
Definition atom.h:33
@ WarningLeft
Definition atom.h:106
@ TableOfContentsLeft
Definition atom.h:102
@ SidebarLeft
Definition atom.h:85
@ TableHeaderRight
Definition atom.h:97
@ InlineImage
Definition atom.h:56
@ TableRowRight
Definition atom.h:99
@ FootnoteRight
Definition atom.h:44
@ SnippetCommand
Definition atom.h:90
@ TableRowLeft
Definition atom.h:98
@ Nop
Definition atom.h:72
@ WarningRight
Definition atom.h:107
@ LegaleseRight
Definition atom.h:59
@ ListTagRight
Definition atom.h:66
@ CaptionRight
Definition atom.h:30
@ ListItemNumber
Definition atom.h:64
@ CodeBad
Definition atom.h:32
@ RawString
Definition atom.h:80
@ Target
Definition atom.h:104
@ AnnotatedList
Definition atom.h:22
@ SectionRight
Definition atom.h:82
@ SectionHeadingLeft
Definition atom.h:83
@ TableLeft
Definition atom.h:94
@ ListItemRight
Definition atom.h:68
@ Image
Definition atom.h:52
@ TableItemRight
Definition atom.h:101
@ ListItemLeft
Definition atom.h:67
@ ImportantRight
Definition atom.h:55
@ Code
Definition atom.h:31
@ String
Definition atom.h:93
@ ListLeft
Definition atom.h:63
@ CodeQuoteCommand
Definition atom.h:34
@ BriefLeft
Definition atom.h:26
@ ImageText
Definition atom.h:53
@ ExampleFileLink
Definition atom.h:41
@ LegaleseLeft
Definition atom.h:58
@ ListRight
Definition atom.h:69
@ C
Definition atom.h:28
@ ParaRight
Definition atom.h:76
@ FormattingLeft
Definition atom.h:48
@ FormattingRight
Definition atom.h:49
@ SectionHeadingRight
Definition atom.h:84
@ Link
Definition atom.h:61
@ ImportantLeft
Definition atom.h:54
@ FormatEndif
Definition atom.h:46
@ UnhandledFormat
Definition atom.h:105
@ ExampleImageLink
Definition atom.h:42
@ FootnoteLeft
Definition atom.h:43
@ AutoLink
Definition atom.h:23
@ SnippetLocation
Definition atom.h:92
@ TableHeaderLeft
Definition atom.h:96
@ QuotationLeft
Definition atom.h:78
@ SectionLeft
Definition atom.h:81
@ LinkNode
Definition atom.h:62
@ TableItemLeft
Definition atom.h:100
@ NoteRight
Definition atom.h:74
@ QuotationRight
Definition atom.h:79
@ ParaLeft
Definition atom.h:75
@ BaseName
Definition atom.h:24
@ FormatIf
Definition atom.h:47
@ SnippetIdentifier
Definition atom.h:91
@ NoteLeft
Definition atom.h:73
@ SidebarRight
Definition atom.h:86
@ UnknownCommand
Definition atom.h:108
const Atom * next() const
Return the next atom in the atom list.
Definition atom.h:148
A class for holding the members of a collection of doc pages.
bool hasClasses() const override
Returns true if this collection node contains at least one class node.
const NodeList & members() const
bool hasNamespaces() const override
Returns true if this collection node contains at least one namespace node.
NodeMap getMembers(NodeType type) const
Definition doc.h:31
const Location & location() const
Returns the starting location of a qdoc comment.
Definition doc.cpp:90
static void quoteFromFile(const Location &location, Quoter &quoter, ResolvedFile resolved_file)
Definition doc.cpp:421
const Text & body() const
Definition doc.cpp:115
Encapsulate the logic that QDoc uses to find files whose path is provided by the user and that are re...
bool m_quoting
Definition generator.h:225
FileResolver & file_resolver
Definition generator.h:217
QDocDatabase * m_qdb
Definition generator.h:219
bool m_inLink
Definition generator.h:220
static bool appendTrademark(const Atom *atom)
Returns true if a trademark symbol should be appended to the output as determined by atom.
bool m_inSectionHeading
Definition generator.h:222
QTextStream & out()
void endSubPage()
Flush the text stream associated with the subpage, and then pop it off the text stream stack and dele...
void generateRequiredLinks(const Node *node, CodeMarker *marker)
Generates either a link to the project folder for example node, or a list of links files/images if 'u...
HtmlGenerator(FileResolver &file_resolver)
void initializeGenerator() override
Initializes the HTML output generator's data structures from the configuration (Config) singleton.
void terminateGenerator() override
Gracefully terminates the HTML output generator.
static bool isIncluded(const InclusionPolicy &policy, const NodeContext &context)
A PageNode is a Node that generates a documentation page.
Definition pagenode.h:19
bool noAutoList() const
Returns the value of the no auto-list flag.
Definition pagenode.h:42
This class describes one instance of using the Q_PROPERTY macro.
const NodeList & getters() const
void mergeCollections(CollectionNode *c)
Finds all the collection nodes with the same name and type as c and merges their members into the mem...
This class handles qdoc index files.
Definition text.h:12
static Text sectionHeading(const Atom *sectionBegin)
Definition text.cpp:176
const Atom * firstAtom() const
Definition text.h:34
QString fileBase(const Node *node) const override
virtual const Atom * addAtomElements(QXmlStreamWriter &writer, const Atom *atom, const Node *relative, CodeMarker *marker)
void terminateGenerator() override
Gracefully terminates the HTML output generator.
void generateDocumentation(Node *node) override
Recursive writing of HTML files from the root node.
void append(QXmlStreamWriter &writer, Node *node) override
virtual void generateIndexSections(QXmlStreamWriter &writer, Node *node)
void generateExampleFilePage(const Node *en, ResolvedFile file, CodeMarker *marker=nullptr) override
Generate an html file with the contents of a C++ or QML source file.
void generatePageNode(PageNode *pn, CodeMarker *marker) override
Generate the HTML page for an entity that doesn't map to any underlying parsable C++ or QML element.
WebXMLGenerator(FileResolver &file_resolver)
QString format() override
QString fileExtension() const override
Returns "html" for this subclass of Generator.
void initializeGenerator() override
Initializes the HTML output generator's data structures from the configuration (Config) singleton.
void generateCppReferencePage(Aggregate *aggregate, CodeMarker *marker) override
Generate a reference page for the C++ class, namespace, or header file documented in node using the c...
qsizetype generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker) override
Most of the output is generated by QDocIndexFiles and the append() callback.
#define CONFIG_LOCATIONINFO
Definition config.h:404
NodeType
Definition genustypes.h:150
Combined button and popup list for selecting options.
QList< Node * > NodeList
Definition node.h:44
QMap< QString, Node * > NodeMap
Definition node.h:47
The Node class is the base class for all the nodes in QDoc's parse tree.
bool isExternalPage() const
Returns true if the node type is ExternalPage.
Definition node.h:106
const Doc & doc() const
Returns a reference to the node's Doc data member.
Definition node.h:242
bool isGroup() const
Returns true if the node type is Group.
Definition node.h:111
bool isNamespace() const
Returns true if the node type is Namespace.
Definition node.h:115
bool isHeader() const
Returns true if the node type is HeaderFile.
Definition node.h:112
NodeType nodeType() const override
Returns this node's type.
Definition node.h:89
bool isEnumType() const
Returns true if the node type is Enum.
Definition node.h:100
virtual bool isTextPageNode() const
Returns true if the node is a PageNode but not an Aggregate.
Definition node.h:160
Aggregate * parent() const
Returns the node's parent pointer.
Definition node.h:215
bool isVariable() const
Returns true if the node type is Variable.
Definition node.h:138
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
Definition node.h:141
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
Definition node.h:143
const Location & location() const
If this node's definition location is empty, this function returns this node's declaration location.
Definition node.h:238
virtual bool wasSeen() const
Returns the seen flag data member of this node if it is a NamespaceNode or a CollectionNode.
Definition node.h:199
bool isProperty() const
Returns true if the node type is Property.
Definition node.h:119
NodeContext createContext() const
Definition node.cpp:162
bool isModule() const
Returns true if the node type is Module.
Definition node.h:114
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
Definition node.h:150
virtual bool isCollectionNode() const
Returns true if this is an instance of CollectionNode.
Definition node.h:151
bool isExample() const
Returns true if the node type is Example.
Definition node.h:105
bool isIndexNode() const
Returns true if this node was created from something in an index file.
Definition node.h:113
Represents a file that is reachable by QDoc based on its current configuration.
static CodeMarker * marker_