diff options
author | Martin Smith <martin.smith@digia.com> | 2014-06-10 12:08:37 +0200 |
---|---|---|
committer | Martin Smith <martin.smith@digia.com> | 2014-06-26 08:33:53 +0200 |
commit | d8062f117b19e2bb32739892606bdd5856586b1d (patch) | |
tree | 323917ff8a9fb1b7c4f23b2a2a791999628f38c1 /src/tools/qdoc/ditaxmlgenerator.cpp | |
parent | b6ba4ac00d1ea86bb1a735391f03fd6ea9e464b1 (diff) |
qdoc: Give documenter more control of linking
This update enables using the module name as the parameter
in square brackets for the \l command. You will use this
when your link goes to the wrong page. e.g. Suppose this
link command went to a page in QtGui instead of the page
where it is meant to go in QtQuick:
\l { mytarget } { the text for my link }
When a link goes to a page in the wrong module, it means
the target exists in more than one module and because qdoc
searches the modules in sequence and stops when it finds a
match, it might match the wrong target. This would be a
collision in the single tree version of qdoc, but now qdoc
builds a separate tree for each module. Since you know
which module you want your link to go to, put the module
name in square brackets as the first parameter, like this:
\l [QtQuick] { mytarget } { the text for my link }
Now qdoc will only search for mytarget in the tree for
the QtQuick module.
The \target command can now be used anywhere. It has not
been tested in all possible locations, but it works in
the places where people have asked why it doesn't work there.
There will be a further update to complete this task for
implementing the other types of parameters that can be in
the square brackets.
Task-number: QTBUG-39221
Change-Id: I2db4fdd0319ff272ec1d2fa9dc396f14599d80f9
Reviewed-by: Martin Smith <martin.smith@digia.com>
Diffstat (limited to 'src/tools/qdoc/ditaxmlgenerator.cpp')
-rw-r--r-- | src/tools/qdoc/ditaxmlgenerator.cpp | 230 |
1 files changed, 127 insertions, 103 deletions
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp index bbd32204ce..c2a5cdb8b8 100644 --- a/src/tools/qdoc/ditaxmlgenerator.cpp +++ b/src/tools/qdoc/ditaxmlgenerator.cpp @@ -765,7 +765,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, case Atom::AutoLink: if (!noLinks && !inLink_ && !inContents_ && !inSectionHeading_) { const Node* node = 0; - QString link = getLink(atom, relative, &node); + QString link = getAutoLink(atom, relative, &node); if (!link.isEmpty()) { beginLink(link); generateLink(atom, marker); @@ -1308,13 +1308,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, case Atom::Link: { const Node *node = 0; - QString myLink = getLink(atom, relative, &node); - //if (myLink.isEmpty()) - //myLink = getCollisionLink(atom); - if (myLink.isEmpty() && !noLinkErrors()) + QString link = getLink(atom, relative, &node); + if (link.isEmpty() && !noLinkErrors()) relative->doc().location().warning(tr("Can't link to '%1'").arg(atom->string())); else if (!inSectionHeading_) - beginLink(myLink); + beginLink(link); skipAhead = 1; } break; @@ -3722,6 +3720,129 @@ QString DitaXmlGenerator::fileName(const Node* node) return Generator::fileName(node); } +/*! + This function is called for links, i.e. for words that + are marked with the qdoc link command. For autolinks + that are not marked with the qdoc link command, qdoc + calls getAutoLink(). + + Return the link represented by the \a atom, and set \a node + to point to the target node for that link. \a relative points + to the node holding the qdoc comment where the link command + was found. + */ +QString DitaXmlGenerator::getLink(const Atom *atom, const Node *relative, const Node** node) +{ + if (atom->string().contains(QLatin1Char(':')) && (atom->string().startsWith("file:") || + atom->string().startsWith("http:") || + atom->string().startsWith("https:") || + atom->string().startsWith("ftp:") || + atom->string().startsWith("mailto:"))) { + return atom->string(); // It's some kind of protocol. + } + + QString ref; + QString link; + QStringList path = atom->string().split("#"); + QString first = path.first().trimmed(); + + *node = 0; + if (first.isEmpty()) + *node = relative; // search for a target on the current page. + else { + if (first.endsWith(".html")) { // The target is an html file. + *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document); + } + else if (first.endsWith("()")) { // The target is a C++ function or QML method. + *node = qdb_->resolveFunctionTarget(first, relative); + } + else { + *node = qdb_->resolveTarget(first, relative); + if (!(*node)) + *node = qdb_->findDocNodeByTitle(first); + if (!(*node)) { + *node = qdb_->findUnambiguousTarget(first, ref); + if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) { + QString final = (*node)->url() + "#" + ref; + return final; + } + } + } + } + if (!(*node)) + return link; // empty + + if (!(*node)->url().isEmpty()) + return (*node)->url(); + + if (!path.isEmpty()) { + ref = qdb_->findTarget(path.first(), *node); + if (ref.isEmpty()) + return link; // empty + } + + /* + Given that *node is not null, we now cconstruct a link + to the page that *node represents, and then if we found + a target on that page, we connect the target to the link + with '#'. + */ + link = linkForNode(*node, relative); + if (*node && (*node)->subType() == Node::Image) + link = "images/used-in-examples/" + link; + if (!ref.isEmpty()) + link += QLatin1Char('#') + ref; + return link; +} + +/*! + This function is called for autolinks, i.e. for words that + are not marked with the qdoc link command that qdoc has + reason to believe should be links. For links marked with + the qdoc link command, qdoc calls getLink(). + + Return the link represented by the \a atom, and set \a node + to point to the target node for that link. \a relative points + to the node holding the qdoc comment where the link command + was found. + */ +QString DitaXmlGenerator::getAutoLink(const Atom *atom, const Node *relative, const Node** node) +{ + QString ref; + QString link; + QString target = atom->string().trimmed(); + *node = 0; + + if (target.endsWith("()")) { // The target is a C++ function or QML method. + *node = qdb_->resolveFunctionTarget(target, relative); + } + else { + *node = qdb_->resolveTarget(target, relative); + if (!(*node)) { + *node = qdb_->findDocNodeByTitle(target); + } + if (!(*node)) { + *node = qdb_->findUnambiguousTarget(target, ref); + if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) { + QString final = (*node)->url() + "#" + ref; + return final; + } + } + } + + if (!(*node)) + return link; // empty + + if (!(*node)->url().isEmpty()) + return (*node)->url(); + + link = linkForNode(*node, relative); + if (!ref.isEmpty()) + link += QLatin1Char('#') + ref; + return link; +} + + QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative) { if (node == 0 || node == relative) @@ -3832,103 +3953,6 @@ const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node* node) return anchorPair; } -QString DitaXmlGenerator::getLink(const Atom* atom, const Node* relative, const Node** node) -{ - QString link; - *node = 0; - inObsoleteLink = false; - - if (atom->string().contains(QLatin1Char(':')) && - (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('#')) - path = atom->string().split('#'); - else - path.append(atom->string()); - - QString ref; - QString first = path.first().trimmed(); - - if (first.isEmpty()) - *node = relative; - else if (first.endsWith(".html")) - *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document); - else if (first.endsWith("()")) // The target is a C++ function or QML method. - *node = qdb_->resolveFunctionTarget(first, relative); - else { - *node = qdb_->resolveTarget(first, relative); - if (!(*node)) - *node = qdb_->findDocNodeByTitle(first); - if (!*node) - *node = qdb_->findUnambiguousTarget(first, ref); - } - - if (*node) { - if (!(*node)->url().isEmpty()) - return (*node)->url(); - else - path.removeFirst(); - } - else - *node = relative; - - if (*node && (*node)->status() == Node::Obsolete) { - if (relative && (relative->parent() != *node) && - (relative->status() != Node::Obsolete)) { - bool porting = false; - if (relative->isDocNode()) { - const DocNode* fake = static_cast<const DocNode*>(relative); - if (fake->title().startsWith("Porting")) - porting = true; - } - QString name = relative->plainFullName(); - 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; - } - } - } - - while (!path.isEmpty()) { - ref = qdb_->findTarget(path.first(), *node); - if (ref.isEmpty()) - break; - path.removeFirst(); - } - - if (path.isEmpty()) { - link = linkForNode(*node, relative); - if (*node && (*node)->subType() == Node::Image) - link = "images/used-in-examples/" + link; - if (!ref.isEmpty()) { - if (link.isEmpty()) - link = outFileName(); - QString guid = lookupGuid(link, ref); - link += QLatin1Char('#') + guid; - } - else if (!link.isEmpty() && *node && (link.endsWith(".xml") || link.endsWith(".dita"))) { - link += QLatin1Char('#') + (*node)->guid(); - } - } - } - if (!link.isEmpty() && link[0] == '#') { - link.prepend(outFileName()); - } - return link; -} - void DitaXmlGenerator::generateStatus(const Node* node, CodeMarker* marker) { Text text; |