tools/qdoc3/ditaxmlgenerator.cpp
changeset 33 3e2da88830cd
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
       
     1 
       
     2 /****************************************************************************
       
     3 **
       
     4 ** Copyright (C) 2010 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 ** No Commercial Usage
       
    12 ** This file contains pre-release code and may not be distributed.
       
    13 ** You may use this file in accordance with the terms and conditions
       
    14 ** contained in the Technology Preview License Agreement accompanying
       
    15 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    30 ** Nokia at qt-info@nokia.com.
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 **
       
    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 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 #define COMMAND_VERSION                         Doc::alias("version")
       
    63 int 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 
       
   338 QString 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 
       
   357 static bool showBrokenLinks = false;
       
   358 
       
   359 static 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 
       
   376 DitaXmlGenerator::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 
       
   392 DitaXmlGenerator::~DitaXmlGenerator()
       
   393 {
       
   394     // nothing yet.
       
   395 }
       
   396 
       
   397 void 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     offlineDocs = !config.getBool(CONFIG_ONLINE);
       
   444     projectDescription = config.getString(CONFIG_DESCRIPTION);
       
   445     if (projectDescription.isEmpty() && !project.isEmpty())
       
   446         projectDescription = project + " Reference Documentation";
       
   447 
       
   448     projectUrl = config.getString(CONFIG_URL);
       
   449 
       
   450     outputEncoding = config.getString(CONFIG_OUTPUTENCODING);
       
   451     if (outputEncoding.isEmpty())
       
   452         outputEncoding = QLatin1String("ISO-8859-1");
       
   453     outputCodec = QTextCodec::codecForName(outputEncoding.toLocal8Bit());
       
   454 
       
   455     naturalLanguage = config.getString(CONFIG_NATURALLANGUAGE);
       
   456     if (naturalLanguage.isEmpty())
       
   457         naturalLanguage = QLatin1String("en");
       
   458 
       
   459     QSet<QString> editionNames = config.subVars(CONFIG_EDITION);
       
   460     QSet<QString>::ConstIterator edition = editionNames.begin();
       
   461     while (edition != editionNames.end()) {
       
   462         QString editionName = *edition;
       
   463         QStringList editionModules = config.getStringList(CONFIG_EDITION +
       
   464                                                           Config::dot +
       
   465                                                           editionName +
       
   466                                                           Config::dot +
       
   467                                                           "modules");
       
   468         QStringList editionGroups = config.getStringList(CONFIG_EDITION +
       
   469                                                          Config::dot +
       
   470                                                          editionName +
       
   471                                                          Config::dot +
       
   472                                                          "groups");
       
   473 
       
   474         if (!editionModules.isEmpty())
       
   475             editionModuleMap[editionName] = editionModules;
       
   476         if (!editionGroups.isEmpty())
       
   477             editionGroupMap[editionName] = editionGroups;
       
   478 
       
   479         ++edition;
       
   480     }
       
   481 
       
   482     slow = config.getBool(CONFIG_SLOW);
       
   483 
       
   484     stylesheets = config.getStringList(DitaXmlGenerator::format() +
       
   485                                        Config::dot +
       
   486                                        DITAXMLGENERATOR_STYLESHEETS);
       
   487     customHeadElements = config.getStringList(DitaXmlGenerator::format() +
       
   488                                               Config::dot +
       
   489                                               DITAXMLGENERATOR_CUSTOMHEADELEMENTS);
       
   490     codeIndent = config.getInt(CONFIG_CODEINDENT);
       
   491 
       
   492 }
       
   493 
       
   494 void DitaXmlGenerator::terminateGenerator()
       
   495 {
       
   496     Generator::terminateGenerator();
       
   497 }
       
   498 
       
   499 QString DitaXmlGenerator::format()
       
   500 {
       
   501     return "DITAXML";
       
   502 }
       
   503 
       
   504 /*!
       
   505   Calls lookupGuid() to get a GUID for \a text, then writes
       
   506   it to the XML stream as an "id" attribute, and returns it.
       
   507  */
       
   508 QString DitaXmlGenerator::writeGuidAttribute(QString text)
       
   509 {
       
   510     QString guid = lookupGuid(text);
       
   511     writer.writeAttribute("id",guid);
       
   512     return guid;
       
   513 }
       
   514 
       
   515 /*!
       
   516   Looks up \a text in the GUID map. If it finds \a text,
       
   517   it returns the associated GUID. Otherwise it inserts
       
   518   \a text into the map with a new GUID, and it returns
       
   519   the new GUID.
       
   520  */
       
   521 QString DitaXmlGenerator::lookupGuid(QString text)
       
   522 {
       
   523     QMap<QString, QString>::const_iterator i = name2guidMap.find(text);
       
   524     if (i != name2guidMap.end())
       
   525         return i.value();
       
   526     QString guid = QUuid::createUuid().toString();
       
   527     name2guidMap.insert(text,guid);
       
   528     return guid;
       
   529 }
       
   530 
       
   531 /*!
       
   532   This is where the DITA XML files are written.
       
   533   \note The file generation is done in the base class,
       
   534   PageGenerator::generateTree().
       
   535  */
       
   536 void DitaXmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
       
   537 {
       
   538     myTree = tree;
       
   539     nonCompatClasses.clear();
       
   540     mainClasses.clear();
       
   541     compatClasses.clear();
       
   542     obsoleteClasses.clear();
       
   543     moduleClassMap.clear();
       
   544     moduleNamespaceMap.clear();
       
   545     funcIndex.clear();
       
   546     legaleseTexts.clear();
       
   547     serviceClasses.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 
       
   557 void 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  */
       
   573 int 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().contains("classesbymodule")) {
       
   756             QString arg = atom->string().trimmed();
       
   757             QString moduleName = atom->string().mid(atom->string().indexOf(
       
   758                 "classesbymodule") + 15).trimmed();
       
   759             if (moduleClassMap.contains(moduleName))
       
   760                 generateAnnotatedList(relative, marker, moduleClassMap[moduleName]);
       
   761         }
       
   762         else if (atom->string().contains("classesbyedition")) {
       
   763 
       
   764             QString arg = atom->string().trimmed();
       
   765             QString editionName = atom->string().mid(atom->string().indexOf(
       
   766                 "classesbyedition") + 16).trimmed();
       
   767 
       
   768             if (editionModuleMap.contains(editionName)) {
       
   769 
       
   770                 // Add all classes in the modules listed for that edition.
       
   771                 NodeMap editionClasses;
       
   772                 foreach (const QString &moduleName, editionModuleMap[editionName]) {
       
   773                     if (moduleClassMap.contains(moduleName))
       
   774                         editionClasses.unite(moduleClassMap[moduleName]);
       
   775                 }
       
   776 
       
   777                 // Add additional groups and remove groups of classes that
       
   778                 // should be excluded from the edition.
       
   779 
       
   780                 QMultiMap <QString, Node *> groups = myTree->groups();
       
   781                 foreach (const QString &groupName, editionGroupMap[editionName]) {
       
   782                     QList<Node *> groupClasses;
       
   783                     if (groupName.startsWith("-")) {
       
   784                         groupClasses = groups.values(groupName.mid(1));
       
   785                         foreach (const Node *node, groupClasses)
       
   786                             editionClasses.remove(node->name());
       
   787                     }
       
   788                     else {
       
   789                         groupClasses = groups.values(groupName);
       
   790                         foreach (const Node *node, groupClasses)
       
   791                             editionClasses.insert(node->name(), node);
       
   792                     }
       
   793                 }
       
   794                 generateAnnotatedList(relative, marker, editionClasses);
       
   795             }
       
   796         }
       
   797         else if (atom->string() == "classhierarchy") {
       
   798             generateClassHierarchy(relative, marker, nonCompatClasses);
       
   799         }
       
   800         else if (atom->string() == "compatclasses") {
       
   801             generateCompactList(relative, marker, compatClasses, false);
       
   802         }
       
   803         else if (atom->string() == "obsoleteclasses") {
       
   804             generateCompactList(relative, marker, obsoleteClasses, false);
       
   805         }
       
   806         else if (atom->string() == "functionindex") {
       
   807             generateFunctionIndex(relative, marker);
       
   808         }
       
   809         else if (atom->string() == "legalese") {
       
   810             generateLegaleseList(relative, marker);
       
   811         }
       
   812         else if (atom->string() == "mainclasses") {
       
   813             generateCompactList(relative, marker, mainClasses, true);
       
   814         }
       
   815         else if (atom->string() == "services") {
       
   816             generateCompactList(relative, marker, serviceClasses, false);
       
   817         }
       
   818         else if (atom->string() == "overviews") {
       
   819             generateOverviewList(relative, marker);
       
   820         }
       
   821         else if (atom->string() == "namespaces") {
       
   822             generateAnnotatedList(relative, marker, namespaceIndex);
       
   823         }
       
   824         else if (atom->string() == "related") {
       
   825             const FakeNode *fake = static_cast<const FakeNode *>(relative);
       
   826             if (fake && !fake->groupMembers().isEmpty()) {
       
   827                 NodeMap groupMembersMap;
       
   828                 foreach (const Node *node, fake->groupMembers()) {
       
   829                     if (node->type() == Node::Fake)
       
   830                         groupMembersMap[fullName(node, relative, marker)] = node;
       
   831                 }
       
   832                 generateAnnotatedList(fake, marker, groupMembersMap);
       
   833             }
       
   834         }
       
   835         else if (atom->string() == "relatedinline") {
       
   836             const FakeNode *fake = static_cast<const FakeNode *>(relative);
       
   837             if (fake && !fake->groupMembers().isEmpty()) {
       
   838                 // Reverse the list into the original scan order.
       
   839                 // Should be sorted.  But on what?  It may not be a
       
   840                 // regular class or page definition.
       
   841                 QList<const Node *> list;
       
   842                 foreach (const Node *node, fake->groupMembers())
       
   843                     list.prepend(node);
       
   844                 foreach (const Node *node, list)
       
   845                     generateBody(node, marker);
       
   846             }
       
   847         }
       
   848         break;
       
   849     case Atom::SinceList:
       
   850         {
       
   851             NewSinceMaps::const_iterator nsmap;
       
   852             nsmap = newSinceMaps.find(atom->string());
       
   853             NewClassMaps::const_iterator ncmap;
       
   854             ncmap = newClassMaps.find(atom->string());
       
   855             NewClassMaps::const_iterator nqcmap;
       
   856             nqcmap = newQmlClassMaps.find(atom->string());
       
   857             if ((nsmap != newSinceMaps.constEnd()) && !nsmap.value().isEmpty()) {
       
   858                 QList<Section> sections;
       
   859                 QList<Section>::ConstIterator s;
       
   860                 for (int i=0; i<LastSinceType; ++i)
       
   861                     sections.append(Section(sinceTitle(i),QString(),QString(),QString()));
       
   862 
       
   863                 NodeMultiMap::const_iterator n = nsmap.value().constBegin();
       
   864                 while (n != nsmap.value().constEnd()) {
       
   865                     const Node* node = n.value();
       
   866                     switch (node->type()) {
       
   867                       case Node::Fake:
       
   868                           if (node->subType() == Node::QmlClass) {
       
   869                               sections[QmlClass].appendMember((Node*)node);
       
   870                           }
       
   871                           break;
       
   872                       case Node::Namespace:
       
   873                           sections[Namespace].appendMember((Node*)node);
       
   874                           break;
       
   875                       case Node::Class: 
       
   876                           sections[Class].appendMember((Node*)node);
       
   877                           break;
       
   878                       case Node::Enum: 
       
   879                           sections[Enum].appendMember((Node*)node);
       
   880                           break;
       
   881                       case Node::Typedef: 
       
   882                           sections[Typedef].appendMember((Node*)node);
       
   883                           break;
       
   884                       case Node::Function: {
       
   885                           const FunctionNode* fn = static_cast<const FunctionNode*>(node);
       
   886                           if (fn->isMacro())
       
   887                               sections[Macro].appendMember((Node*)node);
       
   888                           else {
       
   889                               Node* p = fn->parent();
       
   890                               if (p) {
       
   891                                   if (p->type() == Node::Class)
       
   892                                       sections[MemberFunction].appendMember((Node*)node);
       
   893                                   else if (p->type() == Node::Namespace) {
       
   894                                       if (p->name().isEmpty())
       
   895                                           sections[GlobalFunction].appendMember((Node*)node);
       
   896                                       else
       
   897                                           sections[NamespaceFunction].appendMember((Node*)node);
       
   898                                   }
       
   899                                   else
       
   900                                       sections[GlobalFunction].appendMember((Node*)node);
       
   901                               }
       
   902                               else
       
   903                                   sections[GlobalFunction].appendMember((Node*)node);
       
   904                           }
       
   905                           break;
       
   906                       }
       
   907                       case Node::Property:
       
   908                           sections[Property].appendMember((Node*)node);
       
   909                           break;
       
   910                       case Node::Variable: 
       
   911                           sections[Variable].appendMember((Node*)node);
       
   912                           break;
       
   913                       case Node::QmlProperty:
       
   914                           sections[QmlProperty].appendMember((Node*)node);
       
   915                           break;
       
   916                       case Node::QmlSignal:
       
   917                           sections[QmlSignal].appendMember((Node*)node);
       
   918                           break;
       
   919                       case Node::QmlMethod:
       
   920                           sections[QmlMethod].appendMember((Node*)node);
       
   921                           break;
       
   922                       default:
       
   923                           break;
       
   924                     }
       
   925                     ++n;
       
   926                 }
       
   927 
       
   928                 /*
       
   929                   First generate the table of contents.
       
   930                  */
       
   931                 writer.writeStartElement("ul");
       
   932                 s = sections.constBegin();
       
   933                 while (s != sections.constEnd()) {
       
   934                     if (!(*s).members.isEmpty()) {
       
   935 
       
   936                         writer.writeStartElement("li");
       
   937                         writer.writeStartElement("xref");
       
   938                         writer.writeAttribute("href",QString("#" + Doc::canonicalTitle((*s).name)));
       
   939                         writer.writeCharacters((*s).name);
       
   940                         writer.writeEndElement(); // </xref>
       
   941                         writer.writeEndElement(); // </li>
       
   942                     }
       
   943                     ++s;
       
   944                 }
       
   945                 writer.writeEndElement(); // </ul>
       
   946 
       
   947                 int idx = 0;
       
   948                 s = sections.constBegin();
       
   949                 while (s != sections.constEnd()) {
       
   950                     if (!(*s).members.isEmpty()) {
       
   951                         writer.writeStartElement("p");
       
   952                         writeGuidAttribute(Doc::canonicalTitle((*s).name));
       
   953                         writer.writeAttribute("outputclass","h3");
       
   954                         writer.writeCharacters(protectEnc((*s).name));
       
   955                         writer.writeEndElement(); // </p>
       
   956                         if (idx == Class)
       
   957                             generateCompactList(0, marker, ncmap.value(), false, QString("Q"));
       
   958                         else if (idx == QmlClass)
       
   959                             generateCompactList(0, marker, nqcmap.value(), false, QString("Q"));
       
   960                         else if (idx == MemberFunction) {
       
   961                             ParentMaps parentmaps;
       
   962                             ParentMaps::iterator pmap;
       
   963                             NodeList::const_iterator i = s->members.constBegin();
       
   964                             while (i != s->members.constEnd()) {
       
   965                                 Node* p = (*i)->parent();
       
   966                                 pmap = parentmaps.find(p);
       
   967                                 if (pmap == parentmaps.end())
       
   968                                     pmap = parentmaps.insert(p,NodeMultiMap());
       
   969                                 pmap->insert((*i)->name(),(*i));
       
   970                                 ++i;
       
   971                             }
       
   972                             pmap = parentmaps.begin();
       
   973                             while (pmap != parentmaps.end()) {
       
   974                                 NodeList nlist = pmap->values();
       
   975                                 writer.writeStartElement("p");
       
   976                                 writer.writeCharacters("Class ");
       
   977                                 writer.writeStartElement("xref");
       
   978                                 writer.writeAttribute("href",linkForNode(pmap.key(), 0));
       
   979                                 QStringList pieces = fullName(pmap.key(), 0, marker).split("::");
       
   980                                 writer.writeCharacters(protectEnc(pieces.last()));
       
   981                                 writer.writeEndElement(); // </xref>
       
   982                                 writer.writeCharacters(":");
       
   983                                 writer.writeEndElement(); // </p>
       
   984 
       
   985                                 generateSection(nlist, 0, marker, CodeMarker::Summary);
       
   986                                 writer.writeEmptyElement("br");
       
   987                                 ++pmap;
       
   988                             }
       
   989                         }
       
   990                         else
       
   991                             generateSection(s->members, 0, marker, CodeMarker::Summary);
       
   992                      }
       
   993                     ++idx;
       
   994                     ++s;
       
   995                 }
       
   996             }
       
   997         }
       
   998         break;
       
   999     case Atom::Image:
       
  1000     case Atom::InlineImage:
       
  1001         {
       
  1002             QString fileName = imageFileName(relative, atom->string());
       
  1003             QString text;
       
  1004             if (atom->next() != 0)
       
  1005                 text = atom->next()->string();
       
  1006             if (atom->type() == Atom::Image) {
       
  1007                 writer.writeStartElement("p");
       
  1008                 writer.writeAttribute("outputclass","centerAlign");
       
  1009             }
       
  1010             if (fileName.isEmpty()) {
       
  1011                 writer.writeStartElement("font");
       
  1012                 writer.writeAttribute("color","red");
       
  1013                 writer.writeCharacters("[Missing image: ");
       
  1014                 writer.writeCharacters(protectEnc(atom->string()));
       
  1015                 writer.writeEndElement(); // </font>
       
  1016             }
       
  1017             else {
       
  1018                 writer.writeStartElement("img");
       
  1019                 writer.writeAttribute("src",protectEnc(fileName));
       
  1020                 if (!text.isEmpty())
       
  1021                     writer.writeAttribute("alt",protectEnc(text));
       
  1022                 writer.writeEndElement(); // </img>
       
  1023             }
       
  1024             if (atom->type() == Atom::Image)
       
  1025                 writer.writeEndElement(); // </p>
       
  1026         }
       
  1027         break;
       
  1028     case Atom::ImageText:
       
  1029         // nothing
       
  1030         break;
       
  1031     case Atom::LegaleseLeft:
       
  1032         writer.writeStartElement("p");
       
  1033         writer.writeAttribute("outputclass","legalese");
       
  1034         break;
       
  1035     case Atom::LegaleseRight:
       
  1036         writer.writeEndElement(); // </p>
       
  1037         break;
       
  1038     case Atom::LineBreak:
       
  1039         writer.writeEmptyElement("br");
       
  1040         break;
       
  1041     case Atom::Link:
       
  1042         {
       
  1043             const Node *node = 0;
       
  1044             QString myLink = getLink(atom, relative, marker, &node);
       
  1045             if (myLink.isEmpty()) {
       
  1046                 relative->doc().location().warning(tr("Cannot link to '%1' in %2")
       
  1047                         .arg(atom->string())
       
  1048                         .arg(marker->plainFullName(relative)));
       
  1049             }
       
  1050             beginLink(myLink, node, relative, marker);
       
  1051             skipAhead = 1;
       
  1052         }
       
  1053         break;
       
  1054     case Atom::LinkNode:
       
  1055         {
       
  1056             const Node *node = CodeMarker::nodeForString(atom->string());
       
  1057             beginLink(linkForNode(node, relative), node, relative, marker);
       
  1058             skipAhead = 1;
       
  1059         }
       
  1060         break;
       
  1061     case Atom::ListLeft:
       
  1062         if (in_para) {
       
  1063             writer.writeEndElement(); // </p>
       
  1064             in_para = false;
       
  1065         }
       
  1066         if (atom->string() == ATOM_LIST_BULLET) {
       
  1067             writer.writeStartElement("ul");
       
  1068         }
       
  1069         else if (atom->string() == ATOM_LIST_TAG) {
       
  1070             writer.writeStartElement("dl");
       
  1071         }
       
  1072         else if (atom->string() == ATOM_LIST_VALUE) {
       
  1073             threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
       
  1074             if (threeColumnEnumValueTable) {
       
  1075                 writer.writeStartElement("table");
       
  1076                 writer.writeAttribute("outputclass","valuelist");
       
  1077                 writer.writeStartElement("tr");
       
  1078                 if (++numTableRows % 2 == 1)
       
  1079                     writer.writeAttribute("outputclass","odd");
       
  1080                 else
       
  1081                     writer.writeAttribute("outputclass","even");
       
  1082                 writer.writeStartElement("th");
       
  1083                 writer.writeCharacters("Constant");
       
  1084                 writer.writeEndElement(); // </th>
       
  1085                 writer.writeStartElement("th");
       
  1086                 writer.writeCharacters("Value");
       
  1087                 writer.writeEndElement(); // </th>
       
  1088                 writer.writeStartElement("th");
       
  1089                 writer.writeCharacters("Description");
       
  1090                 writer.writeEndElement(); // </th>
       
  1091                 writer.writeEndElement(); // </tr>
       
  1092             }
       
  1093             else {
       
  1094                 writer.writeStartElement("table");
       
  1095                 writer.writeAttribute("outputclass","valuelist");
       
  1096                 writer.writeStartElement("tr");
       
  1097                 writer.writeStartElement("th");
       
  1098                 writer.writeCharacters("Constant");
       
  1099                 writer.writeEndElement(); // </th>
       
  1100                 writer.writeStartElement("th");
       
  1101                 writer.writeCharacters("Value");
       
  1102                 writer.writeEndElement(); // </th>
       
  1103                 writer.writeEndElement(); // </tr>
       
  1104             }
       
  1105         }
       
  1106         else {
       
  1107             writer.writeStartElement("ol");
       
  1108             if (atom->string() == ATOM_LIST_UPPERALPHA)
       
  1109                 writer.writeAttribute("type","A");
       
  1110             else if (atom->string() == ATOM_LIST_LOWERALPHA)
       
  1111                 writer.writeAttribute("type","a");
       
  1112             else if (atom->string() == ATOM_LIST_UPPERROMAN)
       
  1113                 writer.writeAttribute("type","I");
       
  1114             else if (atom->string() == ATOM_LIST_LOWERROMAN)
       
  1115                 writer.writeAttribute("type","i");
       
  1116             else // (atom->string() == ATOM_LIST_NUMERIC)
       
  1117                 writer.writeAttribute("type","1");
       
  1118             if (atom->next() != 0 && atom->next()->string().toInt() != 1)
       
  1119                 writer.writeAttribute("start",atom->next()->string());
       
  1120         }
       
  1121         break;
       
  1122     case Atom::ListItemNumber:
       
  1123         // nothing
       
  1124         break;
       
  1125     case Atom::ListTagLeft:
       
  1126         if (atom->string() == ATOM_LIST_TAG) {
       
  1127             writer.writeStartElement("dt");
       
  1128         }
       
  1129         else { // (atom->string() == ATOM_LIST_VALUE)
       
  1130             writer.writeStartElement("tr");
       
  1131             writer.writeStartElement("td");
       
  1132             writer.writeAttribute("outputclass","topAlign");
       
  1133             writer.writeStartElement("tt");
       
  1134             writer.writeCharacters(protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(),
       
  1135                                                                                   relative))));
       
  1136             writer.writeEndElement(); // </tt>
       
  1137             writer.writeEndElement(); // </td>
       
  1138             writer.writeStartElement("td");
       
  1139             writer.writeAttribute("outputclass","topAlign");
       
  1140 
       
  1141             QString itemValue;
       
  1142             if (relative->type() == Node::Enum) {
       
  1143                 const EnumNode *enume = static_cast<const EnumNode *>(relative);
       
  1144                 itemValue = enume->itemValue(atom->next()->string());
       
  1145             }
       
  1146 
       
  1147             if (itemValue.isEmpty())
       
  1148                 writer.writeCharacters("?");
       
  1149             else {
       
  1150                 writer.writeStartElement("tt");
       
  1151                 writer.writeCharacters(protectEnc(itemValue));
       
  1152                 writer.writeEndElement(); // </tt>
       
  1153             }
       
  1154             skipAhead = 1;
       
  1155         }
       
  1156         break;
       
  1157     case Atom::ListTagRight:
       
  1158         if (atom->string() == ATOM_LIST_TAG)
       
  1159             writer.writeEndElement(); // </dt>
       
  1160         break;
       
  1161     case Atom::ListItemLeft:
       
  1162         if (atom->string() == ATOM_LIST_TAG) {
       
  1163             writer.writeStartElement("dd");
       
  1164         }
       
  1165         else if (atom->string() == ATOM_LIST_VALUE) {
       
  1166             if (threeColumnEnumValueTable) {
       
  1167                 writer.writeEndElement(); // </td>
       
  1168                 writer.writeStartElement("td");
       
  1169                 writer.writeAttribute("outputclass","topAlign");
       
  1170                 if (matchAhead(atom, Atom::ListItemRight))
       
  1171                     writer.writeCharacters("&nbsp;");
       
  1172             }
       
  1173         }
       
  1174         else {
       
  1175             writer.writeStartElement("li");
       
  1176         }
       
  1177         if (matchAhead(atom, Atom::ParaLeft))
       
  1178             skipAhead = 1;
       
  1179         break;
       
  1180     case Atom::ListItemRight:
       
  1181         if (atom->string() == ATOM_LIST_TAG) {
       
  1182             writer.writeEndElement(); // </dd>
       
  1183         }
       
  1184         else if (atom->string() == ATOM_LIST_VALUE) {
       
  1185             writer.writeEndElement(); // </td>
       
  1186             writer.writeEndElement(); // </tr>
       
  1187         }
       
  1188         else {
       
  1189             writer.writeEndElement(); // </li>
       
  1190         }
       
  1191         break;
       
  1192     case Atom::ListRight:
       
  1193         if (atom->string() == ATOM_LIST_BULLET) {
       
  1194             writer.writeEndElement(); // </ul>
       
  1195         }
       
  1196         else if (atom->string() == ATOM_LIST_TAG) {
       
  1197             writer.writeEndElement(); // </dl>
       
  1198         }
       
  1199         else if (atom->string() == ATOM_LIST_VALUE) {
       
  1200             writer.writeEndElement(); // </table>
       
  1201         }
       
  1202         else {
       
  1203             writer.writeEndElement(); // </ol>
       
  1204         }
       
  1205         break;
       
  1206     case Atom::Nop:
       
  1207         // nothing
       
  1208         break;
       
  1209     case Atom::ParaLeft:
       
  1210         writer.writeStartElement("p");
       
  1211         in_para = true;
       
  1212         break;
       
  1213     case Atom::ParaRight:
       
  1214         endLink();
       
  1215         if (in_para) {
       
  1216             writer.writeEndElement(); // </p?
       
  1217             in_para = false;
       
  1218         }
       
  1219         break;
       
  1220     case Atom::QuotationLeft:
       
  1221         writer.writeStartElement("blockquote");
       
  1222         break;
       
  1223     case Atom::QuotationRight:
       
  1224         writer.writeEndElement(); // </blockquote>
       
  1225         break;
       
  1226     case Atom::RawString:
       
  1227         writer.writeCharacters(atom->string());
       
  1228         break;
       
  1229     case Atom::SectionLeft:
       
  1230         writer.writeStartElement("p");
       
  1231         writeGuidAttribute(Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
       
  1232         writer.writeAttribute("outputclass","target");
       
  1233         writer.writeCharacters(protectEnc(Text::sectionHeading(atom).toString()));
       
  1234         writer.writeEndElement(); // </p>
       
  1235         break;
       
  1236     case Atom::SectionRight:
       
  1237         // nothing
       
  1238         break;
       
  1239     case Atom::SectionHeadingLeft:
       
  1240         writer.writeStartElement("p");
       
  1241         hx = "h" + QString::number(atom->string().toInt() + hOffset(relative));
       
  1242         writer.writeAttribute("outputclass",hx);
       
  1243         inSectionHeading = true;
       
  1244         break;
       
  1245     case Atom::SectionHeadingRight:
       
  1246         writer.writeEndElement(); // </p> (see case Atom::SectionHeadingLeft)
       
  1247         inSectionHeading = false;
       
  1248         break;
       
  1249     case Atom::SidebarLeft:
       
  1250         // nothing
       
  1251         break;
       
  1252     case Atom::SidebarRight:
       
  1253         // nothing
       
  1254         break;
       
  1255     case Atom::String:
       
  1256         if (inLink && !inContents && !inSectionHeading) {
       
  1257             generateLink(atom, relative, marker);
       
  1258         }
       
  1259         else {
       
  1260             writer.writeCharacters(protectEnc(atom->string()));
       
  1261         }
       
  1262         break;
       
  1263     case Atom::TableLeft:
       
  1264         if (in_para) {
       
  1265             writer.writeEndElement(); // </p>
       
  1266             in_para = false;
       
  1267         }
       
  1268         writer.writeStartElement("table");
       
  1269         writer.writeAttribute("outputclass","generic");
       
  1270         numTableRows = 0;
       
  1271         break;
       
  1272     case Atom::TableRight:
       
  1273         writer.writeEndElement(); // </table>
       
  1274         break;
       
  1275     case Atom::TableHeaderLeft:
       
  1276         writer.writeStartElement("thead");
       
  1277         writer.writeStartElement("tr");
       
  1278         writer.writeAttribute("outputclass","qt-style topAlign");
       
  1279         inTableHeader = true;
       
  1280         break;
       
  1281     case Atom::TableHeaderRight:
       
  1282         writer.writeEndElement(); // </tr>
       
  1283         if (matchAhead(atom, Atom::TableHeaderLeft)) {
       
  1284             skipAhead = 1;
       
  1285             writer.writeStartElement("tr");
       
  1286             writer.writeAttribute("outputclass","qt-style topAlign");
       
  1287         }
       
  1288         else { 
       
  1289             writer.writeEndElement(); // </thead>
       
  1290             inTableHeader = false;
       
  1291         }
       
  1292         break;
       
  1293     case Atom::TableRowLeft:
       
  1294         writer.writeStartElement("tr");
       
  1295         if (++numTableRows % 2 == 1)
       
  1296             writer.writeAttribute("outputclass","odd topAlign");
       
  1297         else
       
  1298             writer.writeAttribute("outputclass","even topAlign");
       
  1299         break;
       
  1300     case Atom::TableRowRight:
       
  1301         writer.writeEndElement(); // </tr>\n";
       
  1302         break;
       
  1303     case Atom::TableItemLeft:
       
  1304         {
       
  1305             if (inTableHeader)
       
  1306                 writer.writeStartElement("th");
       
  1307             else
       
  1308                 writer.writeStartElement("td");
       
  1309 
       
  1310             QStringList spans = atom->string().split(",");
       
  1311             if (spans.size() == 2) {
       
  1312 #if zzz        
       
  1313                 
       
  1314                 if (spans.at(0) != "1")
       
  1315                     out() << " colspan=\"" << spans.at(0) << "\"";
       
  1316                 if (spans.at(1) != "1")
       
  1317                     out() << " rowspan=\"" << spans.at(1) << "\"";
       
  1318 #endif                
       
  1319                 if (!inTableHeader)
       
  1320                     writer.writeStartElement("p"); 
       
  1321             }
       
  1322             if (matchAhead(atom, Atom::ParaLeft))
       
  1323                 skipAhead = 1;
       
  1324         }
       
  1325         break;
       
  1326     case Atom::TableItemRight:
       
  1327         if (inTableHeader)
       
  1328             writer.writeEndElement(); // </th>
       
  1329         else {
       
  1330             writer.writeEndElement(); // </p>
       
  1331             writer.writeEndElement(); // </td>
       
  1332         }
       
  1333         if (matchAhead(atom, Atom::ParaLeft))
       
  1334             skipAhead = 1;
       
  1335         break;
       
  1336     case Atom::TableOfContents:
       
  1337         {
       
  1338             int numColumns = 1;
       
  1339             const Node *node = relative;
       
  1340 
       
  1341             Doc::SectioningUnit sectioningUnit = Doc::Section4;
       
  1342             QStringList params = atom->string().split(",");
       
  1343             QString columnText = params.at(0);
       
  1344             QStringList pieces = columnText.split(" ", QString::SkipEmptyParts);
       
  1345             if (pieces.size() >= 2) {
       
  1346                 columnText = pieces.at(0);
       
  1347                 pieces.pop_front();
       
  1348                 QString path = pieces.join(" ").trimmed();
       
  1349                 node = findNodeForTarget(path, relative, marker, atom);
       
  1350             }
       
  1351 
       
  1352             if (params.size() == 2) {
       
  1353                 numColumns = qMax(columnText.toInt(), numColumns);
       
  1354                 sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt();
       
  1355             }
       
  1356 
       
  1357             if (node)
       
  1358                 generateTableOfContents(node,
       
  1359                                         marker,
       
  1360                                         sectioningUnit,
       
  1361                                         numColumns,
       
  1362                                         relative);
       
  1363         }
       
  1364         break;
       
  1365     case Atom::Target:
       
  1366         writer.writeStartElement("p");
       
  1367         writeGuidAttribute(Doc::canonicalTitle(atom->string()));
       
  1368         writer.writeAttribute("outputclass","target");
       
  1369         writer.writeCharacters(protectEnc(atom->string()));
       
  1370         writer.writeEndElement(); // </p>
       
  1371         break;
       
  1372     case Atom::UnhandledFormat:
       
  1373         writer.writeStartElement("b");
       
  1374         writer.writeAttribute("outputclass","redFont");
       
  1375         writer.writeCharacters("&lt;Missing DITAXML&gt");
       
  1376         writer.writeEndElement(); // </b>
       
  1377         break;
       
  1378     case Atom::UnknownCommand:
       
  1379         writer.writeStartElement("b");
       
  1380         writer.writeAttribute("outputclass","redFont code");
       
  1381         writer.writeCharacters(protectEnc(atom->string()));
       
  1382         writer.writeEndElement(); // </b>
       
  1383         break;
       
  1384 #ifdef QDOC_QML
       
  1385     case Atom::QmlText:
       
  1386     case Atom::EndQmlText:
       
  1387         // don't do anything with these. They are just tags.
       
  1388         break;
       
  1389 #endif
       
  1390     default:
       
  1391         //        unknownAtom(atom);
       
  1392         break;
       
  1393     }
       
  1394     return skipAhead;
       
  1395 }
       
  1396 
       
  1397 /*!
       
  1398   Generate a reference page for a C++ class.
       
  1399  */
       
  1400 void
       
  1401 DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* marker)
       
  1402 {
       
  1403     QList<Section> sections;
       
  1404     QList<Section>::ConstIterator s;
       
  1405 
       
  1406     const ClassNode* cn = 0;
       
  1407     const NamespaceNode* namespasse = 0;
       
  1408 
       
  1409     QString title;
       
  1410     QString rawTitle;
       
  1411     QString fullTitle;
       
  1412     if (inner->type() == Node::Namespace) {
       
  1413         namespasse = const_cast<NamespaceNode*>(static_cast<const NamespaceNode*>(inner));
       
  1414         rawTitle = marker->plainName(inner);
       
  1415         fullTitle = marker->plainFullName(inner);
       
  1416         title = rawTitle + " Namespace";
       
  1417     }
       
  1418     else if (inner->type() == Node::Class) {
       
  1419         cn = const_cast<ClassNode*>(static_cast<const ClassNode*>(inner));
       
  1420         rawTitle = marker->plainName(inner);
       
  1421         fullTitle = marker->plainFullName(inner);
       
  1422         title = rawTitle + " Class Reference";
       
  1423 
       
  1424         generateHeader(inner);
       
  1425 
       
  1426         writer.writeStartElement(CXXCLASS);
       
  1427         writer.writeAttribute("id",cn->guid());
       
  1428         writer.writeStartElement(APINAME);
       
  1429         writer.writeCharacters(fullTitle);
       
  1430         writer.writeEndElement(); // </apiName>
       
  1431 
       
  1432         generateBrief(inner, marker);
       
  1433     
       
  1434         writer.writeStartElement(CXXCLASSDETAIL);
       
  1435         writer.writeStartElement(CXXCLASSDEFINITION);
       
  1436         writer.writeStartElement(CXXCLASSACCESSSPECIFIER);
       
  1437         writer.writeAttribute("value",inner->accessString());
       
  1438         writer.writeEndElement(); // <cxxClassAccessSpecifier>
       
  1439         if (cn->isAbstract()) {
       
  1440             writer.writeStartElement(CXXCLASSABSTRACT);
       
  1441             writer.writeAttribute("name","abstract");
       
  1442             writer.writeAttribute("value","abstract");
       
  1443             writer.writeEndElement(); // </cxxClassAbstract>
       
  1444         }
       
  1445         writeDerivations(cn, marker);
       
  1446         writeLocation(cn);
       
  1447         writer.writeEndElement(); // <cxxClassDefinition>
       
  1448         writer.writeStartElement(APIDESC);
       
  1449 
       
  1450         if (!inner->doc().isEmpty()) {
       
  1451             writer.writeStartElement("p");
       
  1452             writer.writeAttribute("outputclass","h2");
       
  1453             writer.writeCharacters("Detailed Description");
       
  1454             writer.writeEndElement(); // </p>
       
  1455             generateBody(inner, marker);
       
  1456             //        generateAlsoList(inner, marker);
       
  1457         }
       
  1458     
       
  1459         writer.writeEndElement(); // </apiDesc>
       
  1460         writer.writeEndElement(); // </cxxClassDetail>
       
  1461 
       
  1462         sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
       
  1463         s = sections.begin();
       
  1464         while (s != sections.end()) {
       
  1465             if ((*s).name == "Member Function Documentation") {
       
  1466                 writeFunctions((*s),cn,marker);
       
  1467             }
       
  1468             else if ((*s).name == "Member Type Documentation") {
       
  1469                 writeEnumerations((*s),cn,marker);
       
  1470                 writeTypedefs((*s),cn,marker);
       
  1471             }
       
  1472             else if ((*s).name == "Member Variable Documentation") {
       
  1473                 writeDataMembers((*s),cn,marker);
       
  1474             }
       
  1475             else if ((*s).name == "Property Documentation") {
       
  1476                 writeProperties((*s),cn,marker);
       
  1477             }
       
  1478             else if ((*s).name == "Macro Documentation") {
       
  1479                 writeMacros((*s),cn,marker);
       
  1480             }
       
  1481             ++s;
       
  1482         }
       
  1483         writer.writeEndElement(); // </cxxClass>
       
  1484     }
       
  1485 
       
  1486 #ifdef WRITE_HTML    
       
  1487     Text subtitleText;
       
  1488     if (rawTitle != fullTitle)
       
  1489         subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")"
       
  1490                      << Atom(Atom::LineBreak);
       
  1491 
       
  1492     QString shortVersion;
       
  1493     shortVersion = project + " " + shortVersion + ": ";
       
  1494     shortVersion = myTree->version();
       
  1495     if (shortVersion.count(QChar('.')) == 2)
       
  1496         shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
       
  1497     if (!shortVersion.isEmpty()) {
       
  1498         if (project == "QSA")
       
  1499             shortVersion = "QSA " + shortVersion + ": ";
       
  1500         else
       
  1501             shortVersion = "Qt " + shortVersion + ": ";
       
  1502     }
       
  1503 
       
  1504     out() << "  <title>" << shortVersion << protectEnc(title) << "</title>\n";
       
  1505 
       
  1506 #if 0    
       
  1507     out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
       
  1508     generateBreadCrumbs(title,node,marker);
       
  1509     out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
       
  1510 #endif    
       
  1511     
       
  1512     sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
       
  1513     generateTableOfContents(inner,marker,&sections);
       
  1514     generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
       
  1515 
       
  1516 #ifdef QDOC_QML
       
  1517     if (cn && !cn->qmlElement().isEmpty()) {
       
  1518         generateInstantiatedBy(cn,marker);
       
  1519     }
       
  1520 #endif
       
  1521     
       
  1522     generateBrief(inner, marker);
       
  1523     generateIncludes(inner, marker);
       
  1524     generateStatus(inner, marker);
       
  1525     if (cn) {
       
  1526         generateInherits(cn, marker);
       
  1527         generateInheritedBy(cn, marker);
       
  1528     }
       
  1529     generateThreadSafeness(inner, marker);
       
  1530     generateSince(inner, marker);
       
  1531 
       
  1532     out() << "<ul>\n";
       
  1533 
       
  1534     QString membersLink = generateListOfAllMemberFile(inner, marker);
       
  1535     if (!membersLink.isEmpty())
       
  1536         out() << "<li><xref href=\"" << membersLink << "\">"
       
  1537               << "List of all members, including inherited members</xref></li>\n";
       
  1538 
       
  1539     QString obsoleteLink = generateLowStatusMemberFile(inner,
       
  1540                                                        marker,
       
  1541                                                        CodeMarker::Obsolete);
       
  1542     if (!obsoleteLink.isEmpty())
       
  1543         out() << "<li><xref href=\"" << obsoleteLink << "\">"
       
  1544               << "Obsolete members</xref></li>\n";
       
  1545 
       
  1546     QString compatLink = generateLowStatusMemberFile(inner,
       
  1547                                                      marker,
       
  1548                                                      CodeMarker::Compat);
       
  1549     if (!compatLink.isEmpty())
       
  1550         out() << "<li><xref href=\"" << compatLink << "\">"
       
  1551               << "Qt 3 support members</xref></li>\n";
       
  1552 
       
  1553     out() << "</ul>\n";
       
  1554 
       
  1555     bool needOtherSection = false;
       
  1556 
       
  1557     /*
       
  1558       sections is built above for the call to generateTableOfContents().
       
  1559      */
       
  1560     s = sections.begin();
       
  1561     while (s != sections.end()) {
       
  1562         if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
       
  1563             if (!s->inherited.isEmpty())
       
  1564                 needOtherSection = true;
       
  1565         }
       
  1566         else {
       
  1567             if (!s->members.isEmpty()) {
       
  1568                 out() << "<hr />\n";
       
  1569                 out() << "<a name=\""
       
  1570                       << registerRef((*s).name.toLower())
       
  1571                       << "\"></a>\n";
       
  1572                 out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
       
  1573                 generateSection(s->members, inner, marker, CodeMarker::Summary);
       
  1574             }
       
  1575             if (!s->reimpMembers.isEmpty()) {
       
  1576                 QString name = QString("Reimplemented ") + (*s).name;
       
  1577                 out() << "<hr />\n";
       
  1578                 out() << "<a name=\""
       
  1579                       << registerRef(name.toLower())
       
  1580                       << "\"></a>\n";
       
  1581                 out() << "<h2>" << protectEnc(name) << "</h2>\n";
       
  1582                 generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
       
  1583             }
       
  1584 
       
  1585             if (!s->inherited.isEmpty()) {
       
  1586                 out() << "<ul>\n";
       
  1587                 generateSectionInheritedList(*s, inner, marker, true);
       
  1588                 out() << "</ul>\n";
       
  1589             }
       
  1590         }
       
  1591         ++s;
       
  1592     }
       
  1593 
       
  1594     if (needOtherSection) {
       
  1595         out() << "<h3>Additional Inherited Members</h3>\n"
       
  1596                  "<ul>\n";
       
  1597 
       
  1598         s = sections.begin();
       
  1599         while (s != sections.end()) {
       
  1600             if (s->members.isEmpty() && !s->inherited.isEmpty())
       
  1601                 generateSectionInheritedList(*s, inner, marker);
       
  1602             ++s;
       
  1603         }
       
  1604         out() << "</ul>\n";
       
  1605     }
       
  1606 
       
  1607     out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
       
  1608 
       
  1609     if (!inner->doc().isEmpty()) {
       
  1610         out() << "<hr />\n"
       
  1611               << "<div class=\"descr\"/>\n" // QTBUG-9504
       
  1612               << "<h2>" << "Detailed Description" << "</h2>\n";
       
  1613         generateBody(inner, marker);
       
  1614         out() << "</div>\n"; // QTBUG-9504
       
  1615         generateAlsoList(inner, marker);
       
  1616     }
       
  1617 
       
  1618     sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
       
  1619     s = sections.begin();
       
  1620     while (s != sections.end()) {
       
  1621         out() << "<hr />\n";
       
  1622         if (!(*s).divClass.isEmpty())
       
  1623             out() << "<div class=\"" << (*s).divClass << "\"/>\n"; // QTBUG-9504
       
  1624         out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
       
  1625 
       
  1626         NodeList::ConstIterator m = (*s).members.begin();
       
  1627         while (m != (*s).members.end()) {
       
  1628             if ((*m)->access() != Node::Private) { // ### check necessary?
       
  1629                 if ((*m)->type() != Node::Class)
       
  1630                     generateDetailedMember(*m, inner, marker);
       
  1631                 else {
       
  1632                     out() << "<h3> class ";
       
  1633                     generateFullName(*m, inner, marker);
       
  1634                     out() << "</h3>";
       
  1635                     generateBrief(*m, marker, inner);
       
  1636                 }
       
  1637 
       
  1638                 QStringList names;
       
  1639                 names << (*m)->name();
       
  1640                 if ((*m)->type() == Node::Function) {
       
  1641                     const FunctionNode *func = reinterpret_cast<const FunctionNode *>(*m);
       
  1642                     if (func->metaness() == FunctionNode::Ctor ||
       
  1643                         func->metaness() == FunctionNode::Dtor ||
       
  1644                         func->overloadNumber() != 1)
       
  1645                         names.clear();
       
  1646                 }
       
  1647                 else if ((*m)->type() == Node::Property) {
       
  1648                     const PropertyNode *prop = reinterpret_cast<const PropertyNode *>(*m);
       
  1649                     if (!prop->getters().isEmpty() &&
       
  1650                         !names.contains(prop->getters().first()->name()))
       
  1651                         names << prop->getters().first()->name();
       
  1652                     if (!prop->setters().isEmpty())
       
  1653                         names << prop->setters().first()->name();
       
  1654                     if (!prop->resetters().isEmpty())
       
  1655                         names << prop->resetters().first()->name();
       
  1656                 }
       
  1657                 else if ((*m)->type() == Node::Enum) {
       
  1658                     const EnumNode *enume = reinterpret_cast<const EnumNode*>(*m);
       
  1659                     if (enume->flagsType())
       
  1660                         names << enume->flagsType()->name();
       
  1661 
       
  1662                     foreach (const QString &enumName,
       
  1663                              enume->doc().enumItemNames().toSet() -
       
  1664                              enume->doc().omitEnumItemNames().toSet())
       
  1665                         names << plainCode(marker->markedUpEnumValue(enumName,
       
  1666                                                                      enume));
       
  1667                 }
       
  1668             }
       
  1669             ++m;
       
  1670         }
       
  1671         if (!(*s).divClass.isEmpty())
       
  1672             out() << "</div>\n"; // QTBUG-9504
       
  1673         ++s;
       
  1674     }
       
  1675 #endif
       
  1676 }
       
  1677 
       
  1678 /*!
       
  1679   Generate the html page for a qdoc file that doesn't map
       
  1680   to an underlying c++ file.
       
  1681  */
       
  1682 void DitaXmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
       
  1683 {
       
  1684     return; // zzz
       
  1685     
       
  1686     SubTitleSize subTitleSize = LargeSubTitle;
       
  1687     QList<Section> sections;
       
  1688     QList<Section>::const_iterator s;
       
  1689     QString fullTitle = fake->fullTitle();
       
  1690     QString htmlTitle = fullTitle;
       
  1691 
       
  1692     if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) {
       
  1693         subTitleSize = SmallSubTitle;
       
  1694         htmlTitle += " (" + fake->subTitle() + ")";
       
  1695     }
       
  1696     else if (fake->subType() == Node::QmlBasicType) {
       
  1697         fullTitle = "QML Basic Type: " + fullTitle;
       
  1698         htmlTitle = fullTitle;
       
  1699     }
       
  1700 
       
  1701     generateHeader(fake);
       
  1702         
       
  1703     /*
       
  1704       Generate the TOC for the new doc format.
       
  1705       Don't generate a TOC for the home page.
       
  1706     */
       
  1707     if (fake->name() != QString("index.html"))
       
  1708         generateTableOfContents(fake,marker,0);
       
  1709 
       
  1710     generateTitle(fullTitle,
       
  1711                   Text() << fake->subTitle(),
       
  1712                   subTitleSize,
       
  1713                   fake,
       
  1714                   marker);
       
  1715 
       
  1716     if (fake->subType() == Node::Module) {
       
  1717         // Generate brief text and status for modules.
       
  1718         generateBrief(fake, marker);
       
  1719         generateStatus(fake, marker);
       
  1720 
       
  1721         if (moduleNamespaceMap.contains(fake->name())) {
       
  1722             out() << "<a name=\"" << registerRef("namespaces") << "\"></a>\n";
       
  1723             out() << "<h2>Namespaces</h2>\n";
       
  1724             generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]);
       
  1725         }
       
  1726         if (moduleClassMap.contains(fake->name())) {
       
  1727             out() << "<a name=\"" << registerRef("classes") << "\"></a>\n";
       
  1728             out() << "<h2>Classes</h2>\n";
       
  1729             generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
       
  1730         }
       
  1731     }
       
  1732     else if (fake->subType() == Node::HeaderFile) {
       
  1733         // Generate brief text and status for modules.
       
  1734         generateBrief(fake, marker);
       
  1735         generateStatus(fake, marker);
       
  1736 
       
  1737         out() << "<ul>\n";
       
  1738 
       
  1739         QString membersLink = generateListOfAllMemberFile(fake, marker);
       
  1740         if (!membersLink.isEmpty())
       
  1741             out() << "<li><xref href=\"" << membersLink << "\">"
       
  1742                   << "List of all members, including inherited members</xref></li>\n";
       
  1743 
       
  1744         QString obsoleteLink = generateLowStatusMemberFile(fake,
       
  1745                                                            marker,
       
  1746                                                            CodeMarker::Obsolete);
       
  1747         if (!obsoleteLink.isEmpty())
       
  1748             out() << "<li><xref href=\"" << obsoleteLink << "\">"
       
  1749                   << "Obsolete members</xref></li>\n";
       
  1750 
       
  1751         QString compatLink = generateLowStatusMemberFile(fake,
       
  1752                                                          marker,
       
  1753                                                          CodeMarker::Compat);
       
  1754         if (!compatLink.isEmpty())
       
  1755             out() << "<li><xref href=\"" << compatLink << "\">"
       
  1756                   << "Qt 3 support members</xref></li>\n";
       
  1757 
       
  1758         out() << "</ul>\n";
       
  1759     }
       
  1760 #ifdef QDOC_QML
       
  1761     else if (fake->subType() == Node::QmlClass) {
       
  1762         const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake);
       
  1763         const ClassNode* cn = qml_cn->classNode();
       
  1764         generateQmlInherits(qml_cn, marker);
       
  1765         generateQmlInstantiates(qml_cn, marker);
       
  1766         generateBrief(qml_cn, marker);
       
  1767         generateQmlInheritedBy(qml_cn, marker);
       
  1768         sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
       
  1769         s = sections.begin();
       
  1770         while (s != sections.end()) {
       
  1771             out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
       
  1772             out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
       
  1773             generateQmlSummary(*s,fake,marker);
       
  1774             ++s;
       
  1775         }
       
  1776 
       
  1777         out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
       
  1778         out() << "<h2>" << "Detailed Description" << "</h2>\n";
       
  1779         generateBody(fake, marker);
       
  1780         if (cn)
       
  1781             generateQmlText(cn->doc().body(), cn, marker, fake->name());
       
  1782         generateAlsoList(fake, marker);
       
  1783         out() << "<hr />\n";
       
  1784 
       
  1785         sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
       
  1786         s = sections.begin();
       
  1787         while (s != sections.end()) {
       
  1788             out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
       
  1789             NodeList::ConstIterator m = (*s).members.begin();
       
  1790             while (m != (*s).members.end()) {
       
  1791                 generateDetailedQmlMember(*m, fake, marker);
       
  1792                 out() << "<br/>\n";
       
  1793                 ++m;
       
  1794             }
       
  1795             ++s;
       
  1796         }
       
  1797         return;
       
  1798     }
       
  1799 #endif
       
  1800     
       
  1801     sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay);
       
  1802     s = sections.begin();
       
  1803     while (s != sections.end()) {
       
  1804         out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
       
  1805         out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
       
  1806         generateSectionList(*s, fake, marker, CodeMarker::Summary);
       
  1807         ++s;
       
  1808     }
       
  1809 
       
  1810     Text brief = fake->doc().briefText();
       
  1811     if (fake->subType() == Node::Module && !brief.isEmpty()) {
       
  1812         out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
       
  1813         out() << "<div class=\"descr\"/>\n"; // QTBUG-9504
       
  1814         out() << "<h2>" << "Detailed Description" << "</h2>\n";
       
  1815     }
       
  1816     else
       
  1817         out() << "<div class=\"descr\"/>\n"; // QTBUG-9504
       
  1818 
       
  1819     generateBody(fake, marker);
       
  1820     out() << "</div>\n"; // QTBUG-9504
       
  1821     generateAlsoList(fake, marker);
       
  1822 
       
  1823     if (!fake->groupMembers().isEmpty()) {
       
  1824         NodeMap groupMembersMap;
       
  1825         foreach (const Node *node, fake->groupMembers()) {
       
  1826             if (node->type() == Node::Class || node->type() == Node::Namespace)
       
  1827                 groupMembersMap[node->name()] = node;
       
  1828         }
       
  1829         generateAnnotatedList(fake, marker, groupMembersMap);
       
  1830     }
       
  1831 
       
  1832     sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay);
       
  1833     s = sections.begin();
       
  1834     while (s != sections.end()) {
       
  1835         out() << "<hr />\n";
       
  1836         out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
       
  1837 
       
  1838         NodeList::ConstIterator m = (*s).members.begin();
       
  1839         while (m != (*s).members.end()) {
       
  1840             generateDetailedMember(*m, fake, marker);
       
  1841             ++m;
       
  1842         }
       
  1843         ++s;
       
  1844     }
       
  1845 }
       
  1846 
       
  1847 /*!
       
  1848   Returns "xml" for this subclass of Generator.
       
  1849  */
       
  1850 QString DitaXmlGenerator::fileExtension(const Node * /* node */) const
       
  1851 {
       
  1852     return "xml";
       
  1853 }
       
  1854 
       
  1855 /*!
       
  1856   Output breadcrumb list in the html file.
       
  1857  */
       
  1858 void DitaXmlGenerator::generateBreadCrumbs(const QString& title,
       
  1859                                            const Node *node,
       
  1860                                            CodeMarker *marker)
       
  1861 {
       
  1862     Text breadcrumb;
       
  1863     if (node->type() == Node::Class) {
       
  1864         const ClassNode* cn = static_cast<const ClassNode*>(node);
       
  1865         QString name =  node->moduleName();
       
  1866         out() << "              <li><xref href=\"modules.html\">All Modules</xref></li>";
       
  1867         if (!name.isEmpty()) {
       
  1868             out() << "              <li>";
       
  1869             breadcrumb << Atom(Atom::AutoLink,name);
       
  1870             generateText(breadcrumb, node, marker);
       
  1871             out() << "</li>\n";
       
  1872         }
       
  1873         breadcrumb.clear();
       
  1874         if (!cn->name().isEmpty()) {
       
  1875             out() << "              <li>";
       
  1876             breadcrumb << Atom(Atom::AutoLink,cn->name());
       
  1877             generateText(breadcrumb, 0, marker);
       
  1878             out() << "</li>\n";
       
  1879         }
       
  1880     }
       
  1881     else if (node->type() == Node::Fake) {
       
  1882         const FakeNode* fn = static_cast<const FakeNode*>(node);
       
  1883         if (node->subType() == Node::Module) {
       
  1884             out() << "              <li><xref href=\"modules.html\">All Modules</xref></li>";
       
  1885             QString name =  node->name();
       
  1886             if (!name.isEmpty()) {
       
  1887                 out() << "              <li>";
       
  1888                 breadcrumb << Atom(Atom::AutoLink,name);
       
  1889                 generateText(breadcrumb, 0, marker);
       
  1890                 out() << "</li>\n";
       
  1891             }
       
  1892         }
       
  1893         else if (node->subType() == Node::Group) {
       
  1894             if (fn->name() == QString("modules"))
       
  1895                 out() << "              <li><xref href=\"modules.html\">All Modules</xref></li>";
       
  1896             else {
       
  1897                 out() << "              <li><xref href=\"" << fn->name() << "\">" << title
       
  1898                       << "</xref></li>";
       
  1899             }
       
  1900         }
       
  1901         else if (node->subType() == Node::Page) {
       
  1902             if (fn->name() == QString("examples.html")) {
       
  1903                 out() << "              <li><xref href=\"all-examples.html\">Examples</xref></li>";
       
  1904             }
       
  1905             else if (fn->name().startsWith("examples-")) {
       
  1906                 out() << "              <li><xref href=\"all-examples.html\">Examples</xref></li>";
       
  1907                 out() << "              <li><xref href=\"" << fn->name() << "\">" << title
       
  1908                       << "</xref></li>";
       
  1909             }
       
  1910             else if (fn->name() == QString("namespaces.html")) {
       
  1911                 out() << "              <li><xref href=\"namespaces.html\">All Namespaces</xref></li>";
       
  1912             }
       
  1913             else {
       
  1914                 out() << "              <li><xref href=\"" << fn->name() << "\">" << title
       
  1915                       << "</xref></li>";
       
  1916             }
       
  1917         }
       
  1918         else if (node->subType() == Node::QmlClass) {
       
  1919             out() << "              <li><xref href=\"qdeclarativeelements.html\">QML Elements</xref></li>";
       
  1920             out() << "              <li><xref href=\"" << fn->name() << "\">" << title
       
  1921                   << "</xref></li>";
       
  1922         }
       
  1923         else if (node->subType() == Node::Example) {
       
  1924             out() << "              <li><xref href=\"all-examples.html\">Examples</xref></li>";
       
  1925             QStringList sl = fn->name().split('/');
       
  1926             QString name = "examples-" + sl.at(0) + ".html";
       
  1927             QString t = CodeParser::titleFromName(name);
       
  1928             out() << "              <li><xref href=\"" << name << "\">"
       
  1929                   << t << "</xref></li>";
       
  1930             out() << "              <li><xref href=\"" << sl.at(0)
       
  1931                   << "-" << sl.at(sl.size()-1) << ".html\">"
       
  1932                   << title << "</xref></li>";
       
  1933         }
       
  1934     }
       
  1935     else if (node->type() == Node::Namespace) {
       
  1936         const NamespaceNode* nsn = static_cast<const NamespaceNode*>(node);
       
  1937         out() << "              <li><xref href=\"namespaces.html\">All Namespaces</xref></li>";
       
  1938         out() << "              <li><xref href=\"" << fileName(nsn) << "\">" << title
       
  1939               << "</xref></li>";
       
  1940     }
       
  1941 }
       
  1942 
       
  1943 void DitaXmlGenerator::generateHeader(const Node* node)
       
  1944 {
       
  1945     writer.setDevice(out().device());
       
  1946     writer.setAutoFormatting(true);
       
  1947     writer.setAutoFormattingIndent(4);
       
  1948     writer.writeStartDocument();
       
  1949     
       
  1950     if (!node)
       
  1951         return;
       
  1952 
       
  1953     QString docType;
       
  1954     QString dtd;
       
  1955     QString version;
       
  1956     if (node->type() == Node::Class) {
       
  1957         docType = "cxxClass";
       
  1958         dtd = "dtd/cxxClass.dtd";
       
  1959         version = "0.6.0";
       
  1960     }
       
  1961 
       
  1962     QString doctype = "<!DOCTYPE " + docType +
       
  1963         " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
       
  1964         version + "//EN\" \"" + dtd + "\">";
       
  1965     writer.writeDTD(doctype);
       
  1966     writer.writeComment(node->doc().location().fileName());
       
  1967 }
       
  1968 
       
  1969 void DitaXmlGenerator::generateTitle(const QString& title,
       
  1970                                      const Text &subTitle,
       
  1971                                      SubTitleSize subTitleSize,
       
  1972                                      const Node *relative,
       
  1973                                      CodeMarker *marker)
       
  1974 {
       
  1975     if (!title.isEmpty())
       
  1976         out() << "<h1 class=\"title\">" << protectEnc(title) << "</h1>\n";
       
  1977     if (!subTitle.isEmpty()) {
       
  1978  			out() << "<span";
       
  1979        if (subTitleSize == SmallSubTitle)
       
  1980             out() << " class=\"small-subtitle\">";
       
  1981         else
       
  1982             out() << " class=\"subtitle\">";
       
  1983         generateText(subTitle, relative, marker);
       
  1984         out() << "</span>\n";
       
  1985     }
       
  1986 }
       
  1987 
       
  1988 /*!
       
  1989   Outputs the brief command as a <shortdesc" element.
       
  1990  */
       
  1991 void DitaXmlGenerator::generateBrief(const Node* node, CodeMarker* marker)
       
  1992 {
       
  1993     Text brief = node->doc().briefText();
       
  1994     if (!brief.isEmpty()) {
       
  1995         ++noLinks;
       
  1996         writer.writeStartElement(SHORTDESC);
       
  1997         generateText(brief, node, marker);
       
  1998         writer.writeEndElement(); // shortdesc
       
  1999         --noLinks;
       
  2000     }
       
  2001 }
       
  2002 
       
  2003 void DitaXmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker)
       
  2004 {
       
  2005     if (!inner->includes().isEmpty()) {
       
  2006         out() << "<pre class=\"highlightedCode\">"
       
  2007               << trimmedTrailing(highlightedCode(indent(codeIndent,
       
  2008                                                         marker->markedUpIncludes(inner->includes())),
       
  2009                                                  marker,inner))
       
  2010               << "</pre>";
       
  2011     }
       
  2012 }
       
  2013 
       
  2014 /*!
       
  2015   Generates a table of contents begining at \a node.
       
  2016  */
       
  2017 void DitaXmlGenerator::generateTableOfContents(const Node *node,
       
  2018                                             CodeMarker *marker,
       
  2019                                             Doc::SectioningUnit sectioningUnit,
       
  2020                                             int numColumns,
       
  2021                                             const Node *relative)
       
  2022 
       
  2023 {
       
  2024     return;
       
  2025     if (!node->doc().hasTableOfContents())
       
  2026         return;
       
  2027     QList<Atom *> toc = node->doc().tableOfContents();
       
  2028     if (toc.isEmpty())
       
  2029         return;
       
  2030 
       
  2031     QString nodeName = "";
       
  2032     if (node != relative)
       
  2033         nodeName = node->name();
       
  2034 
       
  2035     QStringList sectionNumber;
       
  2036     int columnSize = 0;
       
  2037 
       
  2038     QString tdTag;
       
  2039     if (numColumns > 1) {
       
  2040         tdTag = "<td>"; /* width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";*/
       
  2041         out() << "<table class=\"toc\">\n<tr class=\"topAlign\">"
       
  2042               << tdTag << "\n";
       
  2043     }
       
  2044 
       
  2045     // disable nested links in table of contents
       
  2046     inContents = true;
       
  2047     inLink = true;
       
  2048 
       
  2049     for (int i = 0; i < toc.size(); ++i) {
       
  2050         Atom *atom = toc.at(i);
       
  2051 
       
  2052         int nextLevel = atom->string().toInt();
       
  2053         if (nextLevel > (int)sectioningUnit)
       
  2054             continue;
       
  2055 
       
  2056         if (sectionNumber.size() < nextLevel) {
       
  2057             do {
       
  2058                 out() << "<ul>";
       
  2059                 sectionNumber.append("1");
       
  2060             } while (sectionNumber.size() < nextLevel);
       
  2061         }
       
  2062         else {
       
  2063             while (sectionNumber.size() > nextLevel) {
       
  2064                 out() << "</ul>\n";
       
  2065                 sectionNumber.removeLast();
       
  2066             }
       
  2067             sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
       
  2068         }
       
  2069         int numAtoms;
       
  2070         Text headingText = Text::sectionHeading(atom);
       
  2071 
       
  2072         if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) {
       
  2073             out() << "</ul></td>" << tdTag << "<ul>\n";
       
  2074             columnSize = 0;
       
  2075         }
       
  2076         out() << "<li>";
       
  2077         out() << "<xref href=\""
       
  2078               << nodeName
       
  2079               << "#"
       
  2080               << Doc::canonicalTitle(headingText.toString())
       
  2081               << "\">";
       
  2082         generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
       
  2083         out() << "</xref></li>\n";
       
  2084 
       
  2085         ++columnSize;
       
  2086     }
       
  2087     while (!sectionNumber.isEmpty()) {
       
  2088         out() << "</ul>\n";
       
  2089         sectionNumber.removeLast();
       
  2090     }
       
  2091 
       
  2092     if (numColumns > 1)
       
  2093         out() << "</td></tr></table>\n";
       
  2094 
       
  2095     inContents = false;
       
  2096     inLink = false;
       
  2097 }
       
  2098 
       
  2099 /*!
       
  2100   Revised for the new doc format.
       
  2101   Generates a table of contents begining at \a node.
       
  2102  */
       
  2103 void DitaXmlGenerator::generateTableOfContents(const Node *node,
       
  2104                                             CodeMarker *marker,
       
  2105                                             QList<Section>* sections)
       
  2106 {
       
  2107     QList<Atom*> toc;
       
  2108     if (node->doc().hasTableOfContents()) 
       
  2109         toc = node->doc().tableOfContents();
       
  2110     if (toc.isEmpty() && !sections && (node->subType() != Node::Module))
       
  2111         return;
       
  2112 
       
  2113     QStringList sectionNumber;
       
  2114     int detailsBase = 0;
       
  2115 
       
  2116     // disable nested links in table of contents
       
  2117     inContents = true;
       
  2118     inLink = true;
       
  2119 
       
  2120     out() << "<div class=\"toc\">\n";
       
  2121     out() << "<h3>Contents</h3>\n";
       
  2122     sectionNumber.append("1");
       
  2123     out() << "<ul>\n";
       
  2124 
       
  2125     if (node->subType() == Node::Module) {
       
  2126         if (moduleNamespaceMap.contains(node->name())) {
       
  2127             out() << "<li class=\"level"
       
  2128                   << sectionNumber.size()
       
  2129                   << "\"><xref href=\"#"
       
  2130                   << registerRef("namespaces")
       
  2131                   << "\">Namespaces</xref></li>\n";
       
  2132         }
       
  2133         if (moduleClassMap.contains(node->name())) {
       
  2134             out() << "<li class=\"level"
       
  2135                   << sectionNumber.size()
       
  2136                   << "\"><xref href=\"#"
       
  2137                   << registerRef("classes")
       
  2138                   << "\">Classes</xref></li>\n";
       
  2139         }
       
  2140         out() << "<li class=\"level"
       
  2141               << sectionNumber.size()
       
  2142               << "\"><xref href=\"#"
       
  2143               << registerRef("details")
       
  2144               << "\">Detailed Description</xref></li>\n";
       
  2145         for (int i = 0; i < toc.size(); ++i) {
       
  2146             if (toc.at(i)->string().toInt() == 1) {
       
  2147                 detailsBase = 1;
       
  2148                 break;
       
  2149             }
       
  2150         }
       
  2151     }
       
  2152     else if (sections && (node->type() == Node::Class)) {
       
  2153         QList<Section>::ConstIterator s = sections->begin();
       
  2154         while (s != sections->end()) {
       
  2155             if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) {
       
  2156                 out() << "<li class=\"level"
       
  2157                       << sectionNumber.size()
       
  2158                       << "\"><xref href=\"#"
       
  2159                       << registerRef((*s).pluralMember)
       
  2160                       << "\">" << (*s).name
       
  2161                       << "</xref></li>\n";
       
  2162             }
       
  2163             ++s;
       
  2164         }
       
  2165         out() << "<li class=\"level"
       
  2166               << sectionNumber.size()
       
  2167               << "\"><xref href=\"#"
       
  2168               << registerRef("details")
       
  2169               << "\">Detailed Description</xref></li>\n";
       
  2170         for (int i = 0; i < toc.size(); ++i) {
       
  2171             if (toc.at(i)->string().toInt() == 1) {
       
  2172                 detailsBase = 1;
       
  2173                 break;
       
  2174             }
       
  2175         }
       
  2176     }
       
  2177 
       
  2178     for (int i = 0; i < toc.size(); ++i) {
       
  2179         Atom *atom = toc.at(i);
       
  2180         int nextLevel = atom->string().toInt() + detailsBase;
       
  2181         if (sectionNumber.size() < nextLevel) {
       
  2182             do {
       
  2183                 sectionNumber.append("1");
       
  2184             } while (sectionNumber.size() < nextLevel);
       
  2185         }
       
  2186         else {
       
  2187             while (sectionNumber.size() > nextLevel) {
       
  2188                 sectionNumber.removeLast();
       
  2189             }
       
  2190             sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
       
  2191         }
       
  2192         int numAtoms;
       
  2193         Text headingText = Text::sectionHeading(atom);
       
  2194         QString s = headingText.toString();
       
  2195         out() << "<li class=\"level"
       
  2196               << sectionNumber.size()
       
  2197               << "\">";
       
  2198         out() << "<xref href=\""
       
  2199               << "#"
       
  2200               << Doc::canonicalTitle(s)
       
  2201               << "\">";
       
  2202         generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
       
  2203         out() << "</xref></li>\n";
       
  2204     }
       
  2205     while (!sectionNumber.isEmpty()) {
       
  2206         sectionNumber.removeLast();
       
  2207     }
       
  2208     out() << "</ul>\n";
       
  2209     out() << "</div>\n";
       
  2210     inContents = false;
       
  2211     inLink = false;
       
  2212 }
       
  2213 
       
  2214 QString DitaXmlGenerator::generateListOfAllMemberFile(const InnerNode *inner,
       
  2215                                                    CodeMarker *marker)
       
  2216 {
       
  2217     QList<Section> sections;
       
  2218     QList<Section>::ConstIterator s;
       
  2219 
       
  2220     sections = marker->sections(inner,
       
  2221                                 CodeMarker::SeparateList,
       
  2222                                 CodeMarker::Okay);
       
  2223     if (sections.isEmpty())
       
  2224         return QString();
       
  2225 
       
  2226     QString fileName = fileBase(inner) + "-members." + fileExtension(inner);
       
  2227     beginSubPage(inner->location(), fileName);
       
  2228     QString title = "List of All Members for " + inner->name();
       
  2229     generateHeader(inner);
       
  2230     generateTitle(title, Text(), SmallSubTitle, inner, marker);
       
  2231     out() << "<p>This is the complete list of members for ";
       
  2232     generateFullName(inner, 0, marker);
       
  2233     out() << ", including inherited members.</p>\n";
       
  2234 
       
  2235     Section section = sections.first();
       
  2236     generateSectionList(section, 0, marker, CodeMarker::SeparateList);
       
  2237 
       
  2238     endSubPage();
       
  2239     return fileName;
       
  2240 }
       
  2241 
       
  2242 QString DitaXmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
       
  2243                                                    CodeMarker *marker,
       
  2244                                                    CodeMarker::Status status)
       
  2245 {
       
  2246     QList<Section> sections = marker->sections(inner,
       
  2247                                                CodeMarker::Summary,
       
  2248                                                status);
       
  2249     QMutableListIterator<Section> j(sections);
       
  2250     while (j.hasNext()) {
       
  2251         if (j.next().members.size() == 0)
       
  2252             j.remove();
       
  2253     }
       
  2254     if (sections.isEmpty())
       
  2255         return QString();
       
  2256 
       
  2257     int i;
       
  2258 
       
  2259     QString title;
       
  2260     QString fileName;
       
  2261 
       
  2262     if (status == CodeMarker::Compat) {
       
  2263         title = "Qt 3 Support Members for " + inner->name();
       
  2264         fileName = fileBase(inner) + "-qt3." + fileExtension(inner);
       
  2265     }
       
  2266     else {
       
  2267         title = "Obsolete Members for " + inner->name();
       
  2268         fileName = fileBase(inner) + "-obsolete." + fileExtension(inner);
       
  2269     }
       
  2270 
       
  2271     beginSubPage(inner->location(), fileName);
       
  2272     generateHeader(inner);
       
  2273     generateTitle(title, Text(), SmallSubTitle, inner, marker);
       
  2274 
       
  2275     if (status == CodeMarker::Compat) {
       
  2276         out() << "<p><b>The following class members are part of the "
       
  2277                  "<xref href=\"qt3support.html\">Qt 3 support layer</xref>.</b> "
       
  2278                  "They are provided to help you port old code to Qt 4. We advise against "
       
  2279                  "using them in new code.</p>\n";
       
  2280     }
       
  2281     else {
       
  2282         out() << "<p><b>The following class members are obsolete.</b> "
       
  2283               << "They are provided to keep old source code working. "
       
  2284               << "We strongly advise against using them in new code.</p>\n";
       
  2285     }
       
  2286 
       
  2287     out() << "<p><ul><li><xref href=\""
       
  2288           << linkForNode(inner, 0) << "\">"
       
  2289           << protectEnc(inner->name())
       
  2290           << " class reference</xref></li></ul></p>\n";
       
  2291 
       
  2292     for (i = 0; i < sections.size(); ++i) {
       
  2293         out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n";
       
  2294         generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary);
       
  2295     }
       
  2296 
       
  2297     sections = marker->sections(inner, CodeMarker::Detailed, status);
       
  2298     for (i = 0; i < sections.size(); ++i) {
       
  2299         out() << "<hr />\n";
       
  2300         out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n";
       
  2301 
       
  2302         NodeList::ConstIterator m = sections.at(i).members.begin();
       
  2303         while (m != sections.at(i).members.end()) {
       
  2304             if ((*m)->access() != Node::Private)
       
  2305                 generateDetailedMember(*m, inner, marker);
       
  2306             ++m;
       
  2307         }
       
  2308     }
       
  2309 
       
  2310     endSubPage();
       
  2311     return fileName;
       
  2312 }
       
  2313 
       
  2314 void DitaXmlGenerator::generateClassHierarchy(const Node *relative,
       
  2315                                            CodeMarker *marker,
       
  2316                                            const QMap<QString,const Node*> &classMap)
       
  2317 {
       
  2318     if (classMap.isEmpty())
       
  2319         return;
       
  2320 
       
  2321     NodeMap topLevel;
       
  2322     NodeMap::ConstIterator c = classMap.begin();
       
  2323     while (c != classMap.end()) {
       
  2324         const ClassNode *classe = static_cast<const ClassNode *>(*c);
       
  2325         if (classe->baseClasses().isEmpty())
       
  2326             topLevel.insert(classe->name(), classe);
       
  2327         ++c;
       
  2328     }
       
  2329 
       
  2330     QStack<NodeMap > stack;
       
  2331     stack.push(topLevel);
       
  2332 
       
  2333     out() << "<ul>\n";
       
  2334     while (!stack.isEmpty()) {
       
  2335         if (stack.top().isEmpty()) {
       
  2336             stack.pop();
       
  2337             out() << "</ul>\n";
       
  2338         }
       
  2339         else {
       
  2340             const ClassNode *child =
       
  2341                 static_cast<const ClassNode *>(*stack.top().begin());
       
  2342             out() << "<li>";
       
  2343             generateFullName(child, relative, marker);
       
  2344             out() << "</li>\n";
       
  2345             stack.top().erase(stack.top().begin());
       
  2346 
       
  2347             NodeMap newTop;
       
  2348             foreach (const RelatedClass &d, child->derivedClasses()) {
       
  2349                 if (d.access != Node::Private)
       
  2350                     newTop.insert(d.node->name(), d.node);
       
  2351             }
       
  2352             if (!newTop.isEmpty()) {
       
  2353                 stack.push(newTop);
       
  2354                 out() << "<ul>\n";
       
  2355             }
       
  2356         }
       
  2357     }
       
  2358 }
       
  2359 
       
  2360 void DitaXmlGenerator::generateAnnotatedList(const Node *relative,
       
  2361                                           CodeMarker *marker,
       
  2362                                           const NodeMap &nodeMap)
       
  2363 {
       
  2364     out() << "<table class=\"annotated\">\n";
       
  2365 
       
  2366     int row = 0;
       
  2367     foreach (const QString &name, nodeMap.keys()) {
       
  2368         const Node *node = nodeMap[name];
       
  2369 
       
  2370         if (node->status() == Node::Obsolete)
       
  2371             continue;
       
  2372 
       
  2373         if (++row % 2 == 1)
       
  2374             out() << "<tr class=\"odd topAlign\">";
       
  2375         else
       
  2376             out() << "<tr class=\"even topAlign\">";
       
  2377         out() << "<td><p>";
       
  2378         generateFullName(node, relative, marker);
       
  2379         out() << "</p></td>";
       
  2380 
       
  2381         if (!(node->type() == Node::Fake)) {
       
  2382             Text brief = node->doc().trimmedBriefText(name);
       
  2383             if (!brief.isEmpty()) {
       
  2384                 out() << "<td><p>";
       
  2385                 generateText(brief, node, marker);
       
  2386                 out() << "</p></td>";
       
  2387             }
       
  2388         }
       
  2389         else {
       
  2390             out() << "<td><p>";
       
  2391             out() << protectEnc(node->doc().briefText().toString());
       
  2392             out() << "</p></td>";
       
  2393         }
       
  2394         out() << "</tr>\n";
       
  2395     }
       
  2396     out() << "</table>\n";
       
  2397 }
       
  2398 
       
  2399 /*!
       
  2400   This function finds the common prefix of the names of all
       
  2401   the classes in \a classMap and then generates a compact
       
  2402   list of the class names alphabetized on the part of the
       
  2403   name not including the common prefix. You can tell the
       
  2404   function to use \a comonPrefix as the common prefix, but
       
  2405   normally you let it figure it out itself by looking at
       
  2406   the name of the first and last classes in \a classMap.
       
  2407  */
       
  2408 void DitaXmlGenerator::generateCompactList(const Node *relative,
       
  2409                                         CodeMarker *marker,
       
  2410                                         const NodeMap &classMap,
       
  2411                                         bool includeAlphabet,
       
  2412                                         QString commonPrefix)
       
  2413 {
       
  2414     const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_'
       
  2415 
       
  2416     if (classMap.isEmpty())
       
  2417         return;
       
  2418 
       
  2419     /*
       
  2420       If commonPrefix is not empty, then the caller knows what
       
  2421       the common prefix is and has passed it in, so just use that
       
  2422       one.
       
  2423      */
       
  2424     int commonPrefixLen = commonPrefix.length();
       
  2425     if (commonPrefixLen == 0) {
       
  2426         QString first;
       
  2427         QString last;
       
  2428         
       
  2429         /*
       
  2430           The caller didn't pass in a common prefix, so get the common
       
  2431           prefix by looking at the class names of the first and last
       
  2432           classes in the class map. Discard any namespace names and
       
  2433           just use the bare class names. For Qt, the prefix is "Q".
       
  2434 
       
  2435           Note that the algorithm used here to derive the common prefix
       
  2436           from the first and last classes in alphabetical order (QAccel
       
  2437           and QXtWidget in Qt 2.1), fails if either class name does not
       
  2438           begin with Q.
       
  2439         */
       
  2440 
       
  2441         NodeMap::const_iterator iter = classMap.begin();
       
  2442         while (iter != classMap.end()) {
       
  2443             if (!iter.key().contains("::")) {
       
  2444                 first = iter.key();
       
  2445                 break;
       
  2446             }
       
  2447             ++iter;
       
  2448         }
       
  2449 
       
  2450         if (first.isEmpty())
       
  2451             first = classMap.begin().key();
       
  2452 
       
  2453         iter = classMap.end();
       
  2454         while (iter != classMap.begin()) {
       
  2455             --iter;
       
  2456             if (!iter.key().contains("::")) {
       
  2457                 last = iter.key();
       
  2458                 break;
       
  2459             }
       
  2460         }
       
  2461 
       
  2462         if (last.isEmpty())
       
  2463             last = classMap.begin().key();
       
  2464 
       
  2465         if (classMap.size() > 1) {
       
  2466             while (commonPrefixLen < first.length() + 1 &&
       
  2467                    commonPrefixLen < last.length() + 1 &&
       
  2468                    first[commonPrefixLen] == last[commonPrefixLen])
       
  2469                 ++commonPrefixLen;
       
  2470         }
       
  2471 
       
  2472         commonPrefix = first.left(commonPrefixLen);
       
  2473     }
       
  2474 
       
  2475     /*
       
  2476       Divide the data into 37 paragraphs: 0, ..., 9, A, ..., Z,
       
  2477       underscore (_). QAccel will fall in paragraph 10 (A) and
       
  2478       QXtWidget in paragraph 33 (X). This is the only place where we
       
  2479       assume that NumParagraphs is 37. Each paragraph is a NodeMap.
       
  2480     */
       
  2481     NodeMap paragraph[NumParagraphs+1];
       
  2482     QString paragraphName[NumParagraphs+1];
       
  2483     QSet<char> usedParagraphNames;
       
  2484 
       
  2485     NodeMap::ConstIterator c = classMap.begin();
       
  2486     while (c != classMap.end()) {
       
  2487         QStringList pieces = c.key().split("::");
       
  2488         QString key;
       
  2489         int idx = commonPrefixLen;
       
  2490         if (!pieces.last().startsWith(commonPrefix))
       
  2491             idx = 0;
       
  2492         if (pieces.size() == 1)
       
  2493             key = pieces.last().mid(idx).toLower();
       
  2494         else
       
  2495             key = pieces.last().toLower();
       
  2496 
       
  2497         int paragraphNr = NumParagraphs - 1;
       
  2498 
       
  2499         if (key[0].digitValue() != -1) {
       
  2500             paragraphNr = key[0].digitValue();
       
  2501         }
       
  2502         else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
       
  2503             paragraphNr = 10 + key[0].unicode() - 'a';
       
  2504         }
       
  2505 
       
  2506         paragraphName[paragraphNr] = key[0].toUpper();
       
  2507         usedParagraphNames.insert(key[0].toLower().cell());
       
  2508         paragraph[paragraphNr].insert(key, c.value());
       
  2509         ++c;
       
  2510     }
       
  2511 
       
  2512     /*
       
  2513       Each paragraph j has a size: paragraph[j].count(). In the
       
  2514       discussion, we will assume paragraphs 0 to 5 will have sizes
       
  2515       3, 1, 4, 1, 5, 9.
       
  2516 
       
  2517       We now want to compute the paragraph offset. Paragraphs 0 to 6
       
  2518       start at offsets 0, 3, 4, 8, 9, 14, 23.
       
  2519     */
       
  2520     int paragraphOffset[NumParagraphs + 1];     // 37 + 1
       
  2521     paragraphOffset[0] = 0;
       
  2522     for (int i=0; i<NumParagraphs; i++)         // i = 0..36
       
  2523         paragraphOffset[i+1] = paragraphOffset[i] + paragraph[i].count();
       
  2524 
       
  2525     int curParNr = 0;
       
  2526     int curParOffset = 0;
       
  2527 
       
  2528     /*
       
  2529       Output the alphabet as a row of links.
       
  2530      */
       
  2531     if (includeAlphabet) {
       
  2532         out() << "<p  class=\"centerAlign functionIndex\"><b>";
       
  2533         for (int i = 0; i < 26; i++) {
       
  2534             QChar ch('a' + i);
       
  2535             if (usedParagraphNames.contains(char('a' + i)))
       
  2536                 out() << QString("<xref href=\"#%1\">%2</xref>&nbsp;").arg(ch).arg(ch.toUpper());
       
  2537         }
       
  2538         out() << "</b></p>\n";
       
  2539     }
       
  2540 
       
  2541     /*
       
  2542       Output a <div> element to contain all the <dl> elements.
       
  2543      */
       
  2544     out() << "<div class=\"flowListDiv\">\n";
       
  2545 
       
  2546     for (int i=0; i<classMap.count()-1; i++) {
       
  2547         while ((curParNr < NumParagraphs) &&
       
  2548                (curParOffset == paragraph[curParNr].count())) {
       
  2549             ++curParNr;
       
  2550             curParOffset = 0;
       
  2551         }
       
  2552 
       
  2553         /*
       
  2554           Starting a new paragraph means starting a new <dl>.
       
  2555         */
       
  2556         if (curParOffset == 0) {
       
  2557             if (i > 0)
       
  2558                 out() << "</dl>\n";
       
  2559             if (++numTableRows % 2 == 1)
       
  2560                 out() << "<dl class=\"flowList odd\">";
       
  2561             else
       
  2562                 out() << "<dl class=\"flowList even\">";
       
  2563             out() << "<dt class=\"alphaChar\">";
       
  2564             if (includeAlphabet) {
       
  2565                 QChar c = paragraphName[curParNr][0].toLower();
       
  2566                 out() << QString("<a name=\"%1\"></a>").arg(c);
       
  2567             }
       
  2568             out() << "<b>"
       
  2569                   << paragraphName[curParNr]
       
  2570                   << "</b>";
       
  2571             out() << "</dt>\n";
       
  2572         }
       
  2573 
       
  2574         /*
       
  2575           Output a <dd> for the current offset in the current paragraph.
       
  2576          */
       
  2577         out() << "<dd>";
       
  2578         if ((curParNr < NumParagraphs) &&
       
  2579             !paragraphName[curParNr].isEmpty()) {
       
  2580             NodeMap::Iterator it;
       
  2581             it = paragraph[curParNr].begin();
       
  2582             for (int i=0; i<curParOffset; i++)
       
  2583                 ++it;
       
  2584 
       
  2585             /*
       
  2586               Previously, we used generateFullName() for this, but we
       
  2587               require some special formatting.
       
  2588             */
       
  2589             out() << "<xref href=\"" << linkForNode(it.value(), relative) << "\">";
       
  2590             
       
  2591             QStringList pieces;
       
  2592             if (it.value()->subType() == Node::QmlClass)
       
  2593                 pieces << it.value()->name();
       
  2594             else
       
  2595                 pieces = fullName(it.value(), relative, marker).split("::");
       
  2596             out() << protectEnc(pieces.last());
       
  2597             out() << "</xref>";
       
  2598             if (pieces.size() > 1) {
       
  2599                 out() << " (";
       
  2600                 generateFullName(it.value()->parent(), relative, marker);
       
  2601                 out() << ")";
       
  2602             }
       
  2603         }
       
  2604         out() << "</dd>\n";
       
  2605         curParOffset++;
       
  2606     }
       
  2607     out() << "</dl>\n";
       
  2608     out() << "</div>\n";
       
  2609 }
       
  2610 
       
  2611 void DitaXmlGenerator::generateFunctionIndex(const Node *relative,
       
  2612                                           CodeMarker *marker)
       
  2613 {
       
  2614     out() << "<p  class=\"centerAlign functionIndex\"><b>";
       
  2615     for (int i = 0; i < 26; i++) {
       
  2616         QChar ch('a' + i);
       
  2617         out() << QString("<xref href=\"#%1\">%2</xref>&nbsp;").arg(ch).arg(ch.toUpper());
       
  2618     }
       
  2619     out() << "</b></p>\n";
       
  2620 
       
  2621     char nextLetter = 'a';
       
  2622     char currentLetter;
       
  2623 
       
  2624 #if 1
       
  2625     out() << "<ul>\n";
       
  2626 #endif
       
  2627     QMap<QString, NodeMap >::ConstIterator f = funcIndex.begin();
       
  2628     while (f != funcIndex.end()) {
       
  2629 #if 1
       
  2630         out() << "<li>";
       
  2631 #else
       
  2632         out() << "<p>";
       
  2633 #endif
       
  2634         out() << protectEnc(f.key()) << ":";
       
  2635 
       
  2636         currentLetter = f.key()[0].unicode();
       
  2637         while (islower(currentLetter) && currentLetter >= nextLetter) {
       
  2638             out() << QString("<a name=\"%1\"></a>").arg(nextLetter);
       
  2639             nextLetter++;
       
  2640         }
       
  2641 
       
  2642         NodeMap::ConstIterator s = (*f).begin();
       
  2643         while (s != (*f).end()) {
       
  2644             out() << " ";
       
  2645             generateFullName((*s)->parent(), relative, marker, *s);
       
  2646             ++s;
       
  2647         }
       
  2648 #if 1
       
  2649         out() << "</li>";
       
  2650 #else
       
  2651         out() << "</p>";
       
  2652 #endif
       
  2653         out() << "\n";
       
  2654         ++f;
       
  2655     }
       
  2656 #if 1
       
  2657     out() << "</ul>\n";
       
  2658 #endif
       
  2659 }
       
  2660 
       
  2661 void DitaXmlGenerator::generateLegaleseList(const Node *relative,
       
  2662                                          CodeMarker *marker)
       
  2663 {
       
  2664     QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin();
       
  2665     while (it != legaleseTexts.end()) {
       
  2666         Text text = it.key();
       
  2667         out() << "<hr />\n";
       
  2668         generateText(text, relative, marker);
       
  2669         out() << "<ul>\n";
       
  2670         do {
       
  2671             out() << "<li>";
       
  2672             generateFullName(it.value(), relative, marker);
       
  2673             out() << "</li>\n";
       
  2674             ++it;
       
  2675         } while (it != legaleseTexts.end() && it.key() == text);
       
  2676         out() << "</ul>\n";
       
  2677     }
       
  2678 }
       
  2679 
       
  2680 /*void DitaXmlGenerator::generateSynopsis(const Node *node,
       
  2681                                      const Node *relative,
       
  2682                                      CodeMarker *marker,
       
  2683                                      CodeMarker::SynopsisStyle style)
       
  2684 {
       
  2685     QString marked = marker->markedUpSynopsis(node, relative, style);
       
  2686     QRegExp templateTag("(<[^@>]*>)");
       
  2687     if (marked.indexOf(templateTag) != -1) {
       
  2688         QString contents = protectEnc(marked.mid(templateTag.pos(1),
       
  2689                                               templateTag.cap(1).length()));
       
  2690         marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
       
  2691                         contents);
       
  2692     }
       
  2693     marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
       
  2694                    "<i>\\1<sub>\\2</sub></i>");
       
  2695     marked.replace("<@param>", "<i>");
       
  2696     marked.replace("</@param>", "</i>");
       
  2697 
       
  2698     if (style == CodeMarker::Summary)
       
  2699         marked.replace("@name>", "b>");
       
  2700 
       
  2701     if (style == CodeMarker::SeparateList) {
       
  2702         QRegExp extraRegExp("<@extra>.*</@extra>");
       
  2703         extraRegExp.setMinimal(true);
       
  2704         marked.replace(extraRegExp, "");
       
  2705     }
       
  2706     else {
       
  2707         marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
       
  2708         marked.replace("</@extra>", "</tt>");
       
  2709     }
       
  2710 
       
  2711     if (style != CodeMarker::Detailed) {
       
  2712         marked.replace("<@type>", "");
       
  2713         marked.replace("</@type>", "");
       
  2714     }
       
  2715     out() << highlightedCode(marked, marker, relative);
       
  2716 }*/
       
  2717 
       
  2718 #ifdef QDOC_QML
       
  2719 void DitaXmlGenerator::generateQmlItem(const Node *node,
       
  2720                                     const Node *relative,
       
  2721                                     CodeMarker *marker,
       
  2722                                     bool summary)
       
  2723 { 
       
  2724     QString marked = marker->markedUpQmlItem(node,summary);
       
  2725     QRegExp templateTag("(<[^@>]*>)");
       
  2726     if (marked.indexOf(templateTag) != -1) {
       
  2727         QString contents = protectEnc(marked.mid(templateTag.pos(1),
       
  2728                                               templateTag.cap(1).length()));
       
  2729         marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
       
  2730                         contents);
       
  2731     }
       
  2732     marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
       
  2733                    "<i>\\1<sub>\\2</sub></i>");
       
  2734     marked.replace("<@param>", "<i>");
       
  2735     marked.replace("</@param>", "</i>");
       
  2736 
       
  2737     if (summary)
       
  2738         marked.replace("@name>", "b>");
       
  2739 
       
  2740     marked.replace("<@extra>", "<tt>");
       
  2741     marked.replace("</@extra>", "</tt>");
       
  2742 
       
  2743     if (summary) {
       
  2744         marked.replace("<@type>", "");
       
  2745         marked.replace("</@type>", "");
       
  2746     }
       
  2747     out() << highlightedCode(marked, marker, relative);
       
  2748 }
       
  2749 #endif
       
  2750 
       
  2751 void DitaXmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */)
       
  2752 {
       
  2753     QMap<const FakeNode *, QMap<QString, FakeNode *> > fakeNodeMap;
       
  2754     QMap<QString, const FakeNode *> groupTitlesMap;
       
  2755     QMap<QString, FakeNode *> uncategorizedNodeMap;
       
  2756     QRegExp singleDigit("\\b([0-9])\\b");
       
  2757 
       
  2758     const NodeList children = myTree->root()->childNodes();
       
  2759     foreach (Node *child, children) {
       
  2760         if (child->type() == Node::Fake && child != relative) {
       
  2761             FakeNode *fakeNode = static_cast<FakeNode *>(child);
       
  2762 
       
  2763             // Check whether the page is part of a group or is the group
       
  2764             // definition page.
       
  2765             QString group;
       
  2766             bool isGroupPage = false;
       
  2767             if (fakeNode->doc().metaCommandsUsed().contains("group")) {
       
  2768                 group = fakeNode->doc().metaCommandArgs("group")[0];
       
  2769                 isGroupPage = true;
       
  2770             }
       
  2771 
       
  2772             // there are too many examples; they would clutter the list
       
  2773             if (fakeNode->subType() == Node::Example)
       
  2774                 continue;
       
  2775 
       
  2776             // not interested either in individual (Qt Designer etc.) manual chapters
       
  2777             if (fakeNode->links().contains(Node::ContentsLink))
       
  2778                 continue;
       
  2779 
       
  2780             // Discard external nodes.
       
  2781             if (fakeNode->subType() == Node::ExternalPage)
       
  2782                 continue;
       
  2783 
       
  2784             QString sortKey = fakeNode->fullTitle().toLower();
       
  2785             if (sortKey.startsWith("the "))
       
  2786                 sortKey.remove(0, 4);
       
  2787             sortKey.replace(singleDigit, "0\\1");
       
  2788 
       
  2789             if (!group.isEmpty()) {
       
  2790                 if (isGroupPage) {
       
  2791                     // If we encounter a group definition page, we add all
       
  2792                     // the pages in that group to the list for that group.
       
  2793                     foreach (Node *member, fakeNode->groupMembers()) {
       
  2794                         if (member->type() != Node::Fake)
       
  2795                             continue;
       
  2796                         FakeNode *page = static_cast<FakeNode *>(member);
       
  2797                         if (page) {
       
  2798                             QString sortKey = page->fullTitle().toLower();
       
  2799                             if (sortKey.startsWith("the "))
       
  2800                                 sortKey.remove(0, 4);
       
  2801                             sortKey.replace(singleDigit, "0\\1");
       
  2802                             fakeNodeMap[const_cast<const FakeNode *>(fakeNode)].insert(sortKey, page);
       
  2803                             groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode);
       
  2804                         }
       
  2805                     }
       
  2806                 }
       
  2807                 else if (!isGroupPage) {
       
  2808                     // If we encounter a page that belongs to a group then
       
  2809                     // we add that page to the list for that group.
       
  2810                     const FakeNode *groupNode = static_cast<const FakeNode *>(myTree->root()->findNode(group, Node::Fake));
       
  2811                     if (groupNode)
       
  2812                         fakeNodeMap[groupNode].insert(sortKey, fakeNode);
       
  2813                     //else
       
  2814                     //    uncategorizedNodeMap.insert(sortKey, fakeNode);
       
  2815                 }// else
       
  2816                 //    uncategorizedNodeMap.insert(sortKey, fakeNode);
       
  2817             }// else
       
  2818             //    uncategorizedNodeMap.insert(sortKey, fakeNode);
       
  2819         }
       
  2820     }
       
  2821 
       
  2822     // We now list all the pages found that belong to groups.
       
  2823     // If only certain pages were found for a group, but the definition page
       
  2824     // for that group wasn't listed, the list of pages will be intentionally
       
  2825     // incomplete. However, if the group definition page was listed, all the
       
  2826     // pages in that group are listed for completeness.
       
  2827 
       
  2828     if (!fakeNodeMap.isEmpty()) {
       
  2829         foreach (const QString &groupTitle, groupTitlesMap.keys()) {
       
  2830             const FakeNode *groupNode = groupTitlesMap[groupTitle];
       
  2831             out() << QString("<h3><xref href=\"%1\">%2</xref></h3>\n").arg(
       
  2832                         linkForNode(groupNode, relative)).arg(
       
  2833                         protectEnc(groupNode->fullTitle()));
       
  2834 
       
  2835             if (fakeNodeMap[groupNode].count() == 0)
       
  2836                 continue;
       
  2837 
       
  2838             out() << "<ul>\n";
       
  2839 
       
  2840             foreach (const FakeNode *fakeNode, fakeNodeMap[groupNode]) {
       
  2841                 QString title = fakeNode->fullTitle();
       
  2842                 if (title.startsWith("The "))
       
  2843                     title.remove(0, 4);
       
  2844                 out() << "<li><xref href=\"" << linkForNode(fakeNode, relative) << "\">"
       
  2845                       << protectEnc(title) << "</xref></li>\n";
       
  2846             }
       
  2847             out() << "</ul>\n";
       
  2848         }
       
  2849     }
       
  2850 
       
  2851     if (!uncategorizedNodeMap.isEmpty()) {
       
  2852         out() << QString("<h3>Miscellaneous</h3>\n");
       
  2853         out() << "<ul>\n";
       
  2854         foreach (const FakeNode *fakeNode, uncategorizedNodeMap) {
       
  2855             QString title = fakeNode->fullTitle();
       
  2856             if (title.startsWith("The "))
       
  2857                 title.remove(0, 4);
       
  2858             out() << "<li><xref href=\"" << linkForNode(fakeNode, relative) << "\">"
       
  2859                   << protectEnc(title) << "</xref></li>\n";
       
  2860         }
       
  2861         out() << "</ul>\n";
       
  2862     }
       
  2863 }
       
  2864 
       
  2865 void DitaXmlGenerator::generateSection(const NodeList& nl,
       
  2866                                     const Node *relative,
       
  2867                                     CodeMarker *marker,
       
  2868                                     CodeMarker::SynopsisStyle style)
       
  2869 {
       
  2870     bool name_alignment = true;
       
  2871     if (!nl.isEmpty()) {
       
  2872         bool twoColumn = false;
       
  2873         if (style == CodeMarker::SeparateList) {
       
  2874             name_alignment = false;
       
  2875             twoColumn = (nl.count() >= 16);
       
  2876         }
       
  2877         else if (nl.first()->type() == Node::Property) {
       
  2878             twoColumn = (nl.count() >= 5);
       
  2879             name_alignment = false;
       
  2880         }
       
  2881         if (name_alignment) {
       
  2882             out() << "<table class=\"alignedsummary\">\n";
       
  2883         }
       
  2884         else {
       
  2885             if (twoColumn)
       
  2886                 out() << "<table class=\"propsummary\">\n"
       
  2887                       << "<tr><td  class=\"topAlign\">";
       
  2888             out() << "<ul>\n";
       
  2889         }
       
  2890 
       
  2891         int i = 0;
       
  2892         NodeList::ConstIterator m = nl.begin();
       
  2893         while (m != nl.end()) {
       
  2894             if ((*m)->access() == Node::Private) {
       
  2895                 ++m;
       
  2896                 continue;
       
  2897             }
       
  2898 
       
  2899             if (name_alignment) {
       
  2900                 out() << "<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
       
  2901             }
       
  2902             else {
       
  2903                 if (twoColumn && i == (int) (nl.count() + 1) / 2)
       
  2904                     out() << "</ul></td><td  class=\"topAlign\"><ul>\n";
       
  2905                 out() << "<li class=\"fn\">";
       
  2906             }
       
  2907 
       
  2908             generateSynopsis(*m, relative, marker, style, name_alignment);
       
  2909             if (name_alignment)
       
  2910                 out() << "</td></tr>\n";
       
  2911             else
       
  2912                 out() << "</li>\n";
       
  2913             i++;
       
  2914             ++m;
       
  2915         }
       
  2916         if (name_alignment)
       
  2917             out() << "</table>\n";
       
  2918         else {
       
  2919             out() << "</ul>\n";
       
  2920             if (twoColumn)
       
  2921                 out() << "</td></tr>\n</table>\n";
       
  2922         }
       
  2923     }
       
  2924 }
       
  2925 
       
  2926 void DitaXmlGenerator::generateSectionList(const Section& section,
       
  2927                                         const Node *relative,
       
  2928                                         CodeMarker *marker,
       
  2929                                         CodeMarker::SynopsisStyle style)
       
  2930 {
       
  2931     bool name_alignment = true;
       
  2932     if (!section.members.isEmpty()) {
       
  2933         bool twoColumn = false;
       
  2934         if (style == CodeMarker::SeparateList) {
       
  2935             name_alignment = false;
       
  2936             twoColumn = (section.members.count() >= 16);
       
  2937         }
       
  2938         else if (section.members.first()->type() == Node::Property) {
       
  2939             twoColumn = (section.members.count() >= 5);
       
  2940             name_alignment = false;
       
  2941         }
       
  2942         if (name_alignment) {
       
  2943             out() << "<table class=\"alignedsummary\">\n";
       
  2944         }
       
  2945         else {
       
  2946             if (twoColumn)
       
  2947                 out() << "<table class=\"propsummary\">\n"
       
  2948                       << "<tr><td  class=\"topAlign\">";
       
  2949             out() << "<ul>\n";
       
  2950         }
       
  2951 
       
  2952         int i = 0;
       
  2953         NodeList::ConstIterator m = section.members.begin();
       
  2954         while (m != section.members.end()) {
       
  2955             if ((*m)->access() == Node::Private) {
       
  2956                 ++m;
       
  2957                 continue;
       
  2958             }
       
  2959 
       
  2960             if (name_alignment) {
       
  2961                 out() << "<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
       
  2962             }
       
  2963             else {
       
  2964                 if (twoColumn && i == (int) (section.members.count() + 1) / 2)
       
  2965                     out() << "</ul></td><td class=\"topAlign\"><ul>\n";
       
  2966                 out() << "<li class=\"fn\">";
       
  2967             }
       
  2968 
       
  2969             generateSynopsis(*m, relative, marker, style, name_alignment);
       
  2970             if (name_alignment)
       
  2971                 out() << "</td></tr>\n";
       
  2972             else
       
  2973                 out() << "</li>\n";
       
  2974             i++;
       
  2975             ++m;
       
  2976         }
       
  2977         if (name_alignment)
       
  2978             out() << "</table>\n";
       
  2979         else {
       
  2980             out() << "</ul>\n";
       
  2981             if (twoColumn)
       
  2982                 out() << "</td></tr>\n</table>\n";
       
  2983         }
       
  2984     }
       
  2985 
       
  2986     if (style == CodeMarker::Summary && !section.inherited.isEmpty()) {
       
  2987         out() << "<ul>\n";
       
  2988         generateSectionInheritedList(section, relative, marker, name_alignment);
       
  2989         out() << "</ul>\n";
       
  2990     }
       
  2991 }
       
  2992 
       
  2993 void DitaXmlGenerator::generateSectionInheritedList(const Section& section,
       
  2994                                                  const Node *relative,
       
  2995                                                  CodeMarker *marker,
       
  2996                                                  bool nameAlignment)
       
  2997 {
       
  2998     QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin();
       
  2999     while (p != section.inherited.end()) {
       
  3000         if (nameAlignment)
       
  3001             out() << "<li class=\"fn\">";
       
  3002         else
       
  3003             out() << "<li class=\"fn\">";
       
  3004         out() << (*p).second << " ";
       
  3005         if ((*p).second == 1) {
       
  3006             out() << section.singularMember;
       
  3007         }
       
  3008         else {
       
  3009             out() << section.pluralMember;
       
  3010         }
       
  3011         out() << " inherited from <xref href=\"" << fileName((*p).first)
       
  3012               << "#" << DitaXmlGenerator::cleanRef(section.name.toLower()) << "\">"
       
  3013               << protectEnc(marker->plainFullName((*p).first, relative))
       
  3014               << "</xref></li>\n";
       
  3015         ++p;
       
  3016     }
       
  3017 }
       
  3018 
       
  3019 void DitaXmlGenerator::generateSynopsis(const Node *node,
       
  3020                                      const Node *relative,
       
  3021                                      CodeMarker *marker,
       
  3022                                      CodeMarker::SynopsisStyle style,
       
  3023                                      bool nameAlignment)
       
  3024 {
       
  3025     QString marked = marker->markedUpSynopsis(node, relative, style);
       
  3026     QRegExp templateTag("(<[^@>]*>)");
       
  3027     if (marked.indexOf(templateTag) != -1) {
       
  3028         QString contents = protectEnc(marked.mid(templateTag.pos(1),
       
  3029                                               templateTag.cap(1).length()));
       
  3030         marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
       
  3031                         contents);
       
  3032     }
       
  3033     marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
       
  3034                    "<i>\\1<sub>\\2</sub></i>");
       
  3035     marked.replace("<@param>", "<i>");
       
  3036     marked.replace("</@param>", "</i>");
       
  3037 
       
  3038     if (style == CodeMarker::Summary) {
       
  3039         marked.replace("<@name>", "");   // was "<b>"
       
  3040         marked.replace("</@name>", "");  // was "</b>"
       
  3041     }
       
  3042 
       
  3043     if (style == CodeMarker::SeparateList) {
       
  3044         QRegExp extraRegExp("<@extra>.*</@extra>");
       
  3045         extraRegExp.setMinimal(true);
       
  3046         marked.replace(extraRegExp, "");
       
  3047     } else {
       
  3048         marked.replace("<@extra>", "<tt>");
       
  3049         marked.replace("</@extra>", "</tt>");
       
  3050     }
       
  3051 
       
  3052     if (style != CodeMarker::Detailed) {
       
  3053         marked.replace("<@type>", "");
       
  3054         marked.replace("</@type>", "");
       
  3055     }
       
  3056     out() << highlightedCode(marked, marker, relative, style, nameAlignment);
       
  3057 }
       
  3058 
       
  3059 QString DitaXmlGenerator::highlightedCode(const QString& markedCode,
       
  3060                                        CodeMarker *marker,
       
  3061                                        const Node *relative,
       
  3062                                        CodeMarker::SynopsisStyle ,
       
  3063                                        bool nameAlignment)
       
  3064 {
       
  3065     QString src = markedCode;
       
  3066     QString html;
       
  3067     QStringRef arg;
       
  3068     QStringRef par1;
       
  3069 
       
  3070     const QChar charLangle = '<';
       
  3071     const QChar charAt = '@';
       
  3072 
       
  3073     // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
       
  3074     static const QString linkTag("link");
       
  3075     bool done = false;
       
  3076     for (int i = 0, n = src.size(); i < n;) {
       
  3077         if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') {
       
  3078             if (nameAlignment && !done) {// && (i != 0)) Why was this here?
       
  3079                 html += "</td><td class=\"memItemRight bottomAlign\">";
       
  3080                 done = true;
       
  3081             }
       
  3082             i += 2;
       
  3083             if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
       
  3084                 html += "<b>";
       
  3085                 QString link = linkForNode(
       
  3086                     CodeMarker::nodeForString(par1.toString()), relative);
       
  3087                 addLink(link, arg, &html);
       
  3088                 html += "</b>";
       
  3089             }
       
  3090             else {
       
  3091                 html += charLangle;
       
  3092                 html += charAt;
       
  3093             }
       
  3094         }
       
  3095         else {
       
  3096             html += src.at(i++);
       
  3097         }
       
  3098     }
       
  3099 
       
  3100 
       
  3101     if (slow) {
       
  3102         // is this block ever used at all?
       
  3103         // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)"
       
  3104         src = html;
       
  3105         html = QString();
       
  3106         static const QString funcTag("func");
       
  3107         for (int i = 0, n = src.size(); i < n;) {
       
  3108             if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
       
  3109                 i += 2;
       
  3110                 if (parseArg(src, funcTag, &i, n, &arg, &par1)) {
       
  3111                     QString link = linkForNode(
       
  3112                             marker->resolveTarget(par1.toString(),
       
  3113                                                   myTree,
       
  3114                                                   relative),
       
  3115                             relative);
       
  3116                     addLink(link, arg, &html);
       
  3117                     par1 = QStringRef();
       
  3118                 }
       
  3119                 else {
       
  3120                     html += charLangle;
       
  3121                     html += charAt;
       
  3122                 }
       
  3123             }
       
  3124             else {
       
  3125                 html += src.at(i++);
       
  3126             }
       
  3127         }
       
  3128     }
       
  3129 
       
  3130     // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
       
  3131     src = html;
       
  3132     html = QString();
       
  3133     static const QString typeTags[] = { "type", "headerfile", "func" };
       
  3134     for (int i = 0, n = src.size(); i < n;) {
       
  3135         if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
       
  3136             i += 2;
       
  3137             bool handled = false;
       
  3138             for (int k = 0; k != 3; ++k) {
       
  3139                 if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) {
       
  3140                     par1 = QStringRef();
       
  3141                     QString link = linkForNode(
       
  3142                             marker->resolveTarget(arg.toString(), myTree, relative),
       
  3143                             relative);
       
  3144                     addLink(link, arg, &html);
       
  3145                     handled = true;
       
  3146                     break;
       
  3147                 }
       
  3148             }
       
  3149             if (!handled) {
       
  3150                 html += charLangle;
       
  3151                 html += charAt;
       
  3152             }
       
  3153         }
       
  3154         else {
       
  3155             html += src.at(i++);
       
  3156         }
       
  3157     }
       
  3158 
       
  3159     // replace all
       
  3160     // "<@comment>" -> "<span class=\"comment\">";
       
  3161     // "<@preprocessor>" -> "<span class=\"preprocessor\">";
       
  3162     // "<@string>" -> "<span class=\"string\">";
       
  3163     // "<@char>" -> "<span class=\"char\">";
       
  3164     // "</@(?:comment|preprocessor|string|char)>" -> "</span>"
       
  3165     src = html;
       
  3166     html = QString();
       
  3167     static const QString spanTags[] = {
       
  3168         "<@comment>",      "<span class=\"comment\">",
       
  3169         "<@preprocessor>", "<span class=\"preprocessor\">",
       
  3170         "<@string>",       "<span class=\"string\">",
       
  3171         "<@char>",         "<span class=\"char\">",
       
  3172         "</@comment>",     "</span>",
       
  3173         "</@preprocessor>","</span>",
       
  3174         "</@string>",      "</span>",
       
  3175         "</@char>",        "</span>"
       
  3176         // "<@char>",      "<font color=blue>",
       
  3177         // "</@char>",     "</font>",
       
  3178         // "<@func>",      "<font color=green>",
       
  3179         // "</@func>",     "</font>",
       
  3180         // "<@id>",        "<i>",
       
  3181         // "</@id>",       "</i>",
       
  3182         // "<@keyword>",   "<b>",
       
  3183         // "</@keyword>",  "</b>",
       
  3184         // "<@number>",    "<font color=yellow>",
       
  3185         // "</@number>",   "</font>",
       
  3186         // "<@op>",        "<b>",
       
  3187         // "</@op>",       "</b>",
       
  3188         // "<@param>",     "<i>",
       
  3189         // "</@param>",    "</i>",
       
  3190         // "<@string>",    "<font color=green>",
       
  3191         // "</@string>",  "</font>",
       
  3192     };
       
  3193     for (int i = 0, n = src.size(); i < n;) {
       
  3194         if (src.at(i) == charLangle) {
       
  3195             bool handled = false;
       
  3196             for (int k = 0; k != 8; ++k) {
       
  3197                 const QString & tag = spanTags[2 * k];
       
  3198                 if (tag == QStringRef(&src, i, tag.length())) {
       
  3199                     html += spanTags[2 * k + 1];
       
  3200                     i += tag.length();
       
  3201                     handled = true;
       
  3202                     break;
       
  3203                 }
       
  3204             }
       
  3205             if (!handled) {
       
  3206                 ++i;
       
  3207                 if (src.at(i) == charAt ||
       
  3208                     (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) {
       
  3209                     // drop 'our' unknown tags (the ones still containing '@')
       
  3210                     while (i < n && src.at(i) != QLatin1Char('>'))
       
  3211                         ++i;
       
  3212                     ++i;
       
  3213                 }
       
  3214                 else {
       
  3215                     // retain all others
       
  3216                     html += charLangle;
       
  3217                 }
       
  3218             }
       
  3219         }
       
  3220         else {
       
  3221             html += src.at(i);
       
  3222             ++i;
       
  3223         }
       
  3224     }
       
  3225 
       
  3226     return html;
       
  3227 }
       
  3228 
       
  3229 void DitaXmlGenerator::generateLink(const Atom* atom,
       
  3230                                  const Node* /* relative */,
       
  3231                                  CodeMarker* marker)
       
  3232 {
       
  3233     static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_");
       
  3234 
       
  3235     if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) {
       
  3236         // hack for C++: move () outside of link
       
  3237         int k = funcLeftParen.pos(1);
       
  3238         writer.writeCharacters(protectEnc(atom->string().left(k)));
       
  3239         if (link.isEmpty()) {
       
  3240             if (showBrokenLinks)
       
  3241                 writer.writeEndElement(); // </i>
       
  3242         }
       
  3243         else {
       
  3244             writer.writeEndElement(); // </xref>
       
  3245         }
       
  3246         inLink = false;
       
  3247         writer.writeCharacters(protectEnc(atom->string().mid(k)));
       
  3248     } else if (marker->recognizeLanguage("Java")) {
       
  3249 	// hack for Java: remove () and use <tt> when appropriate
       
  3250         bool func = atom->string().endsWith("()");
       
  3251         bool tt = (func || atom->string().contains(camelCase));
       
  3252         if (tt)
       
  3253             writer.writeStartElement("tt");
       
  3254         if (func) {
       
  3255             writer.writeCharacters(protectEnc(atom->string().left(atom->string().length() - 2)));
       
  3256         }
       
  3257         else {
       
  3258             writer.writeCharacters(protectEnc(atom->string()));
       
  3259         }
       
  3260         writer.writeEndElement(); // </tt>
       
  3261     }
       
  3262     else {
       
  3263         writer.writeCharacters(protectEnc(atom->string()));
       
  3264     }
       
  3265 }
       
  3266 
       
  3267 QString DitaXmlGenerator::cleanRef(const QString& ref)
       
  3268 {
       
  3269     QString clean;
       
  3270 
       
  3271     if (ref.isEmpty())
       
  3272         return clean;
       
  3273 
       
  3274     clean.reserve(ref.size() + 20);
       
  3275     const QChar c = ref[0];
       
  3276     const uint u = c.unicode();
       
  3277 
       
  3278     if ((u >= 'a' && u <= 'z') ||
       
  3279          (u >= 'A' && u <= 'Z') ||
       
  3280          (u >= '0' && u <= '9')) {
       
  3281         clean += c;
       
  3282     } else if (u == '~') {
       
  3283         clean += "dtor.";
       
  3284     } else if (u == '_') {
       
  3285         clean += "underscore.";
       
  3286     } else {
       
  3287         clean += "A";
       
  3288     }
       
  3289 
       
  3290     for (int i = 1; i < (int) ref.length(); i++) {
       
  3291         const QChar c = ref[i];
       
  3292         const uint u = c.unicode();
       
  3293         if ((u >= 'a' && u <= 'z') ||
       
  3294              (u >= 'A' && u <= 'Z') ||
       
  3295              (u >= '0' && u <= '9') || u == '-' ||
       
  3296              u == '_' || u == ':' || u == '.') {
       
  3297             clean += c;
       
  3298         } else if (c.isSpace()) {
       
  3299             clean += "-";
       
  3300         } else if (u == '!') {
       
  3301             clean += "-not";
       
  3302         } else if (u == '&') {
       
  3303             clean += "-and";
       
  3304         } else if (u == '<') {
       
  3305             clean += "-lt";
       
  3306         } else if (u == '=') {
       
  3307             clean += "-eq";
       
  3308         } else if (u == '>') {
       
  3309             clean += "-gt";
       
  3310         } else if (u == '#') {
       
  3311             clean += "#";
       
  3312         } else {
       
  3313             clean += "-";
       
  3314             clean += QString::number((int)u, 16);
       
  3315         }
       
  3316     }
       
  3317     return clean;
       
  3318 }
       
  3319 
       
  3320 QString DitaXmlGenerator::registerRef(const QString& ref)
       
  3321 {
       
  3322     QString clean = DitaXmlGenerator::cleanRef(ref);
       
  3323 
       
  3324     for (;;) {
       
  3325         QString& prevRef = refMap[clean.toLower()];
       
  3326         if (prevRef.isEmpty()) {
       
  3327             prevRef = ref;
       
  3328             break;
       
  3329         } else if (prevRef == ref) {
       
  3330             break;
       
  3331         }
       
  3332         clean += "x";
       
  3333     }
       
  3334     return clean;
       
  3335 }
       
  3336 
       
  3337 QString DitaXmlGenerator::protectEnc(const QString &string)
       
  3338 {
       
  3339     return protect(string, outputEncoding);
       
  3340 }
       
  3341 
       
  3342 QString DitaXmlGenerator::protect(const QString &string, const QString &outputEncoding)
       
  3343 {
       
  3344 #define APPEND(x) \
       
  3345     if (xml.isEmpty()) { \
       
  3346         xml = string; \
       
  3347         xml.truncate(i); \
       
  3348     } \
       
  3349     xml += (x);
       
  3350 
       
  3351     QString xml;
       
  3352     int n = string.length();
       
  3353 
       
  3354     for (int i = 0; i < n; ++i) {
       
  3355         QChar ch = string.at(i);
       
  3356 
       
  3357         if (ch == QLatin1Char('&')) {
       
  3358             APPEND("&amp;");
       
  3359         } else if (ch == QLatin1Char('<')) {
       
  3360             APPEND("&lt;");
       
  3361         } else if (ch == QLatin1Char('>')) {
       
  3362             APPEND("&gt;");
       
  3363         } else if (ch == QLatin1Char('"')) {
       
  3364             APPEND("&quot;");
       
  3365         } else if ((outputEncoding == "ISO-8859-1" && ch.unicode() > 0x007F)
       
  3366                    || (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/'))
       
  3367                    || (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) {
       
  3368             // we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator
       
  3369             APPEND("&#x");
       
  3370             xml += QString::number(ch.unicode(), 16);
       
  3371             xml += QLatin1Char(';');
       
  3372         } else {
       
  3373             if (!xml.isEmpty())
       
  3374                 xml += ch;
       
  3375         }
       
  3376     }
       
  3377 
       
  3378     if (!xml.isEmpty())
       
  3379         return xml;
       
  3380     return string;
       
  3381 
       
  3382 #undef APPEND
       
  3383 }
       
  3384 
       
  3385 QString DitaXmlGenerator::fileBase(const Node *node)
       
  3386 {
       
  3387     QString result;
       
  3388 
       
  3389     result = PageGenerator::fileBase(node);
       
  3390 
       
  3391     if (!node->isInnerNode()) {
       
  3392         switch (node->status()) {
       
  3393         case Node::Compat:
       
  3394             result += "-qt3";
       
  3395             break;
       
  3396         case Node::Obsolete:
       
  3397             result += "-obsolete";
       
  3398             break;
       
  3399         default:
       
  3400             ;
       
  3401         }
       
  3402     }
       
  3403     return result;
       
  3404 }
       
  3405 
       
  3406 #if 0
       
  3407 QString DitaXmlGenerator::fileBase(const Node *node,
       
  3408                                 const SectionIterator& section)
       
  3409 {
       
  3410     QStringList::ConstIterator s = section.sectionNumber().end();
       
  3411     QStringList::ConstIterator b = section.baseNameStack().end();
       
  3412 
       
  3413     QString suffix;
       
  3414     QString base = fileBase(node);
       
  3415 
       
  3416     while (s != section.sectionNumber().begin()) {
       
  3417         --s;
       
  3418         --b;
       
  3419         if (!(*b).isEmpty()) {
       
  3420             base = *b;
       
  3421             break;
       
  3422         }
       
  3423         suffix.prepend("-" + *s);
       
  3424     }
       
  3425     return base + suffix;
       
  3426 }
       
  3427 #endif
       
  3428 
       
  3429 QString DitaXmlGenerator::fileName(const Node *node)
       
  3430 {
       
  3431     if (node->type() == Node::Fake) {
       
  3432         if (static_cast<const FakeNode *>(node)->subType() == Node::ExternalPage)
       
  3433             return node->name();
       
  3434         if (static_cast<const FakeNode *>(node)->subType() == Node::Image)
       
  3435             return node->name();
       
  3436     }
       
  3437     return PageGenerator::fileName(node);
       
  3438 }
       
  3439 
       
  3440 QString DitaXmlGenerator::refForNode(const Node *node)
       
  3441 {
       
  3442     const FunctionNode *func;
       
  3443     const TypedefNode *typedeffe;
       
  3444     QString ref;
       
  3445 
       
  3446     switch (node->type()) {
       
  3447     case Node::Namespace:
       
  3448     case Node::Class:
       
  3449     default:
       
  3450         break;
       
  3451     case Node::Enum:
       
  3452         ref = node->name() + "-enum";
       
  3453         break;
       
  3454     case Node::Typedef:
       
  3455         typedeffe = static_cast<const TypedefNode *>(node);
       
  3456         if (typedeffe->associatedEnum()) {
       
  3457             return refForNode(typedeffe->associatedEnum());
       
  3458         }
       
  3459         else {
       
  3460             ref = node->name() + "-typedef";
       
  3461         }
       
  3462         break;
       
  3463     case Node::Function:
       
  3464         func = static_cast<const FunctionNode *>(node);
       
  3465         if (func->associatedProperty()) {
       
  3466             return refForNode(func->associatedProperty());
       
  3467         }
       
  3468         else {
       
  3469             ref = func->name();
       
  3470             if (func->overloadNumber() != 1)
       
  3471                 ref += "-" + QString::number(func->overloadNumber());
       
  3472         }
       
  3473         break;
       
  3474 #ifdef QDOC_QML        
       
  3475     case Node::Fake:
       
  3476         if (node->subType() != Node::QmlPropertyGroup)
       
  3477             break;
       
  3478     case Node::QmlProperty:
       
  3479 #endif        
       
  3480     case Node::Property:
       
  3481         ref = node->name() + "-prop";
       
  3482         break;
       
  3483 #ifdef QDOC_QML
       
  3484     case Node::QmlSignal:
       
  3485         ref = node->name() + "-signal";
       
  3486         break;
       
  3487     case Node::QmlMethod:
       
  3488         ref = node->name() + "-method";
       
  3489         break;
       
  3490 #endif        
       
  3491     case Node::Variable:
       
  3492         ref = node->name() + "-var";
       
  3493         break;
       
  3494     case Node::Target:
       
  3495         return protectEnc(node->name());
       
  3496     }
       
  3497     return registerRef(ref);
       
  3498 }
       
  3499 
       
  3500 QString DitaXmlGenerator::linkForNode(const Node *node, const Node *relative)
       
  3501 {
       
  3502     QString link;
       
  3503     QString fn;
       
  3504     QString ref;
       
  3505 
       
  3506     if (node == 0 || node == relative)
       
  3507         return QString();
       
  3508     if (!node->url().isEmpty())
       
  3509         return node->url();
       
  3510     if (fileBase(node).isEmpty())
       
  3511         return QString();
       
  3512     if (node->access() == Node::Private)
       
  3513         return QString();
       
  3514 
       
  3515     fn = fileName(node);
       
  3516     link += fn;
       
  3517 
       
  3518     if (!node->isInnerNode() || node->subType() == Node::QmlPropertyGroup) {
       
  3519         ref = refForNode(node);
       
  3520         if (relative && fn == fileName(relative) && ref == refForNode(relative))
       
  3521             return QString();
       
  3522 
       
  3523         link += "#";
       
  3524         link += ref;
       
  3525     }
       
  3526     return link;
       
  3527 }
       
  3528 
       
  3529 QString DitaXmlGenerator::refForAtom(Atom *atom, const Node * /* node */)
       
  3530 {
       
  3531     if (atom->type() == Atom::SectionLeft) {
       
  3532         return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
       
  3533     }
       
  3534     else if (atom->type() == Atom::Target) {
       
  3535         return Doc::canonicalTitle(atom->string());
       
  3536     }
       
  3537     else {
       
  3538         return QString();
       
  3539     }
       
  3540 }
       
  3541 
       
  3542 void DitaXmlGenerator::generateFullName(const Node *apparentNode,
       
  3543                                      const Node *relative,
       
  3544                                      CodeMarker *marker,
       
  3545                                      const Node *actualNode)
       
  3546 {
       
  3547     if (actualNode == 0)
       
  3548         actualNode = apparentNode;
       
  3549     out() << "<xref href=\"" << linkForNode(actualNode, relative);
       
  3550     if (true || relative == 0 || relative->status() != actualNode->status()) {
       
  3551         switch (actualNode->status()) {
       
  3552         case Node::Obsolete:
       
  3553             out() << "\" class=\"obsolete";
       
  3554             break;
       
  3555         case Node::Compat:
       
  3556             out() << "\" class=\"compat";
       
  3557             break;
       
  3558         default:
       
  3559             ;
       
  3560         }
       
  3561     }
       
  3562     out() << "\">";
       
  3563     out() << protectEnc(fullName(apparentNode, relative, marker));
       
  3564     out() << "</xref>";
       
  3565 }
       
  3566 
       
  3567 void DitaXmlGenerator::generateDetailedMember(const Node *node,
       
  3568                                            const InnerNode *relative,
       
  3569                                            CodeMarker *marker)
       
  3570 {
       
  3571     const EnumNode *enume;
       
  3572 
       
  3573 #ifdef GENERATE_MAC_REFS    
       
  3574     generateMacRef(node, marker);
       
  3575 #endif    
       
  3576     if (node->type() == Node::Enum
       
  3577             && (enume = static_cast<const EnumNode *>(node))->flagsType()) {
       
  3578 #ifdef GENERATE_MAC_REFS    
       
  3579         generateMacRef(enume->flagsType(), marker);
       
  3580 #endif        
       
  3581         out() << "<h3 class=\"flags\">";
       
  3582         out() << "<a name=\"" + refForNode(node) + "\"></a>";
       
  3583         generateSynopsis(enume, relative, marker, CodeMarker::Detailed);
       
  3584         out() << "<br/>";
       
  3585         generateSynopsis(enume->flagsType(),
       
  3586                          relative,
       
  3587                          marker,
       
  3588                          CodeMarker::Detailed);
       
  3589         out() << "</h3>\n";
       
  3590     }
       
  3591     else {
       
  3592         out() << "<h3 class=\"fn\">";
       
  3593         out() << "<a name=\"" + refForNode(node) + "\"></a>";
       
  3594         generateSynopsis(node, relative, marker, CodeMarker::Detailed);
       
  3595         out() << "</h3>\n";
       
  3596     }
       
  3597 
       
  3598     generateStatus(node, marker);
       
  3599     generateBody(node, marker);
       
  3600     generateThreadSafeness(node, marker);
       
  3601     generateSince(node, marker);
       
  3602 
       
  3603     if (node->type() == Node::Property) {
       
  3604         const PropertyNode *property = static_cast<const PropertyNode *>(node);
       
  3605         Section section;
       
  3606 
       
  3607         section.members += property->getters();
       
  3608         section.members += property->setters();
       
  3609         section.members += property->resetters();
       
  3610 
       
  3611         if (!section.members.isEmpty()) {
       
  3612             out() << "<p><b>Access functions:</b></p>\n";
       
  3613             generateSectionList(section, node, marker, CodeMarker::Accessors);
       
  3614         }
       
  3615 
       
  3616         Section notifiers;
       
  3617         notifiers.members += property->notifiers();
       
  3618         
       
  3619         if (!notifiers.members.isEmpty()) {
       
  3620             out() << "<p><b>Notifier signal:</b></p>\n";
       
  3621             //out() << "<p>This signal is emitted when the property value is changed.</p>\n";
       
  3622             generateSectionList(notifiers, node, marker, CodeMarker::Accessors);
       
  3623         }
       
  3624     }
       
  3625     else if (node->type() == Node::Enum) {
       
  3626         const EnumNode *enume = static_cast<const EnumNode *>(node);
       
  3627         if (enume->flagsType()) {
       
  3628             out() << "<p>The " << protectEnc(enume->flagsType()->name())
       
  3629                   << " type is a typedef for "
       
  3630                   << "<xref href=\"qflags.html\">QFlags</xref>&lt;"
       
  3631                   << protectEnc(enume->name())
       
  3632                   << "&gt;. It stores an OR combination of "
       
  3633                   << protectEnc(enume->name())
       
  3634                   << " values.</p>\n";
       
  3635         }
       
  3636     }
       
  3637     generateAlsoList(node, marker);
       
  3638 }
       
  3639 
       
  3640 void DitaXmlGenerator::findAllClasses(const InnerNode *node)
       
  3641 {
       
  3642     NodeList::const_iterator c = node->childNodes().constBegin();
       
  3643     while (c != node->childNodes().constEnd()) {
       
  3644         if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) {
       
  3645             if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
       
  3646                 QString className = (*c)->name();
       
  3647                 if ((*c)->parent() &&
       
  3648                     (*c)->parent()->type() == Node::Namespace &&
       
  3649                     !(*c)->parent()->name().isEmpty())
       
  3650                     className = (*c)->parent()->name()+"::"+className;
       
  3651 
       
  3652                 if (!(static_cast<const ClassNode *>(*c))->hideFromMainList()) {
       
  3653                     if ((*c)->status() == Node::Compat) {
       
  3654                         compatClasses.insert(className, *c);
       
  3655                     }
       
  3656                     else if ((*c)->status() == Node::Obsolete) {
       
  3657                         obsoleteClasses.insert(className, *c);
       
  3658                     }
       
  3659                     else {
       
  3660                         nonCompatClasses.insert(className, *c);
       
  3661                         if ((*c)->status() == Node::Main)
       
  3662                             mainClasses.insert(className, *c);
       
  3663                     }
       
  3664                 }
       
  3665 
       
  3666                 QString moduleName = (*c)->moduleName();
       
  3667                 if (moduleName == "Qt3SupportLight") {
       
  3668                     moduleClassMap[moduleName].insert((*c)->name(), *c);
       
  3669                     moduleName = "Qt3Support";
       
  3670                 }
       
  3671                 if (!moduleName.isEmpty())
       
  3672                     moduleClassMap[moduleName].insert((*c)->name(), *c);
       
  3673 
       
  3674                 QString serviceName =
       
  3675                     (static_cast<const ClassNode *>(*c))->serviceName();
       
  3676                 if (!serviceName.isEmpty())
       
  3677                     serviceClasses.insert(serviceName, *c);
       
  3678             }
       
  3679             else if ((*c)->isInnerNode()) {
       
  3680                 findAllClasses(static_cast<InnerNode *>(*c));
       
  3681             }
       
  3682         }
       
  3683         ++c;
       
  3684     }
       
  3685 }
       
  3686 
       
  3687 /*!
       
  3688   For generating the "New Classes... in 4.6" section on the
       
  3689   What's New in 4.6" page.
       
  3690  */
       
  3691 void DitaXmlGenerator::findAllSince(const InnerNode *node)
       
  3692 {
       
  3693     NodeList::const_iterator child = node->childNodes().constBegin();
       
  3694     while (child != node->childNodes().constEnd()) {
       
  3695         QString sinceVersion = (*child)->since();
       
  3696         if (((*child)->access() != Node::Private) && !sinceVersion.isEmpty()) {
       
  3697             NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceVersion);
       
  3698             if (nsmap == newSinceMaps.end())
       
  3699                 nsmap = newSinceMaps.insert(sinceVersion,NodeMultiMap());
       
  3700             NewClassMaps::iterator ncmap = newClassMaps.find(sinceVersion);
       
  3701             if (ncmap == newClassMaps.end())
       
  3702                 ncmap = newClassMaps.insert(sinceVersion,NodeMap());
       
  3703             NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceVersion);
       
  3704             if (nqcmap == newQmlClassMaps.end())
       
  3705                 nqcmap = newQmlClassMaps.insert(sinceVersion,NodeMap());
       
  3706  
       
  3707             if ((*child)->type() == Node::Function) {
       
  3708                 FunctionNode *func = static_cast<FunctionNode *>(*child);
       
  3709                 if ((func->status() > Node::Obsolete) &&
       
  3710                     (func->metaness() != FunctionNode::Ctor) &&
       
  3711                     (func->metaness() != FunctionNode::Dtor)) {
       
  3712                     nsmap.value().insert(func->name(),(*child));
       
  3713                 }
       
  3714             }
       
  3715             else if ((*child)->url().isEmpty()) {
       
  3716                 if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
       
  3717                     QString className = (*child)->name();
       
  3718                     if ((*child)->parent() &&
       
  3719                         (*child)->parent()->type() == Node::Namespace &&
       
  3720                         !(*child)->parent()->name().isEmpty())
       
  3721                         className = (*child)->parent()->name()+"::"+className;
       
  3722                     nsmap.value().insert(className,(*child));
       
  3723                     ncmap.value().insert(className,(*child));
       
  3724                 }
       
  3725                 else if ((*child)->subType() == Node::QmlClass) {
       
  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                     nqcmap.value().insert(className,(*child));
       
  3733                 }
       
  3734             }
       
  3735             else {
       
  3736                 QString name = (*child)->name();
       
  3737                 if ((*child)->parent() &&
       
  3738                     (*child)->parent()->type() == Node::Namespace &&
       
  3739                     !(*child)->parent()->name().isEmpty())
       
  3740                     name = (*child)->parent()->name()+"::"+name;
       
  3741                 nsmap.value().insert(name,(*child));
       
  3742             }
       
  3743             if ((*child)->isInnerNode()) {
       
  3744                 findAllSince(static_cast<InnerNode *>(*child));
       
  3745             }
       
  3746         }
       
  3747         ++child;
       
  3748     }
       
  3749 }
       
  3750 
       
  3751 #if 0
       
  3752     const QRegExp versionSeparator("[\\-\\.]");
       
  3753     const int minorIndex = version.indexOf(versionSeparator);
       
  3754     const int patchIndex = version.indexOf(versionSeparator, minorIndex+1);
       
  3755     version = version.left(patchIndex);
       
  3756 #endif
       
  3757 
       
  3758 void DitaXmlGenerator::findAllFunctions(const InnerNode *node)
       
  3759 {
       
  3760     NodeList::ConstIterator c = node->childNodes().begin();
       
  3761     while (c != node->childNodes().end()) {
       
  3762         if ((*c)->access() != Node::Private) {
       
  3763             if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
       
  3764                 findAllFunctions(static_cast<const InnerNode *>(*c));
       
  3765             }
       
  3766             else if ((*c)->type() == Node::Function) {
       
  3767                 const FunctionNode *func = static_cast<const FunctionNode *>(*c);
       
  3768                 if ((func->status() > Node::Obsolete) &&
       
  3769                     (func->metaness() != FunctionNode::Ctor) &&
       
  3770                     (func->metaness() != FunctionNode::Dtor)) {
       
  3771                     funcIndex[(*c)->name()].insert(myTree->fullDocumentName((*c)->parent()), *c);
       
  3772                 }
       
  3773             }
       
  3774         }
       
  3775         ++c;
       
  3776     }
       
  3777 }
       
  3778 
       
  3779 void DitaXmlGenerator::findAllLegaleseTexts(const InnerNode *node)
       
  3780 {
       
  3781     NodeList::ConstIterator c = node->childNodes().begin();
       
  3782     while (c != node->childNodes().end()) {
       
  3783         if ((*c)->access() != Node::Private) {
       
  3784             if (!(*c)->doc().legaleseText().isEmpty())
       
  3785                 legaleseTexts.insertMulti((*c)->doc().legaleseText(), *c);
       
  3786             if ((*c)->isInnerNode())
       
  3787                 findAllLegaleseTexts(static_cast<const InnerNode *>(*c));
       
  3788         }
       
  3789         ++c;
       
  3790     }
       
  3791 }
       
  3792 
       
  3793 void DitaXmlGenerator::findAllNamespaces(const InnerNode *node)
       
  3794 {
       
  3795     NodeList::ConstIterator c = node->childNodes().begin();
       
  3796     while (c != node->childNodes().end()) {
       
  3797         if ((*c)->access() != Node::Private) {
       
  3798             if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
       
  3799                 findAllNamespaces(static_cast<const InnerNode *>(*c));
       
  3800                 if ((*c)->type() == Node::Namespace) {
       
  3801                     const NamespaceNode *nspace = static_cast<const NamespaceNode *>(*c);
       
  3802                     // Ensure that the namespace's name is not empty (the root
       
  3803                     // namespace has no name).
       
  3804                     if (!nspace->name().isEmpty()) {
       
  3805                         namespaceIndex.insert(nspace->name(), *c);
       
  3806                         QString moduleName = (*c)->moduleName();
       
  3807                         if (moduleName == "Qt3SupportLight") {
       
  3808                             moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
       
  3809                             moduleName = "Qt3Support";
       
  3810                         }
       
  3811                         if (!moduleName.isEmpty())
       
  3812                             moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
       
  3813                     }
       
  3814                 }
       
  3815             }
       
  3816         }
       
  3817         ++c;
       
  3818     }
       
  3819 }
       
  3820 
       
  3821 int DitaXmlGenerator::hOffset(const Node *node)
       
  3822 {
       
  3823     switch (node->type()) {
       
  3824     case Node::Namespace:
       
  3825     case Node::Class:
       
  3826         return 2;
       
  3827     case Node::Fake:
       
  3828         return 1;
       
  3829 #if 0        
       
  3830         if (node->doc().briefText().isEmpty())
       
  3831             return 1;
       
  3832         else
       
  3833             return 2;
       
  3834 #endif        
       
  3835     case Node::Enum:
       
  3836     case Node::Typedef:
       
  3837     case Node::Function:
       
  3838     case Node::Property:
       
  3839     default:
       
  3840         return 3;
       
  3841     }
       
  3842 }
       
  3843 
       
  3844 bool DitaXmlGenerator::isThreeColumnEnumValueTable(const Atom *atom)
       
  3845 {
       
  3846     while (atom != 0 && !(atom->type() == Atom::ListRight && atom->string() == ATOM_LIST_VALUE)) {
       
  3847         if (atom->type() == Atom::ListItemLeft && !matchAhead(atom, Atom::ListItemRight))
       
  3848             return true;
       
  3849         atom = atom->next();
       
  3850     }
       
  3851     return false;
       
  3852 }
       
  3853 
       
  3854 const Node *DitaXmlGenerator::findNodeForTarget(const QString &target,
       
  3855                                              const Node *relative,
       
  3856                                              CodeMarker *marker,
       
  3857                                              const Atom *atom)
       
  3858 {
       
  3859     const Node *node = 0;
       
  3860 
       
  3861     if (target.isEmpty()) {
       
  3862         node = relative;
       
  3863     }
       
  3864     else if (target.endsWith(".html")) {
       
  3865         node = myTree->root()->findNode(target, Node::Fake);
       
  3866     }
       
  3867     else if (marker) {
       
  3868         node = marker->resolveTarget(target, myTree, relative);
       
  3869         if (!node)
       
  3870             node = myTree->findFakeNodeByTitle(target);
       
  3871         if (!node && atom) {
       
  3872             node = myTree->findUnambiguousTarget(target,
       
  3873                 *const_cast<Atom**>(&atom));
       
  3874         }
       
  3875     }
       
  3876 
       
  3877     if (!node)
       
  3878         relative->doc().location().warning(tr("Cannot link to '%1'").arg(target));
       
  3879 
       
  3880     return node;
       
  3881 }
       
  3882 
       
  3883 const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node *node)
       
  3884 {
       
  3885     QPair<QString,QString> anchorPair;
       
  3886 
       
  3887     anchorPair.first = PageGenerator::fileName(node);
       
  3888     if (node->type() == Node::Fake) {
       
  3889         const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
       
  3890         anchorPair.second = fakeNode->title();
       
  3891     }
       
  3892 
       
  3893     return anchorPair;
       
  3894 }
       
  3895 
       
  3896 QString DitaXmlGenerator::getLink(const Atom *atom,
       
  3897                                const Node *relative,
       
  3898                                CodeMarker *marker,
       
  3899                                const Node** node)
       
  3900 {
       
  3901     QString link;
       
  3902     *node = 0;
       
  3903     inObsoleteLink = false;
       
  3904 
       
  3905     if (atom->string().contains(":") &&
       
  3906             (atom->string().startsWith("file:")
       
  3907              || atom->string().startsWith("http:")
       
  3908              || atom->string().startsWith("https:")
       
  3909              || atom->string().startsWith("ftp:")
       
  3910              || atom->string().startsWith("mailto:"))) {
       
  3911 
       
  3912         link = atom->string();
       
  3913     }
       
  3914     else {
       
  3915         QStringList path;
       
  3916         if (atom->string().contains('#')) {
       
  3917             path = atom->string().split('#');
       
  3918         }
       
  3919         else {
       
  3920             path.append(atom->string());
       
  3921         }
       
  3922 
       
  3923         Atom *targetAtom = 0;
       
  3924 
       
  3925         QString first = path.first().trimmed();
       
  3926         if (first.isEmpty()) {
       
  3927             *node = relative;
       
  3928         }
       
  3929         else if (first.endsWith(".html")) {
       
  3930             *node = myTree->root()->findNode(first, Node::Fake);
       
  3931         }
       
  3932         else {
       
  3933             *node = marker->resolveTarget(first, myTree, relative);
       
  3934             if (!*node) {
       
  3935                 *node = myTree->findFakeNodeByTitle(first);
       
  3936             }
       
  3937             if (!*node) {
       
  3938                 *node = myTree->findUnambiguousTarget(first, targetAtom);
       
  3939             }
       
  3940         }
       
  3941 
       
  3942         if (*node) {
       
  3943             if (!(*node)->url().isEmpty())
       
  3944                 return (*node)->url();
       
  3945             else
       
  3946                 path.removeFirst();
       
  3947         }
       
  3948         else {
       
  3949             *node = relative;
       
  3950         }
       
  3951 
       
  3952         if (*node) {
       
  3953             if ((*node)->status() == Node::Obsolete) {
       
  3954                 if (relative) {
       
  3955                     if (relative->parent() != *node) {
       
  3956                         if (relative->status() != Node::Obsolete) {
       
  3957                             bool porting = false;
       
  3958                             if (relative->type() == Node::Fake) {
       
  3959                                 const FakeNode* fake = static_cast<const FakeNode*>(relative);
       
  3960                                 if (fake->title().startsWith("Porting"))
       
  3961                                     porting = true;
       
  3962                             }
       
  3963                             QString name = marker->plainFullName(relative);
       
  3964                             if (!porting && !name.startsWith("Q3")) {
       
  3965                                 if (obsoleteLinks) {
       
  3966                                     relative->doc().location().warning(tr("Link to obsolete item '%1' in %2")
       
  3967                                                                        .arg(atom->string())
       
  3968                                                                        .arg(name));
       
  3969                                 }
       
  3970                                 inObsoleteLink = true;
       
  3971                             }
       
  3972                         }
       
  3973                     }
       
  3974                 }
       
  3975                 else {
       
  3976                     qDebug() << "Link to Obsolete entity"
       
  3977                              << (*node)->name() << "no relative";
       
  3978                 }
       
  3979             }
       
  3980 #if 0                    
       
  3981             else if ((*node)->status() == Node::Deprecated) {
       
  3982                 qDebug() << "Link to Deprecated entity";
       
  3983             }
       
  3984             else if ((*node)->status() == Node::Internal) {
       
  3985                 qDebug() << "Link to Internal entity";
       
  3986             }
       
  3987 #endif                
       
  3988         }
       
  3989 
       
  3990         while (!path.isEmpty()) {
       
  3991             targetAtom = myTree->findTarget(path.first(), *node);
       
  3992             if (targetAtom == 0)
       
  3993                 break;
       
  3994             path.removeFirst();
       
  3995         }
       
  3996 
       
  3997         if (path.isEmpty()) {
       
  3998             link = linkForNode(*node, relative);
       
  3999             if (*node && (*node)->subType() == Node::Image)
       
  4000                 link = "images/used-in-examples/" + link;
       
  4001             if (targetAtom)
       
  4002                 link += "#" + refForAtom(targetAtom, *node);
       
  4003         }
       
  4004     }
       
  4005     return link;
       
  4006 }
       
  4007 
       
  4008 void DitaXmlGenerator::generateIndex(const QString &fileBase,
       
  4009                                   const QString &url,
       
  4010                                   const QString &title)
       
  4011 {
       
  4012     myTree->generateIndex(outputDir() + "/" + fileBase + ".index", url, title);
       
  4013 }
       
  4014 
       
  4015 void DitaXmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
       
  4016 {
       
  4017     Text text;
       
  4018 
       
  4019     switch (node->status()) {
       
  4020     case Node::Obsolete:
       
  4021         if (node->isInnerNode())
       
  4022 	    Generator::generateStatus(node, marker);
       
  4023         break;
       
  4024     case Node::Compat:
       
  4025         if (node->isInnerNode()) {
       
  4026             text << Atom::ParaLeft
       
  4027                  << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
       
  4028                  << "This "
       
  4029                  << typeString(node)
       
  4030                  << " is part of the Qt 3 support library."
       
  4031                  << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
       
  4032                  << " It is provided to keep old source code working. "
       
  4033                  << "We strongly advise against "
       
  4034                  << "using it in new code. See ";
       
  4035 
       
  4036             const FakeNode *fakeNode = myTree->findFakeNodeByTitle("Porting To Qt 4");
       
  4037             Atom *targetAtom = 0;
       
  4038             if (fakeNode && node->type() == Node::Class) {
       
  4039                 QString oldName(node->name());
       
  4040                 targetAtom = myTree->findTarget(oldName.replace("3", ""),
       
  4041                                                 fakeNode);
       
  4042             }
       
  4043 
       
  4044             if (targetAtom) {
       
  4045                 text << Atom(Atom::Link, linkForNode(fakeNode, node) + "#" +
       
  4046                                          refForAtom(targetAtom, fakeNode));
       
  4047             }
       
  4048             else
       
  4049                 text << Atom(Atom::Link, "Porting to Qt 4");
       
  4050 
       
  4051             text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
       
  4052                  << Atom(Atom::String, "Porting to Qt 4")
       
  4053                  << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
       
  4054                  << " for more information."
       
  4055                  << Atom::ParaRight;
       
  4056         }
       
  4057         generateText(text, node, marker);
       
  4058         break;
       
  4059     default:
       
  4060         Generator::generateStatus(node, marker);
       
  4061     }
       
  4062 }
       
  4063 
       
  4064 #ifdef GENERATE_MAC_REFS    
       
  4065 /*
       
  4066   No longer valid.
       
  4067  */
       
  4068 void DitaXmlGenerator::generateMacRef(const Node *node, CodeMarker *marker)
       
  4069 {
       
  4070     if (!pleaseGenerateMacRef || marker == 0)
       
  4071         return;
       
  4072 
       
  4073     QStringList macRefs = marker->macRefsForNode(node);
       
  4074     foreach (const QString &macRef, macRefs)
       
  4075         out() << "<a name=\"" << "//apple_ref/" << macRef << "\"></a>\n";
       
  4076 }
       
  4077 #endif
       
  4078 
       
  4079 void DitaXmlGenerator::beginLink(const QString &link,
       
  4080                               const Node *node,
       
  4081                               const Node *relative,
       
  4082                               CodeMarker *marker)
       
  4083 {
       
  4084     Q_UNUSED(marker)
       
  4085     Q_UNUSED(relative)
       
  4086 
       
  4087     this->link = link;
       
  4088     if (link.isEmpty()) {
       
  4089         if (showBrokenLinks)
       
  4090             writer.writeStartElement("i");
       
  4091     }
       
  4092     else if (node == 0 || (relative != 0 &&
       
  4093                            node->status() == relative->status())) {
       
  4094         writer.writeStartElement("xref");
       
  4095         writer.writeAttribute("href",link);
       
  4096     }
       
  4097     else {
       
  4098         switch (node->status()) {
       
  4099         case Node::Obsolete:
       
  4100             writer.writeStartElement("xref");
       
  4101             writer.writeAttribute("href",link);
       
  4102             writer.writeAttribute("outputclass","obsolete");
       
  4103             break;
       
  4104         case Node::Compat:
       
  4105             writer.writeStartElement("xref");
       
  4106             writer.writeAttribute("href",link);
       
  4107             writer.writeAttribute("outputclass","compat");
       
  4108             break;
       
  4109         default:
       
  4110             writer.writeStartElement("xref");
       
  4111             writer.writeAttribute("href",link);
       
  4112         }
       
  4113     }
       
  4114     inLink = true;
       
  4115 }
       
  4116 
       
  4117 void DitaXmlGenerator::endLink()
       
  4118 {
       
  4119     if (inLink) {
       
  4120         if (link.isEmpty()) {
       
  4121             if (showBrokenLinks)
       
  4122                 writer.writeEndElement(); // i
       
  4123         }
       
  4124         else {
       
  4125             if (inObsoleteLink) {
       
  4126                 writer.writeStartElement("sup");
       
  4127                 writer.writeCharacters("(obsolete)");
       
  4128                 writer.writeEndElement(); // sup
       
  4129             }
       
  4130             writer.writeEndElement(); // xref
       
  4131         }
       
  4132     }
       
  4133     inLink = false;
       
  4134     inObsoleteLink = false;
       
  4135 }
       
  4136 
       
  4137 #ifdef QDOC_QML
       
  4138 
       
  4139 /*!
       
  4140   Generates the summary for the \a section. Only used for
       
  4141   sections of QML element documentation.
       
  4142 
       
  4143   Currently handles only the QML property group.
       
  4144  */
       
  4145 void DitaXmlGenerator::generateQmlSummary(const Section& section,
       
  4146                                        const Node *relative,
       
  4147                                        CodeMarker *marker)
       
  4148 {
       
  4149     if (!section.members.isEmpty()) {
       
  4150         NodeList::ConstIterator m;
       
  4151         int count = section.members.size();
       
  4152         bool twoColumn = false;
       
  4153         if (section.members.first()->type() == Node::QmlProperty) {
       
  4154             twoColumn = (count >= 5);
       
  4155         }
       
  4156         if (twoColumn)
       
  4157             out() << "<table class=\"qmlsummary\">\n";
       
  4158 			        if (++numTableRows % 2 == 1)
       
  4159 				out() << "<tr class=\"odd topAlign\">";
       
  4160 				else
       
  4161 				out() << "<tr class=\"even topAlign\">";
       
  4162             //      << "<tr><td class=\"topAlign\">";
       
  4163         out() << "<ul>\n";
       
  4164 
       
  4165         int row = 0;
       
  4166         m = section.members.begin();
       
  4167         while (m != section.members.end()) {
       
  4168             if (twoColumn && row == (int) (count + 1) / 2)
       
  4169                 out() << "</ul></td><td class=\"topAlign\"><ul>\n";
       
  4170             out() << "<li class=\"fn\">";
       
  4171             generateQmlItem(*m,relative,marker,true);
       
  4172             out() << "</li>\n";
       
  4173             row++;
       
  4174             ++m;
       
  4175         }
       
  4176         out() << "</ul>\n";
       
  4177         if (twoColumn)
       
  4178             out() << "</td></tr>\n</table>\n";
       
  4179     }
       
  4180 }
       
  4181 
       
  4182 /*!
       
  4183   Outputs the html detailed documentation for a section
       
  4184   on a QML element reference page.
       
  4185  */
       
  4186 void DitaXmlGenerator::generateDetailedQmlMember(const Node *node,
       
  4187                                               const InnerNode *relative,
       
  4188                                               CodeMarker *marker)
       
  4189 {
       
  4190     const QmlPropertyNode* qpn = 0;
       
  4191 #ifdef GENERATE_MAC_REFS    
       
  4192     generateMacRef(node, marker);
       
  4193 #endif    
       
  4194     out() << "<div class=\"qmlitem\">";
       
  4195     if (node->subType() == Node::QmlPropertyGroup) {
       
  4196         const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
       
  4197         NodeList::ConstIterator p = qpgn->childNodes().begin();
       
  4198         out() << "<div class=\"qmlproto\">";
       
  4199         out() << "<table class=\"qmlname\">";
       
  4200 
       
  4201         while (p != qpgn->childNodes().end()) {
       
  4202             if ((*p)->type() == Node::QmlProperty) {
       
  4203                 qpn = static_cast<const QmlPropertyNode*>(*p);
       
  4204                 
       
  4205 				if (++numTableRows % 2 == 1)
       
  4206 					out() << "<tr class=\"odd\">";
       
  4207 				else
       
  4208 					out() << "<tr class=\"even\">";
       
  4209 				
       
  4210 				out() << "<td><p>";
       
  4211                 //out() << "<tr><td>"; // old
       
  4212                 out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
       
  4213                 if (!qpn->isWritable(myTree))
       
  4214                     out() << "<span class=\"qmlreadonly\">read-only</span>";
       
  4215                 if (qpgn->isDefault())
       
  4216                     out() << "<span class=\"qmldefault\">default</span>";
       
  4217                 generateQmlItem(qpn, relative, marker, false);
       
  4218                 out() << "</td></tr>";
       
  4219             }
       
  4220             ++p;
       
  4221         }
       
  4222         out() << "</table>";
       
  4223         out() << "</div>";
       
  4224     }
       
  4225     else if (node->type() == Node::QmlSignal) {
       
  4226         const FunctionNode* qsn = static_cast<const FunctionNode*>(node);
       
  4227         out() << "<div class=\"qmlproto\">";
       
  4228         out() << "<table class=\"qmlname\">";
       
  4229         //out() << "<tr>";
       
  4230 		if (++numTableRows % 2 == 1)
       
  4231 			out() << "<tr class=\"odd\">";
       
  4232 		else
       
  4233 			out() << "<tr class=\"even\">";
       
  4234         out() << "<td><p>";
       
  4235         out() << "<a name=\"" + refForNode(qsn) + "\"></a>";
       
  4236         generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false);
       
  4237         //generateQmlItem(qsn,relative,marker,false);
       
  4238         out() << "</p></td></tr>";
       
  4239         out() << "</table>";
       
  4240         out() << "</div>";
       
  4241     }
       
  4242     else if (node->type() == Node::QmlMethod) {
       
  4243         const FunctionNode* qmn = static_cast<const FunctionNode*>(node);
       
  4244         out() << "<div class=\"qmlproto\">";
       
  4245         out() << "<table class=\"qmlname\">";
       
  4246         //out() << "<tr>";
       
  4247 		if (++numTableRows % 2 == 1)
       
  4248 			out() << "<tr class=\"odd\">";
       
  4249 		else
       
  4250 			out() << "<tr class=\"even\">";
       
  4251         out() << "<td><p>";
       
  4252         out() << "<a name=\"" + refForNode(qmn) + "\"></a>";
       
  4253         generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false);
       
  4254         out() << "</p></td></tr>";
       
  4255         out() << "</table>";
       
  4256         out() << "</div>";
       
  4257     }
       
  4258     out() << "<div class=\"qmldoc\">";
       
  4259     generateStatus(node, marker);
       
  4260     generateBody(node, marker);
       
  4261     generateThreadSafeness(node, marker);
       
  4262     generateSince(node, marker);
       
  4263     generateAlsoList(node, marker);
       
  4264     out() << "</div>";
       
  4265     out() << "</div>";
       
  4266 }
       
  4267 
       
  4268 /*!
       
  4269   Output the "Inherits" line for the QML element,
       
  4270   if there should be one.
       
  4271  */
       
  4272 void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* cn,
       
  4273                                         CodeMarker* marker)
       
  4274 {
       
  4275     if (cn && !cn->links().empty()) {
       
  4276         if (cn->links().contains(Node::InheritsLink)) {
       
  4277             QPair<QString,QString> linkPair;
       
  4278             linkPair = cn->links()[Node::InheritsLink];
       
  4279             QStringList strList(linkPair.first);
       
  4280             const Node* n = myTree->findNode(strList,Node::Fake);
       
  4281             if (n && n->subType() == Node::QmlClass) {
       
  4282                 const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
       
  4283                 out() << "<p class=\"centerAlign\">";
       
  4284                 Text text;
       
  4285                 text << "[Inherits ";
       
  4286                 text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
       
  4287                 text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
       
  4288                 text << Atom(Atom::String, linkPair.second);
       
  4289                 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
       
  4290                 text << "]";
       
  4291                 generateText(text, cn, marker);
       
  4292                 out() << "</p>";
       
  4293             }
       
  4294         }
       
  4295     }
       
  4296 }
       
  4297 
       
  4298 /*!
       
  4299   Output the "Inherit by" list for the QML element,
       
  4300   if it is inherited by any other elements.
       
  4301  */
       
  4302 void DitaXmlGenerator::generateQmlInheritedBy(const QmlClassNode* cn,
       
  4303                                            CodeMarker* marker)
       
  4304 {
       
  4305     if (cn) {
       
  4306         NodeList subs;
       
  4307         QmlClassNode::subclasses(cn->name(),subs);
       
  4308         if (!subs.isEmpty()) {
       
  4309             Text text;
       
  4310             text << Atom::ParaLeft << "Inherited by ";
       
  4311             appendSortedQmlNames(text,cn,subs,marker);
       
  4312             text << Atom::ParaRight;
       
  4313             generateText(text, cn, marker);
       
  4314         }
       
  4315     }
       
  4316 }
       
  4317 
       
  4318 /*!
       
  4319   Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]"
       
  4320   line for the QML element, if there should be one.
       
  4321 
       
  4322   If there is no class node, or if the class node status
       
  4323   is set to Node::Internal, do nothing. 
       
  4324  */
       
  4325 void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn,
       
  4326                                             CodeMarker* marker)
       
  4327 {
       
  4328     const ClassNode* cn = qcn->classNode();
       
  4329     if (cn && (cn->status() != Node::Internal)) {
       
  4330         out() << "<p class=\"centerAlign\">";
       
  4331         Text text;
       
  4332         text << "[";
       
  4333         text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
       
  4334         text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
       
  4335         text << Atom(Atom::String, qcn->name());
       
  4336         text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
       
  4337         text << " instantiates the C++ class ";
       
  4338         text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
       
  4339         text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
       
  4340         text << Atom(Atom::String, cn->name());
       
  4341         text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
       
  4342         text << "]";
       
  4343         generateText(text, qcn, marker);
       
  4344         out() << "</p>";
       
  4345     }
       
  4346 }
       
  4347 
       
  4348 /*!
       
  4349   Output the "[QmlGraphicsXxx is instantiated by QML element Xxx]"
       
  4350   line for the class, if there should be one.
       
  4351 
       
  4352   If there is no QML element, or if the class node status
       
  4353   is set to Node::Internal, do nothing. 
       
  4354  */
       
  4355 void DitaXmlGenerator::generateInstantiatedBy(const ClassNode* cn,
       
  4356                                            CodeMarker* marker)
       
  4357 {
       
  4358     if (cn &&  cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) {
       
  4359         const Node* n = myTree->root()->findNode(cn->qmlElement(),Node::Fake);
       
  4360         if (n && n->subType() == Node::QmlClass) {
       
  4361             out() << "<p class=\"centerAlign\">";
       
  4362             Text text;
       
  4363             text << "[";
       
  4364             text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
       
  4365             text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
       
  4366             text << Atom(Atom::String, cn->name());
       
  4367             text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
       
  4368             text << " is instantiated by QML element ";
       
  4369             text << Atom(Atom::LinkNode,CodeMarker::stringForNode(n));
       
  4370             text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
       
  4371             text << Atom(Atom::String, n->name());
       
  4372             text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
       
  4373             text << "]";
       
  4374             generateText(text, cn, marker);
       
  4375             out() << "</p>";
       
  4376         }
       
  4377     }
       
  4378 }
       
  4379 
       
  4380 /*!
       
  4381   Generate the <page> element for the given \a node using the \a writer.
       
  4382   Return true if a <page> element was written; otherwise return false.
       
  4383  */
       
  4384 bool DitaXmlGenerator::generatePageElement(QXmlStreamWriter& writer,
       
  4385                                         const Node* node,
       
  4386                                         CodeMarker* marker) const
       
  4387 {
       
  4388     if (node->pageType() == Node::NoPageType)
       
  4389         return false;
       
  4390     if (node->name().isEmpty())
       
  4391         return true;
       
  4392     if (node->access() == Node::Private)
       
  4393         return false;
       
  4394     if (!node->isInnerNode())
       
  4395         return false;
       
  4396 
       
  4397     QString title;
       
  4398     QString rawTitle;
       
  4399     QString fullTitle;
       
  4400     const InnerNode* inner = static_cast<const InnerNode*>(node);
       
  4401         
       
  4402     writer.writeStartElement("page");
       
  4403     QXmlStreamAttributes attributes;
       
  4404     QString t;
       
  4405     t.setNum(id++);
       
  4406     switch (node->type()) {
       
  4407     case Node::Fake:
       
  4408         {
       
  4409             const FakeNode* fake = static_cast<const FakeNode*>(node);
       
  4410             title = fake->fullTitle();
       
  4411             break;
       
  4412         }
       
  4413     case Node::Class:
       
  4414         {
       
  4415             title = node->name() + " Class Reference";
       
  4416             break;
       
  4417         }
       
  4418     case Node::Namespace:
       
  4419         {
       
  4420             rawTitle = marker->plainName(inner);
       
  4421             fullTitle = marker->plainFullName(inner);
       
  4422             title = rawTitle + " Namespace Reference";
       
  4423             break;
       
  4424         }
       
  4425     default:
       
  4426         title = node->name();
       
  4427         break;
       
  4428     }
       
  4429     writer.writeAttribute("id",t);
       
  4430     writer.writeStartElement("pageWords");
       
  4431     writer.writeCharacters(title);
       
  4432     if (!inner->pageKeywords().isEmpty()) {
       
  4433         const QStringList& w = inner->pageKeywords();
       
  4434         for (int i = 0; i < w.size(); ++i) {
       
  4435             writer.writeCharacters(" ");
       
  4436             writer.writeCharacters(w.at(i).toLocal8Bit().constData());
       
  4437         }
       
  4438     }
       
  4439     writer.writeEndElement();
       
  4440     writer.writeStartElement("pageTitle");
       
  4441     writer.writeCharacters(title);
       
  4442     writer.writeEndElement();
       
  4443     writer.writeStartElement("pageUrl");
       
  4444     writer.writeCharacters(PageGenerator::fileName(node));
       
  4445     writer.writeEndElement();
       
  4446     writer.writeStartElement("pageType");
       
  4447     switch (node->pageType()) {
       
  4448     case Node::ApiPage:
       
  4449         writer.writeCharacters("APIPage");
       
  4450         break;
       
  4451     case Node::ArticlePage:
       
  4452         writer.writeCharacters("Article");
       
  4453         break;
       
  4454     case Node::ExamplePage:
       
  4455         writer.writeCharacters("Example");
       
  4456         break;
       
  4457     default:
       
  4458         break;
       
  4459     }
       
  4460     writer.writeEndElement();
       
  4461     writer.writeEndElement();
       
  4462     return true;
       
  4463 }
       
  4464 
       
  4465 /*!
       
  4466   Traverse the tree recursively and generate the <keyword>
       
  4467   elements.
       
  4468  */
       
  4469 void DitaXmlGenerator::generatePageElements(QXmlStreamWriter& writer, const Node* node, CodeMarker* marker) const
       
  4470 {
       
  4471     if (generatePageElement(writer, node, marker)) {
       
  4472 
       
  4473         if (node->isInnerNode()) {
       
  4474             const InnerNode *inner = static_cast<const InnerNode *>(node);
       
  4475 
       
  4476             // Recurse to write an element for this child node and all its children.
       
  4477             foreach (const Node *child, inner->childNodes())
       
  4478                 generatePageElements(writer, child, marker);
       
  4479         }
       
  4480     }
       
  4481 }
       
  4482 
       
  4483 /*!
       
  4484   Outputs the file containing the index used for searching the html docs.
       
  4485  */
       
  4486 void DitaXmlGenerator::generatePageIndex(const QString& fileName, CodeMarker* marker) const
       
  4487 {
       
  4488     QFile file(fileName);
       
  4489     if (!file.open(QFile::WriteOnly | QFile::Text))
       
  4490         return ;
       
  4491 
       
  4492     QXmlStreamWriter writer(&file);
       
  4493     writer.setAutoFormatting(true);
       
  4494     writer.writeStartDocument();
       
  4495     writer.writeStartElement("qtPageIndex");
       
  4496 
       
  4497     generatePageElements(writer, myTree->root(), marker);
       
  4498 
       
  4499     writer.writeEndElement(); // qtPageIndex
       
  4500     writer.writeEndDocument();
       
  4501     file.close();
       
  4502 }
       
  4503 
       
  4504 #endif
       
  4505 
       
  4506 /*!
       
  4507   Return the full qualification of the node \a n, but without
       
  4508   the name of \a n itself. e.g. A::B::C
       
  4509  */
       
  4510 QString DitaXmlGenerator::fullQualification(const Node* n)
       
  4511 {
       
  4512     QString fq;
       
  4513     InnerNode* in = n->parent();
       
  4514     while (in) {
       
  4515         if ((in->type() == Node::Class) ||
       
  4516             (in->type() == Node::Namespace)) {
       
  4517             if (in->name().isEmpty())
       
  4518                 break;
       
  4519             if (fq.isEmpty())
       
  4520                 fq = in->name();
       
  4521             else
       
  4522                 fq = in->name() + "::" + fq;
       
  4523         }
       
  4524         else
       
  4525             break;
       
  4526         in = in->parent();
       
  4527     }
       
  4528     return fq;
       
  4529 }
       
  4530 
       
  4531 void DitaXmlGenerator::writeDerivations(const ClassNode* cn, CodeMarker* marker)
       
  4532 {
       
  4533     QList<RelatedClass>::ConstIterator r;
       
  4534     int index;
       
  4535 
       
  4536     if (!cn->baseClasses().isEmpty()) {
       
  4537         writer.writeStartElement(CXXCLASSDERIVATIONS);
       
  4538         r = cn->baseClasses().begin();
       
  4539         index = 0;
       
  4540         while (r != cn->baseClasses().end()) {
       
  4541             writer.writeStartElement(CXXCLASSDERIVATION);
       
  4542             writer.writeStartElement(CXXCLASSDERIVATIONACCESSSPECIFIER);
       
  4543             writer.writeAttribute("value",(*r).accessString());
       
  4544             writer.writeEndElement(); // </cxxClassDerivationAccessSpecifier>
       
  4545             writer.writeStartElement(CXXCLASSBASECLASS);
       
  4546             writer.writeAttribute("href",(*r).node->ditaXmlHref());
       
  4547             writer.writeCharacters(marker->plainFullName((*r).node));
       
  4548             writer.writeEndElement(); // </cxxClassBaseClass>
       
  4549             writer.writeEndElement(); // </cxxClassDerivation>
       
  4550              ++r;
       
  4551         }
       
  4552         writer.writeEndElement(); // </cxxClassDerivations>
       
  4553      }
       
  4554 }
       
  4555 
       
  4556 void DitaXmlGenerator::writeLocation(const Node* n)
       
  4557 {
       
  4558     QString s1, s2, s3;
       
  4559     if (n->type() == Node::Class) {
       
  4560         s1 = CXXCLASSAPIITEMLOCATION;
       
  4561         s2 = CXXCLASSDECLARATIONFILE;
       
  4562         s3 = CXXCLASSDECLARATIONFILELINE;
       
  4563     }
       
  4564     else if (n->type() == Node::Function) {
       
  4565         s1 = CXXFUNCTIONAPIITEMLOCATION;
       
  4566         s2 = CXXFUNCTIONDECLARATIONFILE;
       
  4567         s3 = CXXFUNCTIONDECLARATIONFILELINE;
       
  4568     }
       
  4569     else if (n->type() == Node::Enum) {
       
  4570         s1 = CXXENUMERATIONAPIITEMLOCATION;
       
  4571         s2 = CXXENUMERATIONDECLARATIONFILE;
       
  4572         s3 = CXXENUMERATIONDECLARATIONFILELINE;
       
  4573     }
       
  4574     else if (n->type() == Node::Typedef) {
       
  4575         s1 = CXXTYPEDEFAPIITEMLOCATION;
       
  4576         s2 = CXXTYPEDEFDECLARATIONFILE;
       
  4577         s3 = CXXTYPEDEFDECLARATIONFILELINE;
       
  4578     }
       
  4579     else if ((n->type() == Node::Property) ||
       
  4580              (n->type() == Node::Variable)) {
       
  4581         s1 = CXXVARIABLEAPIITEMLOCATION;
       
  4582         s2 = CXXVARIABLEDECLARATIONFILE;
       
  4583         s3 = CXXVARIABLEDECLARATIONFILELINE;
       
  4584     }
       
  4585     writer.writeStartElement(s1);
       
  4586     writer.writeStartElement(s2);
       
  4587     writer.writeAttribute("name","filePath");
       
  4588     writer.writeAttribute("value",n->location().filePath());
       
  4589     writer.writeEndElement(); // </cxx<s2>DeclarationFile>
       
  4590     writer.writeStartElement(s3);
       
  4591     writer.writeAttribute("name","lineNumber");
       
  4592     QString lineNr;
       
  4593     writer.writeAttribute("value",lineNr.setNum(n->location().lineNo()));
       
  4594     writer.writeEndElement(); // </cxx<s3>DeclarationFileLine>
       
  4595     writer.writeEndElement(); // </cxx<s1>ApiItemLocation>
       
  4596 }
       
  4597 
       
  4598 void DitaXmlGenerator::writeFunctions(const Section& s, 
       
  4599                                       const ClassNode* cn, 
       
  4600                                       CodeMarker* marker)
       
  4601 {
       
  4602     NodeList::ConstIterator m = s.members.begin();
       
  4603     while (m != s.members.end()) {
       
  4604         if ((*m)->type() == Node::Function) {
       
  4605             FunctionNode* fn = const_cast<FunctionNode*>(static_cast<const FunctionNode*>(*m));
       
  4606             writer.writeStartElement(CXXFUNCTION);
       
  4607             writer.writeAttribute("id",fn->guid());
       
  4608             writer.writeStartElement(APINAME);
       
  4609             writer.writeCharacters(fn->name());
       
  4610             writer.writeEndElement(); // </apiName>
       
  4611             generateBrief(fn,marker);
       
  4612             writer.writeStartElement(CXXFUNCTIONDETAIL);
       
  4613             writer.writeStartElement(CXXFUNCTIONDEFINITION);
       
  4614             writer.writeStartElement(CXXFUNCTIONACCESSSPECIFIER);
       
  4615             writer.writeAttribute("value",fn->accessString());
       
  4616             writer.writeEndElement(); // <cxxFunctionAccessSpecifier>
       
  4617 
       
  4618             if (fn->isStatic()) {
       
  4619                 writer.writeStartElement(CXXFUNCTIONSTORAGECLASSSPECIFIERSTATIC);
       
  4620                 writer.writeAttribute("name","static");
       
  4621                 writer.writeAttribute("value","static");
       
  4622                 writer.writeEndElement(); // <cxxFunctionStorageClassSpecifierStatic>
       
  4623             }
       
  4624             
       
  4625             if (fn->isConst()) {
       
  4626                 writer.writeStartElement(CXXFUNCTIONCONST);
       
  4627                 writer.writeAttribute("name","const");
       
  4628                 writer.writeAttribute("value","const");
       
  4629                 writer.writeEndElement(); // <cxxFunctionConst>
       
  4630             }
       
  4631 
       
  4632             if (fn->virtualness() != FunctionNode::NonVirtual) {
       
  4633                 writer.writeStartElement(CXXFUNCTIONVIRTUAL);
       
  4634                 writer.writeAttribute("name","virtual");
       
  4635                 writer.writeAttribute("value","virtual");
       
  4636                 writer.writeEndElement(); // <cxxFunctionVirtual>
       
  4637                 if (fn->virtualness() == FunctionNode::PureVirtual) {
       
  4638                     writer.writeStartElement(CXXFUNCTIONPUREVIRTUAL);
       
  4639                     writer.writeAttribute("name","pure virtual");
       
  4640                     writer.writeAttribute("value","pure virtual");
       
  4641                     writer.writeEndElement(); // <cxxFunctionPureVirtual>
       
  4642                 }
       
  4643             }
       
  4644             
       
  4645             if (fn->name() == cn->name()) {
       
  4646                 writer.writeStartElement(CXXFUNCTIONCONSTRUCTOR);
       
  4647                 writer.writeAttribute("name","constructor");
       
  4648                 writer.writeAttribute("value","constructor");
       
  4649                 writer.writeEndElement(); // <cxxFunctionConstructor>
       
  4650             }
       
  4651             else if (fn->name()[0] == QChar('~')) {
       
  4652                 writer.writeStartElement(CXXFUNCTIONDESTRUCTOR);
       
  4653                 writer.writeAttribute("name","destructor");
       
  4654                 writer.writeAttribute("value","destructor");
       
  4655                 writer.writeEndElement(); // <cxxFunctionDestructor>
       
  4656             }
       
  4657             else {
       
  4658                 writer.writeStartElement(CXXFUNCTIONDECLAREDTYPE);
       
  4659                 writer.writeCharacters(fn->returnType());
       
  4660                 writer.writeEndElement(); // <cxxFunctionDeclaredType>
       
  4661             }
       
  4662             QString fq = fullQualification(fn);
       
  4663             if (!fq.isEmpty()) {
       
  4664                 writer.writeStartElement(CXXFUNCTIONSCOPEDNAME);
       
  4665                 writer.writeCharacters(fq);
       
  4666                 writer.writeEndElement(); // <cxxFunctionScopedName>
       
  4667             }
       
  4668             writer.writeStartElement(CXXFUNCTIONPROTOTYPE);
       
  4669             writer.writeCharacters(fn->signature(true));
       
  4670             writer.writeEndElement(); // <cxxFunctionPrototype>
       
  4671 
       
  4672             QString fnl = fn->signature(false);
       
  4673             int idx = fnl.indexOf(' ');
       
  4674             if (idx < 0)
       
  4675                 idx = 0;
       
  4676             else
       
  4677                 ++idx;
       
  4678             fnl = fn->parent()->name() + "::" + fnl.mid(idx);
       
  4679             writer.writeStartElement(CXXFUNCTIONNAMELOOKUP);
       
  4680             writer.writeCharacters(fnl);
       
  4681             writer.writeEndElement(); // <cxxFunctionNameLookup>
       
  4682 
       
  4683             if (fn->isReimp() && fn->reimplementedFrom() != 0) {
       
  4684                 FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom();
       
  4685                 writer.writeStartElement(CXXFUNCTIONREIMPLEMENTED);
       
  4686                 writer.writeAttribute("href",rfn->ditaXmlHref());
       
  4687                 writer.writeCharacters(marker->plainFullName(rfn));
       
  4688                 writer.writeEndElement(); // </cxxFunctionReimplemented>
       
  4689             }
       
  4690             writeParameters(fn,marker);
       
  4691             writeLocation(fn);
       
  4692             writer.writeEndElement(); // <cxxFunctionDefinition>
       
  4693             writer.writeStartElement(APIDESC);
       
  4694 
       
  4695             if (!fn->doc().isEmpty()) {
       
  4696                 generateBody(fn, marker);
       
  4697                 //        generateAlsoList(inner, marker);
       
  4698             }
       
  4699 
       
  4700             writer.writeEndElement(); // </apiDesc>
       
  4701             writer.writeEndElement(); // </cxxFunctionDetail>
       
  4702             writer.writeEndElement(); // </cxxFunction>
       
  4703 
       
  4704             if (fn->metaness() == FunctionNode::Ctor ||
       
  4705                 fn->metaness() == FunctionNode::Dtor ||
       
  4706                 fn->overloadNumber() != 1) {
       
  4707             }
       
  4708         }
       
  4709         ++m;
       
  4710     }
       
  4711 }
       
  4712 
       
  4713 void DitaXmlGenerator::writeParameters(const FunctionNode* fn, CodeMarker* marker)
       
  4714 {
       
  4715     const QList<Parameter>& parameters = fn->parameters();
       
  4716     if (!parameters.isEmpty()) {
       
  4717         writer.writeStartElement(CXXFUNCTIONPARAMETERS);
       
  4718         QList<Parameter>::ConstIterator p = parameters.begin();
       
  4719         while (p != parameters.end()) {
       
  4720             writer.writeStartElement(CXXFUNCTIONPARAMETER);
       
  4721             writer.writeStartElement(CXXFUNCTIONPARAMETERDECLAREDTYPE);
       
  4722             writer.writeCharacters((*p).leftType());
       
  4723             if (!(*p).rightType().isEmpty())
       
  4724                 writer.writeCharacters((*p).rightType());
       
  4725             writer.writeEndElement(); // <cxxFunctionParameterDeclaredType>
       
  4726             writer.writeStartElement(CXXFUNCTIONPARAMETERDECLARATIONNAME);
       
  4727             writer.writeCharacters((*p).name());
       
  4728             writer.writeEndElement(); // <cxxFunctionParameterDeclarationName>
       
  4729             if (!(*p).defaultValue().isEmpty()) {
       
  4730                 writer.writeStartElement(CXXFUNCTIONPARAMETERDEFAULTVALUE);
       
  4731                 writer.writeCharacters((*p).defaultValue());
       
  4732                 writer.writeEndElement(); // <cxxFunctionParameterDefaultValue>
       
  4733             }
       
  4734             writer.writeEndElement(); // <cxxFunctionParameter>
       
  4735             ++p;
       
  4736         }
       
  4737         writer.writeEndElement(); // <cxxFunctionParameters>
       
  4738     }
       
  4739 }
       
  4740 
       
  4741 void DitaXmlGenerator::writeEnumerations(const Section& s, 
       
  4742                                          const ClassNode* cn, 
       
  4743                                          CodeMarker* marker)
       
  4744 {
       
  4745     NodeList::ConstIterator m = s.members.begin();
       
  4746     while (m != s.members.end()) {
       
  4747         if ((*m)->type() == Node::Enum) {
       
  4748             const EnumNode* en = static_cast<const EnumNode*>(*m);
       
  4749             writer.writeStartElement(CXXENUMERATION);
       
  4750             writer.writeAttribute("id",en->guid());
       
  4751             writer.writeStartElement(APINAME);
       
  4752             writer.writeCharacters(en->name());
       
  4753             writer.writeEndElement(); // </apiName>
       
  4754             generateBrief(en,marker);
       
  4755             writer.writeStartElement(CXXENUMERATIONDETAIL);
       
  4756             writer.writeStartElement(CXXENUMERATIONDEFINITION);
       
  4757             writer.writeStartElement(CXXENUMERATIONACCESSSPECIFIER);
       
  4758             writer.writeAttribute("value",en->accessString());
       
  4759             writer.writeEndElement(); // <cxxEnumerationAccessSpecifier>
       
  4760 
       
  4761             QString fq = fullQualification(en);
       
  4762             if (!fq.isEmpty()) {
       
  4763                 writer.writeStartElement(CXXENUMERATIONSCOPEDNAME);
       
  4764                 writer.writeCharacters(fq);
       
  4765                 writer.writeEndElement(); // <cxxEnumerationScopedName>
       
  4766             }
       
  4767             const QList<EnumItem>& items = en->items();
       
  4768             if (!items.isEmpty()) {
       
  4769                 writer.writeStartElement(CXXENUMERATIONPROTOTYPE);
       
  4770                 writer.writeCharacters(en->name());
       
  4771                 writer.writeCharacters(" = { ");
       
  4772                 QList<EnumItem>::ConstIterator i = items.begin();
       
  4773                 while (i != items.end()) {
       
  4774                     writer.writeCharacters((*i).name());
       
  4775                     if (!(*i).value().isEmpty()) {
       
  4776                         writer.writeCharacters(" = ");
       
  4777                         writer.writeCharacters((*i).value());
       
  4778                     }
       
  4779                     ++i;
       
  4780                     if (i != items.end())
       
  4781                         writer.writeCharacters(", ");
       
  4782                 }
       
  4783                 writer.writeCharacters(" }");
       
  4784                 writer.writeEndElement(); // <cxxEnumerationPrototype>
       
  4785             }
       
  4786 
       
  4787             writer.writeStartElement(CXXENUMERATIONNAMELOOKUP);
       
  4788             writer.writeCharacters(en->parent()->name() + "::" + en->name());
       
  4789             writer.writeEndElement(); // <cxxEnumerationNameLookup>
       
  4790 
       
  4791             if (!items.isEmpty()) {
       
  4792                 writer.writeStartElement(CXXENUMERATORS);
       
  4793                 QList<EnumItem>::ConstIterator i = items.begin();
       
  4794                 while (i != items.end()) {
       
  4795                     writer.writeStartElement(CXXENUMERATOR);
       
  4796                     writer.writeStartElement(APINAME);
       
  4797                     writer.writeCharacters((*i).name());
       
  4798                     writer.writeEndElement(); // </apiName>
       
  4799 
       
  4800                     QString fq = fullQualification(en->parent());
       
  4801                     if (!fq.isEmpty()) {
       
  4802                         writer.writeStartElement(CXXENUMERATORSCOPEDNAME);
       
  4803                         writer.writeCharacters(fq + "::" + (*i).name());
       
  4804                         writer.writeEndElement(); // <cxxEnumeratorScopedName>
       
  4805                     }
       
  4806                     writer.writeStartElement(CXXENUMERATORPROTOTYPE);
       
  4807                     writer.writeCharacters((*i).name());
       
  4808                     writer.writeEndElement(); // <cxxEnumeratorPrototype>
       
  4809                     writer.writeStartElement(CXXENUMERATORNAMELOOKUP);
       
  4810                     writer.writeCharacters(en->parent()->name() + "::" + (*i).name());
       
  4811                     writer.writeEndElement(); // <cxxEnumeratorNameLookup>
       
  4812 
       
  4813                     if (!(*i).value().isEmpty()) {
       
  4814                         writer.writeStartElement(CXXENUMERATORINITIALISER);
       
  4815                         writer.writeAttribute("value", (*i).value());
       
  4816                         writer.writeEndElement(); // <cxxEnumeratorInitialiser>
       
  4817                     }
       
  4818                     if (!(*i).text().isEmpty()) {
       
  4819                         writer.writeStartElement(APIDESC);
       
  4820                         generateText((*i).text(), en, marker);
       
  4821                         writer.writeEndElement(); // </apiDesc>
       
  4822                     }
       
  4823                     writer.writeEndElement(); // <cxxEnumerator>
       
  4824                     ++i;
       
  4825                 }
       
  4826                 writer.writeEndElement(); // <cxxEnumerators>
       
  4827             }
       
  4828             
       
  4829             writeLocation(en);
       
  4830             writer.writeEndElement(); // <cxxEnumerationDefinition>
       
  4831             writer.writeStartElement(APIDESC);
       
  4832 
       
  4833             if (!en->doc().isEmpty()) {
       
  4834                 generateBody(en, marker);
       
  4835             }
       
  4836 
       
  4837             writer.writeEndElement(); // </apiDesc>
       
  4838             writer.writeEndElement(); // </cxxEnumerationDetail>
       
  4839             writer.writeEndElement(); // </cxxEnumeration>
       
  4840         }
       
  4841         ++m;
       
  4842     }
       
  4843 }
       
  4844 
       
  4845 void DitaXmlGenerator::writeTypedefs(const Section& s, 
       
  4846                                      const ClassNode* cn, 
       
  4847                                      CodeMarker* marker)
       
  4848 {
       
  4849     NodeList::ConstIterator m = s.members.begin();
       
  4850     while (m != s.members.end()) {
       
  4851         if ((*m)->type() == Node::Typedef) {
       
  4852             const TypedefNode* tn = static_cast<const TypedefNode*>(*m);
       
  4853             writer.writeStartElement(CXXTYPEDEF);
       
  4854             writer.writeAttribute("id",tn->guid());
       
  4855             writer.writeStartElement(APINAME);
       
  4856             writer.writeCharacters(tn->name());
       
  4857             writer.writeEndElement(); // </apiName>
       
  4858             generateBrief(tn,marker);
       
  4859             writer.writeStartElement(CXXTYPEDEFDETAIL);
       
  4860             writer.writeStartElement(CXXTYPEDEFDEFINITION);
       
  4861             writer.writeStartElement(CXXTYPEDEFACCESSSPECIFIER);
       
  4862             writer.writeAttribute("value",tn->accessString());
       
  4863             writer.writeEndElement(); // <cxxTypedefAccessSpecifier>
       
  4864 
       
  4865             QString fq = fullQualification(tn);
       
  4866             if (!fq.isEmpty()) {
       
  4867                 writer.writeStartElement(CXXTYPEDEFSCOPEDNAME);
       
  4868                 writer.writeCharacters(fq);
       
  4869                 writer.writeEndElement(); // <cxxTypedefScopedName>
       
  4870             }
       
  4871             writer.writeStartElement(CXXTYPEDEFNAMELOOKUP);
       
  4872             writer.writeCharacters(tn->parent()->name() + "::" + tn->name());
       
  4873             writer.writeEndElement(); // <cxxTypedefNameLookup>
       
  4874             
       
  4875             writeLocation(tn);
       
  4876             writer.writeEndElement(); // <cxxTypedefDefinition>
       
  4877             writer.writeStartElement(APIDESC);
       
  4878 
       
  4879             if (!tn->doc().isEmpty()) {
       
  4880                 generateBody(tn, marker);
       
  4881             }
       
  4882 
       
  4883             writer.writeEndElement(); // </apiDesc>
       
  4884             writer.writeEndElement(); // </cxxTypedefDetail>
       
  4885             writer.writeEndElement(); // </cxxTypedef>
       
  4886         }
       
  4887         ++m;
       
  4888     }
       
  4889 }
       
  4890 
       
  4891 void DitaXmlGenerator::writeProperties(const Section& s, 
       
  4892                                        const ClassNode* cn, 
       
  4893                                        CodeMarker* marker)
       
  4894 {
       
  4895     NodeList::ConstIterator m = s.members.begin();
       
  4896     while (m != s.members.end()) {
       
  4897         if ((*m)->type() == Node::Property) {
       
  4898             const PropertyNode* pn = static_cast<const PropertyNode*>(*m);
       
  4899             writer.writeStartElement(CXXVARIABLE);
       
  4900             writer.writeAttribute("id",pn->guid());
       
  4901             writer.writeStartElement(APINAME);
       
  4902             writer.writeCharacters(pn->name());
       
  4903             writer.writeEndElement(); // </apiName>
       
  4904             generateBrief(pn,marker);
       
  4905             writer.writeStartElement(CXXVARIABLEDETAIL);
       
  4906             writer.writeStartElement(CXXVARIABLEDEFINITION);
       
  4907             writer.writeStartElement(CXXVARIABLEACCESSSPECIFIER);
       
  4908             writer.writeAttribute("value",pn->accessString());
       
  4909             writer.writeEndElement(); // <cxxVariableAccessSpecifier>
       
  4910 
       
  4911             if (!pn->qualifiedDataType().isEmpty()) {
       
  4912                 writer.writeStartElement(CXXVARIABLEDECLAREDTYPE);
       
  4913                 writer.writeCharacters(pn->qualifiedDataType());
       
  4914                 writer.writeEndElement(); // <cxxVariableDeclaredType>
       
  4915             }
       
  4916             QString fq = fullQualification(pn);
       
  4917             if (!fq.isEmpty()) {
       
  4918                 writer.writeStartElement(CXXVARIABLESCOPEDNAME);
       
  4919                 writer.writeCharacters(fq);
       
  4920                 writer.writeEndElement(); // <cxxVariableScopedName>
       
  4921             }
       
  4922             
       
  4923             writer.writeStartElement(CXXVARIABLEPROTOTYPE);
       
  4924             writer.writeCharacters("Q_PROPERTY(");
       
  4925             writer.writeCharacters(pn->qualifiedDataType());
       
  4926             writer.writeCharacters(" ");
       
  4927             writer.writeCharacters(pn->name());
       
  4928             writePropParams("READ",pn->getters());
       
  4929             writePropParams("WRITE",pn->setters());
       
  4930             writePropParams("RESET",pn->resetters());
       
  4931             writePropParams("NOTIFY",pn->notifiers());
       
  4932             if (pn->isDesignable() != pn->designableDefault()) {
       
  4933                 writer.writeCharacters(" DESIGNABLE ");
       
  4934                 if (!pn->runtimeDesignabilityFunction().isEmpty())
       
  4935                     writer.writeCharacters(pn->runtimeDesignabilityFunction());
       
  4936                 else
       
  4937                     writer.writeCharacters(pn->isDesignable() ? "true" : "false");
       
  4938             }
       
  4939             if (pn->isScriptable() != pn->scriptableDefault()) {
       
  4940                 writer.writeCharacters(" SCRIPTABLE ");
       
  4941                 if (!pn->runtimeScriptabilityFunction().isEmpty())
       
  4942                     writer.writeCharacters(pn->runtimeScriptabilityFunction());
       
  4943                 else
       
  4944                     writer.writeCharacters(pn->isScriptable() ? "true" : "false");
       
  4945             }
       
  4946             if (pn->isWritable() != pn->writableDefault()) {
       
  4947                 writer.writeCharacters(" STORED ");
       
  4948                 writer.writeCharacters(pn->isStored() ? "true" : "false");
       
  4949             }
       
  4950             if (pn->isUser() != pn->userDefault()) {
       
  4951                 writer.writeCharacters(" USER ");
       
  4952                 writer.writeCharacters(pn->isUser() ? "true" : "false");
       
  4953             }
       
  4954             if (pn->isConstant())
       
  4955                 writer.writeCharacters(" CONSTANT");
       
  4956             if (pn->isFinal())
       
  4957                 writer.writeCharacters(" FINAL");
       
  4958             writer.writeCharacters(")");
       
  4959             writer.writeEndElement(); // <cxxVariablePrototype>
       
  4960 
       
  4961             writer.writeStartElement(CXXVARIABLENAMELOOKUP);
       
  4962             writer.writeCharacters(pn->parent()->name() + "::" + pn->name());
       
  4963             writer.writeEndElement(); // <cxxVariableNameLookup>
       
  4964 
       
  4965             if (pn->overriddenFrom() != 0) {
       
  4966                 PropertyNode* opn = (PropertyNode*)pn->overriddenFrom();
       
  4967                 writer.writeStartElement(CXXVARIABLEREIMPLEMENTED);
       
  4968                 writer.writeAttribute("href",opn->ditaXmlHref());
       
  4969                 writer.writeCharacters(marker->plainFullName(opn));
       
  4970                 writer.writeEndElement(); // </cxxVariableReimplemented>
       
  4971             }
       
  4972 
       
  4973             writeLocation(pn);
       
  4974             writer.writeEndElement(); // <cxxVariableDefinition>
       
  4975             writer.writeStartElement(APIDESC);
       
  4976 
       
  4977             if (!pn->doc().isEmpty()) {
       
  4978                 generateBody(pn, marker);
       
  4979             }
       
  4980 
       
  4981             writer.writeEndElement(); // </apiDesc>
       
  4982             writer.writeEndElement(); // </cxxVariableDetail>
       
  4983             writer.writeEndElement(); // </cxxVariable>
       
  4984         }
       
  4985         ++m;
       
  4986     }
       
  4987 }
       
  4988 
       
  4989 void DitaXmlGenerator::writeDataMembers(const Section& s, 
       
  4990                                         const ClassNode* cn, 
       
  4991                                         CodeMarker* marker)
       
  4992 {
       
  4993     NodeList::ConstIterator m = s.members.begin();
       
  4994     while (m != s.members.end()) {
       
  4995         if ((*m)->type() == Node::Variable) {
       
  4996             const VariableNode* vn = static_cast<const VariableNode*>(*m);
       
  4997             writer.writeStartElement(CXXVARIABLE);
       
  4998             writer.writeAttribute("id",vn->guid());
       
  4999             writer.writeStartElement(APINAME);
       
  5000             writer.writeCharacters(vn->name());
       
  5001             writer.writeEndElement(); // </apiName>
       
  5002             generateBrief(vn,marker);
       
  5003             writer.writeStartElement(CXXVARIABLEDETAIL);
       
  5004             writer.writeStartElement(CXXVARIABLEDEFINITION);
       
  5005             writer.writeStartElement(CXXVARIABLEACCESSSPECIFIER);
       
  5006             writer.writeAttribute("value",vn->accessString());
       
  5007             writer.writeEndElement(); // <cxxVariableAccessSpecifier>
       
  5008 
       
  5009             if (vn->isStatic()) {
       
  5010                 writer.writeStartElement(CXXVARIABLESTORAGECLASSSPECIFIERSTATIC);
       
  5011                 writer.writeAttribute("name","static");
       
  5012                 writer.writeAttribute("value","static");
       
  5013                 writer.writeEndElement(); // <cxxVariableStorageClassSpecifierStatic>
       
  5014             }
       
  5015 
       
  5016             writer.writeStartElement(CXXVARIABLEDECLAREDTYPE);
       
  5017             writer.writeCharacters(vn->leftType());
       
  5018             if (!vn->rightType().isEmpty())
       
  5019                 writer.writeCharacters(vn->rightType());
       
  5020             writer.writeEndElement(); // <cxxVariableDeclaredType>
       
  5021 
       
  5022             QString fq = fullQualification(vn);
       
  5023             if (!fq.isEmpty()) {
       
  5024                 writer.writeStartElement(CXXVARIABLESCOPEDNAME);
       
  5025                 writer.writeCharacters(fq);
       
  5026                 writer.writeEndElement(); // <cxxVariableScopedName>
       
  5027             }
       
  5028             
       
  5029             writer.writeStartElement(CXXVARIABLEPROTOTYPE);
       
  5030             writer.writeCharacters(vn->leftType() + " ");
       
  5031             //writer.writeCharacters(vn->parent()->name() + "::" + vn->name()); 
       
  5032             writer.writeCharacters(vn->name()); 
       
  5033             if (!vn->rightType().isEmpty())
       
  5034                 writer.writeCharacters(vn->rightType());
       
  5035             writer.writeEndElement(); // <cxxVariablePrototype>
       
  5036 
       
  5037             writer.writeStartElement(CXXVARIABLENAMELOOKUP);
       
  5038             writer.writeCharacters(vn->parent()->name() + "::" + vn->name());
       
  5039             writer.writeEndElement(); // <cxxVariableNameLookup>
       
  5040 
       
  5041             writeLocation(vn);
       
  5042             writer.writeEndElement(); // <cxxVariableDefinition>
       
  5043             writer.writeStartElement(APIDESC);
       
  5044 
       
  5045             if (!vn->doc().isEmpty()) {
       
  5046                 generateBody(vn, marker);
       
  5047             }
       
  5048 
       
  5049             writer.writeEndElement(); // </apiDesc>
       
  5050             writer.writeEndElement(); // </cxxVariableDetail>
       
  5051             writer.writeEndElement(); // </cxxVariable>
       
  5052         }
       
  5053         ++m;
       
  5054     }
       
  5055 }
       
  5056 
       
  5057 void DitaXmlGenerator::writeMacros(const Section& s, 
       
  5058                                    const ClassNode* cn, 
       
  5059                                    CodeMarker* marker)
       
  5060 {
       
  5061     NodeList::ConstIterator m = s.members.begin();
       
  5062     while (m != s.members.end()) {
       
  5063         if ((*m)->type() == Node::Function) {
       
  5064             const FunctionNode* fn = static_cast<const FunctionNode*>(*m);
       
  5065             if (fn->isMacro()) {
       
  5066                 writer.writeStartElement(CXXDEFINE);
       
  5067                 writer.writeAttribute("id",fn->guid());
       
  5068                 writer.writeStartElement(APINAME);
       
  5069                 writer.writeCharacters(fn->name());
       
  5070                 writer.writeEndElement(); // </apiName>
       
  5071                 generateBrief(fn,marker);
       
  5072                 writer.writeStartElement(CXXDEFINEDETAIL);
       
  5073                 writer.writeStartElement(CXXDEFINEDEFINITION);
       
  5074                 writer.writeStartElement(CXXDEFINEACCESSSPECIFIER);
       
  5075                 writer.writeAttribute("value",fn->accessString());
       
  5076                 writer.writeEndElement(); // <cxxDefineAccessSpecifier>
       
  5077             
       
  5078                 writer.writeStartElement(CXXDEFINEPROTOTYPE);
       
  5079                 writer.writeCharacters("#define ");
       
  5080                 writer.writeCharacters(fn->name());
       
  5081                 if (fn->metaness() == FunctionNode::MacroWithParams) {
       
  5082                     QStringList params = fn->parameterNames();
       
  5083                     if (!params.isEmpty()) {
       
  5084                         writer.writeCharacters("(");
       
  5085                         for (int i = 0; i < params.size(); ++i) {
       
  5086                             if (params[i].isEmpty())
       
  5087                                 writer.writeCharacters("...");
       
  5088                             else
       
  5089                                 writer.writeCharacters(params[i]);
       
  5090                             if ((i+1) < params.size()) 
       
  5091                                 writer.writeCharacters(", ");
       
  5092                         }
       
  5093                         writer.writeCharacters(")");
       
  5094                     }
       
  5095                 }
       
  5096                 writer.writeEndElement(); // <cxxDefinePrototype>
       
  5097 
       
  5098                 writer.writeStartElement(CXXDEFINENAMELOOKUP);
       
  5099                 writer.writeCharacters(fn->name());
       
  5100                 writer.writeEndElement(); // <cxxDefineNameLookup>
       
  5101 
       
  5102                 if (fn->reimplementedFrom() != 0) {
       
  5103                     FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom();
       
  5104                     writer.writeStartElement(CXXDEFINEREIMPLEMENTED);
       
  5105                     writer.writeAttribute("href",rfn->ditaXmlHref());
       
  5106                     writer.writeCharacters(marker->plainFullName(rfn));
       
  5107                     writer.writeEndElement(); // </cxxDefineReimplemented>
       
  5108                 }
       
  5109 
       
  5110                 if (fn->metaness() == FunctionNode::MacroWithParams) {
       
  5111                     QStringList params = fn->parameterNames();
       
  5112                     if (!params.isEmpty()) {
       
  5113                         writer.writeStartElement(CXXDEFINEPARAMETERS);
       
  5114                         for (int i = 0; i < params.size(); ++i) {
       
  5115                             writer.writeStartElement(CXXDEFINEPARAMETER);
       
  5116                             writer.writeStartElement(CXXDEFINEPARAMETERDECLARATIONNAME);
       
  5117                             writer.writeCharacters(params[i]);
       
  5118                             writer.writeEndElement(); // <cxxDefineParameterDeclarationName>
       
  5119                             writer.writeEndElement(); // <cxxDefineParameter>
       
  5120                         }
       
  5121                         writer.writeEndElement(); // <cxxDefineParameters>
       
  5122                     }
       
  5123                 }
       
  5124 
       
  5125                 writeLocation(fn);
       
  5126                 writer.writeEndElement(); // <cxxDefineDefinition>
       
  5127                 writer.writeStartElement(APIDESC);
       
  5128 
       
  5129                 if (!fn->doc().isEmpty()) {
       
  5130                     generateBody(fn, marker);
       
  5131                 }
       
  5132 
       
  5133                 writer.writeEndElement(); // </apiDesc>
       
  5134                 writer.writeEndElement(); // </cxxDefineDetail>
       
  5135                 writer.writeEndElement(); // </cxxDefine>
       
  5136             }
       
  5137         }
       
  5138         ++m;
       
  5139     }
       
  5140 }
       
  5141 
       
  5142 void DitaXmlGenerator::writePropParams(const QString& tag, const NodeList& nlist)
       
  5143 {
       
  5144     NodeList::const_iterator n = nlist.begin();
       
  5145     while (n != nlist.end()) {
       
  5146         writer.writeCharacters(" ");
       
  5147         writer.writeCharacters(tag);
       
  5148         writer.writeCharacters(" ");
       
  5149         writer.writeCharacters((*n)->name());
       
  5150         ++n;
       
  5151     }
       
  5152 }
       
  5153 
       
  5154 QT_END_NAMESPACE