qdoc: Make links to \target work intermodule

\target sets up a unique target that should be
accessible with \l across module boundaries.
This was not working across module boundaries.
Now it has been fixed, and it is one way of
handling the problem described in the referenced
bug report.

Task-number: QTBUG-28244
Change-Id: I541f409b998f84b2b8dcf66751762cf07f9f108b
Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
bb10
Martin Smith 2012-12-11 14:53:29 +01:00 committed by The Qt Project
parent 0549a4b6f5
commit f03f8431ef
4 changed files with 42 additions and 35 deletions

View File

@ -3502,6 +3502,10 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod
}
if (!*node) {
*node = qdb_->findUnambiguousTarget(first, ref, relative);
if (*node && !(*node)->url().isEmpty() && !ref.isEmpty()) {
QString final = (*node)->url() + "#" + ref;
return final;
}
}
}
if (*node) {

View File

@ -684,14 +684,15 @@ const Node* QDocDatabase::findNodeForTarget(const QString& target, const Node* r
Inserts a new target into the target table with the specified
\a name, \a node, and \a priority.
*/
void QDocDatabase::insertTarget(const QString& name, Node* node, int priority)
void QDocDatabase::insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority)
{
Target target;
TargetRec target;
target.type_ = type;
target.node_ = node;
target.priority_ = priority;
Atom a = Atom(Atom::Target, name);
target.ref_ = refForAtom(&a);
targetMultiMap_.insert(name, target);
targetRecMultiMap_.insert(name, target);
}
/*!
@ -701,16 +702,16 @@ void QDocDatabase::insertTarget(const QString& name, Node* node, int priority)
const Node*
QDocDatabase::findUnambiguousTarget(const QString& target, QString& ref, const Node* relative)
{
Target bestTarget;
TargetRec bestTarget;
int numBestTargets = 0;
QList<Target> bestTargetList;
QList<TargetRec> bestTargetList;
QString key = Doc::canonicalTitle(target);
TargetMultiMap::iterator i = targetMultiMap_.find(key);
while (i != targetMultiMap_.end()) {
TargetRecMultiMap::iterator i = targetRecMultiMap_.find(key);
while (i != targetRecMultiMap_.end()) {
if (i.key() != key)
break;
const Target& candidate = i.value();
const TargetRec& candidate = i.value();
if (candidate.priority_ < bestTarget.priority_) {
bestTarget = candidate;
bestTargetList.clear();
@ -808,14 +809,14 @@ const DocNode* QDocDatabase::findDocNodeByTitle(const QString& title, const Node
QString QDocDatabase::findTarget(const QString& target, const Node* node) const
{
QString key = Doc::canonicalTitle(target);
TargetMultiMap::const_iterator i = targetMultiMap_.constFind(key);
TargetRecMultiMap::const_iterator i = targetRecMultiMap_.constFind(key);
if (i != targetMultiMap_.constEnd()) {
if (i != targetRecMultiMap_.constEnd()) {
do {
if (i.value().node_ == node)
return i.value().ref_;
++i;
} while (i != targetMultiMap_.constEnd() && i.key() == key);
} while (i != targetRecMultiMap_.constEnd() && i.key() == key);
}
return QString();
}
@ -840,7 +841,7 @@ void QDocDatabase::resolveTargets(InnerNode* root)
if (child->doc().hasTableOfContents()) {
const QList<Atom*>& toc = child->doc().tableOfContents();
Target target;
TargetRec target;
target.node_ = child;
target.priority_ = 3;
@ -849,32 +850,32 @@ void QDocDatabase::resolveTargets(InnerNode* root)
QString title = Text::sectionHeading(toc.at(i)).toString();
if (!title.isEmpty()) {
QString key = Doc::canonicalTitle(title);
targetMultiMap_.insert(key, target);
targetRecMultiMap_.insert(key, target);
}
}
}
if (child->doc().hasKeywords()) {
const QList<Atom*>& keywords = child->doc().keywords();
Target target;
TargetRec target;
target.node_ = child;
target.priority_ = 1;
for (int i = 0; i < keywords.size(); ++i) {
target.ref_ = refForAtom(keywords.at(i));
QString key = Doc::canonicalTitle(keywords.at(i)->string());
targetMultiMap_.insert(key, target);
targetRecMultiMap_.insert(key, target);
}
}
if (child->doc().hasTargets()) {
const QList<Atom*>& toc = child->doc().targets();
Target target;
TargetRec target;
target.node_ = child;
target.priority_ = 2;
for (int i = 0; i < toc.size(); ++i) {
target.ref_ = refForAtom(toc.at(i));
QString key = Doc::canonicalTitle(toc.at(i)->string());
targetMultiMap_.insert(key, target);
targetRecMultiMap_.insert(key, target);
}
}
}

View File

@ -65,21 +65,23 @@ enum FindFlag {
NonFunction = 0x4
};
struct TargetRec
{
public:
enum Type { Unknown, Target, Keyword, Contents, Class, Function, Page, Subtitle };
TargetRec() : node_(0), priority_(INT_MAX), type_(Unknown) { }
bool isEmpty() const { return ref_.isEmpty(); }
//void debug(int idx, const QString& key);
Node* node_;
QString ref_;
int priority_;
Type type_;
};
typedef QMultiMap<QString, TargetRec> TargetRecMultiMap;
class QDocDatabase
{
struct Target
{
public:
Target() : node_(0), priority_(INT_MAX) { }
bool isEmpty() const { return ref_.isEmpty(); }
//void debug(int idx, const QString& key);
Node* node_;
QString ref_;
int priority_;
};
typedef QMultiMap<QString, Target> TargetMultiMap;
public:
static QDocDatabase* qdocDB();
static void destroyQdocDB();
@ -127,7 +129,7 @@ class QDocDatabase
const Node* resolveTarget(const QString& target, const Node* relative, const Node* self=0);
const Node* findNodeForTarget(const QString& target, const Node* relative);
void insertTarget(const QString& name, Node* node, int priority);
void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
/* convenience functions
Many of these will be either eliminated or replaced.
@ -226,7 +228,7 @@ class QDocDatabase
NodeMapMap funcIndex_;
TextToNodeMap legaleseTexts_;
DocNodeMultiMap docNodesByTitle_;
TargetMultiMap targetMultiMap_;
TargetRecMultiMap targetRecMultiMap_;
};
QT_END_NAMESPACE

View File

@ -381,15 +381,15 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
location = Location(parent->name().toLower() + ".html");
}
else if (element.nodeName() == "keyword") {
qdb_->insertTarget(name, parent,1);
qdb_->insertTarget(name, TargetRec::Keyword, parent, 1);
return;
}
else if (element.nodeName() == "target") {
qdb_->insertTarget(name, parent,2);
qdb_->insertTarget(name, TargetRec::Target, parent, 2);
return;
}
else if (element.nodeName() == "contents") {
qdb_->insertTarget(name, parent,3);
qdb_->insertTarget(name, TargetRec::Contents, parent, 3);
return;
}
else