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

Last change on this file since 1147 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 (qt-info@nokia.com)
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 qt-info@nokia.com.
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);
3148 handled = true;
3149 break;
3150 }
3151 }
3152 if (!handled) {
3153 html += charLangle;
3154 html += charAt;
3155 }
3156 }
3157 else {
3158 html += src.at(i++);
3159 }
3160 }
3161
3162 // replace all
3163 // "<@comment>" -> "<span class=\"comment\">";
3164 // "<@preprocessor>" -> "<span class=\"preprocessor\">";
3165 // "<@string>" -> "<span class=\"string\">";
3166 // "<@char>" -> "<span class=\"char\">";
3167 // "</@(?:comment|preprocessor|string|char)>" -> "</span>"
3168 src = html;
3169 html = QString();
3170 static const QString spanTags[] = {
3171 "<@comment>", "<span class=\"comment\">",
3172 "<@preprocessor>", "<span class=\"preprocessor\">",
3173 "<@string>", "<span class=\"string\">",
3174 "<@char>", "<span class=\"char\">",
3175 "</@comment>", "</span>",
3176 "</@preprocessor>","</span>",
3177 "</@string>", "</span>",
3178 "</@char>", "</span>"
3179 // "<@char>", "<font color=blue>",
3180 // "</@char>", "</font>",
3181 // "<@func>", "<font color=green>",
3182 // "</@func>", "</font>",
3183 // "<@id>", "<i>",
3184 // "</@id>", "</i>",
3185 // "<@keyword>", "<b>",
3186 // "</@keyword>", "</b>",
3187 // "<@number>", "<font color=yellow>",
3188 // "</@number>", "</font>",
3189 // "<@op>", "<b>",
3190 // "</@op>", "</b>",
3191 // "<@param>", "<i>",
3192 // "</@param>", "</i>",
3193 // "<@string>", "<font color=green>",
3194 // "</@string>", "</font>",
3195 };
3196 for (int i = 0, n = src.size(); i < n;) {
3197 if (src.at(i) == charLangle) {
3198 bool handled = false;
3199 for (int k = 0; k != 8; ++k) {
3200 const QString & tag = spanTags[2 * k];
3201 if (tag == QStringRef(&src, i, tag.length())) {
3202 html += spanTags[2 * k + 1];
3203 i += tag.length();
3204 handled = true;
3205 break;
3206 }
3207 }
3208 if (!handled) {
3209 ++i;
3210 if (src.at(i) == charAt ||
3211 (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) {
3212 // drop 'our' unknown tags (the ones still containing '@')
3213 while (i < n && src.at(i) != QLatin1Char('>'))
3214 ++i;
3215 ++i;
3216 }
3217 else {
3218 // retain all others
3219 html += charLangle;
3220 }
3221 }
3222 }
3223 else {
3224 html += src.at(i);
3225 ++i;
3226 }
3227 }
3228
3229 return html;
3230}
3231
3232void DitaXmlGenerator::generateLink(const Atom* atom,
3233 const Node* /* relative */,
3234 CodeMarker* marker)
3235{
3236 static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_");
3237
3238 if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) {
3239 // hack for C++: move () outside of link
3240 int k = funcLeftParen.pos(1);
3241 writer.writeCharacters(protectEnc(atom->string().left(k)));
3242 if (link.isEmpty()) {
3243 if (showBrokenLinks)
3244 writer.writeEndElement(); // </i>
3245 }
3246 else {
3247 writer.writeEndElement(); // </xref>
3248 }
3249 inLink = false;
3250 writer.writeCharacters(protectEnc(atom->string().mid(k)));
3251 } else if (marker->recognizeLanguage("Java")) {
3252 // hack for Java: remove () and use <tt> when appropriate
3253 bool func = atom->string().endsWith("()");
3254 bool tt = (func || atom->string().contains(camelCase));
3255 if (tt)
3256 writer.writeStartElement("tt");
3257 if (func) {
3258 writer.writeCharacters(protectEnc(atom->string().left(atom->string().length() - 2)));
3259 }
3260 else {
3261 writer.writeCharacters(protectEnc(atom->string()));
3262 }
3263 writer.writeEndElement(); // </tt>
3264 }
3265 else {
3266 writer.writeCharacters(protectEnc(atom->string()));
3267 }
3268}
3269
3270QString DitaXmlGenerator::cleanRef(const QString& ref)
3271{
3272 QString clean;
3273
3274 if (ref.isEmpty())
3275 return clean;
3276
3277 clean.reserve(ref.size() + 20);
3278 const QChar c = ref[0];
3279 const uint u = c.unicode();
3280
3281 if ((u >= 'a' && u <= 'z') ||
3282 (u >= 'A' && u <= 'Z') ||
3283 (u >= '0' && u <= '9')) {
3284 clean += c;
3285 } else if (u == '~') {
3286 clean += "dtor.";
3287 } else if (u == '_') {
3288 clean += "underscore.";
3289 } else {
3290 clean += "A";
3291 }
3292
3293 for (int i = 1; i < (int) ref.length(); i++) {
3294 const QChar c = ref[i];
3295 const uint u = c.unicode();
3296 if ((u >= 'a' && u <= 'z') ||
3297 (u >= 'A' && u <= 'Z') ||
3298 (u >= '0' && u <= '9') || u == '-' ||
3299 u == '_' || u == ':' || u == '.') {
3300 clean += c;
3301 } else if (c.isSpace()) {
3302 clean += "-";
3303 } else if (u == '!') {
3304 clean += "-not";
3305 } else if (u == '&') {
3306 clean += "-and";
3307 } else if (u == '<') {
3308 clean += "-lt";
3309 } else if (u == '=') {
3310 clean += "-eq";
3311 } else if (u == '>') {
3312 clean += "-gt";
3313 } else if (u == '#') {
3314 clean += "#";
3315 } else {
3316 clean += "-";
3317 clean += QString::number((int)u, 16);
3318 }
3319 }
3320 return clean;
3321}
3322
3323QString DitaXmlGenerator::registerRef(const QString& ref)
3324{
3325 QString clean = DitaXmlGenerator::cleanRef(ref);
3326
3327 for (;;) {
3328 QString& prevRef = refMap[clean.toLower()];
3329 if (prevRef.isEmpty()) {
3330 prevRef = ref;
3331 break;
3332 } else if (prevRef == ref) {
3333 break;
3334 }
3335 clean += "x";
3336 }
3337 return clean;
3338}
3339
3340QString DitaXmlGenerator::protectEnc(const QString &string)
3341{
3342 return protect(string, outputEncoding);
3343}
3344
3345QString DitaXmlGenerator::protect(const QString &string, const QString &outputEncoding)
3346{
3347#define APPEND(x) \
3348 if (xml.isEmpty()) { \
3349 xml = string; \
3350 xml.truncate(i); \
3351 } \
3352 xml += (x);
3353
3354 QString xml;
3355 int n = string.length();
3356
3357 for (int i = 0; i < n; ++i) {
3358 QChar ch = string.at(i);
3359
3360 if (ch == QLatin1Char('&')) {
3361 APPEND("&amp;");
3362 } else if (ch == QLatin1Char('<')) {
3363 APPEND("&lt;");
3364 } else if (ch == QLatin1Char('>')) {
3365 APPEND("&gt;");
3366 } else if (ch == QLatin1Char('"')) {
3367 APPEND("&quot;");
3368 } else if ((outputEncoding == "ISO-8859-1" && ch.unicode() > 0x007F)
3369 || (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/'))
3370 || (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) {
3371 // we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator
3372 APPEND("&#x");
3373 xml += QString::number(ch.unicode(), 16);
3374 xml += QLatin1Char(';');
3375 } else {
3376 if (!xml.isEmpty())
3377 xml += ch;
3378 }
3379 }
3380
3381 if (!xml.isEmpty())
3382 return xml;
3383 return string;
3384
3385#undef APPEND
3386}
3387
3388QString DitaXmlGenerator::fileBase(const Node *node)
3389{
3390 QString result;
3391
3392 result = PageGenerator::fileBase(node);
3393
3394 if (!node->isInnerNode()) {
3395 switch (node->status()) {
3396 case Node::Compat:
3397 result += "-qt3";
3398 break;
3399 case Node::Obsolete:
3400 result += "-obsolete";
3401 break;
3402 default:
3403 ;
3404 }
3405 }
3406 return result;
3407}
3408
3409#if 0
3410QString DitaXmlGenerator::fileBase(const Node *node,
3411 const SectionIterator& section)
3412{
3413 QStringList::ConstIterator s = section.sectionNumber().end();
3414 QStringList::ConstIterator b = section.baseNameStack().end();
3415
3416 QString suffix;
3417 QString base = fileBase(node);
3418
3419 while (s != section.sectionNumber().begin()) {
3420 --s;
3421 --b;
3422 if (!(*b).isEmpty()) {
3423 base = *b;
3424 break;
3425 }
3426 suffix.prepend("-" + *s);
3427 }
3428 return base + suffix;
3429}
3430#endif
3431
3432QString DitaXmlGenerator::fileName(const Node *node)
3433{
3434 if (node->type() == Node::Fake) {
3435 if (static_cast<const FakeNode *>(node)->subType() == Node::ExternalPage)
3436 return node->name();
3437 if (static_cast<const FakeNode *>(node)->subType() == Node::Image)
3438 return node->name();
3439 }
3440 return PageGenerator::fileName(node);
3441}
3442
3443QString DitaXmlGenerator::refForNode(const Node *node)
3444{
3445 const FunctionNode *func;
3446 const TypedefNode *typedeffe;
3447 QString ref;
3448
3449 switch (node->type()) {
3450 case Node::Namespace:
3451 case Node::Class:
3452 default:
3453 break;
3454 case Node::Enum:
3455 ref = node->name() + "-enum";
3456 break;
3457 case Node::Typedef:
3458 typedeffe = static_cast<const TypedefNode *>(node);
3459 if (typedeffe->associatedEnum()) {
3460 return refForNode(typedeffe->associatedEnum());
3461 }
3462 else {
3463 ref = node->name() + "-typedef";
3464 }
3465 break;
3466 case Node::Function:
3467 func = static_cast<const FunctionNode *>(node);
3468 if (func->associatedProperty()) {
3469 return refForNode(func->associatedProperty());
3470 }
3471 else {
3472 ref = func->name();
3473 if (func->overloadNumber() != 1)
3474 ref += "-" + QString::number(func->overloadNumber());
3475 }
3476 break;
3477#ifdef QDOC_QML
3478 case Node::Fake:
3479 if (node->subType() != Node::QmlPropertyGroup)
3480 break;
3481 case Node::QmlProperty:
3482#endif
3483 case Node::Property:
3484 ref = node->name() + "-prop";
3485 break;
3486#ifdef QDOC_QML
3487 case Node::QmlSignal:
3488 ref = node->name() + "-signal";
3489 break;
3490 case Node::QmlMethod:
3491 ref = node->name() + "-method";
3492 break;
3493#endif
3494 case Node::Variable:
3495 ref = node->name() + "-var";
3496 break;
3497 case Node::Target:
3498 return protectEnc(node->name());
3499 }
3500 return registerRef(ref);
3501}
3502
3503QString DitaXmlGenerator::linkForNode(const Node *node, const Node *relative)
3504{
3505 QString link;
3506 QString fn;
3507 QString ref;
3508
3509 if (node == 0 || node == relative)
3510 return QString();
3511 if (!node->url().isEmpty())
3512 return node->url();
3513 if (fileBase(node).isEmpty())
3514 return QString();
3515 if (node->access() == Node::Private)
3516 return QString();
3517
3518 fn = fileName(node);
3519 link += fn;
3520
3521 if (!node->isInnerNode() || node->subType() == Node::QmlPropertyGroup) {
3522 ref = refForNode(node);
3523 if (relative && fn == fileName(relative) && ref == refForNode(relative))
3524 return QString();
3525
3526 link += "#";
3527 link += ref;
3528 }
3529 return link;
3530}
3531
3532QString DitaXmlGenerator::refForAtom(Atom *atom, const Node * /* node */)
3533{
3534 if (atom->type() == Atom::SectionLeft) {
3535 return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
3536 }
3537 else if (atom->type() == Atom::Target) {
3538 return Doc::canonicalTitle(atom->string());
3539 }
3540 else {
3541 return QString();
3542 }
3543}
3544
3545void DitaXmlGenerator::generateFullName(const Node *apparentNode,
3546 const Node *relative,
3547 CodeMarker *marker,
3548 const Node *actualNode)
3549{
3550 if (actualNode == 0)
3551 actualNode = apparentNode;
3552 out() << "<xref href=\"" << linkForNode(actualNode, relative);
3553 if (true || relative == 0 || relative->status() != actualNode->status()) {
3554 switch (actualNode->status()) {
3555 case Node::Obsolete:
3556 out() << "\" class=\"obsolete";
3557 break;
3558 case Node::Compat:
3559 out() << "\" class=\"compat";
3560 break;
3561 default:
3562 ;
3563 }
3564 }
3565 out() << "\">";
3566 out() << protectEnc(fullName(apparentNode, relative, marker));
3567 out() << "</xref>";
3568}
3569
3570void DitaXmlGenerator::generateDetailedMember(const Node *node,
3571 const InnerNode *relative,
3572 CodeMarker *marker)
3573{
3574 const EnumNode *enume;
3575
3576#ifdef GENERATE_MAC_REFS
3577 generateMacRef(node, marker);
3578#endif
3579 if (node->type() == Node::Enum
3580 && (enume = static_cast<const EnumNode *>(node))->flagsType()) {
3581#ifdef GENERATE_MAC_REFS
3582 generateMacRef(enume->flagsType(), marker);
3583#endif
3584 out() << "<h3 class=\"flags\">";
3585 out() << "<a name=\"" + refForNode(node) + "\"></a>";
3586 generateSynopsis(enume, relative, marker, CodeMarker::Detailed);
3587 out() << "<br/>";
3588 generateSynopsis(enume->flagsType(),
3589 relative,
3590 marker,
3591 CodeMarker::Detailed);
3592 out() << "</h3>\n";
3593 }
3594 else {
3595 out() << "<h3 class=\"fn\">";
3596 out() << "<a name=\"" + refForNode(node) + "\"></a>";
3597 generateSynopsis(node, relative, marker, CodeMarker::Detailed);
3598 out() << "</h3>\n";
3599 }
3600
3601 generateStatus(node, marker);
3602 generateBody(node, marker);
3603 generateThreadSafeness(node, marker);
3604 generateSince(node, marker);
3605
3606 if (node->type() == Node::Property) {
3607 const PropertyNode *property = static_cast<const PropertyNode *>(node);
3608 Section section;
3609
3610 section.members += property->getters();
3611 section.members += property->setters();
3612 section.members += property->resetters();
3613
3614 if (!section.members.isEmpty()) {
3615 out() << "<p><b>Access functions:</b></p>\n";
3616 generateSectionList(section, node, marker, CodeMarker::Accessors);
3617 }
3618
3619 Section notifiers;
3620 notifiers.members += property->notifiers();
3621
3622 if (!notifiers.members.isEmpty()) {
3623 out() << "<p><b>Notifier signal:</b></p>\n";
3624 //out() << "<p>This signal is emitted when the property value is changed.</p>\n";
3625 generateSectionList(notifiers, node, marker, CodeMarker::Accessors);
3626 }
3627 }
3628 else if (node->type() == Node::Enum) {
3629 const EnumNode *enume = static_cast<const EnumNode *>(node);
3630 if (enume->flagsType()) {
3631 out() << "<p>The " << protectEnc(enume->flagsType()->name())
3632 << " type is a typedef for "
3633 << "<xref href=\"qflags.html\">QFlags</xref>&lt;"
3634 << protectEnc(enume->name())
3635 << "&gt;. It stores an OR combination of "
3636 << protectEnc(enume->name())
3637 << " values.</p>\n";
3638 }
3639 }
3640 generateAlsoList(node, marker);
3641}
3642
3643void DitaXmlGenerator::findAllClasses(const InnerNode *node)
3644{
3645 NodeList::const_iterator c = node->childNodes().constBegin();
3646 while (c != node->childNodes().constEnd()) {
3647 if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) {
3648 if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
3649 QString className = (*c)->name();
3650 if ((*c)->parent() &&
3651 (*c)->parent()->type() == Node::Namespace &&
3652 !(*c)->parent()->name().isEmpty())
3653 className = (*c)->parent()->name()+"::"+className;
3654
3655 if (!(static_cast<const ClassNode *>(*c))->hideFromMainList()) {
3656 if ((*c)->status() == Node::Compat) {
3657 compatClasses.insert(className, *c);
3658 }
3659 else if ((*c)->status() == Node::Obsolete) {
3660 obsoleteClasses.insert(className, *c);
3661 }
3662 else {
3663 nonCompatClasses.insert(className, *c);
3664 if ((*c)->status() == Node::Main)
3665 mainClasses.insert(className, *c);
3666 }
3667 }
3668
3669 QString moduleName = (*c)->moduleName();
3670 if (moduleName == "Qt3SupportLight") {
3671 moduleClassMap[moduleName].insert((*c)->name(), *c);
3672 moduleName = "Qt3Support";
3673 }
3674 if (!moduleName.isEmpty())
3675 moduleClassMap[moduleName].insert((*c)->name(), *c);
3676
3677 QString serviceName =
3678 (static_cast<const ClassNode *>(*c))->serviceName();
3679 if (!serviceName.isEmpty())
3680 serviceClasses.insert(serviceName, *c);
3681 }
3682 else if ((*c)->type() == Node::Fake &&
3683 (*c)->subType() == Node::QmlClass &&
3684 !(*c)->doc().isEmpty()) {
3685 QString qmlClassName = (*c)->name();
3686 qmlClasses.insert(qmlClassName,*c);
3687 }
3688 else if ((*c)->isInnerNode()) {
3689 findAllClasses(static_cast<InnerNode *>(*c));
3690 }
3691 }
3692 ++c;
3693 }
3694}
3695
3696/*!
3697 For generating the "New Classes... in 4.6" section on the
3698 What's New in 4.6" page.
3699 */
3700void DitaXmlGenerator::findAllSince(const InnerNode *node)
3701{
3702 NodeList::const_iterator child = node->childNodes().constBegin();
3703 while (child != node->childNodes().constEnd()) {
3704 QString sinceVersion = (*child)->since();
3705 if (((*child)->access() != Node::Private) && !sinceVersion.isEmpty()) {
3706 NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceVersion);
3707 if (nsmap == newSinceMaps.end())
3708 nsmap = newSinceMaps.insert(sinceVersion,NodeMultiMap());
3709 NewClassMaps::iterator ncmap = newClassMaps.find(sinceVersion);
3710 if (ncmap == newClassMaps.end())
3711 ncmap = newClassMaps.insert(sinceVersion,NodeMap());
3712 NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceVersion);
3713 if (nqcmap == newQmlClassMaps.end())
3714 nqcmap = newQmlClassMaps.insert(sinceVersion,NodeMap());
3715
3716 if ((*child)->type() == Node::Function) {
3717 FunctionNode *func = static_cast<FunctionNode *>(*child);
3718 if ((func->status() > Node::Obsolete) &&
3719 (func->metaness() != FunctionNode::Ctor) &&
3720 (func->metaness() != FunctionNode::Dtor)) {
3721 nsmap.value().insert(func->name(),(*child));
3722 }
3723 }
3724 else if ((*child)->url().isEmpty()) {
3725 if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
3726 QString className = (*child)->name();
3727 if ((*child)->parent() &&
3728 (*child)->parent()->type() == Node::Namespace &&
3729 !(*child)->parent()->name().isEmpty())
3730 className = (*child)->parent()->name()+"::"+className;
3731 nsmap.value().insert(className,(*child));
3732 ncmap.value().insert(className,(*child));
3733 }
3734 else if ((*child)->subType() == Node::QmlClass) {
3735 QString className = (*child)->name();
3736 if ((*child)->parent() &&
3737 (*child)->parent()->type() == Node::Namespace &&
3738 !(*child)->parent()->name().isEmpty())
3739 className = (*child)->parent()->name()+"::"+className;
3740 nsmap.value().insert(className,(*child));
3741 nqcmap.value().insert(className,(*child));
3742 }
3743 }
3744 else {
3745 QString name = (*child)->name();
3746 if ((*child)->parent() &&
3747 (*child)->parent()->type() == Node::Namespace &&
3748 !(*child)->parent()->name().isEmpty())
3749 name = (*child)->parent()->name()+"::"+name;
3750 nsmap.value().insert(name,(*child));
3751 }
3752 if ((*child)->isInnerNode()) {
3753 findAllSince(static_cast<InnerNode *>(*child));
3754 }
3755 }
3756 ++child;
3757 }
3758}
3759
3760#if 0
3761 const QRegExp versionSeparator("[\\-\\.]");
3762 const int minorIndex = version.indexOf(versionSeparator);
3763 const int patchIndex = version.indexOf(versionSeparator, minorIndex+1);
3764 version = version.left(patchIndex);
3765#endif
3766
3767void DitaXmlGenerator::findAllFunctions(const InnerNode *node)
3768{
3769 NodeList::ConstIterator c = node->childNodes().begin();
3770 while (c != node->childNodes().end()) {
3771 if ((*c)->access() != Node::Private) {
3772 if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
3773 findAllFunctions(static_cast<const InnerNode *>(*c));
3774 }
3775 else if ((*c)->type() == Node::Function) {
3776 const FunctionNode *func = static_cast<const FunctionNode *>(*c);
3777 if ((func->status() > Node::Obsolete) &&
3778 (func->metaness() != FunctionNode::Ctor) &&
3779 (func->metaness() != FunctionNode::Dtor)) {
3780 funcIndex[(*c)->name()].insert(myTree->fullDocumentName((*c)->parent()), *c);
3781 }
3782 }
3783 }
3784 ++c;
3785 }
3786}
3787
3788void DitaXmlGenerator::findAllLegaleseTexts(const InnerNode *node)
3789{
3790 NodeList::ConstIterator c = node->childNodes().begin();
3791 while (c != node->childNodes().end()) {
3792 if ((*c)->access() != Node::Private) {
3793 if (!(*c)->doc().legaleseText().isEmpty())
3794 legaleseTexts.insertMulti((*c)->doc().legaleseText(), *c);
3795 if ((*c)->isInnerNode())
3796 findAllLegaleseTexts(static_cast<const InnerNode *>(*c));
3797 }
3798 ++c;
3799 }
3800}
3801
3802void DitaXmlGenerator::findAllNamespaces(const InnerNode *node)
3803{
3804 NodeList::ConstIterator c = node->childNodes().begin();
3805 while (c != node->childNodes().end()) {
3806 if ((*c)->access() != Node::Private) {
3807 if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
3808 findAllNamespaces(static_cast<const InnerNode *>(*c));
3809 if ((*c)->type() == Node::Namespace) {
3810 const NamespaceNode *nspace = static_cast<const NamespaceNode *>(*c);
3811 // Ensure that the namespace's name is not empty (the root
3812 // namespace has no name).
3813 if (!nspace->name().isEmpty()) {
3814 namespaceIndex.insert(nspace->name(), *c);
3815 QString moduleName = (*c)->moduleName();
3816 if (moduleName == "Qt3SupportLight") {
3817 moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
3818 moduleName = "Qt3Support";
3819 }
3820 if (!moduleName.isEmpty())
3821 moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
3822 }
3823 }
3824 }
3825 }
3826 ++c;
3827 }
3828}
3829
3830int DitaXmlGenerator::hOffset(const Node *node)
3831{
3832 switch (node->type()) {
3833 case Node::Namespace:
3834 case Node::Class:
3835 return 2;
3836 case Node::Fake:
3837 return 1;
3838#if 0
3839 if (node->doc().briefText().isEmpty())
3840 return 1;
3841 else
3842 return 2;
3843#endif
3844 case Node::Enum:
3845 case Node::Typedef:
3846 case Node::Function:
3847 case Node::Property:
3848 default:
3849 return 3;
3850 }
3851}
3852
3853bool DitaXmlGenerator::isThreeColumnEnumValueTable(const Atom *atom)
3854{
3855 while (atom != 0 && !(atom->type() == Atom::ListRight && atom->string() == ATOM_LIST_VALUE)) {
3856 if (atom->type() == Atom::ListItemLeft && !matchAhead(atom, Atom::ListItemRight))
3857 return true;
3858 atom = atom->next();
3859 }
3860 return false;
3861}
3862
3863const Node *DitaXmlGenerator::findNodeForTarget(const QString &target,
3864 const Node *relative,
3865 CodeMarker *marker,
3866 const Atom *atom)
3867{
3868 const Node *node = 0;
3869
3870 if (target.isEmpty()) {
3871 node = relative;
3872 }
3873 else if (target.endsWith(".html")) {
3874 node = myTree->root()->findNode(target, Node::Fake);
3875 }
3876 else if (marker) {
3877 node = marker->resolveTarget(target, myTree, relative);
3878 if (!node)
3879 node = myTree->findFakeNodeByTitle(target);
3880 if (!node && atom) {
3881 node = myTree->findUnambiguousTarget(target,
3882 *const_cast<Atom**>(&atom));
3883 }
3884 }
3885
3886 if (!node)
3887 relative->doc().location().warning(tr("Cannot link to '%1'").arg(target));
3888
3889 return node;
3890}
3891
3892const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node *node)
3893{
3894 QPair<QString,QString> anchorPair;
3895
3896 anchorPair.first = PageGenerator::fileName(node);
3897 if (node->type() == Node::Fake) {
3898 const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
3899 anchorPair.second = fakeNode->title();
3900 }
3901
3902 return anchorPair;
3903}
3904
3905QString DitaXmlGenerator::getLink(const Atom *atom,
3906 const Node *relative,
3907 CodeMarker *marker,
3908 const Node** node)
3909{
3910 QString link;
3911 *node = 0;
3912 inObsoleteLink = false;
3913
3914 if (atom->string().contains(":") &&
3915 (atom->string().startsWith("file:")
3916 || atom->string().startsWith("http:")
3917 || atom->string().startsWith("https:")
3918 || atom->string().startsWith("ftp:")
3919 || atom->string().startsWith("mailto:"))) {
3920
3921 link = atom->string();
3922 }
3923 else {
3924 QStringList path;
3925 if (atom->string().contains('#')) {
3926 path = atom->string().split('#');
3927 }
3928 else {
3929 path.append(atom->string());
3930 }
3931
3932 Atom *targetAtom = 0;
3933
3934 QString first = path.first().trimmed();
3935 if (first.isEmpty()) {
3936 *node = relative;
3937 }
3938 else if (first.endsWith(".html")) {
3939 *node = myTree->root()->findNode(first, Node::Fake);
3940 }
3941 else {
3942 *node = marker->resolveTarget(first, myTree, relative);
3943 if (!*node) {
3944 *node = myTree->findFakeNodeByTitle(first);
3945 }
3946 if (!*node) {
3947 *node = myTree->findUnambiguousTarget(first, targetAtom);
3948 }
3949 }
3950
3951 if (*node) {
3952 if (!(*node)->url().isEmpty())
3953 return (*node)->url();
3954 else
3955 path.removeFirst();
3956 }
3957 else {
3958 *node = relative;
3959 }
3960
3961 if (*node) {
3962 if ((*node)->status() == Node::Obsolete) {
3963 if (relative) {
3964 if (relative->parent() != *node) {
3965 if (relative->status() != Node::Obsolete) {
3966 bool porting = false;
3967 if (relative->type() == Node::Fake) {
3968 const FakeNode* fake = static_cast<const FakeNode*>(relative);
3969 if (fake->title().startsWith("Porting"))
3970 porting = true;
3971 }
3972 QString name = marker->plainFullName(relative);
3973 if (!porting && !name.startsWith("Q3")) {
3974 if (obsoleteLinks) {
3975 relative->doc().location().warning(tr("Link to obsolete item '%1' in %2")
3976 .arg(atom->string())
3977 .arg(name));
3978 }
3979 inObsoleteLink = true;
3980 }
3981 }
3982 }
3983 }
3984 else {
3985 qDebug() << "Link to Obsolete entity"
3986 << (*node)->name() << "no relative";
3987 }
3988 }
3989#if 0
3990 else if ((*node)->status() == Node::Deprecated) {
3991 qDebug() << "Link to Deprecated entity";
3992 }
3993 else if ((*node)->status() == Node::Internal) {
3994 qDebug() << "Link to Internal entity";
3995 }
3996#endif
3997 }
3998
3999 while (!path.isEmpty()) {
4000 targetAtom = myTree->findTarget(path.first(), *node);
4001 if (targetAtom == 0)
4002 break;
4003 path.removeFirst();
4004 }
4005
4006 if (path.isEmpty()) {
4007 link = linkForNode(*node, relative);
4008 if (*node && (*node)->subType() == Node::Image)
4009 link = "images/used-in-examples/" + link;
4010 if (targetAtom)
4011 link += "#" + refForAtom(targetAtom, *node);
4012 }
4013 }
4014 return link;
4015}
4016
4017void DitaXmlGenerator::generateIndex(const QString &fileBase,
4018 const QString &url,
4019 const QString &title)
4020{
4021 myTree->generateIndex(outputDir() + "/" + fileBase + ".index", url, title);
4022}
4023
4024void DitaXmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
4025{
4026 Text text;
4027
4028 switch (node->status()) {
4029 case Node::Obsolete:
4030 if (node->isInnerNode())
4031 Generator::generateStatus(node, marker);
4032 break;
4033 case Node::Compat:
4034 if (node->isInnerNode()) {
4035 text << Atom::ParaLeft
4036 << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
4037 << "This "
4038 << typeString(node)
4039 << " is part of the Qt 3 support library."
4040 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
4041 << " It is provided to keep old source code working. "
4042 << "We strongly advise against "
4043 << "using it in new code. See ";
4044
4045 const FakeNode *fakeNode = myTree->findFakeNodeByTitle("Porting To Qt 4");
4046 Atom *targetAtom = 0;
4047 if (fakeNode && node->type() == Node::Class) {
4048 QString oldName(node->name());
4049 targetAtom = myTree->findTarget(oldName.replace("3", ""),
4050 fakeNode);
4051 }
4052
4053 if (targetAtom) {
4054 text << Atom(Atom::Link, linkForNode(fakeNode, node) + "#" +
4055 refForAtom(targetAtom, fakeNode));
4056 }
4057 else
4058 text << Atom(Atom::Link, "Porting to Qt 4");
4059
4060 text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
4061 << Atom(Atom::String, "Porting to Qt 4")
4062 << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
4063 << " for more information."
4064 << Atom::ParaRight;
4065 }
4066 generateText(text, node, marker);
4067 break;
4068 default:
4069 Generator::generateStatus(node, marker);
4070 }
4071}
4072
4073#ifdef GENERATE_MAC_REFS
4074/*
4075 No longer valid.
4076 */
4077void DitaXmlGenerator::generateMacRef(const Node *node, CodeMarker *marker)
4078{
4079 if (!pleaseGenerateMacRef || marker == 0)
4080 return;
4081
4082 QStringList macRefs = marker->macRefsForNode(node);
4083 foreach (const QString &macRef, macRefs)
4084 out() << "<a name=\"" << "//apple_ref/" << macRef << "\"></a>\n";
4085}
4086#endif
4087
4088void DitaXmlGenerator::beginLink(const QString &link,
4089 const Node *node,
4090 const Node *relative,
4091 CodeMarker *marker)
4092{
4093 Q_UNUSED(marker)
4094 Q_UNUSED(relative)
4095
4096 this->link = link;
4097 if (link.isEmpty()) {
4098 if (showBrokenLinks)
4099 writer.writeStartElement("i");
4100 }
4101 else if (node == 0 || (relative != 0 &&
4102 node->status() == relative->status())) {
4103 writer.writeStartElement("xref");
4104 writer.writeAttribute("href",link);
4105 }
4106 else {
4107 switch (node->status()) {
4108 case Node::Obsolete:
4109 writer.writeStartElement("xref");
4110 writer.writeAttribute("href",link);
4111 writer.writeAttribute("outputclass","obsolete");
4112 break;
4113 case Node::Compat:
4114 writer.writeStartElement("xref");
4115 writer.writeAttribute("href",link);
4116 writer.writeAttribute("outputclass","compat");
4117 break;
4118 default:
4119 writer.writeStartElement("xref");
4120 writer.writeAttribute("href",link);
4121 }
4122 }
4123 inLink = true;
4124}
4125
4126void DitaXmlGenerator::endLink()
4127{
4128 if (inLink) {
4129 if (link.isEmpty()) {
4130 if (showBrokenLinks)
4131 writer.writeEndElement(); // i
4132 }
4133 else {
4134 if (inObsoleteLink) {
4135 writer.writeStartElement("sup");
4136 writer.writeCharacters("(obsolete)");
4137 writer.writeEndElement(); // sup
4138 }
4139 writer.writeEndElement(); // xref
4140 }
4141 }
4142 inLink = false;
4143 inObsoleteLink = false;
4144}
4145
4146#ifdef QDOC_QML
4147
4148/*!
4149 Generates the summary for the \a section. Only used for
4150 sections of QML element documentation.
4151
4152 Currently handles only the QML property group.
4153 */
4154void DitaXmlGenerator::generateQmlSummary(const Section& section,
4155 const Node *relative,
4156 CodeMarker *marker)
4157{
4158 if (!section.members.isEmpty()) {
4159 NodeList::ConstIterator m;
4160 int count = section.members.size();
4161 bool twoColumn = false;
4162 if (section.members.first()->type() == Node::QmlProperty) {
4163 twoColumn = (count >= 5);
4164 }
4165 if (twoColumn)
4166 out() << "<table class=\"qmlsummary\">\n";
4167 if (++numTableRows % 2 == 1)
4168 out() << "<tr class=\"odd topAlign\">";
4169 else
4170 out() << "<tr class=\"even topAlign\">";
4171 // << "<tr><td class=\"topAlign\">";
4172 out() << "<ul>\n";
4173
4174 int row = 0;
4175 m = section.members.begin();
4176 while (m != section.members.end()) {
4177 if (twoColumn && row == (int) (count + 1) / 2)
4178 out() << "</ul></td><td class=\"topAlign\"><ul>\n";
4179 out() << "<li class=\"fn\">";
4180 generateQmlItem(*m,relative,marker,true);
4181 out() << "</li>\n";
4182 row++;
4183 ++m;
4184 }
4185 out() << "</ul>\n";
4186 if (twoColumn)
4187 out() << "</td></tr>\n</table>\n";
4188 }
4189}
4190
4191/*!
4192 Outputs the html detailed documentation for a section
4193 on a QML element reference page.
4194 */
4195void DitaXmlGenerator::generateDetailedQmlMember(const Node *node,
4196 const InnerNode *relative,
4197 CodeMarker *marker)
4198{
4199 const QmlPropertyNode* qpn = 0;
4200#ifdef GENERATE_MAC_REFS
4201 generateMacRef(node, marker);
4202#endif
4203 out() << "<div class=\"qmlitem\">";
4204 if (node->subType() == Node::QmlPropertyGroup) {
4205 const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
4206 NodeList::ConstIterator p = qpgn->childNodes().begin();
4207 out() << "<div class=\"qmlproto\">";
4208 out() << "<table class=\"qmlname\">";
4209
4210 while (p != qpgn->childNodes().end()) {
4211 if ((*p)->type() == Node::QmlProperty) {
4212 qpn = static_cast<const QmlPropertyNode*>(*p);
4213
4214 if (++numTableRows % 2 == 1)
4215 out() << "<tr class=\"odd\">";
4216 else
4217 out() << "<tr class=\"even\">";
4218
4219 out() << "<td><p>";
4220 //out() << "<tr><td>"; // old
4221 out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
4222 if (!qpn->isWritable(myTree))
4223 out() << "<span class=\"qmlreadonly\">read-only</span>";
4224 if (qpgn->isDefault())
4225 out() << "<span class=\"qmldefault\">default</span>";
4226 generateQmlItem(qpn, relative, marker, false);
4227 out() << "</td></tr>";
4228 }
4229 ++p;
4230 }
4231 out() << "</table>";
4232 out() << "</div>";
4233 }
4234 else if (node->type() == Node::QmlSignal) {
4235 const FunctionNode* qsn = static_cast<const FunctionNode*>(node);
4236 out() << "<div class=\"qmlproto\">";
4237 out() << "<table class=\"qmlname\">";
4238 //out() << "<tr>";
4239 if (++numTableRows % 2 == 1)
4240 out() << "<tr class=\"odd\">";
4241 else
4242 out() << "<tr class=\"even\">";
4243 out() << "<td><p>";
4244 out() << "<a name=\"" + refForNode(qsn) + "\"></a>";
4245 generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false);
4246 //generateQmlItem(qsn,relative,marker,false);
4247 out() << "</p></td></tr>";
4248 out() << "</table>";
4249 out() << "</div>";
4250 }
4251 else if (node->type() == Node::QmlMethod) {
4252 const FunctionNode* qmn = static_cast<const FunctionNode*>(node);
4253 out() << "<div class=\"qmlproto\">";
4254 out() << "<table class=\"qmlname\">";
4255 //out() << "<tr>";
4256 if (++numTableRows % 2 == 1)
4257 out() << "<tr class=\"odd\">";
4258 else
4259 out() << "<tr class=\"even\">";
4260 out() << "<td><p>";
4261 out() << "<a name=\"" + refForNode(qmn) + "\"></a>";
4262 generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false);
4263 out() << "</p></td></tr>";
4264 out() << "</table>";
4265 out() << "</div>";
4266 }
4267 out() << "<div class=\"qmldoc\">";
4268 generateStatus(node, marker);
4269 generateBody(node, marker);
4270 generateThreadSafeness(node, marker);
4271 generateSince(node, marker);
4272 generateAlsoList(node, marker);
4273 out() << "</div>";
4274 out() << "</div>";
4275}
4276
4277/*!
4278 Output the "Inherits" line for the QML element,
4279 if there should be one.
4280 */
4281void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* cn,
4282 CodeMarker* marker)
4283{
4284 if (cn && !cn->links().empty()) {
4285 if (cn->links().contains(Node::InheritsLink)) {
4286 QPair<QString,QString> linkPair;
4287 linkPair = cn->links()[Node::InheritsLink];
4288 QStringList strList(linkPair.first);
4289 const Node* n = myTree->findNode(strList,Node::Fake);
4290 if (n && n->subType() == Node::QmlClass) {
4291 const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
4292 out() << "<p class=\"centerAlign\">";
4293 Text text;
4294 text << "[Inherits ";
4295 text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
4296 text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
4297 text << Atom(Atom::String, linkPair.second);
4298 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
4299 text << "]";
4300 generateText(text, cn, marker);
4301 out() << "</p>";
4302 }
4303 }
4304 }
4305}
4306
4307/*!
4308 Output the "Inherit by" list for the QML element,
4309 if it is inherited by any other elements.
4310 */
4311void DitaXmlGenerator::generateQmlInheritedBy(const QmlClassNode* cn,
4312 CodeMarker* marker)
4313{
4314 if (cn) {
4315 NodeList subs;
4316 QmlClassNode::subclasses(cn->name(),subs);
4317 if (!subs.isEmpty()) {
4318 Text text;
4319 text << Atom::ParaLeft << "Inherited by ";
4320 appendSortedQmlNames(text,cn,subs,marker);
4321 text << Atom::ParaRight;
4322 generateText(text, cn, marker);
4323 }
4324 }
4325}
4326
4327/*!
4328 Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]"
4329 line for the QML element, if there should be one.
4330
4331 If there is no class node, or if the class node status
4332 is set to Node::Internal, do nothing.
4333 */
4334void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn,
4335 CodeMarker* marker)
4336{
4337 const ClassNode* cn = qcn->classNode();
4338 if (cn && (cn->status() != Node::Internal)) {
4339 out() << "<p class=\"centerAlign\">";
4340 Text text;
4341 text << "[";
4342 text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
4343 text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
4344 text << Atom(Atom::String, qcn->name());
4345 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
4346 text << " instantiates the C++ class ";
4347 text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
4348 text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
4349 text << Atom(Atom::String, cn->name());
4350 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
4351 text << "]";
4352 generateText(text, qcn, marker);
4353 out() << "</p>";
4354 }
4355}
4356
4357/*!
4358 Output the "[QmlGraphicsXxx is instantiated by QML element Xxx]"
4359 line for the class, if there should be one.
4360
4361 If there is no QML element, or if the class node status
4362 is set to Node::Internal, do nothing.
4363 */
4364void DitaXmlGenerator::generateInstantiatedBy(const ClassNode* cn,
4365 CodeMarker* marker)
4366{
4367 if (cn && cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) {
4368 const Node* n = myTree->root()->findNode(cn->qmlElement(),Node::Fake);
4369 if (n && n->subType() == Node::QmlClass) {
4370 out() << "<p class=\"centerAlign\">";
4371 Text text;
4372 text << "[";
4373 text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
4374 text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
4375 text << Atom(Atom::String, cn->name());
4376 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
4377 text << " is instantiated by QML element ";
4378 text << Atom(Atom::LinkNode,CodeMarker::stringForNode(n));
4379 text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
4380 text << Atom(Atom::String, n->name());
4381 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
4382 text << "]";
4383 generateText(text, cn, marker);
4384 out() << "</p>";
4385 }
4386 }
4387}
4388
4389/*!
4390 Generate the <page> element for the given \a node using the \a writer.
4391 Return true if a <page> element was written; otherwise return false.
4392 */
4393bool DitaXmlGenerator::generatePageElement(QXmlStreamWriter& writer,
4394 const Node* node,
4395 CodeMarker* marker) const
4396{
4397 if (node->pageType() == Node::NoPageType)
4398 return false;
4399 if (node->name().isEmpty())
4400 return true;
4401 if (node->access() == Node::Private)
4402 return false;
4403 if (!node->isInnerNode())
4404 return false;
4405
4406 QString title;
4407 QString rawTitle;
4408 QString fullTitle;
4409 const InnerNode* inner = static_cast<const InnerNode*>(node);
4410
4411 writer.writeStartElement("page");
4412 QXmlStreamAttributes attributes;
4413 QString t;
4414 t.setNum(id++);
4415 switch (node->type()) {
4416 case Node::Fake:
4417 {
4418 const FakeNode* fake = static_cast<const FakeNode*>(node);
4419 title = fake->fullTitle();
4420 break;
4421 }
4422 case Node::Class:
4423 {
4424 title = node->name() + " Class Reference";
4425 break;
4426 }
4427 case Node::Namespace:
4428 {
4429 rawTitle = marker->plainName(inner);
4430 fullTitle = marker->plainFullName(inner);
4431 title = rawTitle + " Namespace Reference";
4432 break;
4433 }
4434 default:
4435 title = node->name();
4436 break;
4437 }
4438 writer.writeAttribute("id",t);
4439 writer.writeStartElement("pageWords");
4440 writer.writeCharacters(title);
4441 if (!inner->pageKeywords().isEmpty()) {
4442 const QStringList& w = inner->pageKeywords();
4443 for (int i = 0; i < w.size(); ++i) {
4444 writer.writeCharacters(" ");
4445 writer.writeCharacters(w.at(i).toLocal8Bit().constData());
4446 }
4447 }
4448 writer.writeEndElement();
4449 writer.writeStartElement("pageTitle");
4450 writer.writeCharacters(title);
4451 writer.writeEndElement();
4452 writer.writeStartElement("pageUrl");
4453 writer.writeCharacters(PageGenerator::fileName(node));
4454 writer.writeEndElement();
4455 writer.writeStartElement("pageType");
4456 switch (node->pageType()) {
4457 case Node::ApiPage:
4458 writer.writeCharacters("APIPage");
4459 break;
4460 case Node::ArticlePage:
4461 writer.writeCharacters("Article");
4462 break;
4463 case Node::ExamplePage:
4464 writer.writeCharacters("Example");
4465 break;
4466 default:
4467 break;
4468 }
4469 writer.writeEndElement();
4470 writer.writeEndElement();
4471 return true;
4472}
4473
4474/*!
4475 Traverse the tree recursively and generate the <keyword>
4476 elements.
4477 */
4478void DitaXmlGenerator::generatePageElements(QXmlStreamWriter& writer, const Node* node, CodeMarker* marker) const
4479{
4480 if (generatePageElement(writer, node, marker)) {
4481
4482 if (node->isInnerNode()) {
4483 const InnerNode *inner = static_cast<const InnerNode *>(node);
4484
4485 // Recurse to write an element for this child node and all its children.
4486 foreach (const Node *child, inner->childNodes())
4487 generatePageElements(writer, child, marker);
4488 }
4489 }
4490}
4491
4492/*!
4493 Outputs the file containing the index used for searching the html docs.
4494 */
4495void DitaXmlGenerator::generatePageIndex(const QString& fileName, CodeMarker* marker) const
4496{
4497 QFile file(fileName);
4498 if (!file.open(QFile::WriteOnly | QFile::Text))
4499 return ;
4500
4501 QXmlStreamWriter writer(&file);
4502 writer.setAutoFormatting(true);
4503 writer.writeStartDocument();
4504 writer.writeStartElement("qtPageIndex");
4505
4506 generatePageElements(writer, myTree->root(), marker);
4507
4508 writer.writeEndElement(); // qtPageIndex
4509 writer.writeEndDocument();
4510 file.close();
4511}
4512
4513#endif
4514
4515/*!
4516 Return the full qualification of the node \a n, but without
4517 the name of \a n itself. e.g. A::B::C
4518 */
4519QString DitaXmlGenerator::fullQualification(const Node* n)
4520{
4521 QString fq;
4522 InnerNode* in = n->parent();
4523 while (in) {
4524 if ((in->type() == Node::Class) ||
4525 (in->type() == Node::Namespace)) {
4526 if (in->name().isEmpty())
4527 break;
4528 if (fq.isEmpty())
4529 fq = in->name();
4530 else
4531 fq = in->name() + "::" + fq;
4532 }
4533 else
4534 break;
4535 in = in->parent();
4536 }
4537 return fq;
4538}
4539
4540void DitaXmlGenerator::writeDerivations(const ClassNode* cn, CodeMarker* marker)
4541{
4542 QList<RelatedClass>::ConstIterator r;
4543 int index;
4544
4545 if (!cn->baseClasses().isEmpty()) {
4546 writer.writeStartElement(CXXCLASSDERIVATIONS);
4547 r = cn->baseClasses().begin();
4548 index = 0;
4549 while (r != cn->baseClasses().end()) {
4550 writer.writeStartElement(CXXCLASSDERIVATION);
4551 writer.writeStartElement(CXXCLASSDERIVATIONACCESSSPECIFIER);
4552 writer.writeAttribute("value",(*r).accessString());
4553 writer.writeEndElement(); // </cxxClassDerivationAccessSpecifier>
4554 writer.writeStartElement(CXXCLASSBASECLASS);
4555 writer.writeAttribute("href",(*r).node->ditaXmlHref());
4556 writer.writeCharacters(marker->plainFullName((*r).node));
4557 writer.writeEndElement(); // </cxxClassBaseClass>
4558 writer.writeEndElement(); // </cxxClassDerivation>
4559 ++r;
4560 }
4561 writer.writeEndElement(); // </cxxClassDerivations>
4562 }
4563}
4564
4565void DitaXmlGenerator::writeLocation(const Node* n)
4566{
4567 QString s1, s2, s3;
4568 if (n->type() == Node::Class) {
4569 s1 = CXXCLASSAPIITEMLOCATION;
4570 s2 = CXXCLASSDECLARATIONFILE;
4571 s3 = CXXCLASSDECLARATIONFILELINE;
4572 }
4573 else if (n->type() == Node::Function) {
4574 s1 = CXXFUNCTIONAPIITEMLOCATION;
4575 s2 = CXXFUNCTIONDECLARATIONFILE;
4576 s3 = CXXFUNCTIONDECLARATIONFILELINE;
4577 }
4578 else if (n->type() == Node::Enum) {
4579 s1 = CXXENUMERATIONAPIITEMLOCATION;
4580 s2 = CXXENUMERATIONDECLARATIONFILE;
4581 s3 = CXXENUMERATIONDECLARATIONFILELINE;
4582 }
4583 else if (n->type() == Node::Typedef) {
4584 s1 = CXXTYPEDEFAPIITEMLOCATION;
4585 s2 = CXXTYPEDEFDECLARATIONFILE;
4586 s3 = CXXTYPEDEFDECLARATIONFILELINE;
4587 }
4588 else if ((n->type() == Node::Property) ||
4589 (n->type() == Node::Variable)) {
4590 s1 = CXXVARIABLEAPIITEMLOCATION;
4591 s2 = CXXVARIABLEDECLARATIONFILE;
4592 s3 = CXXVARIABLEDECLARATIONFILELINE;
4593 }
4594 writer.writeStartElement(s1);
4595 writer.writeStartElement(s2);
4596 writer.writeAttribute("name","filePath");
4597 writer.writeAttribute("value",n->location().filePath());
4598 writer.writeEndElement(); // </cxx<s2>DeclarationFile>
4599 writer.writeStartElement(s3);
4600 writer.writeAttribute("name","lineNumber");
4601 QString lineNr;
4602 writer.writeAttribute("value",lineNr.setNum(n->location().lineNo()));
4603 writer.writeEndElement(); // </cxx<s3>DeclarationFileLine>
4604 writer.writeEndElement(); // </cxx<s1>ApiItemLocation>
4605}
4606
4607void DitaXmlGenerator::writeFunctions(const Section& s,
4608 const ClassNode* cn,
4609 CodeMarker* marker)
4610{
4611 NodeList::ConstIterator m = s.members.begin();
4612 while (m != s.members.end()) {
4613 if ((*m)->type() == Node::Function) {
4614 FunctionNode* fn = const_cast<FunctionNode*>(static_cast<const FunctionNode*>(*m));
4615 writer.writeStartElement(CXXFUNCTION);
4616 writer.writeAttribute("id",fn->guid());
4617 writer.writeStartElement(APINAME);
4618 writer.writeCharacters(fn->name());
4619 writer.writeEndElement(); // </apiName>
4620 generateBrief(fn,marker);
4621 writer.writeStartElement(CXXFUNCTIONDETAIL);
4622 writer.writeStartElement(CXXFUNCTIONDEFINITION);
4623 writer.writeStartElement(CXXFUNCTIONACCESSSPECIFIER);
4624 writer.writeAttribute("value",fn->accessString());
4625 writer.writeEndElement(); // <cxxFunctionAccessSpecifier>
4626
4627 if (fn->isStatic()) {
4628 writer.writeStartElement(CXXFUNCTIONSTORAGECLASSSPECIFIERSTATIC);
4629 writer.writeAttribute("name","static");
4630 writer.writeAttribute("value","static");
4631 writer.writeEndElement(); // <cxxFunctionStorageClassSpecifierStatic>
4632 }
4633
4634 if (fn->isConst()) {
4635 writer.writeStartElement(CXXFUNCTIONCONST);
4636 writer.writeAttribute("name","const");
4637 writer.writeAttribute("value","const");
4638 writer.writeEndElement(); // <cxxFunctionConst>
4639 }
4640
4641 if (fn->virtualness() != FunctionNode::NonVirtual) {
4642 writer.writeStartElement(CXXFUNCTIONVIRTUAL);
4643 writer.writeAttribute("name","virtual");
4644 writer.writeAttribute("value","virtual");
4645 writer.writeEndElement(); // <cxxFunctionVirtual>
4646 if (fn->virtualness() == FunctionNode::PureVirtual) {
4647 writer.writeStartElement(CXXFUNCTIONPUREVIRTUAL);
4648 writer.writeAttribute("name","pure virtual");
4649 writer.writeAttribute("value","pure virtual");
4650 writer.writeEndElement(); // <cxxFunctionPureVirtual>
4651 }
4652 }
4653
4654 if (fn->name() == cn->name()) {
4655 writer.writeStartElement(CXXFUNCTIONCONSTRUCTOR);
4656 writer.writeAttribute("name","constructor");
4657 writer.writeAttribute("value","constructor");
4658 writer.writeEndElement(); // <cxxFunctionConstructor>
4659 }
4660 else if (fn->name()[0] == QChar('~')) {
4661 writer.writeStartElement(CXXFUNCTIONDESTRUCTOR);
4662 writer.writeAttribute("name","destructor");
4663 writer.writeAttribute("value","destructor");
4664 writer.writeEndElement(); // <cxxFunctionDestructor>
4665 }
4666 else {
4667 writer.writeStartElement(CXXFUNCTIONDECLAREDTYPE);
4668 writer.writeCharacters(fn->returnType());
4669 writer.writeEndElement(); // <cxxFunctionDeclaredType>
4670 }
4671 QString fq = fullQualification(fn);
4672 if (!fq.isEmpty()) {
4673 writer.writeStartElement(CXXFUNCTIONSCOPEDNAME);
4674 writer.writeCharacters(fq);
4675 writer.writeEndElement(); // <cxxFunctionScopedName>
4676 }
4677 writer.writeStartElement(CXXFUNCTIONPROTOTYPE);
4678 writer.writeCharacters(fn->signature(true));
4679 writer.writeEndElement(); // <cxxFunctionPrototype>
4680
4681 QString fnl = fn->signature(false);
4682 int idx = fnl.indexOf(' ');
4683 if (idx < 0)
4684 idx = 0;
4685 else
4686 ++idx;
4687 fnl = fn->parent()->name() + "::" + fnl.mid(idx);
4688 writer.writeStartElement(CXXFUNCTIONNAMELOOKUP);
4689 writer.writeCharacters(fnl);
4690 writer.writeEndElement(); // <cxxFunctionNameLookup>
4691
4692 if (fn->isReimp() && fn->reimplementedFrom() != 0) {
4693 FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom();
4694 writer.writeStartElement(CXXFUNCTIONREIMPLEMENTED);
4695 writer.writeAttribute("href",rfn->ditaXmlHref());
4696 writer.writeCharacters(marker->plainFullName(rfn));
4697 writer.writeEndElement(); // </cxxFunctionReimplemented>
4698 }
4699 writeParameters(fn,marker);
4700 writeLocation(fn);
4701 writer.writeEndElement(); // <cxxFunctionDefinition>
4702 writer.writeStartElement(APIDESC);
4703
4704 if (!fn->doc().isEmpty()) {
4705 generateBody(fn, marker);
4706 // generateAlsoList(inner, marker);
4707 }
4708
4709 writer.writeEndElement(); // </apiDesc>
4710 writer.writeEndElement(); // </cxxFunctionDetail>
4711 writer.writeEndElement(); // </cxxFunction>
4712
4713 if (fn->metaness() == FunctionNode::Ctor ||
4714 fn->metaness() == FunctionNode::Dtor ||
4715 fn->overloadNumber() != 1) {
4716 }
4717 }
4718 ++m;
4719 }
4720}
4721
4722void DitaXmlGenerator::writeParameters(const FunctionNode* fn, CodeMarker* marker)
4723{
4724 const QList<Parameter>& parameters = fn->parameters();
4725 if (!parameters.isEmpty()) {
4726 writer.writeStartElement(CXXFUNCTIONPARAMETERS);
4727 QList<Parameter>::ConstIterator p = parameters.begin();
4728 while (p != parameters.end()) {
4729 writer.writeStartElement(CXXFUNCTIONPARAMETER);
4730 writer.writeStartElement(CXXFUNCTIONPARAMETERDECLAREDTYPE);
4731 writer.writeCharacters((*p).leftType());
4732 if (!(*p).rightType().isEmpty())
4733 writer.writeCharacters((*p).rightType());
4734 writer.writeEndElement(); // <cxxFunctionParameterDeclaredType>
4735 writer.writeStartElement(CXXFUNCTIONPARAMETERDECLARATIONNAME);
4736 writer.writeCharacters((*p).name());
4737 writer.writeEndElement(); // <cxxFunctionParameterDeclarationName>
4738 if (!(*p).defaultValue().isEmpty()) {
4739 writer.writeStartElement(CXXFUNCTIONPARAMETERDEFAULTVALUE);
4740 writer.writeCharacters((*p).defaultValue());
4741 writer.writeEndElement(); // <cxxFunctionParameterDefaultValue>
4742 }
4743 writer.writeEndElement(); // <cxxFunctionParameter>
4744 ++p;
4745 }
4746 writer.writeEndElement(); // <cxxFunctionParameters>
4747 }
4748}
4749
4750void DitaXmlGenerator::writeEnumerations(const Section& s,
4751 const ClassNode* cn,
4752 CodeMarker* marker)
4753{
4754 NodeList::ConstIterator m = s.members.begin();
4755 while (m != s.members.end()) {
4756 if ((*m)->type() == Node::Enum) {
4757 const EnumNode* en = static_cast<const EnumNode*>(*m);
4758 writer.writeStartElement(CXXENUMERATION);
4759 writer.writeAttribute("id",en->guid());
4760 writer.writeStartElement(APINAME);
4761 writer.writeCharacters(en->name());
4762 writer.writeEndElement(); // </apiName>
4763 generateBrief(en,marker);
4764 writer.writeStartElement(CXXENUMERATIONDETAIL);
4765 writer.writeStartElement(CXXENUMERATIONDEFINITION);
4766 writer.writeStartElement(CXXENUMERATIONACCESSSPECIFIER);
4767 writer.writeAttribute("value",en->accessString());
4768 writer.writeEndElement(); // <cxxEnumerationAccessSpecifier>
4769
4770 QString fq = fullQualification(en);
4771 if (!fq.isEmpty()) {
4772 writer.writeStartElement(CXXENUMERATIONSCOPEDNAME);
4773 writer.writeCharacters(fq);
4774 writer.writeEndElement(); // <cxxEnumerationScopedName>
4775 }
4776 const QList<EnumItem>& items = en->items();
4777 if (!items.isEmpty()) {
4778 writer.writeStartElement(CXXENUMERATIONPROTOTYPE);
4779 writer.writeCharacters(en->name());
4780 writer.writeCharacters(" = { ");
4781 QList<EnumItem>::ConstIterator i = items.begin();
4782 while (i != items.end()) {
4783 writer.writeCharacters((*i).name());
4784 if (!(*i).value().isEmpty()) {
4785 writer.writeCharacters(" = ");
4786 writer.writeCharacters((*i).value());
4787 }
4788 ++i;
4789 if (i != items.end())
4790 writer.writeCharacters(", ");
4791 }
4792 writer.writeCharacters(" }");
4793 writer.writeEndElement(); // <cxxEnumerationPrototype>
4794 }
4795
4796 writer.writeStartElement(CXXENUMERATIONNAMELOOKUP);
4797 writer.writeCharacters(en->parent()->name() + "::" + en->name());
4798 writer.writeEndElement(); // <cxxEnumerationNameLookup>
4799
4800 if (!items.isEmpty()) {
4801 writer.writeStartElement(CXXENUMERATORS);
4802 QList<EnumItem>::ConstIterator i = items.begin();
4803 while (i != items.end()) {
4804 writer.writeStartElement(CXXENUMERATOR);
4805 writer.writeStartElement(APINAME);
4806 writer.writeCharacters((*i).name());
4807 writer.writeEndElement(); // </apiName>
4808
4809 QString fq = fullQualification(en->parent());
4810 if (!fq.isEmpty()) {
4811 writer.writeStartElement(CXXENUMERATORSCOPEDNAME);
4812 writer.writeCharacters(fq + "::" + (*i).name());
4813 writer.writeEndElement(); // <cxxEnumeratorScopedName>
4814 }
4815 writer.writeStartElement(CXXENUMERATORPROTOTYPE);
4816 writer.writeCharacters((*i).name());
4817 writer.writeEndElement(); // <cxxEnumeratorPrototype>
4818 writer.writeStartElement(CXXENUMERATORNAMELOOKUP);
4819 writer.writeCharacters(en->parent()->name() + "::" + (*i).name());
4820 writer.writeEndElement(); // <cxxEnumeratorNameLookup>
4821
4822 if (!(*i).value().isEmpty()) {
4823 writer.writeStartElement(CXXENUMERATORINITIALISER);
4824 writer.writeAttribute("value", (*i).value());
4825 writer.writeEndElement(); // <cxxEnumeratorInitialiser>
4826 }
4827 if (!(*i).text().isEmpty()) {
4828 writer.writeStartElement(APIDESC);
4829 generateText((*i).text(), en, marker);
4830 writer.writeEndElement(); // </apiDesc>
4831 }
4832 writer.writeEndElement(); // <cxxEnumerator>
4833 ++i;
4834 }
4835 writer.writeEndElement(); // <cxxEnumerators>
4836 }
4837
4838 writeLocation(en);
4839 writer.writeEndElement(); // <cxxEnumerationDefinition>
4840 writer.writeStartElement(APIDESC);
4841
4842 if (!en->doc().isEmpty()) {
4843 generateBody(en, marker);
4844 }
4845
4846 writer.writeEndElement(); // </apiDesc>
4847 writer.writeEndElement(); // </cxxEnumerationDetail>
4848 writer.writeEndElement(); // </cxxEnumeration>
4849 }
4850 ++m;
4851 }
4852}
4853
4854void DitaXmlGenerator::writeTypedefs(const Section& s,
4855 const ClassNode* cn,
4856 CodeMarker* marker)
4857{
4858 NodeList::ConstIterator m = s.members.begin();
4859 while (m != s.members.end()) {
4860 if ((*m)->type() == Node::Typedef) {
4861 const TypedefNode* tn = static_cast<const TypedefNode*>(*m);
4862 writer.writeStartElement(CXXTYPEDEF);
4863 writer.writeAttribute("id",tn->guid());
4864 writer.writeStartElement(APINAME);
4865 writer.writeCharacters(tn->name());
4866 writer.writeEndElement(); // </apiName>
4867 generateBrief(tn,marker);
4868 writer.writeStartElement(CXXTYPEDEFDETAIL);
4869 writer.writeStartElement(CXXTYPEDEFDEFINITION);
4870 writer.writeStartElement(CXXTYPEDEFACCESSSPECIFIER);
4871 writer.writeAttribute("value",tn->accessString());
4872 writer.writeEndElement(); // <cxxTypedefAccessSpecifier>
4873
4874 QString fq = fullQualification(tn);
4875 if (!fq.isEmpty()) {
4876 writer.writeStartElement(CXXTYPEDEFSCOPEDNAME);
4877 writer.writeCharacters(fq);
4878 writer.writeEndElement(); // <cxxTypedefScopedName>
4879 }
4880 writer.writeStartElement(CXXTYPEDEFNAMELOOKUP);
4881 writer.writeCharacters(tn->parent()->name() + "::" + tn->name());
4882 writer.writeEndElement(); // <cxxTypedefNameLookup>
4883
4884 writeLocation(tn);
4885 writer.writeEndElement(); // <cxxTypedefDefinition>
4886 writer.writeStartElement(APIDESC);
4887
4888 if (!tn->doc().isEmpty()) {
4889 generateBody(tn, marker);
4890 }
4891
4892 writer.writeEndElement(); // </apiDesc>
4893 writer.writeEndElement(); // </cxxTypedefDetail>
4894 writer.writeEndElement(); // </cxxTypedef>
4895 }
4896 ++m;
4897 }
4898}
4899
4900void DitaXmlGenerator::writeProperties(const Section& s,
4901 const ClassNode* cn,
4902 CodeMarker* marker)
4903{
4904 NodeList::ConstIterator m = s.members.begin();
4905 while (m != s.members.end()) {
4906 if ((*m)->type() == Node::Property) {
4907 const PropertyNode* pn = static_cast<const PropertyNode*>(*m);
4908 writer.writeStartElement(CXXVARIABLE);
4909 writer.writeAttribute("id",pn->guid());
4910 writer.writeStartElement(APINAME);
4911 writer.writeCharacters(pn->name());
4912 writer.writeEndElement(); // </apiName>
4913 generateBrief(pn,marker);
4914 writer.writeStartElement(CXXVARIABLEDETAIL);
4915 writer.writeStartElement(CXXVARIABLEDEFINITION);
4916 writer.writeStartElement(CXXVARIABLEACCESSSPECIFIER);
4917 writer.writeAttribute("value",pn->accessString());
4918 writer.writeEndElement(); // <cxxVariableAccessSpecifier>
4919
4920 if (!pn->qualifiedDataType().isEmpty()) {
4921 writer.writeStartElement(CXXVARIABLEDECLAREDTYPE);
4922 writer.writeCharacters(pn->qualifiedDataType());
4923 writer.writeEndElement(); // <cxxVariableDeclaredType>
4924 }
4925 QString fq = fullQualification(pn);
4926 if (!fq.isEmpty()) {
4927 writer.writeStartElement(CXXVARIABLESCOPEDNAME);
4928 writer.writeCharacters(fq);
4929 writer.writeEndElement(); // <cxxVariableScopedName>
4930 }
4931
4932 writer.writeStartElement(CXXVARIABLEPROTOTYPE);
4933 writer.writeCharacters("Q_PROPERTY(");
4934 writer.writeCharacters(pn->qualifiedDataType());
4935 writer.writeCharacters(" ");
4936 writer.writeCharacters(pn->name());
4937 writePropParams("READ",pn->getters());
4938 writePropParams("WRITE",pn->setters());
4939 writePropParams("RESET",pn->resetters());
4940 writePropParams("NOTIFY",pn->notifiers());
4941 if (pn->isDesignable() != pn->designableDefault()) {
4942 writer.writeCharacters(" DESIGNABLE ");
4943 if (!pn->runtimeDesignabilityFunction().isEmpty())
4944 writer.writeCharacters(pn->runtimeDesignabilityFunction());
4945 else
4946 writer.writeCharacters(pn->isDesignable() ? "true" : "false");
4947 }
4948 if (pn->isScriptable() != pn->scriptableDefault()) {
4949 writer.writeCharacters(" SCRIPTABLE ");
4950 if (!pn->runtimeScriptabilityFunction().isEmpty())
4951 writer.writeCharacters(pn->runtimeScriptabilityFunction());
4952 else
4953 writer.writeCharacters(pn->isScriptable() ? "true" : "false");
4954 }
4955 if (pn->isWritable() != pn->writableDefault()) {
4956 writer.writeCharacters(" STORED ");
4957 writer.writeCharacters(pn->isStored() ? "true" : "false");
4958 }
4959 if (pn->isUser() != pn->userDefault()) {
4960 writer.writeCharacters(" USER ");
4961 writer.writeCharacters(pn->isUser() ? "true" : "false");
4962 }
4963 if (pn->isConstant())
4964 writer.writeCharacters(" CONSTANT");
4965 if (pn->isFinal())
4966 writer.writeCharacters(" FINAL");
4967 writer.writeCharacters(")");
4968 writer.writeEndElement(); // <cxxVariablePrototype>
4969
4970 writer.writeStartElement(CXXVARIABLENAMELOOKUP);
4971 writer.writeCharacters(pn->parent()->name() + "::" + pn->name());
4972 writer.writeEndElement(); // <cxxVariableNameLookup>
4973
4974 if (pn->overriddenFrom() != 0) {
4975 PropertyNode* opn = (PropertyNode*)pn->overriddenFrom();
4976 writer.writeStartElement(CXXVARIABLEREIMPLEMENTED);
4977 writer.writeAttribute("href",opn->ditaXmlHref());
4978 writer.writeCharacters(marker->plainFullName(opn));
4979 writer.writeEndElement(); // </cxxVariableReimplemented>
4980 }
4981
4982 writeLocation(pn);
4983 writer.writeEndElement(); // <cxxVariableDefinition>
4984 writer.writeStartElement(APIDESC);
4985
4986 if (!pn->doc().isEmpty()) {
4987 generateBody(pn, marker);
4988 }
4989
4990 writer.writeEndElement(); // </apiDesc>
4991 writer.writeEndElement(); // </cxxVariableDetail>
4992 writer.writeEndElement(); // </cxxVariable>
4993 }
4994 ++m;
4995 }
4996}
4997
4998void DitaXmlGenerator::writeDataMembers(const Section& s,
4999 const ClassNode* cn,
5000 CodeMarker* marker)
5001{
5002 NodeList::ConstIterator m = s.members.begin();
5003 while (m != s.members.end()) {
5004 if ((*m)->type() == Node::Variable) {
5005 const VariableNode* vn = static_cast<const VariableNode*>(*m);
5006 writer.writeStartElement(CXXVARIABLE);
5007 writer.writeAttribute("id",vn->guid());
5008 writer.writeStartElement(APINAME);
5009 writer.writeCharacters(vn->name());
5010 writer.writeEndElement(); // </apiName>
5011 generateBrief(vn,marker);
5012 writer.writeStartElement(CXXVARIABLEDETAIL);
5013 writer.writeStartElement(CXXVARIABLEDEFINITION);
5014 writer.writeStartElement(CXXVARIABLEACCESSSPECIFIER);
5015 writer.writeAttribute("value",vn->accessString());
5016 writer.writeEndElement(); // <cxxVariableAccessSpecifier>
5017
5018 if (vn->isStatic()) {
5019 writer.writeStartElement(CXXVARIABLESTORAGECLASSSPECIFIERSTATIC);
5020 writer.writeAttribute("name","static");
5021 writer.writeAttribute("value","static");
5022 writer.writeEndElement(); // <cxxVariableStorageClassSpecifierStatic>
5023 }
5024
5025 writer.writeStartElement(CXXVARIABLEDECLAREDTYPE);
5026 writer.writeCharacters(vn->leftType());
5027 if (!vn->rightType().isEmpty())
5028 writer.writeCharacters(vn->rightType());
5029 writer.writeEndElement(); // <cxxVariableDeclaredType>
5030
5031 QString fq = fullQualification(vn);
5032 if (!fq.isEmpty()) {
5033 writer.writeStartElement(CXXVARIABLESCOPEDNAME);
5034 writer.writeCharacters(fq);
5035 writer.writeEndElement(); // <cxxVariableScopedName>
5036 }
5037
5038 writer.writeStartElement(CXXVARIABLEPROTOTYPE);
5039 writer.writeCharacters(vn->leftType() + " ");
5040 //writer.writeCharacters(vn->parent()->name() + "::" + vn->name());
5041 writer.writeCharacters(vn->name());
5042 if (!vn->rightType().isEmpty())
5043 writer.writeCharacters(vn->rightType());
5044 writer.writeEndElement(); // <cxxVariablePrototype>
5045
5046 writer.writeStartElement(CXXVARIABLENAMELOOKUP);
5047 writer.writeCharacters(vn->parent()->name() + "::" + vn->name());
5048 writer.writeEndElement(); // <cxxVariableNameLookup>
5049
5050 writeLocation(vn);
5051 writer.writeEndElement(); // <cxxVariableDefinition>
5052 writer.writeStartElement(APIDESC);
5053
5054 if (!vn->doc().isEmpty()) {
5055 generateBody(vn, marker);
5056 }
5057
5058 writer.writeEndElement(); // </apiDesc>
5059 writer.writeEndElement(); // </cxxVariableDetail>
5060 writer.writeEndElement(); // </cxxVariable>
5061 }
5062 ++m;
5063 }
5064}
5065
5066void DitaXmlGenerator::writeMacros(const Section& s,
5067 const ClassNode* cn,
5068 CodeMarker* marker)
5069{
5070 NodeList::ConstIterator m = s.members.begin();
5071 while (m != s.members.end()) {
5072 if ((*m)->type() == Node::Function) {
5073 const FunctionNode* fn = static_cast<const FunctionNode*>(*m);
5074 if (fn->isMacro()) {
5075 writer.writeStartElement(CXXDEFINE);
5076 writer.writeAttribute("id",fn->guid());
5077 writer.writeStartElement(APINAME);
5078 writer.writeCharacters(fn->name());
5079 writer.writeEndElement(); // </apiName>
5080 generateBrief(fn,marker);
5081 writer.writeStartElement(CXXDEFINEDETAIL);
5082 writer.writeStartElement(CXXDEFINEDEFINITION);
5083 writer.writeStartElement(CXXDEFINEACCESSSPECIFIER);
5084 writer.writeAttribute("value",fn->accessString());
5085 writer.writeEndElement(); // <cxxDefineAccessSpecifier>
5086
5087 writer.writeStartElement(CXXDEFINEPROTOTYPE);
5088 writer.writeCharacters("#define ");
5089 writer.writeCharacters(fn->name());
5090 if (fn->metaness() == FunctionNode::MacroWithParams) {
5091 QStringList params = fn->parameterNames();
5092 if (!params.isEmpty()) {
5093 writer.writeCharacters("(");
5094 for (int i = 0; i < params.size(); ++i) {
5095 if (params[i].isEmpty())
5096 writer.writeCharacters("...");
5097 else
5098 writer.writeCharacters(params[i]);
5099 if ((i+1) < params.size())
5100 writer.writeCharacters(", ");
5101 }
5102 writer.writeCharacters(")");
5103 }
5104 }
5105 writer.writeEndElement(); // <cxxDefinePrototype>
5106
5107 writer.writeStartElement(CXXDEFINENAMELOOKUP);
5108 writer.writeCharacters(fn->name());
5109 writer.writeEndElement(); // <cxxDefineNameLookup>
5110
5111 if (fn->reimplementedFrom() != 0) {
5112 FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom();
5113 writer.writeStartElement(CXXDEFINEREIMPLEMENTED);
5114 writer.writeAttribute("href",rfn->ditaXmlHref());
5115 writer.writeCharacters(marker->plainFullName(rfn));
5116 writer.writeEndElement(); // </cxxDefineReimplemented>
5117 }
5118
5119 if (fn->metaness() == FunctionNode::MacroWithParams) {
5120 QStringList params = fn->parameterNames();
5121 if (!params.isEmpty()) {
5122 writer.writeStartElement(CXXDEFINEPARAMETERS);
5123 for (int i = 0; i < params.size(); ++i) {
5124 writer.writeStartElement(CXXDEFINEPARAMETER);
5125 writer.writeStartElement(CXXDEFINEPARAMETERDECLARATIONNAME);
5126 writer.writeCharacters(params[i]);
5127 writer.writeEndElement(); // <cxxDefineParameterDeclarationName>
5128 writer.writeEndElement(); // <cxxDefineParameter>
5129 }
5130 writer.writeEndElement(); // <cxxDefineParameters>
5131 }
5132 }
5133
5134 writeLocation(fn);
5135 writer.writeEndElement(); // <cxxDefineDefinition>
5136 writer.writeStartElement(APIDESC);
5137
5138 if (!fn->doc().isEmpty()) {
5139 generateBody(fn, marker);
5140 }
5141
5142 writer.writeEndElement(); // </apiDesc>
5143 writer.writeEndElement(); // </cxxDefineDetail>
5144 writer.writeEndElement(); // </cxxDefine>
5145 }
5146 }
5147 ++m;
5148 }
5149}
5150
5151void DitaXmlGenerator::writePropParams(const QString& tag, const NodeList& nlist)
5152{
5153 NodeList::const_iterator n = nlist.begin();
5154 while (n != nlist.end()) {
5155 writer.writeCharacters(" ");
5156 writer.writeCharacters(tag);
5157 writer.writeCharacters(" ");
5158 writer.writeCharacters((*n)->name());
5159 ++n;
5160 }
5161}
5162
5163QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.