1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2010 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 | htmlgenerator.cpp
|
---|
44 | */
|
---|
45 |
|
---|
46 | #include "codemarker.h"
|
---|
47 | #include "helpprojectwriter.h"
|
---|
48 | #include "htmlgenerator.h"
|
---|
49 | #include "node.h"
|
---|
50 | #include "separator.h"
|
---|
51 | #include "tree.h"
|
---|
52 | #include <ctype.h>
|
---|
53 |
|
---|
54 | #include <qdebug.h>
|
---|
55 | #include <qlist.h>
|
---|
56 | #include <qiterator.h>
|
---|
57 |
|
---|
58 | QT_BEGIN_NAMESPACE
|
---|
59 |
|
---|
60 | #define COMMAND_VERSION Doc::alias("version")
|
---|
61 |
|
---|
62 | QString HtmlGenerator::sinceTitles[] =
|
---|
63 | {
|
---|
64 | " New Namespaces",
|
---|
65 | " New Classes",
|
---|
66 | " New Member Functions",
|
---|
67 | " New Functions in Namespaces",
|
---|
68 | " New Global Functions",
|
---|
69 | " New Macros",
|
---|
70 | " New Enum Types",
|
---|
71 | " New Typedefs",
|
---|
72 | " New Properties",
|
---|
73 | " New Variables",
|
---|
74 | " New Qml Properties",
|
---|
75 | " New Qml Signals",
|
---|
76 | " New Qml Methods",
|
---|
77 | ""
|
---|
78 | };
|
---|
79 |
|
---|
80 | static bool showBrokenLinks = false;
|
---|
81 |
|
---|
82 | static QRegExp linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
|
---|
83 | static QRegExp funcTag("(<@func target=\"([^\"]*)\">)(.*)(</@func>)");
|
---|
84 | static QRegExp typeTag("(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)");
|
---|
85 | static QRegExp spanTag("</@(?:comment|preprocessor|string|char)>");
|
---|
86 | static QRegExp unknownTag("</?@[^>]*>");
|
---|
87 |
|
---|
88 | bool parseArg(const QString &src,
|
---|
89 | const QString &tag,
|
---|
90 | int *pos,
|
---|
91 | int n,
|
---|
92 | QStringRef *contents,
|
---|
93 | QStringRef *par1 = 0,
|
---|
94 | bool debug = false)
|
---|
95 | {
|
---|
96 | #define SKIP_CHAR(c) \
|
---|
97 | if (debug) \
|
---|
98 | qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
|
---|
99 | if (i >= n || src[i] != c) { \
|
---|
100 | if (debug) \
|
---|
101 | qDebug() << " char '" << c << "' not found"; \
|
---|
102 | return false; \
|
---|
103 | } \
|
---|
104 | ++i;
|
---|
105 |
|
---|
106 |
|
---|
107 | #define SKIP_SPACE \
|
---|
108 | while (i < n && src[i] == ' ') \
|
---|
109 | ++i;
|
---|
110 |
|
---|
111 | int i = *pos;
|
---|
112 | int j = i;
|
---|
113 |
|
---|
114 | // assume "<@" has been parsed outside
|
---|
115 | //SKIP_CHAR('<');
|
---|
116 | //SKIP_CHAR('@');
|
---|
117 |
|
---|
118 | if (tag != QStringRef(&src, i, tag.length())) {
|
---|
119 | if (0 && debug)
|
---|
120 | qDebug() << "tag " << tag << " not found at " << i;
|
---|
121 | return false;
|
---|
122 | }
|
---|
123 |
|
---|
124 | if (debug)
|
---|
125 | qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
|
---|
126 |
|
---|
127 | // skip tag
|
---|
128 | i += tag.length();
|
---|
129 |
|
---|
130 | // parse stuff like: linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
|
---|
131 | if (par1) {
|
---|
132 | SKIP_SPACE;
|
---|
133 | // read parameter name
|
---|
134 | j = i;
|
---|
135 | while (i < n && src[i].isLetter())
|
---|
136 | ++i;
|
---|
137 | if (src[i] == '=') {
|
---|
138 | if (debug)
|
---|
139 | qDebug() << "read parameter" << QString(src.data() + j, i - j);
|
---|
140 | SKIP_CHAR('=');
|
---|
141 | SKIP_CHAR('"');
|
---|
142 | // skip parameter name
|
---|
143 | j = i;
|
---|
144 | while (i < n && src[i] != '"')
|
---|
145 | ++i;
|
---|
146 | *par1 = QStringRef(&src, j, i - j);
|
---|
147 | SKIP_CHAR('"');
|
---|
148 | SKIP_SPACE;
|
---|
149 | } else {
|
---|
150 | if (debug)
|
---|
151 | qDebug() << "no optional parameter found";
|
---|
152 | }
|
---|
153 | }
|
---|
154 | SKIP_SPACE;
|
---|
155 | SKIP_CHAR('>');
|
---|
156 |
|
---|
157 | // find contents up to closing "</@tag>
|
---|
158 | j = i;
|
---|
159 | for (; true; ++i) {
|
---|
160 | if (i + 4 + tag.length() > n)
|
---|
161 | return false;
|
---|
162 | if (src[i] != '<')
|
---|
163 | continue;
|
---|
164 | if (src[i + 1] != '/')
|
---|
165 | continue;
|
---|
166 | if (src[i + 2] != '@')
|
---|
167 | continue;
|
---|
168 | if (tag != QStringRef(&src, i + 3, tag.length()))
|
---|
169 | continue;
|
---|
170 | if (src[i + 3 + tag.length()] != '>')
|
---|
171 | continue;
|
---|
172 | break;
|
---|
173 | }
|
---|
174 |
|
---|
175 | *contents = QStringRef(&src, j, i - j);
|
---|
176 |
|
---|
177 | i += tag.length() + 4;
|
---|
178 |
|
---|
179 | *pos = i;
|
---|
180 | if (debug)
|
---|
181 | qDebug() << " tag " << tag << " found: pos now: " << i;
|
---|
182 | return true;
|
---|
183 | #undef SKIP_CHAR
|
---|
184 | }
|
---|
185 |
|
---|
186 | static void addLink(const QString &linkTarget,
|
---|
187 | const QStringRef &nestedStuff,
|
---|
188 | QString *res)
|
---|
189 | {
|
---|
190 | if (!linkTarget.isEmpty()) {
|
---|
191 | *res += "<a href=\"";
|
---|
192 | *res += linkTarget;
|
---|
193 | *res += "\">";
|
---|
194 | *res += nestedStuff;
|
---|
195 | *res += "</a>";
|
---|
196 | }
|
---|
197 | else {
|
---|
198 | *res += nestedStuff;
|
---|
199 | }
|
---|
200 | }
|
---|
201 |
|
---|
202 |
|
---|
203 | HtmlGenerator::HtmlGenerator()
|
---|
204 | : helpProjectWriter(0), inLink(false), inContents(false),
|
---|
205 | inSectionHeading(false), inTableHeader(false), numTableRows(0),
|
---|
206 | threeColumnEnumValueTable(true), funcLeftParen("\\S(\\()"),
|
---|
207 | myTree(0), slow(false), obsoleteLinks(false)
|
---|
208 | {
|
---|
209 | }
|
---|
210 |
|
---|
211 | HtmlGenerator::~HtmlGenerator()
|
---|
212 | {
|
---|
213 | if (helpProjectWriter)
|
---|
214 | delete helpProjectWriter;
|
---|
215 | }
|
---|
216 |
|
---|
217 | void HtmlGenerator::initializeGenerator(const Config &config)
|
---|
218 | {
|
---|
219 | static const struct {
|
---|
220 | const char *key;
|
---|
221 | const char *left;
|
---|
222 | const char *right;
|
---|
223 | } defaults[] = {
|
---|
224 | { ATOM_FORMATTING_BOLD, "<b>", "</b>" },
|
---|
225 | { ATOM_FORMATTING_INDEX, "<!--", "-->" },
|
---|
226 | { ATOM_FORMATTING_ITALIC, "<i>", "</i>" },
|
---|
227 | { ATOM_FORMATTING_PARAMETER, "<i>", "</i>" },
|
---|
228 | { ATOM_FORMATTING_SUBSCRIPT, "<sub>", "</sub>" },
|
---|
229 | { ATOM_FORMATTING_SUPERSCRIPT, "<sup>", "</sup>" },
|
---|
230 | { ATOM_FORMATTING_TELETYPE, "<tt>", "</tt>" },
|
---|
231 | { ATOM_FORMATTING_UNDERLINE, "<u>", "</u>" },
|
---|
232 | { 0, 0, 0 }
|
---|
233 | };
|
---|
234 |
|
---|
235 | Generator::initializeGenerator(config);
|
---|
236 | obsoleteLinks = config.getBool(QLatin1String(CONFIG_OBSOLETELINKS));
|
---|
237 | setImageFileExtensions(QStringList() << "png" << "jpg" << "jpeg" << "gif");
|
---|
238 | int i = 0;
|
---|
239 | while (defaults[i].key) {
|
---|
240 | formattingLeftMap().insert(defaults[i].key, defaults[i].left);
|
---|
241 | formattingRightMap().insert(defaults[i].key, defaults[i].right);
|
---|
242 | i++;
|
---|
243 | }
|
---|
244 |
|
---|
245 | style = config.getString(HtmlGenerator::format() +
|
---|
246 | Config::dot +
|
---|
247 | HTMLGENERATOR_STYLE);
|
---|
248 | postHeader = config.getString(HtmlGenerator::format() +
|
---|
249 | Config::dot +
|
---|
250 | HTMLGENERATOR_POSTHEADER);
|
---|
251 | footer = config.getString(HtmlGenerator::format() +
|
---|
252 | Config::dot +
|
---|
253 | HTMLGENERATOR_FOOTER);
|
---|
254 | address = config.getString(HtmlGenerator::format() +
|
---|
255 | Config::dot +
|
---|
256 | HTMLGENERATOR_ADDRESS);
|
---|
257 | pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() +
|
---|
258 | Config::dot +
|
---|
259 | HTMLGENERATOR_GENERATEMACREFS);
|
---|
260 |
|
---|
261 | project = config.getString(CONFIG_PROJECT);
|
---|
262 |
|
---|
263 | projectDescription = config.getString(CONFIG_DESCRIPTION);
|
---|
264 | if (projectDescription.isEmpty() && !project.isEmpty())
|
---|
265 | projectDescription = project + " Reference Documentation";
|
---|
266 |
|
---|
267 | projectUrl = config.getString(CONFIG_URL);
|
---|
268 |
|
---|
269 | QSet<QString> editionNames = config.subVars(CONFIG_EDITION);
|
---|
270 | QSet<QString>::ConstIterator edition = editionNames.begin();
|
---|
271 | while (edition != editionNames.end()) {
|
---|
272 | QString editionName = *edition;
|
---|
273 | QStringList editionModules = config.getStringList(CONFIG_EDITION +
|
---|
274 | Config::dot +
|
---|
275 | editionName +
|
---|
276 | Config::dot +
|
---|
277 | "modules");
|
---|
278 | QStringList editionGroups = config.getStringList(CONFIG_EDITION +
|
---|
279 | Config::dot +
|
---|
280 | editionName +
|
---|
281 | Config::dot +
|
---|
282 | "groups");
|
---|
283 |
|
---|
284 | if (!editionModules.isEmpty())
|
---|
285 | editionModuleMap[editionName] = editionModules;
|
---|
286 | if (!editionGroups.isEmpty())
|
---|
287 | editionGroupMap[editionName] = editionGroups;
|
---|
288 |
|
---|
289 | ++edition;
|
---|
290 | }
|
---|
291 |
|
---|
292 | slow = config.getBool(CONFIG_SLOW);
|
---|
293 |
|
---|
294 | stylesheets = config.getStringList(HtmlGenerator::format() +
|
---|
295 | Config::dot +
|
---|
296 | HTMLGENERATOR_STYLESHEETS);
|
---|
297 | customHeadElements = config.getStringList(HtmlGenerator::format() +
|
---|
298 | Config::dot +
|
---|
299 | HTMLGENERATOR_CUSTOMHEADELEMENTS);
|
---|
300 | codeIndent = config.getInt(CONFIG_CODEINDENT);
|
---|
301 |
|
---|
302 | helpProjectWriter = new HelpProjectWriter(config,
|
---|
303 | project.toLower() +
|
---|
304 | ".qhp");
|
---|
305 | }
|
---|
306 |
|
---|
307 | void HtmlGenerator::terminateGenerator()
|
---|
308 | {
|
---|
309 | Generator::terminateGenerator();
|
---|
310 | }
|
---|
311 |
|
---|
312 | QString HtmlGenerator::format()
|
---|
313 | {
|
---|
314 | return "HTML";
|
---|
315 | }
|
---|
316 |
|
---|
317 | /*!
|
---|
318 | This is where the html files and dcf files are written.
|
---|
319 | \note The html file generation is done in the base class,
|
---|
320 | PageGenerator::generateTree().
|
---|
321 | */
|
---|
322 | void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
|
---|
323 | {
|
---|
324 | // Copy the stylesheets from the directory containing the qdocconf file.
|
---|
325 | // ### This should be changed to use a special directory in doc/src.
|
---|
326 | QStringList::ConstIterator styleIter = stylesheets.begin();
|
---|
327 | QDir configPath = QDir::current();
|
---|
328 | while (styleIter != stylesheets.end()) {
|
---|
329 | QString filePath = configPath.absoluteFilePath(*styleIter);
|
---|
330 | Config::copyFile(Location(), filePath, filePath, outputDir());
|
---|
331 | ++styleIter;
|
---|
332 | }
|
---|
333 |
|
---|
334 | myTree = tree;
|
---|
335 | nonCompatClasses.clear();
|
---|
336 | mainClasses.clear();
|
---|
337 | compatClasses.clear();
|
---|
338 | obsoleteClasses.clear();
|
---|
339 | moduleClassMap.clear();
|
---|
340 | moduleNamespaceMap.clear();
|
---|
341 | funcIndex.clear();
|
---|
342 | legaleseTexts.clear();
|
---|
343 | serviceClasses.clear();
|
---|
344 | findAllClasses(tree->root());
|
---|
345 | findAllFunctions(tree->root());
|
---|
346 | findAllLegaleseTexts(tree->root());
|
---|
347 | findAllNamespaces(tree->root());
|
---|
348 | #ifdef ZZZ_QDOC_QML
|
---|
349 | findAllQmlClasses(tree->root());
|
---|
350 | #endif
|
---|
351 | findAllSince(tree->root());
|
---|
352 |
|
---|
353 | PageGenerator::generateTree(tree, marker);
|
---|
354 |
|
---|
355 | dcfClassesRoot.ref = "classes.html";
|
---|
356 | dcfClassesRoot.title = "Classes";
|
---|
357 | qSort(dcfClassesRoot.subsections);
|
---|
358 |
|
---|
359 | dcfOverviewsRoot.ref = "overviews.html";
|
---|
360 | dcfOverviewsRoot.title = "Overviews";
|
---|
361 | qSort(dcfOverviewsRoot.subsections);
|
---|
362 |
|
---|
363 | dcfExamplesRoot.ref = "examples.html";
|
---|
364 | dcfExamplesRoot.title = "Tutorial & Examples";
|
---|
365 | qSort(dcfExamplesRoot.subsections);
|
---|
366 |
|
---|
367 | DcfSection qtRoot;
|
---|
368 | appendDcfSubSection(&qtRoot, dcfClassesRoot);
|
---|
369 | appendDcfSubSection(&qtRoot, dcfOverviewsRoot);
|
---|
370 | appendDcfSubSection(&qtRoot, dcfExamplesRoot);
|
---|
371 |
|
---|
372 | generateDcf(project.toLower().simplified().replace(" ", "-"),
|
---|
373 | "index.html",
|
---|
374 | projectDescription, qtRoot);
|
---|
375 | generateDcf("designer",
|
---|
376 | "designer-manual.html",
|
---|
377 | "Qt Designer Manual",
|
---|
378 | dcfDesignerRoot);
|
---|
379 | generateDcf("linguist",
|
---|
380 | "linguist-manual.html",
|
---|
381 | "Qt Linguist Manual",
|
---|
382 | dcfLinguistRoot);
|
---|
383 | generateDcf("assistant",
|
---|
384 | "assistant-manual.html",
|
---|
385 | "Qt Assistant Manual",
|
---|
386 | dcfAssistantRoot);
|
---|
387 | generateDcf("qmake",
|
---|
388 | "qmake-manual.html",
|
---|
389 | "qmake Manual",
|
---|
390 | dcfQmakeRoot);
|
---|
391 |
|
---|
392 | generateIndex(project.toLower().simplified().replace(" ", "-"),
|
---|
393 | projectUrl,
|
---|
394 | projectDescription);
|
---|
395 |
|
---|
396 | helpProjectWriter->generate(myTree);
|
---|
397 | }
|
---|
398 |
|
---|
399 | void HtmlGenerator::startText(const Node * /* relative */,
|
---|
400 | CodeMarker * /* marker */)
|
---|
401 | {
|
---|
402 | inLink = false;
|
---|
403 | inContents = false;
|
---|
404 | inSectionHeading = false;
|
---|
405 | inTableHeader = false;
|
---|
406 | numTableRows = 0;
|
---|
407 | threeColumnEnumValueTable = true;
|
---|
408 | link.clear();
|
---|
409 | sectionNumber.clear();
|
---|
410 | }
|
---|
411 |
|
---|
412 | int HtmlGenerator::generateAtom(const Atom *atom,
|
---|
413 | const Node *relative,
|
---|
414 | CodeMarker *marker)
|
---|
415 | {
|
---|
416 | int skipAhead = 0;
|
---|
417 | static bool in_para = false;
|
---|
418 |
|
---|
419 | switch (atom->type()) {
|
---|
420 | case Atom::AbstractLeft:
|
---|
421 | break;
|
---|
422 | case Atom::AbstractRight:
|
---|
423 | break;
|
---|
424 | case Atom::AutoLink:
|
---|
425 | if (!inLink && !inContents && !inSectionHeading) {
|
---|
426 | const Node *node = 0;
|
---|
427 | QString link = getLink(atom, relative, marker, &node);
|
---|
428 | if (!link.isEmpty()) {
|
---|
429 | beginLink(link, node, relative, marker);
|
---|
430 | generateLink(atom, relative, marker);
|
---|
431 | endLink();
|
---|
432 | }
|
---|
433 | else {
|
---|
434 | out() << protect(atom->string());
|
---|
435 | }
|
---|
436 | }
|
---|
437 | else {
|
---|
438 | out() << protect(atom->string());
|
---|
439 | }
|
---|
440 | break;
|
---|
441 | case Atom::BaseName:
|
---|
442 | break;
|
---|
443 | case Atom::BriefLeft:
|
---|
444 | if (relative->type() == Node::Fake) {
|
---|
445 | skipAhead = skipAtoms(atom, Atom::BriefRight);
|
---|
446 | break;
|
---|
447 | }
|
---|
448 |
|
---|
449 | out() << "<p>";
|
---|
450 | if (relative->type() == Node::Property ||
|
---|
451 | relative->type() == Node::Variable) {
|
---|
452 | QString str;
|
---|
453 | atom = atom->next();
|
---|
454 | while (atom != 0 && atom->type() != Atom::BriefRight) {
|
---|
455 | if (atom->type() == Atom::String ||
|
---|
456 | atom->type() == Atom::AutoLink)
|
---|
457 | str += atom->string();
|
---|
458 | skipAhead++;
|
---|
459 | atom = atom->next();
|
---|
460 | }
|
---|
461 | str[0] = str[0].toLower();
|
---|
462 | if (str.right(1) == ".")
|
---|
463 | str.truncate(str.length() - 1);
|
---|
464 | out() << "This ";
|
---|
465 | if (relative->type() == Node::Property)
|
---|
466 | out() << "property";
|
---|
467 | else
|
---|
468 | out() << "variable";
|
---|
469 | QStringList words = str.split(" ");
|
---|
470 | if (!(words.first() == "contains" || words.first() == "specifies"
|
---|
471 | || words.first() == "describes" || words.first() == "defines"
|
---|
472 | || words.first() == "holds" || words.first() == "determines"))
|
---|
473 | out() << " holds ";
|
---|
474 | else
|
---|
475 | out() << " ";
|
---|
476 | out() << str << ".";
|
---|
477 | }
|
---|
478 | break;
|
---|
479 | case Atom::BriefRight:
|
---|
480 | if (relative->type() != Node::Fake)
|
---|
481 | out() << "</p>\n";
|
---|
482 | break;
|
---|
483 | case Atom::C:
|
---|
484 | out() << formattingLeftMap()[ATOM_FORMATTING_TELETYPE];
|
---|
485 | if (inLink) {
|
---|
486 | out() << protect(plainCode(atom->string()));
|
---|
487 | }
|
---|
488 | else {
|
---|
489 | out() << highlightedCode(atom->string(), marker, relative);
|
---|
490 | }
|
---|
491 | out() << formattingRightMap()[ATOM_FORMATTING_TELETYPE];
|
---|
492 | break;
|
---|
493 | case Atom::Code:
|
---|
494 | out() << "<pre>"
|
---|
495 | << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
|
---|
496 | marker,relative))
|
---|
497 | << "</pre>\n";
|
---|
498 | break;
|
---|
499 | #ifdef QDOC_QML
|
---|
500 | case Atom::Qml:
|
---|
501 | out() << "<pre>"
|
---|
502 | << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
|
---|
503 | marker,relative))
|
---|
504 | << "</pre>\n";
|
---|
505 | break;
|
---|
506 | #endif
|
---|
507 | case Atom::CodeNew:
|
---|
508 | out() << "<p>you can rewrite it as</p>\n"
|
---|
509 | << "<pre>"
|
---|
510 | << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
|
---|
511 | marker,relative))
|
---|
512 | << "</pre>\n";
|
---|
513 | break;
|
---|
514 | case Atom::CodeOld:
|
---|
515 | out() << "<p>For example, if you have code like</p>\n";
|
---|
516 | // fallthrough
|
---|
517 | case Atom::CodeBad:
|
---|
518 | out() << "<pre><font color=\"#404040\">"
|
---|
519 | << trimmedTrailing(protect(plainCode(indent(codeIndent,atom->string()))))
|
---|
520 | << "</font></pre>\n";
|
---|
521 | break;
|
---|
522 | case Atom::FootnoteLeft:
|
---|
523 | // ### For now
|
---|
524 | if (in_para) {
|
---|
525 | out() << "</p>\n";
|
---|
526 | in_para = false;
|
---|
527 | }
|
---|
528 | out() << "<!-- ";
|
---|
529 | break;
|
---|
530 | case Atom::FootnoteRight:
|
---|
531 | // ### For now
|
---|
532 | out() << "-->";
|
---|
533 | break;
|
---|
534 | case Atom::FormatElse:
|
---|
535 | case Atom::FormatEndif:
|
---|
536 | case Atom::FormatIf:
|
---|
537 | break;
|
---|
538 | case Atom::FormattingLeft:
|
---|
539 | out() << formattingLeftMap()[atom->string()];
|
---|
540 | if (atom->string() == ATOM_FORMATTING_PARAMETER) {
|
---|
541 | if (atom->next() != 0 && atom->next()->type() == Atom::String) {
|
---|
542 | QRegExp subscriptRegExp("([a-z]+)_([0-9n])");
|
---|
543 | if (subscriptRegExp.exactMatch(atom->next()->string())) {
|
---|
544 | out() << subscriptRegExp.cap(1) << "<sub>"
|
---|
545 | << subscriptRegExp.cap(2) << "</sub>";
|
---|
546 | skipAhead = 1;
|
---|
547 | }
|
---|
548 | }
|
---|
549 | }
|
---|
550 | break;
|
---|
551 | case Atom::FormattingRight:
|
---|
552 | if (atom->string() == ATOM_FORMATTING_LINK) {
|
---|
553 | endLink();
|
---|
554 | }
|
---|
555 | else {
|
---|
556 | out() << formattingRightMap()[atom->string()];
|
---|
557 | }
|
---|
558 | break;
|
---|
559 | case Atom::AnnotatedList:
|
---|
560 | {
|
---|
561 | QList<Node*> values = myTree->groups().values(atom->string());
|
---|
562 | NodeMap nodeMap;
|
---|
563 | for (int i = 0; i < values.size(); ++i) {
|
---|
564 | const Node* n = values.at(i);
|
---|
565 | if ((n->status() != Node::Internal) && (n->access() != Node::Private)) {
|
---|
566 | nodeMap.insert(n->nameForLists(),n);
|
---|
567 | }
|
---|
568 | }
|
---|
569 | generateAnnotatedList(relative, marker, nodeMap);
|
---|
570 | }
|
---|
571 | break;
|
---|
572 | case Atom::GeneratedList:
|
---|
573 | if (atom->string() == "annotatedclasses") {
|
---|
574 | generateAnnotatedList(relative, marker, nonCompatClasses);
|
---|
575 | }
|
---|
576 | else if (atom->string() == "classes") {
|
---|
577 | generateCompactList(relative, marker, nonCompatClasses);
|
---|
578 | }
|
---|
579 | else if (atom->string().contains("classesbymodule")) {
|
---|
580 | QString arg = atom->string().trimmed();
|
---|
581 | QString moduleName = atom->string().mid(atom->string().indexOf(
|
---|
582 | "classesbymodule") + 15).trimmed();
|
---|
583 | if (moduleClassMap.contains(moduleName))
|
---|
584 | generateAnnotatedList(relative, marker, moduleClassMap[moduleName]);
|
---|
585 | }
|
---|
586 | else if (atom->string().contains("classesbyedition")) {
|
---|
587 |
|
---|
588 | QString arg = atom->string().trimmed();
|
---|
589 | QString editionName = atom->string().mid(atom->string().indexOf(
|
---|
590 | "classesbyedition") + 16).trimmed();
|
---|
591 |
|
---|
592 | if (editionModuleMap.contains(editionName)) {
|
---|
593 |
|
---|
594 | // Add all classes in the modules listed for that edition.
|
---|
595 | NodeMap editionClasses;
|
---|
596 | foreach (const QString &moduleName, editionModuleMap[editionName]) {
|
---|
597 | if (moduleClassMap.contains(moduleName))
|
---|
598 | editionClasses.unite(moduleClassMap[moduleName]);
|
---|
599 | }
|
---|
600 |
|
---|
601 | // Add additional groups and remove groups of classes that
|
---|
602 | // should be excluded from the edition.
|
---|
603 |
|
---|
604 | QMultiMap <QString, Node *> groups = myTree->groups();
|
---|
605 | foreach (const QString &groupName, editionGroupMap[editionName]) {
|
---|
606 | QList<Node *> groupClasses;
|
---|
607 | if (groupName.startsWith("-")) {
|
---|
608 | groupClasses = groups.values(groupName.mid(1));
|
---|
609 | foreach (const Node *node, groupClasses)
|
---|
610 | editionClasses.remove(node->name());
|
---|
611 | }
|
---|
612 | else {
|
---|
613 | groupClasses = groups.values(groupName);
|
---|
614 | foreach (const Node *node, groupClasses)
|
---|
615 | editionClasses.insert(node->name(), node);
|
---|
616 | }
|
---|
617 | }
|
---|
618 | generateAnnotatedList(relative, marker, editionClasses);
|
---|
619 | }
|
---|
620 | }
|
---|
621 | else if (atom->string() == "classhierarchy") {
|
---|
622 | generateClassHierarchy(relative, marker, nonCompatClasses);
|
---|
623 | }
|
---|
624 | else if (atom->string() == "compatclasses") {
|
---|
625 | generateCompactList(relative, marker, compatClasses);
|
---|
626 | }
|
---|
627 | else if (atom->string() == "obsoleteclasses") {
|
---|
628 | generateCompactList(relative, marker, obsoleteClasses);
|
---|
629 | }
|
---|
630 | else if (atom->string() == "functionindex") {
|
---|
631 | generateFunctionIndex(relative, marker);
|
---|
632 | }
|
---|
633 | else if (atom->string() == "legalese") {
|
---|
634 | generateLegaleseList(relative, marker);
|
---|
635 | }
|
---|
636 | else if (atom->string() == "mainclasses") {
|
---|
637 | generateCompactList(relative, marker, mainClasses);
|
---|
638 | }
|
---|
639 | else if (atom->string() == "services") {
|
---|
640 | generateCompactList(relative, marker, serviceClasses);
|
---|
641 | }
|
---|
642 | else if (atom->string() == "overviews") {
|
---|
643 | generateOverviewList(relative, marker);
|
---|
644 | }
|
---|
645 | else if (atom->string() == "namespaces") {
|
---|
646 | generateAnnotatedList(relative, marker, namespaceIndex);
|
---|
647 | }
|
---|
648 | else if (atom->string() == "related") {
|
---|
649 | const FakeNode *fake = static_cast<const FakeNode *>(relative);
|
---|
650 | if (fake && !fake->groupMembers().isEmpty()) {
|
---|
651 | NodeMap groupMembersMap;
|
---|
652 | foreach (const Node *node, fake->groupMembers()) {
|
---|
653 | if (node->type() == Node::Fake)
|
---|
654 | groupMembersMap[fullName(node, relative, marker)] = node;
|
---|
655 | }
|
---|
656 | generateAnnotatedList(fake, marker, groupMembersMap);
|
---|
657 | }
|
---|
658 | }
|
---|
659 | else if (atom->string() == "relatedinline") {
|
---|
660 | const FakeNode *fake = static_cast<const FakeNode *>(relative);
|
---|
661 | if (fake && !fake->groupMembers().isEmpty()) {
|
---|
662 | // Reverse the list into the original scan order.
|
---|
663 | // Should be sorted. But on what? It may not be a
|
---|
664 | // regular class or page definition.
|
---|
665 | QList<const Node *> list;
|
---|
666 | foreach (const Node *node, fake->groupMembers())
|
---|
667 | list.prepend(node);
|
---|
668 | foreach (const Node *node, list)
|
---|
669 | generateBody(node, marker);
|
---|
670 | }
|
---|
671 | }
|
---|
672 | break;
|
---|
673 | case Atom::SinceList:
|
---|
674 | {
|
---|
675 | NewSinceMaps::const_iterator nsmap;
|
---|
676 | nsmap = newSinceMaps.find(atom->string());
|
---|
677 | NewClassMaps::const_iterator ncmap;
|
---|
678 | ncmap = newClassMaps.find(atom->string());
|
---|
679 | if ((nsmap != newSinceMaps.constEnd()) && !nsmap.value().isEmpty()) {
|
---|
680 | QList<Section> sections;
|
---|
681 | QList<Section>::ConstIterator s;
|
---|
682 | for (int i=0; i<LastSinceType; ++i)
|
---|
683 | sections.append(Section(sinceTitle(i),QString(),QString()));
|
---|
684 |
|
---|
685 | NodeMultiMap::const_iterator n = nsmap.value().constBegin();
|
---|
686 | while (n != nsmap.value().constEnd()) {
|
---|
687 | const Node* node = n.value();
|
---|
688 | switch (node->type()) {
|
---|
689 | case Node::Namespace:
|
---|
690 | sections[Namespace].appendMember((Node*)node);
|
---|
691 | break;
|
---|
692 | case Node::Class:
|
---|
693 | sections[Class].appendMember((Node*)node);
|
---|
694 | break;
|
---|
695 | case Node::Enum:
|
---|
696 | sections[Enum].appendMember((Node*)node);
|
---|
697 | break;
|
---|
698 | case Node::Typedef:
|
---|
699 | sections[Typedef].appendMember((Node*)node);
|
---|
700 | break;
|
---|
701 | case Node::Function: {
|
---|
702 | const FunctionNode* fn = static_cast<const FunctionNode*>(node);
|
---|
703 | if (fn->isMacro())
|
---|
704 | sections[Macro].appendMember((Node*)node);
|
---|
705 | else {
|
---|
706 | Node* p = fn->parent();
|
---|
707 | if (p) {
|
---|
708 | if (p->type() == Node::Class)
|
---|
709 | sections[MemberFunction].appendMember((Node*)node);
|
---|
710 | else if (p->type() == Node::Namespace) {
|
---|
711 | if (p->name().isEmpty())
|
---|
712 | sections[GlobalFunction].appendMember((Node*)node);
|
---|
713 | else
|
---|
714 | sections[NamespaceFunction].appendMember((Node*)node);
|
---|
715 | }
|
---|
716 | else
|
---|
717 | sections[GlobalFunction].appendMember((Node*)node);
|
---|
718 | }
|
---|
719 | else
|
---|
720 | sections[GlobalFunction].appendMember((Node*)node);
|
---|
721 | }
|
---|
722 | break;
|
---|
723 | }
|
---|
724 | case Node::Property:
|
---|
725 | sections[Property].appendMember((Node*)node);
|
---|
726 | break;
|
---|
727 | case Node::Variable:
|
---|
728 | sections[Variable].appendMember((Node*)node);
|
---|
729 | break;
|
---|
730 | case Node::QmlProperty:
|
---|
731 | sections[QmlProperty].appendMember((Node*)node);
|
---|
732 | break;
|
---|
733 | case Node::QmlSignal:
|
---|
734 | sections[QmlSignal].appendMember((Node*)node);
|
---|
735 | break;
|
---|
736 | case Node::QmlMethod:
|
---|
737 | sections[QmlMethod].appendMember((Node*)node);
|
---|
738 | break;
|
---|
739 | default:
|
---|
740 | break;
|
---|
741 | }
|
---|
742 | ++n;
|
---|
743 | }
|
---|
744 |
|
---|
745 | /*
|
---|
746 | First generate the table of contents.
|
---|
747 | */
|
---|
748 | out() << "<ul>\n";
|
---|
749 | s = sections.constBegin();
|
---|
750 | while (s != sections.constEnd()) {
|
---|
751 | if (!(*s).members.isEmpty()) {
|
---|
752 |
|
---|
753 | out() << "<li>"
|
---|
754 | << "<a href=\"#"
|
---|
755 | << Doc::canonicalTitle((*s).name)
|
---|
756 | << "\">"
|
---|
757 | << (*s).name
|
---|
758 | << "</a></li>\n";
|
---|
759 | }
|
---|
760 | ++s;
|
---|
761 | }
|
---|
762 | out() << "</ul>\n";
|
---|
763 |
|
---|
764 | int idx = 0;
|
---|
765 | s = sections.constBegin();
|
---|
766 | while (s != sections.constEnd()) {
|
---|
767 | if (!(*s).members.isEmpty()) {
|
---|
768 | out() << "<a name=\""
|
---|
769 | << Doc::canonicalTitle((*s).name)
|
---|
770 | << "\"></a>\n";
|
---|
771 | out() << "<h3>" << protect((*s).name) << "</h3>\n";
|
---|
772 | if (idx == Class)
|
---|
773 | generateCompactList(0, marker, ncmap.value(), QString("Q"));
|
---|
774 | else if (idx == MemberFunction) {
|
---|
775 | ParentMaps parentmaps;
|
---|
776 | ParentMaps::iterator pmap;
|
---|
777 | NodeList::const_iterator i = s->members.constBegin();
|
---|
778 | while (i != s->members.constEnd()) {
|
---|
779 | Node* p = (*i)->parent();
|
---|
780 | pmap = parentmaps.find(p);
|
---|
781 | if (pmap == parentmaps.end())
|
---|
782 | pmap = parentmaps.insert(p,NodeMultiMap());
|
---|
783 | pmap->insert((*i)->name(),(*i));
|
---|
784 | ++i;
|
---|
785 | }
|
---|
786 | pmap = parentmaps.begin();
|
---|
787 | while (pmap != parentmaps.end()) {
|
---|
788 | NodeList nlist = pmap->values();
|
---|
789 | out() << "<p>Class ";
|
---|
790 |
|
---|
791 | out() << "<a href=\""
|
---|
792 | << linkForNode(pmap.key(), 0)
|
---|
793 | << "\">";
|
---|
794 | QStringList pieces = fullName(pmap.key(), 0, marker).split("::");
|
---|
795 | out() << protect(pieces.last());
|
---|
796 | out() << "</a>" << ":</p>\n";
|
---|
797 |
|
---|
798 | generateSection(nlist, 0, marker, CodeMarker::Summary);
|
---|
799 | out() << "<br />";
|
---|
800 | ++pmap;
|
---|
801 | }
|
---|
802 | }
|
---|
803 | else
|
---|
804 | generateSection(s->members, 0, marker, CodeMarker::Summary);
|
---|
805 | }
|
---|
806 | ++idx;
|
---|
807 | ++s;
|
---|
808 | }
|
---|
809 | }
|
---|
810 | }
|
---|
811 | break;
|
---|
812 | case Atom::Image:
|
---|
813 | case Atom::InlineImage:
|
---|
814 | {
|
---|
815 | QString fileName = imageFileName(relative, atom->string());
|
---|
816 | QString text;
|
---|
817 | if (atom->next() != 0)
|
---|
818 | text = atom->next()->string();
|
---|
819 | if (atom->type() == Atom::Image)
|
---|
820 | out() << "<p align=\"center\">";
|
---|
821 | if (fileName.isEmpty()) {
|
---|
822 | out() << "<font color=\"red\">[Missing image "
|
---|
823 | << protect(atom->string()) << "]</font>";
|
---|
824 | }
|
---|
825 | else {
|
---|
826 | out() << "<img src=\"" << protect(fileName) << "\"";
|
---|
827 | if (!text.isEmpty())
|
---|
828 | out() << " alt=\"" << protect(text) << "\"";
|
---|
829 | out() << " />";
|
---|
830 | helpProjectWriter->addExtraFile(fileName);
|
---|
831 | }
|
---|
832 | if (atom->type() == Atom::Image)
|
---|
833 | out() << "</p>";
|
---|
834 | }
|
---|
835 | break;
|
---|
836 | case Atom::ImageText:
|
---|
837 | break;
|
---|
838 | case Atom::LegaleseLeft:
|
---|
839 | out() << "<div style=\"padding: 0.5em; background: #e0e0e0; color: black\">";
|
---|
840 | break;
|
---|
841 | case Atom::LegaleseRight:
|
---|
842 | out() << "</div>";
|
---|
843 | break;
|
---|
844 | case Atom::LineBreak:
|
---|
845 | out() << "<br />";
|
---|
846 | break;
|
---|
847 | case Atom::Link:
|
---|
848 | {
|
---|
849 | const Node *node = 0;
|
---|
850 | QString myLink = getLink(atom, relative, marker, &node);
|
---|
851 | if (myLink.isEmpty()) {
|
---|
852 | relative->doc().location().warning(tr("Cannot link to '%1' in %2")
|
---|
853 | .arg(atom->string())
|
---|
854 | .arg(marker->plainFullName(relative)));
|
---|
855 | }
|
---|
856 | beginLink(myLink, node, relative, marker);
|
---|
857 | skipAhead = 1;
|
---|
858 | }
|
---|
859 | break;
|
---|
860 | case Atom::LinkNode:
|
---|
861 | {
|
---|
862 | const Node *node = CodeMarker::nodeForString(atom->string());
|
---|
863 | beginLink(linkForNode(node, relative), node, relative, marker);
|
---|
864 | skipAhead = 1;
|
---|
865 | }
|
---|
866 | break;
|
---|
867 | case Atom::ListLeft:
|
---|
868 | if (in_para) {
|
---|
869 | out() << "</p>\n";
|
---|
870 | in_para = false;
|
---|
871 | }
|
---|
872 | if (atom->string() == ATOM_LIST_BULLET) {
|
---|
873 | out() << "<ul>\n";
|
---|
874 | }
|
---|
875 | else if (atom->string() == ATOM_LIST_TAG) {
|
---|
876 | out() << "<dl>\n";
|
---|
877 | }
|
---|
878 | else if (atom->string() == ATOM_LIST_VALUE) {
|
---|
879 | threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
|
---|
880 | if (threeColumnEnumValueTable) {
|
---|
881 | out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
|
---|
882 | << "cellspacing=\"1\" width=\"100%\">\n"
|
---|
883 | << "<tr><th width=\"25%\">Constant</th>"
|
---|
884 | << "<th width=\"15%\">Value</th>"
|
---|
885 | << "<th width=\"60%\">Description</th></tr>\n";
|
---|
886 | }
|
---|
887 | else {
|
---|
888 | out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
|
---|
889 | << "cellspacing=\"1\" width=\"40%\">\n"
|
---|
890 | << "<tr><th width=\"60%\">Constant</th><th "
|
---|
891 | << "width=\"40%\">Value</th></tr>\n";
|
---|
892 | }
|
---|
893 | }
|
---|
894 | else {
|
---|
895 | out() << "<ol type=";
|
---|
896 | if (atom->string() == ATOM_LIST_UPPERALPHA) {
|
---|
897 | out() << "\"A\"";
|
---|
898 | }
|
---|
899 | else if (atom->string() == ATOM_LIST_LOWERALPHA) {
|
---|
900 | out() << "\"a\"";
|
---|
901 | }
|
---|
902 | else if (atom->string() == ATOM_LIST_UPPERROMAN) {
|
---|
903 | out() << "\"I\"";
|
---|
904 | }
|
---|
905 | else if (atom->string() == ATOM_LIST_LOWERROMAN) {
|
---|
906 | out() << "\"i\"";
|
---|
907 | }
|
---|
908 | else { // (atom->string() == ATOM_LIST_NUMERIC)
|
---|
909 | out() << "\"1\"";
|
---|
910 | }
|
---|
911 | if (atom->next() != 0 && atom->next()->string().toInt() != 1)
|
---|
912 | out() << " start=\"" << atom->next()->string() << "\"";
|
---|
913 | out() << ">\n";
|
---|
914 | }
|
---|
915 | break;
|
---|
916 | case Atom::ListItemNumber:
|
---|
917 | break;
|
---|
918 | case Atom::ListTagLeft:
|
---|
919 | if (atom->string() == ATOM_LIST_TAG) {
|
---|
920 | out() << "<dt>";
|
---|
921 | }
|
---|
922 | else { // (atom->string() == ATOM_LIST_VALUE)
|
---|
923 | // ### Trenton
|
---|
924 |
|
---|
925 | out() << "<tr><td valign=\"top\"><tt>"
|
---|
926 | << protect(plainCode(marker->markedUpEnumValue(atom->next()->string(),
|
---|
927 | relative)))
|
---|
928 | << "</tt></td><td align=\"center\" valign=\"top\">";
|
---|
929 |
|
---|
930 | QString itemValue;
|
---|
931 | if (relative->type() == Node::Enum) {
|
---|
932 | const EnumNode *enume = static_cast<const EnumNode *>(relative);
|
---|
933 | itemValue = enume->itemValue(atom->next()->string());
|
---|
934 | }
|
---|
935 |
|
---|
936 | if (itemValue.isEmpty())
|
---|
937 | out() << "?";
|
---|
938 | else
|
---|
939 | out() << "<tt>" << protect(itemValue) << "</tt>";
|
---|
940 |
|
---|
941 | skipAhead = 1;
|
---|
942 | }
|
---|
943 | break;
|
---|
944 | case Atom::ListTagRight:
|
---|
945 | if (atom->string() == ATOM_LIST_TAG)
|
---|
946 | out() << "</dt>\n";
|
---|
947 | break;
|
---|
948 | case Atom::ListItemLeft:
|
---|
949 | if (atom->string() == ATOM_LIST_TAG) {
|
---|
950 | out() << "<dd>";
|
---|
951 | }
|
---|
952 | else if (atom->string() == ATOM_LIST_VALUE) {
|
---|
953 | if (threeColumnEnumValueTable) {
|
---|
954 | out() << "</td><td valign=\"top\">";
|
---|
955 | if (matchAhead(atom, Atom::ListItemRight))
|
---|
956 | out() << " ";
|
---|
957 | }
|
---|
958 | }
|
---|
959 | else {
|
---|
960 | out() << "<li>";
|
---|
961 | }
|
---|
962 | if (matchAhead(atom, Atom::ParaLeft))
|
---|
963 | skipAhead = 1;
|
---|
964 | break;
|
---|
965 | case Atom::ListItemRight:
|
---|
966 | if (atom->string() == ATOM_LIST_TAG) {
|
---|
967 | out() << "</dd>\n";
|
---|
968 | }
|
---|
969 | else if (atom->string() == ATOM_LIST_VALUE) {
|
---|
970 | out() << "</td></tr>\n";
|
---|
971 | }
|
---|
972 | else {
|
---|
973 | out() << "</li>\n";
|
---|
974 | }
|
---|
975 | break;
|
---|
976 | case Atom::ListRight:
|
---|
977 | if (atom->string() == ATOM_LIST_BULLET) {
|
---|
978 | out() << "</ul>\n";
|
---|
979 | }
|
---|
980 | else if (atom->string() == ATOM_LIST_TAG) {
|
---|
981 | out() << "</dl>\n";
|
---|
982 | }
|
---|
983 | else if (atom->string() == ATOM_LIST_VALUE) {
|
---|
984 | out() << "</table></p>\n";
|
---|
985 | }
|
---|
986 | else {
|
---|
987 | out() << "</ol>\n";
|
---|
988 | }
|
---|
989 | break;
|
---|
990 | case Atom::Nop:
|
---|
991 | break;
|
---|
992 | case Atom::ParaLeft:
|
---|
993 | out() << "<p>";
|
---|
994 | in_para = true;
|
---|
995 | break;
|
---|
996 | case Atom::ParaRight:
|
---|
997 | endLink();
|
---|
998 | if (in_para) {
|
---|
999 | out() << "</p>\n";
|
---|
1000 | in_para = false;
|
---|
1001 | }
|
---|
1002 | //if (!matchAhead(atom, Atom::ListItemRight) && !matchAhead(atom, Atom::TableItemRight))
|
---|
1003 | // out() << "</p>\n";
|
---|
1004 | break;
|
---|
1005 | case Atom::QuotationLeft:
|
---|
1006 | out() << "<blockquote>";
|
---|
1007 | break;
|
---|
1008 | case Atom::QuotationRight:
|
---|
1009 | out() << "</blockquote>\n";
|
---|
1010 | break;
|
---|
1011 | case Atom::RawString:
|
---|
1012 | out() << atom->string();
|
---|
1013 | break;
|
---|
1014 | case Atom::SectionLeft:
|
---|
1015 | #if 0
|
---|
1016 | {
|
---|
1017 | int nextLevel = atom->string().toInt();
|
---|
1018 | if (sectionNumber.size() < nextLevel) {
|
---|
1019 | do {
|
---|
1020 | sectionNumber.append("1");
|
---|
1021 | } while (sectionNumber.size() < nextLevel);
|
---|
1022 | }
|
---|
1023 | else {
|
---|
1024 | while (sectionNumber.size() > nextLevel) {
|
---|
1025 | sectionNumber.removeLast();
|
---|
1026 | }
|
---|
1027 | sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
|
---|
1028 | }
|
---|
1029 | out() << "<a name=\"sec-" << sectionNumber.join("-") << "\"></a>\n";
|
---|
1030 | }
|
---|
1031 | #else
|
---|
1032 | out() << "<a name=\"" << Doc::canonicalTitle(Text::sectionHeading(atom).toString())
|
---|
1033 | << "\"></a>\n";
|
---|
1034 | #endif
|
---|
1035 | break;
|
---|
1036 | case Atom::SectionRight:
|
---|
1037 | break;
|
---|
1038 | case Atom::SectionHeadingLeft:
|
---|
1039 | out() << "<h" + QString::number(atom->string().toInt() + hOffset(relative)) + ">";
|
---|
1040 | inSectionHeading = true;
|
---|
1041 | break;
|
---|
1042 | case Atom::SectionHeadingRight:
|
---|
1043 | out() << "</h" + QString::number(atom->string().toInt() + hOffset(relative)) + ">\n";
|
---|
1044 | inSectionHeading = false;
|
---|
1045 | break;
|
---|
1046 | case Atom::SidebarLeft:
|
---|
1047 | break;
|
---|
1048 | case Atom::SidebarRight:
|
---|
1049 | break;
|
---|
1050 | case Atom::String:
|
---|
1051 | if (inLink && !inContents && !inSectionHeading) {
|
---|
1052 | generateLink(atom, relative, marker);
|
---|
1053 | }
|
---|
1054 | else {
|
---|
1055 | out() << protect(atom->string());
|
---|
1056 | }
|
---|
1057 | break;
|
---|
1058 | case Atom::TableLeft:
|
---|
1059 | if (in_para) {
|
---|
1060 | out() << "</p>\n";
|
---|
1061 | in_para = false;
|
---|
1062 | }
|
---|
1063 | if (!atom->string().isEmpty()) {
|
---|
1064 | if (atom->string().contains("%"))
|
---|
1065 | out() << "<p><table class=\"generic\" width=\"" << atom->string() << "\" "
|
---|
1066 | << "align=\"center\" cellpadding=\"2\" "
|
---|
1067 | << "cellspacing=\"1\" border=\"0\">\n";
|
---|
1068 | else {
|
---|
1069 | out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
|
---|
1070 | << "cellspacing=\"1\" border=\"0\">\n";
|
---|
1071 | }
|
---|
1072 | }
|
---|
1073 | else {
|
---|
1074 | out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
|
---|
1075 | << "cellspacing=\"1\" border=\"0\">\n";
|
---|
1076 | }
|
---|
1077 | numTableRows = 0;
|
---|
1078 | break;
|
---|
1079 | case Atom::TableRight:
|
---|
1080 | out() << "</table></p>\n";
|
---|
1081 | break;
|
---|
1082 | case Atom::TableHeaderLeft:
|
---|
1083 | out() << "<thead><tr valign=\"top\" class=\"qt-style\">";
|
---|
1084 | inTableHeader = true;
|
---|
1085 | break;
|
---|
1086 | case Atom::TableHeaderRight:
|
---|
1087 | out() << "</tr>";
|
---|
1088 | if (matchAhead(atom, Atom::TableHeaderLeft)) {
|
---|
1089 | skipAhead = 1;
|
---|
1090 | out() << "\n<tr valign=\"top\" class=\"qt-style\">";
|
---|
1091 | }
|
---|
1092 | else {
|
---|
1093 | out() << "</thead>\n";
|
---|
1094 | inTableHeader = false;
|
---|
1095 | }
|
---|
1096 | break;
|
---|
1097 | case Atom::TableRowLeft:
|
---|
1098 | if (++numTableRows % 2 == 1)
|
---|
1099 | out() << "<tr valign=\"top\" class=\"odd\">";
|
---|
1100 | else
|
---|
1101 | out() << "<tr valign=\"top\" class=\"even\">";
|
---|
1102 | break;
|
---|
1103 | case Atom::TableRowRight:
|
---|
1104 | out() << "</tr>\n";
|
---|
1105 | break;
|
---|
1106 | case Atom::TableItemLeft:
|
---|
1107 | {
|
---|
1108 | if (inTableHeader)
|
---|
1109 | out() << "<th";
|
---|
1110 | else
|
---|
1111 | out() << "<td";
|
---|
1112 |
|
---|
1113 | QStringList spans = atom->string().split(",");
|
---|
1114 | if (spans.size() == 2) {
|
---|
1115 | if (spans.at(0) != "1")
|
---|
1116 | out() << " colspan=\"" << spans.at(0) << "\"";
|
---|
1117 | if (spans.at(1) != "1")
|
---|
1118 | out() << " rowspan=\"" << spans.at(1) << "\"";
|
---|
1119 | out() << ">";
|
---|
1120 | }
|
---|
1121 | if (matchAhead(atom, Atom::ParaLeft))
|
---|
1122 | skipAhead = 1;
|
---|
1123 | }
|
---|
1124 | break;
|
---|
1125 | case Atom::TableItemRight:
|
---|
1126 | if (inTableHeader)
|
---|
1127 | out() << "</th>";
|
---|
1128 | else
|
---|
1129 | out() << "</td>";
|
---|
1130 | if (matchAhead(atom, Atom::ParaLeft))
|
---|
1131 | skipAhead = 1;
|
---|
1132 | break;
|
---|
1133 | case Atom::TableOfContents:
|
---|
1134 | {
|
---|
1135 | int numColumns = 1;
|
---|
1136 | const Node *node = relative;
|
---|
1137 |
|
---|
1138 | Doc::SectioningUnit sectioningUnit = Doc::Section4;
|
---|
1139 | QStringList params = atom->string().split(",");
|
---|
1140 | QString columnText = params.at(0);
|
---|
1141 | QStringList pieces = columnText.split(" ", QString::SkipEmptyParts);
|
---|
1142 | if (pieces.size() >= 2) {
|
---|
1143 | columnText = pieces.at(0);
|
---|
1144 | pieces.pop_front();
|
---|
1145 | QString path = pieces.join(" ").trimmed();
|
---|
1146 | node = findNodeForTarget(path, relative, marker, atom);
|
---|
1147 | }
|
---|
1148 |
|
---|
1149 | if (params.size() == 2) {
|
---|
1150 | numColumns = qMax(columnText.toInt(), numColumns);
|
---|
1151 | sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt();
|
---|
1152 | }
|
---|
1153 |
|
---|
1154 | if (node)
|
---|
1155 | generateTableOfContents(node,
|
---|
1156 | marker,
|
---|
1157 | sectioningUnit,
|
---|
1158 | numColumns,
|
---|
1159 | relative);
|
---|
1160 | }
|
---|
1161 | break;
|
---|
1162 | case Atom::Target:
|
---|
1163 | out() << "<a name=\"" << Doc::canonicalTitle(atom->string()) << "\"></a>";
|
---|
1164 | break;
|
---|
1165 | case Atom::UnhandledFormat:
|
---|
1166 | out() << "<font color=\"red\"><b><Missing HTML></b></font>";
|
---|
1167 | break;
|
---|
1168 | case Atom::UnknownCommand:
|
---|
1169 | out() << "<font color=\"red\"><b><code>\\" << protect(atom->string())
|
---|
1170 | << "</code></b></font>";
|
---|
1171 | break;
|
---|
1172 | #ifdef QDOC_QML
|
---|
1173 | case Atom::QmlText:
|
---|
1174 | case Atom::EndQmlText:
|
---|
1175 | // don't do anything with these. They are just tags.
|
---|
1176 | break;
|
---|
1177 | #endif
|
---|
1178 | default:
|
---|
1179 | unknownAtom(atom);
|
---|
1180 | }
|
---|
1181 | return skipAhead;
|
---|
1182 | }
|
---|
1183 |
|
---|
1184 | void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
|
---|
1185 | CodeMarker *marker)
|
---|
1186 | {
|
---|
1187 | QList<Section> sections;
|
---|
1188 | QList<Section>::ConstIterator s;
|
---|
1189 |
|
---|
1190 | const ClassNode *classe = 0;
|
---|
1191 | const NamespaceNode *namespasse = 0;
|
---|
1192 |
|
---|
1193 | QString title;
|
---|
1194 | QString rawTitle;
|
---|
1195 | QString fullTitle;
|
---|
1196 | if (inner->type() == Node::Namespace) {
|
---|
1197 | namespasse = static_cast<const NamespaceNode *>(inner);
|
---|
1198 | rawTitle = marker->plainName(inner);
|
---|
1199 | fullTitle = marker->plainFullName(inner);
|
---|
1200 | title = rawTitle + " Namespace Reference";
|
---|
1201 | }
|
---|
1202 | else if (inner->type() == Node::Class) {
|
---|
1203 | classe = static_cast<const ClassNode *>(inner);
|
---|
1204 | rawTitle = marker->plainName(inner);
|
---|
1205 | fullTitle = marker->plainFullName(inner);
|
---|
1206 | title = rawTitle + " Class Reference";
|
---|
1207 | }
|
---|
1208 |
|
---|
1209 | DcfSection classSection;
|
---|
1210 | classSection.title = title;
|
---|
1211 | classSection.ref = linkForNode(inner, 0);
|
---|
1212 | classSection.keywords += qMakePair(inner->name(), classSection.ref);
|
---|
1213 |
|
---|
1214 | Text subtitleText;
|
---|
1215 | if (rawTitle != fullTitle)
|
---|
1216 | subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")"
|
---|
1217 | << Atom(Atom::LineBreak);
|
---|
1218 |
|
---|
1219 | QString fixedModule = inner->moduleName();
|
---|
1220 | if (fixedModule == "Qt3SupportLight")
|
---|
1221 | fixedModule = "Qt3Support";
|
---|
1222 | if (!fixedModule.isEmpty())
|
---|
1223 | subtitleText << "[" << Atom(Atom::AutoLink, fixedModule) << " module]";
|
---|
1224 |
|
---|
1225 | if (fixedModule.isEmpty()) {
|
---|
1226 | QMultiMap<QString, QString> publicGroups = myTree->publicGroups();
|
---|
1227 | QList<QString> groupNames = publicGroups.values(inner->name());
|
---|
1228 | if (!groupNames.isEmpty()) {
|
---|
1229 | qSort(groupNames.begin(), groupNames.end());
|
---|
1230 | subtitleText << "[";
|
---|
1231 | for (int j=0; j<groupNames.count(); j++) {
|
---|
1232 | subtitleText << Atom(Atom::AutoLink, groupNames[j]);
|
---|
1233 | if (j<groupNames.count()-1)
|
---|
1234 | subtitleText <<", ";
|
---|
1235 | }
|
---|
1236 | subtitleText << "]";
|
---|
1237 | }
|
---|
1238 | }
|
---|
1239 |
|
---|
1240 | generateHeader(title, inner, marker, true);
|
---|
1241 | generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
|
---|
1242 |
|
---|
1243 | #ifdef QDOC_QML
|
---|
1244 | if (classe && !classe->qmlElement().isEmpty()) {
|
---|
1245 | generateInstantiatedBy(classe,marker);
|
---|
1246 | }
|
---|
1247 | #endif
|
---|
1248 |
|
---|
1249 | generateBrief(inner, marker);
|
---|
1250 | generateIncludes(inner, marker);
|
---|
1251 | generateStatus(inner, marker);
|
---|
1252 | if (classe) {
|
---|
1253 | generateModuleWarning(classe, marker);
|
---|
1254 | generateInherits(classe, marker);
|
---|
1255 | generateInheritedBy(classe, marker);
|
---|
1256 | }
|
---|
1257 | generateThreadSafeness(inner, marker);
|
---|
1258 | generateSince(inner, marker);
|
---|
1259 |
|
---|
1260 | out() << "<ul>\n";
|
---|
1261 |
|
---|
1262 | QString membersLink = generateListOfAllMemberFile(inner, marker);
|
---|
1263 | if (!membersLink.isEmpty())
|
---|
1264 | out() << "<li><a href=\"" << membersLink << "\">"
|
---|
1265 | << "List of all members, including inherited members</a></li>\n";
|
---|
1266 |
|
---|
1267 | QString obsoleteLink = generateLowStatusMemberFile(inner,
|
---|
1268 | marker,
|
---|
1269 | CodeMarker::Obsolete);
|
---|
1270 | if (!obsoleteLink.isEmpty())
|
---|
1271 | out() << "<li><a href=\"" << obsoleteLink << "\">"
|
---|
1272 | << "Obsolete members</a></li>\n";
|
---|
1273 |
|
---|
1274 | QString compatLink = generateLowStatusMemberFile(inner,
|
---|
1275 | marker,
|
---|
1276 | CodeMarker::Compat);
|
---|
1277 | if (!compatLink.isEmpty())
|
---|
1278 | out() << "<li><a href=\"" << compatLink << "\">"
|
---|
1279 | << "Qt 3 support members</a></li>\n";
|
---|
1280 |
|
---|
1281 | out() << "</ul>\n";
|
---|
1282 |
|
---|
1283 | bool needOtherSection = false;
|
---|
1284 |
|
---|
1285 | sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
|
---|
1286 | s = sections.begin();
|
---|
1287 | while (s != sections.end()) {
|
---|
1288 | if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
|
---|
1289 | if (!s->inherited.isEmpty())
|
---|
1290 | needOtherSection = true;
|
---|
1291 | }
|
---|
1292 | else {
|
---|
1293 | if (!s->members.isEmpty()) {
|
---|
1294 | out() << "<hr />\n";
|
---|
1295 | out() << "<a name=\""
|
---|
1296 | << registerRef((*s).name.toLower())
|
---|
1297 | << "\"></a>\n";
|
---|
1298 | out() << "<h2>" << protect((*s).name) << "</h2>\n";
|
---|
1299 | generateSection(s->members, inner, marker, CodeMarker::Summary);
|
---|
1300 | }
|
---|
1301 | if (!s->reimpMembers.isEmpty()) {
|
---|
1302 | QString name = QString("Reimplemented ") + (*s).name;
|
---|
1303 | out() << "<hr />\n";
|
---|
1304 | out() << "<a name=\""
|
---|
1305 | << registerRef(name.toLower())
|
---|
1306 | << "\"></a>\n";
|
---|
1307 | out() << "<h2>" << protect(name) << "</h2>\n";
|
---|
1308 | generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
|
---|
1309 | }
|
---|
1310 |
|
---|
1311 | if (!s->inherited.isEmpty()) {
|
---|
1312 | out() << "<ul>\n";
|
---|
1313 | generateSectionInheritedList(*s, inner, marker, true);
|
---|
1314 | out() << "</ul>\n";
|
---|
1315 | }
|
---|
1316 | }
|
---|
1317 | ++s;
|
---|
1318 | }
|
---|
1319 |
|
---|
1320 | if (needOtherSection) {
|
---|
1321 | out() << "<h3>Additional Inherited Members</h3>\n"
|
---|
1322 | "<ul>\n";
|
---|
1323 |
|
---|
1324 | s = sections.begin();
|
---|
1325 | while (s != sections.end()) {
|
---|
1326 | if (s->members.isEmpty() && !s->inherited.isEmpty())
|
---|
1327 | generateSectionInheritedList(*s, inner, marker);
|
---|
1328 | ++s;
|
---|
1329 | }
|
---|
1330 | out() << "</ul>\n";
|
---|
1331 | }
|
---|
1332 |
|
---|
1333 | out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
|
---|
1334 |
|
---|
1335 | if (!inner->doc().isEmpty()) {
|
---|
1336 | out() << "<hr />\n"
|
---|
1337 | << "<h2>" << "Detailed Description" << "</h2>\n";
|
---|
1338 | generateBody(inner, marker);
|
---|
1339 | generateAlsoList(inner, marker);
|
---|
1340 | }
|
---|
1341 |
|
---|
1342 | sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
|
---|
1343 | s = sections.begin();
|
---|
1344 | while (s != sections.end()) {
|
---|
1345 | out() << "<hr />\n";
|
---|
1346 | out() << "<h2>" << protect((*s).name) << "</h2>\n";
|
---|
1347 |
|
---|
1348 | NodeList::ConstIterator m = (*s).members.begin();
|
---|
1349 | while (m != (*s).members.end()) {
|
---|
1350 | if ((*m)->access() != Node::Private) { // ### check necessary?
|
---|
1351 | if ((*m)->type() != Node::Class)
|
---|
1352 | generateDetailedMember(*m, inner, marker);
|
---|
1353 | else {
|
---|
1354 | out() << "<h3> class ";
|
---|
1355 | generateFullName(*m, inner, marker);
|
---|
1356 | out() << "</h3>";
|
---|
1357 | generateBrief(*m, marker, inner);
|
---|
1358 | }
|
---|
1359 |
|
---|
1360 | QStringList names;
|
---|
1361 | names << (*m)->name();
|
---|
1362 | if ((*m)->type() == Node::Function) {
|
---|
1363 | const FunctionNode *func = reinterpret_cast<const FunctionNode *>(*m);
|
---|
1364 | if (func->metaness() == FunctionNode::Ctor ||
|
---|
1365 | func->metaness() == FunctionNode::Dtor ||
|
---|
1366 | func->overloadNumber() != 1)
|
---|
1367 | names.clear();
|
---|
1368 | }
|
---|
1369 | else if ((*m)->type() == Node::Property) {
|
---|
1370 | const PropertyNode *prop = reinterpret_cast<const PropertyNode *>(*m);
|
---|
1371 | if (!prop->getters().isEmpty() &&
|
---|
1372 | !names.contains(prop->getters().first()->name()))
|
---|
1373 | names << prop->getters().first()->name();
|
---|
1374 | if (!prop->setters().isEmpty())
|
---|
1375 | names << prop->setters().first()->name();
|
---|
1376 | if (!prop->resetters().isEmpty())
|
---|
1377 | names << prop->resetters().first()->name();
|
---|
1378 | }
|
---|
1379 | else if ((*m)->type() == Node::Enum) {
|
---|
1380 | const EnumNode *enume = reinterpret_cast<const EnumNode*>(*m);
|
---|
1381 | if (enume->flagsType())
|
---|
1382 | names << enume->flagsType()->name();
|
---|
1383 |
|
---|
1384 | foreach (const QString &enumName,
|
---|
1385 | enume->doc().enumItemNames().toSet() -
|
---|
1386 | enume->doc().omitEnumItemNames().toSet())
|
---|
1387 | names << plainCode(marker->markedUpEnumValue(enumName,
|
---|
1388 | enume));
|
---|
1389 | }
|
---|
1390 | foreach (const QString &name, names)
|
---|
1391 | classSection.keywords += qMakePair(name,linkForNode(*m,0));
|
---|
1392 | }
|
---|
1393 | ++m;
|
---|
1394 | }
|
---|
1395 | ++s;
|
---|
1396 | }
|
---|
1397 | generateFooter(inner);
|
---|
1398 |
|
---|
1399 | if (!membersLink.isEmpty()) {
|
---|
1400 | DcfSection membersSection;
|
---|
1401 | membersSection.title = "List of all members";
|
---|
1402 | membersSection.ref = membersLink;
|
---|
1403 | appendDcfSubSection(&classSection, membersSection);
|
---|
1404 | }
|
---|
1405 | if (!obsoleteLink.isEmpty()) {
|
---|
1406 | DcfSection obsoleteSection;
|
---|
1407 | obsoleteSection.title = "Obsolete members";
|
---|
1408 | obsoleteSection.ref = obsoleteLink;
|
---|
1409 | appendDcfSubSection(&classSection, obsoleteSection);
|
---|
1410 | }
|
---|
1411 | if (!compatLink.isEmpty()) {
|
---|
1412 | DcfSection compatSection;
|
---|
1413 | compatSection.title = "Qt 3 support members";
|
---|
1414 | compatSection.ref = compatLink;
|
---|
1415 | appendDcfSubSection(&classSection, compatSection);
|
---|
1416 | }
|
---|
1417 |
|
---|
1418 | appendDcfSubSection(&dcfClassesRoot, classSection);
|
---|
1419 | }
|
---|
1420 |
|
---|
1421 | void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
|
---|
1422 | {
|
---|
1423 | SubTitleSize subTitleSize = LargeSubTitle;
|
---|
1424 | DcfSection fakeSection;
|
---|
1425 | fakeSection.title = fake->fullTitle();
|
---|
1426 | fakeSection.ref = linkForNode(fake, 0);
|
---|
1427 |
|
---|
1428 | QList<Section> sections;
|
---|
1429 | QList<Section>::const_iterator s;
|
---|
1430 |
|
---|
1431 | QString htmlTitle = fake->fullTitle();
|
---|
1432 | if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) {
|
---|
1433 | subTitleSize = SmallSubTitle;
|
---|
1434 | htmlTitle += " (" + fake->subTitle() + ")";
|
---|
1435 | }
|
---|
1436 |
|
---|
1437 | generateHeader(htmlTitle, fake, marker, true);
|
---|
1438 | generateTitle(fake->fullTitle(),
|
---|
1439 | Text() << fake->subTitle(),
|
---|
1440 | subTitleSize,
|
---|
1441 | fake,
|
---|
1442 | marker);
|
---|
1443 |
|
---|
1444 | if (fake->subType() == Node::Module) {
|
---|
1445 | // Generate brief text and status for modules.
|
---|
1446 | generateBrief(fake, marker);
|
---|
1447 | generateStatus(fake, marker);
|
---|
1448 |
|
---|
1449 | if (moduleNamespaceMap.contains(fake->name())) {
|
---|
1450 | out() << "<h2>Namespaces</h2>\n";
|
---|
1451 | generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]);
|
---|
1452 | }
|
---|
1453 | if (moduleClassMap.contains(fake->name())) {
|
---|
1454 | out() << "<h2>Classes</h2>\n";
|
---|
1455 | generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
|
---|
1456 | }
|
---|
1457 | }
|
---|
1458 | else if (fake->subType() == Node::HeaderFile) {
|
---|
1459 | // Generate brief text and status for modules.
|
---|
1460 | generateBrief(fake, marker);
|
---|
1461 | generateStatus(fake, marker);
|
---|
1462 |
|
---|
1463 | out() << "<ul>\n";
|
---|
1464 |
|
---|
1465 | QString membersLink = generateListOfAllMemberFile(fake, marker);
|
---|
1466 | if (!membersLink.isEmpty())
|
---|
1467 | out() << "<li><a href=\"" << membersLink << "\">"
|
---|
1468 | << "List of all members, including inherited members</a></li>\n";
|
---|
1469 |
|
---|
1470 | QString obsoleteLink = generateLowStatusMemberFile(fake,
|
---|
1471 | marker,
|
---|
1472 | CodeMarker::Obsolete);
|
---|
1473 | if (!obsoleteLink.isEmpty())
|
---|
1474 | out() << "<li><a href=\"" << obsoleteLink << "\">"
|
---|
1475 | << "Obsolete members</a></li>\n";
|
---|
1476 |
|
---|
1477 | QString compatLink = generateLowStatusMemberFile(fake,
|
---|
1478 | marker,
|
---|
1479 | CodeMarker::Compat);
|
---|
1480 | if (!compatLink.isEmpty())
|
---|
1481 | out() << "<li><a href=\"" << compatLink << "\">"
|
---|
1482 | << "Qt 3 support members</a></li>\n";
|
---|
1483 |
|
---|
1484 | out() << "</ul>\n";
|
---|
1485 |
|
---|
1486 | if (!membersLink.isEmpty()) {
|
---|
1487 | DcfSection membersSection;
|
---|
1488 | membersSection.title = "List of all members";
|
---|
1489 | membersSection.ref = membersLink;
|
---|
1490 | appendDcfSubSection(&fakeSection, membersSection);
|
---|
1491 | }
|
---|
1492 | if (!obsoleteLink.isEmpty()) {
|
---|
1493 | DcfSection obsoleteSection;
|
---|
1494 | obsoleteSection.title = "Obsolete members";
|
---|
1495 | obsoleteSection.ref = obsoleteLink;
|
---|
1496 | appendDcfSubSection(&fakeSection, obsoleteSection);
|
---|
1497 | }
|
---|
1498 | if (!compatLink.isEmpty()) {
|
---|
1499 | DcfSection compatSection;
|
---|
1500 | compatSection.title = "Qt 3 support members";
|
---|
1501 | compatSection.ref = compatLink;
|
---|
1502 | appendDcfSubSection(&fakeSection, compatSection);
|
---|
1503 | }
|
---|
1504 | }
|
---|
1505 | #ifdef QDOC_QML
|
---|
1506 | else if (fake->subType() == Node::QmlClass) {
|
---|
1507 | const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake);
|
---|
1508 | const ClassNode* cn = qml_cn->classNode();
|
---|
1509 | generateQmlInherits(qml_cn, marker);
|
---|
1510 | generateQmlInstantiates(qml_cn, marker);
|
---|
1511 | generateBrief(qml_cn, marker);
|
---|
1512 | sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
|
---|
1513 | s = sections.begin();
|
---|
1514 | while (s != sections.end()) {
|
---|
1515 | out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
|
---|
1516 | out() << "<h2>" << protect((*s).name) << "</h2>\n";
|
---|
1517 | generateQmlSummary(*s,fake,marker);
|
---|
1518 | ++s;
|
---|
1519 | }
|
---|
1520 |
|
---|
1521 | out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
|
---|
1522 | out() << "<h2>" << "Detailed Description" << "</h2>\n";
|
---|
1523 | generateBody(fake, marker);
|
---|
1524 | if (cn)
|
---|
1525 | generateQmlText(cn->doc().body(), cn, marker, fake->name());
|
---|
1526 | generateAlsoList(fake, marker);
|
---|
1527 | out() << "<hr />\n";
|
---|
1528 |
|
---|
1529 | sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
|
---|
1530 | s = sections.begin();
|
---|
1531 | while (s != sections.end()) {
|
---|
1532 | out() << "<h2>" << protect((*s).name) << "</h2>\n";
|
---|
1533 | NodeList::ConstIterator m = (*s).members.begin();
|
---|
1534 | while (m != (*s).members.end()) {
|
---|
1535 | generateDetailedQmlMember(*m, fake, marker);
|
---|
1536 | out() << "<br />\n";
|
---|
1537 | fakeSection.keywords += qMakePair((*m)->name(),
|
---|
1538 | linkForNode(*m,0));
|
---|
1539 | ++m;
|
---|
1540 | }
|
---|
1541 | ++s;
|
---|
1542 | }
|
---|
1543 | generateFooter(fake);
|
---|
1544 | return;
|
---|
1545 | }
|
---|
1546 | #endif
|
---|
1547 |
|
---|
1548 | sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay);
|
---|
1549 | s = sections.begin();
|
---|
1550 | while (s != sections.end()) {
|
---|
1551 | out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
|
---|
1552 | out() << "<h2>" << protect((*s).name) << "</h2>\n";
|
---|
1553 | generateSectionList(*s, fake, marker, CodeMarker::Summary);
|
---|
1554 | ++s;
|
---|
1555 | }
|
---|
1556 |
|
---|
1557 | Text brief = fake->doc().briefText();
|
---|
1558 | if (fake->subType() == Node::Module && !brief.isEmpty()) {
|
---|
1559 | out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
|
---|
1560 | out() << "<h2>" << "Detailed Description" << "</h2>\n";
|
---|
1561 | }
|
---|
1562 |
|
---|
1563 | generateBody(fake, marker);
|
---|
1564 | generateAlsoList(fake, marker);
|
---|
1565 |
|
---|
1566 | if (!fake->groupMembers().isEmpty()) {
|
---|
1567 | NodeMap groupMembersMap;
|
---|
1568 | foreach (const Node *node, fake->groupMembers()) {
|
---|
1569 | if (node->type() == Node::Class || node->type() == Node::Namespace)
|
---|
1570 | groupMembersMap[node->name()] = node;
|
---|
1571 | }
|
---|
1572 | generateAnnotatedList(fake, marker, groupMembersMap);
|
---|
1573 | }
|
---|
1574 |
|
---|
1575 | fakeSection.keywords += qMakePair(fakeSection.title, fakeSection.ref);
|
---|
1576 |
|
---|
1577 | sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay);
|
---|
1578 | s = sections.begin();
|
---|
1579 | while (s != sections.end()) {
|
---|
1580 | out() << "<hr />\n";
|
---|
1581 | out() << "<h2>" << protect((*s).name) << "</h2>\n";
|
---|
1582 |
|
---|
1583 | NodeList::ConstIterator m = (*s).members.begin();
|
---|
1584 | while (m != (*s).members.end()) {
|
---|
1585 | generateDetailedMember(*m, fake, marker);
|
---|
1586 | fakeSection.keywords += qMakePair((*m)->name(), linkForNode(*m, 0));
|
---|
1587 | ++m;
|
---|
1588 | }
|
---|
1589 | ++s;
|
---|
1590 | }
|
---|
1591 | generateFooter(fake);
|
---|
1592 |
|
---|
1593 | if (fake->subType() == Node::Example) {
|
---|
1594 | appendDcfSubSection(&dcfExamplesRoot, fakeSection);
|
---|
1595 | }
|
---|
1596 | else if (fake->subType() != Node::File) {
|
---|
1597 | QString contentsPage = fake->links().value(Node::ContentsLink).first;
|
---|
1598 |
|
---|
1599 | if (contentsPage == "Qt Designer Manual") {
|
---|
1600 | appendDcfSubSection(&dcfDesignerRoot, fakeSection);
|
---|
1601 | }
|
---|
1602 | else if (contentsPage == "Qt Linguist Manual") {
|
---|
1603 | appendDcfSubSection(&dcfLinguistRoot, fakeSection);
|
---|
1604 | }
|
---|
1605 | else if (contentsPage == "Qt Assistant Manual") {
|
---|
1606 | appendDcfSubSection(&dcfAssistantRoot, fakeSection);
|
---|
1607 | }
|
---|
1608 | else if (contentsPage == "qmake Manual") {
|
---|
1609 | appendDcfSubSection(&dcfQmakeRoot, fakeSection);
|
---|
1610 | }
|
---|
1611 | else {
|
---|
1612 | appendDcfSubSection(&dcfOverviewsRoot, fakeSection);
|
---|
1613 | }
|
---|
1614 | }
|
---|
1615 | }
|
---|
1616 |
|
---|
1617 | QString HtmlGenerator::fileExtension(const Node * /* node */)
|
---|
1618 | {
|
---|
1619 | return "html";
|
---|
1620 | }
|
---|
1621 |
|
---|
1622 | void HtmlGenerator::generateHeader(const QString& title,
|
---|
1623 | const Node *node,
|
---|
1624 | CodeMarker *marker,
|
---|
1625 | bool mainPage)
|
---|
1626 | {
|
---|
1627 | out() << "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";
|
---|
1628 |
|
---|
1629 | out() << "<!DOCTYPE html\n"
|
---|
1630 | " PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n"
|
---|
1631 | "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
|
---|
1632 |
|
---|
1633 | QString shortVersion;
|
---|
1634 | if ((project != "Qtopia") && (project != "Qt Extended")) {
|
---|
1635 | shortVersion = project + " " + shortVersion + ": ";
|
---|
1636 | if (node && !node->doc().location().isEmpty())
|
---|
1637 | out() << "<!-- " << node->doc().location().fileName() << " -->\n";
|
---|
1638 |
|
---|
1639 | shortVersion = myTree->version();
|
---|
1640 | if (shortVersion.count(QChar('.')) == 2)
|
---|
1641 | shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
|
---|
1642 | if (!shortVersion.isEmpty()) {
|
---|
1643 | if (project == "QSA")
|
---|
1644 | shortVersion = "QSA " + shortVersion + ": ";
|
---|
1645 | else
|
---|
1646 | shortVersion = "Qt " + shortVersion + ": ";
|
---|
1647 | }
|
---|
1648 | }
|
---|
1649 |
|
---|
1650 | out() << "<head>\n"
|
---|
1651 | " <title>" << shortVersion << protect(title) << "</title>\n";
|
---|
1652 | if (!style.isEmpty())
|
---|
1653 | out() << " <style type=\"text/css\">" << style << "</style>\n";
|
---|
1654 |
|
---|
1655 | const QMap<QString, QString> &metaMap = node->doc().metaTagMap();
|
---|
1656 | if (!metaMap.isEmpty()) {
|
---|
1657 | QMapIterator<QString, QString> i(metaMap);
|
---|
1658 | while (i.hasNext()) {
|
---|
1659 | i.next();
|
---|
1660 | out() << " <meta name=\"" << protect(i.key()) << "\" contents=\""
|
---|
1661 | << protect(i.value()) << "\" />\n";
|
---|
1662 | }
|
---|
1663 | }
|
---|
1664 |
|
---|
1665 | navigationLinks.clear();
|
---|
1666 |
|
---|
1667 | if (node && !node->links().empty()) {
|
---|
1668 | QPair<QString,QString> linkPair;
|
---|
1669 | QPair<QString,QString> anchorPair;
|
---|
1670 | const Node *linkNode;
|
---|
1671 |
|
---|
1672 | if (node->links().contains(Node::PreviousLink)) {
|
---|
1673 | linkPair = node->links()[Node::PreviousLink];
|
---|
1674 | linkNode = findNodeForTarget(linkPair.first, node, marker);
|
---|
1675 | if (!linkNode || linkNode == node)
|
---|
1676 | anchorPair = linkPair;
|
---|
1677 | else
|
---|
1678 | anchorPair = anchorForNode(linkNode);
|
---|
1679 |
|
---|
1680 | out() << " <link rel=\"prev\" href=\""
|
---|
1681 | << anchorPair.first << "\" />\n";
|
---|
1682 |
|
---|
1683 | navigationLinks += "[Previous: <a href=\"" + anchorPair.first + "\">";
|
---|
1684 | if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
|
---|
1685 | navigationLinks += protect(anchorPair.second);
|
---|
1686 | else
|
---|
1687 | navigationLinks += protect(linkPair.second);
|
---|
1688 | navigationLinks += "</a>]\n";
|
---|
1689 | }
|
---|
1690 | if (node->links().contains(Node::ContentsLink)) {
|
---|
1691 | linkPair = node->links()[Node::ContentsLink];
|
---|
1692 | linkNode = findNodeForTarget(linkPair.first, node, marker);
|
---|
1693 | if (!linkNode || linkNode == node)
|
---|
1694 | anchorPair = linkPair;
|
---|
1695 | else
|
---|
1696 | anchorPair = anchorForNode(linkNode);
|
---|
1697 |
|
---|
1698 | out() << " <link rel=\"contents\" href=\""
|
---|
1699 | << anchorPair.first << "\" />\n";
|
---|
1700 |
|
---|
1701 | navigationLinks += "[<a href=\"" + anchorPair.first + "\">";
|
---|
1702 | if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
|
---|
1703 | navigationLinks += protect(anchorPair.second);
|
---|
1704 | else
|
---|
1705 | navigationLinks += protect(linkPair.second);
|
---|
1706 | navigationLinks += "</a>]\n";
|
---|
1707 | }
|
---|
1708 | if (node->links().contains(Node::NextLink)) {
|
---|
1709 | linkPair = node->links()[Node::NextLink];
|
---|
|
---|