source: trunk/tools/qdoc3/ditaxmlgenerator.cpp@ 1054

Last change on this file since 1054 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 195.5 KB
Line 
1
2/****************************************************************************
3**
4** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5** All rights reserved.
6** Contact: Nokia Corporation ([email protected])
7**
8** This file is part of the tools applications of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial Usage
12** Licensees holding valid Qt Commercial licenses may use this file in
13** accordance with the Qt Commercial License Agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and Nokia.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Nokia gives you certain additional
26** rights. These rights are described in the Nokia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37** If you have questions regarding the use of this file, please contact
38** Nokia at [email protected].
39** $QT_END_LICENSE$
40**
41****************************************************************************/
42
43/*
44 ditaxmlgenerator.cpp
45*/
46
47#include "codemarker.h"
48#include "codeparser.h"
49#include "ditaxmlgenerator.h"
50#include "node.h"
51#include "separator.h"
52#include "tree.h"
53#include <ctype.h>
54#include <qdebug.h>
55#include <qlist.h>
56#include <qiterator.h>
57#include <qtextcodec.h>
58#include <QUuid>
59
60QT_BEGIN_NAMESPACE
61
62#define COMMAND_VERSION Doc::alias("version")
63int DitaXmlGenerator::id = 0;
64
65#define cxxapi_d_xref Doc::alias("cxxapi-d-xref")
66#define cxxclass Doc::alias("cxxclass")
67#define cxxdefine Doc::alias("cxxdefine")
68#define cxxenumeration Doc::alias("cxxenumeration")
69#define cxxfile Doc::alias("cxxfile")
70#define cxxfunction Doc::alias("cxxfunction")
71#define cxxstruct Doc::alias("cxxstruct")
72#define cxxtypedef Doc::alias("cxxtypedef")
73#define cxxunion Doc::alias("cxxunion")
74#define cxxvariable Doc::alias("cxxvariable")
75
76#define CXXAPIMAP Doc::alias("cxxAPIMap")
77#define CXXCLASSREF Doc::alias("cxxClassRef")
78#define CXXDEFINEREF Doc::alias("cxxDefineRef")
79#define CXXENUMERATIONREF Doc::alias("cxxEnumerationRef")
80#define CXXFILEREF Doc::alias("cxxFileRef")
81#define CXXFUNCTIONREF Doc::alias("cxxFunctionRef")
82#define CXXSTRUCTREF Doc::alias("cxxStructRef")
83#define CXXTYPDEFREF Doc::alias("cxxTypedefRef")
84#define CXXUNIONREF Doc::alias("cxxUnionRef")
85#define CXXVARIABLEREF Doc::alias("cxxVariableRef")
86
87#define CXXCLASS Doc::alias("cxxClass")
88#define CXXCLASSABSTRACT Doc::alias("cxxClassAbstract")
89#define CXXCLASSACCESSSPECIFIER Doc::alias("cxxClassAccessSpecifier")
90#define CXXCLASSAPIITEMLOCATION Doc::alias("cxxClassAPIItemLocation")
91#define CXXCLASSBASECLASS Doc::alias("cxxClassBaseClass")
92#define CXXCLASSBASECLASSSTRUCT Doc::alias("cxxClassBaseStruct")
93#define CXXCLASSBASEUNION Doc::alias("cxxClassBaseUnion")
94#define CXXCLASSDECLARATIONFILE Doc::alias("cxxClassDeclarationFile")
95#define CXXCLASSDECLARATIONFILELINE Doc::alias("cxxClassDeclarationFileLine")
96#define CXXCLASSDEFINITION Doc::alias("cxxClassDefinition")
97#define CXXCLASSDEFINITIONFILE Doc::alias("cxxClassDefinitionFile")
98#define CXXCLASSDEFINITIONFILEEND Doc::alias("cxxClassDefinitionFileLineEnd")
99#define CXXCLASSDEFINITIONFILESTART Doc::alias("cxxClassDefinitionFileLineStart")
100#define CXXCLASSDERIVATION Doc::alias("cxxClassDerivation")
101#define CXXCLASSDERIVATIONACCESSSPECIFIER Doc::alias("cxxClassDerivationAccessSpecifier")
102#define CXXCLASSDERIVATIONS Doc::alias("cxxClassDerivations")
103#define CXXCLASSDERIVATIONVIRTUAL Doc::alias("cxxClassDerivationVirtual")
104#define CXXCLASSDETAIL Doc::alias("cxxClassDetail")
105#define CXXCLASSENUMERATIONINHERITED Doc::alias("cxxClassEnumerationInherited")
106#define CXXCLASSENUMERATORINHERITED Doc::alias("cxxClassEnumeratorInherited")
107#define CXXCLASSFUNCTIONINHERITED Doc::alias("cxxClassFunctionInherited")
108#define CXXCLASSINHERITS Doc::alias("cxxClassInherits")
109#define CXXCLASSINHERITSDETAIL Doc::alias("cxxClassInheritsDetail")
110#define CXXCLASSNESTED Doc::alias("cxxClassNested")
111#define CXXCLASSNESTEDCLASS Doc::alias("cxxClassNestedClass")
112#define CXXCLASSNESTEDDETAIL Doc::alias("cxxClassNestedDetail")
113#define CXXCLASSNESTEDSTRUCT Doc::alias("cxxClassNestedStruct")
114#define CXXCLASSNESTEDUNION Doc::alias("cxxClassNestedUnion")
115#define CXXCLASSTEMPLATEPARAMETER Doc::alias("cxxClassTemplateParameter")
116#define CXXCLASSTEMPLATEPARAMETERS Doc::alias("cxxClassTemplateParameters")
117#define CXXCLASSTEMPLATEPARAMETERTYPE Doc::alias("cxxClassTemplateParameterType")
118#define CXXCLASSVARIABLEINHERITED Doc::alias("cxxClassVariableInherited")
119
120#define CXXDEFINE Doc::alias("cxxDefine")
121#define CXXDEFINEACCESSSPECIFIER Doc::alias("cxxDefineAccessSpecifier")
122#define CXXDEFINEAPIITEMLOCATION Doc::alias("cxxDefineAPIItemLocation")
123#define CXXDEFINEDECLARATIONFILE Doc::alias("cxxDefineDeclarationFile")
124#define CXXDEFINEDECLARATIONFILELINE Doc::alias("cxxDefineDeclarationFileLine")
125#define CXXDEFINEDEFINITION Doc::alias("cxxDefineDefinition")
126#define CXXDEFINEDETAIL Doc::alias("cxxDefineDetail")
127#define CXXDEFINENAMELOOKUP Doc::alias("cxxDefineNameLookup")
128#define CXXDEFINEPARAMETER Doc::alias("cxxDefineParameter")
129#define CXXDEFINEPARAMETERDECLARATIONNAME Doc::alias("cxxDefineParameterDeclarationName")
130#define CXXDEFINEPARAMETERS Doc::alias("cxxDefineParameters")
131#define CXXDEFINEPROTOTYPE Doc::alias("cxxDefinePrototype")
132#define CXXDEFINEREIMPLEMENTED Doc::alias("cxxDefineReimplemented")
133
134#define CXXENUMERATION Doc::alias("cxxEnumeration")
135#define CXXENUMERATIONACCESSSPECIFIER Doc::alias("cxxEnumerationAccessSpecifier")
136#define CXXENUMERATIONAPIITEMLOCATION Doc::alias("cxxEnumerationAPIItemLocation")
137#define CXXENUMERATIONDECLARATIONFILE Doc::alias("cxxEnumerationDeclarationFile")
138#define CXXENUMERATIONDECLARATIONFILELINE Doc::alias("cxxEnumerationDeclarationFileLine")
139#define CXXENUMERATIONDEFINITION Doc::alias("cxxEnumerationDefinition")
140#define CXXENUMERATIONDEFINITIONFILE Doc::alias("cxxEnumerationDefinitionFile")
141#define CXXENUMERATIONDEFINITIONFILELINEEND Doc::alias("cxxEnumerationDefinitionFileLineEnd")
142#define CXXENUMERATIONDEFINITIONFILELINESTART Doc::alias("cxxEnumerationDefinitionFileLineStart")
143#define CXXENUMERATIONDETAIL Doc::alias("cxxEnumerationDetail")
144#define CXXENUMERATIONNAMELOOKUP Doc::alias("cxxEnumerationNameLookup")
145#define CXXENUMERATIONPROTOTYPE Doc::alias("cxxEnumerationPrototype")
146#define CXXENUMERATIONREIMPLEMENTED Doc::alias("cxxEnumerationReimplemented")
147#define CXXENUMERATIONSCOPEDNAME Doc::alias("cxxEnumerationScopedName")
148#define CXXENUMERATOR Doc::alias("cxxEnumerator")
149#define CXXENUMERATORAPIITEMLOCATION Doc::alias("cxxEnumeratorAPIItemLocation")
150#define CXXENUMERATORDECLARATIONFILE Doc::alias("cxxEnumeratorDeclarationFile")
151#define CXXENUMERATORDECLARATIONFILELINE Doc::alias("cxxEnumeratorDeclarationFileLine")
152#define CXXENUMERATORINITIALISER Doc::alias("cxxEnumeratorInitialiser")
153#define CXXENUMERATORNAMELOOKUP Doc::alias("cxxEnumeratorNameLookup")
154#define CXXENUMERATORPROTOTYPE Doc::alias("cxxEnumeratorPrototype")
155#define CXXENUMERATORS Doc::alias("cxxEnumerators")
156#define CXXENUMERATORSCOPEDNAME Doc::alias("cxxEnumeratorScopedName")
157
158#define CXXFILE_INFO_TYPES Doc::alias("cxxFile-info-types")
159#define CXXFILE_TYPES_DEFAULT Doc::alias("cxxFile-types-default")
160#define CXXFILE Doc::alias("cxxFile")
161#define CXXFILEAPIITMELOCATION Doc::alias("cxxFileAPIItemLocation")
162#define CXXFILEDECLARATIONFILE Doc::alias("cxxFileDeclarationFile")
163
164#define CXXFUNCTION Doc::alias("cxxFunction")
165#define CXXFUNCTIONACCESSSPECIFIER Doc::alias("cxxFunctionAccessSpecifier")
166#define CXXFUNCTIONAPIITEMLOCATION Doc::alias("cxxFunctionAPIItemLocation")
167#define CXXFUNCTIONCONST Doc::alias("cxxFunctionConst")
168#define CXXFUNCTIONCONSTRUCTOR Doc::alias("cxxFunctionConstructor")
169#define CXXFUNCTIONDECLARATIONFILE Doc::alias("cxxFunctionDeclarationFile")
170#define CXXFUNCTIONDECLARATIONFILELINE Doc::alias("cxxFunctionDeclarationFileLine")
171#define CXXFUNCTIONDECLAREDTYPE Doc::alias("cxxFunctionDeclaredType")
172#define CXXFUNCTIONDEFINITION Doc::alias("cxxFunctionDefinition")
173#define CXXFUNCTIONDEFINITIONFILE Doc::alias("cxxFunctionDefinitionFile")
174#define CXXFUNCTIONDEFINITIONFILELINEEND Doc::alias("cxxFunctionDefinitionFileLineEnd")
175#define CXXFUNCTIONDEFINITIONFILELINESTART Doc::alias("cxxFunctionDefinitionFileLineStart")
176#define CXXFUNCTIONDESTRUCTOR Doc::alias("cxxFunctionDestructor")
177#define CXXFUNCTIONDETAIL Doc::alias("cxxFunctionDetail")
178#define CXXFUNCTIONEXPLICIT Doc::alias("cxxFunctionExplicit")
179#define CXXFUNCTIONINLINE Doc::alias("cxxFunctionInline")
180#define CXXFUNCTIONNAMELOOKUP Doc::alias("cxxFunctionNameLookup")
181#define CXXFUNCTIONPARAMETER Doc::alias("cxxFunctionParameter")
182#define CXXFUNCTIONPARAMETERDECLARATIONNAME Doc::alias("cxxFunctionParameterDeclarationName")
183#define CXXFUNCTIONPARAMETERDECLAREDTYPE Doc::alias("cxxFunctionParameterDeclaredType")
184#define CXXFUNCTIONPARAMETERDEFAULTVALUE Doc::alias("cxxFunctionParameterDefaultValue")
185#define CXXFUNCTIONPARAMETERDEFINITIONNAME Doc::alias("cxxFunctionParameterDefinitionName")
186#define CXXFUNCTIONPARAMETERS Doc::alias("cxxFunctionParameters")
187#define CXXFUNCTIONPROTOTYPE Doc::alias("cxxFunctionPrototype")
188#define CXXFUNCTIONPUREVIRTUAL Doc::alias("cxxFunctionPureVirtual")
189#define CXXFUNCTIONREIMPLEMENTED Doc::alias("cxxFunctionReimplemented")
190#define CXXFUNCTIONRETURNTYPE Doc::alias("cxxFunctionReturnType")
191#define CXXFUNCTIONSCOPEDNAME Doc::alias("cxxFunctionScopedName")
192#define CXXFUNCTIONSTORAGECLASSSPECIFIEREXTERN Doc::alias("cxxFunctionStorageClassSpecifierExtern")
193#define CXXFUNCTIONSTORAGECLASSSPECIFIERMUTABLE Doc::alias("cxxFunctionStorageClassSpecifierMutable")
194#define CXXFUNCTIONSTORAGECLASSSPECIFIERSTATIC Doc::alias("cxxFunctionStorageClassSpecifierStatic")
195#define CXXFUNCTIONTEMPLATEPARAMETER Doc::alias("cxxFunctionTemplateParameter")
196#define CXXFUNCTIONTEMPLATEPARAMETERS Doc::alias("cxxFunctionTemplateParameters")
197#define CXXFUNCTIONTEMPLATEPARAMETERTYPE Doc::alias("cxxFunctionTemplateParameterType")
198#define CXXFUNCTIONVIRTUAL Doc::alias("cxxFunctionVirtual")
199#define CXXFUNCTIONVOLATILE Doc::alias("cxxFunctionVolatile")
200
201#define CXXSTRUCT Doc::alias("cxxStruct")
202#define CXXSTRUCTABSTRACT Doc::alias("cxxStructAbstract")
203#define CXXSTRUCTACCESSSPECIFIER Doc::alias("cxxStructAccessSpecifier")
204#define CXXSTRUCTAPIITEMLOCATION Doc::alias("cxxStructAPIItemLocation")
205#define CXXSTRUCTBASECLASS Doc::alias("cxxStructBaseClass")
206#define CXXSTRUCTBASESTRUCT Doc::alias("cxxStructBaseStruct")
207#define CXXSTRUCTBASEUNION Doc::alias("cxxStructBaseUnion")
208#define CXXSTRUCTDECLARATIONFILE Doc::alias("cxxStructDeclarationFile")
209#define CXXSTRUCTDECLARATIONFILELINE Doc::alias("cxxStructDeclarationFileLine")
210#define CXXSTRUCTDEFINITION Doc::alias("cxxStructDefinition")
211#define CXXSTRUCTDEFINITIONFILE Doc::alias("cxxStructDefinitionFile")
212#define CXXSTRUCTDEFINITIONFILELINEEND Doc::alias("cxxStructDefinitionFileLineEnd")
213#define CXXSTRUCTDEFINITIONFILELINESTART Doc::alias("cxxStructDefinitionFileLineStart")
214#define CXXSTRUCTDERIVATION Doc::alias("cxxStructDerivation")
215#define CXXSTRUCTDERIVATIONACCESSSPECIFIER Doc::alias("cxxStructDerivationAccessSpecifier")
216#define CXXSTRUCTDERIVATIONS Doc::alias("cxxStructDerivations")
217#define CXXSTRUCTDERIVATIONVIRTUAL Doc::alias("cxxStructDerivationVirtual")
218#define CXXSTRUCTDETAIL Doc::alias("cxxStructDetail")
219#define CXXSTRUCTENUMERATIONINHERITED Doc::alias("cxxStructEnumerationInherited")
220#define CXXSTRUCTENUMERATORINHERITED Doc::alias("cxxStructEnumeratorInherited")
221#define CXXSTRUCTFUNCTIONINHERITED Doc::alias("cxxStructFunctionInherited")
222#define CXXSTRUCTINHERITS Doc::alias("cxxStructInherits")
223#define CXXSTRUCTINHERITSDETAIL Doc::alias("cxxStructInheritsDetail")
224#define CXXSTRUCTNESTED Doc::alias("cxxStructNested")
225#define CXXSTRUCTNESTEDCLASS Doc::alias("cxxStructNestedClass")
226#define CXXSTRUCTNESTEDDETAIL Doc::alias("cxxStructNestedDetail")
227#define CXXSTRUCTNESTEDSTRUCT Doc::alias("cxxStructNestedStruct")
228#define CXXSTRUCTNESTEDUNION Doc::alias("cxxStructNestedUnion")
229#define CXXSTRUCTTEMPLATEPARAMETER Doc::alias("cxxStructTemplateParameter")
230#define CXXSTRUCTTEMPLATEPARAMETERS Doc::alias("cxxStructTemplateParameters")
231#define CXXSTRUCTTEMPLATEPARAMETERTYPE Doc::alias("cxxStructTemplateParameterType")
232#define CXXSTRUCTVARIABLEINHERITED Doc::alias("cxxStructVariableInherited")
233
234#define CXXTYPEDEF Doc::alias("cxxTypedef")
235#define CXXTYPEDEFACCESSSPECIFIER Doc::alias("cxxTypedefAccessSpecifier")
236#define CXXTYPEDEFAPIITEMLOCATION Doc::alias("cxxTypedefAPIItemLocation")
237#define CXXTYPEDEFDECLARATIONFILE Doc::alias("cxxTypedefDeclarationFile")
238#define CXXTYPEDEFDECLARATIONFILELINE Doc::alias("cxxTypedefDeclarationFileLine")
239#define CXXTYPEDEFDECLAREDTYPE Doc::alias("cxxTypedefDeclaredType")
240#define CXXTYPEDEFDEFINITION Doc::alias("cxxTypedefDefinition")
241#define CXXTYPEDEFDETAIL Doc::alias("cxxTypedefDetail")
242#define CXXTYPEDEFNAMELOOKUP Doc::alias("cxxTypedefNameLookup")
243#define CXXTYPEDEFPROTOTYPE Doc::alias("cxxTypedefPrototype")
244#define CXXTYPEDEFREIMPLEMENTED Doc::alias("cxxTypedefReimplemented")
245#define CXXTYPEDEFSCOPEDNAME Doc::alias("cxxTypedefScopedName")
246
247#define CXXUNION Doc::alias("cxxUnion")
248#define CXXUNIONABSTRACT Doc::alias("cxxUnionAbstract")
249#define CXXUNIONACCESSSPECIFIER Doc::alias("cxxUnionAccessSpecifier")
250#define CXXUNIONAPIITEMLOCATION Doc::alias("cxxUnionAPIItemLocation")
251#define CXXUNIONDECLARATIONFILE Doc::alias("cxxUnionDeclarationFile")
252#define CXXUNIONDECLARATIONFILELINE Doc::alias("cxxUnionDeclarationFileLine")
253#define CXXUNIONDEFINITION Doc::alias("cxxUnionDefinition")
254#define CXXUNIONDEFINITIONFILE Doc::alias("cxxUnionDefinitionFile")
255#define CXXUNIONDEFINITIONFILELINEEND Doc::alias("cxxUnionDefinitionFileLineEnd")
256#define CXXUNIONDEFINITIONFILELINESTART Doc::alias("cxxUnionDefinitionFileLineStart")
257#define CXXUNIONDETAIL Doc::alias("cxxUnionDetail")
258#define CXXUNIONNESTED Doc::alias("cxxUnionNested")
259#define CXXUNIONNESTEDCLASS Doc::alias("cxxUnionNestedClass")
260#define CXXUNIONNESTEDDETAIL Doc::alias("cxxUnionNestedDetail")
261#define CXXUNIONNESTEDSTRUCT Doc::alias("cxxUnionNestedStruct")
262#define CXXUNIONNESTEDUNION Doc::alias("cxxUnionNestedUnion")
263#define CXXUNIONTEMPLATEPARAMETER Doc::alias("cxxUnionTemplateParameter")
264#define CXXUNIONTEMPLATEPARAMETERS Doc::alias("cxxUnionTemplateParameters")
265#define CXXUNIONTEMPLATEPARAMETERTYPE Doc::alias("cxxUnionTemplateParameterType")
266
267#define CXXVARIABLE Doc::alias("cxxVariable")
268#define CXXVARIABLEACCESSSPECIFIER Doc::alias("cxxVariableAccessSpecifier")
269#define CXXVARIABLEAPIITEMLOCATION Doc::alias("cxxVariableAPIItemLocation")
270#define CXXVARIABLECONST Doc::alias("cxxVariableConst")
271#define CXXVARIABLEDECLARATIONFILE Doc::alias("cxxVariableDeclarationFile")
272#define CXXVARIABLEDECLARATIONFILELINE Doc::alias("cxxVariableDeclarationFileLine")
273#define CXXVARIABLEDECLAREDTYPE Doc::alias("cxxVariableDeclaredType")
274#define CXXVARIABLEDEFINITION Doc::alias("cxxVariableDefinition")
275#define CXXVARIABLEDETAIL Doc::alias("cxxVariableDetail")
276#define CXXVARIABLENAMELOOKUP Doc::alias("cxxVariableNameLookup")
277#define CXXVARIABLEPROTOTYPE Doc::alias("cxxVariablePrototype")
278#define CXXVARIABLEREIMPLEMENTED Doc::alias("cxxVariableReimplemented")
279#define CXXVARIABLESCOPEDNAME Doc::alias("cxxVariableScopedName")
280#define CXXVARIABLESTORAGECLASSSPECIFIEREXTERN Doc::alias("cxxVariableStorageClassSpecifierExtern")
281#define CXXVARIABLESTORAGECLASSSPECIFIERMUTABLE Doc::alias("cxxVariableStorageClassSpecifierMutable")
282#define CXXVARIABLESTORAGECLASSSPECIFIERSTATIC Doc::alias("cxxVariableStorageClassSpecifierStatic")
283#define CXXVARIABLEVOLATILE Doc::alias("cxxVariableVolatile")
284
285#define APIREF Doc::alias("apiRef")
286#define APINAME Doc::alias("apiName")
287#define APIDETAIL Doc::alias("apiDetail")
288#define APISYNTAX Doc::alias("apiSyntax")
289#define APISYNTAXTEXT Doc::alias("apiSyntaxText")
290#define APISYNTAXITEM Doc::alias("apiSyntaxItem")
291#define APIDEF Doc::alias("apiDef")
292#define APIQUALIFIER Doc::alias("apiQualifier")
293#define APIRELATION Doc::alias("apiRelation")
294#define APITYPE Doc::alias("apiType")
295#define APIARRAY Doc::alias("apiArray")
296#define APIDATA Doc::alias("apiData")
297#define APIDEFNOTE Doc::alias("apiDefNote")
298#define APIDEFITEM Doc::alias("apiDefItem")
299#define APIITEMNAME Doc::alias("apiItemName")
300#define APIDESC Doc::alias("apiDesc")
301#define APIIMPL Doc::alias("apiImpl")
302
303#define APIPACKAGE Doc::alias("apiPackage")
304
305#define APICLASSIFIER Doc::alias("apiClassifier")
306#define APICLASSIFIERDETAIL Doc::alias("apiClassifierDetail")
307#define APICLASSIFIERDEF Doc::alias("apiClassifierDef")
308#define APICLASSIFIERMEMBER Doc::alias("apiClassifierMember")
309#define APIOTHERCLASSIFIER Doc::alias("apiOtherClassifier")
310#define APIBASECLASSIFIER Doc::alias("apiBaseClassifier")
311
312#define APIOPERATION Doc::alias("apiOperation")
313#define APIOPERATIONDETAIL Doc::alias("apiOperationDetail")
314#define APIOPERATIONDEF Doc::alias("apiOperationDef")
315#define APIRETURN Doc::alias("apiReturn")
316#define APIPARAM Doc::alias("apiParam")
317#define APIEVENT Doc::alias("apiEvent")
318#define APIOPERATIONDEFITEM Doc::alias("apiOperationDefItem")
319#define APIOPERATIONCLASSIFIER Doc::alias("apiOperationClassifier")
320#define APICONSTRUCTORDEF Doc::alias("apiConstructorDef")
321
322#define APIVALUE Doc::alias("apiValue")
323#define APIVALUEDETAIL Doc::alias("apiValueDetail")
324#define APIVALUEDEF Doc::alias("apiValueDef")
325#define APIVALUEMEMBER Doc::alias("apiValueMember")
326#define APIVALUECLASSIFIER Doc::alias("apiValueClassifier")
327
328#define APIclassifier Doc::alias("apiclassifier")
329#define APIoperation Doc::alias("apioperation")
330#define APIpackage Doc::alias("apipackage")
331#define APIvalue Doc::alias("apivalue")
332
333#define APIMAP Doc::alias("apiMap")
334#define APIITEMREF Doc::alias("apiItemRef")
335
336#define SHORTDESC Doc::alias("shortdesc")
337
338QString DitaXmlGenerator::sinceTitles[] =
339 {
340 " New Namespaces",
341 " New Classes",
342 " New Member Functions",
343 " New Functions in Namespaces",
344 " New Global Functions",
345 " New Macros",
346 " New Enum Types",
347 " New Typedefs",
348 " New Properties",
349 " New Variables",
350 " New QML Elements",
351 " New Qml Properties",
352 " New Qml Signals",
353 " New Qml Methods",
354 ""
355 };
356
357static bool showBrokenLinks = false;
358
359static void addLink(const QString &linkTarget,
360 const QStringRef &nestedStuff,
361 QString *res)
362{
363 if (!linkTarget.isEmpty()) {
364 *res += "<xref href=\"";
365 *res += linkTarget;
366 *res += "\">";
367 *res += nestedStuff;
368 *res += "</xref>";
369 }
370 else {
371 *res += nestedStuff;
372 }
373}
374
375
376DitaXmlGenerator::DitaXmlGenerator()
377 : inLink(false),
378 inContents(false),
379 inSectionHeading(false),
380 inTableHeader(false),
381 numTableRows(0),
382 threeColumnEnumValueTable(true),
383 offlineDocs(true),
384 funcLeftParen("\\S(\\()"),
385 myTree(0),
386 slow(false),
387 obsoleteLinks(false),
388 noLinks(0)
389{
390}
391
392DitaXmlGenerator::~DitaXmlGenerator()
393{
394 // nothing yet.
395}
396
397void DitaXmlGenerator::initializeGenerator(const Config &config)
398{
399 static const struct {
400 const char *key;
401 const char *tag;
402 } defaults[] = {
403 { ATOM_FORMATTING_BOLD, "b" },
404 { ATOM_FORMATTING_INDEX, "<!--" },
405 { ATOM_FORMATTING_ITALIC, "i" },
406 { ATOM_FORMATTING_PARAMETER, "i" },
407 { ATOM_FORMATTING_SUBSCRIPT, "sub" },
408 { ATOM_FORMATTING_SUPERSCRIPT, "sup" },
409 { ATOM_FORMATTING_TELETYPE, "tt", },
410 { ATOM_FORMATTING_UNDERLINE, "u", },
411 { 0, 0 }
412 };
413
414 Generator::initializeGenerator(config);
415 obsoleteLinks = config.getBool(QLatin1String(CONFIG_OBSOLETELINKS));
416 setImageFileExtensions(QStringList() << "png" << "jpg" << "jpeg" << "gif");
417 int i = 0;
418 while (defaults[i].key) {
419 formattingLeftMap().insert(defaults[i].key, defaults[i].tag);
420 i++;
421 }
422
423 style = config.getString(DitaXmlGenerator::format() +
424 Config::dot +
425 DITAXMLGENERATOR_STYLE);
426 postHeader = config.getString(DitaXmlGenerator::format() +
427 Config::dot +
428 DITAXMLGENERATOR_POSTHEADER);
429 postPostHeader = config.getString(DitaXmlGenerator::format() +
430 Config::dot +
431 DITAXMLGENERATOR_POSTPOSTHEADER);
432 footer = config.getString(DitaXmlGenerator::format() +
433 Config::dot +
434 DITAXMLGENERATOR_FOOTER);
435 address = config.getString(DitaXmlGenerator::format() +
436 Config::dot +
437 DITAXMLGENERATOR_ADDRESS);
438 pleaseGenerateMacRef = config.getBool(DitaXmlGenerator::format() +
439 Config::dot +
440 DITAXMLGENERATOR_GENERATEMACREFS);
441
442 project = config.getString(CONFIG_PROJECT);
443 projectDescription = config.getString(CONFIG_DESCRIPTION);
444 if (projectDescription.isEmpty() && !project.isEmpty())
445 projectDescription = project + " Reference Documentation";
446
447 projectUrl = config.getString(CONFIG_URL);
448
449 outputEncoding = config.getString(CONFIG_OUTPUTENCODING);
450 if (outputEncoding.isEmpty())
451 outputEncoding = QLatin1String("ISO-8859-1");
452 outputCodec = QTextCodec::codecForName(outputEncoding.toLocal8Bit());
453
454 naturalLanguage = config.getString(CONFIG_NATURALLANGUAGE);
455 if (naturalLanguage.isEmpty())
456 naturalLanguage = QLatin1String("en");
457
458 QSet<QString> editionNames = config.subVars(CONFIG_EDITION);
459 QSet<QString>::ConstIterator edition = editionNames.begin();
460 while (edition != editionNames.end()) {
461 QString editionName = *edition;
462 QStringList editionModules = config.getStringList(CONFIG_EDITION +
463 Config::dot +
464 editionName +
465 Config::dot +
466 "modules");
467 QStringList editionGroups = config.getStringList(CONFIG_EDITION +
468 Config::dot +
469 editionName +
470 Config::dot +
471 "groups");
472
473 if (!editionModules.isEmpty())
474 editionModuleMap[editionName] = editionModules;
475 if (!editionGroups.isEmpty())
476 editionGroupMap[editionName] = editionGroups;
477
478 ++edition;
479 }
480
481 slow = config.getBool(CONFIG_SLOW);
482
483 stylesheets = config.getStringList(DitaXmlGenerator::format() +
484 Config::dot +
485 DITAXMLGENERATOR_STYLESHEETS);
486 customHeadElements = config.getStringList(DitaXmlGenerator::format() +
487 Config::dot +
488 DITAXMLGENERATOR_CUSTOMHEADELEMENTS);
489 codeIndent = config.getInt(CONFIG_CODEINDENT);
490
491}
492
493void DitaXmlGenerator::terminateGenerator()
494{
495 Generator::terminateGenerator();
496}
497
498QString DitaXmlGenerator::format()
499{
500 return "DITAXML";
501}
502
503/*!
504 Calls lookupGuid() to get a GUID for \a text, then writes
505 it to the XML stream as an "id" attribute, and returns it.
506 */
507QString DitaXmlGenerator::writeGuidAttribute(QString text)
508{
509 QString guid = lookupGuid(text);
510 writer.writeAttribute("id",guid);
511 return guid;
512}
513
514/*!
515 Looks up \a text in the GUID map. If it finds \a text,
516 it returns the associated GUID. Otherwise it inserts
517 \a text into the map with a new GUID, and it returns
518 the new GUID.
519 */
520QString DitaXmlGenerator::lookupGuid(QString text)
521{
522 QMap<QString, QString>::const_iterator i = name2guidMap.find(text);
523 if (i != name2guidMap.end())
524 return i.value();
525 QString guid = QUuid::createUuid().toString();
526 name2guidMap.insert(text,guid);
527 return guid;
528}
529
530/*!
531 This is where the DITA XML files are written.
532 \note The file generation is done in the base class,
533 PageGenerator::generateTree().
534 */
535void DitaXmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
536{
537 myTree = tree;
538 nonCompatClasses.clear();
539 mainClasses.clear();
540 compatClasses.clear();
541 obsoleteClasses.clear();
542 moduleClassMap.clear();
543 moduleNamespaceMap.clear();
544 funcIndex.clear();
545 legaleseTexts.clear();
546 serviceClasses.clear();
547 qmlClasses.clear();
548 findAllClasses(tree->root());
549 findAllFunctions(tree->root());
550 findAllLegaleseTexts(tree->root());
551 findAllNamespaces(tree->root());
552 findAllSince(tree->root());
553
554 PageGenerator::generateTree(tree, marker);
555}
556
557void DitaXmlGenerator::startText(const Node* /* relative */,
558 CodeMarker* /* marker */)
559{
560 inLink = false;
561 inContents = false;
562 inSectionHeading = false;
563 inTableHeader = false;
564 numTableRows = 0;
565 threeColumnEnumValueTable = true;
566 link.clear();
567 sectionNumber.clear();
568}
569
570/*!
571 Generate html from an instance of Atom.
572 */
573int DitaXmlGenerator::generateAtom(const Atom *atom,
574 const Node *relative,
575 CodeMarker *marker)
576{
577 int skipAhead = 0;
578 QString hx;
579 static bool in_para = false;
580 QString guid;
581
582 switch (atom->type()) {
583 case Atom::AbstractLeft:
584 break;
585 case Atom::AbstractRight:
586 break;
587 case Atom::AutoLink:
588 if ((noLinks > 0) && !inLink && !inContents && !inSectionHeading) {
589 const Node *node = 0;
590 QString link = getLink(atom, relative, marker, &node);
591 if (!link.isEmpty()) {
592 beginLink(link, node, relative, marker);
593 generateLink(atom, relative, marker);
594 endLink();
595 }
596 else {
597 writer.writeCharacters(protectEnc(atom->string()));
598 }
599 }
600 else {
601 writer.writeCharacters(protectEnc(atom->string()));
602 }
603 break;
604 case Atom::BaseName:
605 break;
606 case Atom::BriefLeft:
607 if (relative->type() == Node::Fake) {
608 skipAhead = skipAtoms(atom, Atom::BriefRight);
609 break;
610 }
611 writer.writeStartElement(SHORTDESC);
612 if (relative->type() == Node::Property ||
613 relative->type() == Node::Variable) {
614 QString str;
615 atom = atom->next();
616 while (atom != 0 && atom->type() != Atom::BriefRight) {
617 if (atom->type() == Atom::String ||
618 atom->type() == Atom::AutoLink)
619 str += atom->string();
620 skipAhead++;
621 atom = atom->next();
622 }
623 str[0] = str[0].toLower();
624 if (str.right(1) == ".")
625 str.truncate(str.length() - 1);
626 writer.writeCharacters("This ");
627 if (relative->type() == Node::Property)
628 writer.writeCharacters("property");
629 else
630 writer.writeCharacters("variable");
631 QStringList words = str.split(" ");
632 if (!(words.first() == "contains" || words.first() == "specifies"
633 || words.first() == "describes" || words.first() == "defines"
634 || words.first() == "holds" || words.first() == "determines"))
635 writer.writeCharacters(" holds ");
636 else
637 writer.writeCharacters(" ");
638 writer.writeCharacters(str + ".");
639 }
640 break;
641 case Atom::BriefRight:
642 if (relative->type() != Node::Fake) {
643 writer.writeEndElement(); // </shortdesc>
644 }
645 break;
646 case Atom::C:
647 writer.writeStartElement(formattingLeftMap()[ATOM_FORMATTING_TELETYPE]);
648 if (inLink) {
649 writer.writeCharacters(protectEnc(plainCode(atom->string())));
650 }
651 else {
652 writer.writeCharacters(highlightedCode(atom->string(), marker, relative));
653 }
654 writer.writeEndElement(); // sse writeStartElement() above
655 break;
656 case Atom::Code:
657 writer.writeStartElement("pre");
658 writer.writeAttribute("outputclass","highlightedCode");
659 writer.writeCharacters(trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
660 marker,
661 relative)));
662 writer.writeEndElement(); // </pre>
663 break;
664#ifdef QDOC_QML
665 case Atom::Qml:
666 writer.writeStartElement("pre");
667 writer.writeAttribute("outputclass","highlightedCode");
668 writer.writeCharacters(trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
669 marker,
670 relative)));
671 writer.writeEndElement(); // pre
672 break;
673#endif
674 case Atom::CodeNew:
675 writer.writeStartElement("p");
676 writer.writeCharacters("you can rewrite it as");
677 writer.writeEndElement(); // </p>
678 writer.writeStartElement("pre");
679 writer.writeAttribute("outputclass","highlightedCode");
680 writer.writeCharacters(trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
681 marker,
682 relative)));
683 writer.writeEndElement(); // </pre>
684 break;
685 case Atom::CodeOld:
686 writer.writeStartElement("p");
687 writer.writeCharacters("For example, if you have code like");
688 writer.writeEndElement(); // </p>
689 // fallthrough
690 case Atom::CodeBad:
691 writer.writeStartElement("pre");
692 writer.writeAttribute("outputclass","highlightedCode");
693 writer.writeCharacters(trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string())))));
694 writer.writeEndElement(); // </pre>
695 break;
696 case Atom::FootnoteLeft:
697 // ### For now
698 if (in_para) {
699 writer.writeEndElement(); // </p>
700 in_para = false;
701 }
702 writer.writeCharacters("<!-- ");
703 break;
704 case Atom::FootnoteRight:
705 // ### For now
706 writer.writeCharacters("-->");
707 break;
708 case Atom::FormatElse:
709 case Atom::FormatEndif:
710 case Atom::FormatIf:
711 break;
712 case Atom::FormattingLeft:
713 writer.writeStartElement(formattingLeftMap()[atom->string()]);
714 if (atom->string() == ATOM_FORMATTING_PARAMETER) {
715 if (atom->next() != 0 && atom->next()->type() == Atom::String) {
716 QRegExp subscriptRegExp("([a-z]+)_([0-9n])");
717 if (subscriptRegExp.exactMatch(atom->next()->string())) {
718 writer.writeCharacters(subscriptRegExp.cap(1));
719 writer.writeStartElement("sub");
720 writer.writeCharacters(subscriptRegExp.cap(2));
721 writer.writeEndElement(); // </sub>
722 skipAhead = 1;
723 }
724 }
725 }
726 break;
727 case Atom::FormattingRight:
728 if (atom->string() == ATOM_FORMATTING_LINK) {
729 endLink();
730 }
731 else {
732 writer.writeEndElement(); // ?
733 }
734 break;
735 case Atom::AnnotatedList:
736 {
737 QList<Node*> values = myTree->groups().values(atom->string());
738 NodeMap nodeMap;
739 for (int i = 0; i < values.size(); ++i) {
740 const Node* n = values.at(i);
741 if ((n->status() != Node::Internal) && (n->access() != Node::Private)) {
742 nodeMap.insert(n->nameForLists(),n);
743 }
744 }
745 generateAnnotatedList(relative, marker, nodeMap);
746 }
747 break;
748 case Atom::GeneratedList:
749 if (atom->string() == "annotatedclasses") {
750 generateAnnotatedList(relative, marker, nonCompatClasses);
751 }
752 else if (atom->string() == "classes") {
753 generateCompactList(relative, marker, nonCompatClasses, true);
754 }
755 else if (atom->string() == "qmlclasses") {
756 generateCompactList(relative, marker, qmlClasses, true);
757 }
758 else if (atom->string().contains("classesbymodule")) {
759 QString arg = atom->string().trimmed();
760 QString moduleName = atom->string().mid(atom->string().indexOf(
761 "classesbymodule") + 15).trimmed();
762 if (moduleClassMap.contains(moduleName))
763 generateAnnotatedList(relative, marker, moduleClassMap[moduleName]);
764 }
765 else if (atom->string().contains("classesbyedition")) {
766
767 QString arg = atom->string().trimmed();
768 QString editionName = atom->string().mid(atom->string().indexOf(
769 "classesbyedition") + 16).trimmed();
770
771 if (editionModuleMap.contains(editionName)) {
772
773 // Add all classes in the modules listed for that edition.
774 NodeMap editionClasses;
775 foreach (const QString &moduleName, editionModuleMap[editionName]) {
776 if (moduleClassMap.contains(moduleName))
777 editionClasses.unite(moduleClassMap[moduleName]);
778 }
779
780 // Add additional groups and remove groups of classes that
781 // should be excluded from the edition.
782
783 QMultiMap <QString, Node *> groups = myTree->groups();
784 foreach (const QString &groupName, editionGroupMap[editionName]) {
785 QList<Node *> groupClasses;
786 if (groupName.startsWith("-")) {
787 groupClasses = groups.values(groupName.mid(1));
788 foreach (const Node *node, groupClasses)
789 editionClasses.remove(node->name());
790 }
791 else {
792 groupClasses = groups.values(groupName);
793 foreach (const Node *node, groupClasses)
794 editionClasses.insert(node->name(), node);
795 }
796 }
797 generateAnnotatedList(relative, marker, editionClasses);
798 }
799 }
800 else if (atom->string() == "classhierarchy") {
801 generateClassHierarchy(relative, marker, nonCompatClasses);
802 }
803 else if (atom->string() == "compatclasses") {
804 generateCompactList(relative, marker, compatClasses, false);
805 }
806 else if (atom->string() == "obsoleteclasses") {
807 generateCompactList(relative, marker, obsoleteClasses, false);
808 }
809 else if (atom->string() == "functionindex") {
810 generateFunctionIndex(relative, marker);
811 }
812 else if (atom->string() == "legalese") {
813 generateLegaleseList(relative, marker);
814 }
815 else if (atom->string() == "mainclasses") {
816 generateCompactList(relative, marker, mainClasses, true);
817 }
818 else if (atom->string() == "services") {
819 generateCompactList(relative, marker, serviceClasses, false);
820 }
821 else if (atom->string() == "overviews") {
822 generateOverviewList(relative, marker);
823 }
824 else if (atom->string() == "namespaces") {
825 generateAnnotatedList(relative, marker, namespaceIndex);
826 }
827 else if (atom->string() == "related") {
828 const FakeNode *fake = static_cast<const FakeNode *>(relative);
829 if (fake && !fake->groupMembers().isEmpty()) {
830 NodeMap groupMembersMap;
831 foreach (const Node *node, fake->groupMembers()) {
832 if (node->type() == Node::Fake)
833 groupMembersMap[fullName(node, relative, marker)] = node;
834 }
835 generateAnnotatedList(fake, marker, groupMembersMap);
836 }
837 }
838 else if (atom->string() == "relatedinline") {
839 const FakeNode *fake = static_cast<const FakeNode *>(relative);
840 if (fake && !fake->groupMembers().isEmpty()) {
841 // Reverse the list into the original scan order.
842 // Should be sorted. But on what? It may not be a
843 // regular class or page definition.
844 QList<const Node *> list;
845 foreach (const Node *node, fake->groupMembers())
846 list.prepend(node);
847 foreach (const Node *node, list)
848 generateBody(node, marker);
849 }
850 }
851 break;
852 case Atom::SinceList:
853 {
854 NewSinceMaps::const_iterator nsmap;
855 nsmap = newSinceMaps.find(atom->string());
856 NewClassMaps::const_iterator ncmap;
857 ncmap = newClassMaps.find(atom->string());
858 NewClassMaps::const_iterator nqcmap;
859 nqcmap = newQmlClassMaps.find(atom->string());
860 if ((nsmap != newSinceMaps.constEnd()) && !nsmap.value().isEmpty()) {
861 QList<Section> sections;
862 QList<Section>::ConstIterator s;
863 for (int i=0; i<LastSinceType; ++i)
864 sections.append(Section(sinceTitle(i),QString(),QString(),QString()));
865
866 NodeMultiMap::const_iterator n = nsmap.value().constBegin();
867 while (n != nsmap.value().constEnd()) {
868 const Node* node = n.value();
869 switch (node->type()) {
870 case Node::Fake:
871 if (node->subType() == Node::QmlClass) {
872 sections[QmlClass].appendMember((Node*)node);
873 }
874 break;
875 case Node::Namespace:
876 sections[Namespace].appendMember((Node*)node);
877 break;
878 case Node::Class:
879 sections[Class].appendMember((Node*)node);
880 break;
881 case Node::Enum:
882 sections[Enum].appendMember((Node*)node);
883 break;
884 case Node::Typedef:
885 sections[Typedef].appendMember((Node*)node);
886 break;
887 case Node::Function: {
888 const FunctionNode* fn = static_cast<const FunctionNode*>(node);
889 if (fn->isMacro())
890 sections[Macro].appendMember((Node*)node);
891 else {
892 Node* p = fn->parent();
893 if (p) {
894 if (p->type() == Node::Class)
895 sections[MemberFunction].appendMember((Node*)node);
896 else if (p->type() == Node::Namespace) {
897 if (p->name().isEmpty())
898 sections[GlobalFunction].appendMember((Node*)node);
899 else
900 sections[NamespaceFunction].appendMember((Node*)node);
901 }
902 else
903 sections[GlobalFunction].appendMember((Node*)node);
904 }
905 else
906 sections[GlobalFunction].appendMember((Node*)node);
907 }
908 break;
909 }
910 case Node::Property:
911 sections[Property].appendMember((Node*)node);
912 break;
913 case Node::Variable:
914 sections[Variable].appendMember((Node*)node);
915 break;
916 case Node::QmlProperty:
917 sections[QmlProperty].appendMember((Node*)node);
918 break;
919 case Node::QmlSignal:
920 sections[QmlSignal].appendMember((Node*)node);
921 break;
922 case Node::QmlMethod:
923 sections[QmlMethod].appendMember((Node*)node);
924 break;
925 default:
926 break;
927 }
928 ++n;
929 }
930
931 /*
932 First generate the table of contents.
933 */
934 writer.writeStartElement("ul");
935 s = sections.constBegin();
936 while (s != sections.constEnd()) {
937 if (!(*s).members.isEmpty()) {
938
939 writer.writeStartElement("li");
940 writer.writeStartElement("xref");
941 writer.writeAttribute("href",QString("#" + Doc::canonicalTitle((*s).name)));
942 writer.writeCharacters((*s).name);
943 writer.writeEndElement(); // </xref>
944 writer.writeEndElement(); // </li>
945 }
946 ++s;
947 }
948 writer.writeEndElement(); // </ul>
949
950 int idx = 0;
951 s = sections.constBegin();
952 while (s != sections.constEnd()) {
953 if (!(*s).members.isEmpty()) {
954 writer.writeStartElement("p");
955 writeGuidAttribute(Doc::canonicalTitle((*s).name));
956 writer.writeAttribute("outputclass","h3");
957 writer.writeCharacters(protectEnc((*s).name));
958 writer.writeEndElement(); // </p>
959 if (idx == Class)
960 generateCompactList(0, marker, ncmap.value(), false, QString("Q"));
961 else if (idx == QmlClass)
962 generateCompactList(0, marker, nqcmap.value(), false, QString("Q"));
963 else if (idx == MemberFunction) {
964 ParentMaps parentmaps;
965 ParentMaps::iterator pmap;
966 NodeList::const_iterator i = s->members.constBegin();
967 while (i != s->members.constEnd()) {
968 Node* p = (*i)->parent();
969 pmap = parentmaps.find(p);
970 if (pmap == parentmaps.end())
971 pmap = parentmaps.insert(p,NodeMultiMap());
972 pmap->insert((*i)->name(),(*i));
973 ++i;
974 }
975 pmap = parentmaps.begin();
976 while (pmap != parentmaps.end()) {
977 NodeList nlist = pmap->values();
978 writer.writeStartElement("p");
979 writer.writeCharacters("Class ");
980 writer.writeStartElement("xref");
981 writer.writeAttribute("href",linkForNode(pmap.key(), 0));
982 QStringList pieces = fullName(pmap.key(), 0, marker).split("::");
983 writer.writeCharacters(protectEnc(pieces.last()));
984 writer.writeEndElement(); // </xref>
985 writer.writeCharacters(":");
986 writer.writeEndElement(); // </p>
987
988 generateSection(nlist, 0, marker, CodeMarker::Summary);
989 writer.writeEmptyElement("br");
990 ++pmap;
991 }
992 }
993 else
994 generateSection(s->members, 0, marker, CodeMarker::Summary);
995 }
996 ++idx;
997 ++s;
998 }
999 }
1000 }
1001 break;
1002 case Atom::Image:
1003 case Atom::InlineImage:
1004 {
1005 QString fileName = imageFileName(relative, atom->string());
1006 QString text;
1007 if (atom->next() != 0)
1008 text = atom->next()->string();
1009 if (atom->type() == Atom::Image) {
1010 writer.writeStartElement("p");
1011 writer.writeAttribute("outputclass","centerAlign");
1012 }
1013 if (fileName.isEmpty()) {
1014 writer.writeStartElement("font");
1015 writer.writeAttribute("color","red");
1016 writer.writeCharacters("[Missing image: ");
1017 writer.writeCharacters(protectEnc(atom->string()));
1018 writer.writeEndElement(); // </font>
1019 }
1020 else {
1021 writer.writeStartElement("img");
1022 writer.writeAttribute("src",protectEnc(fileName));
1023 if (!text.isEmpty())
1024 writer.writeAttribute("alt",protectEnc(text));
1025 writer.writeEndElement(); // </img>
1026 }
1027 if (atom->type() == Atom::Image)
1028 writer.writeEndElement(); // </p>
1029 }
1030 break;
1031 case Atom::ImageText:
1032 // nothing
1033 break;
1034 case Atom::LegaleseLeft:
1035 writer.writeStartElement("p");
1036 writer.writeAttribute("outputclass","legalese");
1037 break;
1038 case Atom::LegaleseRight:
1039 writer.writeEndElement(); // </p>
1040 break;
1041 case Atom::LineBreak:
1042 writer.writeEmptyElement("br");
1043 break;
1044 case Atom::Link:
1045 {
1046 const Node *node = 0;
1047 QString myLink = getLink(atom, relative, marker, &node);
1048 if (myLink.isEmpty()) {
1049 relative->doc().location().warning(tr("Cannot link to '%1' in %2")
1050 .arg(atom->string())
1051 .arg(marker->plainFullName(relative)));
1052 }
1053 beginLink(myLink, node, relative, marker);
1054 skipAhead = 1;
1055 }
1056 break;
1057 case Atom::LinkNode:
1058 {
1059 const Node *node = CodeMarker::nodeForString(atom->string());
1060 beginLink(linkForNode(node, relative), node, relative, marker);
1061 skipAhead = 1;
1062 }
1063 break;
1064 case Atom::ListLeft:
1065 if (in_para) {
1066 writer.writeEndElement(); // </p>
1067 in_para = false;
1068 }
1069 if (atom->string() == ATOM_LIST_BULLET) {
1070 writer.writeStartElement("ul");
1071 }
1072 else if (atom->string() == ATOM_LIST_TAG) {
1073 writer.writeStartElement("dl");
1074 }
1075 else if (atom->string() == ATOM_LIST_VALUE) {
1076 threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
1077 if (threeColumnEnumValueTable) {
1078 writer.writeStartElement("table");
1079 writer.writeAttribute("outputclass","valuelist");
1080 writer.writeStartElement("tr");
1081 if (++numTableRows % 2 == 1)
1082 writer.writeAttribute("outputclass","odd");
1083 else
1084 writer.writeAttribute("outputclass","even");
1085 writer.writeStartElement("th");
1086 writer.writeCharacters("Constant");
1087 writer.writeEndElement(); // </th>
1088 writer.writeStartElement("th");
1089 writer.writeCharacters("Value");
1090 writer.writeEndElement(); // </th>
1091 writer.writeStartElement("th");
1092 writer.writeCharacters("Description");
1093 writer.writeEndElement(); // </th>
1094 writer.writeEndElement(); // </tr>
1095 }
1096 else {
1097 writer.writeStartElement("table");
1098 writer.writeAttribute("outputclass","valuelist");
1099 writer.writeStartElement("tr");
1100 writer.writeStartElement("th");
1101 writer.writeCharacters("Constant");
1102 writer.writeEndElement(); // </th>
1103 writer.writeStartElement("th");
1104 writer.writeCharacters("Value");
1105 writer.writeEndElement(); // </th>
1106 writer.writeEndElement(); // </tr>
1107 }
1108 }
1109 else {
1110 writer.writeStartElement("ol");
1111 if (atom->string() == ATOM_LIST_UPPERALPHA)
1112 writer.writeAttribute("type","A");
1113 else if (atom->string() == ATOM_LIST_LOWERALPHA)
1114 writer.writeAttribute("type","a");
1115 else if (atom->string() == ATOM_LIST_UPPERROMAN)
1116 writer.writeAttribute("type","I");
1117 else if (atom->string() == ATOM_LIST_LOWERROMAN)
1118 writer.writeAttribute("type","i");
1119 else // (atom->string() == ATOM_LIST_NUMERIC)
1120 writer.writeAttribute("type","1");
1121 if (atom->next() != 0 && atom->next()->string().toInt() != 1)
1122 writer.writeAttribute("start",atom->next()->string());
1123 }
1124 break;
1125 case Atom::ListItemNumber:
1126 // nothing
1127 break;
1128 case Atom::ListTagLeft:
1129 if (atom->string() == ATOM_LIST_TAG) {
1130 writer.writeStartElement("dt");
1131 }
1132 else { // (atom->string() == ATOM_LIST_VALUE)
1133 writer.writeStartElement("tr");
1134 writer.writeStartElement("td");
1135 writer.writeAttribute("outputclass","topAlign");
1136 writer.writeStartElement("tt");
1137 writer.writeCharacters(protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(),
1138 relative))));
1139 writer.writeEndElement(); // </tt>
1140 writer.writeEndElement(); // </td>
1141 writer.writeStartElement("td");
1142 writer.writeAttribute("outputclass","topAlign");
1143
1144 QString itemValue;
1145 if (relative->type() == Node::Enum) {
1146 const EnumNode *enume = static_cast<const EnumNode *>(relative);
1147 itemValue = enume->itemValue(atom->next()->string());
1148 }
1149
1150 if (itemValue.isEmpty())
1151 writer.writeCharacters("?");
1152 else {
1153 writer.writeStartElement("tt");
1154 writer.writeCharacters(protectEnc(itemValue));
1155 writer.writeEndElement(); // </tt>
1156 }
1157 skipAhead = 1;
1158 }
1159 break;
1160 case Atom::ListTagRight:
1161 if (atom->string() == ATOM_LIST_TAG)
1162 writer.writeEndElement(); // </dt>
1163 break;
1164 case Atom::ListItemLeft:
1165 if (atom->string() == ATOM_LIST_TAG) {
1166 writer.writeStartElement("dd");
1167 }
1168 else if (atom->string() == ATOM_LIST_VALUE) {
1169 if (threeColumnEnumValueTable) {
1170 writer.writeEndElement(); // </td>
1171 writer.writeStartElement("td");
1172 writer.writeAttribute("outputclass","topAlign");
1173 if (matchAhead(atom, Atom::ListItemRight))
1174 writer.writeCharacters("&nbsp;");
1175 }
1176 }
1177 else {
1178 writer.writeStartElement("li");
1179 }
1180 if (matchAhead(atom, Atom::ParaLeft))
1181 skipAhead = 1;
1182 break;
1183 case Atom::ListItemRight:
1184 if (atom->string() == ATOM_LIST_TAG) {
1185 writer.writeEndElement(); // </dd>
1186 }
1187 else if (atom->string() == ATOM_LIST_VALUE) {
1188 writer.writeEndElement(); // </td>
1189 writer.writeEndElement(); // </tr>
1190 }
1191 else {
1192 writer.writeEndElement(); // </li>
1193 }
1194 break;
1195 case Atom::ListRight:
1196 if (atom->string() == ATOM_LIST_BULLET) {
1197 writer.writeEndElement(); // </ul>
1198 }
1199 else if (atom->string() == ATOM_LIST_TAG) {
1200 writer.writeEndElement(); // </dl>
1201 }
1202 else if (atom->string() == ATOM_LIST_VALUE) {
1203 writer.writeEndElement(); // </table>
1204 }
1205 else {
1206 writer.writeEndElement(); // </ol>
1207 }
1208 break;
1209 case Atom::Nop:
1210 // nothing
1211 break;
1212 case Atom::ParaLeft:
1213 writer.writeStartElement("p");
1214 in_para = true;
1215 break;
1216 case Atom::ParaRight:
1217 endLink();
1218 if (in_para) {
1219 writer.writeEndElement(); // </p?
1220 in_para = false;
1221 }
1222 break;
1223 case Atom::QuotationLeft:
1224 writer.writeStartElement("blockquote");
1225 break;
1226 case Atom::QuotationRight:
1227 writer.writeEndElement(); // </blockquote>
1228 break;
1229 case Atom::RawString:
1230 writer.writeCharacters(atom->string());
1231 break;
1232 case Atom::SectionLeft:
1233 writer.writeStartElement("p");
1234 writeGuidAttribute(Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
1235 writer.writeAttribute("outputclass","target");
1236 writer.writeCharacters(protectEnc(Text::sectionHeading(atom).toString()));
1237 writer.writeEndElement(); // </p>
1238 break;
1239 case Atom::SectionRight:
1240 // nothing
1241 break;
1242 case Atom::SectionHeadingLeft:
1243 writer.writeStartElement("p");
1244 hx = "h" + QString::number(atom->string().toInt() + hOffset(relative));
1245 writer.writeAttribute("outputclass",hx);
1246 inSectionHeading = true;
1247 break;
1248 case Atom::SectionHeadingRight:
1249 writer.writeEndElement(); // </p> (see case Atom::SectionHeadingLeft)
1250 inSectionHeading = false;
1251 break;
1252 case Atom::SidebarLeft:
1253 // nothing
1254 break;
1255 case Atom::SidebarRight:
1256 // nothing
1257 break;
1258 case Atom::String:
1259 if (inLink && !inContents && !inSectionHeading) {
1260 generateLink(atom, relative, marker);
1261 }
1262 else {
1263 writer.writeCharacters(protectEnc(atom->string()));
1264 }
1265 break;
1266 case Atom::TableLeft:
1267 if (in_para) {
1268 writer.writeEndElement(); // </p>
1269 in_para = false;
1270 }
1271 writer.writeStartElement("table");
1272 writer.writeAttribute("outputclass","generic");
1273 numTableRows = 0;
1274 break;
1275 case Atom::TableRight:
1276 writer.writeEndElement(); // </table>
1277 break;
1278 case Atom::TableHeaderLeft:
1279 writer.writeStartElement("thead");
1280 writer.writeStartElement("tr");
1281 writer.writeAttribute("outputclass","qt-style topAlign");
1282 inTableHeader = true;
1283 break;
1284 case Atom::TableHeaderRight:
1285 writer.writeEndElement(); // </tr>
1286 if (matchAhead(atom, Atom::TableHeaderLeft)) {
1287 skipAhead = 1;
1288 writer.writeStartElement("tr");
1289 writer.writeAttribute("outputclass","qt-style topAlign");
1290 }
1291 else {
1292 writer.writeEndElement(); // </thead>
1293 inTableHeader = false;
1294 }
1295 break;
1296 case Atom::TableRowLeft:
1297 writer.writeStartElement("tr");
1298 if (++numTableRows % 2 == 1)
1299 writer.writeAttribute("outputclass","odd topAlign");
1300 else
1301 writer.writeAttribute("outputclass","even topAlign");
1302 break;
1303 case Atom::TableRowRight:
1304 writer.writeEndElement(); // </tr>\n";
1305 break;
1306 case Atom::TableItemLeft:
1307 {
1308 if (inTableHeader)
1309 writer.writeStartElement("th");
1310 else
1311 writer.writeStartElement("td");
1312
1313 QStringList spans = atom->string().split(",");
1314 if (spans.size() == 2) {
1315#if zzz
1316
1317 if (spans.at(0) != "1")
1318 out() << " colspan=\"" << spans.at(0) << "\"";
1319 if (spans.at(1) != "1")
1320 out() << " rowspan=\"" << spans.at(1) << "\"";
1321#endif
1322 if (!inTableHeader)
1323 writer.writeStartElement("p");
1324 }
1325 if (matchAhead(atom, Atom::ParaLeft))
1326 skipAhead = 1;
1327 }
1328 break;
1329 case Atom::TableItemRight:
1330 if (inTableHeader)
1331 writer.writeEndElement(); // </th>
1332 else {
1333 writer.writeEndElement(); // </p>
1334 writer.writeEndElement(); // </td>
1335 }
1336 if (matchAhead(atom, Atom::ParaLeft))
1337 skipAhead = 1;
1338 break;
1339 case Atom::TableOfContents:
1340 {
1341 int numColumns = 1;
1342 const Node *node = relative;
1343
1344 Doc::SectioningUnit sectioningUnit = Doc::Section4;
1345 QStringList params = atom->string().split(",");
1346 QString columnText = params.at(0);
1347 QStringList pieces = columnText.split(" ", QString::SkipEmptyParts);
1348 if (pieces.size() >= 2) {
1349 columnText = pieces.at(0);
1350 pieces.pop_front();
1351 QString path = pieces.join(" ").trimmed();
1352 node = findNodeForTarget(path, relative, marker, atom);
1353 }
1354
1355 if (params.size() == 2) {
1356 numColumns = qMax(columnText.toInt(), numColumns);
1357 sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt();
1358 }
1359
1360 if (node)
1361 generateTableOfContents(node,
1362 marker,
1363 sectioningUnit,
1364 numColumns,
1365 relative);
1366 }
1367 break;
1368 case Atom::Target:
1369 writer.writeStartElement("p");
1370 writeGuidAttribute(Doc::canonicalTitle(atom->string()));
1371 writer.writeAttribute("outputclass","target");
1372 writer.writeCharacters(protectEnc(atom->string()));
1373 writer.writeEndElement(); // </p>
1374 break;
1375 case Atom::UnhandledFormat:
1376 writer.writeStartElement("b");
1377 writer.writeAttribute("outputclass","redFont");
1378 writer.writeCharacters("&lt;Missing DITAXML&gt");
1379 writer.writeEndElement(); // </b>
1380 break;
1381 case Atom::UnknownCommand:
1382 writer.writeStartElement("b");
1383 writer.writeAttribute("outputclass","redFont code");
1384 writer.writeCharacters(protectEnc(atom->string()));
1385 writer.writeEndElement(); // </b>
1386 break;
1387#ifdef QDOC_QML
1388 case Atom::QmlText:
1389 case Atom::EndQmlText:
1390 // don't do anything with these. They are just tags.
1391 break;
1392#endif
1393 default:
1394 // unknownAtom(atom);
1395 break;
1396 }
1397 return skipAhead;
1398}
1399
1400/*!
1401 Generate a reference page for a C++ class.
1402 */
1403void
1404DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* marker)
1405{
1406 QList<Section> sections;
1407 QList<Section>::ConstIterator s;
1408
1409 const ClassNode* cn = 0;
1410 const NamespaceNode* namespasse = 0;
1411
1412 QString title;
1413 QString rawTitle;
1414 QString fullTitle;
1415 if (inner->type() == Node::Namespace) {
1416 namespasse = const_cast<NamespaceNode*>(static_cast<const NamespaceNode*>(inner));
1417 rawTitle = marker->plainName(inner);
1418 fullTitle = marker->plainFullName(inner);
1419 title = rawTitle + " Namespace";
1420 }
1421 else if (inner->type() == Node::Class) {
1422 cn = const_cast<ClassNode*>(static_cast<const ClassNode*>(inner));
1423 rawTitle = marker->plainName(inner);
1424 fullTitle = marker->plainFullName(inner);
1425 title = rawTitle + " Class Reference";
1426
1427 generateHeader(inner);
1428
1429 writer.writeStartElement(CXXCLASS);
1430 writer.writeAttribute("id",cn->guid());
1431 writer.writeStartElement(APINAME);
1432 writer.writeCharacters(fullTitle);
1433 writer.writeEndElement(); // </apiName>
1434
1435 generateBrief(inner, marker);
1436
1437 writer.writeStartElement(CXXCLASSDETAIL);
1438 writer.writeStartElement(CXXCLASSDEFINITION);
1439 writer.writeStartElement(CXXCLASSACCESSSPECIFIER);
1440 writer.writeAttribute("value",inner->accessString());
1441 writer.writeEndElement(); // <cxxClassAccessSpecifier>
1442 if (cn->isAbstract()) {
1443 writer.writeStartElement(CXXCLASSABSTRACT);
1444 writer.writeAttribute("name","abstract");
1445 writer.writeAttribute("value","abstract");
1446 writer.writeEndElement(); // </cxxClassAbstract>
1447 }
1448 writeDerivations(cn, marker);
1449 writeLocation(cn);
1450 writer.writeEndElement(); // <cxxClassDefinition>
1451 writer.writeStartElement(APIDESC);
1452
1453 if (!inner->doc().isEmpty()) {
1454 writer.writeStartElement("p");
1455 writer.writeAttribute("outputclass","h2");
1456 writer.writeCharacters("Detailed Description");
1457 writer.writeEndElement(); // </p>
1458 generateBody(inner, marker);
1459 // generateAlsoList(inner, marker);
1460 }
1461
1462 writer.writeEndElement(); // </apiDesc>
1463 writer.writeEndElement(); // </cxxClassDetail>
1464
1465 sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
1466 s = sections.begin();
1467 while (s != sections.end()) {
1468 if ((*s).name == "Member Function Documentation") {
1469 writeFunctions((*s),cn,marker);
1470 }
1471 else if ((*s).name == "Member Type Documentation") {
1472 writeEnumerations((*s),cn,marker);
1473 writeTypedefs((*s),cn,marker);
1474 }
1475 else if ((*s).name == "Member Variable Documentation") {
1476 writeDataMembers((*s),cn,marker);
1477 }
1478 else if ((*s).name == "Property Documentation") {
1479 writeProperties((*s),cn,marker);
1480 }
1481 else if ((*s).name == "Macro Documentation") {
1482 writeMacros((*s),cn,marker);
1483 }
1484 ++s;
1485 }
1486 writer.writeEndElement(); // </cxxClass>
1487 }
1488
1489#ifdef WRITE_HTML
1490 Text subtitleText;
1491 if (rawTitle != fullTitle)
1492 subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")"
1493 << Atom(Atom::LineBreak);
1494
1495 QString shortVersion;
1496 shortVersion = project + " " + shortVersion + ": ";
1497 shortVersion = myTree->version();
1498 if (shortVersion.count(QChar('.')) == 2)
1499 shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
1500 if (!shortVersion.isEmpty()) {
1501 if (project == "QSA")
1502 shortVersion = "QSA " + shortVersion + ": ";
1503 else
1504 shortVersion = "Qt " + shortVersion + ": ";
1505 }
1506
1507 out() << " <title>" << shortVersion << protectEnc(title) << "</title>\n";
1508
1509#if 0
1510 out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
1511 generateBreadCrumbs(title,node,marker);
1512 out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
1513#endif
1514
1515 sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
1516 generateTableOfContents(inner,marker,&sections);
1517 generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
1518
1519#ifdef QDOC_QML
1520 if (cn && !cn->qmlElement().isEmpty()) {
1521 generateInstantiatedBy(cn,marker);
1522 }
1523#endif
1524
1525 generateBrief(inner, marker);
1526 generateIncludes(inner, marker);
1527 generateStatus(inner, marker);
1528 if (cn) {
1529 generateInherits(cn, marker);
1530 generateInheritedBy(cn, marker);
1531 }
1532 generateThreadSafeness(inner, marker);
1533 generateSince(inner, marker);
1534
1535 out() << "<ul>\n";
1536
1537 QString membersLink = generateListOfAllMemberFile(inner, marker);
1538 if (!membersLink.isEmpty())
1539 out() << "<li><xref href=\"" << membersLink << "\">"
1540 << "List of all members, including inherited members</xref></li>\n";
1541
1542 QString obsoleteLink = generateLowStatusMemberFile(inner,
1543 marker,
1544 CodeMarker::Obsolete);
1545 if (!obsoleteLink.isEmpty())
1546 out() << "<li><xref href=\"" << obsoleteLink << "\">"
1547 << "Obsolete members</xref></li>\n";
1548
1549 QString compatLink = generateLowStatusMemberFile(inner,
1550 marker,
1551 CodeMarker::Compat);
1552 if (!compatLink.isEmpty())
1553 out() << "<li><xref href=\"" << compatLink << "\">"
1554 << "Qt 3 support members</xref></li>\n";
1555
1556 out() << "</ul>\n";
1557
1558 bool needOtherSection = false;
1559
1560 /*
1561 sections is built above for the call to generateTableOfContents().
1562 */
1563 s = sections.begin();
1564 while (s != sections.end()) {
1565 if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
1566 if (!s->inherited.isEmpty())
1567 needOtherSection = true;
1568 }
1569 else {
1570 if (!s->members.isEmpty()) {
1571 out() << "<hr />\n";
1572 out() << "<a name=\""
1573 << registerRef((*s).name.toLower())
1574 << "\"></a>\n";
1575 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
1576 generateSection(s->members, inner, marker, CodeMarker::Summary);
1577 }
1578 if (!s->reimpMembers.isEmpty()) {
1579 QString name = QString("Reimplemented ") + (*s).name;
1580 out() << "<hr />\n";
1581 out() << "<a name=\""
1582 << registerRef(name.toLower())
1583 << "\"></a>\n";
1584 out() << "<h2>" << protectEnc(name) << "</h2>\n";
1585 generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
1586 }
1587
1588 if (!s->inherited.isEmpty()) {
1589 out() << "<ul>\n";
1590 generateSectionInheritedList(*s, inner, marker, true);
1591 out() << "</ul>\n";
1592 }
1593 }
1594 ++s;
1595 }
1596
1597 if (needOtherSection) {
1598 out() << "<h3>Additional Inherited Members</h3>\n"
1599 "<ul>\n";
1600
1601 s = sections.begin();
1602 while (s != sections.end()) {
1603 if (s->members.isEmpty() && !s->inherited.isEmpty())
1604 generateSectionInheritedList(*s, inner, marker);
1605 ++s;
1606 }
1607 out() << "</ul>\n";
1608 }
1609
1610 out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
1611
1612 if (!inner->doc().isEmpty()) {
1613 out() << "<hr />\n"
1614 << "<div class=\"descr\"/>\n" // QTBUG-9504
1615 << "<h2>" << "Detailed Description" << "</h2>\n";
1616 generateBody(inner, marker);
1617 out() << "</div>\n"; // QTBUG-9504
1618 generateAlsoList(inner, marker);
1619 }
1620
1621 sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
1622 s = sections.begin();
1623 while (s != sections.end()) {
1624 out() << "<hr />\n";
1625 if (!(*s).divClass.isEmpty())
1626 out() << "<div class=\"" << (*s).divClass << "\"/>\n"; // QTBUG-9504
1627 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
1628
1629 NodeList::ConstIterator m = (*s).members.begin();
1630 while (m != (*s).members.end()) {
1631 if ((*m)->access() != Node::Private) { // ### check necessary?
1632 if ((*m)->type() != Node::Class)
1633 generateDetailedMember(*m, inner, marker);
1634 else {
1635 out() << "<h3> class ";
1636 generateFullName(*m, inner, marker);
1637 out() << "</h3>";
1638 generateBrief(*m, marker, inner);
1639 }
1640
1641 QStringList names;
1642 names << (*m)->name();
1643 if ((*m)->type() == Node::Function) {
1644 const FunctionNode *func = reinterpret_cast<const FunctionNode *>(*m);
1645 if (func->metaness() == FunctionNode::Ctor ||
1646 func->metaness() == FunctionNode::Dtor ||
1647 func->overloadNumber() != 1)
1648 names.clear();
1649 }
1650 else if ((*m)->type() == Node::Property) {
1651 const PropertyNode *prop = reinterpret_cast<const PropertyNode *>(*m);
1652 if (!prop->getters().isEmpty() &&
1653 !names.contains(prop->getters().first()->name()))
1654 names << prop->getters().first()->name();
1655 if (!prop->setters().isEmpty())
1656 names << prop->setters().first()->name();
1657 if (!prop->resetters().isEmpty())
1658 names << prop->resetters().first()->name();
1659 }
1660 else if ((*m)->type() == Node::Enum) {
1661 const EnumNode *enume = reinterpret_cast<const EnumNode*>(*m);
1662 if (enume->flagsType())
1663 names << enume->flagsType()->name();
1664
1665 foreach (const QString &enumName,
1666 enume->doc().enumItemNames().toSet() -
1667 enume->doc().omitEnumItemNames().toSet())
1668 names << plainCode(marker->markedUpEnumValue(enumName,
1669 enume));
1670 }
1671 }
1672 ++m;
1673 }
1674 if (!(*s).divClass.isEmpty())
1675 out() << "</div>\n"; // QTBUG-9504
1676 ++s;
1677 }
1678#endif
1679}
1680
1681/*!
1682 Generate the html page for a qdoc file that doesn't map
1683 to an underlying c++ file.
1684 */
1685void DitaXmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
1686{
1687 return; // zzz
1688
1689 SubTitleSize subTitleSize = LargeSubTitle;
1690 QList<Section> sections;
1691 QList<Section>::const_iterator s;
1692 QString fullTitle = fake->fullTitle();
1693 QString htmlTitle = fullTitle;
1694
1695 if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) {
1696 subTitleSize = SmallSubTitle;
1697 htmlTitle += " (" + fake->subTitle() + ")";
1698 }
1699 else if (fake->subType() == Node::QmlBasicType) {
1700 fullTitle = "QML Basic Type: " + fullTitle;
1701 htmlTitle = fullTitle;
1702 }
1703
1704 generateHeader(fake);
1705
1706 /*
1707 Generate the TOC for the new doc format.
1708 Don't generate a TOC for the home page.
1709 */
1710 if (fake->name() != QString("index.html"))
1711 generateTableOfContents(fake,marker,0);
1712
1713 generateTitle(fullTitle,
1714 Text() << fake->subTitle(),
1715 subTitleSize,
1716 fake,
1717 marker);
1718
1719 if (fake->subType() == Node::Module) {
1720 // Generate brief text and status for modules.
1721 generateBrief(fake, marker);
1722 generateStatus(fake, marker);
1723
1724 if (moduleNamespaceMap.contains(fake->name())) {
1725 out() << "<a name=\"" << registerRef("namespaces") << "\"></a>\n";
1726 out() << "<h2>Namespaces</h2>\n";
1727 generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]);
1728 }
1729 if (moduleClassMap.contains(fake->name())) {
1730 out() << "<a name=\"" << registerRef("classes") << "\"></a>\n";
1731 out() << "<h2>Classes</h2>\n";
1732 generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
1733 }
1734 }
1735 else if (fake->subType() == Node::HeaderFile) {
1736 // Generate brief text and status for modules.
1737 generateBrief(fake, marker);
1738 generateStatus(fake, marker);
1739
1740 out() << "<ul>\n";
1741
1742 QString membersLink = generateListOfAllMemberFile(fake, marker);
1743 if (!membersLink.isEmpty())
1744 out() << "<li><xref href=\"" << membersLink << "\">"
1745 << "List of all members, including inherited members</xref></li>\n";
1746
1747 QString obsoleteLink = generateLowStatusMemberFile(fake,
1748 marker,
1749 CodeMarker::Obsolete);
1750 if (!obsoleteLink.isEmpty())
1751 out() << "<li><xref href=\"" << obsoleteLink << "\">"
1752 << "Obsolete members</xref></li>\n";
1753
1754 QString compatLink = generateLowStatusMemberFile(fake,
1755 marker,
1756 CodeMarker::Compat);
1757 if (!compatLink.isEmpty())
1758 out() << "<li><xref href=\"" << compatLink << "\">"
1759 << "Qt 3 support members</xref></li>\n";
1760
1761 out() << "</ul>\n";
1762 }
1763#ifdef QDOC_QML
1764 else if (fake->subType() == Node::QmlClass) {
1765 const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake);
1766 const ClassNode* cn = qml_cn->classNode();
1767 generateQmlInherits(qml_cn, marker);
1768 generateQmlInstantiates(qml_cn, marker);
1769 generateBrief(qml_cn, marker);
1770 generateQmlInheritedBy(qml_cn, marker);
1771 sections = marker->qmlSections(qml_cn,CodeMarker::Summary,0);
1772 s = sections.begin();
1773 while (s != sections.end()) {
1774 out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
1775 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
1776 generateQmlSummary(*s,fake,marker);
1777 ++s;
1778 }
1779
1780 out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
1781 out() << "<h2>" << "Detailed Description" << "</h2>\n";
1782 generateBody(fake, marker);
1783 if (cn)
1784 generateQmlText(cn->doc().body(), cn, marker, fake->name());
1785 generateAlsoList(fake, marker);
1786 out() << "<hr />\n";
1787
1788 sections = marker->qmlSections(qml_cn,CodeMarker::Detailed,0);
1789 s = sections.begin();
1790 while (s != sections.end()) {
1791 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
1792 NodeList::ConstIterator m = (*s).members.begin();
1793 while (m != (*s).members.end()) {
1794 generateDetailedQmlMember(*m, fake, marker);
1795 out() << "<br/>\n";
1796 ++m;
1797 }
1798 ++s;
1799 }
1800 return;
1801 }
1802#endif
1803
1804 sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay);
1805 s = sections.begin();
1806 while (s != sections.end()) {
1807 out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
1808 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
1809 generateSectionList(*s, fake, marker, CodeMarker::Summary);
1810 ++s;
1811 }
1812
1813 Text brief = fake->doc().briefText();
1814 if (fake->subType() == Node::Module && !brief.isEmpty()) {
1815 out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
1816 out() << "<div class=\"descr\"/>\n"; // QTBUG-9504
1817 out() << "<h2>" << "Detailed Description" << "</h2>\n";
1818 }
1819 else
1820 out() << "<div class=\"descr\"/>\n"; // QTBUG-9504
1821
1822 generateBody(fake, marker);
1823 out() << "</div>\n"; // QTBUG-9504
1824 generateAlsoList(fake, marker);
1825
1826 if (!fake->groupMembers().isEmpty()) {
1827 NodeMap groupMembersMap;
1828 foreach (const Node *node, fake->groupMembers()) {
1829 if (node->type() == Node::Class || node->type() == Node::Namespace)
1830 groupMembersMap[node->name()] = node;
1831 }
1832 generateAnnotatedList(fake, marker, groupMembersMap);
1833 }
1834
1835 sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay);
1836 s = sections.begin();
1837 while (s != sections.end()) {
1838 out() << "<hr />\n";
1839 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
1840
1841 NodeList::ConstIterator m = (*s).members.begin();
1842 while (m != (*s).members.end()) {
1843 generateDetailedMember(*m, fake, marker);
1844 ++m;
1845 }
1846 ++s;
1847 }
1848}
1849
1850/*!
1851 Returns "xml" for this subclass of Generator.
1852 */
1853QString DitaXmlGenerator::fileExtension(const Node * /* node */) const
1854{
1855 return "xml";
1856}
1857
1858/*!
1859 Output breadcrumb list in the html file.
1860 */
1861void DitaXmlGenerator::generateBreadCrumbs(const QString& title,
1862 const Node *node,
1863 CodeMarker *marker)
1864{
1865 Text breadcrumb;
1866 if (node->type() == Node::Class) {
1867 const ClassNode* cn = static_cast<const ClassNode*>(node);
1868 QString name = node->moduleName();
1869 out() << " <li><xref href=\"modules.html\">All Modules</xref></li>";
1870 if (!name.isEmpty()) {
1871 out() << " <li>";
1872 breadcrumb << Atom(Atom::AutoLink,name);
1873 generateText(breadcrumb, node, marker);
1874 out() << "</li>\n";
1875 }
1876 breadcrumb.clear();
1877 if (!cn->name().isEmpty()) {
1878 out() << " <li>";
1879 breadcrumb << Atom(Atom::AutoLink,cn->name());
1880 generateText(breadcrumb, 0, marker);
1881 out() << "</li>\n";
1882 }
1883 }
1884 else if (node->type() == Node::Fake) {
1885 const FakeNode* fn = static_cast<const FakeNode*>(node);
1886 if (node->subType() == Node::Module) {
1887 out() << " <li><xref href=\"modules.html\">All Modules</xref></li>";
1888 QString name = node->name();
1889 if (!name.isEmpty()) {
1890 out() << " <li>";
1891 breadcrumb << Atom(Atom::AutoLink,name);
1892 generateText(breadcrumb, 0, marker);
1893 out() << "</li>\n";
1894 }
1895 }
1896 else if (node->subType() == Node::Group) {
1897 if (fn->name() == QString("modules"))
1898 out() << " <li><xref href=\"modules.html\">All Modules</xref></li>";
1899 else {
1900 out() << " <li><xref href=\"" << fn->name() << "\">" << title
1901 << "</xref></li>";
1902 }
1903 }
1904 else if (node->subType() == Node::Page) {
1905 if (fn->name() == QString("examples.html")) {
1906 out() << " <li><xref href=\"all-examples.html\">Examples</xref></li>";
1907 }
1908 else if (fn->name().startsWith("examples-")) {
1909 out() << " <li><xref href=\"all-examples.html\">Examples</xref></li>";
1910 out() << " <li><xref href=\"" << fn->name() << "\">" << title
1911 << "</xref></li>";
1912 }
1913 else if (fn->name() == QString("namespaces.html")) {
1914 out() << " <li><xref href=\"namespaces.html\">All Namespaces</xref></li>";
1915 }
1916 else {
1917 out() << " <li><xref href=\"" << fn->name() << "\">" << title
1918 << "</xref></li>";
1919 }
1920 }
1921 else if (node->subType() == Node::QmlClass) {
1922 out() << " <li><xref href=\"qdeclarativeelements.html\">QML Elements</xref></li>";
1923 out() << " <li><xref href=\"" << fn->name() << "\">" << title
1924 << "</xref></li>";
1925 }
1926 else if (node->subType() == Node::Example) {
1927 out() << " <li><xref href=\"all-examples.html\">Examples</xref></li>";
1928 QStringList sl = fn->name().split('/');
1929 QString name = "examples-" + sl.at(0) + ".html";
1930 QString t = CodeParser::titleFromName(name);
1931 out() << " <li><xref href=\"" << name << "\">"
1932 << t << "</xref></li>";
1933 out() << " <li><xref href=\"" << sl.at(0)
1934 << "-" << sl.at(sl.size()-1) << ".html\">"
1935 << title << "</xref></li>";
1936 }
1937 }
1938 else if (node->type() == Node::Namespace) {
1939 const NamespaceNode* nsn = static_cast<const NamespaceNode*>(node);
1940 out() << " <li><xref href=\"namespaces.html\">All Namespaces</xref></li>";
1941 out() << " <li><xref href=\"" << fileName(nsn) << "\">" << title
1942 << "</xref></li>";
1943 }
1944}
1945
1946void DitaXmlGenerator::generateHeader(const Node* node)
1947{
1948 writer.setDevice(out().device());
1949 writer.setAutoFormatting(true);
1950 writer.setAutoFormattingIndent(4);
1951 writer.writeStartDocument();
1952
1953 if (!node)
1954 return;
1955
1956 QString docType;
1957 QString dtd;
1958 QString version;
1959 if (node->type() == Node::Class) {
1960 docType = "cxxClass";
1961 dtd = "dtd/cxxClass.dtd";
1962 version = "0.6.0";
1963 }
1964
1965 QString doctype = "<!DOCTYPE " + docType +
1966 " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
1967 version + "//EN\" \"" + dtd + "\">";
1968 writer.writeDTD(doctype);
1969 writer.writeComment(node->doc().location().fileName());
1970}
1971
1972void DitaXmlGenerator::generateTitle(const QString& title,
1973 const Text &subTitle,
1974 SubTitleSize subTitleSize,
1975 const Node *relative,
1976 CodeMarker *marker)
1977{
1978 if (!title.isEmpty())
1979 out() << "<h1 class=\"title\">" << protectEnc(title) << "</h1>\n";
1980 if (!subTitle.isEmpty()) {
1981 out() << "<span";
1982 if (subTitleSize == SmallSubTitle)
1983 out() << " class=\"small-subtitle\">";
1984 else
1985 out() << " class=\"subtitle\">";
1986 generateText(subTitle, relative, marker);
1987 out() << "</span>\n";
1988 }
1989}
1990
1991/*!
1992 Outputs the brief command as a <shortdesc" element.
1993 */
1994void DitaXmlGenerator::generateBrief(const Node* node, CodeMarker* marker)
1995{
1996 Text brief = node->doc().briefText();
1997 if (!brief.isEmpty()) {
1998 ++noLinks;
1999 writer.writeStartElement(SHORTDESC);
2000 generateText(brief, node, marker);
2001 writer.writeEndElement(); // shortdesc
2002 --noLinks;
2003 }
2004}
2005
2006void DitaXmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker)
2007{
2008 if (!inner->includes().isEmpty()) {
2009 out() << "<pre class=\"highlightedCode\">"
2010 << trimmedTrailing(highlightedCode(indent(codeIndent,
2011 marker->markedUpIncludes(inner->includes())),
2012 marker,inner))
2013 << "</pre>";
2014 }
2015}
2016
2017/*!
2018 Generates a table of contents beginning at \a node.
2019 */
2020void DitaXmlGenerator::generateTableOfContents(const Node *node,
2021 CodeMarker *marker,
2022 Doc::SectioningUnit sectioningUnit,
2023 int numColumns,
2024 const Node *relative)
2025
2026{
2027 return;
2028 if (!node->doc().hasTableOfContents())
2029 return;
2030 QList<Atom *> toc = node->doc().tableOfContents();
2031 if (toc.isEmpty())
2032 return;
2033
2034 QString nodeName = "";
2035 if (node != relative)
2036 nodeName = node->name();
2037
2038 QStringList sectionNumber;
2039 int columnSize = 0;
2040
2041 QString tdTag;
2042 if (numColumns > 1) {
2043 tdTag = "<td>"; /* width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";*/
2044 out() << "<table class=\"toc\">\n<tr class=\"topAlign\">"
2045 << tdTag << "\n";
2046 }
2047
2048 // disable nested links in table of contents
2049 inContents = true;
2050 inLink = true;
2051
2052 for (int i = 0; i < toc.size(); ++i) {
2053 Atom *atom = toc.at(i);
2054
2055 int nextLevel = atom->string().toInt();
2056 if (nextLevel > (int)sectioningUnit)
2057 continue;
2058
2059 if (sectionNumber.size() < nextLevel) {
2060 do {
2061 out() << "<ul>";
2062 sectionNumber.append("1");
2063 } while (sectionNumber.size() < nextLevel);
2064 }
2065 else {
2066 while (sectionNumber.size() > nextLevel) {
2067 out() << "</ul>\n";
2068 sectionNumber.removeLast();
2069 }
2070 sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
2071 }
2072 int numAtoms;
2073 Text headingText = Text::sectionHeading(atom);
2074
2075 if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) {
2076 out() << "</ul></td>" << tdTag << "<ul>\n";
2077 columnSize = 0;
2078 }
2079 out() << "<li>";
2080 out() << "<xref href=\""
2081 << nodeName
2082 << "#"
2083 << Doc::canonicalTitle(headingText.toString())
2084 << "\">";
2085 generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
2086 out() << "</xref></li>\n";
2087
2088 ++columnSize;
2089 }
2090 while (!sectionNumber.isEmpty()) {
2091 out() << "</ul>\n";
2092 sectionNumber.removeLast();
2093 }
2094
2095 if (numColumns > 1)
2096 out() << "</td></tr></table>\n";
2097
2098 inContents = false;
2099 inLink = false;
2100}
2101
2102/*!
2103 Revised for the new doc format.
2104 Generates a table of contents beginning at \a node.
2105 */
2106void DitaXmlGenerator::generateTableOfContents(const Node *node,
2107 CodeMarker *marker,
2108 QList<Section>* sections)
2109{
2110 QList<Atom*> toc;
2111 if (node->doc().hasTableOfContents())
2112 toc = node->doc().tableOfContents();
2113 if (toc.isEmpty() && !sections && (node->subType() != Node::Module))
2114 return;
2115
2116 QStringList sectionNumber;
2117 int detailsBase = 0;
2118
2119 // disable nested links in table of contents
2120 inContents = true;
2121 inLink = true;
2122
2123 out() << "<div class=\"toc\">\n";
2124 out() << "<h3>Contents</h3>\n";
2125 sectionNumber.append("1");
2126 out() << "<ul>\n";
2127
2128 if (node->subType() == Node::Module) {
2129 if (moduleNamespaceMap.contains(node->name())) {
2130 out() << "<li class=\"level"
2131 << sectionNumber.size()
2132 << "\"><xref href=\"#"
2133 << registerRef("namespaces")
2134 << "\">Namespaces</xref></li>\n";
2135 }
2136 if (moduleClassMap.contains(node->name())) {
2137 out() << "<li class=\"level"
2138 << sectionNumber.size()
2139 << "\"><xref href=\"#"
2140 << registerRef("classes")
2141 << "\">Classes</xref></li>\n";
2142 }
2143 out() << "<li class=\"level"
2144 << sectionNumber.size()
2145 << "\"><xref href=\"#"
2146 << registerRef("details")
2147 << "\">Detailed Description</xref></li>\n";
2148 for (int i = 0; i < toc.size(); ++i) {
2149 if (toc.at(i)->string().toInt() == 1) {
2150 detailsBase = 1;
2151 break;
2152 }
2153 }
2154 }
2155 else if (sections && (node->type() == Node::Class)) {
2156 QList<Section>::ConstIterator s = sections->begin();
2157 while (s != sections->end()) {
2158 if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) {
2159 out() << "<li class=\"level"
2160 << sectionNumber.size()
2161 << "\"><xref href=\"#"
2162 << registerRef((*s).pluralMember)
2163 << "\">" << (*s).name
2164 << "</xref></li>\n";
2165 }
2166 ++s;
2167 }
2168 out() << "<li class=\"level"
2169 << sectionNumber.size()
2170 << "\"><xref href=\"#"
2171 << registerRef("details")
2172 << "\">Detailed Description</xref></li>\n";
2173 for (int i = 0; i < toc.size(); ++i) {
2174 if (toc.at(i)->string().toInt() == 1) {
2175 detailsBase = 1;
2176 break;
2177 }
2178 }
2179 }
2180
2181 for (int i = 0; i < toc.size(); ++i) {
2182 Atom *atom = toc.at(i);
2183 int nextLevel = atom->string().toInt() + detailsBase;
2184 if (sectionNumber.size() < nextLevel) {
2185 do {
2186 sectionNumber.append("1");
2187 } while (sectionNumber.size() < nextLevel);
2188 }
2189 else {
2190 while (sectionNumber.size() > nextLevel) {
2191 sectionNumber.removeLast();
2192 }
2193 sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
2194 }
2195 int numAtoms;
2196 Text headingText = Text::sectionHeading(atom);
2197 QString s = headingText.toString();
2198 out() << "<li class=\"level"
2199 << sectionNumber.size()
2200 << "\">";
2201 out() << "<xref href=\""
2202 << "#"
2203 << Doc::canonicalTitle(s)
2204 << "\">";
2205 generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
2206 out() << "</xref></li>\n";
2207 }
2208 while (!sectionNumber.isEmpty()) {
2209 sectionNumber.removeLast();
2210 }
2211 out() << "</ul>\n";
2212 out() << "</div>\n";
2213 inContents = false;
2214 inLink = false;
2215}
2216
2217QString DitaXmlGenerator::generateListOfAllMemberFile(const InnerNode *inner,
2218 CodeMarker *marker)
2219{
2220 QList<Section> sections;
2221 QList<Section>::ConstIterator s;
2222
2223 sections = marker->sections(inner,
2224 CodeMarker::SeparateList,
2225 CodeMarker::Okay);
2226 if (sections.isEmpty())
2227 return QString();
2228
2229 QString fileName = fileBase(inner) + "-members." + fileExtension(inner);
2230 beginSubPage(inner->location(), fileName);
2231 QString title = "List of All Members for " + inner->name();
2232 generateHeader(inner);
2233 generateTitle(title, Text(), SmallSubTitle, inner, marker);
2234 out() << "<p>This is the complete list of members for ";
2235 generateFullName(inner, 0, marker);
2236 out() << ", including inherited members.</p>\n";
2237
2238 Section section = sections.first();
2239 generateSectionList(section, 0, marker, CodeMarker::SeparateList);
2240
2241 endSubPage();
2242 return fileName;
2243}
2244
2245QString DitaXmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
2246 CodeMarker *marker,
2247 CodeMarker::Status status)
2248{
2249 QList<Section> sections = marker->sections(inner,
2250 CodeMarker::Summary,
2251 status);
2252 QMutableListIterator<Section> j(sections);
2253 while (j.hasNext()) {
2254 if (j.next().members.size() == 0)
2255 j.remove();
2256 }
2257 if (sections.isEmpty())
2258 return QString();
2259
2260 int i;
2261
2262 QString title;
2263 QString fileName;
2264
2265 if (status == CodeMarker::Compat) {
2266 title = "Qt 3 Support Members for " + inner->name();
2267 fileName = fileBase(inner) + "-qt3." + fileExtension(inner);
2268 }
2269 else {
2270 title = "Obsolete Members for " + inner->name();
2271 fileName = fileBase(inner) + "-obsolete." + fileExtension(inner);
2272 }
2273
2274 beginSubPage(inner->location(), fileName);
2275 generateHeader(inner);
2276 generateTitle(title, Text(), SmallSubTitle, inner, marker);
2277
2278 if (status == CodeMarker::Compat) {
2279 out() << "<p><b>The following class members are part of the "
2280 "<xref href=\"qt3support.html\">Qt 3 support layer</xref>.</b> "
2281 "They are provided to help you port old code to Qt 4. We advise against "
2282 "using them in new code.</p>\n";
2283 }
2284 else {
2285 out() << "<p><b>The following class members are obsolete.</b> "
2286 << "They are provided to keep old source code working. "
2287 << "We strongly advise against using them in new code.</p>\n";
2288 }
2289
2290 out() << "<p><ul><li><xref href=\""
2291 << linkForNode(inner, 0) << "\">"
2292 << protectEnc(inner->name())
2293 << " class reference</xref></li></ul></p>\n";
2294
2295 for (i = 0; i < sections.size(); ++i) {
2296 out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n";
2297 generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary);
2298 }
2299
2300 sections = marker->sections(inner, CodeMarker::Detailed, status);
2301 for (i = 0; i < sections.size(); ++i) {
2302 out() << "<hr />\n";
2303 out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n";
2304
2305 NodeList::ConstIterator m = sections.at(i).members.begin();
2306 while (m != sections.at(i).members.end()) {
2307 if ((*m)->access() != Node::Private)
2308 generateDetailedMember(*m, inner, marker);
2309 ++m;
2310 }
2311 }
2312
2313 endSubPage();
2314 return fileName;
2315}
2316
2317void DitaXmlGenerator::generateClassHierarchy(const Node *relative,
2318 CodeMarker *marker,
2319 const QMap<QString,const Node*> &classMap)
2320{
2321 if (classMap.isEmpty())
2322 return;
2323
2324 NodeMap topLevel;
2325 NodeMap::ConstIterator c = classMap.begin();
2326 while (c != classMap.end()) {
2327 const ClassNode *classe = static_cast<const ClassNode *>(*c);
2328 if (classe->baseClasses().isEmpty())
2329 topLevel.insert(classe->name(), classe);
2330 ++c;
2331 }
2332
2333 QStack<NodeMap > stack;
2334 stack.push(topLevel);
2335
2336 out() << "<ul>\n";
2337 while (!stack.isEmpty()) {
2338 if (stack.top().isEmpty()) {
2339 stack.pop();
2340 out() << "</ul>\n";
2341 }
2342 else {
2343 const ClassNode *child =
2344 static_cast<const ClassNode *>(*stack.top().begin());
2345 out() << "<li>";
2346 generateFullName(child, relative, marker);
2347 out() << "</li>\n";
2348 stack.top().erase(stack.top().begin());
2349
2350 NodeMap newTop;
2351 foreach (const RelatedClass &d, child->derivedClasses()) {
2352 if (d.access != Node::Private)
2353 newTop.insert(d.node->name(), d.node);
2354 }
2355 if (!newTop.isEmpty()) {
2356 stack.push(newTop);
2357 out() << "<ul>\n";
2358 }
2359 }
2360 }
2361}
2362
2363void DitaXmlGenerator::generateAnnotatedList(const Node *relative,
2364 CodeMarker *marker,
2365 const NodeMap &nodeMap)
2366{
2367 out() << "<table class=\"annotated\">\n";
2368
2369 int row = 0;
2370 foreach (const QString &name, nodeMap.keys()) {
2371 const Node *node = nodeMap[name];
2372
2373 if (node->status() == Node::Obsolete)
2374 continue;
2375
2376 if (++row % 2 == 1)
2377 out() << "<tr class=\"odd topAlign\">";
2378 else
2379 out() << "<tr class=\"even topAlign\">";
2380 out() << "<td><p>";
2381 generateFullName(node, relative, marker);
2382 out() << "</p></td>";
2383
2384 if (!(node->type() == Node::Fake)) {
2385 Text brief = node->doc().trimmedBriefText(name);
2386 if (!brief.isEmpty()) {
2387 out() << "<td><p>";
2388 generateText(brief, node, marker);
2389 out() << "</p></td>";
2390 }
2391 }
2392 else {
2393 out() << "<td><p>";
2394 out() << protectEnc(node->doc().briefText().toString());
2395 out() << "</p></td>";
2396 }
2397 out() << "</tr>\n";
2398 }
2399 out() << "</table>\n";
2400}
2401
2402/*!
2403 This function finds the common prefix of the names of all
2404 the classes in \a classMap and then generates a compact
2405 list of the class names alphabetized on the part of the
2406 name not including the common prefix. You can tell the
2407 function to use \a comonPrefix as the common prefix, but
2408 normally you let it figure it out itself by looking at
2409 the name of the first and last classes in \a classMap.
2410 */
2411void DitaXmlGenerator::generateCompactList(const Node *relative,
2412 CodeMarker *marker,
2413 const NodeMap &classMap,
2414 bool includeAlphabet,
2415 QString commonPrefix)
2416{
2417 const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_'
2418
2419 if (classMap.isEmpty())
2420 return;
2421
2422 /*
2423 If commonPrefix is not empty, then the caller knows what
2424 the common prefix is and has passed it in, so just use that
2425 one.
2426 */
2427 int commonPrefixLen = commonPrefix.length();
2428 if (commonPrefixLen == 0) {
2429 QString first;
2430 QString last;
2431
2432 /*
2433 The caller didn't pass in a common prefix, so get the common
2434 prefix by looking at the class names of the first and last
2435 classes in the class map. Discard any namespace names and
2436 just use the bare class names. For Qt, the prefix is "Q".
2437
2438 Note that the algorithm used here to derive the common prefix
2439 from the first and last classes in alphabetical order (QAccel
2440 and QXtWidget in Qt 2.1), fails if either class name does not
2441 begin with Q.
2442 */
2443
2444 NodeMap::const_iterator iter = classMap.begin();
2445 while (iter != classMap.end()) {
2446 if (!iter.key().contains("::")) {
2447 first = iter.key();
2448 break;
2449 }
2450 ++iter;
2451 }
2452
2453 if (first.isEmpty())
2454 first = classMap.begin().key();
2455
2456 iter = classMap.end();
2457 while (iter != classMap.begin()) {
2458 --iter;
2459 if (!iter.key().contains("::")) {
2460 last = iter.key();
2461 break;
2462 }
2463 }
2464
2465 if (last.isEmpty())
2466 last = classMap.begin().key();
2467
2468 if (classMap.size() > 1) {
2469 while (commonPrefixLen < first.length() + 1 &&
2470 commonPrefixLen < last.length() + 1 &&
2471 first[commonPrefixLen] == last[commonPrefixLen])
2472 ++commonPrefixLen;
2473 }
2474
2475 commonPrefix = first.left(commonPrefixLen);
2476 }
2477
2478 /*
2479 Divide the data into 37 paragraphs: 0, ..., 9, A, ..., Z,
2480 underscore (_). QAccel will fall in paragraph 10 (A) and
2481 QXtWidget in paragraph 33 (X). This is the only place where we
2482 assume that NumParagraphs is 37. Each paragraph is a NodeMap.
2483 */
2484 NodeMap paragraph[NumParagraphs+1];
2485 QString paragraphName[NumParagraphs+1];
2486 QSet<char> usedParagraphNames;
2487
2488 NodeMap::ConstIterator c = classMap.begin();
2489 while (c != classMap.end()) {
2490 QStringList pieces = c.key().split("::");
2491 QString key;
2492 int idx = commonPrefixLen;
2493 if (!pieces.last().startsWith(commonPrefix))
2494 idx = 0;
2495 if (pieces.size() == 1)
2496 key = pieces.last().mid(idx).toLower();
2497 else
2498 key = pieces.last().toLower();
2499
2500 int paragraphNr = NumParagraphs - 1;
2501
2502 if (key[0].digitValue() != -1) {
2503 paragraphNr = key[0].digitValue();
2504 }
2505 else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
2506 paragraphNr = 10 + key[0].unicode() - 'a';
2507 }
2508
2509 paragraphName[paragraphNr] = key[0].toUpper();
2510 usedParagraphNames.insert(key[0].toLower().cell());
2511 paragraph[paragraphNr].insert(key, c.value());
2512 ++c;
2513 }
2514
2515 /*
2516 Each paragraph j has a size: paragraph[j].count(). In the
2517 discussion, we will assume paragraphs 0 to 5 will have sizes
2518 3, 1, 4, 1, 5, 9.
2519
2520 We now want to compute the paragraph offset. Paragraphs 0 to 6
2521 start at offsets 0, 3, 4, 8, 9, 14, 23.
2522 */
2523 int paragraphOffset[NumParagraphs + 1]; // 37 + 1
2524 paragraphOffset[0] = 0;
2525 for (int i=0; i<NumParagraphs; i++) // i = 0..36
2526 paragraphOffset[i+1] = paragraphOffset[i] + paragraph[i].count();
2527
2528 int curParNr = 0;
2529 int curParOffset = 0;
2530
2531 /*
2532 Output the alphabet as a row of links.
2533 */
2534 if (includeAlphabet) {
2535 out() << "<p class=\"centerAlign functionIndex\"><b>";
2536 for (int i = 0; i < 26; i++) {
2537 QChar ch('a' + i);
2538 if (usedParagraphNames.contains(char('a' + i)))
2539 out() << QString("<xref href=\"#%1\">%2</xref>&nbsp;").arg(ch).arg(ch.toUpper());
2540 }
2541 out() << "</b></p>\n";
2542 }
2543
2544 /*
2545 Output a <div> element to contain all the <dl> elements.
2546 */
2547 out() << "<div class=\"flowListDiv\">\n";
2548
2549 for (int i=0; i<classMap.count()-1; i++) {
2550 while ((curParNr < NumParagraphs) &&
2551 (curParOffset == paragraph[curParNr].count())) {
2552 ++curParNr;
2553 curParOffset = 0;
2554 }
2555
2556 /*
2557 Starting a new paragraph means starting a new <dl>.
2558 */
2559 if (curParOffset == 0) {
2560 if (i > 0)
2561 out() << "</dl>\n";
2562 if (++numTableRows % 2 == 1)
2563 out() << "<dl class=\"flowList odd\">";
2564 else
2565 out() << "<dl class=\"flowList even\">";
2566 out() << "<dt class=\"alphaChar\">";
2567 if (includeAlphabet) {
2568 QChar c = paragraphName[curParNr][0].toLower();
2569 out() << QString("<a name=\"%1\"></a>").arg(c);
2570 }
2571 out() << "<b>"
2572 << paragraphName[curParNr]
2573 << "</b>";
2574 out() << "</dt>\n";
2575 }
2576
2577 /*
2578 Output a <dd> for the current offset in the current paragraph.
2579 */
2580 out() << "<dd>";
2581 if ((curParNr < NumParagraphs) &&
2582 !paragraphName[curParNr].isEmpty()) {
2583 NodeMap::Iterator it;
2584 it = paragraph[curParNr].begin();
2585 for (int i=0; i<curParOffset; i++)
2586 ++it;
2587
2588 /*
2589 Previously, we used generateFullName() for this, but we
2590 require some special formatting.
2591 */
2592 out() << "<xref href=\"" << linkForNode(it.value(), relative) << "\">";
2593
2594 QStringList pieces;
2595 if (it.value()->subType() == Node::QmlClass)
2596 pieces << it.value()->name();
2597 else
2598 pieces = fullName(it.value(), relative, marker).split("::");
2599 out() << protectEnc(pieces.last());
2600 out() << "</xref>";
2601 if (pieces.size() > 1) {
2602 out() << " (";
2603 generateFullName(it.value()->parent(), relative, marker);
2604 out() << ")";
2605 }
2606 }
2607 out() << "</dd>\n";
2608 curParOffset++;
2609 }
2610 out() << "</dl>\n";
2611 out() << "</div>\n";
2612}
2613
2614void DitaXmlGenerator::generateFunctionIndex(const Node *relative,
2615 CodeMarker *marker)
2616{
2617 out() << "<p class=\"centerAlign functionIndex\"><b>";
2618 for (int i = 0; i < 26; i++) {
2619 QChar ch('a' + i);
2620 out() << QString("<xref href=\"#%1\">%2</xref>&nbsp;").arg(ch).arg(ch.toUpper());
2621 }
2622 out() << "</b></p>\n";
2623
2624 char nextLetter = 'a';
2625 char currentLetter;
2626
2627#if 1
2628 out() << "<ul>\n";
2629#endif
2630 QMap<QString, NodeMap >::ConstIterator f = funcIndex.begin();
2631 while (f != funcIndex.end()) {
2632#if 1
2633 out() << "<li>";
2634#else
2635 out() << "<p>";
2636#endif
2637 out() << protectEnc(f.key()) << ":";
2638
2639 currentLetter = f.key()[0].unicode();
2640 while (islower(currentLetter) && currentLetter >= nextLetter) {
2641 out() << QString("<a name=\"%1\"></a>").arg(nextLetter);
2642 nextLetter++;
2643 }
2644
2645 NodeMap::ConstIterator s = (*f).begin();
2646 while (s != (*f).end()) {
2647 out() << " ";
2648 generateFullName((*s)->parent(), relative, marker, *s);
2649 ++s;
2650 }
2651#if 1
2652 out() << "</li>";
2653#else
2654 out() << "</p>";
2655#endif
2656 out() << "\n";
2657 ++f;
2658 }
2659#if 1
2660 out() << "</ul>\n";
2661#endif
2662}
2663
2664void DitaXmlGenerator::generateLegaleseList(const Node *relative,
2665 CodeMarker *marker)
2666{
2667 QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin();
2668 while (it != legaleseTexts.end()) {
2669 Text text = it.key();
2670 out() << "<hr />\n";
2671 generateText(text, relative, marker);
2672 out() << "<ul>\n";
2673 do {
2674 out() << "<li>";
2675 generateFullName(it.value(), relative, marker);
2676 out() << "</li>\n";
2677 ++it;
2678 } while (it != legaleseTexts.end() && it.key() == text);
2679 out() << "</ul>\n";
2680 }
2681}
2682
2683/*void DitaXmlGenerator::generateSynopsis(const Node *node,
2684 const Node *relative,
2685 CodeMarker *marker,
2686 CodeMarker::SynopsisStyle style)
2687{
2688 QString marked = marker->markedUpSynopsis(node, relative, style);
2689 QRegExp templateTag("(<[^@>]*>)");
2690 if (marked.indexOf(templateTag) != -1) {
2691 QString contents = protectEnc(marked.mid(templateTag.pos(1),
2692 templateTag.cap(1).length()));
2693 marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
2694 contents);
2695 }
2696 marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
2697 "<i>\\1<sub>\\2</sub></i>");
2698 marked.replace("<@param>", "<i>");
2699 marked.replace("</@param>", "</i>");
2700
2701 if (style == CodeMarker::Summary)
2702 marked.replace("@name>", "b>");
2703
2704 if (style == CodeMarker::SeparateList) {
2705 QRegExp extraRegExp("<@extra>.*</@extra>");
2706 extraRegExp.setMinimal(true);
2707 marked.replace(extraRegExp, "");
2708 }
2709 else {
2710 marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
2711 marked.replace("</@extra>", "</tt>");
2712 }
2713
2714 if (style != CodeMarker::Detailed) {
2715 marked.replace("<@type>", "");
2716 marked.replace("</@type>", "");
2717 }
2718 out() << highlightedCode(marked, marker, relative);
2719}*/
2720
2721#ifdef QDOC_QML
2722void DitaXmlGenerator::generateQmlItem(const Node *node,
2723 const Node *relative,
2724 CodeMarker *marker,
2725 bool summary)
2726{
2727 QString marked = marker->markedUpQmlItem(node,summary);
2728 QRegExp templateTag("(<[^@>]*>)");
2729 if (marked.indexOf(templateTag) != -1) {
2730 QString contents = protectEnc(marked.mid(templateTag.pos(1),
2731 templateTag.cap(1).length()));
2732 marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
2733 contents);
2734 }
2735 marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
2736 "<i>\\1<sub>\\2</sub></i>");
2737 marked.replace("<@param>", "<i>");
2738 marked.replace("</@param>", "</i>");
2739
2740 if (summary)
2741 marked.replace("@name>", "b>");
2742
2743 marked.replace("<@extra>", "<tt>");
2744 marked.replace("</@extra>", "</tt>");
2745
2746 if (summary) {
2747 marked.replace("<@type>", "");
2748 marked.replace("</@type>", "");
2749 }
2750 out() << highlightedCode(marked, marker, relative);
2751}
2752#endif
2753
2754void DitaXmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */)
2755{
2756 QMap<const FakeNode *, QMap<QString, FakeNode *> > fakeNodeMap;
2757 QMap<QString, const FakeNode *> groupTitlesMap;
2758 QMap<QString, FakeNode *> uncategorizedNodeMap;
2759 QRegExp singleDigit("\\b([0-9])\\b");
2760
2761 const NodeList children = myTree->root()->childNodes();
2762 foreach (Node *child, children) {
2763 if (child->type() == Node::Fake && child != relative) {
2764 FakeNode *fakeNode = static_cast<FakeNode *>(child);
2765
2766 // Check whether the page is part of a group or is the group
2767 // definition page.
2768 QString group;
2769 bool isGroupPage = false;
2770 if (fakeNode->doc().metaCommandsUsed().contains("group")) {
2771 group = fakeNode->doc().metaCommandArgs("group")[0];
2772 isGroupPage = true;
2773 }
2774
2775 // there are too many examples; they would clutter the list
2776 if (fakeNode->subType() == Node::Example)
2777 continue;
2778
2779 // not interested either in individual (Qt Designer etc.) manual chapters
2780 if (fakeNode->links().contains(Node::ContentsLink))
2781 continue;
2782
2783 // Discard external nodes.
2784 if (fakeNode->subType() == Node::ExternalPage)
2785 continue;
2786
2787 QString sortKey = fakeNode->fullTitle().toLower();
2788 if (sortKey.startsWith("the "))
2789 sortKey.remove(0, 4);
2790 sortKey.replace(singleDigit, "0\\1");
2791
2792 if (!group.isEmpty()) {
2793 if (isGroupPage) {
2794 // If we encounter a group definition page, we add all
2795 // the pages in that group to the list for that group.
2796 foreach (Node *member, fakeNode->groupMembers()) {
2797 if (member->type() != Node::Fake)
2798 continue;
2799 FakeNode *page = static_cast<FakeNode *>(member);
2800 if (page) {
2801 QString sortKey = page->fullTitle().toLower();
2802 if (sortKey.startsWith("the "))
2803 sortKey.remove(0, 4);
2804 sortKey.replace(singleDigit, "0\\1");
2805 fakeNodeMap[const_cast<const FakeNode *>(fakeNode)].insert(sortKey, page);
2806 groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode);
2807 }
2808 }
2809 }
2810 else if (!isGroupPage) {
2811 // If we encounter a page that belongs to a group then
2812 // we add that page to the list for that group.
2813 const FakeNode *groupNode = static_cast<const FakeNode *>(myTree->root()->findNode(group, Node::Fake));
2814 if (groupNode)
2815 fakeNodeMap[groupNode].insert(sortKey, fakeNode);
2816 //else
2817 // uncategorizedNodeMap.insert(sortKey, fakeNode);
2818 }// else
2819 // uncategorizedNodeMap.insert(sortKey, fakeNode);
2820 }// else
2821 // uncategorizedNodeMap.insert(sortKey, fakeNode);
2822 }
2823 }
2824
2825 // We now list all the pages found that belong to groups.
2826 // If only certain pages were found for a group, but the definition page
2827 // for that group wasn't listed, the list of pages will be intentionally
2828 // incomplete. However, if the group definition page was listed, all the
2829 // pages in that group are listed for completeness.
2830
2831 if (!fakeNodeMap.isEmpty()) {
2832 foreach (const QString &groupTitle, groupTitlesMap.keys()) {
2833 const FakeNode *groupNode = groupTitlesMap[groupTitle];
2834 out() << QString("<h3><xref href=\"%1\">%2</xref></h3>\n").arg(
2835 linkForNode(groupNode, relative)).arg(
2836 protectEnc(groupNode->fullTitle()));
2837
2838 if (fakeNodeMap[groupNode].count() == 0)
2839 continue;
2840
2841 out() << "<ul>\n";
2842
2843 foreach (const FakeNode *fakeNode, fakeNodeMap[groupNode]) {
2844 QString title = fakeNode->fullTitle();
2845 if (title.startsWith("The "))
2846 title.remove(0, 4);
2847 out() << "<li><xref href=\"" << linkForNode(fakeNode, relative) << "\">"
2848 << protectEnc(title) << "</xref></li>\n";
2849 }
2850 out() << "</ul>\n";
2851 }
2852 }
2853
2854 if (!uncategorizedNodeMap.isEmpty()) {
2855 out() << QString("<h3>Miscellaneous</h3>\n");
2856 out() << "<ul>\n";
2857 foreach (const FakeNode *fakeNode, uncategorizedNodeMap) {
2858 QString title = fakeNode->fullTitle();
2859 if (title.startsWith("The "))
2860 title.remove(0, 4);
2861 out() << "<li><xref href=\"" << linkForNode(fakeNode, relative) << "\">"
2862 << protectEnc(title) << "</xref></li>\n";
2863 }
2864 out() << "</ul>\n";
2865 }
2866}
2867
2868void DitaXmlGenerator::generateSection(const NodeList& nl,
2869 const Node *relative,
2870 CodeMarker *marker,
2871 CodeMarker::SynopsisStyle style)
2872{
2873 bool name_alignment = true;
2874 if (!nl.isEmpty()) {
2875 bool twoColumn = false;
2876 if (style == CodeMarker::SeparateList) {
2877 name_alignment = false;
2878 twoColumn = (nl.count() >= 16);
2879 }
2880 else if (nl.first()->type() == Node::Property) {
2881 twoColumn = (nl.count() >= 5);
2882 name_alignment = false;
2883 }
2884 if (name_alignment) {
2885 out() << "<table class=\"alignedsummary\">\n";
2886 }
2887 else {
2888 if (twoColumn)
2889 out() << "<table class=\"propsummary\">\n"
2890 << "<tr><td class=\"topAlign\">";
2891 out() << "<ul>\n";
2892 }
2893
2894 int i = 0;
2895 NodeList::ConstIterator m = nl.begin();
2896 while (m != nl.end()) {
2897 if ((*m)->access() == Node::Private) {
2898 ++m;
2899 continue;
2900 }
2901
2902 if (name_alignment) {
2903 out() << "<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
2904 }
2905 else {
2906 if (twoColumn && i == (int) (nl.count() + 1) / 2)
2907 out() << "</ul></td><td class=\"topAlign\"><ul>\n";
2908 out() << "<li class=\"fn\">";
2909 }
2910
2911 generateSynopsis(*m, relative, marker, style, name_alignment);
2912 if (name_alignment)
2913 out() << "</td></tr>\n";
2914 else
2915 out() << "</li>\n";
2916 i++;
2917 ++m;
2918 }
2919 if (name_alignment)
2920 out() << "</table>\n";
2921 else {
2922 out() << "</ul>\n";
2923 if (twoColumn)
2924 out() << "</td></tr>\n</table>\n";
2925 }
2926 }
2927}
2928
2929void DitaXmlGenerator::generateSectionList(const Section& section,
2930 const Node *relative,
2931 CodeMarker *marker,
2932 CodeMarker::SynopsisStyle style)
2933{
2934 bool name_alignment = true;
2935 if (!section.members.isEmpty()) {
2936 bool twoColumn = false;
2937 if (style == CodeMarker::SeparateList) {
2938 name_alignment = false;
2939 twoColumn = (section.members.count() >= 16);
2940 }
2941 else if (section.members.first()->type() == Node::Property) {
2942 twoColumn = (section.members.count() >= 5);
2943 name_alignment = false;
2944 }
2945 if (name_alignment) {
2946 out() << "<table class=\"alignedsummary\">\n";
2947 }
2948 else {
2949 if (twoColumn)
2950 out() << "<table class=\"propsummary\">\n"
2951 << "<tr><td class=\"topAlign\">";
2952 out() << "<ul>\n";
2953 }
2954
2955 int i = 0;
2956 NodeList::ConstIterator m = section.members.begin();
2957 while (m != section.members.end()) {
2958 if ((*m)->access() == Node::Private) {
2959 ++m;
2960 continue;
2961 }
2962
2963 if (name_alignment) {
2964 out() << "<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
2965 }
2966 else {
2967 if (twoColumn && i == (int) (section.members.count() + 1) / 2)
2968 out() << "</ul></td><td class=\"topAlign\"><ul>\n";
2969 out() << "<li class=\"fn\">";
2970 }
2971
2972 generateSynopsis(*m, relative, marker, style, name_alignment);
2973 if (name_alignment)
2974 out() << "</td></tr>\n";
2975 else
2976 out() << "</li>\n";
2977 i++;
2978 ++m;
2979 }
2980 if (name_alignment)
2981 out() << "</table>\n";
2982 else {
2983 out() << "</ul>\n";
2984 if (twoColumn)
2985 out() << "</td></tr>\n</table>\n";
2986 }
2987 }
2988
2989 if (style == CodeMarker::Summary && !section.inherited.isEmpty()) {
2990 out() << "<ul>\n";
2991 generateSectionInheritedList(section, relative, marker, name_alignment);
2992 out() << "</ul>\n";
2993 }
2994}
2995
2996void DitaXmlGenerator::generateSectionInheritedList(const Section& section,
2997 const Node *relative,
2998 CodeMarker *marker,
2999 bool nameAlignment)
3000{
3001 QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin();
3002 while (p != section.inherited.end()) {
3003 if (nameAlignment)
3004 out() << "<li class=\"fn\">";
3005 else
3006 out() << "<li class=\"fn\">";
3007 out() << (*p).second << " ";
3008 if ((*p).second == 1) {
3009 out() << section.singularMember;
3010 }
3011 else {
3012 out() << section.pluralMember;
3013 }
3014 out() << " inherited from <xref href=\"" << fileName((*p).first)
3015 << "#" << DitaXmlGenerator::cleanRef(section.name.toLower()) << "\">"
3016 << protectEnc(marker->plainFullName((*p).first, relative))
3017 << "</xref></li>\n";
3018 ++p;
3019 }
3020}
3021
3022void DitaXmlGenerator::generateSynopsis(const Node *node,
3023 const Node *relative,
3024 CodeMarker *marker,
3025 CodeMarker::SynopsisStyle style,
3026 bool nameAlignment)
3027{
3028 QString marked = marker->markedUpSynopsis(node, relative, style);
3029 QRegExp templateTag("(<[^@>]*>)");
3030 if (marked.indexOf(templateTag) != -1) {
3031 QString contents = protectEnc(marked.mid(templateTag.pos(1),
3032 templateTag.cap(1).length()));
3033 marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
3034 contents);
3035 }
3036 marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
3037 "<i>\\1<sub>\\2</sub></i>");
3038 marked.replace("<@param>", "<i>");
3039 marked.replace("</@param>", "</i>");
3040
3041 if (style == CodeMarker::Summary) {
3042 marked.replace("<@name>", ""); // was "<b>"
3043 marked.replace("</@name>", ""); // was "</b>"
3044 }
3045
3046 if (style == CodeMarker::SeparateList) {
3047 QRegExp extraRegExp("<@extra>.*</@extra>");
3048 extraRegExp.setMinimal(true);
3049 marked.replace(extraRegExp, "");
3050 } else {
3051 marked.replace("<@extra>", "<tt>");
3052 marked.replace("</@extra>", "</tt>");
3053 }
3054
3055 if (style != CodeMarker::Detailed) {
3056 marked.replace("<@type>", "");
3057 marked.replace("</@type>", "");
3058 }
3059 out() << highlightedCode(marked, marker, relative, style, nameAlignment);
3060}
3061
3062QString DitaXmlGenerator::highlightedCode(const QString& markedCode,
3063 CodeMarker *marker,
3064 const Node *relative,
3065 CodeMarker::SynopsisStyle ,
3066 bool nameAlignment)
3067{
3068 QString src = markedCode;
3069 QString html;
3070 QStringRef arg;
3071 QStringRef par1;
3072
3073 const QChar charLangle = '<';
3074 const QChar charAt = '@';
3075
3076 // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
3077 static const QString linkTag("link");
3078 bool done = false;
3079 for (int i = 0, n = src.size(); i < n;) {
3080 if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') {
3081 if (nameAlignment && !done) {// && (i != 0)) Why was this here?
3082 html += "</td><td class=\"memItemRight bottomAlign\">";
3083 done = true;
3084 }
3085 i += 2;
3086 if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
3087 html += "<b>";
3088 QString link = linkForNode(
3089 CodeMarker::nodeForString(par1.toString()), relative);
3090 addLink(link, arg, &html);
3091 html += "</b>";
3092 }
3093 else {
3094 html += charLangle;
3095 html += charAt;
3096 }
3097 }
3098 else {
3099 html += src.at(i++);
3100 }
3101 }
3102
3103
3104 if (slow) {
3105 // is this block ever used at all?
3106 // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)"
3107 src = html;
3108 html = QString();
3109 static const QString funcTag("func");
3110 for (int i = 0, n = src.size(); i < n;) {
3111 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3112 i += 2;
3113 if (parseArg(src, funcTag, &i, n, &arg, &par1)) {
3114 QString link = linkForNode(
3115 marker->resolveTarget(par1.toString(),
3116 myTree,
3117 relative),
3118 relative);
3119 addLink(link, arg, &html);
3120 par1 = QStringRef();
3121 }
3122 else {
3123 html += charLangle;
3124 html += charAt;
3125 }
3126 }
3127 else {
3128 html += src.at(i++);
3129 }
3130 }
3131 }
3132
3133 // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
3134 src = html;
3135 html = QString();
3136 static const QString typeTags[] = { "type", "headerfile", "func" };
3137 for (int i = 0, n = src.size(); i < n;) {
3138 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3139 i += 2;
3140 bool handled = false;
3141 for (int k = 0; k != 3; ++k) {
3142 if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) {
3143 par1 = QStringRef();
3144 QString link = linkForNode(
3145 marker->resolveTarget(arg.toString(), myTree, relative),
3146 relative);
3147 addLink(link, arg, &html);