1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation ([email protected])
|
---|
6 | **
|
---|
7 | ** This file is part of the tools applications of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
15 | **
|
---|
16 | ** GNU Lesser General Public License Usage
|
---|
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
18 | ** General Public License version 2.1 as published by the Free Software
|
---|
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
20 | ** packaging of this file. Please review the following information to
|
---|
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
23 | **
|
---|
24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | /*
|
---|
43 | webxmlgenerator.cpp
|
---|
44 | */
|
---|
45 |
|
---|
46 | #include "codemarker.h"
|
---|
47 | #include "pagegenerator.h"
|
---|
48 | #include "webxmlgenerator.h"
|
---|
49 | #include "node.h"
|
---|
50 | #include "separator.h"
|
---|
51 | #include "tree.h"
|
---|
52 |
|
---|
53 | #include <QtCore/qxmlstream.h>
|
---|
54 |
|
---|
55 | QT_BEGIN_NAMESPACE
|
---|
56 |
|
---|
57 | #define COMMAND_VERSION Doc::alias("version")
|
---|
58 |
|
---|
59 | WebXMLGenerator::WebXMLGenerator()
|
---|
60 | : PageGenerator()
|
---|
61 | {
|
---|
62 | }
|
---|
63 |
|
---|
64 | WebXMLGenerator::~WebXMLGenerator()
|
---|
65 | {
|
---|
66 | }
|
---|
67 |
|
---|
68 | void WebXMLGenerator::initializeGenerator(const Config &config)
|
---|
69 | {
|
---|
70 | Generator::initializeGenerator(config);
|
---|
71 |
|
---|
72 | project = config.getString(CONFIG_PROJECT);
|
---|
73 |
|
---|
74 | projectDescription = config.getString(CONFIG_DESCRIPTION);
|
---|
75 | if (projectDescription.isEmpty() && !project.isEmpty())
|
---|
76 | projectDescription = project + " Reference Documentation";
|
---|
77 |
|
---|
78 | projectUrl = config.getString(CONFIG_URL);
|
---|
79 |
|
---|
80 | generateIndex = config.getBool(CONFIG_GENERATEINDEX);
|
---|
81 | }
|
---|
82 |
|
---|
83 | void WebXMLGenerator::terminateGenerator()
|
---|
84 | {
|
---|
85 | PageGenerator::terminateGenerator();
|
---|
86 | }
|
---|
87 |
|
---|
88 | QString WebXMLGenerator::format()
|
---|
89 | {
|
---|
90 | return "WebXML";
|
---|
91 | }
|
---|
92 |
|
---|
93 | QString WebXMLGenerator::fileExtension(const Node * /* node */) const
|
---|
94 | {
|
---|
95 | return "xml";
|
---|
96 | }
|
---|
97 |
|
---|
98 | void WebXMLGenerator::generateTree(const Tree *tree, CodeMarker *marker)
|
---|
99 | {
|
---|
100 | tre = tree;
|
---|
101 | moduleClassMap.clear();
|
---|
102 | moduleNamespaceMap.clear();
|
---|
103 | serviceClasses.clear();
|
---|
104 | findAllClasses(tree->root());
|
---|
105 | findAllNamespaces(tree->root());
|
---|
106 |
|
---|
107 | PageGenerator::generateTree(tree, marker);
|
---|
108 |
|
---|
109 | if (generateIndex)
|
---|
110 | tre->generateIndex(outputDir() + "/" + project.toLower() + ".index",
|
---|
111 | projectUrl, projectDescription, false);
|
---|
112 | }
|
---|
113 |
|
---|
114 | void WebXMLGenerator::startText(const Node *relative, CodeMarker *marker)
|
---|
115 | {
|
---|
116 | inLink = false;
|
---|
117 | inContents = false;
|
---|
118 | inSectionHeading = false;
|
---|
119 | numTableRows = 0;
|
---|
120 | sectionNumber.clear();
|
---|
121 | PageGenerator::startText(relative, marker);
|
---|
122 | }
|
---|
123 |
|
---|
124 | int WebXMLGenerator::generateAtom(QXmlStreamWriter &writer, const Atom *atom,
|
---|
125 | const Node *relative, CodeMarker *marker)
|
---|
126 | {
|
---|
127 | Q_UNUSED(writer);
|
---|
128 |
|
---|
129 | int skipAhead = 0;
|
---|
130 |
|
---|
131 | switch (atom->type()) {
|
---|
132 | default:
|
---|
133 | PageGenerator::generateAtom(atom, relative, marker);
|
---|
134 | }
|
---|
135 | return skipAhead;
|
---|
136 | }
|
---|
137 |
|
---|
138 | void WebXMLGenerator::generateClassLikeNode(const InnerNode *inner,
|
---|
139 | CodeMarker *marker)
|
---|
140 | {
|
---|
141 | QByteArray data;
|
---|
142 | QXmlStreamWriter writer(&data);
|
---|
143 | writer.setAutoFormatting(true);
|
---|
144 | writer.writeStartDocument();
|
---|
145 | writer.writeStartElement("WebXML");
|
---|
146 | writer.writeStartElement("document");
|
---|
147 |
|
---|
148 | generateIndexSections(writer, inner, marker);
|
---|
149 |
|
---|
150 | writer.writeEndElement(); // document
|
---|
151 | writer.writeEndElement(); // WebXML
|
---|
152 | writer.writeEndDocument();
|
---|
153 |
|
---|
154 | out() << data;
|
---|
155 | out().flush();
|
---|
156 | }
|
---|
157 |
|
---|
158 | void WebXMLGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
|
---|
159 | {
|
---|
160 | QByteArray data;
|
---|
161 | QXmlStreamWriter writer(&data);
|
---|
162 | writer.setAutoFormatting(true);
|
---|
163 | writer.writeStartDocument();
|
---|
164 | writer.writeStartElement("WebXML");
|
---|
165 | writer.writeStartElement("document");
|
---|
166 |
|
---|
167 | generateIndexSections(writer, fake, marker);
|
---|
168 |
|
---|
169 | writer.writeEndElement(); // document
|
---|
170 | writer.writeEndElement(); // WebXML
|
---|
171 | writer.writeEndDocument();
|
---|
172 |
|
---|
173 | out() << data;
|
---|
174 | out().flush();
|
---|
175 | }
|
---|
176 |
|
---|
177 | void WebXMLGenerator::generateIndexSections(QXmlStreamWriter &writer,
|
---|
178 | const Node *node, CodeMarker *marker)
|
---|
179 | {
|
---|
180 | if (tre->generateIndexSection(writer, node, true)) {
|
---|
181 |
|
---|
182 | // Add documentation to this node if it exists.
|
---|
183 | writer.writeStartElement("description");
|
---|
184 | writer.writeAttribute("path", node->doc().location().filePath());
|
---|
185 | writer.writeAttribute("line", QString::number(node->doc().location().lineNo()));
|
---|
186 | writer.writeAttribute("column", QString::number(node->doc().location().columnNo()));
|
---|
187 |
|
---|
188 | if (node->type() == Node::Fake) {
|
---|
189 |
|
---|
190 | const FakeNode *fake = static_cast<const FakeNode *>(node);
|
---|
191 |
|
---|
192 | generateRelations(writer, node, marker);
|
---|
193 |
|
---|
194 | if (fake->subType() == Node::Module) {
|
---|
195 | writer.writeStartElement("generatedlist");
|
---|
196 | writer.writeAttribute("contents", "classesbymodule");
|
---|
197 |
|
---|
198 | if (moduleNamespaceMap.contains(fake->name())) {
|
---|
199 | writer.writeStartElement("section");
|
---|
200 | writer.writeStartElement("heading");
|
---|
201 | writer.writeAttribute("level", "1");
|
---|
202 | writer.writeCharacters("Namespaces");
|
---|
203 | writer.writeEndElement(); // heading
|
---|
204 | generateAnnotatedList(writer, fake, marker, moduleNamespaceMap[fake->name()]);
|
---|
205 | writer.writeEndElement(); // section
|
---|
206 | }
|
---|
207 | if (moduleClassMap.contains(fake->name())) {
|
---|
208 | writer.writeStartElement("section");
|
---|
209 | writer.writeStartElement("heading");
|
---|
210 | writer.writeAttribute("level", "1");
|
---|
211 | writer.writeCharacters("Classes");
|
---|
212 | writer.writeEndElement(); // heading
|
---|
213 | generateAnnotatedList(writer, fake, marker, moduleClassMap[fake->name()]);
|
---|
214 | writer.writeEndElement(); // section
|
---|
215 | }
|
---|
216 |
|
---|
217 | writer.writeEndElement(); // generatedlist
|
---|
218 | }
|
---|
219 | }
|
---|
220 |
|
---|
221 | startText(node, marker);
|
---|
222 |
|
---|
223 | const Atom *atom = node->doc().body().firstAtom();
|
---|
224 | while (atom)
|
---|
225 | atom = addAtomElements(writer, atom, node, marker);
|
---|
226 |
|
---|
227 | QList<Text> alsoList = node->doc().alsoList();
|
---|
228 | supplementAlsoList(node, alsoList);
|
---|
229 |
|
---|
230 | if (!alsoList.isEmpty()) {
|
---|
231 | writer.writeStartElement("see-also");
|
---|
232 | for (int i = 0; i < alsoList.size(); ++i) {
|
---|
233 | const Atom *atom = alsoList.at(i).firstAtom();
|
---|
234 | while (atom)
|
---|
235 | atom = addAtomElements(writer, atom, node, marker);
|
---|
236 | }
|
---|
237 | writer.writeEndElement(); // see-also
|
---|
238 | }
|
---|
239 |
|
---|
240 | writer.writeEndElement(); // description
|
---|
241 |
|
---|
242 | if (node->isInnerNode()) {
|
---|
243 | const InnerNode *inner = static_cast<const InnerNode *>(node);
|
---|
244 |
|
---|
245 | // Recurse to generate an element for this child node and all its children.
|
---|
246 | foreach (const Node *child, inner->childNodes())
|
---|
247 | generateIndexSections(writer, child, marker);
|
---|
248 |
|
---|
249 | writer.writeStartElement("related");
|
---|
250 | if (inner->relatedNodes().size() > 0) {
|
---|
251 | foreach (const Node *child, inner->relatedNodes())
|
---|
252 | generateIndexSections(writer, child, marker);
|
---|
253 | }
|
---|
254 | writer.writeEndElement(); // related
|
---|
255 | }
|
---|
256 | writer.writeEndElement();
|
---|
257 | }
|
---|
258 | }
|
---|
259 |
|
---|
260 | void WebXMLGenerator::generateInnerNode(const InnerNode *node, CodeMarker *marker)
|
---|
261 | {
|
---|
262 | if (!node->url().isNull())
|
---|
263 | return;
|
---|
264 |
|
---|
265 | if (node->type() == Node::Fake) {
|
---|
266 | const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
|
---|
267 | if (fakeNode->subType() == Node::ExternalPage)
|
---|
268 | return;
|
---|
269 | }
|
---|
270 |
|
---|
271 | if ( node->parent() != 0 ) {
|
---|
272 | beginSubPage( node->location(), fileName(node) );
|
---|
273 | if ( node->type() == Node::Namespace || node->type() == Node::Class) {
|
---|
274 | generateClassLikeNode(node, marker);
|
---|
275 | } else if ( node->type() == Node::Fake ) {
|
---|
276 | generateFakeNode(static_cast<const FakeNode *>(node), marker);
|
---|
277 | }
|
---|
278 | endSubPage();
|
---|
279 | }
|
---|
280 |
|
---|
281 | NodeList::ConstIterator c = node->childNodes().begin();
|
---|
282 | while ( c != node->childNodes().end() ) {
|
---|
283 | if ((*c)->isInnerNode() && (
|
---|
284 | (*c)->access() != Node::Private || (*c)->status() == Node::Internal))
|
---|
285 | generateInnerNode( (const InnerNode *) *c, marker );
|
---|
286 | ++c;
|
---|
287 | }
|
---|
288 | }
|
---|
289 |
|
---|
290 | const Atom *WebXMLGenerator::addAtomElements(QXmlStreamWriter &writer,
|
---|
291 | const Atom *atom, const Node *relative, CodeMarker *marker)
|
---|
292 | {
|
---|
293 | switch (atom->type()) {
|
---|
294 | case Atom::AbstractLeft:
|
---|
295 | case Atom::AbstractRight:
|
---|
296 | break;
|
---|
297 | case Atom::AutoLink:
|
---|
298 | if (!inLink && !inSectionHeading) {
|
---|
299 | const Node *node = findNode(atom, relative, marker);
|
---|
300 | if (node) {
|
---|
301 | startLink(writer, atom, node, relative);
|
---|
302 | if (inLink) {
|
---|
303 | writer.writeCharacters(atom->string());
|
---|
304 | writer.writeEndElement(); // link
|
---|
305 | inLink = false;
|
---|
306 | }
|
---|
307 | } else
|
---|
308 | writer.writeCharacters(atom->string());
|
---|
309 | } else
|
---|
310 | writer.writeCharacters(atom->string());
|
---|
311 | break;
|
---|
312 | case Atom::BaseName:
|
---|
313 | break;
|
---|
314 | case Atom::BriefLeft:
|
---|
315 |
|
---|
316 | writer.writeStartElement("brief");
|
---|
317 | switch (relative->type()) {
|
---|
318 | case Node::Property:
|
---|
319 | writer.writeCharacters("This property");
|
---|
320 | break;
|
---|
321 | case Node::Variable:
|
---|
322 | writer.writeCharacters("This variable");
|
---|
323 | break;
|
---|
324 | default:
|
---|
325 | break;
|
---|
326 | }
|
---|
327 | if (relative->type() == Node::Property || relative->type() == Node::Variable) {
|
---|
328 | QString str;
|
---|
329 | const Atom *a = atom->next();
|
---|
330 | while (a != 0 && a->type() != Atom::BriefRight) {
|
---|
331 | if (a->type() == Atom::String || a->type() == Atom::AutoLink)
|
---|
332 | str += a->string();
|
---|
333 | a = a->next();
|
---|
334 | }
|
---|
335 | str[0] = str[0].toLower();
|
---|
336 | if (str.right(1) == ".")
|
---|
337 | str.chop(1);
|
---|
338 |
|
---|
339 | QStringList words = str.split(" ");
|
---|
340 | if (!(words.first() == "contains" || words.first() == "specifies"
|
---|
341 | || words.first() == "describes" || words.first() == "defines"
|
---|
342 | || words.first() == "holds" || words.first() == "determines"))
|
---|
343 | writer.writeCharacters(" holds ");
|
---|
344 | else
|
---|
345 | writer.writeCharacters(" ");
|
---|
346 | }
|
---|
347 | break;
|
---|
348 |
|
---|
349 | case Atom::BriefRight:
|
---|
350 | if (relative->type() == Node::Property || relative->type() == Node::Variable)
|
---|
351 | writer.writeCharacters(".");
|
---|
352 |
|
---|
353 | writer.writeEndElement(); // brief
|
---|
354 | break;
|
---|
355 |
|
---|
356 | case Atom::C:
|
---|
357 | writer.writeStartElement("teletype");
|
---|
358 | if (inLink)
|
---|
359 | writer.writeAttribute("type", "normal");
|
---|
360 | else
|
---|
361 | writer.writeAttribute("type", "highlighted");
|
---|
362 |
|
---|
363 | writer.writeCharacters(plainCode(atom->string()));
|
---|
364 | writer.writeEndElement(); // teletype
|
---|
365 | break;
|
---|
366 |
|
---|
367 | case Atom::Code:
|
---|
368 | writer.writeTextElement("code", trimmedTrailing(plainCode(atom->string())));
|
---|
369 | break;
|
---|
370 |
|
---|
371 | #ifdef QDOC_QML
|
---|
372 | case Atom::Qml:
|
---|
373 | writer.writeTextElement("qml", trimmedTrailing(plainCode(atom->string())));
|
---|
374 | #endif
|
---|
375 |
|
---|
376 | case Atom::CodeBad:
|
---|
377 | writer.writeTextElement("badcode", trimmedTrailing(plainCode(atom->string())));
|
---|
378 | break;
|
---|
379 |
|
---|
380 | case Atom::CodeNew:
|
---|
381 | writer.writeTextElement("para", "you can rewrite it as");
|
---|
382 | writer.writeTextElement("newcode", trimmedTrailing(plainCode(atom->string())));
|
---|
383 | break;
|
---|
384 |
|
---|
385 | case Atom::CodeOld:
|
---|
386 | writer.writeTextElement("para", "For example, if you have code like");
|
---|
387 | writer.writeTextElement("oldcode", trimmedTrailing(plainCode(atom->string())));
|
---|
388 | break;
|
---|
389 |
|
---|
390 | case Atom::CodeQuoteArgument:
|
---|
391 | if (quoteCommand == "dots") {
|
---|
392 | writer.writeAttribute("indent", atom->string());
|
---|
393 | writer.writeCharacters("...");
|
---|
394 | } else
|
---|
395 | writer.writeCharacters(atom->string());
|
---|
396 | writer.writeEndElement(); // code
|
---|
397 | break;
|
---|
398 |
|
---|
399 | case Atom::CodeQuoteCommand:
|
---|
400 | quoteCommand = atom->string();
|
---|
401 | writer.writeStartElement(quoteCommand);
|
---|
402 | break;
|
---|
403 |
|
---|
404 | case Atom::FootnoteLeft:
|
---|
405 | writer.writeStartElement("footnote");
|
---|
406 | break;
|
---|
407 |
|
---|
408 | case Atom::FootnoteRight:
|
---|
409 | writer.writeEndElement(); // footnote
|
---|
410 | break;
|
---|
411 | /*
|
---|
412 | case Atom::FormatElse:
|
---|
413 | writer.writeStartElement("else");
|
---|
414 | writer.writeEndElement(); // else
|
---|
415 | break;
|
---|
416 | */
|
---|
417 | case Atom::FormatEndif:
|
---|
418 | writer.writeEndElement(); // raw
|
---|
419 | break;
|
---|
420 | case Atom::FormatIf:
|
---|
421 | writer.writeStartElement("raw");
|
---|
422 | writer.writeAttribute("format", atom->string());
|
---|
423 | break;
|
---|
424 | case Atom::FormattingLeft:
|
---|
425 | {
|
---|
426 | if (atom->string() == ATOM_FORMATTING_BOLD)
|
---|
427 | writer.writeStartElement("bold");
|
---|
428 | else if (atom->string() == ATOM_FORMATTING_ITALIC)
|
---|
429 | writer.writeStartElement("italic");
|
---|
430 | else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
|
---|
431 | writer.writeStartElement("underline");
|
---|
432 | else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
|
---|
433 | writer.writeStartElement("subscript");
|
---|
434 | else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
|
---|
435 | writer.writeStartElement("superscript");
|
---|
436 | else if (atom->string() == ATOM_FORMATTING_TELETYPE)
|
---|
437 | writer.writeStartElement("teletype");
|
---|
438 | else if (atom->string() == ATOM_FORMATTING_PARAMETER)
|
---|
439 | writer.writeStartElement("argument");
|
---|
440 | else if (atom->string() == ATOM_FORMATTING_INDEX)
|
---|
441 | writer.writeStartElement("index");
|
---|
442 | }
|
---|
443 | break;
|
---|
444 | /* out() << formattingLeftMap()[atom->string()];
|
---|
445 | if ( atom->string() == ATOM_FORMATTING_PARAMETER ) {
|
---|
446 | if ( atom->next() != 0 && atom->next()->type() == Atom::String ) {
|
---|
447 | QRegExp subscriptRegExp( "([a-z]+)_([0-9n])" );
|
---|
448 | if ( subscriptRegExp.exactMatch(atom->next()->string()) ) {
|
---|
449 | out() << subscriptRegExp.cap( 1 ) << "<sub>"
|
---|
450 | << subscriptRegExp.cap( 2 ) << "</sub>";
|
---|
451 | skipAhead = 1;
|
---|
452 | }
|
---|
453 | }
|
---|
454 | }*/
|
---|
455 | case Atom::FormattingRight:
|
---|
456 | {
|
---|
457 | if (atom->string() == ATOM_FORMATTING_BOLD)
|
---|
458 | writer.writeEndElement();
|
---|
459 | else if (atom->string() == ATOM_FORMATTING_ITALIC)
|
---|
460 | writer.writeEndElement();
|
---|
461 | else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
|
---|
462 | writer.writeEndElement();
|
---|
463 | else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
|
---|
464 | writer.writeEndElement();
|
---|
465 | else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
|
---|
466 | writer.writeEndElement();
|
---|
467 | else if (atom->string() == ATOM_FORMATTING_TELETYPE)
|
---|
468 | writer.writeEndElement();
|
---|
469 | else if (atom->string() == ATOM_FORMATTING_PARAMETER)
|
---|
470 | writer.writeEndElement();
|
---|
471 | else if (atom->string() == ATOM_FORMATTING_INDEX)
|
---|
472 | writer.writeEndElement();
|
---|
473 | }
|
---|
474 | if (inLink) {
|
---|
475 | writer.writeEndElement(); // link
|
---|
476 | inLink = false;
|
---|
477 | }
|
---|
478 | break;
|
---|
479 | /* if ( atom->string() == ATOM_FORMATTING_LINK ) {
|
---|
480 | if (inLink) {
|
---|
481 | if ( link.isEmpty() ) {
|
---|
482 | if (showBrokenLinks)
|
---|
483 | out() << "</i>";
|
---|
484 | } else {
|
---|
485 | out() << "</a>";
|
---|
486 | }
|
---|
487 | }
|
---|
488 | inLink = false;
|
---|
489 | } else {
|
---|
490 | out() << formattingRightMap()[atom->string()];
|
---|
491 | }*/
|
---|
492 | case Atom::GeneratedList:
|
---|
493 | writer.writeStartElement("generatedlist");
|
---|
494 | writer.writeAttribute("contents", atom->string());
|
---|
495 | writer.writeEndElement(); // generatedlist
|
---|
496 | /*
|
---|
497 | if (atom->string() == "annotatedclasses") {
|
---|
498 | generateAnnotatedList(relative, marker, nonCompatClasses);
|
---|
499 | } else if (atom->string() == "classes") {
|
---|
500 | generateCompactList(relative, marker, nonCompatClasses);
|
---|
501 | } else if (atom->string().contains("classesbymodule")) {
|
---|
502 | QString arg = atom->string().trimmed();
|
---|
503 | QString moduleName = atom->string().mid(atom->string().indexOf(
|
---|
504 | "classesbymodule") + 15).trimmed();
|
---|
505 | if (moduleClassMap.contains(moduleName))
|
---|
506 | generateAnnotatedList(relative, marker, moduleClassMap[moduleName]);
|
---|
507 | } else if (atom->string().contains("classesbyedition")) {
|
---|
508 | QString arg = atom->string().trimmed();
|
---|
509 | QString editionName = atom->string().mid(atom->string().indexOf(
|
---|
510 | "classesbyedition") + 16).trimmed();
|
---|
511 | if (editionModuleMap.contains(editionName)) {
|
---|
512 | QMap<QString, const Node *> editionClasses;
|
---|
513 | foreach (const QString &moduleName, editionModuleMap[editionName]) {
|
---|
514 | if (moduleClassMap.contains(moduleName))
|
---|
515 | editionClasses.unite(moduleClassMap[moduleName]);
|
---|
516 | }
|
---|
517 | generateAnnotatedList(relative, marker, editionClasses);
|
---|
518 | }
|
---|
519 | } else if (atom->string() == "classhierarchy") {
|
---|
520 | generateClassHierarchy(relative, marker, nonCompatClasses);
|
---|
521 | } else if (atom->string() == "compatclasses") {
|
---|
522 | generateCompactList(relative, marker, compatClasses);
|
---|
523 | } else if (atom->string() == "functionindex") {
|
---|
524 | generateFunctionIndex(relative, marker);
|
---|
525 | } else if (atom->string() == "legalese") {
|
---|
526 | generateLegaleseList(relative, marker);
|
---|
527 | } else if (atom->string() == "mainclasses") {
|
---|
528 | generateCompactList(relative, marker, mainClasses);
|
---|
529 | } else if (atom->string() == "services") {
|
---|
530 | generateCompactList(relative, marker, serviceClasses);
|
---|
531 | } else if (atom->string() == "overviews") {
|
---|
532 | generateOverviewList(relative, marker);
|
---|
533 | } else if (atom->string() == "namespaces") {
|
---|
534 | generateAnnotatedList(relative, marker, namespaceIndex);
|
---|
535 | } else if (atom->string() == "related") {
|
---|
536 | const FakeNode *fake = static_cast<const FakeNode *>(relative);
|
---|
537 | if (fake && !fake->groupMembers().isEmpty()) {
|
---|
538 | QMap<QString, const Node *> groupMembersMap;
|
---|
539 | foreach (Node *node, fake->groupMembers()) {
|
---|
540 | if (node->type() == Node::Fake)
|
---|
541 | groupMembersMap[fullName(node, relative, marker)] = node;
|
---|
542 | }
|
---|
543 | generateAnnotatedList(fake, marker, groupMembersMap);
|
---|
544 | }
|
---|
545 | } else if (atom->string() == "relatedinline") {
|
---|
546 | const FakeNode *fake = static_cast<const FakeNode *>(relative);
|
---|
547 | if (fake && !fake->groupMembers().isEmpty()) {
|
---|
548 | // Reverse the list into the original scan order.
|
---|
549 | // Should be sorted. But on what? It may not be a
|
---|
550 | // regular class or page definition.
|
---|
551 | QList<const Node *> list;
|
---|
552 | foreach (const Node *node, fake->groupMembers())
|
---|
553 | list.prepend(node);
|
---|
554 | foreach (const Node *node, list)
|
---|
555 | generateBody(node, marker );
|
---|
556 | }
|
---|
557 | }
|
---|
558 | break;
|
---|
559 | */
|
---|
560 | break;
|
---|
561 | case Atom::Image:
|
---|
562 | writer.writeStartElement("image");
|
---|
563 | writer.writeAttribute("href", imageFileName(relative, atom->string()));
|
---|
564 | writer.writeEndElement(); // image
|
---|
565 | break;
|
---|
566 |
|
---|
567 | case Atom::InlineImage:
|
---|
568 | writer.writeStartElement("inlineimage");
|
---|
569 | writer.writeAttribute("href", imageFileName(relative, atom->string()));
|
---|
570 | writer.writeEndElement(); // inlineimage
|
---|
571 | break;
|
---|
572 |
|
---|
573 | case Atom::ImageText:
|
---|
574 | break;
|
---|
575 |
|
---|
576 | case Atom::LegaleseLeft:
|
---|
577 | writer.writeStartElement("legalese");
|
---|
578 | break;
|
---|
579 |
|
---|
580 | case Atom::LegaleseRight:
|
---|
581 | writer.writeEndElement(); // legalese
|
---|
582 | break;
|
---|
583 |
|
---|
584 | case Atom::Link:
|
---|
585 | case Atom::LinkNode:
|
---|
586 | if (!inLink) {
|
---|
587 | const Node *node = findNode(atom, relative, marker);
|
---|
588 | if (node)
|
---|
589 | startLink(writer, atom, node, relative);
|
---|
590 | }
|
---|
591 | break;
|
---|
592 |
|
---|
593 | case Atom::ListLeft:
|
---|
594 | writer.writeStartElement("list");
|
---|
595 |
|
---|
596 | if (atom->string() == ATOM_LIST_BULLET)
|
---|
597 | writer.writeAttribute("type", "bullet");
|
---|
598 | else if (atom->string() == ATOM_LIST_TAG)
|
---|
599 | writer.writeAttribute("type", "definition");
|
---|
600 | else if (atom->string() == ATOM_LIST_VALUE)
|
---|
601 | writer.writeAttribute("type", "enum");
|
---|
602 | else {
|
---|
603 | writer.writeAttribute("type", "ordered");
|
---|
604 | if (atom->string() == ATOM_LIST_UPPERALPHA)
|
---|
605 | writer.writeAttribute("start", "A");
|
---|
606 | else if (atom->string() == ATOM_LIST_LOWERALPHA)
|
---|
607 | writer.writeAttribute("start", "a");
|
---|
608 | else if (atom->string() == ATOM_LIST_UPPERROMAN)
|
---|
609 | writer.writeAttribute("start", "I");
|
---|
610 | else if (atom->string() == ATOM_LIST_LOWERROMAN)
|
---|
611 | writer.writeAttribute("start", "i");
|
---|
612 | else // (atom->string() == ATOM_LIST_NUMERIC)
|
---|
613 | writer.writeAttribute("start", "1");
|
---|
614 | }
|
---|
615 | break;
|
---|
616 |
|
---|
617 | case Atom::ListItemNumber:
|
---|
618 | break;
|
---|
619 |
|
---|
620 | case Atom::ListTagLeft:
|
---|
621 | {
|
---|
622 | writer.writeStartElement("definition");
|
---|
623 |
|
---|
624 | writer.writeTextElement("term", plainCode(
|
---|
625 | marker->markedUpEnumValue(atom->next()->string(), relative)));
|
---|
626 | }
|
---|
627 | break;
|
---|
628 |
|
---|
629 | case Atom::ListTagRight:
|
---|
630 | writer.writeEndElement(); // definition
|
---|
631 | break;
|
---|
632 |
|
---|
633 | case Atom::ListItemLeft:
|
---|
634 | writer.writeStartElement("item");
|
---|
635 | break;
|
---|
636 |
|
---|
637 | case Atom::ListItemRight:
|
---|
638 | writer.writeEndElement(); // item
|
---|
639 | break;
|
---|
640 |
|
---|
641 | case Atom::ListRight:
|
---|
642 | writer.writeEndElement(); // list
|
---|
643 | break;
|
---|
644 |
|
---|
645 | case Atom::Nop:
|
---|
646 | break;
|
---|
647 |
|
---|
648 | case Atom::ParaLeft:
|
---|
649 | writer.writeStartElement("para");
|
---|
650 | break;
|
---|
651 |
|
---|
652 | case Atom::ParaRight:
|
---|
653 | writer.writeEndElement(); // para
|
---|
654 | break;
|
---|
655 |
|
---|
656 | case Atom::QuotationLeft:
|
---|
657 | writer.writeStartElement("quote");
|
---|
658 | break;
|
---|
659 |
|
---|
660 | case Atom::QuotationRight:
|
---|
661 | writer.writeEndElement(); // quote
|
---|
662 | break;
|
---|
663 |
|
---|
664 | case Atom::RawString:
|
---|
665 | writer.writeCharacters(atom->string());
|
---|
666 | break;
|
---|
667 |
|
---|
668 | case Atom::SectionLeft:
|
---|
669 | writer.writeStartElement("section");
|
---|
670 | writer.writeAttribute("id", Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
|
---|
671 | break;
|
---|
672 |
|
---|
673 | case Atom::SectionRight:
|
---|
674 | writer.writeEndElement(); // section
|
---|
675 | break;
|
---|
676 |
|
---|
677 | case Atom::SectionHeadingLeft:
|
---|
678 | writer.writeStartElement("heading");
|
---|
679 | writer.writeAttribute("level", atom->string()); // + hOffset(relative)
|
---|
680 | inSectionHeading = true;
|
---|
681 | break;
|
---|
682 |
|
---|
683 | case Atom::SectionHeadingRight:
|
---|
684 | writer.writeEndElement(); // heading
|
---|
685 | inSectionHeading = false;
|
---|
686 | break;
|
---|
687 |
|
---|
688 | case Atom::SidebarLeft:
|
---|
689 | case Atom::SidebarRight:
|
---|
690 | break;
|
---|
691 |
|
---|
692 | case Atom::SnippetCommand:
|
---|
693 | writer.writeStartElement(atom->string());
|
---|
694 | break;
|
---|
695 |
|
---|
696 | case Atom::SnippetIdentifier:
|
---|
697 | writer.writeAttribute("identifier", atom->string());
|
---|
698 | writer.writeEndElement(); // snippet
|
---|
699 | break;
|
---|
700 |
|
---|
701 | case Atom::SnippetLocation:
|
---|
702 | writer.writeAttribute("location", atom->string());
|
---|
703 | break;
|
---|
704 |
|
---|
705 | case Atom::String:
|
---|
706 | writer.writeCharacters(atom->string());
|
---|
707 | break;
|
---|
708 |
|
---|
709 | case Atom::TableLeft:
|
---|
710 | writer.writeStartElement("table");
|
---|
711 | if (atom->string().contains("%"))
|
---|
712 | writer.writeAttribute("width", atom->string());
|
---|
713 | break;
|
---|
714 |
|
---|
715 | case Atom::TableRight:
|
---|
716 | writer.writeEndElement(); // table
|
---|
717 | break;
|
---|
718 |
|
---|
719 | case Atom::TableHeaderLeft:
|
---|
720 | writer.writeStartElement("header");
|
---|
721 | break;
|
---|
722 |
|
---|
723 | case Atom::TableHeaderRight:
|
---|
724 | writer.writeEndElement(); // header
|
---|
725 | break;
|
---|
726 |
|
---|
727 | case Atom::TableRowLeft:
|
---|
728 | writer.writeStartElement("row");
|
---|
729 | break;
|
---|
730 |
|
---|
731 | case Atom::TableRowRight:
|
---|
732 | writer.writeEndElement(); // row
|
---|
733 | break;
|
---|
734 |
|
---|
735 | case Atom::TableItemLeft:
|
---|
736 | {
|
---|
737 | writer.writeStartElement("item");
|
---|
738 | QStringList spans = atom->string().split(",");
|
---|
739 | if (spans.size() == 2) {
|
---|
740 | if (spans.at(0) != "1")
|
---|
741 | writer.writeAttribute("colspan", spans.at(0).trimmed());
|
---|
742 | if (spans.at(1) != "1")
|
---|
743 | writer.writeAttribute("rowspan", spans.at(1).trimmed());
|
---|
744 | }
|
---|
745 | }
|
---|
746 | break;
|
---|
747 |
|
---|
748 | case Atom::TableItemRight:
|
---|
749 | writer.writeEndElement(); // item
|
---|
750 | break;
|
---|
751 |
|
---|
752 | case Atom::TableOfContents:
|
---|
753 | writer.writeStartElement("tableofcontents");
|
---|
754 | writer.writeAttribute("details", atom->string());
|
---|
755 | {
|
---|
756 | int numColumns = 1;
|
---|
757 | const Node *node = relative;
|
---|
758 |
|
---|
759 | Doc::SectioningUnit sectioningUnit = Doc::Section4;
|
---|
760 | QStringList params = atom->string().split(",");
|
---|
761 | QString columnText = params.at(0);
|
---|
762 | QStringList pieces = columnText.split(" ", QString::SkipEmptyParts);
|
---|
763 | if (pieces.size() >= 2) {
|
---|
764 | columnText = pieces.at(0);
|
---|
765 | pieces.pop_front();
|
---|
766 | QString path = pieces.join(" ").trimmed();
|
---|
767 | node = findNode(path, relative, marker);
|
---|
768 | if (node)
|
---|
769 | writer.writeAttribute("href", fileName(node));
|
---|
770 | }
|
---|
771 |
|
---|
772 | if (params.size() == 2) {
|
---|
773 | numColumns = qMax(columnText.toInt(), numColumns);
|
---|
774 | sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt();
|
---|
775 | writer.writeAttribute("columns", QString::number(numColumns));
|
---|
776 | writer.writeAttribute("unit", QString::number(sectioningUnit));
|
---|
777 | }
|
---|
778 |
|
---|
779 | if (node)
|
---|
780 | generateTableOfContents(writer, node, sectioningUnit, numColumns,
|
---|
781 | relative);
|
---|
782 | }
|
---|
783 | writer.writeEndElement(); // tableofcontents
|
---|
784 | break;
|
---|
785 |
|
---|
786 | case Atom::Target:
|
---|
787 | writer.writeStartElement("target");
|
---|
788 | writer.writeAttribute("name", Doc::canonicalTitle(atom->string()));
|
---|
789 | writer.writeEndElement(); // target
|
---|
790 | break;
|
---|
791 |
|
---|
792 | case Atom::UnhandledFormat:
|
---|
793 | case Atom::UnknownCommand:
|
---|
794 | writer.writeCharacters(atom->typeString());
|
---|
795 | break;
|
---|
796 | default:
|
---|
797 | break;
|
---|
798 | }
|
---|
799 |
|
---|
800 | if (atom)
|
---|
801 | return atom->next();
|
---|
802 |
|
---|
803 | return 0;
|
---|
804 | }
|
---|
805 | /*
|
---|
806 | QDomElement atomElement = document.createElement(atom->typeString().toLower());
|
---|
807 | QDomText atomValue = document.createTextNode(atom->string());
|
---|
808 | atomElement.appendChild(atomValue);
|
---|
809 | descriptionElement.appendChild(atomElement);
|
---|
810 | */
|
---|
811 |
|
---|
812 | /*
|
---|
813 | ### Warning: findNode() is a modified version of HtmlGenerator::getLink().
|
---|
814 | */
|
---|
815 | const Node *WebXMLGenerator::findNode(const Atom *atom, const Node *relative, CodeMarker *marker)
|
---|
816 | {
|
---|
817 | return findNode(atom->string(), relative, marker);
|
---|
818 | }
|
---|
819 |
|
---|
820 | const Node *WebXMLGenerator::findNode(const QString &title, const Node *relative, CodeMarker *marker)
|
---|
821 | {
|
---|
822 | QString link;
|
---|
823 | if (title.contains(":") &&
|
---|
824 | (title.startsWith("file:")
|
---|
825 | || title.startsWith("http:")
|
---|
826 | || title.startsWith("https:")
|
---|
827 | || title.startsWith("ftp:")
|
---|
828 | || title.startsWith("mailto:"))) {
|
---|
829 |
|
---|
830 | return 0;
|
---|
831 | } else if (title.count('@') == 1) {
|
---|
832 | return 0;
|
---|
833 | } else {
|
---|
834 | QStringList path;
|
---|
835 | if (title.contains('#')) {
|
---|
836 | path = title.split('#');
|
---|
837 | } else {
|
---|
838 | path.append(title);
|
---|
839 | }
|
---|
840 |
|
---|
841 | const Node *node = 0;
|
---|
842 | Atom *targetAtom = 0;
|
---|
843 |
|
---|
844 | QString first = path.first().trimmed();
|
---|
845 | if (first.isEmpty()) {
|
---|
846 | node = relative;
|
---|
847 | } else if (first.endsWith(".html")) {
|
---|
848 | node = tre->root()->findNode(first, Node::Fake);
|
---|
849 | } else {
|
---|
850 | node = marker->resolveTarget(first, tre, relative);
|
---|
851 | if (!node)
|
---|
852 | node = tre->findFakeNodeByTitle(first);
|
---|
853 | if (!node)
|
---|
854 | node = tre->findUnambiguousTarget(first, targetAtom);
|
---|
855 | }
|
---|
856 |
|
---|
857 | if (node) {
|
---|
858 | if (!node->url().isEmpty())
|
---|
859 | return node;
|
---|
860 | else
|
---|
861 | path.removeFirst();
|
---|
862 | } else {
|
---|
863 | return 0;
|
---|
864 | }
|
---|
865 |
|
---|
866 | while (!path.isEmpty()) {
|
---|
867 | targetAtom = tre->findTarget(path.first(), node);
|
---|
868 | if (targetAtom == 0)
|
---|
869 | break;
|
---|
870 | path.removeFirst();
|
---|
871 | }
|
---|
872 | /* We would ideally treat targets as nodes to be consistent.
|
---|
873 | if (targetAtom && node && node->isInnerNode()) {
|
---|
874 | Node *parentNode = const_cast<Node *>(node);
|
---|
875 | node = new TargetNode(static_cast<InnerNode*>(parentNode), first);
|
---|
876 | }
|
---|
877 | */
|
---|
878 | return node;
|
---|
879 | }
|
---|
880 | return 0;
|
---|
881 | }
|
---|
882 |
|
---|
883 | void WebXMLGenerator::startLink(QXmlStreamWriter &writer, const Atom *atom,
|
---|
884 | const Node *node, const Node *relative)
|
---|
885 | {
|
---|
886 | QString location = tre->fullDocumentLocation(node);
|
---|
887 | if (!location.isEmpty()) {
|
---|
888 | writer.writeStartElement("link");
|
---|
889 | writer.writeAttribute("raw", atom->string());
|
---|
890 | if (atom->string().contains("#") || node == relative) {
|
---|
891 | QString target = atom->string().split("#").last();
|
---|
892 | Atom *targetAtom = tre->findTarget(target, node);
|
---|
893 | if (targetAtom)
|
---|
894 | location += "#" + Doc::canonicalTitle(target);
|
---|
895 | }
|
---|
896 | writer.writeAttribute("href", location);
|
---|
897 | QString type = targetType(node);
|
---|
898 | writer.writeAttribute("type", type);
|
---|
899 | switch (node->type()) {
|
---|
900 | case Node::Enum:
|
---|
901 | writer.writeAttribute("enum", tre->fullDocumentName(node));
|
---|
902 | break;
|
---|
903 | case Node::Fake:
|
---|
904 | writer.writeAttribute("page", tre->fullDocumentName(node));
|
---|
905 | break;
|
---|
906 | case Node::Property:
|
---|
907 | {
|
---|
908 | const PropertyNode *propertyNode = static_cast<const PropertyNode *>(node);
|
---|
909 | if (propertyNode->getters().size() > 0)
|
---|
910 | writer.writeAttribute("getter", tre->fullDocumentName(propertyNode->getters()[0]));
|
---|
911 | }
|
---|
912 | default:
|
---|
913 | ;
|
---|
914 | }
|
---|
915 | inLink = true;
|
---|
916 | }
|
---|
917 | }
|
---|
918 |
|
---|
919 | QString WebXMLGenerator::targetType(const Node *node)
|
---|
920 | {
|
---|
921 | switch (node->type()) {
|
---|
922 | case Node::Namespace:
|
---|
923 | return "namespace";
|
---|
924 | break;
|
---|
925 | case Node::Class:
|
---|
926 | return "class";
|
---|
927 | break;
|
---|
928 | case Node::Fake:
|
---|
929 | return "page";
|
---|
930 | break;
|
---|
931 | case Node::Enum:
|
---|
932 | return "enum";
|
---|
933 | break;
|
---|
934 | case Node::Typedef:
|
---|
935 | return "typedef";
|
---|
936 | break;
|
---|
937 | case Node::Property:
|
---|
938 | return "property";
|
---|
939 | break;
|
---|
940 | case Node::Function:
|
---|
941 | return "function";
|
---|
942 | break;
|
---|
943 | case Node::Variable:
|
---|
944 | return "variable";
|
---|
945 | break;
|
---|
946 | case Node::Target:
|
---|
947 | return "target";
|
---|
948 | break;
|
---|
949 | default:
|
---|
950 | return "";
|
---|
951 | }
|
---|
952 | return "";
|
---|
953 | }
|
---|
954 |
|
---|
955 | void WebXMLGenerator::generateRelations(QXmlStreamWriter &writer, const Node *node, CodeMarker *marker)
|
---|
956 | {
|
---|
957 | if (node && !node->links().empty()) {
|
---|
958 | QPair<QString,QString> linkPair;
|
---|
959 | QPair<QString,QString> anchorPair;
|
---|
960 | const Node *linkNode;
|
---|
961 |
|
---|
962 | foreach (Node::LinkType relation, node->links().keys()) {
|
---|
963 |
|
---|
964 | linkPair = node->links()[relation];
|
---|
965 | linkNode = findNode(linkPair.first, node, marker);
|
---|
966 |
|
---|
967 | if (!linkNode)
|
---|
968 | linkNode = node;
|
---|
969 |
|
---|
970 | if (linkNode == node)
|
---|
971 | anchorPair = linkPair;
|
---|
972 | else
|
---|
973 | anchorPair = anchorForNode(linkNode);
|
---|
974 |
|
---|
975 | writer.writeStartElement("relation");
|
---|
976 | writer.writeAttribute("href", anchorPair.first);
|
---|
977 | writer.writeAttribute("type", targetType(linkNode));
|
---|
978 |
|
---|
979 | switch (relation) {
|
---|
980 | case Node::StartLink:
|
---|
981 | writer.writeAttribute("meta", "start");
|
---|
982 | break;
|
---|
983 | case Node::NextLink:
|
---|
984 | writer.writeAttribute("meta", "next");
|
---|
985 | break;
|
---|
986 | case Node::PreviousLink:
|
---|
987 | writer.writeAttribute("meta", "previous");
|
---|
988 | break;
|
---|
989 | case Node::ContentsLink:
|
---|
990 | writer.writeAttribute("meta", "contents");
|
---|
991 | break;
|
---|
992 | case Node::IndexLink:
|
---|
993 | writer.writeAttribute("meta", "index");
|
---|
994 | break;
|
---|
995 | default:
|
---|
996 | writer.writeAttribute("meta", "");
|
---|
997 | }
|
---|
998 | writer.writeAttribute("description", anchorPair.second);
|
---|
999 | writer.writeEndElement(); // link
|
---|
1000 | }
|
---|
1001 | }
|
---|
1002 | }
|
---|
1003 |
|
---|
1004 | // Classes adapted from HtmlGenerator.
|
---|
1005 |
|
---|
1006 | void WebXMLGenerator::generateTableOfContents(QXmlStreamWriter &writer, const Node *node,
|
---|
1007 | Doc::SectioningUnit sectioningUnit,
|
---|
1008 | int numColumns, const Node *relative)
|
---|
1009 |
|
---|
1010 | {
|
---|
1011 | if (!node->doc().hasTableOfContents())
|
---|
1012 | return;
|
---|
1013 | QList<Atom *> toc = node->doc().tableOfContents();
|
---|
1014 | if (toc.isEmpty())
|
---|
1015 | return;
|
---|
1016 |
|
---|
1017 | QString nodeName = "";
|
---|
1018 | if (node != relative)
|
---|
1019 | nodeName = node->name();
|
---|
1020 |
|
---|
1021 | QStringList sectionNumber;
|
---|
1022 | int columnSize = 0;
|
---|
1023 |
|
---|
1024 | if (numColumns > 1) {
|
---|
1025 | writer.writeStartElement("table");
|
---|
1026 | writer.writeAttribute("width", "100%");
|
---|
1027 | writer.writeStartElement("row");
|
---|
1028 | writer.writeStartElement("item");
|
---|
1029 | writer.writeAttribute("width", QString::number((100 + numColumns - 1) / numColumns) + "%");
|
---|
1030 | }
|
---|
1031 |
|
---|
1032 | // disable nested links in table of contents
|
---|
1033 | inContents = true;
|
---|
1034 | inLink = true;
|
---|
1035 |
|
---|
1036 | for (int i = 0; i < toc.size(); ++i) {
|
---|
1037 | Atom *atom = toc.at(i);
|
---|
1038 |
|
---|
1039 | int nextLevel = atom->string().toInt();
|
---|
1040 | if (nextLevel > (int)sectioningUnit)
|
---|
1041 | continue;
|
---|
1042 |
|
---|
1043 | if (sectionNumber.size() < nextLevel) {
|
---|
1044 | do {
|
---|
1045 | writer.writeStartElement("list");
|
---|
1046 | sectionNumber.append("1");
|
---|
1047 | } while (sectionNumber.size() < nextLevel);
|
---|
1048 | } else {
|
---|
1049 | while (sectionNumber.size() > nextLevel) {
|
---|
1050 | writer.writeEndElement();
|
---|
1051 | sectionNumber.removeLast();
|
---|
1052 | }
|
---|
1053 | sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
|
---|
1054 | }
|
---|
1055 | Text headingText = Text::sectionHeading(atom);
|
---|
1056 |
|
---|
1057 | if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) {
|
---|
1058 | writer.writeEndElement(); // list
|
---|
1059 | writer.writeEndElement(); // item
|
---|
1060 | writer.writeStartElement("item");
|
---|
1061 | writer.writeAttribute("width", QString::number((100 + numColumns - 1) / numColumns) + "%");
|
---|
1062 | writer.writeStartElement("list");
|
---|
1063 | columnSize = 0;
|
---|
1064 | }
|
---|
1065 |
|
---|
1066 | writer.writeStartElement("item");
|
---|
1067 | writer.writeStartElement("para");
|
---|
1068 | writer.writeStartElement("link");
|
---|
1069 | writer.writeAttribute("href", nodeName + "#" + Doc::canonicalTitle(headingText.toString()));
|
---|
1070 | writer.writeAttribute("type", "page");
|
---|
1071 | writer.writeCharacters(headingText.toString());
|
---|
1072 | writer.writeEndElement(); // link
|
---|
1073 | writer.writeEndElement(); // para
|
---|
1074 | writer.writeEndElement(); // item
|
---|
1075 |
|
---|
1076 | ++columnSize;
|
---|
1077 | }
|
---|
1078 | while (!sectionNumber.isEmpty()) {
|
---|
1079 | writer.writeEndElement(); // list
|
---|
1080 | sectionNumber.removeLast();
|
---|
1081 | }
|
---|
1082 |
|
---|
1083 | if (numColumns > 1) {
|
---|
1084 | writer.writeEndElement(); // item
|
---|
1085 | writer.writeEndElement(); // row
|
---|
1086 | writer.writeEndElement(); // table
|
---|
1087 | }
|
---|
1088 |
|
---|
1089 | inContents = false;
|
---|
1090 | inLink = false;
|
---|
1091 | }
|
---|
1092 |
|
---|
1093 | void WebXMLGenerator::generateAnnotatedList(QXmlStreamWriter &writer,
|
---|
1094 | const Node *relative, CodeMarker *marker, const QMap<QString, const Node *> &nodeMap)
|
---|
1095 | {
|
---|
1096 | writer.writeStartElement("table");
|
---|
1097 | writer.writeAttribute("width", "100%");
|
---|
1098 |
|
---|
1099 | foreach (QString name, nodeMap.keys()) {
|
---|
1100 | const Node *node = nodeMap[name];
|
---|
1101 |
|
---|
1102 | writer.writeStartElement("row");
|
---|
1103 | writer.writeStartElement("heading");
|
---|
1104 | generateFullName(writer, node, relative, marker);
|
---|
1105 | writer.writeEndElement(); // heading
|
---|
1106 |
|
---|
1107 | writer.writeStartElement("item");
|
---|
1108 | writer.writeCharacters(node->doc().briefText().toString());
|
---|
1109 | writer.writeEndElement(); // item
|
---|
1110 | writer.writeEndElement(); // row
|
---|
1111 | }
|
---|
1112 | writer.writeEndElement(); // table
|
---|
1113 | }
|
---|
1114 |
|
---|
1115 | void WebXMLGenerator::generateFullName(QXmlStreamWriter &writer,
|
---|
1116 | const Node *apparentNode, const Node *relative, CodeMarker *marker,
|
---|
1117 | const Node *actualNode)
|
---|
1118 | {
|
---|
1119 | if ( actualNode == 0 )
|
---|
1120 | actualNode = apparentNode;
|
---|
1121 | writer.writeStartElement("link");
|
---|
1122 | writer.writeAttribute("href", tre->fullDocumentLocation(actualNode));
|
---|
1123 | writer.writeAttribute("type", targetType(actualNode));
|
---|
1124 | writer.writeCharacters(fullName(apparentNode, relative, marker));
|
---|
1125 | writer.writeEndElement(); // link
|
---|
1126 | }
|
---|
1127 |
|
---|
1128 | // Classes copied (and slightly adapted) from the HtmlGenerator. These need
|
---|
1129 | // refactoring into a common ancestor class.
|
---|
1130 |
|
---|
1131 | void WebXMLGenerator::findAllClasses(const InnerNode *node)
|
---|
1132 | {
|
---|
1133 | NodeList::const_iterator c = node->childNodes().constBegin();
|
---|
1134 | while (c != node->childNodes().constEnd()) {
|
---|
1135 | if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) {
|
---|
1136 | if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
|
---|
1137 | QString className = (*c)->name();
|
---|
1138 | if ((*c)->parent() && (*c)->parent()->type() == Node::Namespace &&
|
---|
1139 | !(*c)->parent()->name().isEmpty())
|
---|
1140 | className = (*c)->parent()->name()+"::"+className;
|
---|
1141 |
|
---|
1142 | QString moduleName = (*c)->moduleName();
|
---|
1143 | if (!moduleName.isEmpty())
|
---|
1144 | moduleClassMap[moduleName].insert((*c)->name(), *c);
|
---|
1145 |
|
---|
1146 | QString serviceName =
|
---|
1147 | (static_cast<const ClassNode *>(*c))->serviceName();
|
---|
1148 | if (!serviceName.isEmpty())
|
---|
1149 | serviceClasses.insert(serviceName, *c);
|
---|
1150 | } else if ((*c)->isInnerNode()) {
|
---|
1151 | findAllClasses(static_cast<InnerNode *>(*c));
|
---|
1152 | }
|
---|
1153 | }
|
---|
1154 | ++c;
|
---|
1155 | }
|
---|
1156 | }
|
---|
1157 |
|
---|
1158 | void WebXMLGenerator::findAllNamespaces(const InnerNode *node)
|
---|
1159 | {
|
---|
1160 | NodeList::ConstIterator c = node->childNodes().begin();
|
---|
1161 | while (c != node->childNodes().end()) {
|
---|
1162 | if ((*c)->access() != Node::Private) {
|
---|
1163 | if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
|
---|
1164 | findAllNamespaces(static_cast<const InnerNode *>(*c));
|
---|
1165 | if ((*c)->type() == Node::Namespace) {
|
---|
1166 | const NamespaceNode *nspace = static_cast<const NamespaceNode *>(*c);
|
---|
1167 | // Ensure that the namespace's name is not empty (the root
|
---|
1168 | // namespace has no name).
|
---|
1169 | if (!nspace->name().isEmpty()) {
|
---|
1170 | namespaceIndex.insert(nspace->name(), *c);
|
---|
1171 | QString moduleName = (*c)->moduleName();
|
---|
1172 | if (!moduleName.isEmpty())
|
---|
1173 | moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
|
---|
1174 | }
|
---|
1175 | }
|
---|
1176 | }
|
---|
1177 | }
|
---|
1178 | ++c;
|
---|
1179 | }
|
---|
1180 | }
|
---|
1181 |
|
---|
1182 | const QPair<QString,QString> WebXMLGenerator::anchorForNode(const Node *node)
|
---|
1183 | {
|
---|
1184 | QPair<QString,QString> anchorPair;
|
---|
1185 |
|
---|
1186 | anchorPair.first = PageGenerator::fileName(node);
|
---|
1187 | if (node->type() == Node::Fake) {
|
---|
1188 | const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
|
---|
1189 | anchorPair.second = fakeNode->title();
|
---|
1190 | }
|
---|
1191 |
|
---|
1192 | return anchorPair;
|
---|
1193 | }
|
---|
1194 |
|
---|
1195 | QT_END_NAMESPACE
|
---|