~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to tools/qdoc3/htmlgenerator.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/****************************************************************************
2
2
**
3
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
4
5
** Contact: Nokia Corporation (qt-info@nokia.com)
5
6
**
6
7
** This file is part of the tools applications of the Qt Toolkit.
7
8
**
8
9
** $QT_BEGIN_LICENSE:LGPL$
9
 
** Commercial Usage
10
 
** Licensees holding valid Qt Commercial licenses may use this file in
11
 
** accordance with the Qt Commercial License Agreement provided with the
12
 
** Software or, alternatively, in accordance with the terms contained in
13
 
** a written agreement between you and Nokia.
 
10
** No Commercial Usage
 
11
** This file contains pre-release code and may not be distributed.
 
12
** You may use this file in accordance with the terms and conditions
 
13
** contained in the Technology Preview License Agreement accompanying
 
14
** this package.
14
15
**
15
16
** GNU Lesser General Public License Usage
16
17
** Alternatively, this file may be used under the terms of the GNU Lesser
20
21
** ensure the GNU Lesser General Public License version 2.1 requirements
21
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22
23
**
23
 
** In addition, as a special exception, Nokia gives you certain
24
 
** additional rights. These rights are described in the Nokia Qt LGPL
25
 
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26
 
** package.
27
 
**
28
 
** GNU General Public License Usage
29
 
** Alternatively, this file may be used under the terms of the GNU
30
 
** General Public License version 3.0 as published by the Free Software
31
 
** Foundation and appearing in the file LICENSE.GPL included in the
32
 
** packaging of this file.  Please review the following information to
33
 
** ensure the GNU General Public License version 3.0 requirements will be
34
 
** met: http://www.gnu.org/copyleft/gpl.html.
35
 
**
36
 
** If you are unsure which license is appropriate for your use, please
37
 
** contact the sales department at http://www.qtsoftware.com/contact.
 
24
** In addition, as a special exception, Nokia gives you certain additional
 
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
 
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
27
**
 
28
** If you have questions regarding the use of this file, please contact
 
29
** Nokia at qt-info@nokia.com.
 
30
**
 
31
**
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
38
38
** $QT_END_LICENSE$
39
39
**
40
40
****************************************************************************/
61
61
 
62
62
static bool showBrokenLinks = false;
63
63
 
 
64
static QRegExp linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
 
65
static QRegExp funcTag("(<@func target=\"([^\"]*)\">)(.*)(</@func>)");
 
66
static QRegExp typeTag("(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)");
 
67
static QRegExp spanTag("</@(?:comment|preprocessor|string|char)>");
 
68
static QRegExp unknownTag("</?@[^>]*>");
 
69
 
 
70
bool parseArg(const QString &src,
 
71
              const QString &tag,
 
72
              int *pos,
 
73
              int n,
 
74
              QStringRef *contents,
 
75
              QStringRef *par1 = 0,
 
76
              bool debug = false)
 
77
{
 
78
#define SKIP_CHAR(c) \
 
79
    if (debug) \
 
80
        qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
 
81
    if (i >= n || src[i] != c) { \
 
82
        if (debug) \
 
83
            qDebug() << " char '" << c << "' not found"; \
 
84
        return false; \
 
85
    } \
 
86
    ++i;
 
87
 
 
88
 
 
89
#define SKIP_SPACE \
 
90
    while (i < n && src[i] == ' ') \
 
91
        ++i;
 
92
 
 
93
    int i = *pos;
 
94
    int j = i;
 
95
 
 
96
    // assume "<@" has been parsed outside
 
97
    //SKIP_CHAR('<');
 
98
    //SKIP_CHAR('@');
 
99
 
 
100
    if (tag != QStringRef(&src, i, tag.length())) {
 
101
        if (0 && debug)
 
102
            qDebug() << "tag " << tag << " not found at " << i;
 
103
        return false;
 
104
    }
 
105
 
 
106
    if (debug)
 
107
        qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
 
108
 
 
109
    // skip tag
 
110
    i += tag.length();
 
111
 
 
112
    // parse stuff like:  linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
 
113
    if (par1) {
 
114
        SKIP_SPACE;
 
115
        // read parameter name
 
116
        j = i;
 
117
        while (i < n && src[i].isLetter())
 
118
            ++i;
 
119
        if (src[i] == '=') {
 
120
            if (debug)
 
121
                qDebug() << "read parameter" << QString(src.data() + j, i - j);
 
122
            SKIP_CHAR('=');
 
123
            SKIP_CHAR('"');
 
124
            // skip parameter name
 
125
            j = i;
 
126
            while (i < n && src[i] != '"')
 
127
                ++i;
 
128
            *par1 = QStringRef(&src, j, i - j);
 
129
            SKIP_CHAR('"');
 
130
            SKIP_SPACE;
 
131
        } else {
 
132
            if (debug)
 
133
                qDebug() << "no optional parameter found";
 
134
        }
 
135
    }
 
136
    SKIP_SPACE;
 
137
    SKIP_CHAR('>');
 
138
 
 
139
    // find contents up to closing "</@tag>
 
140
    j = i;
 
141
    for (; true; ++i) {
 
142
        if (i + 4 + tag.length() > n)
 
143
            return false;
 
144
        if (src[i] != '<')
 
145
            continue;
 
146
        if (src[i + 1] != '/')
 
147
            continue;
 
148
        if (src[i + 2] != '@')
 
149
            continue;
 
150
        if (tag != QStringRef(&src, i + 3, tag.length()))
 
151
            continue;
 
152
        if (src[i + 3 + tag.length()] != '>')
 
153
            continue;
 
154
        break;
 
155
    }
 
156
 
 
157
    *contents = QStringRef(&src, j, i - j);
 
158
 
 
159
    i += tag.length() + 4;
 
160
 
 
161
    *pos = i;
 
162
    if (debug)
 
163
        qDebug() << " tag " << tag << " found: pos now: " << i;
 
164
    return true;
 
165
#undef SKIP_CHAR
 
166
}
 
167
 
 
168
static void addLink(const QString &linkTarget,
 
169
                    const QStringRef &nestedStuff,
 
170
                    QString *res)
 
171
{
 
172
    if (!linkTarget.isEmpty()) {
 
173
        *res += "<a href=\"";
 
174
        *res += linkTarget;
 
175
        *res += "\">";
 
176
        *res += nestedStuff;
 
177
        *res += "</a>";
 
178
    }
 
179
    else {
 
180
        *res += nestedStuff;
 
181
    }
 
182
}
 
183
 
 
184
 
64
185
HtmlGenerator::HtmlGenerator()
65
186
    : helpProjectWriter(0), inLink(false), inContents(false),
66
187
      inSectionHeading(false), inTableHeader(false), numTableRows(0),
67
188
      threeColumnEnumValueTable(true), funcLeftParen("\\S(\\()"),
68
 
      tre(0), slow(false)
 
189
      tre(0), slow(false), obsoleteLinks(false)
69
190
{
70
191
}
71
192
 
94
215
    };
95
216
 
96
217
    Generator::initializeGenerator(config);
 
218
    obsoleteLinks = config.getBool(QLatin1String(CONFIG_OBSOLETELINKS));
97
219
    setImageFileExtensions(QStringList() << "png" << "jpg" << "jpeg" << "gif");
98
220
    int i = 0;
99
221
    while (defaults[i].key) {
102
224
        i++;
103
225
    }
104
226
 
105
 
    style = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLE);
106
 
    postHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTHEADER);
107
 
    footer = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_FOOTER);
108
 
    address = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_ADDRESS);
109
 
    pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_GENERATEMACREFS);
 
227
    style = config.getString(HtmlGenerator::format() +
 
228
                             Config::dot +
 
229
                             HTMLGENERATOR_STYLE);
 
230
    postHeader = config.getString(HtmlGenerator::format() +
 
231
                                  Config::dot +
 
232
                                  HTMLGENERATOR_POSTHEADER);
 
233
    footer = config.getString(HtmlGenerator::format() +
 
234
                              Config::dot +
 
235
                              HTMLGENERATOR_FOOTER);
 
236
    address = config.getString(HtmlGenerator::format() +
 
237
                               Config::dot +
 
238
                               HTMLGENERATOR_ADDRESS);
 
239
    pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() +
 
240
                                          Config::dot +
 
241
                                          HTMLGENERATOR_GENERATEMACREFS);
110
242
 
111
243
    project = config.getString(CONFIG_PROJECT);
112
244
 
120
252
    QSet<QString>::ConstIterator edition = editionNames.begin();
121
253
    while (edition != editionNames.end()) {
122
254
        QString editionName = *edition;
123
 
        QStringList editionModules = config.getStringList(
124
 
            CONFIG_EDITION + Config::dot + editionName + Config::dot + "modules");
125
 
        QStringList editionGroups = config.getStringList(
126
 
            CONFIG_EDITION + Config::dot + editionName + Config::dot + "groups");
 
255
        QStringList editionModules = config.getStringList(CONFIG_EDITION +
 
256
                                                          Config::dot +
 
257
                                                          editionName +
 
258
                                                          Config::dot +
 
259
                                                          "modules");
 
260
        QStringList editionGroups = config.getStringList(CONFIG_EDITION +
 
261
                                                         Config::dot +
 
262
                                                         editionName +
 
263
                                                         Config::dot +
 
264
                                                         "groups");
127
265
 
128
266
        if (!editionModules.isEmpty())
129
267
            editionModuleMap[editionName] = editionModules;
135
273
 
136
274
    slow = config.getBool(CONFIG_SLOW);
137
275
 
138
 
    stylesheets = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLESHEETS);
139
 
    customHeadElements = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_CUSTOMHEADELEMENTS);
 
276
    stylesheets = config.getStringList(HtmlGenerator::format() +
 
277
                                       Config::dot +
 
278
                                       HTMLGENERATOR_STYLESHEETS);
 
279
    customHeadElements = config.getStringList(HtmlGenerator::format() +
 
280
                                              Config::dot +
 
281
                                              HTMLGENERATOR_CUSTOMHEADELEMENTS);
140
282
    codeIndent = config.getInt(CONFIG_CODEINDENT);
141
283
 
142
 
    helpProjectWriter = new HelpProjectWriter(config, project.toLower() + ".qhp");
 
284
    helpProjectWriter = new HelpProjectWriter(config,
 
285
                                              project.toLower() +
 
286
                                              ".qhp");
143
287
}
144
288
 
145
289
void HtmlGenerator::terminateGenerator()
173
317
    nonCompatClasses.clear();
174
318
    mainClasses.clear();
175
319
    compatClasses.clear();
 
320
    obsoleteClasses.clear();
176
321
    moduleClassMap.clear();
177
322
    moduleNamespaceMap.clear();
178
323
    funcIndex.clear();
182
327
    findAllFunctions(tree->root());
183
328
    findAllLegaleseTexts(tree->root());
184
329
    findAllNamespaces(tree->root());
185
 
#ifdef ZZZ_QDOC_QML    
 
330
#ifdef ZZZ_QDOC_QML
186
331
    findAllQmlClasses(tree->root());
187
 
#endif    
 
332
#endif
 
333
    findAllSince(tree->root());
 
334
 
 
335
#if 0    
 
336
    if (!sinceVersions.isEmpty()) {
 
337
        SinceVersionMap::const_iterator v = sinceVersions.constEnd();
 
338
        do {
 
339
            --v;
 
340
            qDebug() << "SINCE:" << v.key();
 
341
            if (!v.value().isEmpty()) {
 
342
                QString type;
 
343
                SinceNodeMultiMap::const_iterator n = v.value().constBegin();
 
344
                while (n != v.value().constEnd()) {
 
345
                    switch (n.value()->type()) {
 
346
                        case Node::Namespace:
 
347
                            type = "namespace";
 
348
                            break;
 
349
                        case Node::Class:
 
350
                            type = "class";
 
351
                            break;
 
352
                        case Node::Fake:
 
353
                            type = "fake";
 
354
                            break;
 
355
                        case Node::Enum: 
 
356
                            type = "enum";
 
357
                            break;
 
358
                        case Node::Typedef:
 
359
                            type = "typedef";
 
360
                            break;
 
361
                        case Node::Function:
 
362
                            type = "function";
 
363
                            break;
 
364
                        case Node::Property:
 
365
                            type = "property";
 
366
                            break;
 
367
                        case Node::Variable:
 
368
                            type = "variable";
 
369
                            break;
 
370
                        case Node::Target:
 
371
                            type = "target";
 
372
                            break;
 
373
                        case Node::QmlProperty:
 
374
                            type = "QML property";
 
375
                            break;
 
376
                        case Node::QmlSignal:
 
377
                            type = "QML signal";
 
378
                            break;
 
379
                        case Node::QmlMethod:
 
380
                            type = "QML method";
 
381
                            break;
 
382
                        default:
 
383
                            type = "No type";
 
384
                    }
 
385
                    qDebug() << "    " << type << n.key();
 
386
                    ++n;
 
387
                }
 
388
            }
 
389
        } while (v != sinceVersions.constBegin());
 
390
    }
 
391
#endif
188
392
 
189
393
    PageGenerator::generateTree(tree, marker);
190
394
 
260
464
    case Atom::AutoLink:
261
465
        if (!inLink && !inContents && !inSectionHeading) {
262
466
            const Node *node = 0;
263
 
            QString link = getLink(atom, relative, marker, node);
 
467
            QString link = getLink(atom, relative, marker, &node);
264
468
            if (!link.isEmpty()) {
265
469
                beginLink(link, node, relative, marker);
266
470
                generateLink(atom, relative, marker);
288
492
            QString str;
289
493
            atom = atom->next();
290
494
            while (atom != 0 && atom->type() != Atom::BriefRight) {
291
 
                if (atom->type() == Atom::String || atom->type() == Atom::AutoLink)
 
495
                if (atom->type() == Atom::String ||
 
496
                    atom->type() == Atom::AutoLink)
292
497
                    str += atom->string();
293
498
                skipAhead++;
294
499
                atom = atom->next();
326
531
        out() << formattingRightMap()[ATOM_FORMATTING_TELETYPE];
327
532
        break;
328
533
    case Atom::Code:
329
 
        out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
330
 
                                                            marker, relative))
 
534
        out() << "<pre>"
 
535
              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
 
536
                                                 marker,relative))
331
537
              << "</pre>\n";
332
538
        break;
333
 
#ifdef QDOC_QML        
 
539
#ifdef QDOC_QML
334
540
    case Atom::Qml:
335
 
        out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
336
 
                                                            marker, relative))
 
541
        out() << "<pre>"
 
542
              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
 
543
                                                 marker,relative))
337
544
              << "</pre>\n";
338
545
        break;
339
 
#endif        
 
546
#endif
340
547
    case Atom::CodeNew:
341
548
        out() << "<p>you can rewrite it as</p>\n"
342
 
              << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
343
 
                                                            marker, relative))
 
549
              << "<pre>"
 
550
              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),
 
551
                                                 marker,relative))
344
552
              << "</pre>\n";
345
553
        break;
346
554
    case Atom::CodeOld:
348
556
        // fallthrough
349
557
    case Atom::CodeBad:
350
558
        out() << "<pre><font color=\"#404040\">"
351
 
              << trimmedTrailing(protect(plainCode(indent(codeIndent, atom->string()))))
 
559
              << trimmedTrailing(protect(plainCode(indent(codeIndent,atom->string()))))
352
560
              << "</font></pre>\n";
353
561
        break;
354
562
    case Atom::FootnoteLeft:
388
596
            out() << formattingRightMap()[atom->string()];
389
597
        }
390
598
        break;
 
599
    case Atom::AnnotatedList:
 
600
        {
 
601
            QList<Node*> values = tre->groups().values(atom->string());
 
602
            QMap<QString, const Node*> nodeMap;
 
603
            for (int i = 0; i < values.size(); ++i) {
 
604
                const Node* n = values.at(i);
 
605
                if ((n->status() != Node::Internal) && (n->access() != Node::Private)) {
 
606
                    nodeMap.insert(n->nameForLists(),n);
 
607
                    //qDebug() << "  " << n->nameForLists();
 
608
                }
 
609
            }
 
610
            generateAnnotatedList(relative, marker, nodeMap);
 
611
        }
 
612
        break;
391
613
    case Atom::GeneratedList:
392
614
        if (atom->string() == "annotatedclasses") {
393
615
            generateAnnotatedList(relative, marker, nonCompatClasses);
443
665
        else if (atom->string() == "compatclasses") {
444
666
            generateCompactList(relative, marker, compatClasses);
445
667
        }
 
668
        else if (atom->string() == "obsoleteclasses") {
 
669
            generateCompactList(relative, marker, obsoleteClasses);
 
670
        }
446
671
        else if (atom->string() == "functionindex") {
447
672
            generateFunctionIndex(relative, marker);
448
673
        }
486
711
            }
487
712
        }
488
713
        break;
489
 
    case Atom::Image:
 
714
    case Atom::SinceList:
 
715
        {
 
716
            QList<Node*> nodes;
 
717
            SinceVersionMap::const_iterator v;
 
718
            v = sinceVersions.find(atom->string());
 
719
            if ((v != sinceVersions.constEnd()) && !v.value().isEmpty()) {
 
720
                for (int i=0; !Node::typeName(i).isEmpty(); i++) {
 
721
                    Node::Type t = (Node::Type) i;
 
722
                    SinceNodeMultiMap::const_iterator n=v.value().constBegin();
 
723
                    QMultiMap<QString, const Node*> nodeMap;
 
724
                    while (n != v.value().constEnd()) {
 
725
                        const Node* node = n.value();
 
726
                        if (node->type() == t)
 
727
                            nodeMap.insert(node->nameForLists(),node);
 
728
                        ++n;
 
729
                    }
 
730
                    if (!nodeMap.isEmpty()) {
 
731
                        out() << "<h2>"
 
732
                              << Node::typeName(i)
 
733
                              << " new in Qt "
 
734
                              << atom->string()
 
735
                              << "</h2>";
 
736
                        generateAnnotatedList(relative, marker, nodeMap);
 
737
                        nodeMap.clear();
 
738
                    }
 
739
                }
 
740
            }
 
741
        }
 
742
        break;
 
743
case Atom::Image:
490
744
    case Atom::InlineImage:
491
745
        {
492
746
            QString fileName = imageFileName(relative, atom->string());
524
778
    case Atom::Link:
525
779
        {
526
780
            const Node *node = 0;
527
 
            QString myLink = getLink(atom, relative, marker, node);
528
 
            if (myLink.isEmpty())
 
781
            QString myLink = getLink(atom, relative, marker, &node);
 
782
            if (myLink.isEmpty()) {
529
783
                relative->doc().location().warning(tr("Cannot link to '%1' in %2")
530
784
                        .arg(atom->string())
531
785
                        .arg(marker->plainFullName(relative)));
 
786
            }
532
787
            beginLink(myLink, node, relative, marker);
533
788
            skipAhead = 1;
534
789
        }
554
809
        else if (atom->string() == ATOM_LIST_VALUE) {
555
810
            threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
556
811
            if (threeColumnEnumValueTable) {
557
 
                out() << "<p><table border=\"1\" cellpadding=\"2\" cellspacing=\"1\" width=\"100%\">\n"
558
 
                         "<tr><th width=\"25%\">Constant</th><th width=\"15%\">Value</th>"
559
 
                         "<th width=\"60%\">Description</th></tr>\n";
 
812
                out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
 
813
                      << "cellspacing=\"1\" width=\"100%\">\n"
 
814
                      << "<tr><th width=\"25%\">Constant</th>"
 
815
                      << "<th width=\"15%\">Value</th>"
 
816
                      << "<th width=\"60%\">Description</th></tr>\n";
560
817
            }
561
818
            else {
562
 
                out() << "<p><table border=\"1\" cellpadding=\"2\" cellspacing=\"1\" width=\"40%\">\n"
563
 
                      << "<tr><th width=\"60%\">Constant</th><th width=\"40%\">Value</th></tr>\n";
 
819
                out() << "<p><table  class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
 
820
                      << "cellspacing=\"1\" width=\"40%\">\n"
 
821
                      << "<tr><th width=\"60%\">Constant</th><th "
 
822
                      << "width=\"40%\">Value</th></tr>\n";
564
823
            }
565
824
        }
566
825
        else {
734
993
        }
735
994
        if (!atom->string().isEmpty()) {
736
995
            if (atom->string().contains("%"))
737
 
                out() << "<p><table width=\"" << atom->string() << "\" "
 
996
                out() << "<p><table class=\"generic\" width=\"" << atom->string() << "\" "
738
997
                      << "align=\"center\" cellpadding=\"2\" "
739
998
                      << "cellspacing=\"1\" border=\"0\">\n";
740
 
            else
741
 
                out() << "<p><table align=\"center\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
 
999
            else {
 
1000
                out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
 
1001
                      << "cellspacing=\"1\" border=\"0\">\n";
 
1002
            }
742
1003
        }
743
1004
        else {
744
 
            out() << "<p><table align=\"center\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
 
1005
            out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
 
1006
                  << "cellspacing=\"1\" border=\"0\">\n";
745
1007
        }
746
1008
        numTableRows = 0;
747
1009
        break;
840
1102
    case Atom::EndQmlText:
841
1103
        // don't do anything with these. They are just tags.
842
1104
        break;
843
 
#endif        
 
1105
#endif
844
1106
    default:
845
1107
        unknownAtom(atom);
846
1108
    }
906
1168
    generateHeader(title, inner, marker, true);
907
1169
    generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
908
1170
 
 
1171
#ifdef QDOC_QML    
 
1172
    if (classe && !classe->qmlElement().isEmpty()) {
 
1173
        generateInstantiatedBy(classe,marker);
 
1174
    }
 
1175
#endif
 
1176
    
909
1177
    generateBrief(inner, marker);
910
1178
    generateIncludes(inner, marker);
911
1179
    generateStatus(inner, marker);
924
1192
        out() << "<li><a href=\"" << membersLink << "\">"
925
1193
              << "List of all members, including inherited members</a></li>\n";
926
1194
 
927
 
    QString obsoleteLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Obsolete);
 
1195
    QString obsoleteLink = generateLowStatusMemberFile(inner,
 
1196
                                                       marker,
 
1197
                                                       CodeMarker::Obsolete);
928
1198
    if (!obsoleteLink.isEmpty())
929
1199
        out() << "<li><a href=\"" << obsoleteLink << "\">"
930
1200
              << "Obsolete members</a></li>\n";
931
1201
 
932
 
    QString compatLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Compat);
 
1202
    QString compatLink = generateLowStatusMemberFile(inner,
 
1203
                                                     marker,
 
1204
                                                     CodeMarker::Compat);
933
1205
    if (!compatLink.isEmpty())
934
1206
        out() << "<li><a href=\"" << compatLink << "\">"
935
1207
              << "Qt 3 support members</a></li>\n";
941
1213
    sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
942
1214
    s = sections.begin();
943
1215
    while (s != sections.end()) {
944
 
        if (s->members.isEmpty()) {
 
1216
        if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
945
1217
            if (!s->inherited.isEmpty())
946
1218
                needOtherSection = true;
947
 
        } else {
948
 
            out() << "<a name=\"" << registerRef((*s).name.toLower()) << "\"></a>\n";
949
 
            out() << "<h3>" << protect((*s).name) << "</h3>\n";
 
1219
        }
 
1220
        else {
 
1221
            if (!s->members.isEmpty()) {
 
1222
                out() << "<hr />\n";
 
1223
                out() << "<a name=\""
 
1224
                      << registerRef((*s).name.toLower())
 
1225
                      << "\"></a>\n";
 
1226
                out() << "<h2>" << protect((*s).name) << "</h2>\n";
 
1227
                generateSection(s->members, inner, marker, CodeMarker::Summary);
 
1228
            }
 
1229
            if (!s->reimpMembers.isEmpty()) {
 
1230
                QString name = QString("Reimplemented ") + (*s).name;
 
1231
                out() << "<hr />\n";
 
1232
                out() << "<a name=\""
 
1233
                      << registerRef(name.toLower())
 
1234
                      << "\"></a>\n";
 
1235
                out() << "<h2>" << protect(name) << "</h2>\n";
 
1236
                generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
 
1237
            }
950
1238
 
951
 
            generateSectionList(*s, inner, marker, CodeMarker::Summary);
 
1239
            if (!s->inherited.isEmpty()) {
 
1240
                out() << "<ul>\n";
 
1241
                generateSectionInheritedList(*s, inner, marker, true);
 
1242
                out() << "</ul>\n";
 
1243
            }
952
1244
        }
953
1245
        ++s;
954
1246
    }
997
1289
                names << (*m)->name();
998
1290
                if ((*m)->type() == Node::Function) {
999
1291
                    const FunctionNode *func = reinterpret_cast<const FunctionNode *>(*m);
1000
 
                    if (func->metaness() == FunctionNode::Ctor || func->metaness() == FunctionNode::Dtor
1001
 
                            || func->overloadNumber() != 1)
 
1292
                    if (func->metaness() == FunctionNode::Ctor ||
 
1293
                        func->metaness() == FunctionNode::Dtor ||
 
1294
                        func->overloadNumber() != 1)
1002
1295
                        names.clear();
1003
 
                } else if ((*m)->type() == Node::Property) {
 
1296
                }
 
1297
                else if ((*m)->type() == Node::Property) {
1004
1298
                    const PropertyNode *prop = reinterpret_cast<const PropertyNode *>(*m);
1005
 
                    if (!prop->getters().isEmpty() && !names.contains(prop->getters().first()->name()))
 
1299
                    if (!prop->getters().isEmpty() &&
 
1300
                        !names.contains(prop->getters().first()->name()))
1006
1301
                        names << prop->getters().first()->name();
1007
1302
                    if (!prop->setters().isEmpty())
1008
1303
                        names << prop->setters().first()->name();
1009
1304
                    if (!prop->resetters().isEmpty())
1010
1305
                        names << prop->resetters().first()->name();
1011
 
                } else if ((*m)->type() == Node::Enum) {
1012
 
                    const EnumNode *enume = reinterpret_cast<const EnumNode *>(*m);
 
1306
                }
 
1307
                else if ((*m)->type() == Node::Enum) {
 
1308
                    const EnumNode *enume = reinterpret_cast<const EnumNode*>(*m);
1013
1309
                    if (enume->flagsType())
1014
1310
                        names << enume->flagsType()->name();
1015
1311
 
1016
1312
                    foreach (const QString &enumName,
1017
 
                             enume->doc().enumItemNames().toSet()
1018
 
                             - enume->doc().omitEnumItemNames().toSet())
1019
 
                        names << plainCode(marker->markedUpEnumValue(enumName, enume));
 
1313
                             enume->doc().enumItemNames().toSet() -
 
1314
                             enume->doc().omitEnumItemNames().toSet())
 
1315
                        names << plainCode(marker->markedUpEnumValue(enumName,
 
1316
                                                                     enume));
1020
1317
                }
1021
1318
                foreach (const QString &name, names)
1022
 
                    classSection.keywords += qMakePair(name, linkForNode(*m, 0));
 
1319
                    classSection.keywords += qMakePair(name,linkForNode(*m,0));
1023
1320
            }
1024
1321
            ++m;
1025
1322
        }
1060
1357
    QList<Section>::const_iterator s;
1061
1358
 
1062
1359
    QString htmlTitle = fake->fullTitle();
1063
 
    if (fake->subType() == FakeNode::File && !fake->subTitle().isEmpty()) {
 
1360
    if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) {
1064
1361
        subTitleSize = SmallSubTitle;
1065
1362
        htmlTitle += " (" + fake->subTitle() + ")";
1066
1363
    }
1067
1364
 
1068
1365
    generateHeader(htmlTitle, fake, marker, true);
1069
 
    generateTitle(fake->fullTitle(), Text() << fake->subTitle(), subTitleSize,
1070
 
                  fake, marker);
 
1366
    generateTitle(fake->fullTitle(),
 
1367
                  Text() << fake->subTitle(),
 
1368
                  subTitleSize,
 
1369
                  fake,
 
1370
                  marker);
1071
1371
 
1072
 
    if (fake->subType() == FakeNode::Module) {
 
1372
    if (fake->subType() == Node::Module) {
1073
1373
        // Generate brief text and status for modules.
1074
1374
        generateBrief(fake, marker);
1075
1375
        generateStatus(fake, marker);
1083
1383
            generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
1084
1384
        }
1085
1385
    }
1086
 
    else if (fake->subType() == FakeNode::HeaderFile) {
 
1386
    else if (fake->subType() == Node::HeaderFile) {
1087
1387
        // Generate brief text and status for modules.
1088
1388
        generateBrief(fake, marker);
1089
1389
        generateStatus(fake, marker);
1095
1395
            out() << "<li><a href=\"" << membersLink << "\">"
1096
1396
                  << "List of all members, including inherited members</a></li>\n";
1097
1397
 
1098
 
        QString obsoleteLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Obsolete);
 
1398
        QString obsoleteLink = generateLowStatusMemberFile(fake,
 
1399
                                                           marker,
 
1400
                                                           CodeMarker::Obsolete);
1099
1401
        if (!obsoleteLink.isEmpty())
1100
1402
            out() << "<li><a href=\"" << obsoleteLink << "\">"
1101
1403
                  << "Obsolete members</a></li>\n";
1102
1404
 
1103
 
        QString compatLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Compat);
 
1405
        QString compatLink = generateLowStatusMemberFile(fake,
 
1406
                                                         marker,
 
1407
                                                         CodeMarker::Compat);
1104
1408
        if (!compatLink.isEmpty())
1105
1409
            out() << "<li><a href=\"" << compatLink << "\">"
1106
1410
                  << "Qt 3 support members</a></li>\n";
1126
1430
            appendDcfSubSection(&fakeSection, compatSection);
1127
1431
        }
1128
1432
    }
1129
 
 
 
1433
#ifdef QDOC_QML
 
1434
    else if (fake->subType() == Node::QmlClass) {
 
1435
        const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake);
 
1436
        const ClassNode* cn = qml_cn->classNode();
 
1437
        generateQmlInherits(qml_cn, marker);
 
1438
        generateQmlInstantiates(qml_cn, marker);
 
1439
        generateBrief(qml_cn, marker);
 
1440
        sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
 
1441
        s = sections.begin();
 
1442
        while (s != sections.end()) {
 
1443
            out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
 
1444
            out() << "<h2>" << protect((*s).name) << "</h2>\n";
 
1445
            generateQmlSummary(*s,fake,marker);
 
1446
            ++s;
 
1447
        }
 
1448
 
 
1449
        out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
 
1450
        out() << "<h2>" << "Detailed Description" << "</h2>\n";
 
1451
        generateBody(fake, marker);
 
1452
        if (cn)
 
1453
            generateQmlText(cn->doc().body(), cn, marker, fake->name());
 
1454
        generateAlsoList(fake, marker);
 
1455
        out() << "<hr />\n";
 
1456
 
 
1457
        sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
 
1458
        s = sections.begin();
 
1459
        while (s != sections.end()) {
 
1460
            out() << "<h2>" << protect((*s).name) << "</h2>\n";
 
1461
            NodeList::ConstIterator m = (*s).members.begin();
 
1462
            while (m != (*s).members.end()) {
 
1463
                generateDetailedQmlMember(*m, fake, marker);
 
1464
                out() << "<br />\n";
 
1465
                fakeSection.keywords += qMakePair((*m)->name(),
 
1466
                                                  linkForNode(*m,0));
 
1467
                ++m;
 
1468
            }
 
1469
            ++s;
 
1470
        }
 
1471
        generateFooter(fake);
 
1472
        return;
 
1473
    }
 
1474
#endif
 
1475
    
1130
1476
    sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay);
1131
1477
    s = sections.begin();
1132
1478
    while (s != sections.end()) {
1133
1479
        out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
1134
 
        out() << "<h3>" << protect((*s).name) << "</h3>\n";
 
1480
        out() << "<h2>" << protect((*s).name) << "</h2>\n";
1135
1481
        generateSectionList(*s, fake, marker, CodeMarker::Summary);
1136
1482
        ++s;
1137
1483
    }
1138
1484
 
1139
1485
    Text brief = fake->doc().briefText();
1140
 
    if (fake->subType() == FakeNode::Module && !brief.isEmpty()) {
 
1486
    if (fake->subType() == Node::Module && !brief.isEmpty()) {
1141
1487
        out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
1142
1488
        out() << "<h2>" << "Detailed Description" << "</h2>\n";
1143
1489
    }
1144
1490
 
1145
1491
    generateBody(fake, marker);
1146
 
#ifdef QDOC_QML    
1147
 
    if (fake->subType() == FakeNode::QmlClass) {
1148
 
        //qDebug() << "generateFakeNode(): QML CLASS" << fake->name();
1149
 
        const QmlNode* qmlNode = static_cast<const QmlNode*>(fake);
1150
 
        const ClassNode* cn = qmlNode->classNode();
1151
 
        if (cn) {
1152
 
            //qDebug() << "  CPP CLASS" << cn->name();
1153
 
            generateQmlText(cn->doc().body(), cn, marker);
1154
 
        }
1155
 
    }
1156
 
#endif    
1157
 
 
1158
1492
    generateAlsoList(fake, marker);
1159
1493
 
1160
1494
    if (!fake->groupMembers().isEmpty()) {
1184
1518
    }
1185
1519
    generateFooter(fake);
1186
1520
 
1187
 
    if (fake->subType() == FakeNode::Example) {
 
1521
    if (fake->subType() == Node::Example) {
1188
1522
        appendDcfSubSection(&dcfExamplesRoot, fakeSection);
1189
1523
    }
1190
 
    else if (fake->subType() != FakeNode::File) {
 
1524
    else if (fake->subType() != Node::File) {
1191
1525
        QString contentsPage = fake->links().value(Node::ContentsLink).first;
1192
1526
 
1193
1527
        if (contentsPage == "Qt Designer Manual") {
1228
1562
    if ((project != "Qtopia") && (project != "Qt Extended")) {
1229
1563
        shortVersion = project + " " + shortVersion + ": ";
1230
1564
        if (node && !node->doc().location().isEmpty())
1231
 
            out() << "<!-- " << node->doc().location().filePath() << " -->\n";
 
1565
            out() << "<!-- " << node->doc().location().fileName() << " -->\n";
1232
1566
 
1233
1567
        shortVersion = tre->version();
1234
1568
        if (shortVersion.count(QChar('.')) == 2)
1407
1741
void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker)
1408
1742
{
1409
1743
    if (!inner->includes().isEmpty()) {
1410
 
        out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent,
1411
 
                                                                   marker->markedUpIncludes(
1412
 
                                                                        inner->includes())),
1413
 
                                                                        marker, inner))
 
1744
        out() << "<pre>"
 
1745
              << trimmedTrailing(highlightedCode(indent(codeIndent,
 
1746
                                                        marker->markedUpIncludes(inner->includes())),
 
1747
                                                 marker,inner))
1414
1748
              << "</pre>";
1415
1749
    }
1416
1750
}
1417
1751
 
1418
 
void HtmlGenerator::generateTableOfContents(const Node *node, CodeMarker *marker,
 
1752
void HtmlGenerator::generateTableOfContents(const Node *node,
 
1753
                                            CodeMarker *marker,
1419
1754
                                            Doc::SectioningUnit sectioningUnit,
1420
 
                                            int numColumns, const Node *relative)
 
1755
                                            int numColumns,
 
1756
                                            const Node *relative)
1421
1757
 
1422
1758
{
1423
1759
    if (!node->doc().hasTableOfContents())
1436
1772
    QString tdTag;
1437
1773
    if (numColumns > 1) {
1438
1774
        tdTag = "<td width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";
1439
 
        out() << "<p><table width=\"100%\">\n<tr valign=\"top\">" << tdTag << "\n";
 
1775
        out() << "<p><table class=\"toc\" width=\"100%\">\n<tr valign=\"top\">"
 
1776
              << tdTag << "\n";
1440
1777
    }
1441
1778
 
1442
1779
    // disable nested links in table of contents
1455
1792
                out() << "<ul>";
1456
1793
                sectionNumber.append("1");
1457
1794
            } while (sectionNumber.size() < nextLevel);
1458
 
        } else {
 
1795
        }
 
1796
        else {
1459
1797
            while (sectionNumber.size() > nextLevel) {
1460
1798
                out() << "</ul>\n";
1461
1799
                sectionNumber.removeLast();
1470
1808
            columnSize = 0;
1471
1809
        }
1472
1810
        out() << "<li>";
1473
 
        out() << "<a href=\"" << nodeName << "#" << Doc::canonicalTitle(headingText.toString())
 
1811
        out() << "<a href=\""
 
1812
              << nodeName
 
1813
              << "#"
 
1814
              << Doc::canonicalTitle(headingText.toString())
1474
1815
              << "\">";
1475
1816
        generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
1476
1817
        out() << "</a></li>\n";
1520
1861
}
1521
1862
#endif
1522
1863
 
1523
 
QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker)
 
1864
QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner,
 
1865
                                                   CodeMarker *marker)
1524
1866
{
1525
1867
    QList<Section> sections;
1526
1868
    QList<Section>::ConstIterator s;
1527
1869
 
1528
 
    sections = marker->sections(inner, CodeMarker::SeparateList, CodeMarker::Okay);
 
1870
    sections = marker->sections(inner,
 
1871
                                CodeMarker::SeparateList,
 
1872
                                CodeMarker::Okay);
1529
1873
    if (sections.isEmpty())
1530
1874
        return QString();
1531
1875
 
1546
1890
    return fileName;
1547
1891
}
1548
1892
 
1549
 
QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeMarker *marker,
 
1893
QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
 
1894
                                                   CodeMarker *marker,
1550
1895
                                                   CodeMarker::Status status)
1551
1896
{
1552
 
    QList<Section> sections = marker->sections(inner, CodeMarker::Summary, status);
 
1897
    QList<Section> sections = marker->sections(inner,
 
1898
                                               CodeMarker::Summary,
 
1899
                                               status);
1553
1900
    QMutableListIterator<Section> j(sections);
1554
1901
    while (j.hasNext()) {
1555
1902
        if (j.next().members.size() == 0)
1566
1913
    if (status == CodeMarker::Compat) {
1567
1914
        title = "Qt 3 Support Members for " + inner->name();
1568
1915
        fileName = fileBase(inner) + "-qt3." + fileExtension(inner);
1569
 
    } else {
 
1916
    }
 
1917
    else {
1570
1918
        title = "Obsolete Members for " + inner->name();
1571
1919
        fileName = fileBase(inner) + "-obsolete." + fileExtension(inner);
1572
1920
    }
1580
1928
                 "<a href=\"qt3support.html\">Qt 3 support layer</a>.</b> "
1581
1929
                 "They are provided to help you port old code to Qt 4. We advise against "
1582
1930
                 "using them in new code.</p>\n";
1583
 
    } else {
1584
 
        out() << "<p><b>The following class members are obsolete.</b> They are provided to keep "
1585
 
                 "old source code working. We strongly advise against using them in new "
1586
 
                 "code.</p>\n";
 
1931
    }
 
1932
    else {
 
1933
        out() << "<p><b>The following class members are obsolete.</b> "
 
1934
              << "They are provided to keep old source code working. "
 
1935
              << "We strongly advise against using them in new code.</p>\n";
1587
1936
    }
1588
1937
 
1589
 
    out() << "<p><ul><li><a href=\"" << linkForNode(inner, 0) << "\">" << protect(inner->name())
 
1938
    out() << "<p><ul><li><a href=\""
 
1939
          << linkForNode(inner, 0) << "\">"
 
1940
          << protect(inner->name())
1590
1941
          << " class reference</a></li></ul></p>\n";
1591
1942
 
1592
1943
    for (i = 0; i < sections.size(); ++i) {
1593
 
        out() << "<h3>" << protect(sections.at(i).name) << "</h3>\n";
1594
 
 
 
1944
        out() << "<h2>" << protect(sections.at(i).name) << "</h2>\n";
1595
1945
        generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary);
1596
1946
    }
1597
1947
 
1613
1963
    return fileName;
1614
1964
}
1615
1965
 
1616
 
void HtmlGenerator::generateClassHierarchy(const Node *relative, CodeMarker *marker,
1617
 
                                           const QMap<QString, const Node *> &classMap)
 
1966
void HtmlGenerator::generateClassHierarchy(const Node *relative,
 
1967
                                           CodeMarker *marker,
 
1968
                                           const QMap<QString,const Node*> &classMap)
1618
1969
{
1619
1970
    if (classMap.isEmpty())
1620
1971
        return;
1636
1987
        if (stack.top().isEmpty()) {
1637
1988
            stack.pop();
1638
1989
            out() << "</ul>\n";
1639
 
        } else {
1640
 
            const ClassNode *child = static_cast<const ClassNode *>(*stack.top().begin());
 
1990
        }
 
1991
        else {
 
1992
            const ClassNode *child =
 
1993
                static_cast<const ClassNode *>(*stack.top().begin());
1641
1994
            out() << "<li>";
1642
1995
            generateFullName(child, relative, marker);
1643
1996
            out() << "</li>\n";
1656
2009
    }
1657
2010
}
1658
2011
 
1659
 
void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker,
1660
 
                    const QMap<QString, const Node *> &nodeMap)
 
2012
void HtmlGenerator::generateAnnotatedList(const Node *relative,
 
2013
                                          CodeMarker *marker,
 
2014
                                          const QMap<QString, const Node *> &nodeMap)
1661
2015
{
1662
 
    out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
 
2016
    out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" "
 
2017
          << "cellspacing=\"1\" border=\"0\">\n";
1663
2018
 
1664
2019
    int row = 0;
1665
2020
    foreach (const QString &name, nodeMap.keys()) {
1666
2021
        const Node *node = nodeMap[name];
1667
2022
 
 
2023
        if (node->status() == Node::Obsolete)
 
2024
            continue;
 
2025
 
1668
2026
        if (++row % 2 == 1)
1669
2027
            out() << "<tr valign=\"top\" class=\"odd\">";
1670
2028
        else
1680
2038
                generateText(brief, node, marker);
1681
2039
                out() << "</td>";
1682
2040
            }
1683
 
        } else {
 
2041
        }
 
2042
        else {
1684
2043
            out() << "<td>";
1685
2044
            out() << protect(node->doc().briefText().toString());
1686
2045
            out() << "</td>";
1690
2049
    out() << "</table></p>\n";
1691
2050
}
1692
2051
 
1693
 
void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker,
 
2052
void HtmlGenerator::generateCompactList(const Node *relative,
 
2053
                                        CodeMarker *marker,
1694
2054
                                        const QMap<QString, const Node *> &classMap)
1695
2055
{
1696
2056
    const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_'
1734
2094
        last = classMap.begin().key();
1735
2095
 
1736
2096
    if (classMap.size() > 1) {
1737
 
        while (commonPrefixLen < first.length() + 1 && commonPrefixLen < last.length() + 1
1738
 
               && first[commonPrefixLen] == last[commonPrefixLen])
 
2097
        while (commonPrefixLen < first.length() + 1 &&
 
2098
               commonPrefixLen < last.length() + 1 &&
 
2099
               first[commonPrefixLen] == last[commonPrefixLen])
1739
2100
            ++commonPrefixLen;
1740
2101
    }
1741
2102
 
1748
2109
      assume that NumParagraphs is 37. Each paragraph is a
1749
2110
      QMap<QString, const Node *>.
1750
2111
    */
1751
 
    QMap<QString, const Node *> paragraph[NumParagraphs];
1752
 
    QString paragraphName[NumParagraphs];
 
2112
    QMap<QString, const Node *> paragraph[NumParagraphs+1];
 
2113
    QString paragraphName[NumParagraphs+1];
1753
2114
 
1754
2115
    QMap<QString, const Node *>::ConstIterator c = classMap.begin();
1755
2116
    while (c != classMap.end()) {
1764
2125
 
1765
2126
        if (key[0].digitValue() != -1) {
1766
2127
            paragraphNo = key[0].digitValue();
1767
 
        } else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
 
2128
        }
 
2129
        else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
1768
2130
            paragraphNo = 10 + key[0].unicode() - 'a';
1769
2131
        }
1770
2132
 
1781
2143
      We now want to compute the paragraph offset. Paragraphs 0 to 6
1782
2144
      start at offsets 0, 3, 4, 8, 9, 14, 23.
1783
2145
    */
1784
 
    int paragraphOffset[NumParagraphs + 1];
 
2146
    int paragraphOffset[NumParagraphs + 1];     // 37 + 1
1785
2147
    int i, j, k;
1786
2148
 
1787
2149
    paragraphOffset[0] = 0;
1788
 
    for (j = 0; j < NumParagraphs; j++)
 
2150
    for (j = 0; j < NumParagraphs; j++)         // j = 0..36
1789
2151
        paragraphOffset[j + 1] = paragraphOffset[j] + paragraph[j].count();
1790
2152
 
1791
 
    int firstOffset[NumColumns + 1];
1792
 
    int currentOffset[NumColumns];
1793
 
    int currentParagraphNo[NumColumns];
1794
 
    int currentOffsetInParagraph[NumColumns];
 
2153
    int firstOffset[NumColumns + 1];            // 4 + 1
 
2154
    int currentOffset[NumColumns];              // 4
 
2155
    int currentParagraphNo[NumColumns];         // 4
 
2156
    int currentOffsetInParagraph[NumColumns];   // 4
1795
2157
 
1796
2158
    int numRows = (classMap.count() + NumColumns - 1) / NumColumns;
1797
2159
    int curParagNo = 0;
1798
2160
 
1799
 
    for (i = 0; i < NumColumns; i++) {
 
2161
    for (i = 0; i < NumColumns; i++) {          // i = 0..3
1800
2162
        firstOffset[i] = qMin(i * numRows, classMap.size());
1801
2163
        currentOffset[i] = firstOffset[i];
1802
2164
 
1812
2174
    }
1813
2175
    firstOffset[NumColumns] = classMap.count();
1814
2176
 
1815
 
    out() << "<p><table width=\"100%\">\n";
 
2177
    out() << "<p><table class=\"generic\" width=\"100%\">\n";
1816
2178
    for (k = 0; k < numRows; k++) {
1817
2179
        out() << "<tr>\n";
1818
2180
        for (i = 0; i < NumColumns; i++) {
1819
2181
            if (currentOffset[i] >= firstOffset[i + 1]) {
1820
2182
                // this column is finished
1821
2183
                out() << "<td>\n</td>\n";
1822
 
            } else {
1823
 
                while (currentOffsetInParagraph[i] == paragraph[currentParagraphNo[i]].count()) {
 
2184
            }
 
2185
            else {
 
2186
                while ((currentParagraphNo[i] < NumParagraphs) &&
 
2187
                       (currentOffsetInParagraph[i] == paragraph[currentParagraphNo[i]].count())) {
1824
2188
                    ++currentParagraphNo[i];
1825
2189
                    currentOffsetInParagraph[i] = 0;
1826
2190
                }
1827
 
 
 
2191
#if 0
 
2192
                if (currentParagraphNo[i] >= NumParagraphs) {
 
2193
                    qDebug() << "### Internal error ###" << __FILE__ << __LINE__
 
2194
                             << currentParagraphNo[i] << NumParagraphs;
 
2195
                    currentParagraphNo[i] = NumParagraphs - 1;
 
2196
                }
 
2197
#endif
1828
2198
                out() << "<td align=\"right\">";
1829
2199
                if (currentOffsetInParagraph[i] == 0) {
1830
2200
                    // start a new paragraph
1831
 
                    out() << "<b>" << paragraphName[currentParagraphNo[i]] << "&nbsp;</b>";
1832
 
                }
1833
 
                out() << "</td>\n";
1834
 
 
1835
 
                // bad loop
1836
 
                QMap<QString, const Node *>::Iterator it;
1837
 
                it = paragraph[currentParagraphNo[i]].begin();
1838
 
                for (j = 0; j < currentOffsetInParagraph[i]; j++)
1839
 
                    ++it;
1840
 
 
1841
 
                out() << "<td>";
1842
 
                // Previously, we used generateFullName() for this, but we
1843
 
                // require some special formatting.
1844
 
                out() << "<a href=\"" << linkForNode(it.value(), relative) << "\">";
1845
 
                QStringList pieces = fullName(it.value(), relative, marker).split("::");
1846
 
                out() << protect(pieces.last());
1847
 
                out() << "</a>";
1848
 
                if (pieces.size() > 1) {
1849
 
                    out() << " (";
1850
 
                    generateFullName(it.value()->parent(), relative, marker);
1851
 
                    out() << ")";
1852
 
                }
1853
 
                out() << "</td>\n";
 
2201
                    out() << "<b>"
 
2202
                          << paragraphName[currentParagraphNo[i]]
 
2203
                          << "&nbsp;</b>";
 
2204
                }
 
2205
                out() << "</td>\n";
 
2206
                    
 
2207
                if ((currentParagraphNo[i] < NumParagraphs) &&
 
2208
                    !paragraphName[currentParagraphNo[i]].isEmpty()) {
 
2209
                    QMap<QString, const Node *>::Iterator it;
 
2210
                    it = paragraph[currentParagraphNo[i]].begin();
 
2211
                    for (j = 0; j < currentOffsetInParagraph[i]; j++)
 
2212
                        ++it;
 
2213
 
 
2214
                    out() << "<td>";
 
2215
                    // Previously, we used generateFullName() for this, but we
 
2216
                    // require some special formatting.
 
2217
                    out() << "<a href=\""
 
2218
                        << linkForNode(it.value(), relative)
 
2219
                        << "\">";
 
2220
                    QStringList pieces = fullName(it.value(), relative, marker).split("::");
 
2221
                    out() << protect(pieces.last());
 
2222
                    out() << "</a>";
 
2223
                    if (pieces.size() > 1) {
 
2224
                        out() << " (";
 
2225
                        generateFullName(it.value()->parent(), relative, marker);
 
2226
                        out() << ")";
 
2227
                    }
 
2228
                    out() << "</td>\n";
 
2229
                 }
1854
2230
 
1855
2231
                currentOffset[i]++;
1856
2232
                currentOffsetInParagraph[i]++;
1861
2237
    out() << "</table></p>\n";
1862
2238
}
1863
2239
 
1864
 
void HtmlGenerator::generateFunctionIndex(const Node *relative, CodeMarker *marker)
 
2240
void HtmlGenerator::generateFunctionIndex(const Node *relative,
 
2241
                                          CodeMarker *marker)
1865
2242
{
1866
2243
    out() << "<p align=\"center\"><font size=\"+1\"><b>";
1867
2244
    for (int i = 0; i < 26; i++) {
1910
2287
#endif
1911
2288
}
1912
2289
 
1913
 
void HtmlGenerator::generateLegaleseList(const Node *relative, CodeMarker *marker)
 
2290
void HtmlGenerator::generateLegaleseList(const Node *relative,
 
2291
                                         CodeMarker *marker)
1914
2292
{
1915
2293
    QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin();
1916
2294
    while (it != legaleseTexts.end()) {
1928
2306
    }
1929
2307
}
1930
2308
 
1931
 
void HtmlGenerator::generateSynopsis(const Node *node, const Node *relative,
1932
 
                                     CodeMarker *marker, CodeMarker::SynopsisStyle style)
 
2309
/*void HtmlGenerator::generateSynopsis(const Node *node,
 
2310
                                     const Node *relative,
 
2311
                                     CodeMarker *marker,
 
2312
                                     CodeMarker::SynopsisStyle style)
1933
2313
{
1934
2314
    QString marked = marker->markedUpSynopsis(node, relative, style);
1935
2315
    QRegExp templateTag("(<[^@>]*>)");
1939
2319
        marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
1940
2320
                        contents);
1941
2321
    }
1942
 
    marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>");
 
2322
    marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
 
2323
                   "<i>\\1<sub>\\2</sub></i>");
1943
2324
    marked.replace("<@param>", "<i>");
1944
2325
    marked.replace("</@param>", "</i>");
1945
2326
 
1950
2331
        QRegExp extraRegExp("<@extra>.*</@extra>");
1951
2332
        extraRegExp.setMinimal(true);
1952
2333
        marked.replace(extraRegExp, "");
1953
 
    } else {
 
2334
    }
 
2335
    else {
1954
2336
        marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
1955
2337
        marked.replace("</@extra>", "</tt>");
1956
2338
    }
1960
2342
        marked.replace("</@type>", "");
1961
2343
    }
1962
2344
    out() << highlightedCode(marked, marker, relative);
 
2345
}*/
 
2346
 
 
2347
#ifdef QDOC_QML
 
2348
void HtmlGenerator::generateQmlItem(const Node *node,
 
2349
                                    const Node *relative,
 
2350
                                    CodeMarker *marker,
 
2351
                                    bool summary)
 
2352
 
2353
    QString marked = marker->markedUpQmlItem(node,summary);
 
2354
    QRegExp templateTag("(<[^@>]*>)");
 
2355
    if (marked.indexOf(templateTag) != -1) {
 
2356
        QString contents = protect(marked.mid(templateTag.pos(1),
 
2357
                                              templateTag.cap(1).length()));
 
2358
        marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
 
2359
                        contents);
 
2360
    }
 
2361
    marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
 
2362
                   "<i>\\1<sub>\\2</sub></i>");
 
2363
    marked.replace("<@param>", "<i>");
 
2364
    marked.replace("</@param>", "</i>");
 
2365
 
 
2366
    if (summary)
 
2367
        marked.replace("@name>", "b>");
 
2368
 
 
2369
    marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
 
2370
    marked.replace("</@extra>", "</tt>");
 
2371
 
 
2372
    if (summary) {
 
2373
        marked.replace("<@type>", "");
 
2374
        marked.replace("</@type>", "");
 
2375
    }
 
2376
    out() << highlightedCode(marked, marker, relative);
1963
2377
}
 
2378
#endif
1964
2379
 
1965
2380
void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */)
1966
2381
{
1984
2399
            }
1985
2400
 
1986
2401
            // there are too many examples; they would clutter the list
1987
 
            if (fakeNode->subType() == FakeNode::Example)
 
2402
            if (fakeNode->subType() == Node::Example)
1988
2403
                continue;
1989
2404
 
1990
2405
            // not interested either in individual (Qt Designer etc.) manual chapters
1992
2407
                continue;
1993
2408
 
1994
2409
            // Discard external nodes.
1995
 
            if (fakeNode->subType() == FakeNode::ExternalPage)
 
2410
            if (fakeNode->subType() == Node::ExternalPage)
1996
2411
                continue;
1997
2412
 
1998
2413
            QString sortKey = fakeNode->fullTitle().toLower();
2017
2432
                            groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode);
2018
2433
                        }
2019
2434
                    }
2020
 
                } else if (!isGroupPage) {
 
2435
                }
 
2436
                else if (!isGroupPage) {
2021
2437
                    // If we encounter a page that belongs to a group then
2022
2438
                    // we add that page to the list for that group.
2023
2439
                    const FakeNode *groupNode = static_cast<const FakeNode *>(tre->root()->findNode(group, Node::Fake));
2075
2491
    }
2076
2492
}
2077
2493
 
2078
 
void HtmlGenerator::generateSectionList(const Section& section, const Node *relative,
2079
 
                                        CodeMarker *marker, CodeMarker::SynopsisStyle style)
2080
 
{
2081
 
    if (!section.members.isEmpty()) {
2082
 
        bool twoColumn = false;
2083
 
        if (style == CodeMarker::SeparateList) {
2084
 
            twoColumn = (section.members.count() >= 16);
2085
 
        } else if (section.members.first()->type() == Node::Property) {
 
2494
#ifdef QDOC_NAME_ALIGNMENT
 
2495
void HtmlGenerator::generateSection(const NodeList& nl,
 
2496
                                    const Node *relative,
 
2497
                                    CodeMarker *marker,
 
2498
                                    CodeMarker::SynopsisStyle style)
 
2499
{
 
2500
    bool name_alignment = true;
 
2501
    if (!nl.isEmpty()) {
 
2502
        bool twoColumn = false;
 
2503
        if (style == CodeMarker::SeparateList) {
 
2504
            name_alignment = false;
 
2505
            twoColumn = (nl.count() >= 16);
 
2506
        }
 
2507
        else if (nl.first()->type() == Node::Property) {
 
2508
            twoColumn = (nl.count() >= 5);
 
2509
            name_alignment = false;
 
2510
        }
 
2511
        if (name_alignment) {
 
2512
            out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" "
 
2513
                  << "cellspacing=\"0\" width=\"100%\">\n";
 
2514
        }
 
2515
        else {
 
2516
            if (twoColumn)
 
2517
                out() << "<p><table class=\"propsummary\" width=\"100%\" "
 
2518
                      << "border=\"0\" cellpadding=\"0\""
 
2519
                      << " cellspacing=\"0\">\n"
 
2520
                      << "<tr><td width=\"45%\" valign=\"top\">";
 
2521
            out() << "<ul>\n";
 
2522
        }
 
2523
 
 
2524
        int i = 0;
 
2525
        NodeList::ConstIterator m = nl.begin();
 
2526
        while (m != nl.end()) {
 
2527
            if ((*m)->access() == Node::Private) {
 
2528
                ++m;
 
2529
                continue;
 
2530
            }
 
2531
 
 
2532
            if (name_alignment) {
 
2533
                out() << "<tr><td class=\"memItemLeft\" "
 
2534
                      << "align=\"right\" valign=\"top\">";
 
2535
            }
 
2536
            else {
 
2537
                if (twoColumn && i == (int) (nl.count() + 1) / 2)
 
2538
                    out() << "</ul></td><td valign=\"top\"><ul>\n";
 
2539
                out() << "<li><div class=\"fn\">";
 
2540
            }
 
2541
 
 
2542
            generateSynopsis(*m, relative, marker, style, name_alignment);
 
2543
            if (name_alignment)
 
2544
                out() << "</td></tr>\n";
 
2545
            else
 
2546
                out() << "</div></li>\n";
 
2547
            i++;
 
2548
            ++m;
 
2549
        }
 
2550
        if (name_alignment)
 
2551
            out() << "</table>\n";
 
2552
        else {
 
2553
            out() << "</ul>\n";
 
2554
            if (twoColumn)
 
2555
                out() << "</td></tr>\n</table></p>\n";
 
2556
        }
 
2557
    }
 
2558
}
 
2559
 
 
2560
void HtmlGenerator::generateSectionList(const Section& section,
 
2561
                                        const Node *relative,
 
2562
                                        CodeMarker *marker,
 
2563
                                        CodeMarker::SynopsisStyle style)
 
2564
{
 
2565
    bool name_alignment = true;
 
2566
    if (!section.members.isEmpty()) {
 
2567
        bool twoColumn = false;
 
2568
        if (style == CodeMarker::SeparateList) {
 
2569
            name_alignment = false;
 
2570
            twoColumn = (section.members.count() >= 16);
 
2571
        }
 
2572
        else if (section.members.first()->type() == Node::Property) {
 
2573
            twoColumn = (section.members.count() >= 5);
 
2574
            name_alignment = false;
 
2575
        }
 
2576
        if (name_alignment) {
 
2577
            out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" "
 
2578
                  << "cellspacing=\"0\" width=\"100%\">\n";
 
2579
        }
 
2580
        else {
 
2581
            if (twoColumn)
 
2582
                out() << "<p><table class=\"propsummary\" width=\"100%\" "
 
2583
                      << "border=\"0\" cellpadding=\"0\""
 
2584
                      << " cellspacing=\"0\">\n"
 
2585
                      << "<tr><td width=\"45%\" valign=\"top\">";
 
2586
            out() << "<ul>\n";
 
2587
        }
 
2588
 
 
2589
        int i = 0;
 
2590
        NodeList::ConstIterator m = section.members.begin();
 
2591
        while (m != section.members.end()) {
 
2592
            if ((*m)->access() == Node::Private) {
 
2593
                ++m;
 
2594
                continue;
 
2595
            }
 
2596
 
 
2597
            if (name_alignment) {
 
2598
                out() << "<tr><td class=\"memItemLeft\" "
 
2599
                      << "align=\"right\" valign=\"top\">";
 
2600
            }
 
2601
            else {
 
2602
                if (twoColumn && i == (int) (section.members.count() + 1) / 2)
 
2603
                    out() << "</ul></td><td valign=\"top\"><ul>\n";
 
2604
                out() << "<li><div class=\"fn\">";
 
2605
            }
 
2606
 
 
2607
            generateSynopsis(*m, relative, marker, style, name_alignment);
 
2608
            if (name_alignment)
 
2609
                out() << "</td></tr>\n";
 
2610
            else
 
2611
                out() << "</div></li>\n";
 
2612
            i++;
 
2613
            ++m;
 
2614
        }
 
2615
        if (name_alignment)
 
2616
            out() << "</table>\n";
 
2617
        else {
 
2618
            out() << "</ul>\n";
 
2619
            if (twoColumn)
 
2620
                out() << "</td></tr>\n</table></p>\n";
 
2621
        }
 
2622
    }
 
2623
 
 
2624
    if (style == CodeMarker::Summary && !section.inherited.isEmpty()) {
 
2625
        out() << "<ul>\n";
 
2626
        generateSectionInheritedList(section, relative, marker, name_alignment);
 
2627
        out() << "</ul>\n";
 
2628
    }
 
2629
}
 
2630
 
 
2631
void HtmlGenerator::generateSectionInheritedList(const Section& section,
 
2632
                                                 const Node *relative,
 
2633
                                                 CodeMarker *marker,
 
2634
                                                 bool nameAlignment)
 
2635
{
 
2636
    QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin();
 
2637
    while (p != section.inherited.end()) {
 
2638
        if (nameAlignment)
 
2639
            out() << "<li><div bar=\"2\" class=\"fn\"></div>";
 
2640
        else
 
2641
            out() << "<li><div class=\"fn\"></div>";
 
2642
        out() << (*p).second << " ";
 
2643
        if ((*p).second == 1) {
 
2644
            out() << section.singularMember;
 
2645
        }
 
2646
        else {
 
2647
            out() << section.pluralMember;
 
2648
        }
 
2649
        out() << " inherited from <a href=\"" << fileName((*p).first)
 
2650
              << "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">"
 
2651
              << protect(marker->plainFullName((*p).first, relative))
 
2652
              << "</a></li>\n";
 
2653
        ++p;
 
2654
    }
 
2655
}
 
2656
 
 
2657
void HtmlGenerator::generateSynopsis(const Node *node,
 
2658
                                     const Node *relative,
 
2659
                                     CodeMarker *marker,
 
2660
                                     CodeMarker::SynopsisStyle style,
 
2661
                                     bool nameAlignment)
 
2662
{
 
2663
    QString marked = marker->markedUpSynopsis(node, relative, style);
 
2664
    QRegExp templateTag("(<[^@>]*>)");
 
2665
    if (marked.indexOf(templateTag) != -1) {
 
2666
        QString contents = protect(marked.mid(templateTag.pos(1),
 
2667
                                              templateTag.cap(1).length()));
 
2668
        marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
 
2669
                        contents);
 
2670
    }
 
2671
    marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
 
2672
                   "<i>\\1<sub>\\2</sub></i>");
 
2673
    marked.replace("<@param>", "<i>");
 
2674
    marked.replace("</@param>", "</i>");
 
2675
 
 
2676
    if (style == CodeMarker::Summary) {
 
2677
        marked.replace("<@name>", "");   // was "<b>"
 
2678
        marked.replace("</@name>", "");  // was "</b>"
 
2679
    }
 
2680
 
 
2681
    if (style == CodeMarker::SeparateList) {
 
2682
        QRegExp extraRegExp("<@extra>.*</@extra>");
 
2683
        extraRegExp.setMinimal(true);
 
2684
        marked.replace(extraRegExp, "");
 
2685
    } else {
 
2686
        marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
 
2687
        marked.replace("</@extra>", "</tt>");
 
2688
    }
 
2689
 
 
2690
    if (style != CodeMarker::Detailed) {
 
2691
        marked.replace("<@type>", "");
 
2692
        marked.replace("</@type>", "");
 
2693
    }
 
2694
    out() << highlightedCode(marked, marker, relative, style, nameAlignment);
 
2695
}
 
2696
 
 
2697
QString HtmlGenerator::highlightedCode(const QString& markedCode,
 
2698
                                       CodeMarker *marker,
 
2699
                                       const Node *relative,
 
2700
                                       CodeMarker::SynopsisStyle ,
 
2701
                                       bool nameAlignment)
 
2702
{
 
2703
    QString src = markedCode;
 
2704
    QString html;
 
2705
    QStringRef arg;
 
2706
    QStringRef par1;
 
2707
 
 
2708
    const QChar charLangle = '<';
 
2709
    const QChar charAt = '@';
 
2710
 
 
2711
    // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
 
2712
    static const QString linkTag("link");
 
2713
    bool done = false;
 
2714
    for (int i = 0, n = src.size(); i < n;) {
 
2715
        if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') {
 
2716
            if (nameAlignment && !done) {// && (i != 0)) Why was this here?
 
2717
                html += "</td><td class=\"memItemRight\" valign=\"bottom\">";
 
2718
                done = true;
 
2719
            }
 
2720
            i += 2;
 
2721
            if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
 
2722
                html += "<b>";
 
2723
                QString link = linkForNode(
 
2724
                    CodeMarker::nodeForString(par1.toString()), relative);
 
2725
                addLink(link, arg, &html);
 
2726
                html += "</b>";
 
2727
            }
 
2728
            else {
 
2729
                html += charLangle;
 
2730
                html += charAt;
 
2731
            }
 
2732
        }
 
2733
        else {
 
2734
            html += src.at(i++);
 
2735
        }
 
2736
    }
 
2737
 
 
2738
 
 
2739
    if (slow) {
 
2740
        // is this block ever used at all?
 
2741
        // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)"
 
2742
        src = html;
 
2743
        html = QString();
 
2744
        static const QString funcTag("func");
 
2745
        for (int i = 0, n = src.size(); i < n;) {
 
2746
            if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
 
2747
                i += 2;
 
2748
                if (parseArg(src, funcTag, &i, n, &arg, &par1)) {
 
2749
                    QString link = linkForNode(
 
2750
                            marker->resolveTarget(par1.toString(),
 
2751
                                                  tre,
 
2752
                                                  relative),
 
2753
                            relative);
 
2754
                    addLink(link, arg, &html);
 
2755
                    par1 = QStringRef();
 
2756
                }
 
2757
                else {
 
2758
                    html += charLangle;
 
2759
                    html += charAt;
 
2760
                }
 
2761
            }
 
2762
            else {
 
2763
                html += src.at(i++);
 
2764
            }
 
2765
        }
 
2766
    }
 
2767
 
 
2768
    // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
 
2769
    src = html;
 
2770
    html = QString();
 
2771
    static const QString typeTags[] = { "type", "headerfile", "func" };
 
2772
    for (int i = 0, n = src.size(); i < n;) {
 
2773
        if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
 
2774
            i += 2;
 
2775
            bool handled = false;
 
2776
            for (int k = 0; k != 3; ++k) {
 
2777
                if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) {
 
2778
                    par1 = QStringRef();
 
2779
                    QString link = linkForNode(
 
2780
                            marker->resolveTarget(arg.toString(), tre, relative),
 
2781
                            relative);
 
2782
                    addLink(link, arg, &html);
 
2783
                    handled = true;
 
2784
                    break;
 
2785
                }
 
2786
            }
 
2787
            if (!handled) {
 
2788
                html += charLangle;
 
2789
                html += charAt;
 
2790
            }
 
2791
        }
 
2792
        else {
 
2793
            html += src.at(i++);
 
2794
        }
 
2795
    }
 
2796
 
 
2797
    // replace all
 
2798
    // "<@comment>" -> "<span class=\"comment\">";
 
2799
    // "<@preprocessor>" -> "<span class=\"preprocessor\">";
 
2800
    // "<@string>" -> "<span class=\"string\">";
 
2801
    // "<@char>" -> "<span class=\"char\">";
 
2802
    // "</@(?:comment|preprocessor|string|char)>" -> "</span>"
 
2803
    src = html;
 
2804
    html = QString();
 
2805
    static const QString spanTags[] = {
 
2806
        "<@comment>",      "<span class=\"comment\">",
 
2807
        "<@preprocessor>", "<span class=\"preprocessor\">",
 
2808
        "<@string>",       "<span class=\"string\">",
 
2809
        "<@char>",         "<span class=\"char\">",
 
2810
        "</@comment>",     "</span>",
 
2811
        "</@preprocessor>","</span>",
 
2812
        "</@string>",      "</span>",
 
2813
        "</@char>",        "</span>"
 
2814
        // "<@char>",      "<font color=blue>",
 
2815
        // "</@char>",     "</font>",
 
2816
        // "<@func>",      "<font color=green>",
 
2817
        // "</@func>",     "</font>",
 
2818
        // "<@id>",        "<i>",
 
2819
        // "</@id>",       "</i>",
 
2820
        // "<@keyword>",   "<b>",
 
2821
        // "</@keyword>",  "</b>",
 
2822
        // "<@number>",    "<font color=yellow>",
 
2823
        // "</@number>",   "</font>",
 
2824
        // "<@op>",        "<b>",
 
2825
        // "</@op>",       "</b>",
 
2826
        // "<@param>",     "<i>",
 
2827
        // "</@param>",    "</i>",
 
2828
        // "<@string>",    "<font color=green>",
 
2829
        // "</@string>",  "</font>",
 
2830
    };
 
2831
    for (int i = 0, n = src.size(); i < n;) {
 
2832
        if (src.at(i) == charLangle) {
 
2833
            bool handled = false;
 
2834
            for (int k = 0; k != 8; ++k) {
 
2835
                const QString & tag = spanTags[2 * k];
 
2836
                if (tag == QStringRef(&src, i, tag.length())) {
 
2837
                    html += spanTags[2 * k + 1];
 
2838
                    i += tag.length();
 
2839
                    handled = true;
 
2840
                    break;
 
2841
                }
 
2842
            }
 
2843
            if (!handled) {
 
2844
                ++i;
 
2845
                if (src.at(i) == charAt ||
 
2846
                    (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) {
 
2847
                    // drop 'our' unknown tags (the ones still containing '@')
 
2848
                    while (i < n && src.at(i) != QLatin1Char('>'))
 
2849
                        ++i;
 
2850
                    ++i;
 
2851
                }
 
2852
                else {
 
2853
                    // retain all others
 
2854
                    html += charLangle;
 
2855
                }
 
2856
            }
 
2857
        }
 
2858
        else {
 
2859
            html += src.at(i);
 
2860
            ++i;
 
2861
        }
 
2862
    }
 
2863
 
 
2864
    return html;
 
2865
}
 
2866
 
 
2867
#else
 
2868
void HtmlGenerator::generateSectionList(const Section& section,
 
2869
                                        const Node *relative,
 
2870
                                        CodeMarker *marker,
 
2871
                                        CodeMarker::SynopsisStyle style)
 
2872
{
 
2873
    if (!section.members.isEmpty()) {
 
2874
        bool twoColumn = false;
 
2875
        if (style == CodeMarker::SeparateList) {
 
2876
            twoColumn = (section.members.count() >= 16);
 
2877
        }
 
2878
        else if (section.members.first()->type() == Node::Property) {
2086
2879
            twoColumn = (section.members.count() >= 5);
2087
2880
        }
2088
2881
        if (twoColumn)
2089
 
            out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\""
2090
 
                     " cellspacing=\"0\">\n"
 
2882
            out() << "<p><table class=\"generic\" width=\"100%\" border=\"0\" "
 
2883
                  << "cellpadding=\"0\" cellspacing=\"0\">\n"
2091
2884
                  << "<tr><td width=\"45%\" valign=\"top\">";
2092
2885
        out() << "<ul>\n";
2093
2886
 
2124
2917
    }
2125
2918
}
2126
2919
 
2127
 
void HtmlGenerator::generateSectionInheritedList(const Section& section, const Node *relative,
 
2920
void HtmlGenerator::generateSectionInheritedList(const Section& section,
 
2921
                                                 const Node *relative,
2128
2922
                                                 CodeMarker *marker)
2129
2923
{
2130
2924
    QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin();
2131
2925
    while (p != section.inherited.end()) {
2132
 
        out() << "<li><div class=\"fn\"></div>";
 
2926
        out() << "<li><div bar=\"2\" class=\"fn\"></div>";
2133
2927
        out() << (*p).second << " ";
2134
2928
        if ((*p).second == 1) {
2135
2929
            out() << section.singularMember;
2144
2938
    }
2145
2939
}
2146
2940
 
2147
 
void HtmlGenerator::generateLink(const Atom *atom, const Node * /* relative */, CodeMarker *marker)
 
2941
void HtmlGenerator::generateSynopsis(const Node *node,
 
2942
                                     const Node *relative,
 
2943
                                     CodeMarker *marker,
 
2944
                                     CodeMarker::SynopsisStyle style)
 
2945
{
 
2946
    QString marked = marker->markedUpSynopsis(node, relative, style);
 
2947
    QRegExp templateTag("(<[^@>]*>)");
 
2948
    if (marked.indexOf(templateTag) != -1) {
 
2949
        QString contents = protect(marked.mid(templateTag.pos(1),
 
2950
                                              templateTag.cap(1).length()));
 
2951
        marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
 
2952
                        contents);
 
2953
    }
 
2954
    marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>");
 
2955
    marked.replace("<@param>", "<i>");
 
2956
    marked.replace("</@param>", "</i>");
 
2957
 
 
2958
    if (style == CodeMarker::Summary)
 
2959
        marked.replace("@name>", "b>");
 
2960
 
 
2961
    if (style == CodeMarker::SeparateList) {
 
2962
        QRegExp extraRegExp("<@extra>.*</@extra>");
 
2963
        extraRegExp.setMinimal(true);
 
2964
        marked.replace(extraRegExp, "");
 
2965
    } else {
 
2966
        marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
 
2967
        marked.replace("</@extra>", "</tt>");
 
2968
    }
 
2969
 
 
2970
    if (style != CodeMarker::Detailed) {
 
2971
        marked.replace("<@type>", "");
 
2972
        marked.replace("</@type>", "");
 
2973
    }
 
2974
    out() << highlightedCode(marked, marker, relative);
 
2975
}
 
2976
 
 
2977
QString HtmlGenerator::highlightedCode(const QString& markedCode,
 
2978
                                       CodeMarker *marker,
 
2979
                                       const Node *relative)
 
2980
{
 
2981
    QString src = markedCode;
 
2982
    QString html;
 
2983
    QStringRef arg;
 
2984
    QStringRef par1;
 
2985
 
 
2986
    const QChar charLangle = '<';
 
2987
    const QChar charAt = '@';
 
2988
 
 
2989
    // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
 
2990
    static const QString linkTag("link");
 
2991
    for (int i = 0, n = src.size(); i < n;) {
 
2992
        if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
 
2993
            i += 2;
 
2994
            if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
 
2995
                const Node* node = CodeMarker::nodeForString(par1.toString());
 
2996
                QString link = linkForNode(node, relative);
 
2997
                addLink(link, arg, &html);
 
2998
            }
 
2999
            else {
 
3000
                html += charLangle;
 
3001
                html += charAt;
 
3002
            }
 
3003
        }
 
3004
        else {
 
3005
            html += src.at(i++);
 
3006
        }
 
3007
    }
 
3008
 
 
3009
    if (slow) {
 
3010
        // is this block ever used at all?
 
3011
        // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)"
 
3012
        src = html;
 
3013
        html = QString();
 
3014
        static const QString funcTag("func");
 
3015
        for (int i = 0, n = src.size(); i < n;) {
 
3016
            if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
 
3017
                i += 2;
 
3018
                if (parseArg(src, funcTag, &i, n, &arg, &par1)) {
 
3019
                    QString link = linkForNode(
 
3020
                            marker->resolveTarget(par1.toString(),
 
3021
                                                  tre,
 
3022
                                                  relative),
 
3023
                            relative);
 
3024
                    addLink(link, arg, &html);
 
3025
                    par1 = QStringRef();
 
3026
                }
 
3027
                else {
 
3028
                    html += charLangle;
 
3029
                    html += charAt;
 
3030
                }
 
3031
            }
 
3032
            else {
 
3033
                html += src.at(i++);
 
3034
            }
 
3035
        }
 
3036
    }
 
3037
 
 
3038
    // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
 
3039
    src = html;
 
3040
    html = QString();
 
3041
    static const QString typeTags[] = { "type", "headerfile", "func" };
 
3042
    for (int i = 0, n = src.size(); i < n;) {
 
3043
        if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
 
3044
            i += 2;
 
3045
            bool handled = false;
 
3046
            for (int k = 0; k != 3; ++k) {
 
3047
                if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) {
 
3048
                    par1 = QStringRef();
 
3049
                    QString link = linkForNode(
 
3050
                            marker->resolveTarget(arg.toString(), tre, relative),
 
3051
                            relative);
 
3052
                    addLink(link, arg, &html);
 
3053
                    handled = true;
 
3054
                    break;
 
3055
                }
 
3056
            }
 
3057
            if (!handled) {
 
3058
                html += charLangle;
 
3059
                html += charAt;
 
3060
            }
 
3061
        }
 
3062
        else {
 
3063
            html += src.at(i++);
 
3064
        }
 
3065
    }
 
3066
 
 
3067
    // replace all
 
3068
    // "<@comment>" -> "<span class=\"comment\">";
 
3069
    // "<@preprocessor>" -> "<span class=\"preprocessor\">";
 
3070
    // "<@string>" -> "<span class=\"string\">";
 
3071
    // "<@char>" -> "<span class=\"char\">";
 
3072
    // "</@(?:comment|preprocessor|string|char)>" -> "</span>"
 
3073
    src = html;
 
3074
    html = QString();
 
3075
    static const QString spanTags[] = {
 
3076
        "<@comment>",      "<span class=\"comment\">",
 
3077
        "<@preprocessor>", "<span class=\"preprocessor\">",
 
3078
        "<@string>",       "<span class=\"string\">",
 
3079
        "<@char>",         "<span class=\"char\">",
 
3080
        "</@comment>",     "</span>",
 
3081
        "</@preprocessor>","</span>",
 
3082
        "</@string>",      "</span>",
 
3083
        "</@char>",        "</span>"
 
3084
        // "<@char>",      "<font color=blue>",
 
3085
        // "</@char>",     "</font>",
 
3086
        // "<@func>",      "<font color=green>",
 
3087
        // "</@func>",     "</font>",
 
3088
        // "<@id>",        "<i>",
 
3089
        // "</@id>",       "</i>",
 
3090
        // "<@keyword>",   "<b>",
 
3091
        // "</@keyword>",  "</b>",
 
3092
        // "<@number>",    "<font color=yellow>",
 
3093
        // "</@number>",   "</font>",
 
3094
        // "<@op>",        "<b>",
 
3095
        // "</@op>",       "</b>",
 
3096
        // "<@param>",     "<i>",
 
3097
        // "</@param>",    "</i>",
 
3098
        // "<@string>",    "<font color=green>",
 
3099
        // "</@string>",  "</font>",
 
3100
    };
 
3101
    for (int i = 0, n = src.size(); i < n;) {
 
3102
        if (src.at(i) == charLangle) {
 
3103
            bool handled = false;
 
3104
            for (int k = 0; k != 8; ++k) {
 
3105
                const QString & tag = spanTags[2 * k];
 
3106
                if (tag == QStringRef(&src, i, tag.length())) {
 
3107
                    html += spanTags[2 * k + 1];
 
3108
                    i += tag.length();
 
3109
                    handled = true;
 
3110
                    break;
 
3111
                }
 
3112
            }
 
3113
            if (!handled) {
 
3114
                ++i;
 
3115
                if (src.at(i) == charAt ||
 
3116
                    (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) {
 
3117
                    // drop 'our' unknown tags (the ones still containing '@')
 
3118
                    while (i < n && src.at(i) != QLatin1Char('>'))
 
3119
                        ++i;
 
3120
                    ++i;
 
3121
                }
 
3122
                else {
 
3123
                    // retain all others
 
3124
                    html += charLangle;
 
3125
                }
 
3126
            }
 
3127
        }
 
3128
        else {
 
3129
            html += src.at(i);
 
3130
            ++i;
 
3131
        }
 
3132
    }
 
3133
 
 
3134
    return html;
 
3135
}
 
3136
#endif
 
3137
 
 
3138
void HtmlGenerator::generateLink(const Atom* atom,
 
3139
                                 const Node* /* relative */,
 
3140
                                 CodeMarker* marker)
2148
3141
{
2149
3142
    static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_");
2150
3143
 
2290
3283
#undef APPEND
2291
3284
}
2292
3285
 
2293
 
static QRegExp linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
2294
 
static QRegExp funcTag("(<@func target=\"([^\"]*)\">)(.*)(</@func>)");
2295
 
static QRegExp typeTag("(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)");
2296
 
static QRegExp spanTag("</@(?:comment|preprocessor|string|char)>");
2297
 
static QRegExp unknownTag("</?@[^>]*>");
2298
 
 
2299
 
bool parseArg(const QString &src,
2300
 
              const QString &tag,
2301
 
              int *pos,
2302
 
              int n,
2303
 
              QStringRef *contents,
2304
 
              QStringRef *par1 = 0,
2305
 
              bool debug = false)
2306
 
{
2307
 
#define SKIP_CHAR(c) \
2308
 
    if (debug) \
2309
 
        qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
2310
 
    if (i >= n || src[i] != c) { \
2311
 
        if (debug) \
2312
 
            qDebug() << " char '" << c << "' not found"; \
2313
 
        return false; \
2314
 
    } \
2315
 
    ++i;
2316
 
 
2317
 
 
2318
 
#define SKIP_SPACE \
2319
 
    while (i < n && src[i] == ' ') \
2320
 
        ++i;
2321
 
 
2322
 
    int i = *pos;
2323
 
    int j = i;
2324
 
 
2325
 
    // assume "<@" has been parsed outside
2326
 
    //SKIP_CHAR('<');
2327
 
    //SKIP_CHAR('@');
2328
 
 
2329
 
    if (tag != QStringRef(&src, i, tag.length())) {
2330
 
        if (0 && debug)
2331
 
            qDebug() << "tag " << tag << " not found at " << i;
2332
 
        return false;
2333
 
    }
2334
 
 
2335
 
    if (debug)
2336
 
        qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
2337
 
 
2338
 
    // skip tag
2339
 
    i += tag.length();
2340
 
 
2341
 
    // parse stuff like:  linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
2342
 
    if (par1) {
2343
 
        SKIP_SPACE;
2344
 
        // read parameter name
2345
 
        j = i;
2346
 
        while (i < n && src[i].isLetter())
2347
 
            ++i;
2348
 
        if (src[i] == '=') {
2349
 
            if (debug)
2350
 
                qDebug() << "read parameter" << QString(src.data() + j, i - j);
2351
 
            SKIP_CHAR('=');
2352
 
            SKIP_CHAR('"');
2353
 
            // skip parameter name
2354
 
            j = i;
2355
 
            while (i < n && src[i] != '"')
2356
 
                ++i;
2357
 
            *par1 = QStringRef(&src, j, i - j);
2358
 
            SKIP_CHAR('"');
2359
 
            SKIP_SPACE;
2360
 
        } else {
2361
 
            if (debug)
2362
 
                qDebug() << "no optional parameter found";
2363
 
        }
2364
 
    }
2365
 
    SKIP_SPACE;
2366
 
    SKIP_CHAR('>');
2367
 
 
2368
 
    // find contents up to closing "</@tag>
2369
 
    j = i;
2370
 
    for (; true; ++i) {
2371
 
        if (i + 4 + tag.length() > n)
2372
 
            return false;
2373
 
        if (src[i] != '<')
2374
 
            continue;
2375
 
        if (src[i + 1] != '/')
2376
 
            continue;
2377
 
        if (src[i + 2] != '@')
2378
 
            continue;
2379
 
        if (tag != QStringRef(&src, i + 3, tag.length()))
2380
 
            continue;
2381
 
        if (src[i + 3 + tag.length()] != '>')
2382
 
            continue;
2383
 
        break;
2384
 
    }
2385
 
 
2386
 
    *contents = QStringRef(&src, j, i - j);
2387
 
 
2388
 
    i += tag.length() + 4;
2389
 
 
2390
 
    *pos = i;
2391
 
    if (debug)
2392
 
        qDebug() << " tag " << tag << " found: pos now: " << i;
2393
 
    return true;
2394
 
#undef SKIP_CHAR
2395
 
}
2396
 
 
2397
 
static void addLink(const QString &linkTarget,
2398
 
                    const QStringRef &nestedStuff,
2399
 
                    QString *res)
2400
 
{
2401
 
    if (!linkTarget.isEmpty()) {
2402
 
        *res += "<a href=\"";
2403
 
        *res += linkTarget;
2404
 
        *res += "\">";
2405
 
        *res += nestedStuff;
2406
 
        *res += "</a>";
2407
 
    }
2408
 
    else {
2409
 
        *res += nestedStuff;
2410
 
    }
2411
 
}
2412
 
 
2413
 
QString HtmlGenerator::highlightedCode(const QString& markedCode,
2414
 
                                       CodeMarker *marker,
2415
 
                                       const Node *relative)
2416
 
{
2417
 
    QString src = markedCode;
2418
 
    QString html;
2419
 
    QStringRef arg;
2420
 
    QStringRef par1;
2421
 
 
2422
 
    const QChar charLangle = '<';
2423
 
    const QChar charAt = '@';
2424
 
 
2425
 
    // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
2426
 
    static const QString linkTag("link");
2427
 
    for (int i = 0, n = src.size(); i < n;) {
2428
 
        if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
2429
 
            i += 2;
2430
 
            if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
2431
 
                QString link = linkForNode(
2432
 
                    CodeMarker::nodeForString(par1.toString()), relative);
2433
 
                addLink(link, arg, &html);
2434
 
            }
2435
 
            else {
2436
 
                html += charLangle;
2437
 
                html += charAt;
2438
 
            }
2439
 
        }
2440
 
        else {
2441
 
            html += src.at(i++);
2442
 
        }
2443
 
    }
2444
 
 
2445
 
 
2446
 
    if (slow) {
2447
 
        // is this block ever used at all?
2448
 
        // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)"
2449
 
        src = html;
2450
 
        html = QString();
2451
 
        static const QString funcTag("func");
2452
 
        for (int i = 0, n = src.size(); i < n;) {
2453
 
            if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
2454
 
                i += 2;
2455
 
                if (parseArg(src, funcTag, &i, n, &arg, &par1)) {
2456
 
                    QString link = linkForNode(
2457
 
                            marker->resolveTarget(par1.toString(),
2458
 
                                                  tre,
2459
 
                                                  relative),
2460
 
                            relative);
2461
 
                    addLink(link, arg, &html);
2462
 
                    par1 = QStringRef();
2463
 
                }
2464
 
                else {
2465
 
                    html += charLangle;
2466
 
                    html += charAt;
2467
 
                }
2468
 
            }
2469
 
            else {
2470
 
                html += src.at(i++);
2471
 
            }
2472
 
        }
2473
 
    }
2474
 
 
2475
 
    // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
2476
 
    src = html;
2477
 
    html = QString();
2478
 
    static const QString typeTags[] = { "type", "headerfile", "func" };
2479
 
    for (int i = 0, n = src.size(); i < n;) {
2480
 
        if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
2481
 
            i += 2;
2482
 
            bool handled = false;
2483
 
            for (int k = 0; k != 3; ++k) {
2484
 
                if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) {
2485
 
                    par1 = QStringRef();
2486
 
                    QString link = linkForNode(
2487
 
                            marker->resolveTarget(arg.toString(), tre, relative),
2488
 
                            relative);
2489
 
                    addLink(link, arg, &html);
2490
 
                    handled = true;
2491
 
                    break;
2492
 
                }
2493
 
            }
2494
 
            if (!handled) {
2495
 
                html += charLangle;
2496
 
                html += charAt;
2497
 
            }
2498
 
        }
2499
 
        else {
2500
 
            html += src.at(i++);
2501
 
        }
2502
 
    }
2503
 
 
2504
 
    // replace all
2505
 
    // "<@comment>" -> "<span class=\"comment\">";
2506
 
    // "<@preprocessor>" -> "<span class=\"preprocessor\">";
2507
 
    // "<@string>" -> "<span class=\"string\">";
2508
 
    // "<@char>" -> "<span class=\"char\">";
2509
 
    // "</@(?:comment|preprocessor|string|char)>" -> "</span>"
2510
 
    src = html;
2511
 
    html = QString();
2512
 
    static const QString spanTags[] = {
2513
 
        "<@comment>",      "<span class=\"comment\">",
2514
 
        "<@preprocessor>", "<span class=\"preprocessor\">",
2515
 
        "<@string>",       "<span class=\"string\">",
2516
 
        "<@char>",         "<span class=\"char\">",
2517
 
        "</@comment>",     "</span>",
2518
 
        "</@preprocessor>","</span>",
2519
 
        "</@string>",      "</span>",
2520
 
        "</@char>",        "</span>"
2521
 
        // "<@char>",      "<font color=blue>",
2522
 
        // "</@char>",     "</font>",
2523
 
        // "<@func>",      "<font color=green>",
2524
 
        // "</@func>",     "</font>",
2525
 
        // "<@id>",        "<i>",
2526
 
        // "</@id>",       "</i>",
2527
 
        // "<@keyword>",   "<b>",
2528
 
        // "</@keyword>",  "</b>",
2529
 
        // "<@number>",    "<font color=yellow>",
2530
 
        // "</@number>",   "</font>",
2531
 
        // "<@op>",        "<b>",
2532
 
        // "</@op>",       "</b>",
2533
 
        // "<@param>",     "<i>",
2534
 
        // "</@param>",    "</i>",
2535
 
        // "<@string>",    "<font color=green>",
2536
 
        // "</@string>",  "</font>",
2537
 
    };
2538
 
    for (int i = 0, n = src.size(); i < n;) {
2539
 
        if (src.at(i) == charLangle) {
2540
 
            bool handled = false;
2541
 
            for (int k = 0; k != 8; ++k) {
2542
 
                const QString & tag = spanTags[2 * k];
2543
 
                if (tag == QStringRef(&src, i, tag.length())) {
2544
 
                    html += spanTags[2 * k + 1];
2545
 
                    i += tag.length();
2546
 
                    handled = true;
2547
 
                    break;
2548
 
                }
2549
 
            }
2550
 
            if (!handled) {
2551
 
                ++i;
2552
 
                if (src.at(i) == charAt ||
2553
 
                    (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) {
2554
 
                    // drop 'our' unknown tags (the ones still containing '@')
2555
 
                    while (i < n && src.at(i) != QLatin1Char('>'))
2556
 
                        ++i;
2557
 
                    ++i;
2558
 
                }
2559
 
                else {
2560
 
                    // retain all others
2561
 
                    html += charLangle;
2562
 
                }
2563
 
            }
2564
 
        }
2565
 
        else {
2566
 
            html += src.at(i);
2567
 
            ++i;
2568
 
        }
2569
 
    }
2570
 
 
2571
 
    return html;
2572
 
}
2573
 
 
2574
3286
QString HtmlGenerator::fileBase(const Node *node)
2575
3287
{
2576
3288
    QString result;
2618
3330
QString HtmlGenerator::fileName(const Node *node)
2619
3331
{
2620
3332
    if (node->type() == Node::Fake) {
2621
 
        if (static_cast<const FakeNode *>(node)->subType() == FakeNode::ExternalPage)
 
3333
        if (static_cast<const FakeNode *>(node)->subType() == Node::ExternalPage)
2622
3334
            return node->name();
2623
3335
    }
2624
 
 
2625
3336
    return PageGenerator::fileName(node);
2626
3337
}
2627
3338
 
2643
3354
        typedeffe = static_cast<const TypedefNode *>(node);
2644
3355
        if (typedeffe->associatedEnum()) {
2645
3356
            return refForNode(typedeffe->associatedEnum());
2646
 
        } else {
 
3357
        }
 
3358
        else {
2647
3359
            ref = node->name() + "-typedef";
2648
3360
        }
2649
3361
        break;
2651
3363
        func = static_cast<const FunctionNode *>(node);
2652
3364
        if (func->associatedProperty()) {
2653
3365
            return refForNode(func->associatedProperty());
2654
 
        } else {
 
3366
        }
 
3367
        else {
2655
3368
            ref = func->name();
2656
3369
            if (func->overloadNumber() != 1)
2657
3370
                ref += "-" + QString::number(func->overloadNumber());
2658
3371
        }
2659
3372
        break;
2660
3373
    case Node::Property:
 
3374
#ifdef QDOC_QML        
 
3375
    case Node::QmlProperty:
 
3376
#endif        
2661
3377
        ref = node->name() + "-prop";
2662
3378
        break;
 
3379
#ifdef QDOC_QML        
 
3380
    case Node::QmlSignal:
 
3381
        ref = node->name() + "-signal";
 
3382
        break;
 
3383
    case Node::QmlMethod:
 
3384
        ref = node->name() + "-method";
 
3385
        break;
 
3386
#endif        
2663
3387
    case Node::Variable:
2664
3388
        ref = node->name() + "-var";
2665
3389
        break;
2708
3432
{
2709
3433
    if (atom->type() == Atom::SectionLeft) {
2710
3434
        return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
2711
 
    } else if (atom->type() == Atom::Target) {
 
3435
    }
 
3436
    else if (atom->type() == Atom::Target) {
2712
3437
        return Doc::canonicalTitle(atom->string());
2713
 
    } else {
 
3438
    }
 
3439
    else {
2714
3440
        return QString();
2715
3441
    }
2716
3442
}
2754
3480
        out() << "<a name=\"" + refForNode(node) + "\"></a>";
2755
3481
        generateSynopsis(enume, relative, marker, CodeMarker::Detailed);
2756
3482
        out() << "<br />";
2757
 
        generateSynopsis(enume->flagsType(), relative, marker, CodeMarker::Detailed);
 
3483
        generateSynopsis(enume->flagsType(),
 
3484
                         relative,
 
3485
                         marker,
 
3486
                         CodeMarker::Detailed);
2758
3487
        out() << "</h3>\n";
2759
3488
    }
2760
3489
    else {
2778
3507
        section.members += property->resetters();
2779
3508
 
2780
3509
        if (!section.members.isEmpty()) {
2781
 
            out() << "<p>Access functions:</p>\n";
 
3510
            out() << "<p><b>Access functions:</b></p>\n";
2782
3511
            generateSectionList(section, node, marker, CodeMarker::Accessors);
2783
3512
        }
 
3513
 
 
3514
        Section notifiers;
 
3515
        notifiers.members += property->notifiers();
 
3516
        
 
3517
        if (!notifiers.members.isEmpty()) {
 
3518
            out() << "<p><b>Notifier signal:</b></p>\n";
 
3519
            //out() << "<p>This signal is emitted when the property value is changed.</p>\n";
 
3520
            generateSectionList(notifiers, node, marker, CodeMarker::Accessors);
 
3521
        }
2784
3522
    }
2785
3523
    else if (node->type() == Node::Enum) {
2786
3524
        const EnumNode *enume = static_cast<const EnumNode *>(node);
2789
3527
                  << " type is a typedef for "
2790
3528
                  << "<a href=\"qflags.html\">QFlags</a>&lt;"
2791
3529
                  << protect(enume->name())
2792
 
                  << "&gt;. It stores an OR combination of " << protect(enume->name())
 
3530
                  << "&gt;. It stores an OR combination of "
 
3531
                  << protect(enume->name())
2793
3532
                  << " values.</p>\n";
2794
3533
        }
2795
3534
    }
2803
3542
        if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) {
2804
3543
            if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
2805
3544
                QString className = (*c)->name();
2806
 
                if ((*c)->parent() && (*c)->parent()->type() == Node::Namespace &&
 
3545
                if ((*c)->parent() &&
 
3546
                    (*c)->parent()->type() == Node::Namespace &&
2807
3547
                    !(*c)->parent()->name().isEmpty())
2808
3548
                    className = (*c)->parent()->name()+"::"+className;
2809
3549
 
2811
3551
                    if ((*c)->status() == Node::Compat) {
2812
3552
                        compatClasses.insert(className, *c);
2813
3553
                    }
 
3554
                    else if ((*c)->status() == Node::Obsolete) {
 
3555
                        obsoleteClasses.insert(className, *c);
 
3556
                    }
2814
3557
                    else {
2815
3558
                        nonCompatClasses.insert(className, *c);
2816
3559
                        if ((*c)->status() == Node::Main)
2839
3582
    }
2840
3583
}
2841
3584
 
 
3585
/*!
 
3586
  For generating the "Since x.y" page.
 
3587
 */
 
3588
void HtmlGenerator::findAllSince(const InnerNode *node)
 
3589
{
 
3590
    NodeList::const_iterator c = node->childNodes().constBegin();
 
3591
    while (c != node->childNodes().constEnd()) {
 
3592
        QString sinceVersion = (*c)->since();
 
3593
        if (((*c)->access() != Node::Private) && !sinceVersion.isEmpty()) {
 
3594
            SinceVersionMap::iterator vmap = sinceVersions.find(sinceVersion);
 
3595
            if (vmap == sinceVersions.end())
 
3596
                vmap = sinceVersions.insert(sinceVersion,SinceNodeMultiMap());
 
3597
            if ((*c)->type() == Node::Function) {
 
3598
                FunctionNode *func = static_cast<FunctionNode *>(*c);
 
3599
                if ((func->status() > Node::Obsolete) &&
 
3600
                    (func->metaness() != FunctionNode::Ctor) &&
 
3601
                    (func->metaness() != FunctionNode::Dtor)) {
 
3602
                    vmap.value().insert(func->name(),(*c));
 
3603
                }
 
3604
            }
 
3605
            else if ((*c)->url().isEmpty()) {
 
3606
                if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
 
3607
                    QString className = (*c)->name();
 
3608
                    if ((*c)->parent() &&
 
3609
                        (*c)->parent()->type() == Node::Namespace &&
 
3610
                        !(*c)->parent()->name().isEmpty())
 
3611
                        className = (*c)->parent()->name()+"::"+className;
 
3612
                    vmap.value().insert(className,(*c));
 
3613
                }
 
3614
            }
 
3615
            else {
 
3616
                QString name = (*c)->name();
 
3617
                if ((*c)->parent() &&
 
3618
                    (*c)->parent()->type() == Node::Namespace &&
 
3619
                    !(*c)->parent()->name().isEmpty())
 
3620
                    name = (*c)->parent()->name()+"::"+name;
 
3621
                vmap.value().insert(name,(*c));
 
3622
                qDebug() << "GOT HEAH" << name;
 
3623
            }
 
3624
            if ((*c)->isInnerNode()) {
 
3625
                findAllSince(static_cast<InnerNode *>(*c));
 
3626
            }
 
3627
        }
 
3628
        ++c;
 
3629
    }
 
3630
}
 
3631
 
 
3632
#if 0
 
3633
    const QRegExp versionSeparator("[\\-\\.]");
 
3634
    const int minorIndex = version.indexOf(versionSeparator);
 
3635
    const int patchIndex = version.indexOf(versionSeparator, minorIndex+1);
 
3636
    version = version.left(patchIndex);
 
3637
#endif
 
3638
 
2842
3639
void HtmlGenerator::findAllFunctions(const InnerNode *node)
2843
3640
{
2844
3641
    NodeList::ConstIterator c = node->childNodes().begin();
2851
3648
                const FunctionNode *func = static_cast<const FunctionNode *>(*c);
2852
3649
                if (func->status() > Node::Obsolete && func->metaness() != FunctionNode::Ctor
2853
3650
                        && func->metaness() != FunctionNode::Dtor) {
2854
 
                    funcIndex[(*c)->name()].insert((*c)->parent()->name(), *c);
 
3651
                    funcIndex[(*c)->name()].insert(tre->fullDocumentName((*c)->parent()), *c);
2855
3652
                }
2856
3653
            }
2857
3654
        }
2901
3698
    }
2902
3699
}
2903
3700
 
2904
 
#ifdef ZZZ_QDOC_QML    
 
3701
#ifdef ZZZ_QDOC_QML
2905
3702
/*!
2906
3703
  This function finds all the qml element nodes and
2907
3704
  stores them in a map for later use.
2912
3709
    while (c != node->childNodes().constEnd()) {
2913
3710
        if ((*c)->type() == Node::Fake) {
2914
3711
            const FakeNode* fakeNode = static_cast<const FakeNode *>(*c);
2915
 
            if (fakeNode->subType() == FakeNode::QmlClass) {
2916
 
                const QmlNode* qmlNode = static_cast<const QmlNode*>(fakeNode);
2917
 
                //qDebug() << "HtmlGenerator: QML CLASS" << qmlNode->name();
 
3712
            if (fakeNode->subType() == Node::QmlClass) {
 
3713
                const QmlClassNode* qmlNode =
 
3714
                    static_cast<const QmlClassNode*>(fakeNode);
2918
3715
                const Node* n = qmlNode->classNode();
2919
 
                if (n)
2920
 
                    //qDebug() << "  FOUND IT!" << n->name();
2921
3716
            }
2922
3717
            qmlClasses.insert(fakeNode->name(),*c);
2923
3718
        }
2924
3719
        ++c;
2925
3720
    }
2926
3721
}
2927
 
#endif    
2928
 
 
2929
 
#if 0
2930
 
            else if ((*c)->isInnerNode()) {
2931
 
                findAllClasses(static_cast<InnerNode *>(*c));
2932
 
            }
2933
3722
#endif
2934
3723
 
2935
3724
int HtmlGenerator::hOffset(const Node *node)
3007
3796
QString HtmlGenerator::getLink(const Atom *atom,
3008
3797
                               const Node *relative,
3009
3798
                               CodeMarker *marker,
3010
 
                               const Node *node)
 
3799
                               const Node** node)
3011
3800
{
3012
3801
    QString link;
3013
 
    node = 0;
 
3802
    *node = 0;
 
3803
    inObsoleteLink = false;
3014
3804
 
3015
3805
    if (atom->string().contains(":") &&
3016
3806
            (atom->string().startsWith("file:")
3034
3824
 
3035
3825
        QString first = path.first().trimmed();
3036
3826
        if (first.isEmpty()) {
3037
 
            node = relative;
 
3827
            *node = relative;
3038
3828
        }
3039
3829
        else if (first.endsWith(".html")) {
3040
 
            node = tre->root()->findNode(first, Node::Fake);
 
3830
            *node = tre->root()->findNode(first, Node::Fake);
3041
3831
        }
3042
3832
        else {
3043
 
            node = marker->resolveTarget(first, tre, relative);
3044
 
            if (!node)
3045
 
                node = tre->findFakeNodeByTitle(first);
3046
 
            if (!node)
3047
 
                node = tre->findUnambiguousTarget(first, targetAtom);
 
3833
            *node = marker->resolveTarget(first, tre, relative);
 
3834
            if (!*node)
 
3835
                *node = tre->findFakeNodeByTitle(first);
 
3836
            if (!*node)
 
3837
                *node = tre->findUnambiguousTarget(first, targetAtom);
3048
3838
        }
3049
3839
 
3050
 
        if (node) {
3051
 
            if (!node->url().isEmpty())
3052
 
                return node->url();
 
3840
        if (*node) {
 
3841
            if (!(*node)->url().isEmpty())
 
3842
                return (*node)->url();
3053
3843
            else
3054
3844
                path.removeFirst();
3055
3845
        }
3056
3846
        else {
3057
 
            node = relative;
 
3847
            *node = relative;
 
3848
        }
 
3849
 
 
3850
        if (*node) {
 
3851
            if ((*node)->status() == Node::Obsolete) {
 
3852
                if (relative) {
 
3853
                    if (relative->parent() != *node) {
 
3854
                        if (relative->status() != Node::Obsolete) {
 
3855
                            bool porting = false;
 
3856
                            if (relative->type() == Node::Fake) {
 
3857
                                const FakeNode* fake = static_cast<const FakeNode*>(relative);
 
3858
                                if (fake->title().startsWith("Porting"))
 
3859
                                    porting = true;
 
3860
                            }
 
3861
                            QString name = marker->plainFullName(relative);
 
3862
                            if (!porting && !name.startsWith("Q3")) {
 
3863
                                if (obsoleteLinks) {
 
3864
                                    relative->doc().location().warning(tr("Link to obsolete item '%1' in %2")
 
3865
                                                                       .arg(atom->string())
 
3866
                                                                       .arg(name));
 
3867
                                }
 
3868
                                inObsoleteLink = true;
 
3869
                            }
 
3870
                        }
 
3871
                    }
 
3872
                }
 
3873
                else {
 
3874
                    qDebug() << "Link to Obsolete entity"
 
3875
                             << (*node)->name() << "no relative";
 
3876
                }
 
3877
            }
 
3878
#if 0                    
 
3879
            else if ((*node)->status() == Node::Deprecated) {
 
3880
                qDebug() << "Link to Deprecated entity";
 
3881
            }
 
3882
            else if ((*node)->status() == Node::Internal) {
 
3883
                qDebug() << "Link to Internal entity";
 
3884
            }
 
3885
#endif                
3058
3886
        }
3059
3887
 
3060
3888
        while (!path.isEmpty()) {
3061
 
            targetAtom = tre->findTarget(path.first(), node);
 
3889
            targetAtom = tre->findTarget(path.first(), *node);
3062
3890
            if (targetAtom == 0)
3063
3891
                break;
3064
3892
            path.removeFirst();
3065
3893
        }
3066
3894
 
3067
3895
        if (path.isEmpty()) {
3068
 
            link = linkForNode(node, relative);
 
3896
            link = linkForNode(*node, relative);
3069
3897
            if (targetAtom)
3070
 
                link += "#" + refForAtom(targetAtom, node);
 
3898
                link += "#" + refForAtom(targetAtom, *node);
3071
3899
        }
3072
3900
    }
3073
3901
    return link;
3186
4014
                out() << "</i>";
3187
4015
        }
3188
4016
        else {
 
4017
            if (inObsoleteLink) {
 
4018
                out() << "<sup>(obsolete)</sup>";
 
4019
            }
3189
4020
            out() << "</a>";
3190
4021
        }
3191
4022
    }
3192
4023
    inLink = false;
 
4024
    inObsoleteLink = false;
3193
4025
}
3194
4026
 
3195
4027
QT_END_NAMESPACE
 
4028
 
 
4029
#ifdef QDOC_QML
 
4030
 
 
4031
/*!
 
4032
  Generates the summary for for the \a section. Only used for
 
4033
  sections of QML element documentation.
 
4034
 
 
4035
  Currently handles only the QML property group.
 
4036
 */
 
4037
void HtmlGenerator::generateQmlSummary(const Section& section,
 
4038
                                       const Node *relative,
 
4039
                                       CodeMarker *marker)
 
4040
{
 
4041
    if (!section.members.isEmpty()) {
 
4042
        NodeList::ConstIterator m;
 
4043
        int count = section.members.size();
 
4044
        bool twoColumn = false;
 
4045
        if (section.members.first()->type() == Node::QmlProperty) {
 
4046
            twoColumn = (count >= 5);
 
4047
        }
 
4048
        if (twoColumn)
 
4049
            out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\""
 
4050
                     " cellspacing=\"0\">\n"
 
4051
                  << "<tr><td width=\"45%\" valign=\"top\">";
 
4052
        out() << "<ul>\n";
 
4053
 
 
4054
        int row = 0;
 
4055
        m = section.members.begin();
 
4056
        while (m != section.members.end()) {
 
4057
            if (twoColumn && row == (int) (count + 1) / 2)
 
4058
                out() << "</ul></td><td valign=\"top\"><ul>\n";
 
4059
            out() << "<li><div class=\"fn\"></div>";
 
4060
            generateQmlItem(*m,relative,marker,true);
 
4061
            out() << "</li>\n";
 
4062
            row++;
 
4063
            ++m;
 
4064
        }
 
4065
        out() << "</ul>\n";
 
4066
        if (twoColumn)
 
4067
            out() << "</td></tr>\n</table></p>\n";
 
4068
    }
 
4069
}
 
4070
 
 
4071
/*!
 
4072
  Outputs the html detailed documentation for a section
 
4073
  on a QML element reference page.
 
4074
 */
 
4075
void HtmlGenerator::generateDetailedQmlMember(const Node *node,
 
4076
                                              const InnerNode *relative,
 
4077
                                              CodeMarker *marker)
 
4078
{
 
4079
    const QmlPropertyNode* qpn = 0;
 
4080
    generateMacRef(node, marker);
 
4081
    out() << "<div class=\"qmlitem\">";
 
4082
    if (node->subType() == Node::QmlPropertyGroup) {
 
4083
        const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
 
4084
        NodeList::ConstIterator p = qpgn->childNodes().begin();
 
4085
        out() << "<div class=\"qmlproto\">";
 
4086
        out() << "<table class=\"qmlname\">";
 
4087
 
 
4088
        while (p != qpgn->childNodes().end()) {
 
4089
            if ((*p)->type() == Node::QmlProperty) {
 
4090
                qpn = static_cast<const QmlPropertyNode*>(*p);
 
4091
                out() << "<tr><td>";
 
4092
                out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
 
4093
                generateQmlItem(qpn, relative, marker, false);
 
4094
                out() << "</td></tr>";
 
4095
                if (qpgn->isDefault()) {
 
4096
                    out() << "</table>"
 
4097
                          << "</div></div>"
 
4098
                          << "<div class=\"qmlitem\">"
 
4099
                          << "<div class=\"qmlproto\">"
 
4100
                          << "<table class=\"qmlname\">"
 
4101
                          << "<tr><td><font color=\"green\">"
 
4102
                          << "default</font></td></tr>";
 
4103
                }
 
4104
            }
 
4105
            ++p;
 
4106
        }
 
4107
        out() << "</table>";
 
4108
        out() << "</div>";
 
4109
    }
 
4110
    else if (node->type() == Node::QmlSignal) {
 
4111
        const QmlSignalNode* qsn = static_cast<const QmlSignalNode*>(node);
 
4112
        out() << "<div class=\"qmlproto\">";
 
4113
        out() << "<table class=\"qmlname\">";
 
4114
        out() << "<tr><td>";
 
4115
        out() << "<a name=\"" + refForNode(qsn) + "\"></a>";
 
4116
        generateQmlItem(qsn,relative,marker,false);
 
4117
        out() << "</td></tr>";
 
4118
        out() << "</table>";
 
4119
        out() << "</div>";
 
4120
    }
 
4121
    else if (node->type() == Node::QmlMethod) {
 
4122
        const QmlMethodNode* qmn = static_cast<const QmlMethodNode*>(node);
 
4123
        out() << "<div class=\"qmlproto\">";
 
4124
        out() << "<table class=\"qmlname\">";
 
4125
        out() << "<tr><td>";
 
4126
        out() << "<a name=\"" + refForNode(qmn) + "\"></a>";
 
4127
        generateQmlItem(qmn,relative,marker,false);
 
4128
        out() << "</td></tr>";
 
4129
        out() << "</table>";
 
4130
        out() << "</div>";
 
4131
    }
 
4132
    out() << "<div class=\"qmldoc\">";
 
4133
    generateStatus(node, marker);
 
4134
    generateBody(node, marker);
 
4135
    generateThreadSafeness(node, marker);
 
4136
    generateSince(node, marker);
 
4137
    generateAlsoList(node, marker);
 
4138
    out() << "</div>";
 
4139
    out() << "</div>";
 
4140
}
 
4141
 
 
4142
/*!
 
4143
  Output the "Inherits" line for the QML element,
 
4144
  if there should be one.
 
4145
 */
 
4146
void HtmlGenerator::generateQmlInherits(const QmlClassNode* cn,
 
4147
                                        CodeMarker* marker)
 
4148
{
 
4149
    if (cn && !cn->links().empty()) {
 
4150
        if (cn->links().contains(Node::InheritsLink)) {
 
4151
            QPair<QString,QString> linkPair;
 
4152
            linkPair = cn->links()[Node::InheritsLink];
 
4153
            QStringList strList(linkPair.first);
 
4154
            const Node* n = tre->findNode(strList,Node::Fake);
 
4155
            if (n && n->subType() == Node::QmlClass) {
 
4156
                const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
 
4157
                out() << "<p style=\"text-align: center\">";
 
4158
                Text text;
 
4159
                text << "[Inherits ";
 
4160
                text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
 
4161
                text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
 
4162
                text << Atom(Atom::String, linkPair.second);
 
4163
                text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
 
4164
                text << "]";
 
4165
                generateText(text, cn, marker);
 
4166
                out() << "</p>";
 
4167
            }
 
4168
        }
 
4169
    }
 
4170
}
 
4171
 
 
4172
/*!
 
4173
  Output the "[Xxx instantiates the C++ class QFxXxx]"
 
4174
  line for the QML element, if there should be one.
 
4175
 
 
4176
  If there is no class node, or if the class node status
 
4177
  is set to Node::Internal, do nothing. 
 
4178
 */
 
4179
void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn,
 
4180
                                            CodeMarker* marker)
 
4181
{
 
4182
    const ClassNode* cn = qcn->classNode();
 
4183
    if (cn && (cn->status() != Node::Internal)) {
 
4184
        out() << "<p style=\"text-align: center\">";
 
4185
        Text text;
 
4186
        text << "[";
 
4187
        text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
 
4188
        text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
 
4189
        text << Atom(Atom::String, qcn->name());
 
4190
        text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
 
4191
        text << " instantiates the C++ class ";
 
4192
        text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
 
4193
        text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
 
4194
        text << Atom(Atom::String, cn->name());
 
4195
        text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
 
4196
        text << "]";
 
4197
        generateText(text, qcn, marker);
 
4198
        out() << "</p>";
 
4199
    }
 
4200
}
 
4201
 
 
4202
/*!
 
4203
  Output the "[QFxXxx is instantiated by QML element Xxx]"
 
4204
  line for the class, if there should be one.
 
4205
 
 
4206
  If there is no QML element, or if the class node status
 
4207
  is set to Node::Internal, do nothing. 
 
4208
 */
 
4209
void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn,
 
4210
                                           CodeMarker* marker)
 
4211
{
 
4212
    if (cn &&  cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) {
 
4213
        const Node* n = tre->root()->findNode(cn->qmlElement(),Node::Fake);
 
4214
        if (n && n->subType() == Node::QmlClass) {
 
4215
            out() << "<p style=\"text-align: center\">";
 
4216
            Text text;
 
4217
            text << "[";
 
4218
            text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
 
4219
            text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
 
4220
            text << Atom(Atom::String, cn->name());
 
4221
            text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
 
4222
            text << " is instantiated by QML element ";
 
4223
            text << Atom(Atom::LinkNode,CodeMarker::stringForNode(n));
 
4224
            text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
 
4225
            text << Atom(Atom::String, n->name());
 
4226
            text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
 
4227
            text << "]";
 
4228
            generateText(text, cn, marker);
 
4229
            out() << "</p>";
 
4230
        }
 
4231
    }
 
4232
}
 
4233
 
 
4234
#endif