author | Eckhart Koeppen <eckhart.koppen@nokia.com> |
Wed, 21 Apr 2010 12:15:23 +0300 | |
branch | RCL_3 |
changeset 12 | cc75c76972ee |
parent 4 | 3b1da2848fc7 |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 4 |
** All rights reserved. |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 |
** |
|
7 |
** This file is part of the tools applications of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** No Commercial Usage |
|
11 |
** This file contains pre-release code and may not be distributed. |
|
12 |
** You may use this file in accordance with the terms and conditions |
|
13 |
** contained in the Technology Preview License Agreement accompanying |
|
14 |
** this package. |
|
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 |
** If you have questions regarding the use of this file, please contact |
|
29 |
** Nokia at qt-info@nokia.com. |
|
30 |
** |
|
31 |
** |
|
32 |
** |
|
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
|
37 |
** |
|
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]; |
|
1710 |
linkNode = findNodeForTarget(linkPair.first, node, marker); |
|
1711 |
if (!linkNode || linkNode == node) |
|
1712 |
anchorPair = linkPair; |
|
1713 |
else |
|
1714 |
anchorPair = anchorForNode(linkNode); |
|
1715 |
||
1716 |
out() << " <link rel=\"next\" href=\"" |
|
1717 |
<< anchorPair.first << "\" />\n"; |
|
1718 |
||
1719 |
navigationLinks += "[Next: <a href=\"" + anchorPair.first + "\">"; |
|
1720 |
if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty()) |
|
1721 |
navigationLinks += protect(anchorPair.second); |
|
1722 |
else |
|
1723 |
navigationLinks += protect(linkPair.second); |
|
1724 |
navigationLinks += "</a>]\n"; |
|
1725 |
} |
|
1726 |
if (node->links().contains(Node::IndexLink)) { |
|
1727 |
linkPair = node->links()[Node::IndexLink]; |
|
1728 |
linkNode = findNodeForTarget(linkPair.first, node, marker); |
|
1729 |
if (!linkNode || linkNode == node) |
|
1730 |
anchorPair = linkPair; |
|
1731 |
else |
|
1732 |
anchorPair = anchorForNode(linkNode); |
|
1733 |
out() << " <link rel=\"index\" href=\"" |
|
1734 |
<< anchorPair.first << "\" />\n"; |
|
1735 |
} |
|
1736 |
if (node->links().contains(Node::StartLink)) { |
|
1737 |
linkPair = node->links()[Node::StartLink]; |
|
1738 |
linkNode = findNodeForTarget(linkPair.first, node, marker); |
|
1739 |
if (!linkNode || linkNode == node) |
|
1740 |
anchorPair = linkPair; |
|
1741 |
else |
|
1742 |
anchorPair = anchorForNode(linkNode); |
|
1743 |
out() << " <link rel=\"start\" href=\"" |
|
1744 |
<< anchorPair.first << "\" />\n"; |
|
1745 |
} |
|
1746 |
} |
|
1747 |
||
1748 |
foreach (const QString &stylesheet, stylesheets) { |
|
1749 |
out() << " <link href=\"" << stylesheet << "\" rel=\"stylesheet\" " |
|
1750 |
<< "type=\"text/css\" />\n"; |
|
1751 |
} |
|
1752 |
||
1753 |
foreach (const QString &customHeadElement, customHeadElements) { |
|
1754 |
out() << " " << customHeadElement << "\n"; |
|
1755 |
} |
|
1756 |
||
1757 |
out() << "</head>\n" |
|
1758 |
"<body>\n"; |
|
1759 |
if (mainPage) |
|
1760 |
generateMacRef(node, marker); |
|
1761 |
out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version()); |
|
1762 |
||
1763 |
||
1764 |
if (node && !node->links().empty()) |
|
1765 |
out() << "<p>\n" << navigationLinks << "</p>\n"; |
|
1766 |
} |
|
1767 |
||
1768 |
void HtmlGenerator::generateTitle(const QString& title, |
|
1769 |
const Text &subTitle, |
|
1770 |
SubTitleSize subTitleSize, |
|
1771 |
const Node *relative, |
|
1772 |
CodeMarker *marker) |
|
1773 |
{ |
|
1774 |
out() << "<h1 class=\"title\">" << protect(title); |
|
1775 |
if (!subTitle.isEmpty()) { |
|
1776 |
out() << "<br />"; |
|
1777 |
if (subTitleSize == SmallSubTitle) |
|
1778 |
out() << "<span class=\"small-subtitle\">"; |
|
1779 |
else |
|
1780 |
out() << "<span class=\"subtitle\">"; |
|
1781 |
generateText(subTitle, relative, marker); |
|
1782 |
out() << "</span>\n"; |
|
1783 |
} |
|
1784 |
out() << "</h1>\n"; |
|
1785 |
} |
|
1786 |
||
1787 |
void HtmlGenerator::generateFooter(const Node *node) |
|
1788 |
{ |
|
1789 |
if (node && !node->links().empty()) |
|
1790 |
out() << "<p>\n" << navigationLinks << "</p>\n"; |
|
1791 |
||
1792 |
out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version()) |
|
1793 |
<< QString(address).replace("\\" + COMMAND_VERSION, myTree->version()) |
|
1794 |
<< "</body>\n" |
|
1795 |
"</html>\n"; |
|
1796 |
} |
|
1797 |
||
1798 |
void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker, |
|
1799 |
const Node *relative) |
|
1800 |
{ |
|
1801 |
Text brief = node->doc().briefText(); |
|
1802 |
if (!brief.isEmpty()) { |
|
1803 |
out() << "<p>"; |
|
1804 |
generateText(brief, node, marker); |
|
1805 |
if (!relative || node == relative) |
|
1806 |
out() << " <a href=\"#"; |
|
1807 |
else |
|
1808 |
out() << " <a href=\"" << linkForNode(node, relative) << "#"; |
|
1809 |
out() << registerRef("details") << "\">More...</a></p>\n"; |
|
1810 |
} |
|
1811 |
} |
|
1812 |
||
1813 |
void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker) |
|
1814 |
{ |
|
1815 |
if (!inner->includes().isEmpty()) { |
|
1816 |
out() << "<pre>" |
|
1817 |
<< trimmedTrailing(highlightedCode(indent(codeIndent, |
|
1818 |
marker->markedUpIncludes(inner->includes())), |
|
1819 |
marker,inner)) |
|
1820 |
<< "</pre>"; |
|
1821 |
} |
|
1822 |
} |
|
1823 |
||
1824 |
void HtmlGenerator::generateTableOfContents(const Node *node, |
|
1825 |
CodeMarker *marker, |
|
1826 |
Doc::SectioningUnit sectioningUnit, |
|
1827 |
int numColumns, |
|
1828 |
const Node *relative) |
|
1829 |
||
1830 |
{ |
|
1831 |
if (!node->doc().hasTableOfContents()) |
|
1832 |
return; |
|
1833 |
QList<Atom *> toc = node->doc().tableOfContents(); |
|
1834 |
if (toc.isEmpty()) |
|
1835 |
return; |
|
1836 |
||
1837 |
QString nodeName = ""; |
|
1838 |
if (node != relative) |
|
1839 |
nodeName = node->name(); |
|
1840 |
||
1841 |
QStringList sectionNumber; |
|
1842 |
int columnSize = 0; |
|
1843 |
||
1844 |
QString tdTag; |
|
1845 |
if (numColumns > 1) { |
|
1846 |
tdTag = "<td width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">"; |
|
1847 |
out() << "<p><table class=\"toc\" width=\"100%\">\n<tr valign=\"top\">" |
|
1848 |
<< tdTag << "\n"; |
|
1849 |
} |
|
1850 |
||
1851 |
// disable nested links in table of contents |
|
1852 |
inContents = true; |
|
1853 |
inLink = true; |
|
1854 |
||
1855 |
for (int i = 0; i < toc.size(); ++i) { |
|
1856 |
Atom *atom = toc.at(i); |
|
1857 |
||
1858 |
int nextLevel = atom->string().toInt(); |
|
1859 |
if (nextLevel > (int)sectioningUnit) |
|
1860 |
continue; |
|
1861 |
||
1862 |
if (sectionNumber.size() < nextLevel) { |
|
1863 |
do { |
|
1864 |
out() << "<ul>"; |
|
1865 |
sectionNumber.append("1"); |
|
1866 |
} while (sectionNumber.size() < nextLevel); |
|
1867 |
} |
|
1868 |
else { |
|
1869 |
while (sectionNumber.size() > nextLevel) { |
|
1870 |
out() << "</ul>\n"; |
|
1871 |
sectionNumber.removeLast(); |
|
1872 |
} |
|
1873 |
sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1); |
|
1874 |
} |
|
1875 |
int numAtoms; |
|
1876 |
Text headingText = Text::sectionHeading(atom); |
|
1877 |
||
1878 |
if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) { |
|
1879 |
out() << "</ul></td>" << tdTag << "<ul>\n"; |
|
1880 |
columnSize = 0; |
|
1881 |
} |
|
1882 |
out() << "<li>"; |
|
1883 |
out() << "<a href=\"" |
|
1884 |
<< nodeName |
|
1885 |
<< "#" |
|
1886 |
<< Doc::canonicalTitle(headingText.toString()) |
|
1887 |
<< "\">"; |
|
1888 |
generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms); |
|
1889 |
out() << "</a></li>\n"; |
|
1890 |
||
1891 |
++columnSize; |
|
1892 |
} |
|
1893 |
while (!sectionNumber.isEmpty()) { |
|
1894 |
out() << "</ul>\n"; |
|
1895 |
sectionNumber.removeLast(); |
|
1896 |
} |
|
1897 |
||
1898 |
if (numColumns > 1) |
|
1899 |
out() << "</td></tr></table></p>\n"; |
|
1900 |
||
1901 |
inContents = false; |
|
1902 |
inLink = false; |
|
1903 |
} |
|
1904 |
||
1905 |
#if 0 |
|
1906 |
void HtmlGenerator::generateNavigationBar(const NavigationBar& bar, |
|
1907 |
const Node *node, |
|
1908 |
CodeMarker *marker) |
|
1909 |
{ |
|
1910 |
if (bar.prev.begin() != 0 || bar.current.begin() != 0 || |
|
1911 |
bar.next.begin() != 0) { |
|
1912 |
out() << "<p align=\"right\">"; |
|
1913 |
if (bar.prev.begin() != 0) { |
|
1914 |
#if 0 |
|
1915 |
out() << "[<a href=\"" << section.previousBaseName() |
|
1916 |
<< ".html\">Prev: "; |
|
1917 |
generateText(section.previousHeading(), node, marker); |
|
1918 |
out() << "</a>]\n"; |
|
1919 |
#endif |
|
1920 |
} |
|
1921 |
if (bar.current.begin() != 0) { |
|
1922 |
out() << "[<a href=\"" << "home" |
|
1923 |
<< ".html\">Home</a>]\n"; |
|
1924 |
} |
|
1925 |
if (bar.next.begin() != 0) { |
|
1926 |
out() << "[<a href=\"" << fileBase(node, bar.next) |
|
1927 |
<< ".html\">Next: "; |
|
1928 |
generateText(Text::sectionHeading(bar.next.begin()), node, marker); |
|
1929 |
out() << "</a>]\n"; |
|
1930 |
} |
|
1931 |
out() << "</p>\n"; |
|
1932 |
} |
|
1933 |
} |
|
1934 |
#endif |
|
1935 |
||
1936 |
QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, |
|
1937 |
CodeMarker *marker) |
|
1938 |
{ |
|
1939 |
QList<Section> sections; |
|
1940 |
QList<Section>::ConstIterator s; |
|
1941 |
||
1942 |
sections = marker->sections(inner, |
|
1943 |
CodeMarker::SeparateList, |
|
1944 |
CodeMarker::Okay); |
|
1945 |
if (sections.isEmpty()) |
|
1946 |
return QString(); |
|
1947 |
||
1948 |
QString fileName = fileBase(inner) + "-members." + fileExtension(inner); |
|
1949 |
beginSubPage(inner->location(), fileName); |
|
1950 |
QString title = "List of All Members for " + inner->name(); |
|
1951 |
generateHeader(title, inner, marker, false); |
|
1952 |
generateTitle(title, Text(), SmallSubTitle, inner, marker); |
|
1953 |
out() << "<p>This is the complete list of members for "; |
|
1954 |
generateFullName(inner, 0, marker); |
|
1955 |
out() << ", including inherited members.</p>\n"; |
|
1956 |
||
1957 |
Section section = sections.first(); |
|
1958 |
generateSectionList(section, 0, marker, CodeMarker::SeparateList); |
|
1959 |
||
1960 |
generateFooter(); |
|
1961 |
endSubPage(); |
|
1962 |
return fileName; |
|
1963 |
} |
|
1964 |
||
1965 |
QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, |
|
1966 |
CodeMarker *marker, |
|
1967 |
CodeMarker::Status status) |
|
1968 |
{ |
|
1969 |
QList<Section> sections = marker->sections(inner, |
|
1970 |
CodeMarker::Summary, |
|
1971 |
status); |
|
1972 |
QMutableListIterator<Section> j(sections); |
|
1973 |
while (j.hasNext()) { |
|
1974 |
if (j.next().members.size() == 0) |
|
1975 |
j.remove(); |
|
1976 |
} |
|
1977 |
if (sections.isEmpty()) |
|
1978 |
return QString(); |
|
1979 |
||
1980 |
int i; |
|
1981 |
||
1982 |
QString title; |
|
1983 |
QString fileName; |
|
1984 |
||
1985 |
if (status == CodeMarker::Compat) { |
|
1986 |
title = "Qt 3 Support Members for " + inner->name(); |
|
1987 |
fileName = fileBase(inner) + "-qt3." + fileExtension(inner); |
|
1988 |
} |
|
1989 |
else { |
|
1990 |
title = "Obsolete Members for " + inner->name(); |
|
1991 |
fileName = fileBase(inner) + "-obsolete." + fileExtension(inner); |
|
1992 |
} |
|
1993 |
||
1994 |
beginSubPage(inner->location(), fileName); |
|
1995 |
generateHeader(title, inner, marker, false); |
|
1996 |
generateTitle(title, Text(), SmallSubTitle, inner, marker); |
|
1997 |
||
1998 |
if (status == CodeMarker::Compat) { |
|
1999 |
out() << "<p><b>The following class members are part of the " |
|
2000 |
"<a href=\"qt3support.html\">Qt 3 support layer</a>.</b> " |
|
2001 |
"They are provided to help you port old code to Qt 4. We advise against " |
|
2002 |
"using them in new code.</p>\n"; |
|
2003 |
} |
|
2004 |
else { |
|
2005 |
out() << "<p><b>The following class members are obsolete.</b> " |
|
2006 |
<< "They are provided to keep old source code working. " |
|
2007 |
<< "We strongly advise against using them in new code.</p>\n"; |
|
2008 |
} |
|
2009 |
||
2010 |
out() << "<p><ul><li><a href=\"" |
|
2011 |
<< linkForNode(inner, 0) << "\">" |
|
2012 |
<< protect(inner->name()) |
|
2013 |
<< " class reference</a></li></ul></p>\n"; |
|
2014 |
||
2015 |
for (i = 0; i < sections.size(); ++i) { |
|
2016 |
out() << "<h2>" << protect(sections.at(i).name) << "</h2>\n"; |
|
2017 |
generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary); |
|
2018 |
} |
|
2019 |
||
2020 |
sections = marker->sections(inner, CodeMarker::Detailed, status); |
|
2021 |
for (i = 0; i < sections.size(); ++i) { |
|
2022 |
out() << "<hr />\n"; |
|
2023 |
out() << "<h2>" << protect(sections.at(i).name) << "</h2>\n"; |
|
2024 |
||
2025 |
NodeList::ConstIterator m = sections.at(i).members.begin(); |
|
2026 |
while (m != sections.at(i).members.end()) { |
|
2027 |
if ((*m)->access() != Node::Private) |
|
2028 |
generateDetailedMember(*m, inner, marker); |
|
2029 |
++m; |
|
2030 |
} |
|
2031 |
} |
|
2032 |
||
2033 |
generateFooter(); |
|
2034 |
endSubPage(); |
|
2035 |
return fileName; |
|
2036 |
} |
|
2037 |
||
2038 |
void HtmlGenerator::generateClassHierarchy(const Node *relative, |
|
2039 |
CodeMarker *marker, |
|
2040 |
const QMap<QString,const Node*> &classMap) |
|
2041 |
{ |
|
2042 |
if (classMap.isEmpty()) |
|
2043 |
return; |
|
2044 |
||
2045 |
NodeMap topLevel; |
|
2046 |
NodeMap::ConstIterator c = classMap.begin(); |
|
2047 |
while (c != classMap.end()) { |
|
2048 |
const ClassNode *classe = static_cast<const ClassNode *>(*c); |
|
2049 |
if (classe->baseClasses().isEmpty()) |
|
2050 |
topLevel.insert(classe->name(), classe); |
|
2051 |
++c; |
|
2052 |
} |
|
2053 |
||
2054 |
QStack<NodeMap > stack; |
|
2055 |
stack.push(topLevel); |
|
2056 |
||
2057 |
out() << "<ul>\n"; |
|
2058 |
while (!stack.isEmpty()) { |
|
2059 |
if (stack.top().isEmpty()) { |
|
2060 |
stack.pop(); |
|
2061 |
out() << "</ul>\n"; |
|
2062 |
} |
|
2063 |
else { |
|
2064 |
const ClassNode *child = |
|
2065 |
static_cast<const ClassNode *>(*stack.top().begin()); |
|
2066 |
out() << "<li>"; |
|
2067 |
generateFullName(child, relative, marker); |
|
2068 |
out() << "</li>\n"; |
|
2069 |
stack.top().erase(stack.top().begin()); |
|
2070 |
||
2071 |
NodeMap newTop; |
|
2072 |
foreach (const RelatedClass &d, child->derivedClasses()) { |
|
2073 |
if (d.access != Node::Private) |
|
2074 |
newTop.insert(d.node->name(), d.node); |
|
2075 |
} |
|
2076 |
if (!newTop.isEmpty()) { |
|
2077 |
stack.push(newTop); |
|
2078 |
out() << "<ul>\n"; |
|
2079 |
} |
|
2080 |
} |
|
2081 |
} |
|
2082 |
} |
|
2083 |
||
2084 |
void HtmlGenerator::generateAnnotatedList(const Node *relative, |
|
2085 |
CodeMarker *marker, |
|
2086 |
const NodeMap &nodeMap) |
|
2087 |
{ |
|
2088 |
out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" " |
|
2089 |
<< "cellspacing=\"1\" border=\"0\">\n"; |
|
2090 |
||
2091 |
int row = 0; |
|
2092 |
foreach (const QString &name, nodeMap.keys()) { |
|
2093 |
const Node *node = nodeMap[name]; |
|
2094 |
||
2095 |
if (node->status() == Node::Obsolete) |
|
2096 |
continue; |
|
2097 |
||
2098 |
if (++row % 2 == 1) |
|
2099 |
out() << "<tr valign=\"top\" class=\"odd\">"; |
|
2100 |
else |
|
2101 |
out() << "<tr valign=\"top\" class=\"even\">"; |
|
2102 |
out() << "<th>"; |
|
2103 |
generateFullName(node, relative, marker); |
|
2104 |
out() << "</th>"; |
|
2105 |
||
2106 |
if (!(node->type() == Node::Fake)) { |
|
2107 |
Text brief = node->doc().trimmedBriefText(name); |
|
2108 |
if (!brief.isEmpty()) { |
|
2109 |
out() << "<td>"; |
|
2110 |
generateText(brief, node, marker); |
|
2111 |
out() << "</td>"; |
|
2112 |
} |
|
2113 |
} |
|
2114 |
else { |
|
2115 |
out() << "<td>"; |
|
2116 |
out() << protect(node->doc().briefText().toString()); |
|
2117 |
out() << "</td>"; |
|
2118 |
} |
|
2119 |
out() << "</tr>\n"; |
|
2120 |
} |
|
2121 |
out() << "</table></p>\n"; |
|
2122 |
} |
|
2123 |
||
2124 |
/*! |
|
2125 |
This function finds the common prefix of the names of all |
|
2126 |
the classes in \a classMap and then generates a compact |
|
2127 |
list of the class names alphabetized on the part of the |
|
2128 |
name not including the common prefix. You can tell the |
|
2129 |
function to use \a comonPrefix as the common prefix, but |
|
2130 |
normally you let it figure it out itself by looking at |
|
2131 |
the name of the first and last classes in \a classMap. |
|
2132 |
*/ |
|
2133 |
void HtmlGenerator::generateCompactList(const Node *relative, |
|
2134 |
CodeMarker *marker, |
|
2135 |
const NodeMap &classMap, |
|
2136 |
QString commonPrefix) |
|
2137 |
{ |
|
2138 |
const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_' |
|
2139 |
const int NumColumns = 4; // number of columns in the result |
|
2140 |
||
2141 |
if (classMap.isEmpty()) |
|
2142 |
return; |
|
2143 |
||
2144 |
/* |
|
2145 |
If commonPrefix is not empty, then the caller knows what |
|
2146 |
the common prefix is and has passed it in, so just use that |
|
2147 |
one. |
|
2148 |
*/ |
|
2149 |
int commonPrefixLen = commonPrefix.length(); |
|
2150 |
if (commonPrefixLen == 0) { |
|
2151 |
QString first; |
|
2152 |
QString last; |
|
2153 |
||
2154 |
/* |
|
2155 |
The caller didn't pass in a common prefix, so get the common |
|
2156 |
prefix by looking at the class names of the first and last |
|
2157 |
classes in the class map. Discard any namespace names and |
|
2158 |
just use the bare class names. For Qt, the prefix is "Q". |
|
2159 |
||
2160 |
Note that the algorithm used here to derive the common prefix |
|
2161 |
from the first and last classes in alphabetical order (QAccel |
|
2162 |
and QXtWidget in Qt 2.1), fails if either class name does not |
|
2163 |
begin with Q. |
|
2164 |
*/ |
|
2165 |
||
2166 |
NodeMap::const_iterator iter = classMap.begin(); |
|
2167 |
while (iter != classMap.end()) { |
|
2168 |
if (!iter.key().contains("::")) { |
|
2169 |
first = iter.key(); |
|
2170 |
break; |
|
2171 |
} |
|
2172 |
++iter; |
|
2173 |
} |
|
2174 |
||
2175 |
if (first.isEmpty()) |
|
2176 |
first = classMap.begin().key(); |
|
2177 |
||
2178 |
iter = classMap.end(); |
|
2179 |
while (iter != classMap.begin()) { |
|
2180 |
--iter; |
|
2181 |
if (!iter.key().contains("::")) { |
|
2182 |
last = iter.key(); |
|
2183 |
break; |
|
2184 |
} |
|
2185 |
} |
|
2186 |
||
2187 |
if (last.isEmpty()) |
|
2188 |
last = classMap.begin().key(); |
|
2189 |
||
2190 |
if (classMap.size() > 1) { |
|
2191 |
while (commonPrefixLen < first.length() + 1 && |
|
2192 |
commonPrefixLen < last.length() + 1 && |
|
2193 |
first[commonPrefixLen] == last[commonPrefixLen]) |
|
2194 |
++commonPrefixLen; |
|
2195 |
} |
|
2196 |
||
2197 |
commonPrefix = first.left(commonPrefixLen); |
|
2198 |
} |
|
2199 |
||
2200 |
/* |
|
2201 |
Divide the data into 37 paragraphs: 0, ..., 9, A, ..., Z, |
|
2202 |
underscore (_). QAccel will fall in paragraph 10 (A) and |
|
2203 |
QXtWidget in paragraph 33 (X). This is the only place where we |
|
2204 |
assume that NumParagraphs is 37. Each paragraph is a NodeMap. |
|
2205 |
*/ |
|
2206 |
NodeMap paragraph[NumParagraphs+1]; |
|
2207 |
QString paragraphName[NumParagraphs+1]; |
|
2208 |
||
2209 |
NodeMap::ConstIterator c = classMap.begin(); |
|
2210 |
while (c != classMap.end()) { |
|
2211 |
QStringList pieces = c.key().split("::"); |
|
2212 |
QString key; |
|
2213 |
int idx = commonPrefixLen; |
|
2214 |
if (!pieces.last().startsWith(commonPrefix)) |
|
2215 |
idx = 0; |
|
2216 |
if (pieces.size() == 1) |
|
2217 |
key = pieces.last().mid(idx).toLower(); |
|
2218 |
else |
|
2219 |
key = pieces.last().toLower(); |
|
2220 |
||
2221 |
int paragraphNo = NumParagraphs - 1; |
|
2222 |
||
2223 |
if (key[0].digitValue() != -1) { |
|
2224 |
paragraphNo = key[0].digitValue(); |
|
2225 |
} |
|
2226 |
else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) { |
|
2227 |
paragraphNo = 10 + key[0].unicode() - 'a'; |
|
2228 |
} |
|
2229 |
||
2230 |
paragraphName[paragraphNo] = key[0].toUpper(); |
|
2231 |
paragraph[paragraphNo].insert(key, c.value()); |
|
2232 |
++c; |
|
2233 |
} |
|
2234 |
||
2235 |
/* |
|
2236 |
Each paragraph j has a size: paragraph[j].count(). In the |
|
2237 |
discussion, we will assume paragraphs 0 to 5 will have sizes |
|
2238 |
3, 1, 4, 1, 5, 9. |
|
2239 |
||
2240 |
We now want to compute the paragraph offset. Paragraphs 0 to 6 |
|
2241 |
start at offsets 0, 3, 4, 8, 9, 14, 23. |
|
2242 |
*/ |
|
2243 |
int paragraphOffset[NumParagraphs + 1]; // 37 + 1 |
|
2244 |
int i, j, k; |
|
2245 |
||
2246 |
paragraphOffset[0] = 0; |
|
2247 |
for (j = 0; j < NumParagraphs; j++) // j = 0..36 |
|
2248 |
paragraphOffset[j + 1] = paragraphOffset[j] + paragraph[j].count(); |
|
2249 |
||
2250 |
int firstOffset[NumColumns + 1]; // 4 + 1 |
|
2251 |
int currentOffset[NumColumns]; // 4 |
|
2252 |
int currentParagraphNo[NumColumns]; // 4 |
|
2253 |
int currentOffsetInParagraph[NumColumns]; // 4 |
|
2254 |
||
2255 |
int numRows = (classMap.count() + NumColumns - 1) / NumColumns; |
|
2256 |
int curParagNo = 0; |
|
2257 |
||
2258 |
for (i = 0; i < NumColumns; i++) { // i = 0..3 |
|
2259 |
firstOffset[i] = qMin(i * numRows, classMap.size()); |
|
2260 |
currentOffset[i] = firstOffset[i]; |
|
2261 |
||
2262 |
for (j = curParagNo; j < NumParagraphs; j++) { |
|
2263 |
if (paragraphOffset[j] > firstOffset[i]) |
|
2264 |
break; |
|
2265 |
if (paragraphOffset[j] <= firstOffset[i]) |
|
2266 |
curParagNo = j; |
|
2267 |
} |
|
2268 |
currentParagraphNo[i] = curParagNo; |
|
2269 |
currentOffsetInParagraph[i] = firstOffset[i] - |
|
2270 |
paragraphOffset[curParagNo]; |
|
2271 |
} |
|
2272 |
firstOffset[NumColumns] = classMap.count(); |
|
2273 |
||
2274 |
out() << "<p><table class=\"generic\" width=\"100%\">\n"; |
|
2275 |
for (k = 0; k < numRows; k++) { |
|
2276 |
out() << "<tr>\n"; |
|
2277 |
for (i = 0; i < NumColumns; i++) { |
|
2278 |
if (currentOffset[i] >= firstOffset[i + 1]) { |
|
2279 |
// this column is finished |
|
2280 |
out() << "<td>\n</td>\n"; |
|
2281 |
} |
|
2282 |
else { |
|
2283 |
while ((currentParagraphNo[i] < NumParagraphs) && |
|
2284 |
(currentOffsetInParagraph[i] == paragraph[currentParagraphNo[i]].count())) { |
|
2285 |
++currentParagraphNo[i]; |
|
2286 |
currentOffsetInParagraph[i] = 0; |
|
2287 |
} |
|
2288 |
#if 0 |
|
2289 |
if (currentParagraphNo[i] >= NumParagraphs) { |
|
2290 |
qDebug() << "### Internal error ###" << __FILE__ << __LINE__ |
|
2291 |
<< currentParagraphNo[i] << NumParagraphs; |
|
2292 |
currentParagraphNo[i] = NumParagraphs - 1; |
|
2293 |
} |
|
2294 |
#endif |
|
2295 |
out() << "<td align=\"right\">"; |
|
2296 |
if (currentOffsetInParagraph[i] == 0) { |
|
2297 |
// start a new paragraph |
|
2298 |
out() << "<b>" |
|
2299 |
<< paragraphName[currentParagraphNo[i]] |
|
2300 |
<< " </b>"; |
|
2301 |
} |
|
2302 |
out() << "</td>\n"; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
2303 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
2304 |
out() << "<td>"; |
0 | 2305 |
if ((currentParagraphNo[i] < NumParagraphs) && |
2306 |
!paragraphName[currentParagraphNo[i]].isEmpty()) { |
|
2307 |
NodeMap::Iterator it; |
|
2308 |
it = paragraph[currentParagraphNo[i]].begin(); |
|
2309 |
for (j = 0; j < currentOffsetInParagraph[i]; j++) |
|
2310 |
++it; |
|
2311 |
||
2312 |
// Previously, we used generateFullName() for this, but we |
|
2313 |
// require some special formatting. |
|
2314 |
out() << "<a href=\"" |
|
2315 |
<< linkForNode(it.value(), relative) |
|
2316 |
<< "\">"; |
|
2317 |
QStringList pieces = fullName(it.value(), relative, marker).split("::"); |
|
2318 |
out() << protect(pieces.last()); |
|
2319 |
out() << "</a>"; |
|
2320 |
if (pieces.size() > 1) { |
|
2321 |
out() << " ("; |
|
2322 |
generateFullName(it.value()->parent(), relative, marker); |
|
2323 |
out() << ")"; |
|
2324 |
} |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
2325 |
} |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
2326 |
out() << "</td>\n"; |
0 | 2327 |
|
2328 |
currentOffset[i]++; |
|
2329 |
currentOffsetInParagraph[i]++; |
|
2330 |
} |
|
2331 |
} |
|
2332 |
out() << "</tr>\n"; |
|
2333 |
} |
|
2334 |
out() << "</table></p>\n"; |
|
2335 |
} |
|
2336 |
||
2337 |
void HtmlGenerator::generateFunctionIndex(const Node *relative, |
|
2338 |
CodeMarker *marker) |
|
2339 |
{ |
|
2340 |
out() << "<p align=\"center\"><font size=\"+1\"><b>"; |
|
2341 |
for (int i = 0; i < 26; i++) { |
|
2342 |
QChar ch('a' + i); |
|
2343 |
out() << QString("<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper()); |
|
2344 |
} |
|
2345 |
out() << "</b></font></p>\n"; |
|
2346 |
||
2347 |
char nextLetter = 'a'; |
|
2348 |
char currentLetter; |
|
2349 |
||
2350 |
#if 1 |
|
2351 |
out() << "<ul>\n"; |
|
2352 |
#endif |
|
2353 |
QMap<QString, NodeMap >::ConstIterator f = funcIndex.begin(); |
|
2354 |
while (f != funcIndex.end()) { |
|
2355 |
#if 1 |
|
2356 |
out() << "<li>"; |
|
2357 |
#else |
|
2358 |
out() << "<p>"; |
|
2359 |
#endif |
|
2360 |
out() << protect(f.key()) << ":"; |
|
2361 |
||
2362 |
currentLetter = f.key()[0].unicode(); |
|
2363 |
while (islower(currentLetter) && currentLetter >= nextLetter) { |
|
2364 |
out() << QString("<a name=\"%1\"></a>").arg(nextLetter); |
|
2365 |
nextLetter++; |
|
2366 |
} |
|
2367 |
||
2368 |
NodeMap::ConstIterator s = (*f).begin(); |
|
2369 |
while (s != (*f).end()) { |
|
2370 |
out() << " "; |
|
2371 |
generateFullName((*s)->parent(), relative, marker, *s); |
|
2372 |
++s; |
|
2373 |
} |
|
2374 |
#if 1 |
|
2375 |
out() << "</li>"; |
|
2376 |
#else |
|
2377 |
out() << "</p>"; |
|
2378 |
#endif |
|
2379 |
out() << "\n"; |
|
2380 |
++f; |
|
2381 |
} |
|
2382 |
#if 1 |
|
2383 |
out() << "</ul>\n"; |
|
2384 |
#endif |
|
2385 |
} |
|
2386 |
||
2387 |
void HtmlGenerator::generateLegaleseList(const Node *relative, |
|
2388 |
CodeMarker *marker) |
|
2389 |
{ |
|
2390 |
QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin(); |
|
2391 |
while (it != legaleseTexts.end()) { |
|
2392 |
Text text = it.key(); |
|
2393 |
out() << "<hr />\n"; |
|
2394 |
generateText(text, relative, marker); |
|
2395 |
out() << "<ul>\n"; |
|
2396 |
do { |
|
2397 |
out() << "<li>"; |
|
2398 |
generateFullName(it.value(), relative, marker); |
|
2399 |
out() << "</li>\n"; |
|
2400 |
++it; |
|
2401 |
} while (it != legaleseTexts.end() && it.key() == text); |
|
2402 |
out() << "</ul>\n"; |
|
2403 |
} |
|
2404 |
} |
|
2405 |
||
2406 |
/*void HtmlGenerator::generateSynopsis(const Node *node, |
|
2407 |
const Node *relative, |
|
2408 |
CodeMarker *marker, |
|
2409 |
CodeMarker::SynopsisStyle style) |
|
2410 |
{ |
|
2411 |
QString marked = marker->markedUpSynopsis(node, relative, style); |
|
2412 |
QRegExp templateTag("(<[^@>]*>)"); |
|
2413 |
if (marked.indexOf(templateTag) != -1) { |
|
2414 |
QString contents = protect(marked.mid(templateTag.pos(1), |
|
2415 |
templateTag.cap(1).length())); |
|
2416 |
marked.replace(templateTag.pos(1), templateTag.cap(1).length(), |
|
2417 |
contents); |
|
2418 |
} |
|
2419 |
marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), |
|
2420 |
"<i>\\1<sub>\\2</sub></i>"); |
|
2421 |
marked.replace("<@param>", "<i>"); |
|
2422 |
marked.replace("</@param>", "</i>"); |
|
2423 |
||
2424 |
if (style == CodeMarker::Summary) |
|
2425 |
marked.replace("@name>", "b>"); |
|
2426 |
||
2427 |
if (style == CodeMarker::SeparateList) { |
|
2428 |
QRegExp extraRegExp("<@extra>.*</@extra>"); |
|
2429 |
extraRegExp.setMinimal(true); |
|
2430 |
marked.replace(extraRegExp, ""); |
|
2431 |
} |
|
2432 |
else { |
|
2433 |
marked.replace("<@extra>", " <tt>"); |
|
2434 |
marked.replace("</@extra>", "</tt>"); |
|
2435 |
} |
|
2436 |
||
2437 |
if (style != CodeMarker::Detailed) { |
|
2438 |
marked.replace("<@type>", ""); |
|
2439 |
marked.replace("</@type>", ""); |
|
2440 |
} |
|
2441 |
out() << highlightedCode(marked, marker, relative); |
|
2442 |
}*/ |
|
2443 |
||
2444 |
#ifdef QDOC_QML |
|
2445 |
void HtmlGenerator::generateQmlItem(const Node *node, |
|
2446 |
const Node *relative, |
|
2447 |
CodeMarker *marker, |
|
2448 |
bool summary) |
|
2449 |
{ |
|
2450 |
QString marked = marker->markedUpQmlItem(node,summary); |
|
2451 |
QRegExp templateTag("(<[^@>]*>)"); |
|
2452 |
if (marked.indexOf(templateTag) != -1) { |
|
2453 |
QString contents = protect(marked.mid(templateTag.pos(1), |
|
2454 |
templateTag.cap(1).length())); |
|
2455 |
marked.replace(templateTag.pos(1), templateTag.cap(1).length(), |
|
2456 |
contents); |
|
2457 |
} |
|
2458 |
marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), |
|
2459 |
"<i>\\1<sub>\\2</sub></i>"); |
|
2460 |
marked.replace("<@param>", "<i>"); |
|
2461 |
marked.replace("</@param>", "</i>"); |
|
2462 |
||
2463 |
if (summary) |
|
2464 |
marked.replace("@name>", "b>"); |
|
2465 |
||
2466 |
marked.replace("<@extra>", " <tt>"); |
|
2467 |
marked.replace("</@extra>", "</tt>"); |
|
2468 |
||
2469 |
if (summary) { |
|
2470 |
marked.replace("<@type>", ""); |
|
2471 |
marked.replace("</@type>", ""); |
|
2472 |
} |
|
2473 |
out() << highlightedCode(marked, marker, relative); |
|
2474 |
} |
|
2475 |
#endif |
|
2476 |
||
2477 |
void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */) |
|
2478 |
{ |
|
2479 |
QMap<const FakeNode *, QMap<QString, FakeNode *> > fakeNodeMap; |
|
2480 |
QMap<QString, const FakeNode *> groupTitlesMap; |
|
2481 |
QMap<QString, FakeNode *> uncategorizedNodeMap; |
|
2482 |
QRegExp singleDigit("\\b([0-9])\\b"); |
|
2483 |
||
2484 |
const NodeList children = myTree->root()->childNodes(); |
|
2485 |
foreach (Node *child, children) { |
|
2486 |
if (child->type() == Node::Fake && child != relative) { |
|
2487 |
FakeNode *fakeNode = static_cast<FakeNode *>(child); |
|
2488 |
||
2489 |
// Check whether the page is part of a group or is the group |
|
2490 |
// definition page. |
|
2491 |
QString group; |
|
2492 |
bool isGroupPage = false; |
|
2493 |
if (fakeNode->doc().metaCommandsUsed().contains("group")) { |
|
2494 |
group = fakeNode->doc().metaCommandArgs("group")[0]; |
|
2495 |
isGroupPage = true; |
|
2496 |
} |
|
2497 |
||
2498 |
// there are too many examples; they would clutter the list |
|
2499 |
if (fakeNode->subType() == Node::Example) |
|
2500 |
continue; |
|
2501 |
||
2502 |
// not interested either in individual (Qt Designer etc.) manual chapters |
|
2503 |
if (fakeNode->links().contains(Node::ContentsLink)) |
|
2504 |
continue; |
|
2505 |
||
2506 |
// Discard external nodes. |
|
2507 |
if (fakeNode->subType() == Node::ExternalPage) |
|
2508 |
continue; |
|
2509 |
||
2510 |
QString sortKey = fakeNode->fullTitle().toLower(); |
|
2511 |
if (sortKey.startsWith("the ")) |
|
2512 |
sortKey.remove(0, 4); |
|
2513 |
sortKey.replace(singleDigit, "0\\1"); |
|
2514 |
||
2515 |
if (!group.isEmpty()) { |
|
2516 |
if (isGroupPage) { |
|
2517 |
// If we encounter a group definition page, we add all |
|
2518 |
// the pages in that group to the list for that group. |
|
2519 |
foreach (Node *member, fakeNode->groupMembers()) { |
|
2520 |
if (member->type() != Node::Fake) |
|
2521 |
continue; |
|
2522 |
FakeNode *page = static_cast<FakeNode *>(member); |
|
2523 |
if (page) { |
|
2524 |
QString sortKey = page->fullTitle().toLower(); |
|
2525 |
if (sortKey.startsWith("the ")) |
|
2526 |
sortKey.remove(0, 4); |
|
2527 |
sortKey.replace(singleDigit, "0\\1"); |
|
2528 |
fakeNodeMap[const_cast<const FakeNode *>(fakeNode)].insert(sortKey, page); |
|
2529 |
groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode); |
|
2530 |
} |
|
2531 |
} |
|
2532 |
} |
|
2533 |
else if (!isGroupPage) { |
|
2534 |
// If we encounter a page that belongs to a group then |
|
2535 |
// we add that page to the list for that group. |
|
2536 |
const FakeNode *groupNode = static_cast<const FakeNode *>(myTree->root()->findNode(group, Node::Fake)); |
|
2537 |
if (groupNode) |
|
2538 |
fakeNodeMap[groupNode].insert(sortKey, fakeNode); |
|
2539 |
//else |
|
2540 |
// uncategorizedNodeMap.insert(sortKey, fakeNode); |
|
2541 |
}// else |
|
2542 |
// uncategorizedNodeMap.insert(sortKey, fakeNode); |
|
2543 |
}// else |
|
2544 |
// uncategorizedNodeMap.insert(sortKey, fakeNode); |
|
2545 |
} |
|
2546 |
} |
|
2547 |
||
2548 |
// We now list all the pages found that belong to groups. |
|
2549 |
// If only certain pages were found for a group, but the definition page |
|
2550 |
// for that group wasn't listed, the list of pages will be intentionally |
|
2551 |
// incomplete. However, if the group definition page was listed, all the |
|
2552 |
// pages in that group are listed for completeness. |
|
2553 |
||
2554 |
if (!fakeNodeMap.isEmpty()) { |
|
2555 |
foreach (const QString &groupTitle, groupTitlesMap.keys()) { |
|
2556 |
const FakeNode *groupNode = groupTitlesMap[groupTitle]; |
|
2557 |
out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg( |
|
2558 |
linkForNode(groupNode, relative)).arg( |
|
2559 |
protect(groupNode->fullTitle())); |
|
2560 |
||
2561 |
if (fakeNodeMap[groupNode].count() == 0) |
|
2562 |
continue; |
|
2563 |
||
2564 |
out() << "<ul>\n"; |
|
2565 |
||
2566 |
foreach (const FakeNode *fakeNode, fakeNodeMap[groupNode]) { |
|
2567 |
QString title = fakeNode->fullTitle(); |
|
2568 |
if (title.startsWith("The ")) |
|
2569 |
title.remove(0, 4); |
|
2570 |
out() << "<li><a href=\"" << linkForNode(fakeNode, relative) << "\">" |
|
2571 |
<< protect(title) << "</a></li>\n"; |
|
2572 |
} |
|
2573 |
out() << "</ul>\n"; |
|
2574 |
} |
|
2575 |
} |
|
2576 |
||
2577 |
if (!uncategorizedNodeMap.isEmpty()) { |
|
2578 |
out() << QString("<h3>Miscellaneous</h3>\n"); |
|
2579 |
out() << "<ul>\n"; |
|
2580 |
foreach (const FakeNode *fakeNode, uncategorizedNodeMap) { |
|
2581 |
QString title = fakeNode->fullTitle(); |
|
2582 |
if (title.startsWith("The ")) |
|
2583 |
title.remove(0, 4); |
|
2584 |
out() << "<li><a href=\"" << linkForNode(fakeNode, relative) << "\">" |
|
2585 |
<< protect(title) << "</a></li>\n"; |
|
2586 |
} |
|
2587 |
out() << "</ul>\n"; |
|
2588 |
} |
|
2589 |
} |
|
2590 |
||
2591 |
#ifdef QDOC_NAME_ALIGNMENT |
|
2592 |
void HtmlGenerator::generateSection(const NodeList& nl, |
|
2593 |
const Node *relative, |
|
2594 |
CodeMarker *marker, |
|
2595 |
CodeMarker::SynopsisStyle style) |
|
2596 |
{ |
|
2597 |
bool name_alignment = true; |
|
2598 |
if (!nl.isEmpty()) { |
|
2599 |
bool twoColumn = false; |
|
2600 |
if (style == CodeMarker::SeparateList) { |
|
2601 |
name_alignment = false; |
|
2602 |
twoColumn = (nl.count() >= 16); |
|
2603 |
} |
|
2604 |
else if (nl.first()->type() == Node::Property) { |
|
2605 |
twoColumn = (nl.count() >= 5); |
|
2606 |
name_alignment = false; |
|
2607 |
} |
|
2608 |
if (name_alignment) { |
|
2609 |
out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" " |
|
2610 |
<< "cellspacing=\"0\" width=\"100%\">\n"; |
|
2611 |
} |
|
2612 |
else { |
|
2613 |
if (twoColumn) |
|
2614 |
out() << "<p><table class=\"propsummary\" width=\"100%\" " |
|
2615 |
<< "border=\"0\" cellpadding=\"0\"" |
|
2616 |
<< " cellspacing=\"0\">\n" |
|
2617 |
<< "<tr><td width=\"45%\" valign=\"top\">"; |
|
2618 |
out() << "<ul>\n"; |
|
2619 |
} |
|
2620 |
||
2621 |
int i = 0; |
|
2622 |
NodeList::ConstIterator m = nl.begin(); |
|
2623 |
while (m != nl.end()) { |
|
2624 |
if ((*m)->access() == Node::Private) { |
|
2625 |
++m; |
|
2626 |
continue; |
|
2627 |
} |
|
2628 |
||
2629 |
if (name_alignment) { |
|
2630 |
out() << "<tr><td class=\"memItemLeft\" " |
|
2631 |
<< "align=\"right\" valign=\"top\">"; |
|
2632 |
} |
|
2633 |
else { |
|
2634 |
if (twoColumn && i == (int) (nl.count() + 1) / 2) |
|
2635 |
out() << "</ul></td><td valign=\"top\"><ul>\n"; |
|
2636 |
out() << "<li><div class=\"fn\">"; |
|
2637 |
} |
|
2638 |
||
2639 |
generateSynopsis(*m, relative, marker, style, name_alignment); |
|
2640 |
if (name_alignment) |
|
2641 |
out() << "</td></tr>\n"; |
|
2642 |
else |
|
2643 |
out() << "</div></li>\n"; |
|
2644 |
i++; |
|
2645 |
++m; |
|
2646 |
} |
|
2647 |
if (name_alignment) |
|
2648 |
out() << "</table>\n"; |
|
2649 |
else { |
|
2650 |
out() << "</ul>\n"; |
|
2651 |
if (twoColumn) |
|
2652 |
out() << "</td></tr>\n</table></p>\n"; |
|
2653 |
} |
|
2654 |
} |
|
2655 |
} |
|
2656 |
||
2657 |
void HtmlGenerator::generateSectionList(const Section& section, |
|
2658 |
const Node *relative, |
|
2659 |
CodeMarker *marker, |
|
2660 |
CodeMarker::SynopsisStyle style) |
|
2661 |
{ |
|
2662 |
bool name_alignment = true; |
|
2663 |
if (!section.members.isEmpty()) { |
|
2664 |
bool twoColumn = false; |
|
2665 |
if (style == CodeMarker::SeparateList) { |
|
2666 |
name_alignment = false; |
|
2667 |
twoColumn = (section.members.count() >= 16); |
|
2668 |
} |
|
2669 |
else if (section.members.first()->type() == Node::Property) { |
|
2670 |
twoColumn = (section.members.count() >= 5); |
|
2671 |
name_alignment = false; |
|
2672 |
} |
|
2673 |
if (name_alignment) { |
|
2674 |
out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" " |
|
2675 |
<< "cellspacing=\"0\" width=\"100%\">\n"; |
|
2676 |
} |
|
2677 |
else { |
|
2678 |
if (twoColumn) |
|
2679 |
out() << "<p><table class=\"propsummary\" width=\"100%\" " |
|
2680 |
<< "border=\"0\" cellpadding=\"0\"" |
|
2681 |
<< " cellspacing=\"0\">\n" |
|
2682 |
<< "<tr><td width=\"45%\" valign=\"top\">"; |
|
2683 |
out() << "<ul>\n"; |
|
2684 |
} |
|
2685 |
||
2686 |
int i = 0; |
|
2687 |
NodeList::ConstIterator m = section.members.begin(); |
|
2688 |
while (m != section.members.end()) { |
|
2689 |
if ((*m)->access() == Node::Private) { |
|
2690 |
++m; |
|
2691 |
continue; |
|
2692 |
} |
|
2693 |
||
2694 |
if (name_alignment) { |
|
2695 |
out() << "<tr><td class=\"memItemLeft\" " |
|
2696 |
<< "align=\"right\" valign=\"top\">"; |
|
2697 |
} |
|
2698 |
else { |
|
2699 |
if (twoColumn && i == (int) (section.members.count() + 1) / 2) |
|
2700 |
out() << "</ul></td><td valign=\"top\"><ul>\n"; |
|
2701 |
out() << "<li><div class=\"fn\">"; |
|
2702 |
} |
|
2703 |
||
2704 |
generateSynopsis(*m, relative, marker, style, name_alignment); |
|
2705 |
if (name_alignment) |
|
2706 |
out() << "</td></tr>\n"; |
|
2707 |
else |
|
2708 |
out() << "</div></li>\n"; |
|
2709 |
i++; |
|
2710 |
++m; |
|
2711 |
} |
|
2712 |
if (name_alignment) |
|
2713 |
out() << "</table>\n"; |
|
2714 |
else { |
|
2715 |
out() << "</ul>\n"; |
|
2716 |
if (twoColumn) |
|
2717 |
out() << "</td></tr>\n</table></p>\n"; |
|
2718 |
} |
|
2719 |
} |
|
2720 |
||
2721 |
if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { |
|
2722 |
out() << "<ul>\n"; |
|
2723 |
generateSectionInheritedList(section, relative, marker, name_alignment); |
|
2724 |
out() << "</ul>\n"; |
|
2725 |
} |
|
2726 |
} |
|
2727 |
||
2728 |
void HtmlGenerator::generateSectionInheritedList(const Section& section, |
|
2729 |
const Node *relative, |
|
2730 |
CodeMarker *marker, |
|
2731 |
bool nameAlignment) |
|
2732 |
{ |
|
2733 |
QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); |
|
2734 |
while (p != section.inherited.end()) { |
|
2735 |
if (nameAlignment) |
|
2736 |
out() << "<li><div bar=\"2\" class=\"fn\"></div>"; |
|
2737 |
else |
|
2738 |
out() << "<li><div class=\"fn\"></div>"; |
|
2739 |
out() << (*p).second << " "; |
|
2740 |
if ((*p).second == 1) { |
|
2741 |
out() << section.singularMember; |
|
2742 |
} |
|
2743 |
else { |
|
2744 |
out() << section.pluralMember; |
|
2745 |
} |
|
2746 |
out() << " inherited from <a href=\"" << fileName((*p).first) |
|
2747 |
<< "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">" |
|
2748 |
<< protect(marker->plainFullName((*p).first, relative)) |
|
2749 |
<< "</a></li>\n"; |
|
2750 |
++p; |
|
2751 |
} |
|
2752 |
} |
|
2753 |
||
2754 |
void HtmlGenerator::generateSynopsis(const Node *node, |
|
2755 |
const Node *relative, |
|
2756 |
CodeMarker *marker, |
|
2757 |
CodeMarker::SynopsisStyle style, |
|
2758 |
bool nameAlignment) |
|
2759 |
{ |
|
2760 |
QString marked = marker->markedUpSynopsis(node, relative, style); |
|
2761 |
QRegExp templateTag("(<[^@>]*>)"); |
|
2762 |
if (marked.indexOf(templateTag) != -1) { |
|
2763 |
QString contents = protect(marked.mid(templateTag.pos(1), |
|
2764 |
templateTag.cap(1).length())); |
|
2765 |
marked.replace(templateTag.pos(1), templateTag.cap(1).length(), |
|
2766 |
contents); |
|
2767 |
} |
|
2768 |
marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), |
|
2769 |
"<i>\\1<sub>\\2</sub></i>"); |
|
2770 |
marked.replace("<@param>", "<i>"); |
|
2771 |
marked.replace("</@param>", "</i>"); |
|
2772 |
||
2773 |
if (style == CodeMarker::Summary) { |
|
2774 |
marked.replace("<@name>", ""); // was "<b>" |
|
2775 |
marked.replace("</@name>", ""); // was "</b>" |
|
2776 |
} |
|
2777 |
||
2778 |
if (style == CodeMarker::SeparateList) { |
|
2779 |
QRegExp extraRegExp("<@extra>.*</@extra>"); |
|
2780 |
extraRegExp.setMinimal(true); |
|
2781 |
marked.replace(extraRegExp, ""); |
|
2782 |
} else { |
|
2783 |
marked.replace("<@extra>", " <tt>"); |
|
2784 |
marked.replace("</@extra>", "</tt>"); |
|
2785 |
} |
|
2786 |
||
2787 |
if (style != CodeMarker::Detailed) { |
|
2788 |
marked.replace("<@type>", ""); |
|
2789 |
marked.replace("</@type>", ""); |
|
2790 |
} |
|
2791 |
out() << highlightedCode(marked, marker, relative, style, nameAlignment); |
|
2792 |
} |
|
2793 |
||
2794 |
QString HtmlGenerator::highlightedCode(const QString& markedCode, |
|
2795 |
CodeMarker *marker, |
|
2796 |
const Node *relative, |
|
2797 |
CodeMarker::SynopsisStyle , |
|
2798 |
bool nameAlignment) |
|
2799 |
{ |
|
2800 |
QString src = markedCode; |
|
2801 |
QString html; |
|
2802 |
QStringRef arg; |
|
2803 |
QStringRef par1; |
|
2804 |
||
2805 |
const QChar charLangle = '<'; |
|
2806 |
const QChar charAt = '@'; |
|
2807 |
||
2808 |
// replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" |
|
2809 |
static const QString linkTag("link"); |
|
2810 |
bool done = false; |
|
2811 |
for (int i = 0, n = src.size(); i < n;) { |
|
2812 |
if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { |
|
2813 |
if (nameAlignment && !done) {// && (i != 0)) Why was this here? |
|
2814 |
html += "</td><td class=\"memItemRight\" valign=\"bottom\">"; |
|
2815 |
done = true; |
|
2816 |
} |
|
2817 |
i += 2; |
|
2818 |
if (parseArg(src, linkTag, &i, n, &arg, &par1)) { |
|
2819 |
html += "<b>"; |
|
2820 |
QString link = linkForNode( |
|
2821 |
CodeMarker::nodeForString(par1.toString()), relative); |
|
2822 |
addLink(link, arg, &html); |
|
2823 |
html += "</b>"; |
|
2824 |
} |
|
2825 |
else { |
|
2826 |
html += charLangle; |
|
2827 |
html += charAt; |
|
2828 |
} |
|
2829 |
} |
|
2830 |
else { |
|
2831 |
html += src.at(i++); |
|
2832 |
} |
|
2833 |
} |
|
2834 |
||
2835 |
||
2836 |
if (slow) { |
|
2837 |
// is this block ever used at all? |
|
2838 |
// replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" |
|
2839 |
src = html; |
|
2840 |
html = QString(); |
|
2841 |
static const QString funcTag("func"); |
|
2842 |
for (int i = 0, n = src.size(); i < n;) { |
|
2843 |
if (src.at(i) == charLangle && src.at(i + 1) == charAt) { |
|
2844 |
i += 2; |
|
2845 |
if (parseArg(src, funcTag, &i, n, &arg, &par1)) { |
|
2846 |
QString link = linkForNode( |
|
2847 |
marker->resolveTarget(par1.toString(), |
|
2848 |
myTree, |
|
2849 |
relative), |
|
2850 |
relative); |
|
2851 |
addLink(link, arg, &html); |
|
2852 |
par1 = QStringRef(); |
|
2853 |
} |
|
2854 |
else { |
|
2855 |
html += charLangle; |
|
2856 |
html += charAt; |
|
2857 |
} |
|
2858 |
} |
|
2859 |
else { |
|
2860 |
html += src.at(i++); |
|
2861 |
} |
|
2862 |
} |
|
2863 |
} |
|
2864 |
||
2865 |
// replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags |
|
2866 |
src = html; |
|
2867 |
html = QString(); |
|
2868 |
static const QString typeTags[] = { "type", "headerfile", "func" }; |
|
2869 |
for (int i = 0, n = src.size(); i < n;) { |
|
2870 |
if (src.at(i) == charLangle && src.at(i + 1) == charAt) { |
|
2871 |
i += 2; |
|
2872 |
bool handled = false; |
|
2873 |
for (int k = 0; k != 3; ++k) { |
|
2874 |
if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { |
|
2875 |
par1 = QStringRef(); |
|
2876 |
QString link = linkForNode( |
|
2877 |
marker->resolveTarget(arg.toString(), myTree, relative), |
|
2878 |
relative); |
|
2879 |
addLink(link, arg, &html); |
|
2880 |
handled = true; |
|
2881 |
break; |
|
2882 |
} |
|
2883 |
} |
|
2884 |
if (!handled) { |
|
2885 |
html += charLangle; |
|
2886 |
html += charAt; |
|
2887 |
} |
|
2888 |
} |
|
2889 |
else { |
|
2890 |
html += src.at(i++); |
|
2891 |
} |
|
2892 |
} |
|
2893 |
||
2894 |
// replace all |
|
2895 |
// "<@comment>" -> "<span class=\"comment\">"; |
|
2896 |
// "<@preprocessor>" -> "<span class=\"preprocessor\">"; |
|
2897 |
// "<@string>" -> "<span class=\"string\">"; |
|
2898 |
// "<@char>" -> "<span class=\"char\">"; |
|
2899 |
// "</@(?:comment|preprocessor|string|char)>" -> "</span>" |
|
2900 |
src = html; |
|
2901 |
html = QString(); |
|
2902 |
static const QString spanTags[] = { |
|
2903 |
"<@comment>", "<span class=\"comment\">", |
|
2904 |
"<@preprocessor>", "<span class=\"preprocessor\">", |
|
2905 |
"<@string>", "<span class=\"string\">", |
|
2906 |
"<@char>", "<span class=\"char\">", |
|
2907 |
"</@comment>", "</span>", |
|
2908 |
"</@preprocessor>","</span>", |
|
2909 |
"</@string>", "</span>", |
|
2910 |
"</@char>", "</span>" |
|
2911 |
// "<@char>", "<font color=blue>", |
|
2912 |
// "</@char>", "</font>", |
|
2913 |
// "<@func>", "<font color=green>", |
|
2914 |
// "</@func>", "</font>", |
|
2915 |
// "<@id>", "<i>", |
|
2916 |
// "</@id>", "</i>", |
|
2917 |
// "<@keyword>", "<b>", |
|
2918 |
// "</@keyword>", "</b>", |
|
2919 |
// "<@number>", "<font color=yellow>", |
|
2920 |
// "</@number>", "</font>", |
|
2921 |
// "<@op>", "<b>", |
|
2922 |
// "</@op>", "</b>", |
|
2923 |
// "<@param>", "<i>", |
|
2924 |
// "</@param>", "</i>", |
|
2925 |
// "<@string>", "<font color=green>", |
|
2926 |
// "</@string>", "</font>", |
|
2927 |
}; |
|
2928 |
for (int i = 0, n = src.size(); i < n;) { |
|
2929 |
if (src.at(i) == charLangle) { |
|
2930 |
bool handled = false; |
|
2931 |
for (int k = 0; k != 8; ++k) { |
|
2932 |
const QString & tag = spanTags[2 * k]; |
|
2933 |
if (tag == QStringRef(&src, i, tag.length())) { |
|
2934 |
html += spanTags[2 * k + 1]; |
|
2935 |
i += tag.length(); |
|
2936 |
handled = true; |
|
2937 |
break; |
|
2938 |
} |
|
2939 |
} |
|
2940 |
if (!handled) { |
|
2941 |
++i; |
|
2942 |
if (src.at(i) == charAt || |
|
2943 |
(src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) { |
|
2944 |
// drop 'our' unknown tags (the ones still containing '@') |
|
2945 |
while (i < n && src.at(i) != QLatin1Char('>')) |
|
2946 |
++i; |
|
2947 |
++i; |
|
2948 |
} |
|
2949 |
else { |
|
2950 |
// retain all others |
|
2951 |
html += charLangle; |
|
2952 |
} |
|
2953 |
} |
|
2954 |
} |
|
2955 |
else { |
|
2956 |
html += src.at(i); |
|
2957 |
++i; |
|
2958 |
} |
|
2959 |
} |
|
2960 |
||
2961 |
return html; |
|
2962 |
} |
|
2963 |
||
2964 |
#else |
|
2965 |
void HtmlGenerator::generateSectionList(const Section& section, |
|
2966 |
const Node *relative, |
|
2967 |
CodeMarker *marker, |
|
2968 |
CodeMarker::SynopsisStyle style) |
|
2969 |
{ |
|
2970 |
if (!section.members.isEmpty()) { |
|
2971 |
bool twoColumn = false; |
|
2972 |
if (style == CodeMarker::SeparateList) { |
|
2973 |
twoColumn = (section.members.count() >= 16); |
|
2974 |
} |
|
2975 |
else if (section.members.first()->type() == Node::Property) { |
|
2976 |
twoColumn = (section.members.count() >= 5); |
|
2977 |
} |
|
2978 |
if (twoColumn) |
|
2979 |
out() << "<p><table class=\"generic\" width=\"100%\" border=\"0\" " |
|
2980 |
<< "cellpadding=\"0\" cellspacing=\"0\">\n" |
|
2981 |
<< "<tr><td width=\"45%\" valign=\"top\">"; |
|
2982 |
out() << "<ul>\n"; |
|
2983 |
||
2984 |
int i = 0; |
|
2985 |
NodeList::ConstIterator m = section.members.begin(); |
|
2986 |
while (m != section.members.end()) { |
|
2987 |
if ((*m)->access() == Node::Private) { |
|
2988 |
++m; |
|
2989 |
continue; |
|
2990 |
} |
|
2991 |
||
2992 |
if (twoColumn && i == (int) (section.members.count() + 1) / 2) |
|
2993 |
out() << "</ul></td><td valign=\"top\"><ul>\n"; |
|
2994 |
||
2995 |
out() << "<li><div class=\"fn\"></div>"; |
|
2996 |
if (style == CodeMarker::Accessors) |
|
2997 |
out() << "<b>"; |
|
2998 |
generateSynopsis(*m, relative, marker, style); |
|
2999 |
if (style == CodeMarker::Accessors) |
|
3000 |
out() << "</b>"; |
|
3001 |
out() << "</li>\n"; |
|
3002 |
i++; |
|
3003 |
++m; |
|
3004 |
} |
|
3005 |
out() << "</ul>\n"; |
|
3006 |
if (twoColumn) |
|
3007 |
out() << "</td></tr>\n</table></p>\n"; |
|
3008 |
} |
|
3009 |
||
3010 |
if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { |
|
3011 |
out() << "<ul>\n"; |
|
3012 |
generateSectionInheritedList(section, relative, marker); |
|
3013 |
out() << "</ul>\n"; |
|
3014 |
} |
|
3015 |
} |
|
3016 |
||
3017 |
void HtmlGenerator::generateSectionInheritedList(const Section& section, |
|
3018 |
const Node *relative, |
|
3019 |
CodeMarker *marker) |
|
3020 |
{ |
|
3021 |
QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); |
|
3022 |
while (p != section.inherited.end()) { |
|
3023 |
out() << "<li><div bar=\"2\" class=\"fn\"></div>"; |
|
3024 |
out() << (*p).second << " "; |
|
3025 |
if ((*p).second == 1) { |
|
3026 |
out() << section.singularMember; |
|
3027 |
} else { |
|
3028 |
out() << section.pluralMember; |
|
3029 |
} |
|
3030 |
out() << " inherited from <a href=\"" << fileName((*p).first) |
|
3031 |
<< "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">" |
|
3032 |
<< protect(marker->plainFullName((*p).first, relative)) |
|
3033 |
<< "</a></li>\n"; |
|
3034 |
++p; |
|
3035 |
} |
|
3036 |
} |
|
3037 |
||
3038 |
void HtmlGenerator::generateSynopsis(const Node *node, |
|
3039 |
const Node *relative, |
|
3040 |
CodeMarker *marker, |
|
3041 |
CodeMarker::SynopsisStyle style) |
|
3042 |
{ |
|
3043 |
QString marked = marker->markedUpSynopsis(node, relative, style); |
|
3044 |
QRegExp templateTag("(<[^@>]*>)"); |
|
3045 |
if (marked.indexOf(templateTag) != -1) { |
|
3046 |
QString contents = protect(marked.mid(templateTag.pos(1), |
|
3047 |
templateTag.cap(1).length())); |
|
3048 |
marked.replace(templateTag.pos(1), templateTag.cap(1).length(), |
|
3049 |
contents); |
|
3050 |
} |
|
3051 |
marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>"); |
|
3052 |
marked.replace("<@param>", "<i>"); |
|
3053 |
marked.replace("</@param>", "</i>"); |
|
3054 |
||
3055 |
if (style == CodeMarker::Summary) |
|
3056 |
marked.replace("@name>", "b>"); |
|
3057 |
||
3058 |
if (style == CodeMarker::SeparateList) { |
|
3059 |
QRegExp extraRegExp("<@extra>.*</@extra>"); |
|
3060 |
extraRegExp.setMinimal(true); |
|
3061 |
marked.replace(extraRegExp, ""); |
|
3062 |
} else { |
|
3063 |
marked.replace("<@extra>", " <tt>"); |
|
3064 |
marked.replace("</@extra>", "</tt>"); |
|
3065 |
} |
|
3066 |
||
3067 |
if (style != CodeMarker::Detailed) { |
|
3068 |
marked.replace("<@type>", ""); |
|
3069 |
marked.replace("</@type>", ""); |
|
3070 |
} |
|
3071 |
out() << highlightedCode(marked, marker, relative); |
|
3072 |
} |
|
3073 |
||
3074 |
QString HtmlGenerator::highlightedCode(const QString& markedCode, |
|
3075 |
CodeMarker *marker, |
|
3076 |
const Node *relative) |
|
3077 |
{ |
|
3078 |
QString src = markedCode; |
|
3079 |
QString html; |
|
3080 |
QStringRef arg; |
|
3081 |
QStringRef par1; |
|
3082 |
||
3083 |
const QChar charLangle = '<'; |
|
3084 |
const QChar charAt = '@'; |
|
3085 |
||
3086 |
// replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" |
|
3087 |
static const QString linkTag("link"); |
|
3088 |
for (int i = 0, n = src.size(); i < n;) { |
|
3089 |
if (src.at(i) == charLangle && src.at(i + 1) == charAt) { |
|
3090 |
i += 2; |
|
3091 |
if (parseArg(src, linkTag, &i, n, &arg, &par1)) { |
|
3092 |
const Node* node = CodeMarker::nodeForString(par1.toString()); |
|
3093 |
QString link = linkForNode(node, relative); |
|
3094 |
addLink(link, arg, &html); |
|
3095 |
} |
|
3096 |
else { |
|
3097 |
html += charLangle; |
|
3098 |
html += charAt; |
|
3099 |
} |
|
3100 |
} |
|
3101 |
else { |
|
3102 |
html += src.at(i++); |
|
3103 |
} |
|
3104 |
} |
|
3105 |
||
3106 |
if (slow) { |
|
3107 |
// is this block ever used at all? |
|
3108 |
// replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" |
|
3109 |
src = html; |
|
3110 |
html = QString(); |
|
3111 |
static const QString funcTag("func"); |
|
3112 |
for (int i = 0, n = src.size(); i < n;) { |
|
3113 |
if (src.at(i) == charLangle && src.at(i + 1) == charAt) { |
|
3114 |
i += 2; |
|
3115 |
if (parseArg(src, funcTag, &i, n, &arg, &par1)) { |
|
3116 |
QString link = linkForNode( |
|
3117 |
marker->resolveTarget(par1.toString(), |
|
3118 |
myTree, |
|
3119 |
relative), |
|
3120 |
relative); |
|
3121 |
addLink(link, arg, &html); |
|
3122 |
par1 = QStringRef(); |
|
3123 |
} |
|
3124 |
else { |
|
3125 |
html += charLangle; |
|
3126 |
html += charAt; |
|
3127 |
} |
|
3128 |
} |
|
3129 |
else { |
|
3130 |
html += src.at(i++); |
|
3131 |
} |
|
3132 |
} |
|
3133 |
} |
|
3134 |
||
3135 |
// replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags |
|
3136 |
src = html; |
|
3137 |
html = QString(); |
|
3138 |
static const QString typeTags[] = { "type", "headerfile", "func" }; |
|
3139 |
for (int i = 0, n = src.size(); i < n;) { |
|
3140 |
if (src.at(i) == charLangle && src.at(i + 1) == charAt) { |
|
3141 |
i += 2; |
|
3142 |
bool handled = false; |
|
3143 |
for (int k = 0; k != 3; ++k) { |
|
3144 |
if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { |
|
3145 |
par1 = QStringRef(); |
|
3146 |
QString link = linkForNode( |
|
3147 |
marker->resolveTarget(arg.toString(), myTree, relative), |
|
3148 |
relative); |
|
3149 |
addLink(link, arg, &html); |
|
3150 |
handled = true; |
|
3151 |
break; |
|
3152 |
} |
|
3153 |
} |
|
3154 |
if (!handled) { |
|
3155 |
html += charLangle; |
|
3156 |
html += charAt; |
|
3157 |
} |
|
3158 |
} |
|
3159 |
else { |
|
3160 |
html += src.at(i++); |
|
3161 |
} |
|
3162 |
} |
|
3163 |
||
3164 |
// replace all |
|
3165 |
// "<@comment>" -> "<span class=\"comment\">"; |
|
3166 |
// "<@preprocessor>" -> "<span class=\"preprocessor\">"; |
|
3167 |
// "<@string>" -> "<span class=\"string\">"; |
|
3168 |
// "<@char>" -> "<span class=\"char\">"; |
|
3169 |
// "</@(?:comment|preprocessor|string|char)>" -> "</span>" |
|
3170 |
src = html; |
|
3171 |
html = QString(); |
|
3172 |
static const QString spanTags[] = { |
|
3173 |
"<@comment>", "<span class=\"comment\">", |
|
3174 |
"<@preprocessor>", "<span class=\"preprocessor\">", |
|
3175 |
"<@string>", "<span class=\"string\">", |
|
3176 |
"<@char>", "<span class=\"char\">", |
|
3177 |
"</@comment>", "</span>", |
|
3178 |
"</@preprocessor>","</span>", |
|
3179 |
"</@string>", "</span>", |
|
3180 |
"</@char>", "</span>" |
|
3181 |
// "<@char>", "<font color=blue>", |
|
3182 |
// "</@char>", "</font>", |
|
3183 |
// "<@func>", "<font color=green>", |
|
3184 |
// "</@func>", "</font>", |
|
3185 |
// "<@id>", "<i>", |
|
3186 |
// "</@id>", "</i>", |
|
3187 |
// "<@keyword>", "<b>", |
|
3188 |
// "</@keyword>", "</b>", |
|
3189 |
// "<@number>", "<font color=yellow>", |
|
3190 |
// "</@number>", "</font>", |
|
3191 |
// "<@op>", "<b>", |
|
3192 |
// "</@op>", "</b>", |
|
3193 |
// "<@param>", "<i>", |
|
3194 |
// "</@param>", "</i>", |
|
3195 |
// "<@string>", "<font color=green>", |
|
3196 |
// "</@string>", "</font>", |
|
3197 |
}; |
|
3198 |
for (int i = 0, n = src.size(); i < n;) { |
|
3199 |
if (src.at(i) == charLangle) { |
|
3200 |
bool handled = false; |
|
3201 |
for (int k = 0; k != 8; ++k) { |
|
3202 |
const QString & tag = spanTags[2 * k]; |
|
3203 |
if (tag == QStringRef(&src, i, tag.length())) { |
|
3204 |
html += spanTags[2 * k + 1]; |
|
3205 |
i += tag.length(); |
|
3206 |
handled = true; |
|
3207 |
break; |
|
3208 |
} |
|
3209 |
} |
|
3210 |
if (!handled) { |
|
3211 |
++i; |
|
3212 |
if (src.at(i) == charAt || |
|
3213 |
(src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) { |
|
3214 |
// drop 'our' unknown tags (the ones still containing '@') |
|
3215 |
while (i < n && src.at(i) != QLatin1Char('>')) |
|
3216 |
++i; |
|
3217 |
++i; |
|
3218 |
} |
|
3219 |
else { |
|
3220 |
// retain all others |
|
3221 |
html += charLangle; |
|
3222 |
} |
|
3223 |
} |
|
3224 |
} |
|
3225 |
else { |
|
3226 |
html += src.at(i); |
|
3227 |
++i; |
|
3228 |
} |
|
3229 |
} |
|
3230 |
||
3231 |
return html; |
|
3232 |
} |
|
3233 |
#endif |
|
3234 |
||
3235 |
void HtmlGenerator::generateLink(const Atom* atom, |
|
3236 |
const Node* /* relative */, |
|
3237 |
CodeMarker* marker) |
|
3238 |
{ |
|
3239 |
static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_"); |
|
3240 |
||
3241 |
if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) { |
|
3242 |
// hack for C++: move () outside of link |
|
3243 |
int k = funcLeftParen.pos(1); |
|
3244 |
out() << protect(atom->string().left(k)); |
|
3245 |
if (link.isEmpty()) { |
|
3246 |
if (showBrokenLinks) |
|
3247 |
out() << "</i>"; |
|
3248 |
} else { |
|
3249 |
out() << "</a>"; |
|
3250 |
} |
|
3251 |
inLink = false; |
|
3252 |
out() << protect(atom->string().mid(k)); |
|
3253 |
} else if (marker->recognizeLanguage("Java")) { |
|
3254 |
// hack for Java: remove () and use <tt> when appropriate |
|
3255 |
bool func = atom->string().endsWith("()"); |
|
3256 |
bool tt = (func || atom->string().contains(camelCase)); |
|
3257 |
if (tt) |
|
3258 |
out() << "<tt>"; |
|
3259 |
if (func) { |
|
3260 |
out() << protect(atom->string().left(atom->string().length() - 2)); |
|
3261 |
} else { |
|
3262 |
out() << protect(atom->string()); |
|
3263 |
} |
|
3264 |
out() << "</tt>"; |
|
3265 |
} else { |
|
3266 |
out() << protect(atom->string()); |
|
3267 |
} |
|
3268 |
} |
|
3269 |
||
3270 |
QString HtmlGenerator::cleanRef(const QString& ref) |
|
3271 |
{ |
|
3272 |
QString clean; |
|
3273 |
||
3274 |
if (ref.isEmpty()) |
|
3275 |
return clean; |
|
3276 |
||
3277 |
clean.reserve(ref.size() + 20); |
|
3278 |
const QChar c = ref[0]; |
|
3279 |
const uint u = c.unicode(); |
|
3280 |
||
3281 |
if ((u >= 'a' && u <= 'z') || |
|
3282 |
(u >= 'A' && u <= 'Z') || |
|
3283 |
(u >= '0' && u <= '9')) { |
|
3284 |
clean += c; |
|
3285 |
} else if (u == '~') { |
|
3286 |
clean += "dtor."; |
|
3287 |
} else if (u == '_') { |
|
3288 |
clean += "underscore."; |
|
3289 |
} else { |
|
3290 |
clean += "A"; |
|
3291 |
} |
|
3292 |
||
3293 |
for (int i = 1; i < (int) ref.length(); i++) { |
|
3294 |
const QChar c = ref[i]; |
|
3295 |
const uint u = c.unicode(); |
|
3296 |
if ((u >= 'a' && u <= 'z') || |
|
3297 |
(u >= 'A' && u <= 'Z') || |
|
3298 |
(u >= '0' && u <= '9') || u == '-' || |
|
3299 |
u == '_' || u == ':' || u == '.') { |
|
3300 |
clean += c; |
|
3301 |
} else if (c.isSpace()) { |
|
3302 |
clean += "-"; |
|
3303 |
} else if (u == '!') { |
|
3304 |
clean += "-not"; |
|
3305 |
} else if (u == '&') { |
|
3306 |
clean += "-and"; |
|
3307 |
} else if (u == '<') { |
|
3308 |
clean += "-lt"; |
|
3309 |
} else if (u == '=') { |
|
3310 |
clean += "-eq"; |
|
3311 |
} else if (u == '>') { |
|
3312 |
clean += "-gt"; |
|
3313 |
} else if (u == '#') { |
|
3314 |
clean += "#"; |
|
3315 |
} else { |
|
3316 |
clean += "-"; |
|
3317 |
clean += QString::number((int)u, 16); |
|
3318 |
} |
|
3319 |
} |
|
3320 |
return clean; |
|
3321 |
} |
|
3322 |
||
3323 |
QString HtmlGenerator::registerRef(const QString& ref) |
|
3324 |
{ |
|
3325 |
QString clean = HtmlGenerator::cleanRef(ref); |
|
3326 |
||
3327 |
for (;;) { |
|
3328 |
QString& prevRef = refMap[clean.toLower()]; |
|
3329 |
if (prevRef.isEmpty()) { |
|
3330 |
prevRef = ref; |
|
3331 |
break; |
|
3332 |
} else if (prevRef == ref) { |
|
3333 |
break; |
|
3334 |
} |
|
3335 |
clean += "x"; |
|
3336 |
} |
|
3337 |
return clean; |
|
3338 |
} |
|
3339 |
||
3340 |
QString HtmlGenerator::protect(const QString& string) |
|
3341 |
{ |
|
3342 |
#define APPEND(x) \ |
|
3343 |
if (html.isEmpty()) { \ |
|
3344 |
html = string; \ |
|
3345 |
html.truncate(i); \ |
|
3346 |
} \ |
|
3347 |
html += (x); |
|
3348 |
||
3349 |
QString html; |
|
3350 |
int n = string.length(); |
|
3351 |
||
3352 |
for (int i = 0; i < n; ++i) { |
|
3353 |
QChar ch = string.at(i); |
|
3354 |
||
3355 |
if (ch == QLatin1Char('&')) { |
|
3356 |
APPEND("&"); |
|
3357 |
} else if (ch == QLatin1Char('<')) { |
|
3358 |
APPEND("<"); |
|
3359 |
} else if (ch == QLatin1Char('>')) { |
|
3360 |
APPEND(">"); |
|
3361 |
} else if (ch == QLatin1Char('"')) { |
|
3362 |
APPEND("""); |
|
3363 |
} else if (ch.unicode() > 0x007F |
|
3364 |
|| (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/')) |
|
3365 |
|| (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) { |
|
3366 |
// we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator |
|
3367 |
APPEND("&#x"); |
|
3368 |
html += QString::number(ch.unicode(), 16); |
|
3369 |
html += QLatin1Char(';'); |
|
3370 |
} else { |
|
3371 |
if (!html.isEmpty()) |
|
3372 |
html += ch; |
|
3373 |
} |
|
3374 |
} |
|
3375 |
||
3376 |
if (!html.isEmpty()) |
|
3377 |
return html; |
|
3378 |
return string; |
|
3379 |
||
3380 |
#undef APPEND |
|
3381 |
} |
|
3382 |
||
3383 |
QString HtmlGenerator::fileBase(const Node *node) |
|
3384 |
{ |
|
3385 |
QString result; |
|
3386 |
||
3387 |
result = PageGenerator::fileBase(node); |
|
3388 |
||
3389 |
if (!node->isInnerNode()) { |
|
3390 |
switch (node->status()) { |
|
3391 |
case Node::Compat: |
|
3392 |
result += "-qt3"; |
|
3393 |
break; |
|
3394 |
case Node::Obsolete: |
|
3395 |
result += "-obsolete"; |
|
3396 |
break; |
|
3397 |
default: |
|
3398 |
; |
|
3399 |
} |
|
3400 |
} |
|
3401 |
return result; |
|
3402 |
} |
|
3403 |
||
3404 |
#if 0 |
|
3405 |
QString HtmlGenerator::fileBase(const Node *node, |
|
3406 |
const SectionIterator& section) |
|
3407 |
{ |
|
3408 |
QStringList::ConstIterator s = section.sectionNumber().end(); |
|
3409 |
QStringList::ConstIterator b = section.baseNameStack().end(); |
|
3410 |
||
3411 |
QString suffix; |
|
3412 |
QString base = fileBase(node); |
|
3413 |
||
3414 |
while (s != section.sectionNumber().begin()) { |
|
3415 |
--s; |
|
3416 |
--b; |
|
3417 |
if (!(*b).isEmpty()) { |
|
3418 |
base = *b; |
|
3419 |
break; |
|
3420 |
} |
|
3421 |
suffix.prepend("-" + *s); |
|
3422 |
} |
|
3423 |
return base + suffix; |
|
3424 |
} |
|
3425 |
#endif |
|
3426 |
||
3427 |
QString HtmlGenerator::fileName(const Node *node) |
|
3428 |
{ |
|
3429 |
if (node->type() == Node::Fake) { |
|
3430 |
if (static_cast<const FakeNode *>(node)->subType() == Node::ExternalPage) |
|
3431 |
return node->name(); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3432 |
if (static_cast<const FakeNode *>(node)->subType() == Node::Image) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3433 |
return node->name(); |
0 | 3434 |
} |
3435 |
return PageGenerator::fileName(node); |
|
3436 |
} |
|
3437 |
||
3438 |
QString HtmlGenerator::refForNode(const Node *node) |
|
3439 |
{ |
|
3440 |
const FunctionNode *func; |
|
3441 |
const TypedefNode *typedeffe; |
|
3442 |
QString ref; |
|
3443 |
||
3444 |
switch (node->type()) { |
|
3445 |
case Node::Namespace: |
|
3446 |
case Node::Class: |
|
3447 |
default: |
|
3448 |
break; |
|
3449 |
case Node::Enum: |
|
3450 |
ref = node->name() + "-enum"; |
|
3451 |
break; |
|
3452 |
case Node::Typedef: |
|
3453 |
typedeffe = static_cast<const TypedefNode *>(node); |
|
3454 |
if (typedeffe->associatedEnum()) { |
|
3455 |
return refForNode(typedeffe->associatedEnum()); |
|
3456 |
} |
|
3457 |
else { |
|
3458 |
ref = node->name() + "-typedef"; |
|
3459 |
} |
|
3460 |
break; |
|
3461 |
case Node::Function: |
|
3462 |
func = static_cast<const FunctionNode *>(node); |
|
3463 |
if (func->associatedProperty()) { |
|
3464 |
return refForNode(func->associatedProperty()); |
|
3465 |
} |
|
3466 |
else { |
|
3467 |
ref = func->name(); |
|
3468 |
if (func->overloadNumber() != 1) |
|
3469 |
ref += "-" + QString::number(func->overloadNumber()); |
|
3470 |
} |
|
3471 |
break; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3472 |
#ifdef QDOC_QML |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3473 |
case Node::Fake: |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3474 |
if (node->subType() != Node::QmlPropertyGroup) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3475 |
break; |
0 | 3476 |
case Node::QmlProperty: |
3477 |
#endif |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3478 |
case Node::Property: |
0 | 3479 |
ref = node->name() + "-prop"; |
3480 |
break; |
|
3481 |
#ifdef QDOC_QML |
|
3482 |
case Node::QmlSignal: |
|
3483 |
ref = node->name() + "-signal"; |
|
3484 |
break; |
|
3485 |
case Node::QmlMethod: |
|
3486 |
ref = node->name() + "-method"; |
|
3487 |
break; |
|
3488 |
#endif |
|
3489 |
case Node::Variable: |
|
3490 |
ref = node->name() + "-var"; |
|
3491 |
break; |
|
3492 |
case Node::Target: |
|
3493 |
return protect(node->name()); |
|
3494 |
} |
|
3495 |
return registerRef(ref); |
|
3496 |
} |
|
3497 |
||
3498 |
QString HtmlGenerator::linkForNode(const Node *node, const Node *relative) |
|
3499 |
{ |
|
3500 |
QString link; |
|
3501 |
QString fn; |
|
3502 |
QString ref; |
|
3503 |
||
3504 |
if (node == 0 || node == relative) |
|
3505 |
return QString(); |
|
3506 |
if (!node->url().isEmpty()) |
|
3507 |
return node->url(); |
|
3508 |
if (fileBase(node).isEmpty()) |
|
3509 |
return QString(); |
|
3510 |
if (node->access() == Node::Private) |
|
3511 |
return QString(); |
|
3512 |
||
3513 |
fn = fileName(node); |
|
3514 |
/* if (!node->url().isEmpty()) |
|
3515 |
return fn;*/ |
|
3516 |
#if 0 |
|
3517 |
// ### reintroduce this test, without breaking .dcf files |
|
3518 |
if (fn != outFileName()) |
|
3519 |
#endif |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3520 |
link += fn; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3521 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3522 |
if (!node->isInnerNode() || node->subType() == Node::QmlPropertyGroup) { |
0 | 3523 |
ref = refForNode(node); |
3524 |
if (relative && fn == fileName(relative) && ref == refForNode(relative)) |
|
3525 |
return QString(); |
|
3526 |
||
3527 |
link += "#"; |
|
3528 |
link += ref; |
|
3529 |
} |
|
3530 |
return link; |
|
3531 |
} |
|
3532 |
||
3533 |
QString HtmlGenerator::refForAtom(Atom *atom, const Node * /* node */) |
|
3534 |
{ |
|
3535 |
if (atom->type() == Atom::SectionLeft) { |
|
3536 |
return Doc::canonicalTitle(Text::sectionHeading(atom).toString()); |
|
3537 |
} |
|
3538 |
else if (atom->type() == Atom::Target) { |
|
3539 |
return Doc::canonicalTitle(atom->string()); |
|
3540 |
} |
|
3541 |
else { |
|
3542 |
return QString(); |
|
3543 |
} |
|
3544 |
} |
|
3545 |
||
3546 |
void HtmlGenerator::generateFullName(const Node *apparentNode, |
|
3547 |
const Node *relative, |
|
3548 |
CodeMarker *marker, |
|
3549 |
const Node *actualNode) |
|
3550 |
{ |
|
3551 |
if (actualNode == 0) |
|
3552 |
actualNode = apparentNode; |
|
3553 |
out() << "<a href=\"" << linkForNode(actualNode, relative); |
|
3554 |
if (true || relative == 0 || relative->status() != actualNode->status()) { |
|
3555 |
switch (actualNode->status()) { |
|
3556 |
case Node::Obsolete: |
|
3557 |
out() << "\" class=\"obsolete"; |
|
3558 |
break; |
|
3559 |
case Node::Compat: |
|
3560 |
out() << "\" class=\"compat"; |
|
3561 |
break; |
|
3562 |
default: |
|
3563 |
; |
|
3564 |
} |
|
3565 |
} |
|
3566 |
out() << "\">"; |
|
3567 |
out() << protect(fullName(apparentNode, relative, marker)); |
|
3568 |
out() << "</a>"; |
|
3569 |
} |
|
3570 |
||
3571 |
void HtmlGenerator::generateDetailedMember(const Node *node, |
|
3572 |
const InnerNode *relative, |
|
3573 |
CodeMarker *marker) |
|
3574 |
{ |
|
3575 |
const EnumNode *enume; |
|
3576 |
||
3577 |
generateMacRef(node, marker); |
|
3578 |
if (node->type() == Node::Enum |
|
3579 |
&& (enume = static_cast<const EnumNode *>(node))->flagsType()) { |
|
3580 |
generateMacRef(enume->flagsType(), marker); |
|
3581 |
out() << "<h3 class=\"flags\">"; |
|
3582 |
out() << "<a name=\"" + refForNode(node) + "\"></a>"; |
|
3583 |
generateSynopsis(enume, relative, marker, CodeMarker::Detailed); |
|
3584 |
out() << "<br />"; |
|
3585 |
generateSynopsis(enume->flagsType(), |
|
3586 |
relative, |
|
3587 |
marker, |
|
3588 |
CodeMarker::Detailed); |
|
3589 |
out() << "</h3>\n"; |
|
3590 |
} |
|
3591 |
else { |
|
3592 |
out() << "<h3 class=\"fn\">"; |
|
3593 |
out() << "<a name=\"" + refForNode(node) + "\"></a>"; |
|
3594 |
generateSynopsis(node, relative, marker, CodeMarker::Detailed); |
|
3595 |
out() << "</h3>\n"; |
|
3596 |
} |
|
3597 |
||
3598 |
generateStatus(node, marker); |
|
3599 |
generateBody(node, marker); |
|
3600 |
generateThreadSafeness(node, marker); |
|
3601 |
generateSince(node, marker); |
|
3602 |
||
3603 |
if (node->type() == Node::Property) { |
|
3604 |
const PropertyNode *property = static_cast<const PropertyNode *>(node); |
|
3605 |
Section section; |
|
3606 |
||
3607 |
section.members += property->getters(); |
|
3608 |
section.members += property->setters(); |
|
3609 |
section.members += property->resetters(); |
|
3610 |
||
3611 |
if (!section.members.isEmpty()) { |
|
3612 |
out() << "<p><b>Access functions:</b></p>\n"; |
|
3613 |
generateSectionList(section, node, marker, CodeMarker::Accessors); |
|
3614 |
} |
|
3615 |
||
3616 |
Section notifiers; |
|
3617 |
notifiers.members += property->notifiers(); |
|
3618 |
||
3619 |
if (!notifiers.members.isEmpty()) { |
|
3620 |
out() << "<p><b>Notifier signal:</b></p>\n"; |
|
3621 |
//out() << "<p>This signal is emitted when the property value is changed.</p>\n"; |
|
3622 |
generateSectionList(notifiers, node, marker, CodeMarker::Accessors); |
|
3623 |
} |
|
3624 |
} |
|
3625 |
else if (node->type() == Node::Enum) { |
|
3626 |
const EnumNode *enume = static_cast<const EnumNode *>(node); |
|
3627 |
if (enume->flagsType()) { |
|
3628 |
out() << "<p>The " << protect(enume->flagsType()->name()) |
|
3629 |
<< " type is a typedef for " |
|
3630 |
<< "<a href=\"qflags.html\">QFlags</a><" |
|
3631 |
<< protect(enume->name()) |
|
3632 |
<< ">. It stores an OR combination of " |
|
3633 |
<< protect(enume->name()) |
|
3634 |
<< " values.</p>\n"; |
|
3635 |
} |
|
3636 |
} |
|
3637 |
generateAlsoList(node, marker); |
|
3638 |
} |
|
3639 |
||
3640 |
void HtmlGenerator::findAllClasses(const InnerNode *node) |
|
3641 |
{ |
|
3642 |
NodeList::const_iterator c = node->childNodes().constBegin(); |
|
3643 |
while (c != node->childNodes().constEnd()) { |
|
3644 |
if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) { |
|
3645 |
if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) { |
|
3646 |
QString className = (*c)->name(); |
|
3647 |
if ((*c)->parent() && |
|
3648 |
(*c)->parent()->type() == Node::Namespace && |
|
3649 |
!(*c)->parent()->name().isEmpty()) |
|
3650 |
className = (*c)->parent()->name()+"::"+className; |
|
3651 |
||
3652 |
if (!(static_cast<const ClassNode *>(*c))->hideFromMainList()) { |
|
3653 |
if ((*c)->status() == Node::Compat) { |
|
3654 |
compatClasses.insert(className, *c); |
|
3655 |
} |
|
3656 |
else if ((*c)->status() == Node::Obsolete) { |
|
3657 |
obsoleteClasses.insert(className, *c); |
|
3658 |
} |
|
3659 |
else { |
|
3660 |
nonCompatClasses.insert(className, *c); |
|
3661 |
if ((*c)->status() == Node::Main) |
|
3662 |
mainClasses.insert(className, *c); |
|
3663 |
} |
|
3664 |
} |
|
3665 |
||
3666 |
QString moduleName = (*c)->moduleName(); |
|
3667 |
if (moduleName == "Qt3SupportLight") { |
|
3668 |
moduleClassMap[moduleName].insert((*c)->name(), *c); |
|
3669 |
moduleName = "Qt3Support"; |
|
3670 |
} |
|
3671 |
if (!moduleName.isEmpty()) |
|
3672 |
moduleClassMap[moduleName].insert((*c)->name(), *c); |
|
3673 |
||
3674 |
QString serviceName = |
|
3675 |
(static_cast<const ClassNode *>(*c))->serviceName(); |
|
3676 |
if (!serviceName.isEmpty()) |
|
3677 |
serviceClasses.insert(serviceName, *c); |
|
3678 |
} |
|
3679 |
else if ((*c)->isInnerNode()) { |
|
3680 |
findAllClasses(static_cast<InnerNode *>(*c)); |
|
3681 |
} |
|
3682 |
} |
|
3683 |
++c; |
|
3684 |
} |
|
3685 |
} |
|
3686 |
||
3687 |
/*! |
|
3688 |
For generating the "New Classes... in 4.6" section on the |
|
3689 |
What's New in 4.6" page. |
|
3690 |
*/ |
|
3691 |
void HtmlGenerator::findAllSince(const InnerNode *node) |
|
3692 |
{ |
|
3693 |
NodeList::const_iterator child = node->childNodes().constBegin(); |
|
3694 |
while (child != node->childNodes().constEnd()) { |
|
3695 |
QString sinceVersion = (*child)->since(); |
|
3696 |
if (((*child)->access() != Node::Private) && !sinceVersion.isEmpty()) { |
|
3697 |
NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceVersion); |
|
3698 |
if (nsmap == newSinceMaps.end()) |
|
3699 |
nsmap = newSinceMaps.insert(sinceVersion,NodeMultiMap()); |
|
3700 |
NewClassMaps::iterator ncmap = newClassMaps.find(sinceVersion); |
|
3701 |
if (ncmap == newClassMaps.end()) |
|
3702 |
ncmap = newClassMaps.insert(sinceVersion,NodeMap()); |
|
3703 |
||
3704 |
if ((*child)->type() == Node::Function) { |
|
3705 |
FunctionNode *func = static_cast<FunctionNode *>(*child); |
|
3706 |
if ((func->status() > Node::Obsolete) && |
|
3707 |
(func->metaness() != FunctionNode::Ctor) && |
|
3708 |
(func->metaness() != FunctionNode::Dtor)) { |
|
3709 |
nsmap.value().insert(func->name(),(*child)); |
|
3710 |
} |
|
3711 |
} |
|
3712 |
else if ((*child)->url().isEmpty()) { |
|
3713 |
if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) { |
|
3714 |
QString className = (*child)->name(); |
|
3715 |
if ((*child)->parent() && |
|
3716 |
(*child)->parent()->type() == Node::Namespace && |
|
3717 |
!(*child)->parent()->name().isEmpty()) |
|
3718 |
className = (*child)->parent()->name()+"::"+className; |
|
3719 |
nsmap.value().insert(className,(*child)); |
|
3720 |
ncmap.value().insert(className,(*child)); |
|
3721 |
} |
|
3722 |
} |
|
3723 |
else { |
|
3724 |
QString name = (*child)->name(); |
|
3725 |
if ((*child)->parent() && |
|
3726 |
(*child)->parent()->type() == Node::Namespace && |
|
3727 |
!(*child)->parent()->name().isEmpty()) |
|
3728 |
name = (*child)->parent()->name()+"::"+name; |
|
3729 |
nsmap.value().insert(name,(*child)); |
|
3730 |
} |
|
3731 |
if ((*child)->isInnerNode()) { |
|
3732 |
findAllSince(static_cast<InnerNode *>(*child)); |
|
3733 |
} |
|
3734 |
} |
|
3735 |
++child; |
|
3736 |
} |
|
3737 |
} |
|
3738 |
||
3739 |
#if 0 |
|
3740 |
const QRegExp versionSeparator("[\\-\\.]"); |
|
3741 |
const int minorIndex = version.indexOf(versionSeparator); |
|
3742 |
const int patchIndex = version.indexOf(versionSeparator, minorIndex+1); |
|
3743 |
version = version.left(patchIndex); |
|
3744 |
#endif |
|
3745 |
||
3746 |
void HtmlGenerator::findAllFunctions(const InnerNode *node) |
|
3747 |
{ |
|
3748 |
NodeList::ConstIterator c = node->childNodes().begin(); |
|
3749 |
while (c != node->childNodes().end()) { |
|
3750 |
if ((*c)->access() != Node::Private) { |
|
3751 |
if ((*c)->isInnerNode() && (*c)->url().isEmpty()) { |
|
3752 |
findAllFunctions(static_cast<const InnerNode *>(*c)); |
|
3753 |
} |
|
3754 |
else if ((*c)->type() == Node::Function) { |
|
3755 |
const FunctionNode *func = static_cast<const FunctionNode *>(*c); |
|
3756 |
if ((func->status() > Node::Obsolete) && |
|
3757 |
(func->metaness() != FunctionNode::Ctor) && |
|
3758 |
(func->metaness() != FunctionNode::Dtor)) { |
|
3759 |
funcIndex[(*c)->name()].insert(myTree->fullDocumentName((*c)->parent()), *c); |
|
3760 |
} |
|
3761 |
} |
|
3762 |
} |
|
3763 |
++c; |
|
3764 |
} |
|
3765 |
} |
|
3766 |
||
3767 |
void HtmlGenerator::findAllLegaleseTexts(const InnerNode *node) |
|
3768 |
{ |
|
3769 |
NodeList::ConstIterator c = node->childNodes().begin(); |
|
3770 |
while (c != node->childNodes().end()) { |
|
3771 |
if ((*c)->access() != Node::Private) { |
|
3772 |
if (!(*c)->doc().legaleseText().isEmpty()) |
|
3773 |
legaleseTexts.insertMulti((*c)->doc().legaleseText(), *c); |
|
3774 |
if ((*c)->isInnerNode()) |
|
3775 |
findAllLegaleseTexts(static_cast<const InnerNode *>(*c)); |
|
3776 |
} |
|
3777 |
++c; |
|
3778 |
} |
|
3779 |
} |
|
3780 |
||
3781 |
void HtmlGenerator::findAllNamespaces(const InnerNode *node) |
|
3782 |
{ |
|
3783 |
NodeList::ConstIterator c = node->childNodes().begin(); |
|
3784 |
while (c != node->childNodes().end()) { |
|
3785 |
if ((*c)->access() != Node::Private) { |
|
3786 |
if ((*c)->isInnerNode() && (*c)->url().isEmpty()) { |
|
3787 |
findAllNamespaces(static_cast<const InnerNode *>(*c)); |
|
3788 |
if ((*c)->type() == Node::Namespace) { |
|
3789 |
const NamespaceNode *nspace = static_cast<const NamespaceNode *>(*c); |
|
3790 |
// Ensure that the namespace's name is not empty (the root |
|
3791 |
// namespace has no name). |
|
3792 |
if (!nspace->name().isEmpty()) { |
|
3793 |
namespaceIndex.insert(nspace->name(), *c); |
|
3794 |
QString moduleName = (*c)->moduleName(); |
|
3795 |
if (moduleName == "Qt3SupportLight") { |
|
3796 |
moduleNamespaceMap[moduleName].insert((*c)->name(), *c); |
|
3797 |
moduleName = "Qt3Support"; |
|
3798 |
} |
|
3799 |
if (!moduleName.isEmpty()) |
|
3800 |
moduleNamespaceMap[moduleName].insert((*c)->name(), *c); |
|
3801 |
} |
|
3802 |
} |
|
3803 |
} |
|
3804 |
} |
|
3805 |
++c; |
|
3806 |
} |
|
3807 |
} |
|
3808 |
||
3809 |
#ifdef ZZZ_QDOC_QML |
|
3810 |
/*! |
|
3811 |
This function finds all the qml element nodes and |
|
3812 |
stores them in a map for later use. |
|
3813 |
*/ |
|
3814 |
void HtmlGenerator::findAllQmlClasses(const InnerNode *node) |
|
3815 |
{ |
|
3816 |
NodeList::const_iterator c = node->childNodes().constBegin(); |
|
3817 |
while (c != node->childNodes().constEnd()) { |
|
3818 |
if ((*c)->type() == Node::Fake) { |
|
3819 |
const FakeNode* fakeNode = static_cast<const FakeNode *>(*c); |
|
3820 |
if (fakeNode->subType() == Node::QmlClass) { |
|
3821 |
const QmlClassNode* qmlNode = |
|
3822 |
static_cast<const QmlClassNode*>(fakeNode); |
|
3823 |
const Node* n = qmlNode->classNode(); |
|
3824 |
} |
|
3825 |
qmlClasses.insert(fakeNode->name(),*c); |
|
3826 |
} |
|
3827 |
++c; |
|
3828 |
} |
|
3829 |
} |
|
3830 |
#endif |
|
3831 |
||
3832 |
int HtmlGenerator::hOffset(const Node *node) |
|
3833 |
{ |
|
3834 |
switch (node->type()) { |
|
3835 |
case Node::Namespace: |
|
3836 |
case Node::Class: |
|
3837 |
return 2; |
|
3838 |
case Node::Fake: |
|
3839 |
if (node->doc().briefText().isEmpty()) |
|
3840 |
return 1; |
|
3841 |
else |
|
3842 |
return 2; |
|
3843 |
case Node::Enum: |
|
3844 |
case Node::Typedef: |
|
3845 |
case Node::Function: |
|
3846 |
case Node::Property: |
|
3847 |
default: |
|
3848 |
return 3; |
|
3849 |
} |
|
3850 |
} |
|
3851 |
||
3852 |
bool HtmlGenerator::isThreeColumnEnumValueTable(const Atom *atom) |
|
3853 |
{ |
|
3854 |
while (atom != 0 && !(atom->type() == Atom::ListRight && atom->string() == ATOM_LIST_VALUE)) { |
|
3855 |
if (atom->type() == Atom::ListItemLeft && !matchAhead(atom, Atom::ListItemRight)) |
|
3856 |
return true; |
|
3857 |
atom = atom->next(); |
|
3858 |
} |
|
3859 |
return false; |
|
3860 |
} |
|
3861 |
||
3862 |
const Node *HtmlGenerator::findNodeForTarget(const QString &target, |
|
3863 |
const Node *relative, |
|
3864 |
CodeMarker *marker, |
|
3865 |
const Atom *atom) |
|
3866 |
{ |
|
3867 |
const Node *node = 0; |
|
3868 |
||
3869 |
if (target.isEmpty()) { |
|
3870 |
node = relative; |
|
3871 |
} |
|
3872 |
else if (target.endsWith(".html")) { |
|
3873 |
node = myTree->root()->findNode(target, Node::Fake); |
|
3874 |
} |
|
3875 |
else if (marker) { |
|
3876 |
node = marker->resolveTarget(target, myTree, relative); |
|
3877 |
if (!node) |
|
3878 |
node = myTree->findFakeNodeByTitle(target); |
|
3879 |
if (!node && atom) { |
|
3880 |
node = myTree->findUnambiguousTarget(target, |
|
3881 |
*const_cast<Atom**>(&atom)); |
|
3882 |
} |
|
3883 |
} |
|
3884 |
||
3885 |
if (!node) |
|
3886 |
relative->doc().location().warning(tr("Cannot link to '%1'").arg(target)); |
|
3887 |
||
3888 |
return node; |
|
3889 |
} |
|
3890 |
||
3891 |
const QPair<QString,QString> HtmlGenerator::anchorForNode(const Node *node) |
|
3892 |
{ |
|
3893 |
QPair<QString,QString> anchorPair; |
|
3894 |
||
3895 |
anchorPair.first = PageGenerator::fileName(node); |
|
3896 |
if (node->type() == Node::Fake) { |
|
3897 |
const FakeNode *fakeNode = static_cast<const FakeNode*>(node); |
|
3898 |
anchorPair.second = fakeNode->title(); |
|
3899 |
} |
|
3900 |
||
3901 |
return anchorPair; |
|
3902 |
} |
|
3903 |
||
3904 |
QString HtmlGenerator::getLink(const Atom *atom, |
|
3905 |
const Node *relative, |
|
3906 |
CodeMarker *marker, |
|
3907 |
const Node** node) |
|
3908 |
{ |
|
3909 |
QString link; |
|
3910 |
*node = 0; |
|
3911 |
inObsoleteLink = false; |
|
3912 |
||
3913 |
if (atom->string().contains(":") && |
|
3914 |
(atom->string().startsWith("file:") |
|
3915 |
|| atom->string().startsWith("http:") |
|
3916 |
|| atom->string().startsWith("https:") |
|
3917 |
|| atom->string().startsWith("ftp:") |
|
3918 |
|| atom->string().startsWith("mailto:"))) { |
|
3919 |
||
3920 |
link = atom->string(); |
|
3921 |
} |
|
3922 |
else { |
|
3923 |
QStringList path; |
|
3924 |
if (atom->string().contains('#')) { |
|
3925 |
path = atom->string().split('#'); |
|
3926 |
} |
|
3927 |
else { |
|
3928 |
path.append(atom->string()); |
|
3929 |
} |
|
3930 |
||
3931 |
Atom *targetAtom = 0; |
|
3932 |
||
3933 |
QString first = path.first().trimmed(); |
|
3934 |
if (first.isEmpty()) { |
|
3935 |
*node = relative; |
|
3936 |
} |
|
3937 |
else if (first.endsWith(".html")) { |
|
3938 |
*node = myTree->root()->findNode(first, Node::Fake); |
|
3939 |
} |
|
3940 |
else { |
|
3941 |
*node = marker->resolveTarget(first, myTree, relative); |
|
3942 |
if (!*node) |
|
3943 |
*node = myTree->findFakeNodeByTitle(first); |
|
3944 |
if (!*node) |
|
3945 |
*node = myTree->findUnambiguousTarget(first, targetAtom); |
|
3946 |
} |
|
3947 |
||
3948 |
if (*node) { |
|
3949 |
if (!(*node)->url().isEmpty()) |
|
3950 |
return (*node)->url(); |
|
3951 |
else |
|
3952 |
path.removeFirst(); |
|
3953 |
} |
|
3954 |
else { |
|
3955 |
*node = relative; |
|
3956 |
} |
|
3957 |
||
3958 |
if (*node) { |
|
3959 |
if ((*node)->status() == Node::Obsolete) { |
|
3960 |
if (relative) { |
|
3961 |
if (relative->parent() != *node) { |
|
3962 |
if (relative->status() != Node::Obsolete) { |
|
3963 |
bool porting = false; |
|
3964 |
if (relative->type() == Node::Fake) { |
|
3965 |
const FakeNode* fake = static_cast<const FakeNode*>(relative); |
|
3966 |
if (fake->title().startsWith("Porting")) |
|
3967 |
porting = true; |
|
3968 |
} |
|
3969 |
QString name = marker->plainFullName(relative); |
|
3970 |
if (!porting && !name.startsWith("Q3")) { |
|
3971 |
if (obsoleteLinks) { |
|
3972 |
relative->doc().location().warning(tr("Link to obsolete item '%1' in %2") |
|
3973 |
.arg(atom->string()) |
|
3974 |
.arg(name)); |
|
3975 |
} |
|
3976 |
inObsoleteLink = true; |
|
3977 |
} |
|
3978 |
} |
|
3979 |
} |
|
3980 |
} |
|
3981 |
else { |
|
3982 |
qDebug() << "Link to Obsolete entity" |
|
3983 |
<< (*node)->name() << "no relative"; |
|
3984 |
} |
|
3985 |
} |
|
3986 |
#if 0 |
|
3987 |
else if ((*node)->status() == Node::Deprecated) { |
|
3988 |
qDebug() << "Link to Deprecated entity"; |
|
3989 |
} |
|
3990 |
else if ((*node)->status() == Node::Internal) { |
|
3991 |
qDebug() << "Link to Internal entity"; |
|
3992 |
} |
|
3993 |
#endif |
|
3994 |
} |
|
3995 |
||
3996 |
while (!path.isEmpty()) { |
|
3997 |
targetAtom = myTree->findTarget(path.first(), *node); |
|
3998 |
if (targetAtom == 0) |
|
3999 |
break; |
|
4000 |
path.removeFirst(); |
|
4001 |
} |
|
4002 |
||
4003 |
if (path.isEmpty()) { |
|
4004 |
link = linkForNode(*node, relative); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4005 |
if (*node && (*node)->subType() == Node::Image) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4006 |
link = "images/used-in-examples/" + link; |
0 | 4007 |
if (targetAtom) |
4008 |
link += "#" + refForAtom(targetAtom, *node); |
|
4009 |
} |
|
4010 |
} |
|
4011 |
return link; |
|
4012 |
} |
|
4013 |
||
4014 |
void HtmlGenerator::generateDcf(const QString &fileBase, |
|
4015 |
const QString &startPage, |
|
4016 |
const QString &title, |
|
4017 |
DcfSection &dcfRoot) |
|
4018 |
{ |
|
4019 |
dcfRoot.ref = startPage; |
|
4020 |
dcfRoot.title = title; |
|
4021 |
generateDcfSections(dcfRoot, outputDir() + "/" + fileBase + ".dcf", fileBase + "/reference"); |
|
4022 |
} |
|
4023 |
||
4024 |
void HtmlGenerator::generateIndex(const QString &fileBase, |
|
4025 |
const QString &url, |
|
4026 |
const QString &title) |
|
4027 |
{ |
|
4028 |
myTree->generateIndex(outputDir() + "/" + fileBase + ".index", url, title); |
|
4029 |
} |
|
4030 |
||
4031 |
void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker) |
|
4032 |
{ |
|
4033 |
Text text; |
|
4034 |
||
4035 |
switch (node->status()) { |
|
4036 |
case Node::Obsolete: |
|
4037 |
if (node->isInnerNode()) |
|
4038 |
Generator::generateStatus(node, marker); |
|
4039 |
break; |
|
4040 |
case Node::Compat: |
|
4041 |
if (node->isInnerNode()) { |
|
4042 |
text << Atom::ParaLeft |
|
4043 |
<< Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) |
|
4044 |
<< "This " |
|
4045 |
<< typeString(node) |
|
4046 |
<< " is part of the Qt 3 support library." |
|
4047 |
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) |
|
4048 |
<< " It is provided to keep old source code working. " |
|
4049 |
<< "We strongly advise against " |
|
4050 |
<< "using it in new code. See "; |
|
4051 |
||
4052 |
const FakeNode *fakeNode = myTree->findFakeNodeByTitle("Porting To Qt 4"); |
|
4053 |
Atom *targetAtom = 0; |
|
4054 |
if (fakeNode && node->type() == Node::Class) { |
|
4055 |
QString oldName(node->name()); |
|
4056 |
targetAtom = myTree->findTarget(oldName.replace("3", ""), |
|
4057 |
fakeNode); |
|
4058 |
} |
|
4059 |
||
4060 |
if (targetAtom) { |
|
4061 |
text << Atom(Atom::Link, linkForNode(fakeNode, node) + "#" + |
|
4062 |
refForAtom(targetAtom, fakeNode)); |
|
4063 |
} |
|
4064 |
else |
|
4065 |
text << Atom(Atom::Link, "Porting to Qt 4"); |
|
4066 |
||
4067 |
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) |
|
4068 |
<< Atom(Atom::String, "Porting to Qt 4") |
|
4069 |
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) |
|
4070 |
<< " for more information." |
|
4071 |
<< Atom::ParaRight; |
|
4072 |
} |
|
4073 |
generateText(text, node, marker); |
|
4074 |
break; |
|
4075 |
default: |
|
4076 |
Generator::generateStatus(node, marker); |
|
4077 |
} |
|
4078 |
} |
|
4079 |
||
4080 |
void HtmlGenerator::generateMacRef(const Node *node, CodeMarker *marker) |
|
4081 |
{ |
|
4082 |
if (!pleaseGenerateMacRef || marker == 0) |
|
4083 |
return; |
|
4084 |
||
4085 |
QStringList macRefs = marker->macRefsForNode(node); |
|
4086 |
foreach (const QString &macRef, macRefs) |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4087 |
out() << "<a name=\"" << "//apple_ref/" << macRef << "\"></a>\n"; |
0 | 4088 |
} |
4089 |
||
4090 |
void HtmlGenerator::beginLink(const QString &link, |
|
4091 |
const Node *node, |
|
4092 |
const Node *relative, |
|
4093 |
CodeMarker *marker) |
|
4094 |
{ |
|
4095 |
Q_UNUSED(marker) |
|
4096 |
Q_UNUSED(relative) |
|
4097 |
||
4098 |
this->link = link; |
|
4099 |
if (link.isEmpty()) { |
|
4100 |
if (showBrokenLinks) |
|
4101 |
out() << "<i>"; |
|
4102 |
} |
|
4103 |
else if (node == 0 || (relative != 0 && |
|
4104 |
node->status() == relative->status())) { |
|
4105 |
out() << "<a href=\"" << link << "\">"; |
|
4106 |
} |
|
4107 |
else { |
|
4108 |
switch (node->status()) { |
|
4109 |
case Node::Obsolete: |
|
4110 |
out() << "<a href=\"" << link << "\" class=\"obsolete\">"; |
|
4111 |
break; |
|
4112 |
case Node::Compat: |
|
4113 |
out() << "<a href=\"" << link << "\" class=\"compat\">"; |
|
4114 |
break; |
|
4115 |
default: |
|
4116 |
out() << "<a href=\"" << link << "\">"; |
|
4117 |
} |
|
4118 |
} |
|
4119 |
inLink = true; |
|
4120 |
} |
|
4121 |
||
4122 |
void HtmlGenerator::endLink() |
|
4123 |
{ |
|
4124 |
if (inLink) { |
|
4125 |
if (link.isEmpty()) { |
|
4126 |
if (showBrokenLinks) |
|
4127 |
out() << "</i>"; |
|
4128 |
} |
|
4129 |
else { |
|
4130 |
if (inObsoleteLink) { |
|
4131 |
out() << "<sup>(obsolete)</sup>"; |
|
4132 |
} |
|
4133 |
out() << "</a>"; |
|
4134 |
} |
|
4135 |
} |
|
4136 |
inLink = false; |
|
4137 |
inObsoleteLink = false; |
|
4138 |
} |
|
4139 |
||
4140 |
QT_END_NAMESPACE |
|
4141 |
||
4142 |
#ifdef QDOC_QML |
|
4143 |
||
4144 |
/*! |
|
4145 |
Generates the summary for for the \a section. Only used for |
|
4146 |
sections of QML element documentation. |
|
4147 |
||
4148 |
Currently handles only the QML property group. |
|
4149 |
*/ |
|
4150 |
void HtmlGenerator::generateQmlSummary(const Section& section, |
|
4151 |
const Node *relative, |
|
4152 |
CodeMarker *marker) |
|
4153 |
{ |
|
4154 |
if (!section.members.isEmpty()) { |
|
4155 |
NodeList::ConstIterator m; |
|
4156 |
int count = section.members.size(); |
|
4157 |
bool twoColumn = false; |
|
4158 |
if (section.members.first()->type() == Node::QmlProperty) { |
|
4159 |
twoColumn = (count >= 5); |
|
4160 |
} |
|
4161 |
if (twoColumn) |
|
4162 |
out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\"" |
|
4163 |
" cellspacing=\"0\">\n" |
|
4164 |
<< "<tr><td width=\"45%\" valign=\"top\">"; |
|
4165 |
out() << "<ul>\n"; |
|
4166 |
||
4167 |
int row = 0; |
|
4168 |
m = section.members.begin(); |
|
4169 |
while (m != section.members.end()) { |
|
4170 |
if (twoColumn && row == (int) (count + 1) / 2) |
|
4171 |
out() << "</ul></td><td valign=\"top\"><ul>\n"; |
|
4172 |
out() << "<li><div class=\"fn\"></div>"; |
|
4173 |
generateQmlItem(*m,relative,marker,true); |
|
4174 |
out() << "</li>\n"; |
|
4175 |
row++; |
|
4176 |
++m; |
|
4177 |
} |
|
4178 |
out() << "</ul>\n"; |
|
4179 |
if (twoColumn) |
|
4180 |
out() << "</td></tr>\n</table></p>\n"; |
|
4181 |
} |
|
4182 |
} |
|
4183 |
||
4184 |
/*! |
|
4185 |
Outputs the html detailed documentation for a section |
|
4186 |
on a QML element reference page. |
|
4187 |
*/ |
|
4188 |
void HtmlGenerator::generateDetailedQmlMember(const Node *node, |
|
4189 |
const InnerNode *relative, |
|
4190 |
CodeMarker *marker) |
|
4191 |
{ |
|
4192 |
const QmlPropertyNode* qpn = 0; |
|
4193 |
generateMacRef(node, marker); |
|
4194 |
out() << "<div class=\"qmlitem\">"; |
|
4195 |
if (node->subType() == Node::QmlPropertyGroup) { |
|
4196 |
const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node); |
|
4197 |
NodeList::ConstIterator p = qpgn->childNodes().begin(); |
|
4198 |
out() << "<div class=\"qmlproto\">"; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4199 |
out() << "<table width=\"100%\" class=\"qmlname\">"; |
0 | 4200 |
|
4201 |
while (p != qpgn->childNodes().end()) { |
|
4202 |
if ((*p)->type() == Node::QmlProperty) { |
|
4203 |
qpn = static_cast<const QmlPropertyNode*>(*p); |
|
4204 |
out() << "<tr><td>"; |
|
4205 |
out() << "<a name=\"" + refForNode(qpn) + "\"></a>"; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4206 |
if (!qpn->isWritable()) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4207 |
out() << "<span class=\"qmlreadonly\">read-only</span>"; |
0 | 4208 |
generateQmlItem(qpn, relative, marker, false); |
4209 |
out() << "</td></tr>"; |
|
4210 |
if (qpgn->isDefault()) { |
|
4211 |
out() << "</table>" |
|
4212 |
<< "</div></div>" |
|
4213 |
<< "<div class=\"qmlitem\">" |
|
4214 |
<< "<div class=\"qmlproto\">" |
|
4215 |
<< "<table class=\"qmlname\">" |
|
4216 |
<< "<tr><td><font color=\"green\">" |
|
4217 |
<< "default</font></td></tr>"; |
|
4218 |
} |
|
4219 |
} |
|
4220 |
++p; |
|
4221 |
} |
|
4222 |
out() << "</table>"; |
|
4223 |
out() << "</div>"; |
|
4224 |
} |
|
4225 |
else if (node->type() == Node::QmlSignal) { |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4226 |
const FunctionNode* qsn = static_cast<const FunctionNode*>(node); |
0 | 4227 |
out() << "<div class=\"qmlproto\">"; |
4228 |
out() << "<table class=\"qmlname\">"; |
|
4229 |
out() << "<tr><td>"; |
|
4230 |
out() << "<a name=\"" + refForNode(qsn) + "\"></a>"; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4231 |
generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4232 |
//generateQmlItem(qsn,relative,marker,false); |
0 | 4233 |
out() << "</td></tr>"; |
4234 |
out() << "</table>"; |
|
4235 |
out() << "</div>"; |
|
4236 |
} |
|
4237 |
else if (node->type() == Node::QmlMethod) { |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4238 |
const FunctionNode* qmn = static_cast<const FunctionNode*>(node); |
0 | 4239 |
out() << "<div class=\"qmlproto\">"; |
4240 |
out() << "<table class=\"qmlname\">"; |
|
4241 |
out() << "<tr><td>"; |
|
4242 |
out() << "<a name=\"" + refForNode(qmn) + "\"></a>"; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4243 |
generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false); |
0 | 4244 |
out() << "</td></tr>"; |
4245 |
out() << "</table>"; |
|
4246 |
out() << "</div>"; |
|
4247 |
} |
|
4248 |
out() << "<div class=\"qmldoc\">"; |
|
4249 |
generateStatus(node, marker); |
|
4250 |
generateBody(node, marker); |
|
4251 |
generateThreadSafeness(node, marker); |
|
4252 |
generateSince(node, marker); |
|
4253 |
generateAlsoList(node, marker); |
|
4254 |
out() << "</div>"; |
|
4255 |
out() << "</div>"; |
|
4256 |
} |
|
4257 |
||
4258 |
/*! |
|
4259 |
Output the "Inherits" line for the QML element, |
|
4260 |
if there should be one. |
|
4261 |
*/ |
|
4262 |
void HtmlGenerator::generateQmlInherits(const QmlClassNode* cn, |
|
4263 |
CodeMarker* marker) |
|
4264 |
{ |
|
4265 |
if (cn && !cn->links().empty()) { |
|
4266 |
if (cn->links().contains(Node::InheritsLink)) { |
|
4267 |
QPair<QString,QString> linkPair; |
|
4268 |
linkPair = cn->links()[Node::InheritsLink]; |
|
4269 |
QStringList strList(linkPair.first); |
|
4270 |
const Node* n = myTree->findNode(strList,Node::Fake); |
|
4271 |
if (n && n->subType() == Node::QmlClass) { |
|
4272 |
const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n); |
|
4273 |
out() << "<p style=\"text-align: center\">"; |
|
4274 |
Text text; |
|
4275 |
text << "[Inherits "; |
|
4276 |
text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); |
|
4277 |
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); |
|
4278 |
text << Atom(Atom::String, linkPair.second); |
|
4279 |
text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); |
|
4280 |
text << "]"; |
|
4281 |
generateText(text, cn, marker); |
|
4282 |
out() << "</p>"; |
|
4283 |
} |
|
4284 |
} |
|
4285 |
} |
|
4286 |
} |
|
4287 |
||
4288 |
/*! |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4289 |
Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]" |
0 | 4290 |
line for the QML element, if there should be one. |
4291 |
||
4292 |
If there is no class node, or if the class node status |
|
4293 |
is set to Node::Internal, do nothing. |
|
4294 |
*/ |
|
4295 |
void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, |
|
4296 |
CodeMarker* marker) |
|
4297 |
{ |
|
4298 |
const ClassNode* cn = qcn->classNode(); |
|
4299 |
if (cn && (cn->status() != Node::Internal)) { |
|
4300 |
out() << "<p style=\"text-align: center\">"; |
|
4301 |
Text text; |
|
4302 |
text << "["; |
|
4303 |
text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); |
|
4304 |
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); |
|
4305 |
text << Atom(Atom::String, qcn->name()); |
|
4306 |
text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); |
|
4307 |
text << " instantiates the C++ class "; |
|
4308 |
text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); |
|
4309 |
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); |
|
4310 |
text << Atom(Atom::String, cn->name()); |
|
4311 |
text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); |
|
4312 |
text << "]"; |
|
4313 |
generateText(text, qcn, marker); |
|
4314 |
out() << "</p>"; |
|
4315 |
} |
|
4316 |
} |
|
4317 |
||
4318 |
/*! |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
4319 |
Output the "[QmlGraphicsXxx is instantiated by QML element Xxx]" |
0 | 4320 |
line for the class, if there should be one. |
4321 |
||
4322 |
If there is no QML element, or if the class node status |
|
4323 |
is set to Node::Internal, do nothing. |
|
4324 |
*/ |
|
4325 |
void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, |
|
4326 |
CodeMarker* marker) |
|
4327 |
{ |
|
4328 |
if (cn && cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) { |
|
4329 |
const Node* n = myTree->root()->findNode(cn->qmlElement(),Node::Fake); |
|
4330 |
if (n && n->subType() == Node::QmlClass) { |
|
4331 |
out() << "<p style=\"text-align: center\">"; |
|
4332 |
Text text; |
|
4333 |
text << "["; |
|
4334 |
text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); |
|
4335 |
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); |
|
4336 |
text << Atom(Atom::String, cn->name()); |
|
4337 |
text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); |
|
4338 |
text << " is instantiated by QML element "; |
|
4339 |
text << Atom(Atom::LinkNode,CodeMarker::stringForNode(n)); |
|
4340 |
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); |
|
4341 |
text << Atom(Atom::String, n->name()); |
|
4342 |
text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); |
|
4343 |
text << "]"; |
|
4344 |
generateText(text, cn, marker); |
|
4345 |
out() << "</p>"; |
|
4346 |
} |
|
4347 |
} |
|
4348 |
} |
|
4349 |
||
4350 |
#endif |