diff options
-rw-r--r-- | src/corelib/tools/qeasingcurve.cpp | 20 | ||||
-rw-r--r-- | src/gui/widgets/qscrollbar.cpp | 39 | ||||
-rw-r--r-- | tools/qdoc3/atom.cpp | 27 | ||||
-rw-r--r-- | tools/qdoc3/atom.h | 1 | ||||
-rw-r--r-- | tools/qdoc3/ditaxmlgenerator.cpp | 4180 | ||||
-rw-r--r-- | tools/qdoc3/ditaxmlgenerator.h | 277 | ||||
-rw-r--r-- | tools/qdoc3/generator.cpp | 91 | ||||
-rw-r--r-- | tools/qdoc3/generator.h | 3 | ||||
-rw-r--r-- | tools/qdoc3/htmlgenerator.cpp | 4 | ||||
-rw-r--r-- | tools/qdoc3/htmlgenerator.h | 4 | ||||
-rw-r--r-- | tools/qdoc3/node.cpp | 4 | ||||
-rw-r--r-- | tools/qdoc3/pagegenerator.cpp | 27 | ||||
-rw-r--r-- | tools/qdoc3/pagegenerator.h | 18 | ||||
-rw-r--r-- | tools/qdoc3/test/qt-ditaxml.qdocconf | 31 | ||||
-rw-r--r-- | tools/qdoc3/text.cpp | 4 |
15 files changed, 2549 insertions, 2181 deletions
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 7fe9170..aee9356 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -92,14 +92,18 @@ animation.setEasingCurve(QEasingCurve::InOutQuad); \endcode - The ability to set an amplitude, overshoot, or period depends on the QEasingCurve type. Amplitude access - is available to curves that behave as springs such as elastic and bounce curves. Changing the amplitude changes - the height of the curve. Period access is only available to elastic curves and setting a higher period slows - the rate of bounce. Only curves that have "boomerang" behaviors such as the InBack, OutBack, InOutBack, and OutInBack - have overshoot settings. These curves will interpolate beyond the end points and return to the end point, - acting similar to a boomerang. - - The \l{Easing Curves Example} contains samples of QEasingCurve types and lets you change the curve settings. + The ability to set an amplitude, overshoot, or period depends on + the QEasingCurve type. Amplitude access is available to curves + that behave as springs such as elastic and bounce curves. Changing + the amplitude changes the height of the curve. Period access is + only available to elastic curves and setting a higher period slows + the rate of bounce. Only curves that have "boomerang" behaviors + such as the InBack, OutBack, InOutBack, and OutInBack have + overshoot settings. These curves will interpolate beyond the end + points and return to the end point, acting similar to a boomerang. + + The \l{Easing Curves Example} contains samples of QEasingCurve + types and lets you change the curve settings. */ diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp index 4ee9f27..a07e2cb 100644 --- a/src/gui/widgets/qscrollbar.cpp +++ b/src/gui/widgets/qscrollbar.cpp @@ -82,21 +82,21 @@ QT_BEGIN_NAMESPACE needs. \table - \row \i \image qscrollbar-picture.png - \i Scroll bars typically include four separate controls: a slider, + \row \o \image qscrollbar-picture.png + \o Scroll bars typically include four separate controls: a slider, scroll arrows, and a page control. \list - \i a. The slider provides a way to quickly go to any part of the + \o a. The slider provides a way to quickly go to any part of the document, but does not support accurate navigation within large documents. - \i b. The scroll arrows are push buttons which can be used to accurately + \o b. The scroll arrows are push buttons which can be used to accurately navigate to a particular place in a document. For a vertical scroll bar connected to a text editor, these typically move the current position one "line" up or down, and adjust the position of the slider by a small amount. In editors and list boxes a "line" might mean one line of text; in an image viewer it might mean 20 pixels. - \i c. The page control is the area over which the slider is dragged (the + \o c. The page control is the area over which the slider is dragged (the scroll bar's background). Clicking here moves the scroll bar towards the click by one "page". This value is usually the same as the length of the slider. @@ -134,13 +134,12 @@ QT_BEGIN_NAMESPACE value of 80. This would give us a scroll bar with five "pages". \table - \row \i \inlineimage qscrollbar-values.png - \i The relationship between a document length, the range of values used + \row \o \inlineimage qscrollbar-values.png + \o The relationship between a document length, the range of values used in a scroll bar, and the page step is simple in many common situations. The scroll bar's range of values is determined by subtracting a chosen page step from some value representing the length of the document. In such cases, the following equation is useful: - \e{document length} = maximum() - minimum() + pageStep(). \endtable @@ -153,18 +152,18 @@ QT_BEGIN_NAMESPACE ScrollBar inherits a comprehensive set of signals from QAbstractSlider: \list - \i \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the + \o \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the scroll bar's value has changed. The tracking() determines whether this signal is emitted during user interaction. - \i \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the + \o \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the scroll bar's range of values has changed. - \i \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when + \o \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when the user starts to drag the slider. - \i \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user + \o \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user drags the slider. - \i \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when + \o \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when the user releases the slider. - \i \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted + \o \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted when the scroll bar is changed by user interaction or via the \l{QAbstractSlider::triggerAction()}{triggerAction()} function. \endlist @@ -173,12 +172,12 @@ QT_BEGIN_NAMESPACE default focusPolicy() of Qt::NoFocus. Use setFocusPolicy() to enable keyboard interaction with the scroll bar: \list - \i Left/Right move a horizontal scroll bar by one single step. - \i Up/Down move a vertical scroll bar by one single step. - \i PageUp moves up one page. - \i PageDown moves down one page. - \i Home moves to the start (mininum). - \i End moves to the end (maximum). + \o Left/Right move a horizontal scroll bar by one single step. + \o Up/Down move a vertical scroll bar by one single step. + \o PageUp moves up one page. + \o PageDown moves down one page. + \o Home moves to the start (mininum). + \o End moves to the end (maximum). \endlist The slider itself can be controlled by using the diff --git a/tools/qdoc3/atom.cpp b/tools/qdoc3/atom.cpp index 88f44ea..d18c3c4 100644 --- a/tools/qdoc3/atom.cpp +++ b/tools/qdoc3/atom.cpp @@ -190,6 +190,7 @@ static const struct { { "FormattingLeft", Atom::FormattingLeft }, { "FormattingRight", Atom::FormattingRight }, { "GeneratedList", Atom::GeneratedList }, + { "GuidLink", Atom::GuidLink}, { "Image", Atom::Image }, { "ImageText", Atom::ImageText }, { "InlineImage", Atom::InlineImage }, @@ -241,25 +242,25 @@ static const struct { { 0, 0 } }; -/*! \fn Atom::Atom( Type type, const QString& string ) +/*! \fn Atom::Atom(Type type, const QString& string) Constructs an atom (\a type, \a string) outside of any atom list. */ -/*! \fn Atom( Atom *prev, Type type, const QString& string ) +/*! \fn Atom(Atom *prev, Type type, const QString& string) Constructs an atom (\a type, \a string) that follows \a prev in \a prev's atom list. */ -/*! \fn void Atom::appendChar( QChar ch ) +/*! \fn void Atom::appendChar(QChar ch) Appends \a ch to the string parameter of this atom. \also string() */ -/*! \fn void Atom::appendString( const QString& string ) +/*! \fn void Atom::appendString(const QString& string) Appends \a string to the string parameter of this atom. @@ -316,18 +317,18 @@ QString Atom::typeString() const { static bool deja = false; - if ( !deja ) { + if (!deja) { int i = 0; - while ( atms[i].english != 0 ) { - if ( atms[i].no != i ) - Location::internalError( tr("atom %1 missing").arg(i) ); + while (atms[i].english != 0) { + if (atms[i].no != i) + Location::internalError(tr("atom %1 missing").arg(i)); i++; } deja = true; } int i = (int) type(); - if ( i < 0 || i > (int) Last ) + if (i < 0 || i > (int) Last) return QLatin1String("Invalid"); return QLatin1String(atms[i].english); } @@ -346,10 +347,10 @@ QString Atom::typeString() const void Atom::dump() const { QString str = string(); - str.replace( "\\", "\\\\" ); - str.replace( "\"", "\\\"" ); - str.replace( "\n", "\\n" ); - str.replace( QRegExp("[^\x20-\x7e]"), "?" ); + str.replace("\\", "\\\\"); + str.replace("\"", "\\\""); + str.replace("\n", "\\n"); + str.replace(QRegExp("[^\x20-\x7e]"), "?"); if (!str.isEmpty()) str = " \"" + str + "\""; fprintf(stderr, diff --git a/tools/qdoc3/atom.h b/tools/qdoc3/atom.h index 70fbae9..13df07b 100644 --- a/tools/qdoc3/atom.h +++ b/tools/qdoc3/atom.h @@ -83,6 +83,7 @@ class Atom FormattingLeft, FormattingRight, GeneratedList, + GuidLink, Image, ImageText, InlineImage, diff --git a/tools/qdoc3/ditaxmlgenerator.cpp b/tools/qdoc3/ditaxmlgenerator.cpp index a83a321..9e41a00 100644 --- a/tools/qdoc3/ditaxmlgenerator.cpp +++ b/tools/qdoc3/ditaxmlgenerator.cpp @@ -1,4 +1,3 @@ - /**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). @@ -61,6 +60,9 @@ QT_BEGIN_NAMESPACE #define COMMAND_VERSION Doc::alias("version") int DitaXmlGenerator::id = 0; +bool DitaXmlGenerator::inApiDesc = false; +bool DitaXmlGenerator::inSection = false; +bool DitaXmlGenerator::inDetailedDescription = false; #define cxxapi_d_xref Doc::alias("cxxapi-d-xref") #define cxxclass Doc::alias("cxxclass") @@ -356,28 +358,33 @@ QString DitaXmlGenerator::sinceTitles[] = static bool showBrokenLinks = false; -static void addLink(const QString &linkTarget, - const QStringRef &nestedStuff, - QString *res) +/*! + Appends an <xref> element to the current XML stream + with the \a href attribute and the \a text. + */ +void DitaXmlGenerator::addLink(const QString& href, + const QStringRef& text) { - if (!linkTarget.isEmpty()) { - *res += "<xref href=\""; - *res += linkTarget; - *res += "\">"; - *res += nestedStuff; - *res += "</xref>"; + if (!href.isEmpty()) { + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href", href); + xmlWriter().writeCharacters(text.toString()); + xmlWriter().writeEndElement(); // </xref> } else { - *res += nestedStuff; + xmlWriter().writeCharacters(text.toString()); } } - +/*! + The default constructor. + */ DitaXmlGenerator::DitaXmlGenerator() : inLink(false), inContents(false), inSectionHeading(false), inTableHeader(false), + inTableBody(false), numTableRows(0), threeColumnEnumValueTable(true), offlineDocs(true), @@ -385,15 +392,27 @@ DitaXmlGenerator::DitaXmlGenerator() myTree(0), slow(false), obsoleteLinks(false), - noLinks(0) + noLinks(false), + tableColumnCount(0) { + // nothing yet. } +/*! + The destructor has nothing to do. + */ DitaXmlGenerator::~DitaXmlGenerator() { - // nothing yet. + GuidMaps::iterator i = guidMaps.begin(); + while (i != guidMaps.end()) { + delete i.value(); + ++i; + } } +/*! + A lot of internal structures are initialized. + */ void DitaXmlGenerator::initializeGenerator(const Config &config) { static const struct { @@ -490,11 +509,17 @@ void DitaXmlGenerator::initializeGenerator(const Config &config) } +/*! + All this does is call the same function in the base class. + */ void DitaXmlGenerator::terminateGenerator() { Generator::terminateGenerator(); } +/*! + Returns "DITAXML". + */ QString DitaXmlGenerator::format() { return "DITAXML"; @@ -506,11 +531,22 @@ QString DitaXmlGenerator::format() */ QString DitaXmlGenerator::writeGuidAttribute(QString text) { - QString guid = lookupGuid(text); - writer.writeAttribute("id",guid); + QString guid = lookupGuid(outFileName(),text); + xmlWriter().writeAttribute("id",guid); return guid; } + +/*! + Write's the GUID for the \a node to the current XML stream + as an "id" attribute. If the \a node doesn't yet have a GUID, + one is generated. + */ +void DitaXmlGenerator::writeGuidAttribute(Node* node) +{ + xmlWriter().writeAttribute("id",node->guid()); +} + /*! Looks up \a text in the GUID map. If it finds \a text, it returns the associated GUID. Otherwise it inserts @@ -528,6 +564,41 @@ QString DitaXmlGenerator::lookupGuid(QString text) } /*! + First, look up the GUID map for \a fileName. If there isn't + a GUID map for \a fileName, create one and insert it into + the map of GUID maps. Then look up \a text in that GUID map. + If \a text is found, return the associated GUID. Otherwise, + insert \a text into the GUID map with a new GUID, and return + the new GUID. + */ +QString DitaXmlGenerator::lookupGuid(const QString& fileName, const QString& text) +{ + GuidMap* gm = lookupGuidMap(fileName); + GuidMap::const_iterator i = gm->find(text); + if (i != gm->end()) + return i.value(); + QString guid = QUuid::createUuid().toString(); + gm->insert(text,guid); + return guid; +} + +/*! + Looks up \a fileName in the map of GUID maps. If it finds + \a fileName, it returns a pointer to the associated GUID + map. Otherwise it creates a new GUID map and inserts it + into the map of GUID maps with \a fileName as its key. + */ +GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName) +{ + GuidMaps::const_iterator i = guidMaps.find(fileName); + if (i != guidMaps.end()) + return i.value(); + GuidMap* gm = new GuidMap; + guidMaps.insert(fileName,gm); + return gm; +} + +/*! This is where the DITA XML files are written. \note The file generation is done in the base class, PageGenerator::generateTree(). @@ -567,6 +638,33 @@ void DitaXmlGenerator::startText(const Node* /* relative */, sectionNumber.clear(); } +static int countTableColumns(const Atom* t) +{ + int result = 0; + if (t->type() == Atom::TableHeaderLeft) { + while (t->type() == Atom::TableHeaderLeft) { + int count = 0; + t = t->next(); + while (t->type() != Atom::TableHeaderRight) { + if (t->type() == Atom::TableItemLeft) + ++count; + t = t->next(); + } + if (count > result) + result = count; + t = t->next(); + } + } + else if (t->type() == Atom::TableRowLeft) { + while (t->type() != Atom::TableRowRight) { + if (t->type() == Atom::TableItemLeft) + ++result; + t = t->next(); + } + } + return result; +} + /*! Generate html from an instance of Atom. */ @@ -577,16 +675,16 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, int skipAhead = 0; QString hx; static bool in_para = false; - QString guid; - + QString guid, hc; + switch (atom->type()) { case Atom::AbstractLeft: break; case Atom::AbstractRight: break; case Atom::AutoLink: - if ((noLinks > 0) && !inLink && !inContents && !inSectionHeading) { - const Node *node = 0; + if (!noLinks && !inLink && !inContents && !inSectionHeading) { + const Node* node = 0; QString link = getLink(atom, relative, marker, &node); if (!link.isEmpty()) { beginLink(link, node, relative, marker); @@ -594,11 +692,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, endLink(); } else { - writer.writeCharacters(protectEnc(atom->string())); + xmlWriter().writeCharacters(protectEnc(atom->string())); } } else { - writer.writeCharacters(protectEnc(atom->string())); + xmlWriter().writeCharacters(protectEnc(atom->string())); } break; case Atom::BaseName: @@ -608,7 +706,12 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, skipAhead = skipAtoms(atom, Atom::BriefRight); break; } - writer.writeStartElement(SHORTDESC); + if (inApiDesc || inSection) + xmlWriter().writeStartElement("p"); + else { + noLinks = true; + xmlWriter().writeStartElement(SHORTDESC); + } if (relative->type() == Node::Property || relative->type() == Node::Variable) { QString str; @@ -623,102 +726,98 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, str[0] = str[0].toLower(); if (str.right(1) == ".") str.truncate(str.length() - 1); - writer.writeCharacters("This "); + xmlWriter().writeCharacters("This "); if (relative->type() == Node::Property) - writer.writeCharacters("property"); + xmlWriter().writeCharacters("property"); else - writer.writeCharacters("variable"); + xmlWriter().writeCharacters("variable"); QStringList words = str.split(" "); if (!(words.first() == "contains" || words.first() == "specifies" || words.first() == "describes" || words.first() == "defines" || words.first() == "holds" || words.first() == "determines")) - writer.writeCharacters(" holds "); + xmlWriter().writeCharacters(" holds "); else - writer.writeCharacters(" "); - writer.writeCharacters(str + "."); + xmlWriter().writeCharacters(" "); + xmlWriter().writeCharacters(str + "."); } break; case Atom::BriefRight: if (relative->type() != Node::Fake) { - writer.writeEndElement(); // </shortdesc> + xmlWriter().writeEndElement(); // </shortdesc> or </p> + noLinks = false; } break; case Atom::C: - writer.writeStartElement(formattingLeftMap()[ATOM_FORMATTING_TELETYPE]); + xmlWriter().writeStartElement(formattingLeftMap()[ATOM_FORMATTING_TELETYPE]); if (inLink) { - writer.writeCharacters(protectEnc(plainCode(atom->string()))); + xmlWriter().writeCharacters(protectEnc(plainCode(atom->string()))); } else { - writer.writeCharacters(highlightedCode(atom->string(), marker, relative)); + writeText(atom->string(), marker, relative); } - writer.writeEndElement(); // sse writeStartElement() above + xmlWriter().writeEndElement(); // sse writeStartElement() above break; case Atom::Code: - writer.writeStartElement("pre"); - writer.writeAttribute("outputclass","highlightedCode"); - writer.writeCharacters(trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), - marker, - relative))); - writer.writeEndElement(); // </pre> + { + xmlWriter().writeStartElement("pre"); + xmlWriter().writeAttribute("outputclass","highlightedcode"); + QString chars = trimmedTrailing(atom->string()); + writeText(chars, marker, relative); + xmlWriter().writeEndElement(); // </pre> + } break; -#ifdef QDOC_QML case Atom::Qml: - writer.writeStartElement("pre"); - writer.writeAttribute("outputclass","highlightedCode"); - writer.writeCharacters(trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), - marker, - relative))); - writer.writeEndElement(); // pre + xmlWriter().writeStartElement("pre"); + xmlWriter().writeAttribute("outputclass","highlightedcode"); + writeText(trimmedTrailing(atom->string()), marker, relative); + xmlWriter().writeEndElement(); // </pre> break; -#endif case Atom::CodeNew: - writer.writeStartElement("p"); - writer.writeCharacters("you can rewrite it as"); - writer.writeEndElement(); // </p> - writer.writeStartElement("pre"); - writer.writeAttribute("outputclass","highlightedCode"); - writer.writeCharacters(trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), - marker, - relative))); - writer.writeEndElement(); // </pre> + xmlWriter().writeStartElement("p"); + xmlWriter().writeCharacters("you can rewrite it as"); + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeStartElement("pre"); + xmlWriter().writeAttribute("outputclass","highlightedcode"); + writeText(trimmedTrailing(atom->string()), marker, relative); + xmlWriter().writeEndElement(); // </pre> break; case Atom::CodeOld: - writer.writeStartElement("p"); - writer.writeCharacters("For example, if you have code like"); - writer.writeEndElement(); // </p> + xmlWriter().writeStartElement("p"); + xmlWriter().writeCharacters("For example, if you have code like"); + xmlWriter().writeEndElement(); // </p> // fallthrough case Atom::CodeBad: - writer.writeStartElement("pre"); - writer.writeAttribute("outputclass","highlightedCode"); - writer.writeCharacters(trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string()))))); - writer.writeEndElement(); // </pre> + xmlWriter().writeStartElement("pre"); + xmlWriter().writeAttribute("outputclass","highlightedcode"); + xmlWriter().writeCharacters(trimmedTrailing(protectEnc(plainCode(atom->string())))); + xmlWriter().writeEndElement(); // </pre> break; case Atom::FootnoteLeft: // ### For now if (in_para) { - writer.writeEndElement(); // </p> + xmlWriter().writeEndElement(); // </p> in_para = false; } - writer.writeCharacters("<!-- "); + xmlWriter().writeCharacters("<!-- "); break; case Atom::FootnoteRight: // ### For now - writer.writeCharacters("-->"); + xmlWriter().writeCharacters("-->"); break; case Atom::FormatElse: case Atom::FormatEndif: case Atom::FormatIf: break; case Atom::FormattingLeft: - writer.writeStartElement(formattingLeftMap()[atom->string()]); + xmlWriter().writeStartElement(formattingLeftMap()[atom->string()]); if (atom->string() == ATOM_FORMATTING_PARAMETER) { if (atom->next() != 0 && atom->next()->type() == Atom::String) { QRegExp subscriptRegExp("([a-z]+)_([0-9n])"); if (subscriptRegExp.exactMatch(atom->next()->string())) { - writer.writeCharacters(subscriptRegExp.cap(1)); - writer.writeStartElement("sub"); - writer.writeCharacters(subscriptRegExp.cap(2)); - writer.writeEndElement(); // </sub> + xmlWriter().writeCharacters(subscriptRegExp.cap(1)); + xmlWriter().writeStartElement("sub"); + xmlWriter().writeCharacters(subscriptRegExp.cap(2)); + xmlWriter().writeEndElement(); // </sub> skipAhead = 1; } } @@ -729,7 +828,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, endLink(); } else { - writer.writeEndElement(); // ? + xmlWriter().writeEndElement(); // ? } break; case Atom::AnnotatedList: @@ -835,19 +934,6 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, generateAnnotatedList(fake, marker, groupMembersMap); } } - else if (atom->string() == "relatedinline") { - const FakeNode *fake = static_cast<const FakeNode *>(relative); - if (fake && !fake->groupMembers().isEmpty()) { - // Reverse the list into the original scan order. - // Should be sorted. But on what? It may not be a - // regular class or page definition. - QList<const Node *> list; - foreach (const Node *node, fake->groupMembers()) - list.prepend(node); - foreach (const Node *node, list) - generateBody(node, marker); - } - } break; case Atom::SinceList: { @@ -931,31 +1017,26 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, /* First generate the table of contents. */ - writer.writeStartElement("ul"); + xmlWriter().writeStartElement("ul"); s = sections.constBegin(); while (s != sections.constEnd()) { if (!(*s).members.isEmpty()) { - - writer.writeStartElement("li"); - writer.writeStartElement("xref"); - writer.writeAttribute("href",QString("#" + Doc::canonicalTitle((*s).name))); - writer.writeCharacters((*s).name); - writer.writeEndElement(); // </xref> - writer.writeEndElement(); // </li> + writeXrefListItem(QString("#" + Doc::canonicalTitle((*s).name)), + (*s).name); } ++s; } - writer.writeEndElement(); // </ul> + xmlWriter().writeEndElement(); // </ul> int idx = 0; s = sections.constBegin(); while (s != sections.constEnd()) { if (!(*s).members.isEmpty()) { - writer.writeStartElement("p"); + xmlWriter().writeStartElement("p"); writeGuidAttribute(Doc::canonicalTitle((*s).name)); - writer.writeAttribute("outputclass","h3"); - writer.writeCharacters(protectEnc((*s).name)); - writer.writeEndElement(); // </p> + xmlWriter().writeAttribute("outputclass","h3"); + xmlWriter().writeCharacters(protectEnc((*s).name)); + xmlWriter().writeEndElement(); // </p> if (idx == Class) generateCompactList(0, marker, ncmap.value(), false, QString("Q")); else if (idx == QmlClass) @@ -975,23 +1056,24 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, pmap = parentmaps.begin(); while (pmap != parentmaps.end()) { NodeList nlist = pmap->values(); - writer.writeStartElement("p"); - writer.writeCharacters("Class "); - writer.writeStartElement("xref"); - writer.writeAttribute("href",linkForNode(pmap.key(), 0)); + xmlWriter().writeStartElement("p"); + xmlWriter().writeCharacters("Class "); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",linkForNode(pmap.key(), 0)); QStringList pieces = fullName(pmap.key(), 0, marker).split("::"); - writer.writeCharacters(protectEnc(pieces.last())); - writer.writeEndElement(); // </xref> - writer.writeCharacters(":"); - writer.writeEndElement(); // </p> + xmlWriter().writeCharacters(protectEnc(pieces.last())); + xmlWriter().writeEndElement(); // </xref> + xmlWriter().writeCharacters(":"); + xmlWriter().writeEndElement(); // </p> generateSection(nlist, 0, marker, CodeMarker::Summary); - writer.writeEmptyElement("br"); + xmlWriter().writeEmptyElement("br"); ++pmap; } } - else + else { generateSection(s->members, 0, marker, CodeMarker::Summary); + } } ++idx; ++s; @@ -1006,120 +1088,136 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, QString text; if (atom->next() != 0) text = atom->next()->string(); - if (atom->type() == Atom::Image) { - writer.writeStartElement("p"); - writer.writeAttribute("outputclass","centerAlign"); - } if (fileName.isEmpty()) { - writer.writeStartElement("font"); - writer.writeAttribute("color","red"); - writer.writeCharacters("[Missing image: "); - writer.writeCharacters(protectEnc(atom->string())); - writer.writeEndElement(); // </font> + xmlWriter().writeStartElement("font"); + xmlWriter().writeAttribute("color","red"); + xmlWriter().writeCharacters("[Missing image: "); + xmlWriter().writeCharacters(protectEnc(atom->string())); + xmlWriter().writeEndElement(); // </font> } else { - writer.writeStartElement("img"); - writer.writeAttribute("src",protectEnc(fileName)); - if (!text.isEmpty()) - writer.writeAttribute("alt",protectEnc(text)); - writer.writeEndElement(); // </img> + xmlWriter().writeStartElement("fig"); + xmlWriter().writeStartElement("image"); + xmlWriter().writeAttribute("href",protectEnc(fileName)); + if (atom->type() == Atom::InlineImage) + xmlWriter().writeAttribute("placement","inline"); + else { + xmlWriter().writeAttribute("placement","break"); + xmlWriter().writeAttribute("align","center"); + } + if (!text.isEmpty()) { + xmlWriter().writeStartElement("alt"); + xmlWriter().writeCharacters(protectEnc(text)); + xmlWriter().writeEndElement(); // </alt> + } + xmlWriter().writeEndElement(); // </image> + xmlWriter().writeEndElement(); // </fig> } - if (atom->type() == Atom::Image) - writer.writeEndElement(); // </p> } break; case Atom::ImageText: // nothing break; case Atom::LegaleseLeft: - writer.writeStartElement("p"); - writer.writeAttribute("outputclass","legalese"); + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","legalese"); break; case Atom::LegaleseRight: - writer.writeEndElement(); // </p> + xmlWriter().writeEndElement(); // </p> break; case Atom::LineBreak: - writer.writeEmptyElement("br"); + xmlWriter().writeEmptyElement("br"); break; case Atom::Link: { const Node *node = 0; QString myLink = getLink(atom, relative, marker, &node); if (myLink.isEmpty()) { - relative->doc().location().warning(tr("Cannot link to '%1' in %2") + relative->doc().location().warning(tr("Can't link to '%1' in %2") .arg(atom->string()) .arg(marker->plainFullName(relative))); } +#if 0 + else + qDebug() << "MYLINK:" << myLink << outFileName();; +#endif beginLink(myLink, node, relative, marker); skipAhead = 1; } break; + case Atom::GuidLink: + { +#if 0 + qDebug() << "GUID LINK:" << atom->string() << outFileName(); +#endif + beginLink(atom->string(), 0, relative, marker); + skipAhead = 1; + } + break; case Atom::LinkNode: { - const Node *node = CodeMarker::nodeForString(atom->string()); + const Node* node = CodeMarker::nodeForString(atom->string()); beginLink(linkForNode(node, relative), node, relative, marker); skipAhead = 1; } break; case Atom::ListLeft: if (in_para) { - writer.writeEndElement(); // </p> + xmlWriter().writeEndElement(); // </p> in_para = false; } if (atom->string() == ATOM_LIST_BULLET) { - writer.writeStartElement("ul"); + xmlWriter().writeStartElement("ul"); } else if (atom->string() == ATOM_LIST_TAG) { - writer.writeStartElement("dl"); + xmlWriter().writeStartElement("dl"); } else if (atom->string() == ATOM_LIST_VALUE) { threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom); if (threeColumnEnumValueTable) { - writer.writeStartElement("table"); - writer.writeAttribute("outputclass","valuelist"); - writer.writeStartElement("tr"); - if (++numTableRows % 2 == 1) - writer.writeAttribute("outputclass","odd"); - else - writer.writeAttribute("outputclass","even"); - writer.writeStartElement("th"); - writer.writeCharacters("Constant"); - writer.writeEndElement(); // </th> - writer.writeStartElement("th"); - writer.writeCharacters("Value"); - writer.writeEndElement(); // </th> - writer.writeStartElement("th"); - writer.writeCharacters("Description"); - writer.writeEndElement(); // </th> - writer.writeEndElement(); // </tr> + xmlWriter().writeStartElement("simpletable"); + xmlWriter().writeAttribute("outputclass","valuelist"); + xmlWriter().writeStartElement("sthead"); + xmlWriter().writeStartElement("stentry"); + xmlWriter().writeCharacters("Constant"); + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeStartElement("stentry"); + xmlWriter().writeCharacters("Value"); + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeStartElement("stentry"); + xmlWriter().writeCharacters("Description"); + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeEndElement(); // </sthead> } else { - writer.writeStartElement("table"); - writer.writeAttribute("outputclass","valuelist"); - writer.writeStartElement("tr"); - writer.writeStartElement("th"); - writer.writeCharacters("Constant"); - writer.writeEndElement(); // </th> - writer.writeStartElement("th"); - writer.writeCharacters("Value"); - writer.writeEndElement(); // </th> - writer.writeEndElement(); // </tr> + xmlWriter().writeStartElement("simpletable"); + xmlWriter().writeAttribute("outputclass","valuelist"); + xmlWriter().writeStartElement("sthead"); + xmlWriter().writeStartElement("stentry"); + xmlWriter().writeCharacters("Constant"); + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeStartElement("stentry"); + xmlWriter().writeCharacters("Value"); + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeEndElement(); // </stentry> } } else { - writer.writeStartElement("ol"); + xmlWriter().writeStartElement("ol"); if (atom->string() == ATOM_LIST_UPPERALPHA) - writer.writeAttribute("type","A"); + xmlWriter().writeAttribute("outputclass","upperalpha"); else if (atom->string() == ATOM_LIST_LOWERALPHA) - writer.writeAttribute("type","a"); + xmlWriter().writeAttribute("outputclass","loweralpha"); else if (atom->string() == ATOM_LIST_UPPERROMAN) - writer.writeAttribute("type","I"); + xmlWriter().writeAttribute("outputclass","upperroman"); else if (atom->string() == ATOM_LIST_LOWERROMAN) - writer.writeAttribute("type","i"); + xmlWriter().writeAttribute("outputclass","lowerroman"); else // (atom->string() == ATOM_LIST_NUMERIC) - writer.writeAttribute("type","1"); - if (atom->next() != 0 && atom->next()->string().toInt() != 1) - writer.writeAttribute("start",atom->next()->string()); + xmlWriter().writeAttribute("outputclass","numeric"); + if (atom->next() != 0 && atom->next()->string().toInt() != 1) { + // I don't think this attribute is supported. + xmlWriter().writeAttribute("start",atom->next()->string()); + } } break; case Atom::ListItemNumber: @@ -1127,19 +1225,17 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, break; case Atom::ListTagLeft: if (atom->string() == ATOM_LIST_TAG) { - writer.writeStartElement("dt"); + xmlWriter().writeStartElement("dt"); } else { // (atom->string() == ATOM_LIST_VALUE) - writer.writeStartElement("tr"); - writer.writeStartElement("td"); - writer.writeAttribute("outputclass","topAlign"); - writer.writeStartElement("tt"); - writer.writeCharacters(protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(), + xmlWriter().writeStartElement("strow"); + xmlWriter().writeStartElement("stentry"); + xmlWriter().writeStartElement("tt"); + xmlWriter().writeCharacters(protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(), relative)))); - writer.writeEndElement(); // </tt> - writer.writeEndElement(); // </td> - writer.writeStartElement("td"); - writer.writeAttribute("outputclass","topAlign"); + xmlWriter().writeEndElement(); // </tt> + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeStartElement("stentry"); QString itemValue; if (relative->type() == Node::Enum) { @@ -1148,105 +1244,110 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, } if (itemValue.isEmpty()) - writer.writeCharacters("?"); + xmlWriter().writeCharacters("?"); else { - writer.writeStartElement("tt"); - writer.writeCharacters(protectEnc(itemValue)); - writer.writeEndElement(); // </tt> + xmlWriter().writeStartElement("tt"); + xmlWriter().writeCharacters(protectEnc(itemValue)); + xmlWriter().writeEndElement(); // </tt> } skipAhead = 1; } break; case Atom::ListTagRight: if (atom->string() == ATOM_LIST_TAG) - writer.writeEndElement(); // </dt> + xmlWriter().writeEndElement(); // </dt> break; case Atom::ListItemLeft: if (atom->string() == ATOM_LIST_TAG) { - writer.writeStartElement("dd"); + xmlWriter().writeStartElement("dd"); } else if (atom->string() == ATOM_LIST_VALUE) { if (threeColumnEnumValueTable) { - writer.writeEndElement(); // </td> - writer.writeStartElement("td"); - writer.writeAttribute("outputclass","topAlign"); + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeStartElement("stentry"); if (matchAhead(atom, Atom::ListItemRight)) - writer.writeCharacters(" "); + xmlWriter().writeCharacters(" "); } } else { - writer.writeStartElement("li"); + xmlWriter().writeStartElement("li"); } if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; break; case Atom::ListItemRight: if (atom->string() == ATOM_LIST_TAG) { - writer.writeEndElement(); // </dd> + xmlWriter().writeEndElement(); // </dd> } else if (atom->string() == ATOM_LIST_VALUE) { - writer.writeEndElement(); // </td> - writer.writeEndElement(); // </tr> + xmlWriter().writeEndElement(); // </stentry> + xmlWriter().writeEndElement(); // </strow> } else { - writer.writeEndElement(); // </li> + xmlWriter().writeEndElement(); // </li> } break; case Atom::ListRight: if (atom->string() == ATOM_LIST_BULLET) { - writer.writeEndElement(); // </ul> + xmlWriter().writeEndElement(); // </ul> } else if (atom->string() == ATOM_LIST_TAG) { - writer.writeEndElement(); // </dl> + xmlWriter().writeEndElement(); // </dl> } else if (atom->string() == ATOM_LIST_VALUE) { - writer.writeEndElement(); // </table> + xmlWriter().writeEndElement(); // </simpletable> } else { - writer.writeEndElement(); // </ol> + xmlWriter().writeEndElement(); // </ol> } break; case Atom::Nop: // nothing break; case Atom::ParaLeft: - writer.writeStartElement("p"); + xmlWriter().writeStartElement("p"); in_para = true; break; case Atom::ParaRight: endLink(); if (in_para) { - writer.writeEndElement(); // </p? + xmlWriter().writeEndElement(); // </p> in_para = false; } break; case Atom::QuotationLeft: - writer.writeStartElement("blockquote"); + xmlWriter().writeStartElement("blockquote"); break; case Atom::QuotationRight: - writer.writeEndElement(); // </blockquote> + xmlWriter().writeEndElement(); // </blockquote> break; case Atom::RawString: - writer.writeCharacters(atom->string()); + xmlWriter().writeCharacters(atom->string()); break; case Atom::SectionLeft: - writer.writeStartElement("p"); + if (inSection || inApiDesc) { + inApiDesc = false; + xmlWriter().writeEndElement(); // </section> or </apiDesc> + } + inSection = true; + xmlWriter().writeStartElement("section"); writeGuidAttribute(Doc::canonicalTitle(Text::sectionHeading(atom).toString())); - writer.writeAttribute("outputclass","target"); - writer.writeCharacters(protectEnc(Text::sectionHeading(atom).toString())); - writer.writeEndElement(); // </p> + xmlWriter().writeAttribute("outputclass","details"); break; case Atom::SectionRight: - // nothing + if (inSection) { + inSection = false; + xmlWriter().writeEndElement(); // </section> + } break; case Atom::SectionHeadingLeft: - writer.writeStartElement("p"); + xmlWriter().writeStartElement("title"); hx = "h" + QString::number(atom->string().toInt() + hOffset(relative)); - writer.writeAttribute("outputclass",hx); + xmlWriter().writeAttribute("outputclass",hx); inSectionHeading = true; break; case Atom::SectionHeadingRight: - writer.writeEndElement(); // </p> (see case Atom::SectionHeadingLeft) + xmlWriter().writeEndElement(); // </title> (see case Atom::SectionHeadingLeft) inSectionHeading = false; break; case Atom::SidebarLeft: @@ -1260,67 +1361,82 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, generateLink(atom, relative, marker); } else { - writer.writeCharacters(protectEnc(atom->string())); + xmlWriter().writeCharacters(protectEnc(atom->string())); } break; case Atom::TableLeft: - if (in_para) { - writer.writeEndElement(); // </p> - in_para = false; + { + if (in_para) { + xmlWriter().writeEndElement(); // </p> + in_para = false; + } + xmlWriter().writeStartElement("table"); + numTableRows = 0; + if (tableColumnCount != 0) { + qDebug() << "ERROR: Nested tables!"; + tableColumnCount = 0; + } + tableColumnCount = countTableColumns(atom->next()); + xmlWriter().writeStartElement("tgroup"); + xmlWriter().writeAttribute("cols",QString::number(tableColumnCount)); + inTableHeader = false; + inTableBody = false; } - writer.writeStartElement("table"); - writer.writeAttribute("outputclass","generic"); - numTableRows = 0; break; case Atom::TableRight: - writer.writeEndElement(); // </table> + xmlWriter().writeEndElement(); // </tbody> + xmlWriter().writeEndElement(); // </tgroup> + xmlWriter().writeEndElement(); // </table> + inTableHeader = false; + inTableBody = false; + tableColumnCount = 0; break; case Atom::TableHeaderLeft: - writer.writeStartElement("thead"); - writer.writeStartElement("tr"); - writer.writeAttribute("outputclass","qt-style topAlign"); + xmlWriter().writeStartElement("thead"); + xmlWriter().writeAttribute("valign","top"); + xmlWriter().writeStartElement("row"); + xmlWriter().writeAttribute("valign","top"); inTableHeader = true; + inTableBody = false; break; case Atom::TableHeaderRight: - writer.writeEndElement(); // </tr> + xmlWriter().writeEndElement(); // </row> if (matchAhead(atom, Atom::TableHeaderLeft)) { skipAhead = 1; - writer.writeStartElement("tr"); - writer.writeAttribute("outputclass","qt-style topAlign"); + xmlWriter().writeStartElement("row"); + xmlWriter().writeAttribute("valign","top"); } else { - writer.writeEndElement(); // </thead> + xmlWriter().writeEndElement(); // </thead> inTableHeader = false; + inTableBody = true; + xmlWriter().writeStartElement("tbody"); } break; case Atom::TableRowLeft: - writer.writeStartElement("tr"); - if (++numTableRows % 2 == 1) - writer.writeAttribute("outputclass","odd topAlign"); - else - writer.writeAttribute("outputclass","even topAlign"); + if (!inTableHeader && !inTableBody) { + inTableBody = true; + xmlWriter().writeStartElement("tbody"); + } + xmlWriter().writeStartElement("row"); + xmlWriter().writeAttribute("valign","top"); break; case Atom::TableRowRight: - writer.writeEndElement(); // </tr>\n"; + xmlWriter().writeEndElement(); // </row> break; case Atom::TableItemLeft: { - if (inTableHeader) - writer.writeStartElement("th"); - else - writer.writeStartElement("td"); - + xmlWriter().writeStartElement("entry"); QStringList spans = atom->string().split(","); if (spans.size() == 2) { -#if zzz - - if (spans.at(0) != "1") - out() << " colspan=\"" << spans.at(0) << "\""; - if (spans.at(1) != "1") - out() << " rowspan=\"" << spans.at(1) << "\""; -#endif + if (inTableHeader || + (spans[0].toInt() != 1) || + (spans[1].toInt() != 1)) { + QString s = "span(" + spans[0] + "," + spans[1] + ")"; + xmlWriter().writeAttribute("outputclass",s); + } if (!inTableHeader) - writer.writeStartElement("p"); + xmlWriter().writeStartElement("p"); } if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; @@ -1328,10 +1444,10 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, break; case Atom::TableItemRight: if (inTableHeader) - writer.writeEndElement(); // </th> + xmlWriter().writeEndElement(); // </entry> else { - writer.writeEndElement(); // </p> - writer.writeEndElement(); // </td> + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeEndElement(); // </entry> } if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; @@ -1339,7 +1455,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, case Atom::TableOfContents: { int numColumns = 1; - const Node *node = relative; + const Node* node = relative; Doc::SectioningUnit sectioningUnit = Doc::Section4; QStringList params = atom->string().split(","); @@ -1366,30 +1482,28 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, } break; case Atom::Target: - writer.writeStartElement("p"); + xmlWriter().writeStartElement("p"); writeGuidAttribute(Doc::canonicalTitle(atom->string())); - writer.writeAttribute("outputclass","target"); - writer.writeCharacters(protectEnc(atom->string())); - writer.writeEndElement(); // </p> + xmlWriter().writeAttribute("outputclass","target"); + xmlWriter().writeCharacters(protectEnc(atom->string())); + xmlWriter().writeEndElement(); // </p> break; case Atom::UnhandledFormat: - writer.writeStartElement("b"); - writer.writeAttribute("outputclass","redFont"); - writer.writeCharacters("<Missing DITAXML>"); - writer.writeEndElement(); // </b> + xmlWriter().writeStartElement("b"); + xmlWriter().writeAttribute("outputclass","redFont"); + xmlWriter().writeCharacters("<Missing DITAXML>"); + xmlWriter().writeEndElement(); // </b> break; case Atom::UnknownCommand: - writer.writeStartElement("b"); - writer.writeAttribute("outputclass","redFont code"); - writer.writeCharacters(protectEnc(atom->string())); - writer.writeEndElement(); // </b> + xmlWriter().writeStartElement("b"); + xmlWriter().writeAttribute("outputclass","redFont code"); + xmlWriter().writeCharacters(protectEnc(atom->string())); + xmlWriter().writeEndElement(); // </b> break; -#ifdef QDOC_QML case Atom::QmlText: case Atom::EndQmlText: // don't do anything with these. They are just tags. break; -#endif default: // unknownAtom(atom); break; @@ -1398,284 +1512,362 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, } /*! - Generate a reference page for a C++ class. + Generate a <cxxClass> element (and all the stuff inside it) + for the C++ class represented by \a innerNode. \a marker is + for marking up the code. I don't know what that means exactly. */ void DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* marker) { - QList<Section> sections; QList<Section>::ConstIterator s; const ClassNode* cn = 0; - const NamespaceNode* namespasse = 0; + const NamespaceNode* nsn = 0; QString title; QString rawTitle; QString fullTitle; if (inner->type() == Node::Namespace) { - namespasse = const_cast<NamespaceNode*>(static_cast<const NamespaceNode*>(inner)); + nsn = const_cast<NamespaceNode*>(static_cast<const NamespaceNode*>(inner)); rawTitle = marker->plainName(inner); fullTitle = marker->plainFullName(inner); title = rawTitle + " Namespace"; - } - else if (inner->type() == Node::Class) { - cn = const_cast<ClassNode*>(static_cast<const ClassNode*>(inner)); - rawTitle = marker->plainName(inner); - fullTitle = marker->plainFullName(inner); - title = rawTitle + " Class Reference"; - - generateHeader(inner); - writer.writeStartElement(CXXCLASS); - writer.writeAttribute("id",cn->guid()); - writer.writeStartElement(APINAME); - writer.writeCharacters(fullTitle); - writer.writeEndElement(); // </apiName> + /* + Note: Because the C++ specialization we are using + has no <cxxNamespace> element, we are using the + <cxxClass> element with an outputclass attribute + set to "namespace" . + */ + generateHeader(inner, fullTitle); + generateBrief(inner, marker); // <shortdesc> - generateBrief(inner, marker); + // not included: <prolog> - writer.writeStartElement(CXXCLASSDETAIL); - writer.writeStartElement(CXXCLASSDEFINITION); - writer.writeStartElement(CXXCLASSACCESSSPECIFIER); - writer.writeAttribute("value",inner->accessString()); - writer.writeEndElement(); // <cxxClassAccessSpecifier> - if (cn->isAbstract()) { - writer.writeStartElement(CXXCLASSABSTRACT); - writer.writeAttribute("name","abstract"); - writer.writeAttribute("value","abstract"); - writer.writeEndElement(); // </cxxClassAbstract> + xmlWriter().writeStartElement(CXXCLASSDETAIL); + xmlWriter().writeStartElement(CXXCLASSDEFINITION); + writeLocation(nsn); + xmlWriter().writeEndElement(); // <cxxClassDefinition> + + xmlWriter().writeStartElement(APIDESC); + xmlWriter().writeAttribute("spectitle",title); + Text brief = nsn->doc().briefText(); + if (!brief.isEmpty()) { + xmlWriter().writeStartElement("p"); + generateText(brief, nsn, marker); + xmlWriter().writeEndElement(); // </p> + } + generateIncludes(nsn, marker); + generateStatus(nsn, marker); + generateThreadSafeness(nsn, marker); + generateSince(nsn, marker); + + xmlWriter().writeStartElement("ul"); + + QString membersLink = generateListOfAllMemberFile(inner, marker); + if (!membersLink.isEmpty()) { + writeXrefListItem(membersLink,"List of all members, including inherited members"); + } + + QString obsoleteLink = generateLowStatusMemberFile(inner, + marker, + CodeMarker::Obsolete); + if (!obsoleteLink.isEmpty()) { + writeXrefListItem(obsoleteLink,"Obsolete members"); } - writeDerivations(cn, marker); - writeLocation(cn); - writer.writeEndElement(); // <cxxClassDefinition> - writer.writeStartElement(APIDESC); - if (!inner->doc().isEmpty()) { - writer.writeStartElement("p"); - writer.writeAttribute("outputclass","h2"); - writer.writeCharacters("Detailed Description"); - writer.writeEndElement(); // </p> - generateBody(inner, marker); - // generateAlsoList(inner, marker); + QString compatLink = generateLowStatusMemberFile(inner, + marker, + CodeMarker::Compat); + if (!compatLink.isEmpty()) { + writeXrefListItem(compatLink,"Qt 3 support members"); } - - writer.writeEndElement(); // </apiDesc> - writer.writeEndElement(); // </cxxClassDetail> - sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay); - s = sections.begin(); - while (s != sections.end()) { - if ((*s).name == "Member Function Documentation") { - writeFunctions((*s),cn,marker); + xmlWriter().writeEndElement(); // </ul> + xmlWriter().writeEndElement(); // </apiDesc> + + bool needOtherSection = false; + QList<Section> summarySections; + summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay); + s = summarySections.begin(); + while (s != summarySections.end()) { + if (s->members.isEmpty() && s->reimpMembers.isEmpty()) { + if (!s->inherited.isEmpty()) + needOtherSection = true; } - else if ((*s).name == "Member Type Documentation") { - writeEnumerations((*s),cn,marker); - writeTypedefs((*s),cn,marker); + else { + QString attr; + if (!s->members.isEmpty()) { + xmlWriter().writeStartElement("section"); + attr = cleanRef((*s).name).toLower() + " redundant"; + xmlWriter().writeAttribute("outputclass",attr); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc((*s).name)); + xmlWriter().writeEndElement(); // </title> + generateSection(s->members, inner, marker, CodeMarker::Summary); + generateSectionInheritedList(*s, inner, marker); + xmlWriter().writeEndElement(); // </section> + } + if (!s->reimpMembers.isEmpty()) { + QString name = QString("Reimplemented ") + (*s).name; + attr = cleanRef(name).toLower() + " redundant"; + xmlWriter().writeStartElement("section"); + xmlWriter().writeAttribute("outputclass",attr); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc(name)); + xmlWriter().writeEndElement(); // </title> + generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary); + generateSectionInheritedList(*s, inner, marker); + xmlWriter().writeEndElement(); // </section> + } } - else if ((*s).name == "Member Variable Documentation") { - writeDataMembers((*s),cn,marker); + ++s; + } + if (needOtherSection) { + xmlWriter().writeStartElement("section"); + xmlWriter().writeAttribute("outputclass","additional-inherited-members redundant"); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h3"); + xmlWriter().writeCharacters("Additional Inherited Members"); + xmlWriter().writeEndElement(); // </title> + s = summarySections.begin(); + while (s != summarySections.end()) { + if (s->members.isEmpty()) + generateSectionInheritedList(*s, inner, marker); + ++s; } - else if ((*s).name == "Property Documentation") { - writeProperties((*s),cn,marker); + xmlWriter().writeEndElement(); // </section> + } + + writeDetailedDescription(nsn, marker, false, QString("Detailed Description")); + xmlWriter().writeEndElement(); // </cxxClassDetail> + + // not included: <related-links> + // not included: <cxxClassNested> + + QList<Section> detailSections; + detailSections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay); + s = detailSections.begin(); + while (s != detailSections.end()) { + if ((*s).name == "Classes") { + writeNestedClasses((*s),nsn); + break; + } + ++s; + } + + s = detailSections.begin(); + while (s != detailSections.end()) { + if ((*s).name == "Function Documentation") { + writeFunctions((*s),nsn,marker); + } + else if ((*s).name == "Type Documentation") { + writeEnumerations((*s),marker); + writeTypedefs((*s),marker); + } + else if ((*s).name == "Namespaces") { + qDebug() << "Nested namespaces" << outFileName(); } else if ((*s).name == "Macro Documentation") { - writeMacros((*s),cn,marker); + writeMacros((*s),marker); } ++s; } - writer.writeEndElement(); // </cxxClass> - } - -#ifdef WRITE_HTML - Text subtitleText; - if (rawTitle != fullTitle) - subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")" - << Atom(Atom::LineBreak); - - QString shortVersion; - shortVersion = project + " " + shortVersion + ": "; - shortVersion = myTree->version(); - if (shortVersion.count(QChar('.')) == 2) - shortVersion.truncate(shortVersion.lastIndexOf(QChar('.'))); - if (!shortVersion.isEmpty()) { - if (project == "QSA") - shortVersion = "QSA " + shortVersion + ": "; - else - shortVersion = "Qt " + shortVersion + ": "; + xmlWriter().writeEndElement(); // </cxxClass> } + else if (inner->type() == Node::Class) { + cn = const_cast<ClassNode*>(static_cast<const ClassNode*>(inner)); + rawTitle = marker->plainName(inner); + fullTitle = marker->plainFullName(inner); + title = rawTitle + " Class Reference"; - out() << " <title>" << shortVersion << protectEnc(title) << "</title>\n"; + generateHeader(inner, fullTitle); + generateBrief(inner, marker); // <shortdesc> -#if 0 - out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - generateBreadCrumbs(title,node,marker); - out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); -#endif + // not included: <prolog> - sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay); - generateTableOfContents(inner,marker,§ions); - generateTitle(title, subtitleText, SmallSubTitle, inner, marker); + xmlWriter().writeStartElement(CXXCLASSDETAIL); + xmlWriter().writeStartElement(CXXCLASSDEFINITION); + xmlWriter().writeStartElement(CXXCLASSACCESSSPECIFIER); + xmlWriter().writeAttribute("value",inner->accessString()); + xmlWriter().writeEndElement(); // <cxxClassAccessSpecifier> + if (cn->isAbstract()) { + xmlWriter().writeStartElement(CXXCLASSABSTRACT); + xmlWriter().writeAttribute("name","abstract"); + xmlWriter().writeAttribute("value","abstract"); + xmlWriter().writeEndElement(); // </cxxClassAbstract> + } + writeDerivations(cn, marker); // <cxxClassDerivations> -#ifdef QDOC_QML - if (cn && !cn->qmlElement().isEmpty()) { - generateInstantiatedBy(cn,marker); - } -#endif - - generateBrief(inner, marker); - generateIncludes(inner, marker); - generateStatus(inner, marker); - if (cn) { + // not included: <cxxClassTemplateParameters> + + writeLocation(cn); + xmlWriter().writeEndElement(); // <cxxClassDefinition> + + xmlWriter().writeStartElement(APIDESC); + xmlWriter().writeAttribute("spectitle",title); + Text brief = cn->doc().briefText(); + if (!brief.isEmpty()) { + xmlWriter().writeStartElement("p"); + generateText(brief, cn, marker); + xmlWriter().writeEndElement(); // </p> + } + generateIncludes(cn, marker); + generateStatus(cn, marker); generateInherits(cn, marker); generateInheritedBy(cn, marker); - } - generateThreadSafeness(inner, marker); - generateSince(inner, marker); - - out() << "<ul>\n"; - - QString membersLink = generateListOfAllMemberFile(inner, marker); - if (!membersLink.isEmpty()) - out() << "<li><xref href=\"" << membersLink << "\">" - << "List of all members, including inherited members</xref></li>\n"; - - QString obsoleteLink = generateLowStatusMemberFile(inner, - marker, - CodeMarker::Obsolete); - if (!obsoleteLink.isEmpty()) - out() << "<li><xref href=\"" << obsoleteLink << "\">" - << "Obsolete members</xref></li>\n"; - - QString compatLink = generateLowStatusMemberFile(inner, - marker, - CodeMarker::Compat); - if (!compatLink.isEmpty()) - out() << "<li><xref href=\"" << compatLink << "\">" - << "Qt 3 support members</xref></li>\n"; + generateThreadSafeness(cn, marker); + generateSince(cn, marker); + + xmlWriter().writeStartElement("ul"); + + QString membersLink = generateListOfAllMemberFile(inner, marker); + if (!membersLink.isEmpty()) { + writeXrefListItem(membersLink,"List of all members, including inherited members"); + } + + QString obsoleteLink = generateLowStatusMemberFile(inner, + marker, + CodeMarker::Obsolete); + if (!obsoleteLink.isEmpty()) { + writeXrefListItem(obsoleteLink,"Obsolete members"); + } - out() << "</ul>\n"; + QString compatLink = generateLowStatusMemberFile(inner, + marker, + CodeMarker::Compat); + if (!compatLink.isEmpty()) { + writeXrefListItem(compatLink,"Qt 3 support members"); + } - bool needOtherSection = false; + xmlWriter().writeEndElement(); // </ul> + xmlWriter().writeEndElement(); // </apiDesc> - /* - sections is built above for the call to generateTableOfContents(). - */ - s = sections.begin(); - while (s != sections.end()) { - if (s->members.isEmpty() && s->reimpMembers.isEmpty()) { - if (!s->inherited.isEmpty()) - needOtherSection = true; - } - else { - if (!s->members.isEmpty()) { - out() << "<hr />\n"; - out() << "<a name=\"" - << registerRef((*s).name.toLower()) - << "\"></a>\n"; - out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; - generateSection(s->members, inner, marker, CodeMarker::Summary); + bool needOtherSection = false; + QList<Section> summarySections; + summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay); + s = summarySections.begin(); + while (s != summarySections.end()) { + if (s->members.isEmpty() && s->reimpMembers.isEmpty()) { + if (!s->inherited.isEmpty()) + needOtherSection = true; } - if (!s->reimpMembers.isEmpty()) { - QString name = QString("Reimplemented ") + (*s).name; - out() << "<hr />\n"; - out() << "<a name=\"" - << registerRef(name.toLower()) - << "\"></a>\n"; - out() << "<h2>" << protectEnc(name) << "</h2>\n"; - generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary); + else { + QString attr; + if (!s->members.isEmpty()) { + xmlWriter().writeStartElement("section"); + attr = cleanRef((*s).name).toLower() + " redundant"; + xmlWriter().writeAttribute("outputclass",attr); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc((*s).name)); + xmlWriter().writeEndElement(); // </title> + generateSection(s->members, inner, marker, CodeMarker::Summary); + generateSectionInheritedList(*s, inner, marker); + xmlWriter().writeEndElement(); // </section> + } + if (!s->reimpMembers.isEmpty()) { + QString name = QString("Reimplemented ") + (*s).name; + attr = cleanRef(name).toLower() + " redundant"; + xmlWriter().writeStartElement("section"); + xmlWriter().writeAttribute("outputclass",attr); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc(name)); + xmlWriter().writeEndElement(); // </title> + generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary); + generateSectionInheritedList(*s, inner, marker); + xmlWriter().writeEndElement(); // </section> + } } - - if (!s->inherited.isEmpty()) { - out() << "<ul>\n"; - generateSectionInheritedList(*s, inner, marker, true); - out() << "</ul>\n"; + ++s; + } + if (needOtherSection) { + xmlWriter().writeStartElement("section"); + xmlWriter().writeAttribute("outputclass","additional-inherited-members redundant"); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h3"); + xmlWriter().writeCharacters("Additional Inherited Members"); + xmlWriter().writeEndElement(); // </title> + s = summarySections.begin(); + while (s != summarySections.end()) { + if (s->members.isEmpty()) + generateSectionInheritedList(*s, inner, marker); + ++s; } + xmlWriter().writeEndElement(); // </section> } - ++s; - } + + writeDetailedDescription(cn, marker, false, QString("Detailed Description")); - if (needOtherSection) { - out() << "<h3>Additional Inherited Members</h3>\n" - "<ul>\n"; + // not included: <example> or <apiImpl> - s = sections.begin(); - while (s != sections.end()) { - if (s->members.isEmpty() && !s->inherited.isEmpty()) - generateSectionInheritedList(*s, inner, marker); + xmlWriter().writeEndElement(); // </cxxClassDetail> + + // not included: <related-links> + // not included: <cxxClassNested> + + QList<Section> detailSections; + detailSections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay); + s = detailSections.begin(); + while (s != detailSections.end()) { + if ((*s).name == "Member Function Documentation") { + writeFunctions((*s),cn,marker); + } + else if ((*s).name == "Member Type Documentation") { + writeEnumerations((*s),marker); + writeTypedefs((*s),marker); + } + else if ((*s).name == "Member Variable Documentation") { + writeDataMembers((*s),marker); + } + else if ((*s).name == "Property Documentation") { + writeProperties((*s),marker); + } + else if ((*s).name == "Macro Documentation") { + writeMacros((*s),marker); + } ++s; } - out() << "</ul>\n"; - } - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + // not included: <cxxClassInherits> - if (!inner->doc().isEmpty()) { - out() << "<hr />\n" - << "<div class=\"descr\"/>\n" // QTBUG-9504 - << "<h2>" << "Detailed Description" << "</h2>\n"; - generateBody(inner, marker); - out() << "</div>\n"; // QTBUG-9504 - generateAlsoList(inner, marker); + xmlWriter().writeEndElement(); // </cxxClass> } +} - sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay); - s = sections.begin(); - while (s != sections.end()) { - out() << "<hr />\n"; - if (!(*s).divClass.isEmpty()) - out() << "<div class=\"" << (*s).divClass << "\"/>\n"; // QTBUG-9504 - out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; - - NodeList::ConstIterator m = (*s).members.begin(); - while (m != (*s).members.end()) { - if ((*m)->access() != Node::Private) { // ### check necessary? - if ((*m)->type() != Node::Class) - generateDetailedMember(*m, inner, marker); - else { - out() << "<h3> class "; - generateFullName(*m, inner, marker); - out() << "</h3>"; - generateBrief(*m, marker, inner); - } +/*! + Write a paragraph for the \a target and a poaragraph for + the \a header. Use the \a attribute for the \a header. + */ +void DitaXmlGenerator::writeTargetAndHeader(const QString& target, + const QString& header, + const QString& attribute) +{ + xmlWriter().writeStartElement("p"); + writeGuidAttribute(registerRef(target)); + xmlWriter().writeAttribute("outputclass","target"); + xmlWriter().writeCharacters(header); + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass",attribute); + xmlWriter().writeCharacters(header); + xmlWriter().writeEndElement(); // </p> +} - QStringList names; - names << (*m)->name(); - if ((*m)->type() == Node::Function) { - const FunctionNode *func = reinterpret_cast<const FunctionNode *>(*m); - if (func->metaness() == FunctionNode::Ctor || - func->metaness() == FunctionNode::Dtor || - func->overloadNumber() != 1) - names.clear(); - } - else if ((*m)->type() == Node::Property) { - const PropertyNode *prop = reinterpret_cast<const PropertyNode *>(*m); - if (!prop->getters().isEmpty() && - !names.contains(prop->getters().first()->name())) - names << prop->getters().first()->name(); - if (!prop->setters().isEmpty()) - names << prop->setters().first()->name(); - if (!prop->resetters().isEmpty()) - names << prop->resetters().first()->name(); - } - else if ((*m)->type() == Node::Enum) { - const EnumNode *enume = reinterpret_cast<const EnumNode*>(*m); - if (enume->flagsType()) - names << enume->flagsType()->name(); - - foreach (const QString &enumName, - enume->doc().enumItemNames().toSet() - - enume->doc().omitEnumItemNames().toSet()) - names << plainCode(marker->markedUpEnumValue(enumName, - enume)); - } - } - ++m; - } - if (!(*s).divClass.isEmpty()) - out() << "</div>\n"; // QTBUG-9504 - ++s; - } -#endif +/*! + Write a list item for a \a link with the given \a text. + */ +void DitaXmlGenerator::writeXrefListItem(const QString& link, const QString& text) +{ + xmlWriter().writeStartElement("li"); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",link); + xmlWriter().writeCharacters(text); + xmlWriter().writeEndElement(); // </xref> + xmlWriter().writeEndElement(); // </li> } /*! @@ -1684,8 +1876,6 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark */ void DitaXmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) { - return; // zzz - SubTitleSize subTitleSize = LargeSubTitle; QList<Section> sections; QList<Section>::const_iterator s; @@ -1701,66 +1891,45 @@ void DitaXmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker htmlTitle = fullTitle; } - generateHeader(fake); - - /* - Generate the TOC for the new doc format. - Don't generate a TOC for the home page. - */ - if (fake->name() != QString("index.html")) - generateTableOfContents(fake,marker,0); - - generateTitle(fullTitle, - Text() << fake->subTitle(), - subTitleSize, - fake, - marker); - + generateHeader(fake, fullTitle); + + generateBrief(fake, marker); // <shortdesc> if (fake->subType() == Node::Module) { - // Generate brief text and status for modules. - generateBrief(fake, marker); generateStatus(fake, marker); - if (moduleNamespaceMap.contains(fake->name())) { - out() << "<a name=\"" << registerRef("namespaces") << "\"></a>\n"; - out() << "<h2>Namespaces</h2>\n"; + writeTargetAndHeader("namespaces","Namespaces","h2"); generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]); } if (moduleClassMap.contains(fake->name())) { - out() << "<a name=\"" << registerRef("classes") << "\"></a>\n"; - out() << "<h2>Classes</h2>\n"; + writeTargetAndHeader("classes","Classes","h2"); generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]); } } else if (fake->subType() == Node::HeaderFile) { - // Generate brief text and status for modules. - generateBrief(fake, marker); generateStatus(fake, marker); - - out() << "<ul>\n"; + xmlWriter().writeStartElement("ul"); QString membersLink = generateListOfAllMemberFile(fake, marker); - if (!membersLink.isEmpty()) - out() << "<li><xref href=\"" << membersLink << "\">" - << "List of all members, including inherited members</xref></li>\n"; + if (!membersLink.isEmpty()) { + writeXrefListItem(membersLink,"List of all members, including inherited members"); + } QString obsoleteLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Obsolete); - if (!obsoleteLink.isEmpty()) - out() << "<li><xref href=\"" << obsoleteLink << "\">" - << "Obsolete members</xref></li>\n"; + if (!obsoleteLink.isEmpty()) { + writeXrefListItem(obsoleteLink,"Obsolete members"); + } QString compatLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Compat); - if (!compatLink.isEmpty()) - out() << "<li><xref href=\"" << compatLink << "\">" - << "Qt 3 support members</xref></li>\n"; + if (!compatLink.isEmpty()) { + writeXrefListItem(compatLink,"Qt 3 support members"); + } - out() << "</ul>\n"; + xmlWriter().writeEndElement(); // </ul> } -#ifdef QDOC_QML else if (fake->subType() == Node::QmlClass) { const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake); const ClassNode* cn = qml_cn->classNode(); @@ -1771,42 +1940,99 @@ void DitaXmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker sections = marker->qmlSections(qml_cn,CodeMarker::Summary,0); s = sections.begin(); while (s != sections.end()) { - out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n"; - out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; + xmlWriter().writeStartElement("section"); + QString attr = cleanRef((*s).name).toLower(); + xmlWriter().writeAttribute("outputclass",attr); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc((*s).name)); + xmlWriter().writeEndElement(); // </title> generateQmlSummary(*s,fake,marker); + xmlWriter().writeEndElement(); // </section> ++s; } + + writeDetailedDescription(fake, marker, false, QString("Detailed Description")); - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; - out() << "<h2>" << "Detailed Description" << "</h2>\n"; - generateBody(fake, marker); if (cn) generateQmlText(cn->doc().body(), cn, marker, fake->name()); + generateAlsoList(fake, marker); - out() << "<hr />\n"; sections = marker->qmlSections(qml_cn,CodeMarker::Detailed,0); s = sections.begin(); while (s != sections.end()) { - out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; - NodeList::ConstIterator m = (*s).members.begin(); - while (m != (*s).members.end()) { - generateDetailedQmlMember(*m, fake, marker); - out() << "<br/>\n"; - ++m; + if (!s->members.isEmpty()) { + QString attr; + xmlWriter().writeStartElement("section"); + attr = cleanRef((*s).name).toLower(); + xmlWriter().writeAttribute("outputclass",attr); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc((*s).name)); + xmlWriter().writeEndElement(); // </title> + NodeList::ConstIterator m = (*s).members.begin(); + while (m != (*s).members.end()) { + generateDetailedQmlMember(*m, fake, marker); + ++m; + } + xmlWriter().writeEndElement(); // </section> } ++s; } return; } -#endif + + if (!fake->doc().isEmpty()) { + xmlWriter().writeStartElement("body"); + if (fake->subType() == Node::Module) { + writeDetailedDescription(fake, marker, false, QString("Detailed Description")); + } + else + writeDetailedDescription(fake, marker, false, QString()); + generateAlsoList(fake, marker); + + if (!fake->groupMembers().isEmpty()) { + NodeMap groupMembersMap; + foreach (const Node *node, fake->groupMembers()) { + if (node->type() == Node::Class || node->type() == Node::Namespace) + groupMembersMap[node->name()] = node; + } + generateAnnotatedList(fake, marker, groupMembersMap); + } + + xmlWriter().writeEndElement(); // </body> + } + xmlWriter().writeEndElement(); // </topic> +} + +#if 0 +zzz + /* + Generate the TOC for the new doc format. + Don't generate a TOC for the home page. + */ + if (fake->name() != QString("index.html")) + generateTableOfContents(fake,marker,0); + + generateTitle(fullTitle, + Text() << fake->subTitle(), + subTitleSize, + fake, + marker); + +#endif + +#if 0 +zzz sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n"; out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; - generateSectionList(*s, fake, marker, CodeMarker::Summary); + generateSection(s->members, fake, marker, CodeMarker::Summary); + generateSectionInheritedList(*s, relative, marker, name_alignment); ++s; } @@ -1819,19 +2045,6 @@ void DitaXmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker else out() << "<div class=\"descr\"/>\n"; // QTBUG-9504 - generateBody(fake, marker); - out() << "</div>\n"; // QTBUG-9504 - generateAlsoList(fake, marker); - - if (!fake->groupMembers().isEmpty()) { - NodeMap groupMembersMap; - foreach (const Node *node, fake->groupMembers()) { - if (node->type() == Node::Class || node->type() == Node::Namespace) - groupMembersMap[node->name()] = node; - } - generateAnnotatedList(fake, marker, groupMembersMap); - } - sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { @@ -1845,10 +2058,10 @@ void DitaXmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker } ++s; } -} +#endif /*! - Returns "xml" for this subclass of Generator. + Returns "xml" for this subclass of class Generator. */ QString DitaXmlGenerator::fileExtension(const Node * /* node */) const { @@ -1856,6 +2069,7 @@ QString DitaXmlGenerator::fileExtension(const Node * /* node */) const } /*! + zzz Output breadcrumb list in the html file. */ void DitaXmlGenerator::generateBreadCrumbs(const QString& title, @@ -1943,85 +2157,168 @@ void DitaXmlGenerator::generateBreadCrumbs(const QString& title, } } -void DitaXmlGenerator::generateHeader(const Node* node) +/*! + Writes an XML file header to the current XML stream. This + depends on which kind of DITA XML file is being generated, + which is determined by the \a node type and subtype and the + \a subpage flag. If the \subpage flag is true, a \c{<topic>} + header is written, regardless of the type of \a node. + */ +void DitaXmlGenerator::generateHeader(const Node* node, + const QString& name, + bool subpage) { - writer.setDevice(out().device()); - writer.setAutoFormatting(true); - writer.setAutoFormattingIndent(4); - writer.writeStartDocument(); - if (!node) return; - QString docType; + QString doctype; + QString mainElement; + QString nameElement; QString dtd; + QString base; QString version; - if (node->type() == Node::Class) { - docType = "cxxClass"; + QString outputclass; + + if (node->type() == Node::Fake || subpage) { + mainElement = "topic"; + nameElement = "title"; + dtd = "dtd/topic.dtd"; + doctype = "<!DOCTYPE " + mainElement + + " PUBLIC \"-//OASIS//DTD DITA Topic//EN\" \"" + dtd + "\">"; + switch (node->subType()) { + case Node::Page: + outputclass = "page"; + break; + case Node::Group: + outputclass = "group"; + break; + case Node::Example: + outputclass = "example"; + break; + case Node::HeaderFile: + outputclass = "headerfile"; + break; + case Node::File: + outputclass = "file"; + break; + case Node::Image: + outputclass = "image"; + break; + case Node::Module: + outputclass = "module"; + break; + case Node::ExternalPage: + outputclass = "externalpage"; + break; + case Node::QmlClass: + outputclass = "QML-class"; + break; + default: + outputclass = "page"; + } + } + else if (node->type() == Node::Class) { + mainElement = "cxxClass"; + nameElement = "apiName"; dtd = "dtd/cxxClass.dtd"; version = "0.6.0"; + doctype = "<!DOCTYPE " + mainElement + + " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" + + version + "//EN\" \"" + dtd + "\">"; } - - QString doctype = "<!DOCTYPE " + docType + - " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" + - version + "//EN\" \"" + dtd + "\">"; - writer.writeDTD(doctype); - writer.writeComment(node->doc().location().fileName()); + else if (node->type() == Node::Namespace) { + mainElement = "cxxClass"; + nameElement = "apiName"; + dtd = "dtd/cxxClass.dtd"; + version = "0.6.0"; + doctype = "<!DOCTYPE " + mainElement + + " PUBLIC \"-//NOKIA//DTD DITA C++ API Namespace Reference Type v" + + version + "//EN\" \"" + dtd + "\">"; + outputclass = "namespace"; + } + + xmlWriter().writeDTD(doctype); + xmlWriter().writeComment(node->doc().location().fileName()); + xmlWriter().writeStartElement(mainElement); + xmlWriter().writeAttribute("id",node->guid()); + if (!outputclass.isEmpty()) + xmlWriter().writeAttribute("outputclass",outputclass); + xmlWriter().writeStartElement(nameElement); + xmlWriter().writeCharacters(name); + xmlWriter().writeEndElement(); // <nameElement> } +/*! + Writes a \a title as a <p> element with an \c {outputclass} + attribute of "h1 title". + + Also generates and writes a \a subTitle as a <p> element, + if one is provided, but this probably doesn't work right. + */ void DitaXmlGenerator::generateTitle(const QString& title, - const Text &subTitle, + const Text& subTitle, SubTitleSize subTitleSize, - const Node *relative, - CodeMarker *marker) + const Node* relative, + CodeMarker* marker) { - if (!title.isEmpty()) - out() << "<h1 class=\"title\">" << protectEnc(title) << "</h1>\n"; + if (!title.isEmpty()) { + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass", "h1 title"); + xmlWriter().writeCharacters(protectEnc(title)); + xmlWriter().writeEndElement(); // </p> + } if (!subTitle.isEmpty()) { - out() << "<span"; - if (subTitleSize == SmallSubTitle) - out() << " class=\"small-subtitle\">"; - else - out() << " class=\"subtitle\">"; + xmlWriter().writeStartElement("p"); + if (subTitleSize == SmallSubTitle) { + xmlWriter().writeAttribute("outputclass", "small-subtitle"); + } + else { + xmlWriter().writeAttribute("outputclass", "subtitle"); + } generateText(subTitle, relative, marker); - out() << "</span>\n"; + xmlWriter().writeEndElement(); // </p> } } /*! - Outputs the brief command as a <shortdesc" element. + Outputs the \e brief command as a <shortdesc> element. */ void DitaXmlGenerator::generateBrief(const Node* node, CodeMarker* marker) { Text brief = node->doc().briefText(); if (!brief.isEmpty()) { - ++noLinks; - writer.writeStartElement(SHORTDESC); + noLinks = true; + xmlWriter().writeStartElement(SHORTDESC); generateText(brief, node, marker); - writer.writeEndElement(); // shortdesc - --noLinks; + xmlWriter().writeEndElement(); // </shortdesc> + noLinks = false; } } -void DitaXmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker) +/*! + Writes the \c {#include ...} required to include the class + or namespace in a compilation. + */ +void DitaXmlGenerator::generateIncludes(const InnerNode* inner, CodeMarker* marker) { if (!inner->includes().isEmpty()) { - out() << "<pre class=\"highlightedCode\">" - << trimmedTrailing(highlightedCode(indent(codeIndent, - marker->markedUpIncludes(inner->includes())), - marker,inner)) - << "</pre>"; + xmlWriter().writeStartElement("pre"); + xmlWriter().writeAttribute("outputclass","highlightedcode"); + writeText(marker->markedUpIncludes(inner->includes()), marker, inner); + xmlWriter().writeEndElement(); // </pre> } } /*! + zzz Generates a table of contents begining at \a node. + Currently just returns without writing anything. */ -void DitaXmlGenerator::generateTableOfContents(const Node *node, - CodeMarker *marker, - Doc::SectioningUnit sectioningUnit, - int numColumns, - const Node *relative) +void DitaXmlGenerator::generateTableOfContents(const Node* node, + CodeMarker* marker, + Doc::SectioningUnit sectioningUnit, + int numColumns, + const Node* relative) { return; @@ -2100,12 +2397,13 @@ void DitaXmlGenerator::generateTableOfContents(const Node *node, } /*! + zzz Revised for the new doc format. Generates a table of contents begining at \a node. */ -void DitaXmlGenerator::generateTableOfContents(const Node *node, - CodeMarker *marker, - QList<Section>* sections) +void DitaXmlGenerator::generateTableOfContents(const Node* node, + CodeMarker* marker, + QList<Section>* sections) { QList<Atom*> toc; if (node->doc().hasTableOfContents()) @@ -2214,8 +2512,8 @@ void DitaXmlGenerator::generateTableOfContents(const Node *node, inLink = false; } -QString DitaXmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, - CodeMarker *marker) +QString DitaXmlGenerator::generateListOfAllMemberFile(const InnerNode* inner, + CodeMarker* marker) { QList<Section> sections; QList<Section>::ConstIterator s; @@ -2229,26 +2527,34 @@ QString DitaXmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, QString fileName = fileBase(inner) + "-members." + fileExtension(inner); beginSubPage(inner->location(), fileName); QString title = "List of All Members for " + inner->name(); - generateHeader(inner); - generateTitle(title, Text(), SmallSubTitle, inner, marker); - out() << "<p>This is the complete list of members for "; + generateHeader(inner, title, true); + xmlWriter().writeStartElement("body"); + xmlWriter().writeStartElement("section"); + if (!title.isEmpty()) { + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass", "h1"); + xmlWriter().writeCharacters(protectEnc(title)); + xmlWriter().writeEndElement(); // </title> + } + xmlWriter().writeStartElement("p"); + xmlWriter().writeCharacters("This is the complete list of members for "); generateFullName(inner, 0, marker); - out() << ", including inherited members.</p>\n"; + xmlWriter().writeCharacters(", including inherited members."); + xmlWriter().writeEndElement(); // </p> Section section = sections.first(); - generateSectionList(section, 0, marker, CodeMarker::SeparateList); - + generateSection(section.members, 0, marker, CodeMarker::SeparateList); + xmlWriter().writeEndElement(); // </section> + xmlWriter().writeEndElement(); // </body> endSubPage(); return fileName; } -QString DitaXmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, - CodeMarker *marker, - CodeMarker::Status status) +QString DitaXmlGenerator::generateLowStatusMemberFile(const InnerNode* inner, + CodeMarker* marker, + CodeMarker::Status status) { - QList<Section> sections = marker->sections(inner, - CodeMarker::Summary, - status); + QList<Section> sections = marker->sections(inner,CodeMarker::Summary,status); QMutableListIterator<Section> j(sections); while (j.hasNext()) { if (j.next().members.size() == 0) @@ -2258,7 +2564,6 @@ QString DitaXmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, return QString(); int i; - QString title; QString fileName; @@ -2270,53 +2575,86 @@ QString DitaXmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, title = "Obsolete Members for " + inner->name(); fileName = fileBase(inner) + "-obsolete." + fileExtension(inner); } - beginSubPage(inner->location(), fileName); - generateHeader(inner); - generateTitle(title, Text(), SmallSubTitle, inner, marker); + generateHeader(inner, title, true); + xmlWriter().writeStartElement("body"); + xmlWriter().writeStartElement("section"); + if (!title.isEmpty()) { + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass", "h1"); + xmlWriter().writeCharacters(protectEnc(title)); + xmlWriter().writeEndElement(); // </title> + } + xmlWriter().writeStartElement("p"); if (status == CodeMarker::Compat) { - out() << "<p><b>The following class members are part of the " - "<xref href=\"qt3support.html\">Qt 3 support layer</xref>.</b> " - "They are provided to help you port old code to Qt 4. We advise against " - "using them in new code.</p>\n"; + xmlWriter().writeStartElement("b"); + xmlWriter().writeCharacters("The following class members are part of the "); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href","qt3support.html"); + xmlWriter().writeCharacters("Qt 3 support layer"); + xmlWriter().writeEndElement(); // </xref> + xmlWriter().writeCharacters(". "); + xmlWriter().writeEndElement(); // </b> + xmlWriter().writeCharacters("They are provided to help you port old code to Qt 4. " + "We advise against using them in new code."); } else { - out() << "<p><b>The following class members are obsolete.</b> " - << "They are provided to keep old source code working. " - << "We strongly advise against using them in new code.</p>\n"; - } - - out() << "<p><ul><li><xref href=\"" - << linkForNode(inner, 0) << "\">" - << protectEnc(inner->name()) - << " class reference</xref></li></ul></p>\n"; - + xmlWriter().writeStartElement("b"); + xmlWriter().writeCharacters("The following class members are obsolete. "); + xmlWriter().writeEndElement(); // </b> + xmlWriter().writeCharacters("They are provided to keep old source code working. " + "We strongly advise against using them in new code."); + } + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeStartElement("p"); + xmlWriter().writeStartElement("ul"); + QString text = protectEnc(inner->name()) + " class reference"; + writeXrefListItem(linkForNode(inner,0),text); + xmlWriter().writeEndElement(); // </ul> + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeEndElement(); // </section> + for (i = 0; i < sections.size(); ++i) { - out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n"; - generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary); + xmlWriter().writeStartElement("section"); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc(sections.at(i).name)); + xmlWriter().writeEndElement(); // </title> + generateSection(sections.at(i).members, inner, marker, CodeMarker::Summary); + generateSectionInheritedList(sections.at(i), inner, marker); + xmlWriter().writeEndElement(); // </section> } sections = marker->sections(inner, CodeMarker::Detailed, status); for (i = 0; i < sections.size(); ++i) { - out() << "<hr />\n"; - out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n"; + xmlWriter().writeStartElement("section"); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(protectEnc(sections.at(i).name)); + xmlWriter().writeEndElement(); // </title> NodeList::ConstIterator m = sections.at(i).members.begin(); while (m != sections.at(i).members.end()) { - if ((*m)->access() != Node::Private) + if ((*m)->access() != Node::Private) { generateDetailedMember(*m, inner, marker); + } ++m; } + xmlWriter().writeEndElement(); // </section> } - + xmlWriter().writeEndElement(); // </body> + xmlWriter().writeEndElement(); // </topic> endSubPage(); return fileName; } -void DitaXmlGenerator::generateClassHierarchy(const Node *relative, - CodeMarker *marker, - const QMap<QString,const Node*> &classMap) +/*! + Write the XML for the class hierarchy to the current XML stream. + */ +void DitaXmlGenerator::generateClassHierarchy(const Node* relative, + CodeMarker* marker, + const QMap<QString,const Node*>& classMap) { if (classMap.isEmpty()) return; @@ -2324,7 +2662,7 @@ void DitaXmlGenerator::generateClassHierarchy(const Node *relative, NodeMap topLevel; NodeMap::ConstIterator c = classMap.begin(); while (c != classMap.end()) { - const ClassNode *classe = static_cast<const ClassNode *>(*c); + const ClassNode* classe = static_cast<const ClassNode*>(*c); if (classe->baseClasses().isEmpty()) topLevel.insert(classe->name(), classe); ++c; @@ -2333,18 +2671,18 @@ void DitaXmlGenerator::generateClassHierarchy(const Node *relative, QStack<NodeMap > stack; stack.push(topLevel); - out() << "<ul>\n"; + xmlWriter().writeStartElement("ul"); while (!stack.isEmpty()) { if (stack.top().isEmpty()) { stack.pop(); - out() << "</ul>\n"; + xmlWriter().writeEndElement(); // </ul> } else { const ClassNode *child = static_cast<const ClassNode *>(*stack.top().begin()); - out() << "<li>"; + xmlWriter().writeStartElement("li"); generateFullName(child, relative, marker); - out() << "</li>\n"; + xmlWriter().writeEndElement(); // </li> stack.top().erase(stack.top().begin()); NodeMap newTop; @@ -2354,49 +2692,61 @@ void DitaXmlGenerator::generateClassHierarchy(const Node *relative, } if (!newTop.isEmpty()) { stack.push(newTop); - out() << "<ul>\n"; + xmlWriter().writeStartElement("ul"); } } } } -void DitaXmlGenerator::generateAnnotatedList(const Node *relative, - CodeMarker *marker, - const NodeMap &nodeMap) +/*! + Write XML for the contents of the \a nodeMap to the current + XML stream. + */ +void DitaXmlGenerator::generateAnnotatedList(const Node* relative, + CodeMarker* marker, + const NodeMap& nodeMap) { - out() << "<table class=\"annotated\">\n"; + xmlWriter().writeStartElement("table"); + xmlWriter().writeAttribute("outputclass","annotated"); + xmlWriter().writeStartElement("tgroup"); + xmlWriter().writeAttribute("cols","2"); + xmlWriter().writeStartElement("tbody"); - int row = 0; - foreach (const QString &name, nodeMap.keys()) { - const Node *node = nodeMap[name]; + foreach (const QString& name, nodeMap.keys()) { + const Node* node = nodeMap[name]; if (node->status() == Node::Obsolete) continue; - if (++row % 2 == 1) - out() << "<tr class=\"odd topAlign\">"; - else - out() << "<tr class=\"even topAlign\">"; - out() << "<td><p>"; + xmlWriter().writeStartElement("row"); + xmlWriter().writeStartElement("entry"); + xmlWriter().writeStartElement("p"); generateFullName(node, relative, marker); - out() << "</p></td>"; + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeEndElement(); // <entry> if (!(node->type() == Node::Fake)) { Text brief = node->doc().trimmedBriefText(name); if (!brief.isEmpty()) { - out() << "<td><p>"; + xmlWriter().writeStartElement("entry"); + xmlWriter().writeStartElement("p"); generateText(brief, node, marker); - out() << "</p></td>"; + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeEndElement(); // <entry> } } else { - out() << "<td><p>"; - out() << protectEnc(node->doc().briefText().toString()); - out() << "</p></td>"; + xmlWriter().writeStartElement("entry"); + xmlWriter().writeStartElement("p"); + xmlWriter().writeCharacters(protectEnc(node->doc().briefText().toString())); + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeEndElement(); // <entry> } - out() << "</tr>\n"; + xmlWriter().writeEndElement(); // </row> } - out() << "</table>\n"; + xmlWriter().writeEndElement(); // </tbody> + xmlWriter().writeEndElement(); // </tgroup> + xmlWriter().writeEndElement(); // </table> } /*! @@ -2408,11 +2758,11 @@ void DitaXmlGenerator::generateAnnotatedList(const Node *relative, normally you let it figure it out itself by looking at the name of the first and last classes in \a classMap. */ -void DitaXmlGenerator::generateCompactList(const Node *relative, - CodeMarker *marker, - const NodeMap &classMap, - bool includeAlphabet, - QString commonPrefix) +void DitaXmlGenerator::generateCompactList(const Node* relative, + CodeMarker* marker, + const NodeMap& classMap, + bool includeAlphabet, + QString commonPrefix) { const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_' @@ -2532,19 +2882,27 @@ void DitaXmlGenerator::generateCompactList(const Node *relative, Output the alphabet as a row of links. */ if (includeAlphabet) { - out() << "<p class=\"centerAlign functionIndex\"><b>"; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","centerAlign functionIndex"); + xmlWriter().writeStartElement("b"); for (int i = 0; i < 26; i++) { QChar ch('a' + i); - if (usedParagraphNames.contains(char('a' + i))) - out() << QString("<xref href=\"#%1\">%2</xref> ").arg(ch).arg(ch.toUpper()); + if (usedParagraphNames.contains(char('a' + i))) { + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",QString("#%1").arg(ch)); + xmlWriter().writeCharacters(QString(ch.toUpper())); + xmlWriter().writeEndElement(); // </xref> + } } - out() << "</b></p>\n"; + xmlWriter().writeEndElement(); // </b> + xmlWriter().writeEndElement(); // </p> } /* - Output a <div> element to contain all the <dl> elements. + Output a <p> element to contain all the <dl> elements. */ - out() << "<div class=\"flowListDiv\">\n"; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","compactlist"); for (int i=0; i<classMap.count()-1; i++) { while ((curParNr < NumParagraphs) && @@ -2557,27 +2915,29 @@ void DitaXmlGenerator::generateCompactList(const Node *relative, Starting a new paragraph means starting a new <dl>. */ if (curParOffset == 0) { - if (i > 0) - out() << "</dl>\n"; - if (++numTableRows % 2 == 1) - out() << "<dl class=\"flowList odd\">"; - else - out() << "<dl class=\"flowList even\">"; - out() << "<dt class=\"alphaChar\">"; + if (i > 0) { + xmlWriter().writeEndElement(); // </dlentry> + xmlWriter().writeEndElement(); // </dl> + } + xmlWriter().writeStartElement("dl"); + xmlWriter().writeStartElement("dlentry"); + xmlWriter().writeStartElement("dt"); + xmlWriter().writeAttribute("outputclass","alphaChar"); if (includeAlphabet) { QChar c = paragraphName[curParNr][0].toLower(); - out() << QString("<a name=\"%1\"></a>").arg(c); + xmlWriter().writeStartElement("a"); + xmlWriter().writeAttribute("name",c); } - out() << "<b>" - << paragraphName[curParNr] - << "</b>"; - out() << "</dt>\n"; + xmlWriter().writeStartElement("b"); + xmlWriter().writeCharacters(paragraphName[curParNr]); + xmlWriter().writeEndElement(); // </b> + xmlWriter().writeEndElement(); // </dt> } /* Output a <dd> for the current offset in the current paragraph. */ - out() << "<dd>"; + xmlWriter().writeStartElement("dd"); if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) { NodeMap::Iterator it; @@ -2589,148 +2949,114 @@ void DitaXmlGenerator::generateCompactList(const Node *relative, Previously, we used generateFullName() for this, but we require some special formatting. */ - out() << "<xref href=\"" << linkForNode(it.value(), relative) << "\">"; + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",linkForNode(it.value(), relative)); QStringList pieces; if (it.value()->subType() == Node::QmlClass) pieces << it.value()->name(); else pieces = fullName(it.value(), relative, marker).split("::"); - out() << protectEnc(pieces.last()); - out() << "</xref>"; + xmlWriter().writeCharacters(protectEnc(pieces.last())); + xmlWriter().writeEndElement(); // </xref> if (pieces.size() > 1) { - out() << " ("; - generateFullName(it.value()->parent(), relative, marker); - out() << ")"; + xmlWriter().writeCharacters(" ("); + generateFullName(it.value()->parent(),relative,marker); + xmlWriter().writeCharacters(")"); } } - out() << "</dd>\n"; + xmlWriter().writeEndElement(); // </dd> curParOffset++; } - out() << "</dl>\n"; - out() << "</div>\n"; + xmlWriter().writeEndElement(); // </dlentry> + xmlWriter().writeEndElement(); // </dl> + xmlWriter().writeEndElement(); // </p> } -void DitaXmlGenerator::generateFunctionIndex(const Node *relative, - CodeMarker *marker) +/*! + Write XML for a function index to the current XML stream. + */ +void DitaXmlGenerator::generateFunctionIndex(const Node* relative, + CodeMarker* marker) { - out() << "<p class=\"centerAlign functionIndex\"><b>"; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","centerAlign functionIndex"); + xmlWriter().writeStartElement("b"); for (int i = 0; i < 26; i++) { QChar ch('a' + i); - out() << QString("<xref href=\"#%1\">%2</xref> ").arg(ch).arg(ch.toUpper()); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",QString("#%1").arg(ch)); + xmlWriter().writeCharacters(QString(ch.toUpper())); + xmlWriter().writeEndElement(); // </xref> } - out() << "</b></p>\n"; + xmlWriter().writeEndElement(); // </b> + xmlWriter().writeEndElement(); // </p> char nextLetter = 'a'; char currentLetter; -#if 1 - out() << "<ul>\n"; -#endif + xmlWriter().writeStartElement("ul"); QMap<QString, NodeMap >::ConstIterator f = funcIndex.begin(); while (f != funcIndex.end()) { -#if 1 - out() << "<li>"; -#else - out() << "<p>"; -#endif - out() << protectEnc(f.key()) << ":"; - + xmlWriter().writeStartElement("li"); currentLetter = f.key()[0].unicode(); while (islower(currentLetter) && currentLetter >= nextLetter) { - out() << QString("<a name=\"%1\"></a>").arg(nextLetter); + xmlWriter().writeStartElement("p"); + writeGuidAttribute(QString(nextLetter)); + xmlWriter().writeAttribute("outputclass","target"); + xmlWriter().writeCharacters(QString(nextLetter)); + xmlWriter().writeEndElement(); // </p> nextLetter++; } + xmlWriter().writeCharacters(protectEnc(f.key())); + xmlWriter().writeCharacters(":"); NodeMap::ConstIterator s = (*f).begin(); while (s != (*f).end()) { - out() << " "; generateFullName((*s)->parent(), relative, marker, *s); ++s; } -#if 1 - out() << "</li>"; -#else - out() << "</p>"; -#endif - out() << "\n"; + xmlWriter().writeEndElement(); // </li> ++f; } -#if 1 - out() << "</ul>\n"; -#endif + xmlWriter().writeEndElement(); // </ul> } -void DitaXmlGenerator::generateLegaleseList(const Node *relative, - CodeMarker *marker) +/*! + Write the legalese texts as XML to the current XML stream. + */ +void DitaXmlGenerator::generateLegaleseList(const Node* relative, + CodeMarker* marker) { - QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin(); + QMap<Text, const Node*>::ConstIterator it = legaleseTexts.begin(); while (it != legaleseTexts.end()) { Text text = it.key(); - out() << "<hr />\n"; generateText(text, relative, marker); - out() << "<ul>\n"; + xmlWriter().writeStartElement("ul"); do { - out() << "<li>"; + xmlWriter().writeStartElement("li"); generateFullName(it.value(), relative, marker); - out() << "</li>\n"; + xmlWriter().writeEndElement(); // </li> ++it; } while (it != legaleseTexts.end() && it.key() == text); - out() << "</ul>\n"; + xmlWriter().writeEndElement(); //</ul> } } -/*void DitaXmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); - } - marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), - "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - - if (style == CodeMarker::Summary) - marked.replace("@name>", "b>"); - - if (style == CodeMarker::SeparateList) { - QRegExp extraRegExp("<@extra>.*</@extra>"); - extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } - else { - marked.replace("<@extra>", " <tt>"); - marked.replace("</@extra>", "</tt>"); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); - } - out() << highlightedCode(marked, marker, relative); -}*/ - -#ifdef QDOC_QML -void DitaXmlGenerator::generateQmlItem(const Node *node, - const Node *relative, - CodeMarker *marker, - bool summary) +/*! + Generate the text for the QML item described by \a node + and write it to the current XML stream. + */ +void DitaXmlGenerator::generateQmlItem(const Node* node, + const Node* relative, + CodeMarker* marker, + bool summary) { QString marked = marker->markedUpQmlItem(node,summary); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); + QRegExp tag("(<[^@>]*>)"); + if (marked.indexOf(tag) != -1) { + QString tmp = protectEnc(marked.mid(tag.pos(1), tag.cap(1).length())); + marked.replace(tag.pos(1), tag.cap(1).length(), tmp); } marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>"); @@ -2747,21 +3073,23 @@ void DitaXmlGenerator::generateQmlItem(const Node *node, marked.replace("<@type>", ""); marked.replace("</@type>", ""); } - out() << highlightedCode(marked, marker, relative); + writeText(marked, marker, relative); } -#endif -void DitaXmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */) +/*! + Writher the XML for the overview list to the current XML stream. + */ +void DitaXmlGenerator::generateOverviewList(const Node* relative, CodeMarker* /* marker */) { - QMap<const FakeNode *, QMap<QString, FakeNode *> > fakeNodeMap; - QMap<QString, const FakeNode *> groupTitlesMap; - QMap<QString, FakeNode *> uncategorizedNodeMap; + QMap<const FakeNode*, QMap<QString, FakeNode*> > fakeNodeMap; + QMap<QString, const FakeNode*> groupTitlesMap; + QMap<QString, FakeNode*> uncategorizedNodeMap; QRegExp singleDigit("\\b([0-9])\\b"); const NodeList children = myTree->root()->childNodes(); - foreach (Node *child, children) { + foreach (Node* child, children) { if (child->type() == Node::Fake && child != relative) { - FakeNode *fakeNode = static_cast<FakeNode *>(child); + FakeNode* fakeNode = static_cast<FakeNode*>(child); // Check whether the page is part of a group or is the group // definition page. @@ -2793,24 +3121,25 @@ void DitaXmlGenerator::generateOverviewList(const Node *relative, CodeMarker * / if (isGroupPage) { // If we encounter a group definition page, we add all // the pages in that group to the list for that group. - foreach (Node *member, fakeNode->groupMembers()) { + foreach (Node* member, fakeNode->groupMembers()) { if (member->type() != Node::Fake) continue; - FakeNode *page = static_cast<FakeNode *>(member); + FakeNode* page = static_cast<FakeNode*>(member); if (page) { QString sortKey = page->fullTitle().toLower(); if (sortKey.startsWith("the ")) sortKey.remove(0, 4); sortKey.replace(singleDigit, "0\\1"); - fakeNodeMap[const_cast<const FakeNode *>(fakeNode)].insert(sortKey, page); - groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode); + fakeNodeMap[const_cast<const FakeNode*>(fakeNode)].insert(sortKey, page); + groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode*>(fakeNode); } } } else if (!isGroupPage) { // If we encounter a page that belongs to a group then // we add that page to the list for that group. - const FakeNode *groupNode = static_cast<const FakeNode *>(myTree->root()->findNode(group, Node::Fake)); + const FakeNode* groupNode = + static_cast<const FakeNode*>(myTree->root()->findNode(group, Node::Fake)); if (groupNode) fakeNodeMap[groupNode].insert(sortKey, fakeNode); //else @@ -2829,241 +3158,172 @@ void DitaXmlGenerator::generateOverviewList(const Node *relative, CodeMarker * / // pages in that group are listed for completeness. if (!fakeNodeMap.isEmpty()) { - foreach (const QString &groupTitle, groupTitlesMap.keys()) { - const FakeNode *groupNode = groupTitlesMap[groupTitle]; - out() << QString("<h3><xref href=\"%1\">%2</xref></h3>\n").arg( - linkForNode(groupNode, relative)).arg( - protectEnc(groupNode->fullTitle())); - + foreach (const QString& groupTitle, groupTitlesMap.keys()) { + const FakeNode* groupNode = groupTitlesMap[groupTitle]; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","h3"); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",linkForNode(groupNode, relative)); + xmlWriter().writeCharacters(protectEnc(groupNode->fullTitle())); + xmlWriter().writeEndElement(); // </xref> + xmlWriter().writeEndElement(); // </p> if (fakeNodeMap[groupNode].count() == 0) continue; - out() << "<ul>\n"; - - foreach (const FakeNode *fakeNode, fakeNodeMap[groupNode]) { + xmlWriter().writeStartElement("ul"); + foreach (const FakeNode* fakeNode, fakeNodeMap[groupNode]) { QString title = fakeNode->fullTitle(); if (title.startsWith("The ")) title.remove(0, 4); - out() << "<li><xref href=\"" << linkForNode(fakeNode, relative) << "\">" - << protectEnc(title) << "</xref></li>\n"; + xmlWriter().writeStartElement("li"); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",linkForNode(fakeNode, relative)); + xmlWriter().writeCharacters(protectEnc(title)); + xmlWriter().writeEndElement(); // </xref> + xmlWriter().writeEndElement(); // </li> } - out() << "</ul>\n"; + xmlWriter().writeEndElement(); // </ul> } } if (!uncategorizedNodeMap.isEmpty()) { - out() << QString("<h3>Miscellaneous</h3>\n"); - out() << "<ul>\n"; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","h3"); + xmlWriter().writeCharacters("Miscellaneous"); + xmlWriter().writeEndElement(); // </p> + xmlWriter().writeStartElement("ul"); foreach (const FakeNode *fakeNode, uncategorizedNodeMap) { QString title = fakeNode->fullTitle(); if (title.startsWith("The ")) title.remove(0, 4); - out() << "<li><xref href=\"" << linkForNode(fakeNode, relative) << "\">" - << protectEnc(title) << "</xref></li>\n"; + xmlWriter().writeStartElement("li"); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",linkForNode(fakeNode, relative)); + xmlWriter().writeCharacters(protectEnc(title)); + xmlWriter().writeEndElement(); // </xref> + xmlWriter().writeEndElement(); // </li> } - out() << "</ul>\n"; + xmlWriter().writeEndElement(); // </ul> } } +/*! + Write the XML for a standard section of a page, e.g. + "Public Functions" or "Protected Slots." The section + is written too the current XML stream as a table. + */ void DitaXmlGenerator::generateSection(const NodeList& nl, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) + const Node* relative, + CodeMarker* marker, + CodeMarker::SynopsisStyle style) { - bool name_alignment = true; if (!nl.isEmpty()) { - bool twoColumn = false; - if (style == CodeMarker::SeparateList) { - name_alignment = false; - twoColumn = (nl.count() >= 16); - } - else if (nl.first()->type() == Node::Property) { - twoColumn = (nl.count() >= 5); - name_alignment = false; - } - if (name_alignment) { - out() << "<table class=\"alignedsummary\">\n"; - } - else { - if (twoColumn) - out() << "<table class=\"propsummary\">\n" - << "<tr><td class=\"topAlign\">"; - out() << "<ul>\n"; - } - - int i = 0; + xmlWriter().writeStartElement("ul"); NodeList::ConstIterator m = nl.begin(); while (m != nl.end()) { - if ((*m)->access() == Node::Private) { - ++m; - continue; - } - - if (name_alignment) { - out() << "<tr><td class=\"memItemLeft rightAlign topAlign\"> "; - } - else { - if (twoColumn && i == (int) (nl.count() + 1) / 2) - out() << "</ul></td><td class=\"topAlign\"><ul>\n"; - out() << "<li class=\"fn\">"; + if ((*m)->access() != Node::Private) { + xmlWriter().writeStartElement("li"); + QString marked = getMarkedUpSynopsis(*m, relative, marker, style); + writeText(marked, marker, relative); + xmlWriter().writeEndElement(); // </li> } - - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) - out() << "</td></tr>\n"; - else - out() << "</li>\n"; - i++; ++m; } - if (name_alignment) - out() << "</table>\n"; - else { - out() << "</ul>\n"; - if (twoColumn) - out() << "</td></tr>\n</table>\n"; - } - } -} - -void DitaXmlGenerator::generateSectionList(const Section& section, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style) -{ - bool name_alignment = true; - if (!section.members.isEmpty()) { - bool twoColumn = false; - if (style == CodeMarker::SeparateList) { - name_alignment = false; - twoColumn = (section.members.count() >= 16); - } - else if (section.members.first()->type() == Node::Property) { - twoColumn = (section.members.count() >= 5); - name_alignment = false; - } - if (name_alignment) { - out() << "<table class=\"alignedsummary\">\n"; - } - else { - if (twoColumn) - out() << "<table class=\"propsummary\">\n" - << "<tr><td class=\"topAlign\">"; - out() << "<ul>\n"; - } - - int i = 0; - NodeList::ConstIterator m = section.members.begin(); - while (m != section.members.end()) { - if ((*m)->access() == Node::Private) { - ++m; - continue; - } - - if (name_alignment) { - out() << "<tr><td class=\"memItemLeft topAlign rightAlign\"> "; - } - else { - if (twoColumn && i == (int) (section.members.count() + 1) / 2) - out() << "</ul></td><td class=\"topAlign\"><ul>\n"; - out() << "<li class=\"fn\">"; - } - - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) - out() << "</td></tr>\n"; - else - out() << "</li>\n"; - i++; - ++m; - } - if (name_alignment) - out() << "</table>\n"; - else { - out() << "</ul>\n"; - if (twoColumn) - out() << "</td></tr>\n</table>\n"; - } - } - - if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { - out() << "<ul>\n"; - generateSectionInheritedList(section, relative, marker, name_alignment); - out() << "</ul>\n"; + xmlWriter().writeEndElement(); // </ul> } } +/*! + Writes the "inherited from" list to the current XML stream. + */ void DitaXmlGenerator::generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker, - bool nameAlignment) + const Node* relative, + CodeMarker* marker) { - QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); + if (section.inherited.isEmpty()) + return; + xmlWriter().writeStartElement("ul"); + QList<QPair<ClassNode*,int> >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { - if (nameAlignment) - out() << "<li class=\"fn\">"; + xmlWriter().writeStartElement("li"); + QString text; + text.setNum((*p).second); + text += " "; + if ((*p).second == 1) + text += section.singularMember; else - out() << "<li class=\"fn\">"; - out() << (*p).second << " "; - if ((*p).second == 1) { - out() << section.singularMember; - } - else { - out() << section.pluralMember; - } - out() << " inherited from <xref href=\"" << fileName((*p).first) - << "#" << DitaXmlGenerator::cleanRef(section.name.toLower()) << "\">" - << protectEnc(marker->plainFullName((*p).first, relative)) - << "</xref></li>\n"; + text += section.pluralMember; + text += " inherited from "; + xmlWriter().writeCharacters(text); + xmlWriter().writeStartElement("xref"); + // zzz + text = fileName((*p).first) + "#"; + text += DitaXmlGenerator::cleanRef(section.name.toLower()); + xmlWriter().writeAttribute("href",text); + text = protectEnc(marker->plainFullName((*p).first, relative)); + xmlWriter().writeCharacters(text); + xmlWriter().writeEndElement(); // </xref> + xmlWriter().writeEndElement(); // </li> ++p; } + xmlWriter().writeEndElement(); // </ul> } -void DitaXmlGenerator::generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style, - bool nameAlignment) +/*! + Get the synopsis from the \a node using the \a relative + node if needed, and mark up the synopsis using \a marker. + Use the style to decide which kind of sysnopsis to build, + normally \c Summary or \c Detailed. Return the marked up + string. + */ +QString DitaXmlGenerator::getMarkedUpSynopsis(const Node* node, + const Node* relative, + CodeMarker* marker, + CodeMarker::SynopsisStyle style) { QString marked = marker->markedUpSynopsis(node, relative, style); - QRegExp templateTag("(<[^@>]*>)"); - if (marked.indexOf(templateTag) != -1) { - QString contents = protectEnc(marked.mid(templateTag.pos(1), - templateTag.cap(1).length())); - marked.replace(templateTag.pos(1), templateTag.cap(1).length(), - contents); + QRegExp tag("(<[^@>]*>)"); + if (marked.indexOf(tag) != -1) { + QString tmp = protectEnc(marked.mid(tag.pos(1), tag.cap(1).length())); + marked.replace(tag.pos(1), tag.cap(1).length(), tmp); } marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - +#if 0 + marked.replace("<@param>","<i>"); + marked.replace("</@param>","</i>"); +#endif if (style == CodeMarker::Summary) { - marked.replace("<@name>", ""); // was "<b>" - marked.replace("</@name>", ""); // was "</b>" + marked.replace("<@name>",""); // was "<b>" + marked.replace("</@name>",""); // was "</b>" } if (style == CodeMarker::SeparateList) { QRegExp extraRegExp("<@extra>.*</@extra>"); extraRegExp.setMinimal(true); - marked.replace(extraRegExp, ""); - } else { - marked.replace("<@extra>", "<tt>"); - marked.replace("</@extra>", "</tt>"); + marked.replace(extraRegExp,""); + } +#if 0 + else { + marked.replace("<@extra>","<tt>"); + marked.replace("</@extra>","</tt>"); } +#endif if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); + marked.replace("<@type>",""); + marked.replace("</@type>",""); } - out() << highlightedCode(marked, marker, relative, style, nameAlignment); + return marked; } -QString DitaXmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle , - bool nameAlignment) +/*! + Renamed from highlightedCode() in the html generator. Writes + the \a markedCode to the current XML stream. + */ +void DitaXmlGenerator::writeText(const QString& markedCode, + CodeMarker* marker, + const Node* relative) { QString src = markedCode; QString html; @@ -3073,130 +3333,29 @@ QString DitaXmlGenerator::highlightedCode(const QString& markedCode, const QChar charLangle = '<'; const QChar charAt = '@'; - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" - static const QString linkTag("link"); - bool done = false; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { - if (nameAlignment && !done) {// && (i != 0)) Why was this here? - html += "</td><td class=\"memItemRight bottomAlign\">"; - done = true; - } - i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { - html += "<b>"; - QString link = linkForNode( - CodeMarker::nodeForString(par1.toString()), relative); - addLink(link, arg, &html); - html += "</b>"; - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - - - if (slow) { - // is this block ever used at all? - // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" - src = html; - html = QString(); - static const QString funcTag("func"); - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, funcTag, &i, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); - addLink(link, arg, &html); - par1 = QStringRef(); - } - else { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - } - - // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags - src = html; - html = QString(); - static const QString typeTags[] = { "type", "headerfile", "func" }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - bool handled = false; - for (int k = 0; k != 3; ++k) { - if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { - par1 = QStringRef(); - QString link = linkForNode( - marker->resolveTarget(arg.toString(), myTree, relative), - relative); - addLink(link, arg, &html); - handled = true; - break; - } - } - if (!handled) { - html += charLangle; - html += charAt; - } - } - else { - html += src.at(i++); - } - } - - // replace all - // "<@comment>" -> "<span class=\"comment\">"; - // "<@preprocessor>" -> "<span class=\"preprocessor\">"; - // "<@string>" -> "<span class=\"string\">"; - // "<@char>" -> "<span class=\"char\">"; - // "</@(?:comment|preprocessor|string|char)>" -> "</span>" - src = html; - html = QString(); + /* + First strip out all the extraneous markup. The table + below contains the markup we want to keep. Everything + else that begins with "<@" or "</@" is stripped out. + */ static const QString spanTags[] = { - "<@comment>", "<span class=\"comment\">", - "<@preprocessor>", "<span class=\"preprocessor\">", - "<@string>", "<span class=\"string\">", - "<@char>", "<span class=\"char\">", - "</@comment>", "</span>", - "</@preprocessor>","</span>", - "</@string>", "</span>", - "</@char>", "</span>" - // "<@char>", "<font color=blue>", - // "</@char>", "</font>", - // "<@func>", "<font color=green>", - // "</@func>", "</font>", - // "<@id>", "<i>", - // "</@id>", "</i>", - // "<@keyword>", "<b>", - // "</@keyword>", "</b>", - // "<@number>", "<font color=yellow>", - // "</@number>", "</font>", - // "<@op>", "<b>", - // "</@op>", "</b>", - // "<@param>", "<i>", - // "</@param>", "</i>", - // "<@string>", "<font color=green>", - // "</@string>", "</font>", + "<@link ", "<@link ", + "<@type>", "<@type>", + "<@headerfile>", "<@headerfile>", + "<@func>", "<@func>", + "<@param>", "<@param>", + "<@extra>", "<@extra>", + "</@link>", "</@link>", + "</@type>", "</@type>", + "</@headerfile>", "</@headerfile>", + "</@func>", "</@func>", + "</@param>", "</@param>", + "</@extra>", "</@extra>" }; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { bool handled = false; - for (int k = 0; k != 8; ++k) { + for (int k = 0; k != 12; ++k) { const QString & tag = spanTags[2 * k]; if (tag == QStringRef(&src, i, tag.length())) { html += spanTags[2 * k + 1]; @@ -3226,45 +3385,120 @@ QString DitaXmlGenerator::highlightedCode(const QString& markedCode, } } - return html; + // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" + // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags + src = html; + html = QString(); + static const QString markTags[] = { + // 0 1 2 3 4 5 + "link", "type", "headerfile", "func", "param", "extra" + }; + + for (int i = 0, n = src.size(); i < n;) { + if (src.at(i) == charLangle && src.at(i + 1) == charAt) { + i += 2; + bool handled = false; + for (int k = 0; k != 6; ++k) { + if (parseArg(src, markTags[k], &i, n, &arg, &par1)) { + const Node* n = 0; + if (k == 0) { // <@link> + if (!html.isEmpty()) { + xmlWriter().writeCharacters(html); + html.clear(); + } + n = CodeMarker::nodeForString(par1.toString()); + QString link = linkForNode(n, relative); + addLink(link, arg); + } + else if (k == 4) { // <@param> + if (!html.isEmpty()) { + xmlWriter().writeCharacters(html); + html.clear(); + } + xmlWriter().writeStartElement("i"); + xmlWriter().writeCharacters(arg.toString()); + xmlWriter().writeEndElement(); // </i> + } + else if (k == 5) { // <@extra> + if (!html.isEmpty()) { + xmlWriter().writeCharacters(html); + html.clear(); + } + xmlWriter().writeStartElement("tt"); + xmlWriter().writeCharacters(arg.toString()); + xmlWriter().writeEndElement(); // </tt> + } + else { + if (!html.isEmpty()) { + xmlWriter().writeCharacters(html); + html.clear(); + } + par1 = QStringRef(); + QString link; + n = marker->resolveTarget(arg.toString(), myTree, relative); + if (n && n->subType() == Node::QmlBasicType) { + if (relative && relative->subType() == Node::QmlClass) { + link = linkForNode(n,relative); + addLink(link, arg); + } + else { + link = arg.toString(); + } + } + else { + // (zzz) Is this correct for all cases? + link = linkForNode(n,relative); + addLink(link, arg); + } + } + handled = true; + break; + } + } + } + else { + html += src.at(i++); + } + } + + if (!html.isEmpty()) { + xmlWriter().writeCharacters(html); + } } void DitaXmlGenerator::generateLink(const Atom* atom, - const Node* /* relative */, - CodeMarker* marker) + const Node* /* relative */, + CodeMarker* marker) { static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_"); if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) { // hack for C++: move () outside of link int k = funcLeftParen.pos(1); - writer.writeCharacters(protectEnc(atom->string().left(k))); + xmlWriter().writeCharacters(protectEnc(atom->string().left(k))); if (link.isEmpty()) { if (showBrokenLinks) - writer.writeEndElement(); // </i> - } - else { - writer.writeEndElement(); // </xref> + xmlWriter().writeEndElement(); // </i> } + else + xmlWriter().writeEndElement(); // </xref> inLink = false; - writer.writeCharacters(protectEnc(atom->string().mid(k))); - } else if (marker->recognizeLanguage("Java")) { + xmlWriter().writeCharacters(protectEnc(atom->string().mid(k))); + } + else if (marker->recognizeLanguage("Java")) { // hack for Java: remove () and use <tt> when appropriate bool func = atom->string().endsWith("()"); bool tt = (func || atom->string().contains(camelCase)); if (tt) - writer.writeStartElement("tt"); - if (func) { - writer.writeCharacters(protectEnc(atom->string().left(atom->string().length() - 2))); - } - else { - writer.writeCharacters(protectEnc(atom->string())); - } - writer.writeEndElement(); // </tt> - } - else { - writer.writeCharacters(protectEnc(atom->string())); + xmlWriter().writeStartElement("tt"); + if (func) + xmlWriter().writeCharacters(protectEnc(atom->string().left(atom->string().length() - 2))); + else + xmlWriter().writeCharacters(protectEnc(atom->string())); + xmlWriter().writeEndElement(); // </tt> } + else + xmlWriter().writeCharacters(protectEnc(atom->string())); } QString DitaXmlGenerator::cleanRef(const QString& ref) @@ -3279,14 +3513,17 @@ QString DitaXmlGenerator::cleanRef(const QString& ref) const uint u = c.unicode(); if ((u >= 'a' && u <= 'z') || - (u >= 'A' && u <= 'Z') || - (u >= '0' && u <= '9')) { + (u >= 'A' && u <= 'Z') || + (u >= '0' && u <= '9')) { clean += c; - } else if (u == '~') { + } + else if (u == '~') { clean += "dtor."; - } else if (u == '_') { + } + else if (u == '_') { clean += "underscore."; - } else { + } + else { clean += "A"; } @@ -3294,25 +3531,33 @@ QString DitaXmlGenerator::cleanRef(const QString& ref) const QChar c = ref[i]; const uint u = c.unicode(); if ((u >= 'a' && u <= 'z') || - (u >= 'A' && u <= 'Z') || - (u >= '0' && u <= '9') || u == '-' || - u == '_' || u == ':' || u == '.') { + (u >= 'A' && u <= 'Z') || + (u >= '0' && u <= '9') || u == '-' || + u == '_' || u == ':' || u == '.') { clean += c; - } else if (c.isSpace()) { + } + else if (c.isSpace()) { clean += "-"; - } else if (u == '!') { + } + else if (u == '!') { clean += "-not"; - } else if (u == '&') { + } + else if (u == '&') { clean += "-and"; - } else if (u == '<') { + } + else if (u == '<') { clean += "-lt"; - } else if (u == '=') { + } + else if (u == '=') { clean += "-eq"; - } else if (u == '>') { + } + else if (u == '>') { clean += "-gt"; - } else if (u == '#') { + } + else if (u == '#') { clean += "#"; - } else { + } + else { clean += "-"; clean += QString::number((int)u, 16); } @@ -3329,20 +3574,27 @@ QString DitaXmlGenerator::registerRef(const QString& ref) if (prevRef.isEmpty()) { prevRef = ref; break; - } else if (prevRef == ref) { - break; } + else if (prevRef == ref) + break; +#if 0 + else + qDebug() << "PREVREF:" << prevRef; +#endif clean += "x"; } return clean; } -QString DitaXmlGenerator::protectEnc(const QString &string) +/*! + Calls protect() with the \a string. Returns the result. + */ +QString DitaXmlGenerator::protectEnc(const QString& string) { return protect(string, outputEncoding); } -QString DitaXmlGenerator::protect(const QString &string, const QString &outputEncoding) +QString DitaXmlGenerator::protect(const QString& string, const QString& outputEncoding) { #define APPEND(x) \ if (xml.isEmpty()) { \ @@ -3359,20 +3611,25 @@ QString DitaXmlGenerator::protect(const QString &string, const QString &outputEn if (ch == QLatin1Char('&')) { APPEND("&"); - } else if (ch == QLatin1Char('<')) { + } + else if (ch == QLatin1Char('<')) { APPEND("<"); - } else if (ch == QLatin1Char('>')) { + } + else if (ch == QLatin1Char('>')) { APPEND(">"); - } else if (ch == QLatin1Char('"')) { + } + else if (ch == QLatin1Char('"')) { APPEND("""); - } else if ((outputEncoding == "ISO-8859-1" && ch.unicode() > 0x007F) - || (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/')) - || (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) { + } + else if ((outputEncoding == "ISO-8859-1" && ch.unicode() > 0x007F) || + (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/')) || + (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) { // we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator APPEND("&#x"); xml += QString::number(ch.unicode(), 16); xml += QLatin1Char(';'); - } else { + } + else { if (!xml.isEmpty()) xml += ch; } @@ -3385,12 +3642,14 @@ QString DitaXmlGenerator::protect(const QString &string, const QString &outputEn #undef APPEND } -QString DitaXmlGenerator::fileBase(const Node *node) +/*! + Constructs a file name appropriate for the \a node + and returns the file name. + */ +QString DitaXmlGenerator::fileBase(const Node* node) const { QString result; - result = PageGenerator::fileBase(node); - if (!node->isInnerNode()) { switch (node->status()) { case Node::Compat: @@ -3406,44 +3665,10 @@ QString DitaXmlGenerator::fileBase(const Node *node) return result; } -#if 0 -QString DitaXmlGenerator::fileBase(const Node *node, - const SectionIterator& section) +QString DitaXmlGenerator::refForNode(const Node* node) { - QStringList::ConstIterator s = section.sectionNumber().end(); - QStringList::ConstIterator b = section.baseNameStack().end(); - - QString suffix; - QString base = fileBase(node); - - while (s != section.sectionNumber().begin()) { - --s; - --b; - if (!(*b).isEmpty()) { - base = *b; - break; - } - suffix.prepend("-" + *s); - } - return base + suffix; -} -#endif - -QString DitaXmlGenerator::fileName(const Node *node) -{ - if (node->type() == Node::Fake) { - if (static_cast<const FakeNode *>(node)->subType() == Node::ExternalPage) - return node->name(); - if (static_cast<const FakeNode *>(node)->subType() == Node::Image) - return node->name(); - } - return PageGenerator::fileName(node); -} - -QString DitaXmlGenerator::refForNode(const Node *node) -{ - const FunctionNode *func; - const TypedefNode *typedeffe; + const FunctionNode* func; + const TypedefNode* tdn; QString ref; switch (node->type()) { @@ -3455,9 +3680,9 @@ QString DitaXmlGenerator::refForNode(const Node *node) ref = node->name() + "-enum"; break; case Node::Typedef: - typedeffe = static_cast<const TypedefNode *>(node); - if (typedeffe->associatedEnum()) { - return refForNode(typedeffe->associatedEnum()); + tdn = static_cast<const TypedefNode *>(node); + if (tdn->associatedEnum()) { + return refForNode(tdn->associatedEnum()); } else { ref = node->name() + "-typedef"; @@ -3474,23 +3699,19 @@ QString DitaXmlGenerator::refForNode(const Node *node) ref += "-" + QString::number(func->overloadNumber()); } break; -#ifdef QDOC_QML case Node::Fake: if (node->subType() != Node::QmlPropertyGroup) break; case Node::QmlProperty: -#endif case Node::Property: ref = node->name() + "-prop"; break; -#ifdef QDOC_QML case Node::QmlSignal: ref = node->name() + "-signal"; break; case Node::QmlMethod: ref = node->name() + "-method"; break; -#endif case Node::Variable: ref = node->name() + "-var"; break; @@ -3500,12 +3721,74 @@ QString DitaXmlGenerator::refForNode(const Node *node) return registerRef(ref); } -QString DitaXmlGenerator::linkForNode(const Node *node, const Node *relative) +QString DitaXmlGenerator::guidForNode(const Node* node) { - QString link; - QString fn; - QString ref; + switch (node->type()) { + case Node::Namespace: + case Node::Class: + default: + break; + case Node::Enum: + return node->guid(); + case Node::Typedef: + { + const TypedefNode* tdn = static_cast<const TypedefNode*>(node); + if (tdn->associatedEnum()) + return guidForNode(tdn->associatedEnum()); + } + return node->guid(); + case Node::Function: + { + const FunctionNode* fn = static_cast<const FunctionNode*>(node); + if (fn->associatedProperty()) { + return guidForNode(fn->associatedProperty()); + } + else { + QString ref = fn->name(); + if (fn->overloadNumber() != 1) { + ref += "-" + QString::number(fn->overloadNumber()); + //qDebug() << "guidForNode() overloaded function:" << outFileName() << ref; + } + } + return fn->guid(); + } + case Node::Fake: + if (node->subType() != Node::QmlPropertyGroup) + break; + case Node::QmlProperty: + case Node::Property: + return node->guid(); + case Node::QmlSignal: + return node->guid(); + case Node::QmlMethod: + return node->guid(); + case Node::Variable: + return node->guid(); + case Node::Target: + return node->guid(); + } + return QString(); +} +/*! + Constructs a file name appropriate for the \a node and returns + it. If the \a node is not a fake node, or if it is a fake node but + it is neither an external page node nor an image node, call the + PageGenerator::fileName() function. + */ +QString DitaXmlGenerator::fileName(const Node* node) +{ + if (node->type() == Node::Fake) { + if (static_cast<const FakeNode*>(node)->subType() == Node::ExternalPage) + return node->name(); + if (static_cast<const FakeNode*>(node)->subType() == Node::Image) + return node->name(); + } + return PageGenerator::fileName(node); +} + +QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative) +{ if (node == 0 || node == relative) return QString(); if (!node->url().isEmpty()) @@ -3515,87 +3798,80 @@ QString DitaXmlGenerator::linkForNode(const Node *node, const Node *relative) if (node->access() == Node::Private) return QString(); - fn = fileName(node); - link += fn; + QString fn = fileName(node); + QString link = fn; if (!node->isInnerNode() || node->subType() == Node::QmlPropertyGroup) { - ref = refForNode(node); - if (relative && fn == fileName(relative) && ref == refForNode(relative)) + QString guid = guidForNode(node); + if (relative && fn == fileName(relative) && guid == guidForNode(relative)) { return QString(); - + } link += "#"; - link += ref; + link += guid; } return link; } -QString DitaXmlGenerator::refForAtom(Atom *atom, const Node * /* node */) +QString DitaXmlGenerator::refForAtom(Atom* atom, const Node* /* node */) { - if (atom->type() == Atom::SectionLeft) { + if (atom->type() == Atom::SectionLeft) return Doc::canonicalTitle(Text::sectionHeading(atom).toString()); - } - else if (atom->type() == Atom::Target) { + if (atom->type() == Atom::Target) return Doc::canonicalTitle(atom->string()); - } - else { - return QString(); - } + return QString(); } -void DitaXmlGenerator::generateFullName(const Node *apparentNode, - const Node *relative, - CodeMarker *marker, - const Node *actualNode) +void DitaXmlGenerator::generateFullName(const Node* apparentNode, + const Node* relative, + CodeMarker* marker, + const Node* actualNode) { if (actualNode == 0) actualNode = apparentNode; - out() << "<xref href=\"" << linkForNode(actualNode, relative); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",linkForNode(actualNode, relative)); if (true || relative == 0 || relative->status() != actualNode->status()) { switch (actualNode->status()) { case Node::Obsolete: - out() << "\" class=\"obsolete"; + xmlWriter().writeAttribute("outputclass","obsolete"); break; case Node::Compat: - out() << "\" class=\"compat"; + xmlWriter().writeAttribute("outputclass","compat"); break; default: - ; + break; } } - out() << "\">"; - out() << protectEnc(fullName(apparentNode, relative, marker)); - out() << "</xref>"; + xmlWriter().writeCharacters(protectEnc(fullName(apparentNode, relative, marker))); + xmlWriter().writeEndElement(); // </xref> } -void DitaXmlGenerator::generateDetailedMember(const Node *node, - const InnerNode *relative, - CodeMarker *marker) +void DitaXmlGenerator::generateDetailedMember(Node* node, + const InnerNode* relative, + CodeMarker* marker) { - const EnumNode *enume; - -#ifdef GENERATE_MAC_REFS - generateMacRef(node, marker); -#endif - if (node->type() == Node::Enum - && (enume = static_cast<const EnumNode *>(node))->flagsType()) { -#ifdef GENERATE_MAC_REFS - generateMacRef(enume->flagsType(), marker); -#endif - out() << "<h3 class=\"flags\">"; - out() << "<a name=\"" + refForNode(node) + "\"></a>"; - generateSynopsis(enume, relative, marker, CodeMarker::Detailed); - out() << "<br/>"; - generateSynopsis(enume->flagsType(), - relative, - marker, - CodeMarker::Detailed); - out() << "</h3>\n"; + QString marked; + const EnumNode* en; + + if ((node->type() == Node::Enum) && + (en = static_cast<const EnumNode*>(node))->flagsType()) { + xmlWriter().writeStartElement("p"); + writeGuidAttribute(node); + xmlWriter().writeAttribute("outputclass","h3 flags"); + marked = getMarkedUpSynopsis(en, relative, marker, CodeMarker::Detailed); + writeText(marked, marker, relative); + xmlWriter().writeCharacters("\n"); + marked = getMarkedUpSynopsis(en->flagsType(),relative,marker,CodeMarker::Detailed); + writeText(marked,marker,relative); + xmlWriter().writeEndElement(); // </p> } else { - out() << "<h3 class=\"fn\">"; - out() << "<a name=\"" + refForNode(node) + "\"></a>"; - generateSynopsis(node, relative, marker, CodeMarker::Detailed); - out() << "</h3>\n"; + xmlWriter().writeStartElement("p"); + writeGuidAttribute(node); + xmlWriter().writeAttribute("outputclass","h3 fn"); + marked = getMarkedUpSynopsis(node, relative, marker, CodeMarker::Detailed); + writeText(marked, marker, relative); + xmlWriter().writeEndElement(); // </p> } generateStatus(node, marker); @@ -3612,35 +3888,40 @@ void DitaXmlGenerator::generateDetailedMember(const Node *node, section.members += property->resetters(); if (!section.members.isEmpty()) { - out() << "<p><b>Access functions:</b></p>\n"; - generateSectionList(section, node, marker, CodeMarker::Accessors); + xmlWriter().writeStartElement("p"); + xmlWriter().writeCharacters("<b>Access functions:</b>"); + xmlWriter().writeEndElement(); // </p> + generateSection(section.members, node, marker, CodeMarker::Accessors); } Section notifiers; notifiers.members += property->notifiers(); if (!notifiers.members.isEmpty()) { - out() << "<p><b>Notifier signal:</b></p>\n"; - //out() << "<p>This signal is emitted when the property value is changed.</p>\n"; - generateSectionList(notifiers, node, marker, CodeMarker::Accessors); + xmlWriter().writeStartElement("p"); + xmlWriter().writeCharacters("<b>Notifier signal:</b>"); + xmlWriter().writeEndElement(); // </p> + generateSection(notifiers.members, node, marker, CodeMarker::Accessors); } } else if (node->type() == Node::Enum) { - const EnumNode *enume = static_cast<const EnumNode *>(node); - if (enume->flagsType()) { - out() << "<p>The " << protectEnc(enume->flagsType()->name()) - << " type is a typedef for " - << "<xref href=\"qflags.html\">QFlags</xref><" - << protectEnc(enume->name()) - << ">. It stores an OR combination of " - << protectEnc(enume->name()) - << " values.</p>\n"; + en = static_cast<const EnumNode *>(node); + if (en->flagsType()) { + xmlWriter().writeStartElement("p"); + QString text = "The " + protectEnc(en->flagsType()->name()) + + " type is a typedef for " + + "<xref href=\"qflags.html\">QFlags</xref><" + + protectEnc(en->name()) + + ">. It stores an OR combination of " + + protectEnc(en->name()) + " values."; + xmlWriter().writeCharacters(text); + xmlWriter().writeEndElement(); // </p> } } generateAlsoList(node, marker); } -void DitaXmlGenerator::findAllClasses(const InnerNode *node) +void DitaXmlGenerator::findAllClasses(const InnerNode* node) { NodeList::const_iterator c = node->childNodes().constBegin(); while (c != node->childNodes().constEnd()) { @@ -3694,10 +3975,10 @@ void DitaXmlGenerator::findAllClasses(const InnerNode *node) } /*! - For generating the "New Classes... in 4.6" section on the - What's New in 4.6" page. + For generating the "New Classes... in 4.x" section on the + What's New in 4.x" page. */ -void DitaXmlGenerator::findAllSince(const InnerNode *node) +void DitaXmlGenerator::findAllSince(const InnerNode* node) { NodeList::const_iterator child = node->childNodes().constBegin(); while (child != node->childNodes().constEnd()) { @@ -3757,23 +4038,16 @@ void DitaXmlGenerator::findAllSince(const InnerNode *node) } } -#if 0 - const QRegExp versionSeparator("[\\-\\.]"); - const int minorIndex = version.indexOf(versionSeparator); - const int patchIndex = version.indexOf(versionSeparator, minorIndex+1); - version = version.left(patchIndex); -#endif - -void DitaXmlGenerator::findAllFunctions(const InnerNode *node) +void DitaXmlGenerator::findAllFunctions(const InnerNode* node) { NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { if ((*c)->access() != Node::Private) { if ((*c)->isInnerNode() && (*c)->url().isEmpty()) { - findAllFunctions(static_cast<const InnerNode *>(*c)); + findAllFunctions(static_cast<const InnerNode*>(*c)); } else if ((*c)->type() == Node::Function) { - const FunctionNode *func = static_cast<const FunctionNode *>(*c); + const FunctionNode* func = static_cast<const FunctionNode*>(*c); if ((func->status() > Node::Obsolete) && (func->metaness() != FunctionNode::Ctor) && (func->metaness() != FunctionNode::Dtor)) { @@ -3785,7 +4059,7 @@ void DitaXmlGenerator::findAllFunctions(const InnerNode *node) } } -void DitaXmlGenerator::findAllLegaleseTexts(const InnerNode *node) +void DitaXmlGenerator::findAllLegaleseTexts(const InnerNode* node) { NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { @@ -3799,7 +4073,7 @@ void DitaXmlGenerator::findAllLegaleseTexts(const InnerNode *node) } } -void DitaXmlGenerator::findAllNamespaces(const InnerNode *node) +void DitaXmlGenerator::findAllNamespaces(const InnerNode* node) { NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { @@ -3827,7 +4101,7 @@ void DitaXmlGenerator::findAllNamespaces(const InnerNode *node) } } -int DitaXmlGenerator::hOffset(const Node *node) +int DitaXmlGenerator::hOffset(const Node* node) { switch (node->type()) { case Node::Namespace: @@ -3835,12 +4109,6 @@ int DitaXmlGenerator::hOffset(const Node *node) return 2; case Node::Fake: return 1; -#if 0 - if (node->doc().briefText().isEmpty()) - return 1; - else - return 2; -#endif case Node::Enum: case Node::Typedef: case Node::Function: @@ -3850,7 +4118,7 @@ int DitaXmlGenerator::hOffset(const Node *node) } } -bool DitaXmlGenerator::isThreeColumnEnumValueTable(const Atom *atom) +bool DitaXmlGenerator::isThreeColumnEnumValueTable(const Atom* atom) { while (atom != 0 && !(atom->type() == Atom::ListRight && atom->string() == ATOM_LIST_VALUE)) { if (atom->type() == Atom::ListItemLeft && !matchAhead(atom, Atom::ListItemRight)) @@ -3860,12 +4128,12 @@ bool DitaXmlGenerator::isThreeColumnEnumValueTable(const Atom *atom) return false; } -const Node *DitaXmlGenerator::findNodeForTarget(const QString &target, - const Node *relative, - CodeMarker *marker, - const Atom *atom) +const Node* DitaXmlGenerator::findNodeForTarget(const QString& target, + const Node* relative, + CodeMarker* marker, + const Atom* atom) { - const Node *node = 0; + const Node* node = 0; if (target.isEmpty()) { node = relative; @@ -3889,10 +4157,9 @@ const Node *DitaXmlGenerator::findNodeForTarget(const QString &target, return node; } -const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node *node) +const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node* node) { QPair<QString,QString> anchorPair; - anchorPair.first = PageGenerator::fileName(node); if (node->type() == Node::Fake) { const FakeNode *fakeNode = static_cast<const FakeNode*>(node); @@ -3902,36 +4169,34 @@ const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node *node) return anchorPair; } -QString DitaXmlGenerator::getLink(const Atom *atom, - const Node *relative, - CodeMarker *marker, - const Node** node) +QString DitaXmlGenerator::getLink(const Atom* atom, + const Node* relative, + CodeMarker* marker, + const Node** node) { QString link; *node = 0; inObsoleteLink = false; if (atom->string().contains(":") && - (atom->string().startsWith("file:") - || atom->string().startsWith("http:") - || atom->string().startsWith("https:") - || atom->string().startsWith("ftp:") - || atom->string().startsWith("mailto:"))) { - + (atom->string().startsWith("file:") + || atom->string().startsWith("http:") + || atom->string().startsWith("https:") + || atom->string().startsWith("ftp:") + || atom->string().startsWith("mailto:"))) { + link = atom->string(); } else { QStringList path; - if (atom->string().contains('#')) { + if (atom->string().contains('#')) path = atom->string().split('#'); - } - else { + else path.append(atom->string()); - } - - Atom *targetAtom = 0; + Atom* targetAtom = 0; QString first = path.first().trimmed(); + if (first.isEmpty()) { *node = relative; } @@ -3949,51 +4214,36 @@ QString DitaXmlGenerator::getLink(const Atom *atom, } if (*node) { - if (!(*node)->url().isEmpty()) + if (!(*node)->url().isEmpty()) { return (*node)->url(); - else + } + else { path.removeFirst(); + } } else { *node = relative; } - if (*node) { - if ((*node)->status() == Node::Obsolete) { - if (relative) { - if (relative->parent() != *node) { - if (relative->status() != Node::Obsolete) { - bool porting = false; - if (relative->type() == Node::Fake) { - const FakeNode* fake = static_cast<const FakeNode*>(relative); - if (fake->title().startsWith("Porting")) - porting = true; - } - QString name = marker->plainFullName(relative); - if (!porting && !name.startsWith("Q3")) { - if (obsoleteLinks) { - relative->doc().location().warning(tr("Link to obsolete item '%1' in %2") - .arg(atom->string()) - .arg(name)); - } - inObsoleteLink = true; - } - } - } + if (*node && (*node)->status() == Node::Obsolete) { + if (relative && (relative->parent() != *node) && + (relative->status() != Node::Obsolete)) { + bool porting = false; + if (relative->type() == Node::Fake) { + const FakeNode* fake = static_cast<const FakeNode*>(relative); + if (fake->title().startsWith("Porting")) + porting = true; } - else { - qDebug() << "Link to Obsolete entity" - << (*node)->name() << "no relative"; + QString name = marker->plainFullName(relative); + if (!porting && !name.startsWith("Q3")) { + if (obsoleteLinks) { + relative->doc().location().warning(tr("Link to obsolete item '%1' in %2") + .arg(atom->string()) + .arg(name)); + } + inObsoleteLink = true; } } -#if 0 - else if ((*node)->status() == Node::Deprecated) { - qDebug() << "Link to Deprecated entity"; - } - else if ((*node)->status() == Node::Internal) { - qDebug() << "Link to Internal entity"; - } -#endif } while (!path.isEmpty()) { @@ -4014,14 +4264,14 @@ QString DitaXmlGenerator::getLink(const Atom *atom, return link; } -void DitaXmlGenerator::generateIndex(const QString &fileBase, - const QString &url, - const QString &title) +void DitaXmlGenerator::generateIndex(const QString& fileBase, + const QString& url, + const QString& title) { myTree->generateIndex(outputDir() + "/" + fileBase + ".index", url, title); } -void DitaXmlGenerator::generateStatus(const Node *node, CodeMarker *marker) +void DitaXmlGenerator::generateStatus(const Node* node, CodeMarker* marker) { Text text; @@ -4046,13 +4296,13 @@ void DitaXmlGenerator::generateStatus(const Node *node, CodeMarker *marker) Atom *targetAtom = 0; if (fakeNode && node->type() == Node::Class) { QString oldName(node->name()); - targetAtom = myTree->findTarget(oldName.replace("3", ""), - fakeNode); + targetAtom = myTree->findTarget(oldName.replace("3",""),fakeNode); } if (targetAtom) { - text << Atom(Atom::Link, linkForNode(fakeNode, node) + "#" + - refForAtom(targetAtom, fakeNode)); + QString fn = fileName(fakeNode); + QString guid = lookupGuid(fn,refForAtom(targetAtom,fakeNode)); + text << Atom(Atom::GuidLink, fn + "#" + guid); } else text << Atom(Atom::Link, "Porting to Qt 4"); @@ -4070,25 +4320,10 @@ void DitaXmlGenerator::generateStatus(const Node *node, CodeMarker *marker) } } -#ifdef GENERATE_MAC_REFS -/* - No longer valid. - */ -void DitaXmlGenerator::generateMacRef(const Node *node, CodeMarker *marker) -{ - if (!pleaseGenerateMacRef || marker == 0) - return; - - QStringList macRefs = marker->macRefsForNode(node); - foreach (const QString &macRef, macRefs) - out() << "<a name=\"" << "//apple_ref/" << macRef << "\"></a>\n"; -} -#endif - -void DitaXmlGenerator::beginLink(const QString &link, - const Node *node, - const Node *relative, - CodeMarker *marker) +void DitaXmlGenerator::beginLink(const QString& link, + const Node* node, + const Node* relative, + CodeMarker* marker) { Q_UNUSED(marker) Q_UNUSED(relative) @@ -4096,28 +4331,28 @@ void DitaXmlGenerator::beginLink(const QString &link, this->link = link; if (link.isEmpty()) { if (showBrokenLinks) - writer.writeStartElement("i"); + xmlWriter().writeStartElement("i"); } else if (node == 0 || (relative != 0 && node->status() == relative->status())) { - writer.writeStartElement("xref"); - writer.writeAttribute("href",link); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",link); } else { switch (node->status()) { case Node::Obsolete: - writer.writeStartElement("xref"); - writer.writeAttribute("href",link); - writer.writeAttribute("outputclass","obsolete"); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",link); + xmlWriter().writeAttribute("outputclass","obsolete"); break; case Node::Compat: - writer.writeStartElement("xref"); - writer.writeAttribute("href",link); - writer.writeAttribute("outputclass","compat"); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",link); + xmlWriter().writeAttribute("outputclass","compat"); break; default: - writer.writeStartElement("xref"); - writer.writeAttribute("href",link); + xmlWriter().writeStartElement("xref"); + xmlWriter().writeAttribute("href",link); } } inLink = true; @@ -4128,23 +4363,21 @@ void DitaXmlGenerator::endLink() if (inLink) { if (link.isEmpty()) { if (showBrokenLinks) - writer.writeEndElement(); // i + xmlWriter().writeEndElement(); // </i> } else { if (inObsoleteLink) { - writer.writeStartElement("sup"); - writer.writeCharacters("(obsolete)"); - writer.writeEndElement(); // sup + xmlWriter().writeStartElement("sup"); + xmlWriter().writeCharacters("(obsolete)"); + xmlWriter().writeEndElement(); // </sup> } - writer.writeEndElement(); // xref + xmlWriter().writeEndElement(); // </xref> } } inLink = false; inObsoleteLink = false; } -#ifdef QDOC_QML - /*! Generates the summary for the \a section. Only used for sections of QML element documentation. @@ -4152,126 +4385,85 @@ void DitaXmlGenerator::endLink() Currently handles only the QML property group. */ void DitaXmlGenerator::generateQmlSummary(const Section& section, - const Node *relative, - CodeMarker *marker) + const Node* relative, + CodeMarker* marker) { if (!section.members.isEmpty()) { + xmlWriter().writeStartElement("ul"); NodeList::ConstIterator m; - int count = section.members.size(); - bool twoColumn = false; - if (section.members.first()->type() == Node::QmlProperty) { - twoColumn = (count >= 5); - } - if (twoColumn) - out() << "<table class=\"qmlsummary\">\n"; - if (++numTableRows % 2 == 1) - out() << "<tr class=\"odd topAlign\">"; - else - out() << "<tr class=\"even topAlign\">"; - // << "<tr><td class=\"topAlign\">"; - out() << "<ul>\n"; - - int row = 0; m = section.members.begin(); while (m != section.members.end()) { - if (twoColumn && row == (int) (count + 1) / 2) - out() << "</ul></td><td class=\"topAlign\"><ul>\n"; - out() << "<li class=\"fn\">"; + xmlWriter().writeStartElement("li"); generateQmlItem(*m,relative,marker,true); - out() << "</li>\n"; - row++; + xmlWriter().writeEndElement(); // </li> ++m; } - out() << "</ul>\n"; - if (twoColumn) - out() << "</td></tr>\n</table>\n"; + xmlWriter().writeEndElement(); // </ul> } } /*! + zzz Outputs the html detailed documentation for a section on a QML element reference page. */ -void DitaXmlGenerator::generateDetailedQmlMember(const Node *node, - const InnerNode *relative, - CodeMarker *marker) +void DitaXmlGenerator::generateDetailedQmlMember(const Node* node, + const InnerNode* relative, + CodeMarker* marker) { - const QmlPropertyNode* qpn = 0; -#ifdef GENERATE_MAC_REFS - generateMacRef(node, marker); -#endif - out() << "<div class=\"qmlitem\">"; + QString marked; + QmlPropertyNode* qpn = 0; if (node->subType() == Node::QmlPropertyGroup) { const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node); NodeList::ConstIterator p = qpgn->childNodes().begin(); - out() << "<div class=\"qmlproto\">"; - out() << "<table class=\"qmlname\">"; - + xmlWriter().writeStartElement("ul"); while (p != qpgn->childNodes().end()) { if ((*p)->type() == Node::QmlProperty) { qpn = static_cast<const QmlPropertyNode*>(*p); - - if (++numTableRows % 2 == 1) - out() << "<tr class=\"odd\">"; - else - out() << "<tr class=\"even\">"; - - out() << "<td><p>"; - //out() << "<tr><td>"; // old - out() << "<a name=\"" + refForNode(qpn) + "\"></a>"; + xmlWriter().writeStartElement("li"); + writeGuidAttribute(qpn); + QString attr; if (!qpn->isWritable(myTree)) - out() << "<span class=\"qmlreadonly\">read-only</span>"; - if (qpgn->isDefault()) - out() << "<span class=\"qmldefault\">default</span>"; + attr = "read-only"; + if (qpgn->isDefault()) { + if (!attr.isEmpty()) + attr += " "; + attr += "default"; + } + if (!attr.isEmpty()) + xmlWriter().writeAttribute("outputclass",attr); generateQmlItem(qpn, relative, marker, false); - out() << "</td></tr>"; + xmlWriter().writeEndElement(); // </li> } ++p; } - out() << "</table>"; - out() << "</div>"; + xmlWriter().writeEndElement(); // </ul> } else if (node->type() == Node::QmlSignal) { - const FunctionNode* qsn = static_cast<const FunctionNode*>(node); - out() << "<div class=\"qmlproto\">"; - out() << "<table class=\"qmlname\">"; - //out() << "<tr>"; - if (++numTableRows % 2 == 1) - out() << "<tr class=\"odd\">"; - else - out() << "<tr class=\"even\">"; - out() << "<td><p>"; - out() << "<a name=\"" + refForNode(qsn) + "\"></a>"; - generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false); - //generateQmlItem(qsn,relative,marker,false); - out() << "</p></td></tr>"; - out() << "</table>"; - out() << "</div>"; + Node* n = const_cast<Node*>(node); + xmlWriter().writeStartElement("ul"); + xmlWriter().writeStartElement("li"); + writeGuidAttribute(n); + marked = getMarkedUpSynopsis(n, relative, marker, CodeMarker::Detailed); + writeText(marked, marker, relative); + xmlWriter().writeEndElement(); // </li> + xmlWriter().writeEndElement(); // </ul> } else if (node->type() == Node::QmlMethod) { - const FunctionNode* qmn = static_cast<const FunctionNode*>(node); - out() << "<div class=\"qmlproto\">"; - out() << "<table class=\"qmlname\">"; - //out() << "<tr>"; - if (++numTableRows % 2 == 1) - out() << "<tr class=\"odd\">"; - else - out() << "<tr class=\"even\">"; - out() << "<td><p>"; - out() << "<a name=\"" + refForNode(qmn) + "\"></a>"; - generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false); - out() << "</p></td></tr>"; - out() << "</table>"; - out() << "</div>"; - } - out() << "<div class=\"qmldoc\">"; + Node* n = const_cast<Node*>(node); + xmlWriter().writeStartElement("ul"); + xmlWriter().writeStartElement("li"); + writeGuidAttribute(n); + marked = getMarkedUpSynopsis(n, relative, marker, CodeMarker::Detailed); + writeText(marked, marker, relative); + xmlWriter().writeEndElement(); // </li> + xmlWriter().writeEndElement(); // </ul> + } generateStatus(node, marker); generateBody(node, marker); generateThreadSafeness(node, marker); generateSince(node, marker); generateAlsoList(node, marker); - out() << "</div>"; - out() << "</div>"; } /*! @@ -4279,7 +4471,7 @@ void DitaXmlGenerator::generateDetailedQmlMember(const Node *node, if there should be one. */ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* cn, - CodeMarker* marker) + CodeMarker* marker) { if (cn && !cn->links().empty()) { if (cn->links().contains(Node::InheritsLink)) { @@ -4289,7 +4481,8 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* cn, const Node* n = myTree->findNode(strList,Node::Fake); if (n && n->subType() == Node::QmlClass) { const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n); - out() << "<p class=\"centerAlign\">"; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","centerAlign"); Text text; text << "[Inherits "; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); @@ -4298,7 +4491,7 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* cn, text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); text << "]"; generateText(text, cn, marker); - out() << "</p>"; + xmlWriter().writeEndElement(); // </p> } } } @@ -4309,7 +4502,7 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* cn, if it is inherited by any other elements. */ void DitaXmlGenerator::generateQmlInheritedBy(const QmlClassNode* cn, - CodeMarker* marker) + CodeMarker* marker) { if (cn) { NodeList subs; @@ -4332,11 +4525,12 @@ void DitaXmlGenerator::generateQmlInheritedBy(const QmlClassNode* cn, is set to Node::Internal, do nothing. */ void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, - CodeMarker* marker) + CodeMarker* marker) { const ClassNode* cn = qcn->classNode(); if (cn && (cn->status() != Node::Internal)) { - out() << "<p class=\"centerAlign\">"; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","centerAlign"); Text text; text << "["; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); @@ -4350,7 +4544,7 @@ void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); text << "]"; generateText(text, qcn, marker); - out() << "</p>"; + xmlWriter().writeEndElement(); // </p> } } @@ -4367,7 +4561,8 @@ void DitaXmlGenerator::generateInstantiatedBy(const ClassNode* cn, if (cn && cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) { const Node* n = myTree->root()->findNode(cn->qmlElement(),Node::Fake); if (n && n->subType() == Node::QmlClass) { - out() << "<p class=\"centerAlign\">"; + xmlWriter().writeStartElement("p"); + xmlWriter().writeAttribute("outputclass","centerAlign"); Text text; text << "["; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); @@ -4381,138 +4576,12 @@ void DitaXmlGenerator::generateInstantiatedBy(const ClassNode* cn, text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); text << "]"; generateText(text, cn, marker); - out() << "</p>"; - } - } -} - -/*! - Generate the <page> element for the given \a node using the \a writer. - Return true if a <page> element was written; otherwise return false. - */ -bool DitaXmlGenerator::generatePageElement(QXmlStreamWriter& writer, - const Node* node, - CodeMarker* marker) const -{ - if (node->pageType() == Node::NoPageType) - return false; - if (node->name().isEmpty()) - return true; - if (node->access() == Node::Private) - return false; - if (!node->isInnerNode()) - return false; - - QString title; - QString rawTitle; - QString fullTitle; - const InnerNode* inner = static_cast<const InnerNode*>(node); - - writer.writeStartElement("page"); - QXmlStreamAttributes attributes; - QString t; - t.setNum(id++); - switch (node->type()) { - case Node::Fake: - { - const FakeNode* fake = static_cast<const FakeNode*>(node); - title = fake->fullTitle(); - break; - } - case Node::Class: - { - title = node->name() + " Class Reference"; - break; - } - case Node::Namespace: - { - rawTitle = marker->plainName(inner); - fullTitle = marker->plainFullName(inner); - title = rawTitle + " Namespace Reference"; - break; - } - default: - title = node->name(); - break; - } - writer.writeAttribute("id",t); - writer.writeStartElement("pageWords"); - writer.writeCharacters(title); - if (!inner->pageKeywords().isEmpty()) { - const QStringList& w = inner->pageKeywords(); - for (int i = 0; i < w.size(); ++i) { - writer.writeCharacters(" "); - writer.writeCharacters(w.at(i).toLocal8Bit().constData()); - } - } - writer.writeEndElement(); - writer.writeStartElement("pageTitle"); - writer.writeCharacters(title); - writer.writeEndElement(); - writer.writeStartElement("pageUrl"); - writer.writeCharacters(PageGenerator::fileName(node)); - writer.writeEndElement(); - writer.writeStartElement("pageType"); - switch (node->pageType()) { - case Node::ApiPage: - writer.writeCharacters("APIPage"); - break; - case Node::ArticlePage: - writer.writeCharacters("Article"); - break; - case Node::ExamplePage: - writer.writeCharacters("Example"); - break; - default: - break; - } - writer.writeEndElement(); - writer.writeEndElement(); - return true; -} - -/*! - Traverse the tree recursively and generate the <keyword> - elements. - */ -void DitaXmlGenerator::generatePageElements(QXmlStreamWriter& writer, const Node* node, CodeMarker* marker) const -{ - if (generatePageElement(writer, node, marker)) { - - if (node->isInnerNode()) { - const InnerNode *inner = static_cast<const InnerNode *>(node); - - // Recurse to write an element for this child node and all its children. - foreach (const Node *child, inner->childNodes()) - generatePageElements(writer, child, marker); + xmlWriter().writeEndElement(); // </p> } } } /*! - Outputs the file containing the index used for searching the html docs. - */ -void DitaXmlGenerator::generatePageIndex(const QString& fileName, CodeMarker* marker) const -{ - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) - return ; - - QXmlStreamWriter writer(&file); - writer.setAutoFormatting(true); - writer.writeStartDocument(); - writer.writeStartElement("qtPageIndex"); - - generatePageElements(writer, myTree->root(), marker); - - writer.writeEndElement(); // qtPageIndex - writer.writeEndDocument(); - file.close(); -} - -#endif - -/*! Return the full qualification of the node \a n, but without the name of \a n itself. e.g. A::B::C */ @@ -4537,35 +4606,69 @@ QString DitaXmlGenerator::fullQualification(const Node* n) return fq; } +/*! + Outputs the <cxxClassDerivations> element. + \code + <cxxClassDerivations> + <cxxClassDerivation> + ... + </cxxClassDerivation> + ... + </cxxClassDerivations> + \endcode + + The <cxxClassDerivation> element is: + + \code + <cxxClassDerivation> + <cxxClassDerivationAccessSpecifier value="public"/> + <cxxClassBaseClass href="class_base">Base</cxxClassBaseClass> + </cxxClassDerivation> + \endcode + */ void DitaXmlGenerator::writeDerivations(const ClassNode* cn, CodeMarker* marker) { QList<RelatedClass>::ConstIterator r; int index; if (!cn->baseClasses().isEmpty()) { - writer.writeStartElement(CXXCLASSDERIVATIONS); + xmlWriter().writeStartElement(CXXCLASSDERIVATIONS); r = cn->baseClasses().begin(); index = 0; while (r != cn->baseClasses().end()) { - writer.writeStartElement(CXXCLASSDERIVATION); - writer.writeStartElement(CXXCLASSDERIVATIONACCESSSPECIFIER); - writer.writeAttribute("value",(*r).accessString()); - writer.writeEndElement(); // </cxxClassDerivationAccessSpecifier> - writer.writeStartElement(CXXCLASSBASECLASS); - writer.writeAttribute("href",(*r).node->ditaXmlHref()); - writer.writeCharacters(marker->plainFullName((*r).node)); - writer.writeEndElement(); // </cxxClassBaseClass> - writer.writeEndElement(); // </cxxClassDerivation> + xmlWriter().writeStartElement(CXXCLASSDERIVATION); + xmlWriter().writeStartElement(CXXCLASSDERIVATIONACCESSSPECIFIER); + xmlWriter().writeAttribute("value",(*r).accessString()); + xmlWriter().writeEndElement(); // </cxxClassDerivationAccessSpecifier> + + // not included: <cxxClassDerivationVirtual> + + xmlWriter().writeStartElement(CXXCLASSBASECLASS); + xmlWriter().writeAttribute("href",(*r).node->ditaXmlHref()); + xmlWriter().writeCharacters(marker->plainFullName((*r).node)); + xmlWriter().writeEndElement(); // </cxxClassBaseClass> + + // not included: <ClassBaseStruct> or <cxxClassBaseUnion> + + xmlWriter().writeEndElement(); // </cxxClassDerivation> + + // not included: <cxxStructDerivation> + ++r; } - writer.writeEndElement(); // </cxxClassDerivations> + xmlWriter().writeEndElement(); // </cxxClassDerivations> } } +/*! + Writes a <cxxXXXAPIItemLocation> element, depending on the + type of the node \a n, which can be a class, function, enum, + typedef, or property. + */ void DitaXmlGenerator::writeLocation(const Node* n) { QString s1, s2, s3; - if (n->type() == Node::Class) { + if (n->type() == Node::Class || n->type() == Node::Namespace) { s1 = CXXCLASSAPIITEMLOCATION; s2 = CXXCLASSDECLARATIONFILE; s3 = CXXCLASSDECLARATIONFILELINE; @@ -4591,92 +4694,116 @@ void DitaXmlGenerator::writeLocation(const Node* n) s2 = CXXVARIABLEDECLARATIONFILE; s3 = CXXVARIABLEDECLARATIONFILELINE; } - writer.writeStartElement(s1); - writer.writeStartElement(s2); - writer.writeAttribute("name","filePath"); - writer.writeAttribute("value",n->location().filePath()); - writer.writeEndElement(); // </cxx<s2>DeclarationFile> - writer.writeStartElement(s3); - writer.writeAttribute("name","lineNumber"); + xmlWriter().writeStartElement(s1); + xmlWriter().writeStartElement(s2); + xmlWriter().writeAttribute("name","filePath"); + xmlWriter().writeAttribute("value",n->location().filePath()); + xmlWriter().writeEndElement(); // </cxx<s2>DeclarationFile> + xmlWriter().writeStartElement(s3); + xmlWriter().writeAttribute("name","lineNumber"); QString lineNr; - writer.writeAttribute("value",lineNr.setNum(n->location().lineNo())); - writer.writeEndElement(); // </cxx<s3>DeclarationFileLine> - writer.writeEndElement(); // </cxx<s1>ApiItemLocation> + xmlWriter().writeAttribute("value",lineNr.setNum(n->location().lineNo())); + xmlWriter().writeEndElement(); // </cxx<s3>DeclarationFileLine> + + // not included: <cxxXXXDefinitionFile>, <cxxXXXDefinitionFileSTart>, + // and <cxxXXXDefinitionFileEnd> + + xmlWriter().writeEndElement(); // </cxx<s1>ApiItemLocation> } +/*! + Write the <cxxFunction> elements. + */ void DitaXmlGenerator::writeFunctions(const Section& s, - const ClassNode* cn, + const Node* n, CodeMarker* marker) { NodeList::ConstIterator m = s.members.begin(); while (m != s.members.end()) { if ((*m)->type() == Node::Function) { FunctionNode* fn = const_cast<FunctionNode*>(static_cast<const FunctionNode*>(*m)); - writer.writeStartElement(CXXFUNCTION); - writer.writeAttribute("id",fn->guid()); - writer.writeStartElement(APINAME); - writer.writeCharacters(fn->name()); - writer.writeEndElement(); // </apiName> + xmlWriter().writeStartElement(CXXFUNCTION); + xmlWriter().writeAttribute("id",fn->guid()); + xmlWriter().writeStartElement(APINAME); + if (fn->metaness() == FunctionNode::Signal) + xmlWriter().writeAttribute("class","signal"); + else if (fn->metaness() == FunctionNode::Slot) + xmlWriter().writeAttribute("class","slot"); + xmlWriter().writeCharacters(fn->name()); + xmlWriter().writeEndElement(); // </apiName> generateBrief(fn,marker); - writer.writeStartElement(CXXFUNCTIONDETAIL); - writer.writeStartElement(CXXFUNCTIONDEFINITION); - writer.writeStartElement(CXXFUNCTIONACCESSSPECIFIER); - writer.writeAttribute("value",fn->accessString()); - writer.writeEndElement(); // <cxxFunctionAccessSpecifier> + + // not included: <prolog> + + xmlWriter().writeStartElement(CXXFUNCTIONDETAIL); + xmlWriter().writeStartElement(CXXFUNCTIONDEFINITION); + xmlWriter().writeStartElement(CXXFUNCTIONACCESSSPECIFIER); + xmlWriter().writeAttribute("value",fn->accessString()); + xmlWriter().writeEndElement(); // <cxxFunctionAccessSpecifier> + + // not included: <cxxFunctionStorageClassSpecifierExtern> if (fn->isStatic()) { - writer.writeStartElement(CXXFUNCTIONSTORAGECLASSSPECIFIERSTATIC); - writer.writeAttribute("name","static"); - writer.writeAttribute("value","static"); - writer.writeEndElement(); // <cxxFunctionStorageClassSpecifierStatic> + xmlWriter().writeStartElement(CXXFUNCTIONSTORAGECLASSSPECIFIERSTATIC); + xmlWriter().writeAttribute("name","static"); + xmlWriter().writeAttribute("value","static"); + xmlWriter().writeEndElement(); // <cxxFunctionStorageClassSpecifierStatic> } - + + // not included: <cxxFunctionStorageClassSpecifierMutable>, + if (fn->isConst()) { - writer.writeStartElement(CXXFUNCTIONCONST); - writer.writeAttribute("name","const"); - writer.writeAttribute("value","const"); - writer.writeEndElement(); // <cxxFunctionConst> + xmlWriter().writeStartElement(CXXFUNCTIONCONST); + xmlWriter().writeAttribute("name","const"); + xmlWriter().writeAttribute("value","const"); + xmlWriter().writeEndElement(); // <cxxFunctionConst> } + + // not included: <cxxFunctionExplicit> + // <cxxFunctionInline if (fn->virtualness() != FunctionNode::NonVirtual) { - writer.writeStartElement(CXXFUNCTIONVIRTUAL); - writer.writeAttribute("name","virtual"); - writer.writeAttribute("value","virtual"); - writer.writeEndElement(); // <cxxFunctionVirtual> + xmlWriter().writeStartElement(CXXFUNCTIONVIRTUAL); + xmlWriter().writeAttribute("name","virtual"); + xmlWriter().writeAttribute("value","virtual"); + xmlWriter().writeEndElement(); // <cxxFunctionVirtual> if (fn->virtualness() == FunctionNode::PureVirtual) { - writer.writeStartElement(CXXFUNCTIONPUREVIRTUAL); - writer.writeAttribute("name","pure virtual"); - writer.writeAttribute("value","pure virtual"); - writer.writeEndElement(); // <cxxFunctionPureVirtual> + xmlWriter().writeStartElement(CXXFUNCTIONPUREVIRTUAL); + xmlWriter().writeAttribute("name","pure virtual"); + xmlWriter().writeAttribute("value","pure virtual"); + xmlWriter().writeEndElement(); // <cxxFunctionPureVirtual> } } - if (fn->name() == cn->name()) { - writer.writeStartElement(CXXFUNCTIONCONSTRUCTOR); - writer.writeAttribute("name","constructor"); - writer.writeAttribute("value","constructor"); - writer.writeEndElement(); // <cxxFunctionConstructor> + if (fn->name() == n->name()) { + xmlWriter().writeStartElement(CXXFUNCTIONCONSTRUCTOR); + xmlWriter().writeAttribute("name","constructor"); + xmlWriter().writeAttribute("value","constructor"); + xmlWriter().writeEndElement(); // <cxxFunctionConstructor> } else if (fn->name()[0] == QChar('~')) { - writer.writeStartElement(CXXFUNCTIONDESTRUCTOR); - writer.writeAttribute("name","destructor"); - writer.writeAttribute("value","destructor"); - writer.writeEndElement(); // <cxxFunctionDestructor> + xmlWriter().writeStartElement(CXXFUNCTIONDESTRUCTOR); + xmlWriter().writeAttribute("name","destructor"); + xmlWriter().writeAttribute("value","destructor"); + xmlWriter().writeEndElement(); // <cxxFunctionDestructor> } else { - writer.writeStartElement(CXXFUNCTIONDECLAREDTYPE); - writer.writeCharacters(fn->returnType()); - writer.writeEndElement(); // <cxxFunctionDeclaredType> + xmlWriter().writeStartElement(CXXFUNCTIONDECLAREDTYPE); + xmlWriter().writeCharacters(fn->returnType()); + xmlWriter().writeEndElement(); // <cxxFunctionDeclaredType> } + + // not included: <cxxFunctionReturnType> + QString fq = fullQualification(fn); if (!fq.isEmpty()) { - writer.writeStartElement(CXXFUNCTIONSCOPEDNAME); - writer.writeCharacters(fq); - writer.writeEndElement(); // <cxxFunctionScopedName> + xmlWriter().writeStartElement(CXXFUNCTIONSCOPEDNAME); + xmlWriter().writeCharacters(fq); + xmlWriter().writeEndElement(); // <cxxFunctionScopedName> } - writer.writeStartElement(CXXFUNCTIONPROTOTYPE); - writer.writeCharacters(fn->signature(true)); - writer.writeEndElement(); // <cxxFunctionPrototype> + xmlWriter().writeStartElement(CXXFUNCTIONPROTOTYPE); + xmlWriter().writeCharacters(fn->signature(true)); + xmlWriter().writeEndElement(); // <cxxFunctionPrototype> QString fnl = fn->signature(false); int idx = fnl.indexOf(' '); @@ -4685,30 +4812,28 @@ void DitaXmlGenerator::writeFunctions(const Section& s, else ++idx; fnl = fn->parent()->name() + "::" + fnl.mid(idx); - writer.writeStartElement(CXXFUNCTIONNAMELOOKUP); - writer.writeCharacters(fnl); - writer.writeEndElement(); // <cxxFunctionNameLookup> + xmlWriter().writeStartElement(CXXFUNCTIONNAMELOOKUP); + xmlWriter().writeCharacters(fnl); + xmlWriter().writeEndElement(); // <cxxFunctionNameLookup> if (fn->isReimp() && fn->reimplementedFrom() != 0) { FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom(); - writer.writeStartElement(CXXFUNCTIONREIMPLEMENTED); - writer.writeAttribute("href",rfn->ditaXmlHref()); - writer.writeCharacters(marker->plainFullName(rfn)); - writer.writeEndElement(); // </cxxFunctionReimplemented> + xmlWriter().writeStartElement(CXXFUNCTIONREIMPLEMENTED); + xmlWriter().writeAttribute("href",rfn->ditaXmlHref()); + xmlWriter().writeCharacters(marker->plainFullName(rfn)); + xmlWriter().writeEndElement(); // </cxxFunctionReimplemented> } - writeParameters(fn,marker); + writeParameters(fn); writeLocation(fn); - writer.writeEndElement(); // <cxxFunctionDefinition> - writer.writeStartElement(APIDESC); + xmlWriter().writeEndElement(); // <cxxFunctionDefinition> - if (!fn->doc().isEmpty()) { - generateBody(fn, marker); - // generateAlsoList(inner, marker); - } + writeDetailedDescription(fn, marker, true, QString()); + // generateAlsoList(inner, marker); + + // not included: <example> or <apiImpl> - writer.writeEndElement(); // </apiDesc> - writer.writeEndElement(); // </cxxFunctionDetail> - writer.writeEndElement(); // </cxxFunction> + xmlWriter().writeEndElement(); // </cxxFunctionDetail> + xmlWriter().writeEndElement(); // </cxxFunction> if (fn->metaness() == FunctionNode::Ctor || fn->metaness() == FunctionNode::Dtor || @@ -4719,352 +4844,412 @@ void DitaXmlGenerator::writeFunctions(const Section& s, } } -void DitaXmlGenerator::writeParameters(const FunctionNode* fn, CodeMarker* marker) +/*! + This function writes the <cxxFunctionParameters> element. + */ +void DitaXmlGenerator::writeParameters(const FunctionNode* fn) { const QList<Parameter>& parameters = fn->parameters(); if (!parameters.isEmpty()) { - writer.writeStartElement(CXXFUNCTIONPARAMETERS); + xmlWriter().writeStartElement(CXXFUNCTIONPARAMETERS); QList<Parameter>::ConstIterator p = parameters.begin(); while (p != parameters.end()) { - writer.writeStartElement(CXXFUNCTIONPARAMETER); - writer.writeStartElement(CXXFUNCTIONPARAMETERDECLAREDTYPE); - writer.writeCharacters((*p).leftType()); + xmlWriter().writeStartElement(CXXFUNCTIONPARAMETER); + xmlWriter().writeStartElement(CXXFUNCTIONPARAMETERDECLAREDTYPE); + xmlWriter().writeCharacters((*p).leftType()); if (!(*p).rightType().isEmpty()) - writer.writeCharacters((*p).rightType()); - writer.writeEndElement(); // <cxxFunctionParameterDeclaredType> - writer.writeStartElement(CXXFUNCTIONPARAMETERDECLARATIONNAME); - writer.writeCharacters((*p).name()); - writer.writeEndElement(); // <cxxFunctionParameterDeclarationName> + xmlWriter().writeCharacters((*p).rightType()); + xmlWriter().writeEndElement(); // <cxxFunctionParameterDeclaredType> + xmlWriter().writeStartElement(CXXFUNCTIONPARAMETERDECLARATIONNAME); + xmlWriter().writeCharacters((*p).name()); + xmlWriter().writeEndElement(); // <cxxFunctionParameterDeclarationName> + + // not included: <cxxFunctionParameterDefinitionName> + if (!(*p).defaultValue().isEmpty()) { - writer.writeStartElement(CXXFUNCTIONPARAMETERDEFAULTVALUE); - writer.writeCharacters((*p).defaultValue()); - writer.writeEndElement(); // <cxxFunctionParameterDefaultValue> + xmlWriter().writeStartElement(CXXFUNCTIONPARAMETERDEFAULTVALUE); + xmlWriter().writeCharacters((*p).defaultValue()); + xmlWriter().writeEndElement(); // <cxxFunctionParameterDefaultValue> } - writer.writeEndElement(); // <cxxFunctionParameter> + + // not included: <apiDefNote> + + xmlWriter().writeEndElement(); // <cxxFunctionParameter> ++p; } - writer.writeEndElement(); // <cxxFunctionParameters> + xmlWriter().writeEndElement(); // <cxxFunctionParameters> } } +/*! + This function writes the enum types. + */ void DitaXmlGenerator::writeEnumerations(const Section& s, - const ClassNode* cn, CodeMarker* marker) { NodeList::ConstIterator m = s.members.begin(); while (m != s.members.end()) { if ((*m)->type() == Node::Enum) { const EnumNode* en = static_cast<const EnumNode*>(*m); - writer.writeStartElement(CXXENUMERATION); - writer.writeAttribute("id",en->guid()); - writer.writeStartElement(APINAME); - writer.writeCharacters(en->name()); - writer.writeEndElement(); // </apiName> + xmlWriter().writeStartElement(CXXENUMERATION); + xmlWriter().writeAttribute("id",en->guid()); + xmlWriter().writeStartElement(APINAME); + xmlWriter().writeCharacters(en->name()); + xmlWriter().writeEndElement(); // </apiName> generateBrief(en,marker); - writer.writeStartElement(CXXENUMERATIONDETAIL); - writer.writeStartElement(CXXENUMERATIONDEFINITION); - writer.writeStartElement(CXXENUMERATIONACCESSSPECIFIER); - writer.writeAttribute("value",en->accessString()); - writer.writeEndElement(); // <cxxEnumerationAccessSpecifier> + + // not included <prolog> + + xmlWriter().writeStartElement(CXXENUMERATIONDETAIL); + xmlWriter().writeStartElement(CXXENUMERATIONDEFINITION); + xmlWriter().writeStartElement(CXXENUMERATIONACCESSSPECIFIER); + xmlWriter().writeAttribute("value",en->accessString()); + xmlWriter().writeEndElement(); // <cxxEnumerationAccessSpecifier> QString fq = fullQualification(en); if (!fq.isEmpty()) { - writer.writeStartElement(CXXENUMERATIONSCOPEDNAME); - writer.writeCharacters(fq); - writer.writeEndElement(); // <cxxEnumerationScopedName> + xmlWriter().writeStartElement(CXXENUMERATIONSCOPEDNAME); + xmlWriter().writeCharacters(fq); + xmlWriter().writeEndElement(); // <cxxEnumerationScopedName> } const QList<EnumItem>& items = en->items(); if (!items.isEmpty()) { - writer.writeStartElement(CXXENUMERATIONPROTOTYPE); - writer.writeCharacters(en->name()); - writer.writeCharacters(" = { "); + xmlWriter().writeStartElement(CXXENUMERATIONPROTOTYPE); + xmlWriter().writeCharacters(en->name()); + xmlWriter().writeCharacters(" = { "); QList<EnumItem>::ConstIterator i = items.begin(); while (i != items.end()) { - writer.writeCharacters((*i).name()); + xmlWriter().writeCharacters((*i).name()); if (!(*i).value().isEmpty()) { - writer.writeCharacters(" = "); - writer.writeCharacters((*i).value()); + xmlWriter().writeCharacters(" = "); + xmlWriter().writeCharacters((*i).value()); } ++i; if (i != items.end()) - writer.writeCharacters(", "); + xmlWriter().writeCharacters(", "); } - writer.writeCharacters(" }"); - writer.writeEndElement(); // <cxxEnumerationPrototype> + xmlWriter().writeCharacters(" }"); + xmlWriter().writeEndElement(); // <cxxEnumerationPrototype> } - writer.writeStartElement(CXXENUMERATIONNAMELOOKUP); - writer.writeCharacters(en->parent()->name() + "::" + en->name()); - writer.writeEndElement(); // <cxxEnumerationNameLookup> + xmlWriter().writeStartElement(CXXENUMERATIONNAMELOOKUP); + xmlWriter().writeCharacters(en->parent()->name() + "::" + en->name()); + xmlWriter().writeEndElement(); // <cxxEnumerationNameLookup> + + // not included: <cxxEnumerationReimplemented> if (!items.isEmpty()) { - writer.writeStartElement(CXXENUMERATORS); + xmlWriter().writeStartElement(CXXENUMERATORS); QList<EnumItem>::ConstIterator i = items.begin(); while (i != items.end()) { - writer.writeStartElement(CXXENUMERATOR); - writer.writeStartElement(APINAME); - writer.writeCharacters((*i).name()); - writer.writeEndElement(); // </apiName> + xmlWriter().writeStartElement(CXXENUMERATOR); + xmlWriter().writeStartElement(APINAME); + xmlWriter().writeCharacters((*i).name()); + xmlWriter().writeEndElement(); // </apiName> QString fq = fullQualification(en->parent()); if (!fq.isEmpty()) { - writer.writeStartElement(CXXENUMERATORSCOPEDNAME); - writer.writeCharacters(fq + "::" + (*i).name()); - writer.writeEndElement(); // <cxxEnumeratorScopedName> + xmlWriter().writeStartElement(CXXENUMERATORSCOPEDNAME); + xmlWriter().writeCharacters(fq + "::" + (*i).name()); + xmlWriter().writeEndElement(); // <cxxEnumeratorScopedName> } - writer.writeStartElement(CXXENUMERATORPROTOTYPE); - writer.writeCharacters((*i).name()); - writer.writeEndElement(); // <cxxEnumeratorPrototype> - writer.writeStartElement(CXXENUMERATORNAMELOOKUP); - writer.writeCharacters(en->parent()->name() + "::" + (*i).name()); - writer.writeEndElement(); // <cxxEnumeratorNameLookup> + xmlWriter().writeStartElement(CXXENUMERATORPROTOTYPE); + xmlWriter().writeCharacters((*i).name()); + xmlWriter().writeEndElement(); // <cxxEnumeratorPrototype> + xmlWriter().writeStartElement(CXXENUMERATORNAMELOOKUP); + xmlWriter().writeCharacters(en->parent()->name() + "::" + (*i).name()); + xmlWriter().writeEndElement(); // <cxxEnumeratorNameLookup> if (!(*i).value().isEmpty()) { - writer.writeStartElement(CXXENUMERATORINITIALISER); - writer.writeAttribute("value", (*i).value()); - writer.writeEndElement(); // <cxxEnumeratorInitialiser> + xmlWriter().writeStartElement(CXXENUMERATORINITIALISER); + xmlWriter().writeAttribute("value", (*i).value()); + xmlWriter().writeEndElement(); // <cxxEnumeratorInitialiser> } + + // not included: <cxxEnumeratorAPIItemLocation> + if (!(*i).text().isEmpty()) { - writer.writeStartElement(APIDESC); + xmlWriter().writeStartElement(APIDESC); generateText((*i).text(), en, marker); - writer.writeEndElement(); // </apiDesc> + xmlWriter().writeEndElement(); // </apiDesc> } - writer.writeEndElement(); // <cxxEnumerator> + xmlWriter().writeEndElement(); // <cxxEnumerator> ++i; } - writer.writeEndElement(); // <cxxEnumerators> + xmlWriter().writeEndElement(); // <cxxEnumerators> } writeLocation(en); - writer.writeEndElement(); // <cxxEnumerationDefinition> - writer.writeStartElement(APIDESC); + xmlWriter().writeEndElement(); // <cxxEnumerationDefinition> - if (!en->doc().isEmpty()) { - generateBody(en, marker); - } + writeDetailedDescription(en, marker, true, QString()); + + // not included: <example> or <apiImpl> + + xmlWriter().writeEndElement(); // </cxxEnumerationDetail> + + // not included: <related-links> - writer.writeEndElement(); // </apiDesc> - writer.writeEndElement(); // </cxxEnumerationDetail> - writer.writeEndElement(); // </cxxEnumeration> + xmlWriter().writeEndElement(); // </cxxEnumeration> } ++m; } } +/*! + This function writes the output for the \typedef commands. + */ void DitaXmlGenerator::writeTypedefs(const Section& s, - const ClassNode* cn, CodeMarker* marker) { NodeList::ConstIterator m = s.members.begin(); while (m != s.members.end()) { if ((*m)->type() == Node::Typedef) { const TypedefNode* tn = static_cast<const TypedefNode*>(*m); - writer.writeStartElement(CXXTYPEDEF); - writer.writeAttribute("id",tn->guid()); - writer.writeStartElement(APINAME); - writer.writeCharacters(tn->name()); - writer.writeEndElement(); // </apiName> + xmlWriter().writeStartElement(CXXTYPEDEF); + xmlWriter().writeAttribute("id",tn->guid()); + xmlWriter().writeStartElement(APINAME); + xmlWriter().writeCharacters(tn->name()); + xmlWriter().writeEndElement(); // </apiName> generateBrief(tn,marker); - writer.writeStartElement(CXXTYPEDEFDETAIL); - writer.writeStartElement(CXXTYPEDEFDEFINITION); - writer.writeStartElement(CXXTYPEDEFACCESSSPECIFIER); - writer.writeAttribute("value",tn->accessString()); - writer.writeEndElement(); // <cxxTypedefAccessSpecifier> + + // not included: <prolog> + + xmlWriter().writeStartElement(CXXTYPEDEFDETAIL); + xmlWriter().writeStartElement(CXXTYPEDEFDEFINITION); + xmlWriter().writeStartElement(CXXTYPEDEFACCESSSPECIFIER); + xmlWriter().writeAttribute("value",tn->accessString()); + xmlWriter().writeEndElement(); // <cxxTypedefAccessSpecifier> + + // not included: <cxxTypedefDeclaredType> QString fq = fullQualification(tn); if (!fq.isEmpty()) { - writer.writeStartElement(CXXTYPEDEFSCOPEDNAME); - writer.writeCharacters(fq); - writer.writeEndElement(); // <cxxTypedefScopedName> + xmlWriter().writeStartElement(CXXTYPEDEFSCOPEDNAME); + xmlWriter().writeCharacters(fq); + xmlWriter().writeEndElement(); // <cxxTypedefScopedName> } - writer.writeStartElement(CXXTYPEDEFNAMELOOKUP); - writer.writeCharacters(tn->parent()->name() + "::" + tn->name()); - writer.writeEndElement(); // <cxxTypedefNameLookup> - + + // not included: <cxxTypedefPrototype> + + xmlWriter().writeStartElement(CXXTYPEDEFNAMELOOKUP); + xmlWriter().writeCharacters(tn->parent()->name() + "::" + tn->name()); + xmlWriter().writeEndElement(); // <cxxTypedefNameLookup> + + // not included: <cxxTypedefReimplemented> + writeLocation(tn); - writer.writeEndElement(); // <cxxTypedefDefinition> - writer.writeStartElement(APIDESC); + xmlWriter().writeEndElement(); // <cxxTypedefDefinition> - if (!tn->doc().isEmpty()) { - generateBody(tn, marker); - } + writeDetailedDescription(tn, marker, true, QString()); + + // not included: <example> or <apiImpl> + + xmlWriter().writeEndElement(); // </cxxTypedefDetail> + + // not included: <related-links> - writer.writeEndElement(); // </apiDesc> - writer.writeEndElement(); // </cxxTypedefDetail> - writer.writeEndElement(); // </cxxTypedef> + xmlWriter().writeEndElement(); // </cxxTypedef> } ++m; } } +/*! + This function writes the output for the \property commands. + This is the Q_PROPERTYs. + */ void DitaXmlGenerator::writeProperties(const Section& s, - const ClassNode* cn, CodeMarker* marker) { NodeList::ConstIterator m = s.members.begin(); while (m != s.members.end()) { if ((*m)->type() == Node::Property) { const PropertyNode* pn = static_cast<const PropertyNode*>(*m); - writer.writeStartElement(CXXVARIABLE); - writer.writeAttribute("id",pn->guid()); - writer.writeStartElement(APINAME); - writer.writeCharacters(pn->name()); - writer.writeEndElement(); // </apiName> + xmlWriter().writeStartElement(CXXVARIABLE); + xmlWriter().writeAttribute("id",pn->guid()); + xmlWriter().writeStartElement(APINAME); + xmlWriter().writeCharacters(pn->name()); + xmlWriter().writeEndElement(); // </apiName> generateBrief(pn,marker); - writer.writeStartElement(CXXVARIABLEDETAIL); - writer.writeStartElement(CXXVARIABLEDEFINITION); - writer.writeStartElement(CXXVARIABLEACCESSSPECIFIER); - writer.writeAttribute("value",pn->accessString()); - writer.writeEndElement(); // <cxxVariableAccessSpecifier> + + // not included: <prolog> + + xmlWriter().writeStartElement(CXXVARIABLEDETAIL); + xmlWriter().writeStartElement(CXXVARIABLEDEFINITION); + xmlWriter().writeStartElement(CXXVARIABLEACCESSSPECIFIER); + xmlWriter().writeAttribute("value",pn->accessString()); + xmlWriter().writeEndElement(); // <cxxVariableAccessSpecifier> + + // not included: <cxxVariableStorageClassSpecifierExtern>, + // <cxxVariableStorageClassSpecifierStatic>, + // <cxxVariableStorageClassSpecifierMutable>, + // <cxxVariableConst>, <cxxVariableVolatile> if (!pn->qualifiedDataType().isEmpty()) { - writer.writeStartElement(CXXVARIABLEDECLAREDTYPE); - writer.writeCharacters(pn->qualifiedDataType()); - writer.writeEndElement(); // <cxxVariableDeclaredType> + xmlWriter().writeStartElement(CXXVARIABLEDECLAREDTYPE); + xmlWriter().writeCharacters(pn->qualifiedDataType()); + xmlWriter().writeEndElement(); // <cxxVariableDeclaredType> } QString fq = fullQualification(pn); if (!fq.isEmpty()) { - writer.writeStartElement(CXXVARIABLESCOPEDNAME); - writer.writeCharacters(fq); - writer.writeEndElement(); // <cxxVariableScopedName> + xmlWriter().writeStartElement(CXXVARIABLESCOPEDNAME); + xmlWriter().writeCharacters(fq); + xmlWriter().writeEndElement(); // <cxxVariableScopedName> } - writer.writeStartElement(CXXVARIABLEPROTOTYPE); - writer.writeCharacters("Q_PROPERTY("); - writer.writeCharacters(pn->qualifiedDataType()); - writer.writeCharacters(" "); - writer.writeCharacters(pn->name()); - writePropParams("READ",pn->getters()); - writePropParams("WRITE",pn->setters()); - writePropParams("RESET",pn->resetters()); - writePropParams("NOTIFY",pn->notifiers()); + xmlWriter().writeStartElement(CXXVARIABLEPROTOTYPE); + xmlWriter().writeCharacters("Q_PROPERTY("); + xmlWriter().writeCharacters(pn->qualifiedDataType()); + xmlWriter().writeCharacters(" "); + xmlWriter().writeCharacters(pn->name()); + writePropertyParameter("READ",pn->getters()); + writePropertyParameter("WRITE",pn->setters()); + writePropertyParameter("RESET",pn->resetters()); + writePropertyParameter("NOTIFY",pn->notifiers()); if (pn->isDesignable() != pn->designableDefault()) { - writer.writeCharacters(" DESIGNABLE "); + xmlWriter().writeCharacters(" DESIGNABLE "); if (!pn->runtimeDesignabilityFunction().isEmpty()) - writer.writeCharacters(pn->runtimeDesignabilityFunction()); + xmlWriter().writeCharacters(pn->runtimeDesignabilityFunction()); else - writer.writeCharacters(pn->isDesignable() ? "true" : "false"); + xmlWriter().writeCharacters(pn->isDesignable() ? "true" : "false"); } if (pn->isScriptable() != pn->scriptableDefault()) { - writer.writeCharacters(" SCRIPTABLE "); + xmlWriter().writeCharacters(" SCRIPTABLE "); if (!pn->runtimeScriptabilityFunction().isEmpty()) - writer.writeCharacters(pn->runtimeScriptabilityFunction()); + xmlWriter().writeCharacters(pn->runtimeScriptabilityFunction()); else - writer.writeCharacters(pn->isScriptable() ? "true" : "false"); + xmlWriter().writeCharacters(pn->isScriptable() ? "true" : "false"); } if (pn->isWritable() != pn->writableDefault()) { - writer.writeCharacters(" STORED "); - writer.writeCharacters(pn->isStored() ? "true" : "false"); + xmlWriter().writeCharacters(" STORED "); + xmlWriter().writeCharacters(pn->isStored() ? "true" : "false"); } if (pn->isUser() != pn->userDefault()) { - writer.writeCharacters(" USER "); - writer.writeCharacters(pn->isUser() ? "true" : "false"); + xmlWriter().writeCharacters(" USER "); + xmlWriter().writeCharacters(pn->isUser() ? "true" : "false"); } if (pn->isConstant()) - writer.writeCharacters(" CONSTANT"); + xmlWriter().writeCharacters(" CONSTANT"); if (pn->isFinal()) - writer.writeCharacters(" FINAL"); - writer.writeCharacters(")"); - writer.writeEndElement(); // <cxxVariablePrototype> + xmlWriter().writeCharacters(" FINAL"); + xmlWriter().writeCharacters(")"); + xmlWriter().writeEndElement(); // <cxxVariablePrototype> - writer.writeStartElement(CXXVARIABLENAMELOOKUP); - writer.writeCharacters(pn->parent()->name() + "::" + pn->name()); - writer.writeEndElement(); // <cxxVariableNameLookup> + xmlWriter().writeStartElement(CXXVARIABLENAMELOOKUP); + xmlWriter().writeCharacters(pn->parent()->name() + "::" + pn->name()); + xmlWriter().writeEndElement(); // <cxxVariableNameLookup> if (pn->overriddenFrom() != 0) { PropertyNode* opn = (PropertyNode*)pn->overriddenFrom(); - writer.writeStartElement(CXXVARIABLEREIMPLEMENTED); - writer.writeAttribute("href",opn->ditaXmlHref()); - writer.writeCharacters(marker->plainFullName(opn)); - writer.writeEndElement(); // </cxxVariableReimplemented> + xmlWriter().writeStartElement(CXXVARIABLEREIMPLEMENTED); + xmlWriter().writeAttribute("href",opn->ditaXmlHref()); + xmlWriter().writeCharacters(marker->plainFullName(opn)); + xmlWriter().writeEndElement(); // </cxxVariableReimplemented> } writeLocation(pn); - writer.writeEndElement(); // <cxxVariableDefinition> - writer.writeStartElement(APIDESC); + xmlWriter().writeEndElement(); // <cxxVariableDefinition> - if (!pn->doc().isEmpty()) { - generateBody(pn, marker); - } + writeDetailedDescription(pn, marker, true, QString()); + + // not included: <example> or <apiImpl> - writer.writeEndElement(); // </apiDesc> - writer.writeEndElement(); // </cxxVariableDetail> - writer.writeEndElement(); // </cxxVariable> + xmlWriter().writeEndElement(); // </cxxVariableDetail> + + // not included: <related-links> + + xmlWriter().writeEndElement(); // </cxxVariable> } ++m; } } +/*! + This function outputs the nodes resulting from \variable commands. + */ void DitaXmlGenerator::writeDataMembers(const Section& s, - const ClassNode* cn, CodeMarker* marker) { NodeList::ConstIterator m = s.members.begin(); while (m != s.members.end()) { if ((*m)->type() == Node::Variable) { const VariableNode* vn = static_cast<const VariableNode*>(*m); - writer.writeStartElement(CXXVARIABLE); - writer.writeAttribute("id",vn->guid()); - writer.writeStartElement(APINAME); - writer.writeCharacters(vn->name()); - writer.writeEndElement(); // </apiName> + xmlWriter().writeStartElement(CXXVARIABLE); + xmlWriter().writeAttribute("id",vn->guid()); + xmlWriter().writeStartElement(APINAME); + xmlWriter().writeCharacters(vn->name()); + xmlWriter().writeEndElement(); // </apiName> generateBrief(vn,marker); - writer.writeStartElement(CXXVARIABLEDETAIL); - writer.writeStartElement(CXXVARIABLEDEFINITION); - writer.writeStartElement(CXXVARIABLEACCESSSPECIFIER); - writer.writeAttribute("value",vn->accessString()); - writer.writeEndElement(); // <cxxVariableAccessSpecifier> + + // not included: <prolog> + + xmlWriter().writeStartElement(CXXVARIABLEDETAIL); + xmlWriter().writeStartElement(CXXVARIABLEDEFINITION); + xmlWriter().writeStartElement(CXXVARIABLEACCESSSPECIFIER); + xmlWriter().writeAttribute("value",vn->accessString()); + xmlWriter().writeEndElement(); // <cxxVariableAccessSpecifier> + + // not included: <cxxVAriableStorageClassSpecifierExtern> if (vn->isStatic()) { - writer.writeStartElement(CXXVARIABLESTORAGECLASSSPECIFIERSTATIC); - writer.writeAttribute("name","static"); - writer.writeAttribute("value","static"); - writer.writeEndElement(); // <cxxVariableStorageClassSpecifierStatic> + xmlWriter().writeStartElement(CXXVARIABLESTORAGECLASSSPECIFIERSTATIC); + xmlWriter().writeAttribute("name","static"); + xmlWriter().writeAttribute("value","static"); + xmlWriter().writeEndElement(); // <cxxVariableStorageClassSpecifierStatic> } - writer.writeStartElement(CXXVARIABLEDECLAREDTYPE); - writer.writeCharacters(vn->leftType()); + // not included: <cxxVAriableStorageClassSpecifierMutable>, + // <cxxVariableConst>, <cxxVariableVolatile> + + xmlWriter().writeStartElement(CXXVARIABLEDECLAREDTYPE); + xmlWriter().writeCharacters(vn->leftType()); if (!vn->rightType().isEmpty()) - writer.writeCharacters(vn->rightType()); - writer.writeEndElement(); // <cxxVariableDeclaredType> + xmlWriter().writeCharacters(vn->rightType()); + xmlWriter().writeEndElement(); // <cxxVariableDeclaredType> QString fq = fullQualification(vn); if (!fq.isEmpty()) { - writer.writeStartElement(CXXVARIABLESCOPEDNAME); - writer.writeCharacters(fq); - writer.writeEndElement(); // <cxxVariableScopedName> + xmlWriter().writeStartElement(CXXVARIABLESCOPEDNAME); + xmlWriter().writeCharacters(fq); + xmlWriter().writeEndElement(); // <cxxVariableScopedName> } - writer.writeStartElement(CXXVARIABLEPROTOTYPE); - writer.writeCharacters(vn->leftType() + " "); - //writer.writeCharacters(vn->parent()->name() + "::" + vn->name()); - writer.writeCharacters(vn->name()); + xmlWriter().writeStartElement(CXXVARIABLEPROTOTYPE); + xmlWriter().writeCharacters(vn->leftType() + " "); + //xmlWriter().writeCharacters(vn->parent()->name() + "::" + vn->name()); + xmlWriter().writeCharacters(vn->name()); if (!vn->rightType().isEmpty()) - writer.writeCharacters(vn->rightType()); - writer.writeEndElement(); // <cxxVariablePrototype> + xmlWriter().writeCharacters(vn->rightType()); + xmlWriter().writeEndElement(); // <cxxVariablePrototype> + + xmlWriter().writeStartElement(CXXVARIABLENAMELOOKUP); + xmlWriter().writeCharacters(vn->parent()->name() + "::" + vn->name()); + xmlWriter().writeEndElement(); // <cxxVariableNameLookup> - writer.writeStartElement(CXXVARIABLENAMELOOKUP); - writer.writeCharacters(vn->parent()->name() + "::" + vn->name()); - writer.writeEndElement(); // <cxxVariableNameLookup> + // not included: <cxxVariableReimplemented> writeLocation(vn); - writer.writeEndElement(); // <cxxVariableDefinition> - writer.writeStartElement(APIDESC); + xmlWriter().writeEndElement(); // <cxxVariableDefinition> - if (!vn->doc().isEmpty()) { - generateBody(vn, marker); - } + writeDetailedDescription(vn, marker, true, QString()); + + // not included: <example> or <apiImpl> + + xmlWriter().writeEndElement(); // </cxxVariableDetail> + + // not included: <related-links> - writer.writeEndElement(); // </apiDesc> - writer.writeEndElement(); // </cxxVariableDetail> - writer.writeEndElement(); // </cxxVariable> + xmlWriter().writeEndElement(); // </cxxVariable> } ++m; } } +/*! + This function writes a \macro as a <cxxDefine>. + */ void DitaXmlGenerator::writeMacros(const Section& s, - const ClassNode* cn, CodeMarker* marker) { NodeList::ConstIterator m = s.members.begin(); @@ -5072,92 +5257,231 @@ void DitaXmlGenerator::writeMacros(const Section& s, if ((*m)->type() == Node::Function) { const FunctionNode* fn = static_cast<const FunctionNode*>(*m); if (fn->isMacro()) { - writer.writeStartElement(CXXDEFINE); - writer.writeAttribute("id",fn->guid()); - writer.writeStartElement(APINAME); - writer.writeCharacters(fn->name()); - writer.writeEndElement(); // </apiName> + xmlWriter().writeStartElement(CXXDEFINE); + xmlWriter().writeAttribute("id",fn->guid()); + xmlWriter().writeStartElement(APINAME); + xmlWriter().writeCharacters(fn->name()); + xmlWriter().writeEndElement(); // </apiName> generateBrief(fn,marker); - writer.writeStartElement(CXXDEFINEDETAIL); - writer.writeStartElement(CXXDEFINEDEFINITION); - writer.writeStartElement(CXXDEFINEACCESSSPECIFIER); - writer.writeAttribute("value",fn->accessString()); - writer.writeEndElement(); // <cxxDefineAccessSpecifier> + + // not included: <prolog> + + xmlWriter().writeStartElement(CXXDEFINEDETAIL); + xmlWriter().writeStartElement(CXXDEFINEDEFINITION); + xmlWriter().writeStartElement(CXXDEFINEACCESSSPECIFIER); + xmlWriter().writeAttribute("value",fn->accessString()); + xmlWriter().writeEndElement(); // <cxxDefineAccessSpecifier> - writer.writeStartElement(CXXDEFINEPROTOTYPE); - writer.writeCharacters("#define "); - writer.writeCharacters(fn->name()); + xmlWriter().writeStartElement(CXXDEFINEPROTOTYPE); + xmlWriter().writeCharacters("#define "); + xmlWriter().writeCharacters(fn->name()); if (fn->metaness() == FunctionNode::MacroWithParams) { QStringList params = fn->parameterNames(); if (!params.isEmpty()) { - writer.writeCharacters("("); + xmlWriter().writeCharacters("("); for (int i = 0; i < params.size(); ++i) { if (params[i].isEmpty()) - writer.writeCharacters("..."); + xmlWriter().writeCharacters("..."); else - writer.writeCharacters(params[i]); + xmlWriter().writeCharacters(params[i]); if ((i+1) < params.size()) - writer.writeCharacters(", "); + xmlWriter().writeCharacters(", "); } - writer.writeCharacters(")"); + xmlWriter().writeCharacters(")"); } } - writer.writeEndElement(); // <cxxDefinePrototype> + xmlWriter().writeEndElement(); // <cxxDefinePrototype> - writer.writeStartElement(CXXDEFINENAMELOOKUP); - writer.writeCharacters(fn->name()); - writer.writeEndElement(); // <cxxDefineNameLookup> + xmlWriter().writeStartElement(CXXDEFINENAMELOOKUP); + xmlWriter().writeCharacters(fn->name()); + xmlWriter().writeEndElement(); // <cxxDefineNameLookup> if (fn->reimplementedFrom() != 0) { FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom(); - writer.writeStartElement(CXXDEFINEREIMPLEMENTED); - writer.writeAttribute("href",rfn->ditaXmlHref()); - writer.writeCharacters(marker->plainFullName(rfn)); - writer.writeEndElement(); // </cxxDefineReimplemented> + xmlWriter().writeStartElement(CXXDEFINEREIMPLEMENTED); + xmlWriter().writeAttribute("href",rfn->ditaXmlHref()); + xmlWriter().writeCharacters(marker->plainFullName(rfn)); + xmlWriter().writeEndElement(); // </cxxDefineReimplemented> } if (fn->metaness() == FunctionNode::MacroWithParams) { QStringList params = fn->parameterNames(); if (!params.isEmpty()) { - writer.writeStartElement(CXXDEFINEPARAMETERS); + xmlWriter().writeStartElement(CXXDEFINEPARAMETERS); for (int i = 0; i < params.size(); ++i) { - writer.writeStartElement(CXXDEFINEPARAMETER); - writer.writeStartElement(CXXDEFINEPARAMETERDECLARATIONNAME); - writer.writeCharacters(params[i]); - writer.writeEndElement(); // <cxxDefineParameterDeclarationName> - writer.writeEndElement(); // <cxxDefineParameter> + xmlWriter().writeStartElement(CXXDEFINEPARAMETER); + xmlWriter().writeStartElement(CXXDEFINEPARAMETERDECLARATIONNAME); + xmlWriter().writeCharacters(params[i]); + xmlWriter().writeEndElement(); // <cxxDefineParameterDeclarationName> + + // not included: <apiDefNote> + + xmlWriter().writeEndElement(); // <cxxDefineParameter> } - writer.writeEndElement(); // <cxxDefineParameters> + xmlWriter().writeEndElement(); // <cxxDefineParameters> } } writeLocation(fn); - writer.writeEndElement(); // <cxxDefineDefinition> - writer.writeStartElement(APIDESC); + xmlWriter().writeEndElement(); // <cxxDefineDefinition> - if (!fn->doc().isEmpty()) { - generateBody(fn, marker); - } + writeDetailedDescription(fn, marker, true, QString()); - writer.writeEndElement(); // </apiDesc> - writer.writeEndElement(); // </cxxDefineDetail> - writer.writeEndElement(); // </cxxDefine> + // not included: <example> or <apiImpl> + + xmlWriter().writeEndElement(); // </cxxDefineDetail> + + // not included: <related-links> + + xmlWriter().writeEndElement(); // </cxxDefine> } } ++m; } } -void DitaXmlGenerator::writePropParams(const QString& tag, const NodeList& nlist) +/*! + This function writes one parameter of a Q_PROPERTY macro. + The property is identified by \a tag ("READ" "WRIE" etc), + and it is found in the 'a nlist. + */ +void DitaXmlGenerator::writePropertyParameter(const QString& tag, const NodeList& nlist) { NodeList::const_iterator n = nlist.begin(); while (n != nlist.end()) { - writer.writeCharacters(" "); - writer.writeCharacters(tag); - writer.writeCharacters(" "); - writer.writeCharacters((*n)->name()); + xmlWriter().writeCharacters(" "); + xmlWriter().writeCharacters(tag); + xmlWriter().writeCharacters(" "); + xmlWriter().writeCharacters((*n)->name()); ++n; } } +/*! + Calls beginSubPage() in the base class to open the file. + Then creates a new XML stream writer using the IO device + from opened file and pushes the XML writer onto a stackj. + Creates the file named \a fileName in the output directory. + Attaches a QTextStream to the created file, which is written + to all over the place using out(). Finally, it sets some + parameters in the XML writer and calls writeStartDocument(). + */ +void DitaXmlGenerator::beginSubPage(const Location& location, + const QString& fileName) +{ + PageGenerator::beginSubPage(location,fileName); + QXmlStreamWriter* writer = new QXmlStreamWriter(out().device()); + xmlWriterStack.push(writer); + writer->setAutoFormatting(true); + writer->setAutoFormattingIndent(4); + writer->writeStartDocument(); +} + +/*! + Calls writeEndDocument() and then pops the XML stream writer + off the stack and deletes it. Then it calls endSubPage() in + the base class to close the device. + */ +void DitaXmlGenerator::endSubPage() +{ + xmlWriter().writeEndDocument(); + delete xmlWriterStack.pop(); + PageGenerator::endSubPage(); +} + +/*! + Returns a reference to the XML stream writer currently in use. + There is one XML stream writer open for each XML file being + written, and they are kept on a stack. The one on top of the + stack is the one being written to at the moment. + */ +QXmlStreamWriter& DitaXmlGenerator::xmlWriter() +{ + return *xmlWriterStack.top(); +} + +/*! + Writes the \e {Detailed Description} section(s) for \a node to the + current XML stream using the code \a marker. if the \a apiDesc flag + is true, then the first section of the sequence of sections written + will be an \c {apiDesc>} element with a \e {spectitle} attribute of + \e {Detailed Description}. Otherwise, the first section will be a + \c {<section>} element with a \c {<title>} element of \e {Detailed + Description}. This function calls the Generator::generateBody() + function to write the XML for the section list. + */ +void DitaXmlGenerator::writeDetailedDescription(const Node* node, + CodeMarker* marker, + bool apiDesc, + const QString& title) +{ + if (!node->doc().isEmpty()) { + inDetailedDescription = true; + if (apiDesc) { + inApiDesc = true; + xmlWriter().writeStartElement(APIDESC); + if (!title.isEmpty()) { + writeGuidAttribute(title); + xmlWriter().writeAttribute("spectitle",title); + } + else + writeGuidAttribute("Detailed Description"); + xmlWriter().writeAttribute("outputclass","details"); + } + else { + inSection = true; + xmlWriter().writeStartElement("section"); + if (!title.isEmpty()) { + writeGuidAttribute(title); + xmlWriter().writeAttribute("outputclass","details"); + xmlWriter().writeStartElement("title"); + xmlWriter().writeAttribute("outputclass","h2"); + xmlWriter().writeCharacters(title); + xmlWriter().writeEndElement(); // </title> + } + else { + writeGuidAttribute("Detailed Description"); + xmlWriter().writeAttribute("outputclass","details"); + } + } + generateBody(node, marker); + if (inApiDesc) { + xmlWriter().writeEndElement(); // </apiDesc> + inApiDesc = false; + } + else if (inSection) { + xmlWriter().writeEndElement(); // </section> + inSection = false; + } + } + inDetailedDescription = false; +} + +/*! + Write the nested class elements. + */ +void DitaXmlGenerator::writeNestedClasses(const Section& s, + const Node* n) +{ + if (s.members.isEmpty()) + return; + xmlWriter().writeStartElement("cxxClassNested"); + xmlWriter().writeStartElement("cxxClassNestedDetail"); + + NodeList::ConstIterator m = s.members.begin(); + while (m != s.members.end()) { + if ((*m)->type() == Node::Class) { + xmlWriter().writeStartElement("cxxClassNestedClass"); + QString link = linkForNode((*m), n); + xmlWriter().writeAttribute("href", link); + QString name = n->name() + "::" + (*m)->name(); + xmlWriter().writeCharacters(name); + xmlWriter().writeEndElement(); // <cxxClassNestedClass> + } + ++m; + } + xmlWriter().writeEndElement(); // <cxxClassNestedDetail> + xmlWriter().writeEndElement(); // <cxxClassNested> +} + QT_END_NAMESPACE diff --git a/tools/qdoc3/ditaxmlgenerator.h b/tools/qdoc3/ditaxmlgenerator.h index 446f735..c0cb0db 100644 --- a/tools/qdoc3/ditaxmlgenerator.h +++ b/tools/qdoc3/ditaxmlgenerator.h @@ -39,10 +39,6 @@ ** ****************************************************************************/ -/* - ditaxmlgenerator.h -*/ - #ifndef DITAXMLGENERATOR_H #define DITAXMLGENERATOR_H @@ -61,7 +57,8 @@ typedef QMap<Node*, NodeMultiMap> ParentMaps; typedef QMap<QString, const Node*> NodeMap; typedef QMap<QString, NodeMap> NewClassMaps; -class HelpProjectWriter; +typedef QMap<QString, QString> GuidMap; +typedef QMap<QString, GuidMap*> GuidMaps; class DitaXmlGenerator : public PageGenerator { @@ -91,110 +88,105 @@ class DitaXmlGenerator : public PageGenerator virtual void initializeGenerator(const Config& config); virtual void terminateGenerator(); virtual QString format(); - virtual void generateTree(const Tree *tree, CodeMarker *marker); + virtual void generateTree(const Tree* tree, CodeMarker* marker); - QString protectEnc(const QString &string); - static QString protect(const QString &string, const QString &encoding = "ISO-8859-1"); + QString protectEnc(const QString& string); + static QString protect(const QString& string, const QString& encoding = "ISO-8859-1"); static QString cleanRef(const QString& ref); static QString sinceTitle(int i) { return sinceTitles[i]; } protected: - virtual void startText(const Node *relative, CodeMarker *marker); - virtual int generateAtom(const Atom *atom, - const Node *relative, - CodeMarker *marker); - virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); - virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); - virtual QString fileExtension(const Node *node) const; - virtual QString refForNode(const Node *node); - virtual QString linkForNode(const Node *node, const Node *relative); - virtual QString refForAtom(Atom *atom, const Node *node); + virtual void startText(const Node* relative, CodeMarker* marker); + virtual int generateAtom(const Atom* atom, + const Node* relative, + CodeMarker* marker); + virtual void generateClassLikeNode(const InnerNode* inner, CodeMarker* marker); + virtual void generateFakeNode(const FakeNode* fake, CodeMarker* marker); + virtual QString fileExtension(const Node* node) const; + virtual QString refForNode(const Node* node); + virtual QString guidForNode(const Node* node); + virtual QString linkForNode(const Node* node, const Node* relative); + virtual QString refForAtom(Atom* atom, const Node* node); + void writeTargetAndHeader(const QString& target, + const QString& header, + const QString& attribute); + void writeXrefListItem(const QString& link, const QString& text); QString fullQualification(const Node* n); void writeDerivations(const ClassNode* cn, CodeMarker* marker); void writeLocation(const Node* n); void writeFunctions(const Section& s, - const ClassNode* cn, + const Node* n, CodeMarker* marker); - void writeParameters(const FunctionNode* fn, CodeMarker* marker); - void writeEnumerations(const Section& s, - const ClassNode* cn, - CodeMarker* marker); - void writeTypedefs(const Section& s, - const ClassNode* cn, - CodeMarker* marker); - void writeDataMembers(const Section& s, - const ClassNode* cn, - CodeMarker* marker); - void writeProperties(const Section& s, - const ClassNode* cn, - CodeMarker* marker); - void writeMacros(const Section& s, - const ClassNode* cn, - CodeMarker* marker); - void writePropParams(const QString& tag, const NodeList& nlist); + void writeNestedClasses(const Section& s, const Node* n); + void writeParameters(const FunctionNode* fn); + void writeEnumerations(const Section& s, CodeMarker* marker); + void writeTypedefs(const Section& s, CodeMarker* marker); + void writeDataMembers(const Section& s, CodeMarker* marker); + void writeProperties(const Section& s, CodeMarker* marker); + void writeMacros(const Section& s, CodeMarker* marker); + void writePropertyParameter(const QString& tag, const NodeList& nlist); private: enum SubTitleSize { SmallSubTitle, LargeSubTitle }; - const QPair<QString,QString> anchorForNode(const Node *node); - const Node *findNodeForTarget(const QString &target, - const Node *relative, - CodeMarker *marker, - const Atom *atom = 0); + const QPair<QString,QString> anchorForNode(const Node* node); + const Node* findNodeForTarget(const QString& target, + const Node* relative, + CodeMarker* marker, + const Atom* atom = 0); void generateBreadCrumbs(const QString& title, - const Node *node, - CodeMarker *marker); - void generateHeader(const Node* node); + const Node* node, + CodeMarker* marker); + void generateHeader(const Node* node, + const QString& name, + bool subpage = false); void generateTitle(const QString& title, - const Text &subTitle, + const Text& subTitle, SubTitleSize subTitleSize, - const Node *relative, - CodeMarker *marker); + const Node* relative, + CodeMarker* marker); void generateBrief(const Node* node, CodeMarker* marker); - void generateIncludes(const InnerNode *inner, CodeMarker *marker); - void generateTableOfContents(const Node *node, - CodeMarker *marker, + void generateIncludes(const InnerNode* inner, CodeMarker* marker); + void generateTableOfContents(const Node* node, + CodeMarker* marker, Doc::SectioningUnit sectioningUnit, int numColumns, - const Node *relative = 0); - void generateTableOfContents(const Node *node, - CodeMarker *marker, + const Node* relative = 0); + void generateTableOfContents(const Node* node, + CodeMarker* marker, QList<Section>* sections = 0); - QString generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker); - QString generateLowStatusMemberFile(const InnerNode *inner, - CodeMarker *marker, + QString generateListOfAllMemberFile(const InnerNode* inner, CodeMarker* marker); + QString generateLowStatusMemberFile(const InnerNode* inner, + CodeMarker* marker, CodeMarker::Status status); - void generateClassHierarchy(const Node *relative, - CodeMarker *marker, - const NodeMap &classMap); - void generateAnnotatedList(const Node *relative, - CodeMarker *marker, - const NodeMap &nodeMap); - void generateCompactList(const Node *relative, - CodeMarker *marker, - const NodeMap &classMap, + void generateClassHierarchy(const Node* relative, + CodeMarker* marker, + const NodeMap& classMap); + void generateAnnotatedList(const Node* relative, + CodeMarker* marker, + const NodeMap& nodeMap); + void generateCompactList(const Node* relative, + CodeMarker* marker, + const NodeMap& classMap, bool includeAlphabet, QString commonPrefix = QString()); - void generateFunctionIndex(const Node *relative, CodeMarker *marker); - void generateLegaleseList(const Node *relative, CodeMarker *marker); - void generateOverviewList(const Node *relative, CodeMarker *marker); - void generateSectionList(const Section& section, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style); + void generateFunctionIndex(const Node* relative, CodeMarker* marker); + void generateLegaleseList(const Node* relative, CodeMarker* marker); + void generateOverviewList(const Node* relative, CodeMarker* marker); + #ifdef QDOC_QML void generateQmlSummary(const Section& section, - const Node *relative, - CodeMarker *marker); - void generateQmlItem(const Node *node, - const Node *relative, - CodeMarker *marker, + const Node* relative, + CodeMarker* marker); + void generateQmlItem(const Node* node, + const Node* relative, + CodeMarker* marker, bool summary); - void generateDetailedQmlMember(const Node *node, - const InnerNode *relative, - CodeMarker *marker); + void generateDetailedQmlMember(const Node* node, + const InnerNode* relative, + CodeMarker* marker); void generateQmlInherits(const QmlClassNode* cn, CodeMarker* marker); void generateQmlInheritedBy(const QmlClassNode* cn, CodeMarker* marker); void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); @@ -202,84 +194,82 @@ class DitaXmlGenerator : public PageGenerator #endif void generateSection(const NodeList& nl, - const Node *relative, - CodeMarker *marker, + const Node* relative, + CodeMarker* marker, CodeMarker::SynopsisStyle style); - void generateSynopsis(const Node *node, - const Node *relative, - CodeMarker *marker, - CodeMarker::SynopsisStyle style, - bool nameAlignment = false); + QString getMarkedUpSynopsis(const Node* node, + const Node* relative, + CodeMarker* marker, + CodeMarker::SynopsisStyle style); void generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker, - bool nameAlignment = false); - QString highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle style = CodeMarker::Accessors, - bool nameAlignment = false); + const Node* relative, + CodeMarker* marker); + void writeText(const QString& markedCode, + CodeMarker* marker, + const Node* relative); - void generateFullName(const Node *apparentNode, - const Node *relative, - CodeMarker *marker, - const Node *actualNode = 0); - void generateDetailedMember(const Node *node, - const InnerNode *relative, - CodeMarker *marker); - void generateLink(const Atom *atom, - const Node *relative, - CodeMarker *marker); - void generateStatus(const Node *node, CodeMarker *marker); + void generateFullName(const Node* apparentNode, + const Node* relative, + CodeMarker* marker, + const Node* actualNode = 0); + void generateDetailedMember(Node* node, + const InnerNode* relative, + CodeMarker* marker); + void generateLink(const Atom* atom, + const Node* relative, + CodeMarker* marker); + void generateStatus(const Node* node, CodeMarker* marker); QString registerRef(const QString& ref); - QString fileBase(const Node *node); -#if 0 - QString fileBase(const Node *node, const SectionIterator& section); -#endif - QString fileName(const Node *node); - void findAllClasses(const InnerNode *node); - void findAllFunctions(const InnerNode *node); - void findAllLegaleseTexts(const InnerNode *node); - void findAllNamespaces(const InnerNode *node); - void findAllSince(const InnerNode *node); - static int hOffset(const Node *node); - static bool isThreeColumnEnumValueTable(const Atom *atom); - virtual QString getLink(const Atom *atom, - const Node *relative, - CodeMarker *marker, + QString fileBase(const Node* node) const; + QString fileName(const Node* node); + void findAllClasses(const InnerNode* node); + void findAllFunctions(const InnerNode* node); + void findAllLegaleseTexts(const InnerNode* node); + void findAllNamespaces(const InnerNode* node); + void findAllSince(const InnerNode* node); + static int hOffset(const Node* node); + static bool isThreeColumnEnumValueTable(const Atom* atom); + virtual QString getLink(const Atom* atom, + const Node* relative, + CodeMarker* marker, const Node** node); - virtual void generateIndex(const QString &fileBase, - const QString &url, - const QString &title); + virtual void generateIndex(const QString& fileBase, + const QString& url, + const QString& title); #ifdef GENERATE_MAC_REFS - void generateMacRef(const Node *node, CodeMarker *marker); + void generateMacRef(const Node* node, CodeMarker* marker); #endif - void beginLink(const QString &link, - const Node *node, - const Node *relative, - CodeMarker *marker); + void beginLink(const QString& link, + const Node* node, + const Node* relative, + CodeMarker* marker); void endLink(); - bool generatePageElement(QXmlStreamWriter& writer, - const Node* node, - CodeMarker* marker) const; - void generatePageElements(QXmlStreamWriter& writer, - const Node* node, - CodeMarker* marker) const; - void generatePageIndex(const QString& fileName, - CodeMarker* marker) const; QString writeGuidAttribute(QString text); + void writeGuidAttribute(Node* node); QString lookupGuid(QString text); + QString lookupGuid(const QString& fileName, const QString& text); + GuidMap* lookupGuidMap(const QString& fileName); + virtual void beginSubPage(const Location& location, const QString& fileName); + virtual void endSubPage(); + QXmlStreamWriter& xmlWriter(); + void writeDetailedDescription(const Node* node, + CodeMarker* marker, + bool apiDesc, + const QString& title); + void addLink(const QString& href, const QStringRef& text); private: QMap<QString, QString> refMap; QMap<QString, QString> name2guidMap; + GuidMaps guidMaps; int codeIndent; bool inLink; bool inObsoleteLink; bool inContents; bool inSectionHeading; bool inTableHeader; + bool inTableBody; int numTableRows; bool threeColumnEnumValueTable; bool offlineDocs; @@ -298,10 +288,11 @@ class DitaXmlGenerator : public PageGenerator QString navigationLinks; QStringList stylesheets; QStringList customHeadElements; - const Tree *myTree; + const Tree* myTree; bool slow; bool obsoleteLinks; - int noLinks; + bool noLinks; + int tableColumnCount; QMap<QString, NodeMap > moduleClassMap; QMap<QString, NodeMap > moduleNamespaceMap; NodeMap nonCompatClasses; @@ -314,13 +305,17 @@ class DitaXmlGenerator : public PageGenerator NodeMap qmlClasses; #endif QMap<QString, NodeMap > funcIndex; - QMap<Text, const Node *> legaleseTexts; + QMap<Text, const Node*> legaleseTexts; NewSinceMaps newSinceMaps; static QString sinceTitles[]; NewClassMaps newClassMaps; NewClassMaps newQmlClassMaps; static int id; - QXmlStreamWriter writer; + static bool inApiDesc; + static bool inSection; + static bool inDetailedDescription; + + QStack<QXmlStreamWriter*> xmlWriterStack; }; #define DITAXMLGENERATOR_ADDRESS "address" diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp index f1eaddc..165bd5e 100644 --- a/tools/qdoc3/generator.cpp +++ b/tools/qdoc3/generator.cpp @@ -54,6 +54,7 @@ #include "quoter.h" #include "separator.h" #include "tokenizer.h" +#include "ditaxmlgenerator.h" QT_BEGIN_NAMESPACE @@ -326,6 +327,7 @@ bool Generator::generateText(const Text& text, const Node *relative, CodeMarker *marker) { + bool result = false; if (text.firstAtom() != 0) { int numAtoms = 0; startText(relative, marker); @@ -335,9 +337,9 @@ bool Generator::generateText(const Text& text, true, numAtoms); endText(relative, marker); - return true; + result = true; } - return false; + return result; } #ifdef QDOC_QML @@ -351,24 +353,26 @@ bool Generator::generateQmlText(const Text& text, const QString& /* qmlName */ ) { const Atom* atom = text.firstAtom(); - if (atom == 0) - return false; + bool result = false; - startText(relative, marker); - while (atom) { - if (atom->type() != Atom::QmlText) - atom = atom->next(); - else { - atom = atom->next(); - while (atom && (atom->type() != Atom::EndQmlText)) { - int n = 1 + generateAtom(atom, relative, marker); - while (n-- > 0) - atom = atom->next(); + if (atom != 0) { + startText(relative, marker); + while (atom) { + if (atom->type() != Atom::QmlText) + atom = atom->next(); + else { + atom = atom->next(); + while (atom && (atom->type() != Atom::EndQmlText)) { + int n = 1 + generateAtom(atom, relative, marker); + while (n-- > 0) + atom = atom->next(); + } } } + endText(relative, marker); + result = true; } - endText(relative, marker); - return true; + return result; } #endif @@ -376,25 +380,21 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) { bool quiet = false; - if (node->type() == Node::Function) { -#if 0 - const FunctionNode *func = (const FunctionNode *) node; - if (func->isOverload() && func->metaness() != FunctionNode::Ctor) - generateOverload(node, marker); -#endif - } - else if (node->type() == Node::Fake) { + if (node->type() == Node::Fake) { const FakeNode *fake = static_cast<const FakeNode *>(node); - if (fake->subType() == Node::Example) + if (fake->subType() == Node::Example) { generateExampleFiles(fake, marker); - else if ((fake->subType() == Node::File) || (fake->subType() == Node::Image)) + } + else if ((fake->subType() == Node::File) || (fake->subType() == Node::Image)) { quiet = true; + } } if (node->doc().isEmpty()) { - if (!quiet && !node->isReimp()) // ### might be unnecessary + if (!quiet && !node->isReimp()) { // ### might be unnecessary node->location().warning(tr("No documentation for '%1'") .arg(marker->plainFullName(node))); + } } else { if (node->type() == Node::Function) { @@ -403,9 +403,10 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) generateReimplementedFrom(func, marker); } - if (!generateText(node->doc().body(), node, marker)) + if (!generateText(node->doc().body(), node, marker)) { if (node->isReimp()) return; + } if (node->type() == Node::Enum) { const EnumNode *enume = (const EnumNode *) node; @@ -496,18 +497,16 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) ++a; } } -/* Something like this return value check should be implemented at some point. */ + /* + Something like this return value check should + be implemented at some point. + */ if (func->status() > Node::Obsolete && func->returnType() == "bool" && func->reimplementedFrom() == 0 && !func->isOverload()) { QString body = func->doc().body().toString(); if (!body.contains("return", Qt::CaseInsensitive)) node->doc().location().warning(tr("Undocumented return value")); } -#if 0 - // Now we put this at the top, before the other text. - if (func->reimplementedFrom() != 0) - generateReimplementedFrom(func, marker); -#endif } } @@ -855,7 +854,11 @@ QMap<QString, QString>& Generator::formattingRightMap() return fmtRightMaps[format()]; } -QString Generator::trimmedTrailing(const QString &string) +/* + Trims trailimng whitespace off the \a string and returns + the trimmed string. + */ +QString Generator::trimmedTrailing(const QString& string) { QString trimmed = string; while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace()) @@ -1085,20 +1088,6 @@ void Generator::generateSince(const Node *node, CodeMarker *marker) } } -/*! - No longer in use. - */ -void Generator::generateOverload(const Node *node, CodeMarker *marker) -{ - Text text; - text << Atom::ParaLeft - << "This function overloads "; - QString t = node->name() + "()"; - text << Atom::AutoLink << t - << Atom::ParaRight; - generateText(text, node, marker); -} - void Generator::generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker) { @@ -1147,8 +1136,8 @@ const Atom *Generator::generateAtomList(const Atom *atom, if (atom->type() == Atom::FormatEndif) { if (generate && numAtoms0 == numAtoms) { - relative->location().warning(tr("Output format %1 not handled") - .arg(format())); + relative->location().warning(tr("Output format %1 not handled %2") + .arg(format()).arg(outFileName())); Atom unhandledFormatAtom(Atom::UnhandledFormat, format()); generateAtomList(&unhandledFormatAtom, relative, diff --git a/tools/qdoc3/generator.h b/tools/qdoc3/generator.h index 326a247..bccfc5d 100644 --- a/tools/qdoc3/generator.h +++ b/tools/qdoc3/generator.h @@ -130,6 +130,8 @@ class Generator const Node *relative, CodeMarker *marker) const; + virtual QString outFileName() { return QString(); } + const QString& outputDir() { return outDir; } QString indent(int level, const QString& markedCode); QString plainCode(const QString& markedCode); @@ -148,7 +150,6 @@ class Generator static void supplementAlsoList(const Node *node, QList<Text> &alsoList); private: - void generateOverload(const Node *node, CodeMarker *marker); void generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker); void appendFullName(Text& text, diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index c804d09..726196f 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -3415,7 +3415,7 @@ QString HtmlGenerator::protect(const QString &string, const QString &outputEncod #undef APPEND } -QString HtmlGenerator::fileBase(const Node *node) +QString HtmlGenerator::fileBase(const Node *node) const { QString result; @@ -3438,7 +3438,7 @@ QString HtmlGenerator::fileBase(const Node *node) #if 0 QString HtmlGenerator::fileBase(const Node *node, - const SectionIterator& section) + const SectionIterator& section) const { QStringList::ConstIterator s = section.sectionNumber().end(); QStringList::ConstIterator b = section.baseNameStack().end(); diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index d885ada..430aca2 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -241,9 +241,9 @@ class HtmlGenerator : public PageGenerator void generateStatus(const Node *node, CodeMarker *marker); QString registerRef(const QString& ref); - QString fileBase(const Node *node); + QString fileBase(const Node *node) const; #if 0 - QString fileBase(const Node *node, const SectionIterator& section); + QString fileBase(const Node *node, const SectionIterator& section) const; #endif QString fileName(const Node *node); void findAllClasses(const InnerNode *node); diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index 41f90d5..ce53b86 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -1152,8 +1152,8 @@ QString Parameter::reconstruct(bool value) const if (!p.endsWith(QChar('*')) && !p.endsWith(QChar('&')) && !p.endsWith(QChar(' '))) p += " "; p += nam; - if (value) - p += def; + if (value && !def.isEmpty()) + p += " = " + def; return p; } diff --git a/tools/qdoc3/pagegenerator.cpp b/tools/qdoc3/pagegenerator.cpp index a187c2e..f4c471c 100644 --- a/tools/qdoc3/pagegenerator.cpp +++ b/tools/qdoc3/pagegenerator.cpp @@ -257,7 +257,12 @@ QString PageGenerator::fileBase(const Node *node) const return res; } -QString PageGenerator::fileName(const Node *node) const +/*! + If the \a node has a URL, return the URL as the file name. + Otherwise, construct the file name from the fileBase() and + the fileExtension(), and return the constructed name. + */ +QString PageGenerator::fileName(const Node* node) const { if (!node->url().isEmpty()) return node->url(); @@ -268,11 +273,19 @@ QString PageGenerator::fileName(const Node *node) const return name; } +/*! + Return the current output file name. + */ QString PageGenerator::outFileName() { - return QFileInfo(static_cast<QFile *>(out().device())->fileName()).fileName(); + return QFileInfo(static_cast<QFile*>(out().device())->fileName()).fileName(); } +/*! + Creates the file named \a fileName in the output directory. + Attaches a QTextStream to the created file, which is written + to all over the place using out(). + */ void PageGenerator::beginSubPage(const Location& location, const QString& fileName) { @@ -285,6 +298,11 @@ void PageGenerator::beginSubPage(const Location& location, outStreamStack.push(out); } +/*! + Flush the text stream associated with the subpage, and + then pop it off the text stream stack and delete it. + This terminates output of the subpage. + */ void PageGenerator::endSubPage() { outStreamStack.top()->flush(); @@ -292,6 +310,11 @@ void PageGenerator::endSubPage() delete outStreamStack.pop(); } +/*! + Used for writing to the current output stream. Returns a + reference to the crrent output stream, which is then used + with the \c {<<} operator for writing. + */ QTextStream &PageGenerator::out() { return *outStreamStack.top(); diff --git a/tools/qdoc3/pagegenerator.h b/tools/qdoc3/pagegenerator.h index 1aa24a1..0fea67a 100644 --- a/tools/qdoc3/pagegenerator.h +++ b/tools/qdoc3/pagegenerator.h @@ -48,14 +48,12 @@ #include <QStack> #include <qtextstream.h> - #include "generator.h" #include "location.h" QT_BEGIN_NAMESPACE class QTextCodec; - class ClassNode; class InnerNode; class NamespaceNode; @@ -66,16 +64,16 @@ class PageGenerator : public Generator PageGenerator(); ~PageGenerator(); - virtual void generateTree(const Tree *tree, CodeMarker *marker); + virtual void generateTree(const Tree* tree, CodeMarker* marker); protected: - virtual QString fileBase(const Node *node) const; - virtual QString fileExtension(const Node *node) const = 0; - QString fileName(const Node *node) const; + virtual QString fileBase(const Node* node) const; + virtual QString fileExtension(const Node* node) const = 0; + QString fileName(const Node* node) const; QString outFileName(); - void beginSubPage(const Location& location, const QString& fileName); - void endSubPage(); - virtual void generateInnerNode(const InnerNode *node, CodeMarker *marker); + virtual void beginSubPage(const Location& location, const QString& fileName); + virtual void endSubPage(); + virtual void generateInnerNode(const InnerNode* node, CodeMarker* marker); QTextStream& out(); QString naturalLanguage; @@ -89,7 +87,7 @@ class PageGenerator : public Generator QStringRef* par1 = 0, bool debug = false); - private: + protected: QStack<QTextStream*> outStreamStack; }; diff --git a/tools/qdoc3/test/qt-ditaxml.qdocconf b/tools/qdoc3/test/qt-ditaxml.qdocconf index 66f30e3..63baead 100644 --- a/tools/qdoc3/test/qt-ditaxml.qdocconf +++ b/tools/qdoc3/test/qt-ditaxml.qdocconf @@ -9,3 +9,34 @@ outputformats = DITAXML generateindex = true url = . +macro.aacute.DITAXML = "á" +macro.Aring.DITAXML = "Å" +macro.aring.DITAXML = "å" +macro.Auml.DITAXML = "Ä" +macro.author = "\\bold{Author:}" +macro.br.DITAXML = " " +macro.BR.DITAXML = " " +macro.copyright.DITAXML = "©" +macro.eacute.DITAXML = "é" +macro.gui = "\\bold" +macro.hr.DITAXML = "<hr />" +macro.iacute.DITAXML = "í" +macro.key = "\\bold" +macro.menu = "\\bold" +macro.note = "\\bold{Note:}" +macro.oslash.DITAXML = "ø" +macro.ouml.DITAXML = "ö" +macro.QA = "\\e{Qt Assistant}" +macro.QD = "\\e{Qt Designer}" +macro.QL = "\\e{Qt Linguist}" +macro.QQV = "\\e{Qt QML Viewer}" +macro.param = "\\e" +macro.raisedaster.DITAXML = "<sup>*</sup>" +macro.rarrow.DITAXML = "→" +macro.reg.DITAXML = "<sup>®</sup>" +macro.return = "Returns" +macro.starslash = "\\c{*/}" +macro.begincomment = "\\c{/*}" +macro.endcomment = "\\c{*/}" +macro.uuml.DITAXML = "ü" +macro.mdash.DITAXML = "—" diff --git a/tools/qdoc3/text.cpp b/tools/qdoc3/text.cpp index 7093a43..11d7edd 100644 --- a/tools/qdoc3/text.cpp +++ b/tools/qdoc3/text.cpp @@ -144,7 +144,9 @@ QString Text::toString() const QString str; const Atom *atom = firstAtom(); while ( atom != 0 ) { - if ( atom->type() == Atom::String || atom->type() == Atom::AutoLink ) + if ( atom->type() == Atom::String || + atom->type() == Atom::AutoLink || + atom->type() == Atom::GuidLink) str += atom->string(); atom = atom->next(); } |