summaryrefslogtreecommitdiffstats
path: root/src/tools/qdoc/ditaxmlgenerator.cpp
diff options
context:
space:
mode:
authorMartin Smith <martin.smith@digia.com>2014-06-10 12:08:37 +0200
committerMartin Smith <martin.smith@digia.com>2014-06-26 08:33:53 +0200
commitd8062f117b19e2bb32739892606bdd5856586b1d (patch)
tree323917ff8a9fb1b7c4f23b2a2a791999628f38c1 /src/tools/qdoc/ditaxmlgenerator.cpp
parentb6ba4ac00d1ea86bb1a735391f03fd6ea9e464b1 (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.cpp230
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;