summaryrefslogtreecommitdiffstats
path: root/src/tools/qdoc/node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/qdoc/node.cpp')
-rw-r--r--src/tools/qdoc/node.cpp1044
1 files changed, 528 insertions, 516 deletions
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index c88ebfc760..b65c531149 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -46,12 +46,44 @@
#include <quuid.h>
#include "qdocdatabase.h"
#include <qdebug.h>
+#include "generator.h"
QT_BEGIN_NAMESPACE
int Node::propertyGroupCount_ = 0;
-ExampleNodeMap ExampleNode::exampleNodeMap;
QStringMap Node::operators_;
+QMap<QString,Node::Type> Node::goals_;
+
+/*!
+ Initialize the map of search goals. This is called once
+ by QDocDatabase::initializeDB(). The map key is a string
+ representing a value in the enum Node::Type. The map value
+ is the enum value.
+
+ There should be an entry in the map for each value in the
+ Type enum.
+ */
+void Node::initialize()
+{
+ goals_.insert("class", Node::Class);
+ goals_.insert("qmltype", Node::QmlType);
+ goals_.insert("page", Node::Document);
+ goals_.insert("function", Node::Function);
+ goals_.insert("property", Node::Property);
+ goals_.insert("variable", Node::Variable);
+ goals_.insert("group", Node::Group);
+ goals_.insert("module", Node::Module);
+ goals_.insert("qmlmodule", Node::QmlModule);
+ goals_.insert("qmppropertygroup", Node::QmlPropertyGroup);
+ goals_.insert("qmlproperty", Node::QmlProperty);
+ goals_.insert("qmlsignal", Node::QmlSignal);
+ goals_.insert("qmlsignalhandler", Node::QmlSignalHandler);
+ goals_.insert("qmlmethod", Node::QmlMethod);
+ goals_.insert("qmlbasictype", Node::QmlBasicType);
+ goals_.insert("enum", Node::Enum);
+ goals_.insert("typedef", Node::Typedef);
+ goals_.insert("namespace", Node::Namespace);
+}
/*!
Increment the number of property groups seen in the current
@@ -112,8 +144,7 @@ QString Node::plainFullName(const Node* relative) const
const Node* node = this;
while (node) {
fullName.prepend(node->plainName());
- if (node->parent() == relative || node->parent()->subType() == Node::Collision ||
- node->parent()->name().isEmpty())
+ if (node->parent() == relative || node->parent()->name().isEmpty())
break;
fullName.prepend(QLatin1String("::"));
node = node->parent();
@@ -122,19 +153,13 @@ QString Node::plainFullName(const Node* relative) const
}
/*!
- Constructs and returns this node's full name. The \a relative
- node is either null or is a collision node.
+ Constructs and returns this node's full name.
*/
QString Node::fullName(const Node* relative) const
{
- if (type() == Node::Document) {
- const DocNode* dn = static_cast<const DocNode*>(this);
- // Only print modulename::type on collision pages.
- if (!dn->qmlModuleName().isEmpty() && relative != 0 && relative->isCollisionNode())
- return dn->qmlModuleName() + "::" + dn->title();
- return dn->title();
- }
- else if (type() == Node::Class) {
+ if (isDocNode())
+ return title();
+ else if (isClass()) {
const ClassNode* cn = static_cast<const ClassNode*>(this);
if (!cn->serviceName().isEmpty())
return cn->serviceName();
@@ -143,6 +168,31 @@ QString Node::fullName(const Node* relative) const
}
/*!
+ Try to match this node's type and subtype with one of the
+ pairs in \a types. If a match is found, return true. If no
+ match is found, return false.
+
+ \a types is a list of type/subtype pairs, where the first
+ value in the pair is a Node::Type, and the second value is
+ a Node::SubType. The second value is used in the match if
+ this node's type is Node::Document.
+ */
+bool Node::match(const NodeTypeList& types) const
+{
+ for (int i=0; i<types.size(); ++i) {
+ if (type() == types.at(i).first) {
+ if (type() == Node::Document) {
+ if (subType() == types.at(i).second)
+ return true;
+ }
+ else
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
Sets this Node's Doc to \a doc. If \a replace is false and
this Node already has a Doc, a warning is reported that the
Doc is being overridden, and it reports where the previous
@@ -170,7 +220,6 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
pageType_(NoPageType),
status_(Commendable),
indexNodeFlag_(false),
- seen_(true),
parent_(parent),
relatesTo_(0),
name_(name)
@@ -224,21 +273,13 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
}
}
-/*!
+/*! \fn QString Node::url() const
Returns the node's URL.
*/
-QString Node::url() const
-{
- return url_;
-}
-/*!
+/*! \fn void Node::setUrl(const QString &url)
Sets the node's URL to \a url
*/
-void Node::setUrl(const QString &url)
-{
- url_ = url;
-}
/*!
Returns this node's page type as a string, for use as an
@@ -309,6 +350,16 @@ QString Node::nodeTypeString(unsigned t)
return "property";
case Variable:
return "variable";
+ case Group:
+ return "group";
+ case Module:
+ return "module";
+ case QmlType:
+ return "QML type";
+ case QmlBasicType:
+ return "QML basic type";
+ case QmlModule:
+ return "QML module";
case QmlProperty:
return "QML property";
case QmlPropertyGroup:
@@ -351,24 +402,12 @@ QString Node::nodeSubtypeString(unsigned t)
return "file";
case Image:
return "image";
- case Group:
- return "group";
- case Module:
- return "module";
case Page:
return "page";
case ExternalPage:
return "external page";
- case QmlClass:
- return "QML type";
- case QmlBasicType:
- return "QML basic type";
- case QmlModule:
- return "QML module";
case DitaMap:
return "ditamap";
- case Collision:
- return "collision";
case NoSubType:
default:
break;
@@ -389,8 +428,8 @@ void Node::setPageType(const QString& t)
pageType_ = OverviewPage;
else if (t == "tutorial")
pageType_ = TutorialPage;
- else if (t == "howto")
- pageType_ = HowToPage;
+ else if (t == "faq")
+ pageType_ = FAQPage;
else if (t == "article")
pageType_ = ArticlePage;
else if (t == "example")
@@ -515,7 +554,7 @@ QString Node::extractClassName(const QString &string) const
*/
QString RelatedClass::accessString() const
{
- switch (access) {
+ switch (access_) {
case Node::Protected:
return "protected";
case Node::Private:
@@ -601,9 +640,9 @@ QmlClassNode* Node::qmlClassNode()
{
if (isQmlNode()) {
Node* n = this;
- while (n && n->subType() != Node::QmlClass)
+ while (n && !n->isQmlType())
n = n->parent();
- if (n && n->subType() == Node::QmlClass)
+ if (n && n->isQmlType())
return static_cast<QmlClassNode*>(n);
}
return 0;
@@ -640,139 +679,186 @@ bool Node::isInternal() const
}
/*!
- \class InnerNode
+ Returns a pointer to the Tree this node is in.
*/
+Tree* Node::tree() const
+{
+ return (parent() ? parent()->tree() : 0);
+}
/*!
- The inner node destructor deletes the children and removes
- this node from its related nodes.
+ Returns a pointer to the root of the Tree this node is in.
*/
-InnerNode::~InnerNode()
+const Node* Node::root() const
{
- deleteChildren();
- removeFromRelated();
+ return (parent() ? parent()->root() : this);
}
/*!
- Returns \c true if this node's members coolection is not empty.
+ \class InnerNode
*/
-bool InnerNode::hasMembers() const
-{
- return !members_.isEmpty();
-}
/*!
- Appends \a node to the members list, if and only if it
- isn't already in the members list.
+ The inner node destructor deletes the children and removes
+ this node from its related nodes.
*/
-void InnerNode::addMember(Node* node)
+InnerNode::~InnerNode()
{
- if (!members_.contains(node))
- members_.append(node);
+ deleteChildren();
+ removeFromRelated();
}
/*!
- Returns \c true if this node's members collection contains at
- least one namespace node.
+ If \a genus is \c{Node::DontCare}, find the first node in
+ this node's child list that has the given \a name. If this
+ node is a QML type, be sure to also look in the children
+ of its property group nodes. Return the matching node or 0.
+
+ If \a genus is either \c{Node::CPP} or \c {Node::QML}, then
+ find all this node's children that have the given \a name,
+ and return the one that satisfies the \a genus requirement.
*/
-bool InnerNode::hasNamespaces() const
+Node *InnerNode::findChildNode(const QString& name, Node::Genus genus) const
{
- if (!members_.isEmpty()) {
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isNamespace())
- return true;
- ++i;
+ if (genus == Node::DontCare) {
+ Node *node = childMap.value(name);
+ if (node && !node->isQmlPropertyGroup()) // mws asks: Why not property group?
+ return node;
+ if (isQmlType()) {
+ for (int i=0; i<children_.size(); ++i) {
+ Node* n = children_.at(i);
+ if (n->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(n)->findChildNode(name, genus);
+ if (node)
+ return node;
+ }
+ }
}
}
- return false;
+ else {
+ NodeList nodes = childMap.values(name);
+ if (!nodes.isEmpty()) {
+ for (int i=0; i<nodes.size(); ++i) {
+ Node* node = nodes.at(i);
+ if (genus == node->genus() || genus == Node::DontCare)
+ return node;
+ }
+ }
+ }
+ return primaryFunctionMap.value(name);
}
/*!
- Returns \c true if this node's members collection contains at
- least one class node.
+ Find all the child nodes of this node that are named
+ \a name and return them in \a nodes.
*/
-bool InnerNode::hasClasses() const
+void InnerNode::findChildren(const QString& name, NodeList& nodes) const
{
- if (!members_.isEmpty()) {
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isClass())
- return true;
- ++i;
+ nodes = childMap.values(name);
+ Node* n = primaryFunctionMap.value(name);
+ if (n) {
+ nodes.append(n);
+ NodeList t = secondaryFunctionMap.value(name);
+ if (!t.isEmpty())
+ nodes.append(t);
+ }
+ if (!nodes.isEmpty() || !isQmlNode())
+ return;
+ int i = name.indexOf(QChar('.'));
+ if (i < 0)
+ return;
+ QString qmlPropGroup = name.left(i);
+ NodeList t = childMap.values(qmlPropGroup);
+ if (t.isEmpty())
+ return;
+ foreach (Node* n, t) {
+ if (n->isQmlPropertyGroup()) {
+ n->findChildren(name, nodes);
+ if (!nodes.isEmpty())
+ break;
}
}
- return false;
}
+#if 0
/*!
- Loads \a out with all this node's member nodes that are namespace nodes.
+ Find the node in this node's children that has the given \a name. If
+ this node is a QML class node, be sure to also look in the children
+ of its property group nodes. Return the matching node or 0. This is
+ not a recearsive search.
+
+ If \a qml is true, only match a node for which node->isQmlNode()
+ returns \c true. If \a qml is false, only match a node for which
+ node->isQmlNode() returns \c false.
*/
-void InnerNode::getMemberNamespaces(NodeMap& out)
+Node* InnerNode::findChildNode(const QString& name, bool qml) const
{
- out.clear();
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isNamespace())
- out.insert((*i)->name(),(*i));
- ++i;
+ NodeList nodes = childMap.values(name);
+ if (!nodes.isEmpty()) {
+ for (int i=0; i<nodes.size(); ++i) {
+ Node* node = nodes.at(i);
+ if (!qml) {
+ if (!node->isQmlNode())
+ return node;
+ }
+ else if (node->isQmlNode())
+ return node;
+ }
}
+ if (qml && isQmlType()) {
+ for (int i=0; i<children_.size(); ++i) {
+ Node* node = children_.at(i);
+ if (node->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
+ if (node)
+ return node;
+ }
+ }
+ }
+ return primaryFunctionMap.value(name);
}
+#endif
/*!
- Loads \a out with all this node's member nodes that are class nodes.
+ This function is like findChildNode(), but if a node
+ with the specified \a name is found but it is not of the
+ specified \a type, 0 is returned.
*/
-void InnerNode::getMemberClasses(NodeMap& out)
+Node* InnerNode::findChildNode(const QString& name, Type type)
{
- out.clear();
- NodeList::const_iterator i = members_.begin();
- while (i != members_.end()) {
- if ((*i)->isClass())
- out.insert((*i)->name(),(*i));
- ++i;
+ if (type == Function)
+ return primaryFunctionMap.value(name);
+ else {
+ NodeList nodes = childMap.values(name);
+ for (int i=0; i<nodes.size(); ++i) {
+ Node* node = nodes.at(i);
+ if (node->type() == type)
+ return node;
+ }
}
+ return 0;
}
+#if 0
/*!
- Find the node in this node's children that has the
- given \a name. If this node is a QML class node, be
- sure to also look in the children of its property
- group nodes. Return the matching node or 0.
*/
-Node *InnerNode::findChildNodeByName(const QString& name)
-{
- Node *node = childMap.value(name);
- if (node && node->type() != QmlPropertyGroup)
- return node;
- if ((type() == Document) && (subType() == QmlClass)) {
- for (int i=0; i<children_.size(); ++i) {
- Node* n = children_.at(i);
- if (n->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
- if (node)
- return node;
- }
- }
- }
- return primaryFunctionMap.value(name);
-}
-void InnerNode::findNodes(const QString& name, QList<Node*>& n)
+void InnerNode::findNodes(const QString& name, NodeList& n)
{
n.clear();
Node* node = 0;
- QList<Node*> nodes = childMap.values(name);
+ NodeList nodes = childMap.values(name);
/*
<sigh> If this node's child map contains no nodes named
- name, then if this node is a QML class, seach each of its
+ name, then if this node is a QML class, search each of its
property group nodes for a node named name. If a match is
found, append it to the output list and return immediately.
*/
if (nodes.isEmpty()) {
- if ((type() == Document) && (subType() == QmlClass)) {
+ if (isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
+ if (node->isQmlPropertyGroup()) {
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
if (node) {
n.append(node);
return;
@@ -793,10 +879,10 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
*/
for (int i=0; i<nodes.size(); ++i) {
node = nodes.at(i);
- if (node->type() != QmlPropertyGroup)
+ if (!node->isQmlPropertyGroup())
n.append(node);
else {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
+ node = static_cast<InnerNode*>(node)->findChildNode(name);
if (node)
n.append(node);
}
@@ -808,75 +894,13 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
if (node)
n.append(node);
}
-
-/*!
- Find the node in this node's children that has the given \a name. If
- this node is a QML class node, be sure to also look in the children
- of its property group nodes. Return the matching node or 0. This is
- not a recearsive search.
-
- If \a qml is true, only match a node for which node->isQmlNode()
- returns \c true. If \a qml is false, only match a node for which
- node->isQmlNode() returns \c false.
- */
-Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
-{
- QList<Node*> nodes = childMap.values(name);
- if (!nodes.isEmpty()) {
- for (int i=0; i<nodes.size(); ++i) {
- Node* node = nodes.at(i);
- if (!qml) {
- if (!node->isQmlNode())
- return node;
- }
- else if (node->isQmlNode() && (node->type() != QmlPropertyGroup))
- return node;
- }
- }
- if (qml && (type() == Document) && (subType() == QmlClass)) {
- for (int i=0; i<children_.size(); ++i) {
- Node* node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
- if (node)
- return node;
- }
- }
- }
- return primaryFunctionMap.value(name);
-}
-
-/*!
- This function is like findChildNodeByName(), but if a node
- with the specified \a name is found but it is not of the
- specified \a type, 0 is returned.
-
- This function is not recursive and therefore can't handle
- collisions. If it finds a collision node named \a name, it
- will return that node. But it might not find the collision
- node because it looks up \a name in the child map, not the
- list.
- */
-Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
-{
- if (type == Function)
- return primaryFunctionMap.value(name);
- else {
- QList<Node*> nodes = childMap.values(name);
- for (int i=0; i<nodes.size(); ++i) {
- Node* node = nodes.at(i);
- if (node->type() == type)
- return node;
- }
- }
- return 0;
-}
+#endif
/*!
Find a function node that is a child of this nose, such
that the function node has the specified \a name.
*/
-FunctionNode *InnerNode::findFunctionNode(const QString& name)
+FunctionNode *InnerNode::findFunctionNode(const QString& name) const
{
return static_cast<FunctionNode *>(primaryFunctionMap.value(name));
}
@@ -968,31 +992,13 @@ void InnerNode::setOverload(const FunctionNode *func, bool overlode)
Mark all child nodes that have no documentation as having
private access and internal status. qdoc will then ignore
them for documentation purposes.
-
- \note Exception: Name collision nodes are not marked
- private/internal.
*/
void InnerNode::makeUndocumentedChildrenInternal()
{
foreach (Node *child, childNodes()) {
if (child->doc().isEmpty()) {
- if (child->subType() != Node::Collision) {
- child->setAccess(Node::Private);
- child->setStatus(Node::Internal);
- }
- }
- }
-}
-
-/*!
- In each child node that is a collision node,
- clear the current child pointer.
- */
-void InnerNode::clearCurrentChildPointers()
-{
- foreach (Node* child, childNodes()) {
- if (child->subType() == Collision) {
- child->clearCurrentChild();
+ child->setAccess(Node::Private);
+ child->setStatus(Node::Internal);
}
}
}
@@ -1092,64 +1098,17 @@ bool Node::isWrapper() const
}
/*!
- */
-const Node *InnerNode::findChildNodeByName(const QString& name) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByName(name);
-}
-
-/*!
- If \a qml is true, only match a node for which node->isQmlNode()
- returns \c true. If \a qml is false, only match a node for which
- node->isQmlNode() returns \c false.
- */
-const Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const
-{
- InnerNode*that = (InnerNode*) this;
- return that->findChildNodeByName(name, qml);
-}
-
-/*!
- Searches this node's children for a child named \a name
- with the specified node \a type.
- */
-const Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByNameAndType(name, type);
-}
-
-/*!
- Find a function node that is a child of this nose, such
- that the function node has the specified \a name. This
- function calls the non-const version of itself.
- */
-const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(name);
-}
-
-/*!
- Find the function node that is a child of this node, such
- that the function has the same name and signature as the
- \a clone node. This function calls the non-const version.
- */
-const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(clone);
-}
-
-/*!
+ Finds the enum type node that has \a enumValue as one of
+ its enum values and returns a pointer to it. Returns 0 if
+ no enum type node is found that has \a enumValue as one
+ of its values.
*/
const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
{
foreach (const Node *node, enumChildren_) {
- const EnumNode *enume = static_cast<const EnumNode *>(node);
- if (enume->hasItem(enumValue))
- return enume;
+ const EnumNode *en = static_cast<const EnumNode *>(node);
+ if (en->hasItem(enumValue))
+ return en;
}
return 0;
}
@@ -1194,6 +1153,7 @@ InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name)
{
switch (type) {
case Class:
+ case QmlType:
case Namespace:
setPageType(ApiPage);
break;
@@ -1278,6 +1238,17 @@ void InnerNode::addChild(Node *child)
}
/*!
+ Adds the \a child to this node's child map using \a title
+ as the key. The \a child is not added to the child list
+ again, because it is presumed to already be there. We just
+ want to be able to find the child by its \a title.
+ */
+void InnerNode::addChild(Node* child, const QString& title)
+{
+ childMap.insertMulti(title, child);
+}
+
+/*!
*/
void InnerNode::removeChild(Node *child)
{
@@ -1307,6 +1278,16 @@ void InnerNode::removeChild(Node *child)
}
++ent;
}
+ if (child->title().isEmpty())
+ return;
+ ent = childMap.find(child->title());
+ while (ent != childMap.end() && ent.key() == child->title()) {
+ if (*ent == child) {
+ childMap.erase(ent);
+ break;
+ }
+ ++ent;
+ }
}
/*!
@@ -1381,7 +1362,7 @@ QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n) const
if (child->name() == n)
return static_cast<QmlPropertyNode*>(child);
}
- else if (child->type() == Node::QmlPropertyGroup) {
+ else if (child->isQmlPropertyGroup()) {
QmlPropertyNode* t = child->hasQmlProperty(n);
if (t)
return t;
@@ -1391,6 +1372,27 @@ QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n) const
}
/*!
+ If this node has a child that is a QML property named \a n
+ whose type (attached or normal property) matches \a attached,
+ return the pointer to that child.
+ */
+QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n, bool attached) const
+{
+ foreach (Node* child, childNodes()) {
+ if (child->type() == Node::QmlProperty) {
+ if (child->name() == n && child->isAttached() == attached)
+ return static_cast<QmlPropertyNode*>(child);
+ }
+ else if (child->isQmlPropertyGroup()) {
+ QmlPropertyNode* t = child->hasQmlProperty(n, attached);
+ if (t)
+ return t;
+ }
+ }
+ return 0;
+}
+
+/*!
\class LeafNode
*/
@@ -1414,6 +1416,7 @@ LeafNode::LeafNode(Type type, InnerNode *parent, const QString& name)
case QmlSignal:
case QmlSignalHandler:
case QmlMethod:
+ case QmlBasicType:
setPageType(ApiPage);
break;
default:
@@ -1457,7 +1460,7 @@ LeafNode::LeafNode(InnerNode* parent, Type type, const QString& name)
Constructs a namespace node.
*/
NamespaceNode::NamespaceNode(InnerNode *parent, const QString& name)
- : InnerNode(Namespace, parent, name)
+ : InnerNode(Namespace, parent, name), tree_(0)
{
setPageType(ApiPage);
}
@@ -1480,13 +1483,36 @@ ClassNode::ClassNode(InnerNode *parent, const QString& name)
}
/*!
+ Adds the base class \a node to this class's list of base
+ classes. The base class has the specified \a access. This
+ is a resolved base class.
*/
-void ClassNode::addBaseClass(Access access,
- ClassNode *node,
- const QString &dataTypeWithTemplateArgs)
+void ClassNode::addResolvedBaseClass(Access access, ClassNode* node)
{
- bases.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
- node->derived.append(RelatedClass(access, this));
+ bases_.append(RelatedClass(access, node));
+ node->derived_.append(RelatedClass(access, this));
+}
+
+/*!
+ Adds the derived class \a node to this class's list of derived
+ classes. The derived class inherits this class with \a access.
+ */
+void ClassNode::addDerivedClass(Access access, ClassNode* node)
+{
+ derived_.append(RelatedClass(access, node));
+}
+
+/*!
+ Add an unresolved base class to this class node's list of
+ base classes. The unresolved base class will be resolved
+ before the generate phase of qdoc. In an unresolved base
+ class, the pointer to the base class node is 0.
+ */
+void ClassNode::addUnresolvedBaseClass(Access access,
+ const QStringList& path,
+ const QString& signature)
+{
+ bases_.append(RelatedClass(access, path, signature));
}
/*!
@@ -1498,15 +1524,15 @@ void ClassNode::fixBaseClasses()
QSet<ClassNode *> found;
// Remove private and duplicate base classes.
- while (i < bases.size()) {
- ClassNode* bc = bases.at(i).node;
- if (bc->access() == Node::Private || found.contains(bc)) {
- RelatedClass rc = bases.at(i);
- bases.removeAt(i);
- ignoredBases.append(rc);
+ while (i < bases_.size()) {
+ ClassNode* bc = bases_.at(i).node_;
+ if (bc && (bc->access() == Node::Private || found.contains(bc))) {
+ RelatedClass rc = bases_.at(i);
+ bases_.removeAt(i);
+ ignoredBases_.append(rc);
const QList<RelatedClass> &bb = bc->baseClasses();
for (int j = bb.size() - 1; j >= 0; --j)
- bases.insert(i, bb.at(j));
+ bases_.insert(i, bb.at(j));
}
else {
++i;
@@ -1515,13 +1541,13 @@ void ClassNode::fixBaseClasses()
}
i = 0;
- while (i < derived.size()) {
- ClassNode* dc = derived.at(i).node;
- if (dc->access() == Node::Private) {
- derived.removeAt(i);
+ while (i < derived_.size()) {
+ ClassNode* dc = derived_.at(i).node_;
+ if (dc && dc->access() == Node::Private) {
+ derived_.removeAt(i);
const QList<RelatedClass> &dd = dc->derivedClasses();
for (int j = dd.size() - 1; j >= 0; --j)
- derived.insert(i, dd.at(j));
+ derived_.insert(i, dd.at(j));
}
else {
++i;
@@ -1530,12 +1556,34 @@ void ClassNode::fixBaseClasses()
}
/*!
+ Not sure why this is needed.
+ */
+void ClassNode::fixPropertyUsingBaseClasses(PropertyNode* pn)
+{
+ QList<RelatedClass>::const_iterator bc = baseClasses().constBegin();
+ while (bc != baseClasses().constEnd()) {
+ ClassNode* cn = bc->node_;
+ if (cn) {
+ Node* n = cn->findChildNode(pn->name(), Node::Property);
+ if (n) {
+ PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
+ cn->fixPropertyUsingBaseClasses(baseProperty);
+ pn->setOverriddenFrom(baseProperty);
+ }
+ else
+ cn->fixPropertyUsingBaseClasses(pn);
+ }
+ ++bc;
+ }
+}
+
+/*!
Search the child list to find the property node with the
specified \a name.
*/
PropertyNode* ClassNode::findPropertyNode(const QString& name)
{
- Node* n = findChildNodeByNameAndType(name, Node::Property);
+ Node* n = findChildNode(name, Node::Property);
if (n)
return static_cast<PropertyNode*>(n);
@@ -1545,19 +1593,23 @@ PropertyNode* ClassNode::findPropertyNode(const QString& name)
const QList<RelatedClass> &bases = baseClasses();
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = bases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
const QList<RelatedClass>& ignoredBases = ignoredBaseClasses();
if (!ignoredBases.isEmpty()) {
for (int i = 0; i < ignoredBases.size(); ++i) {
- ClassNode* cn = ignoredBases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = ignoredBases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
@@ -1577,13 +1629,13 @@ QmlClassNode* ClassNode::findQmlBaseNode()
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node_;
if (cn && cn->qmlElement()) {
return cn->qmlElement();
}
}
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node_;
if (cn) {
result = cn->findQmlBaseNode();
if (result != 0) {
@@ -1614,34 +1666,25 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
case DitaMap:
setPageType(ptype);
break;
- case Module:
- case Group:
- setPageType(OverviewPage);
- break;
- case QmlModule:
- setPageType(OverviewPage);
- break;
- case QmlClass:
- case QmlBasicType:
- setPageType(ApiPage);
- break;
case Example:
setPageType(ExamplePage);
break;
- case Collision:
- setPageType(ptype);
- break;
default:
break;
}
}
-/*!
+/*! \fn QString DocNode::title() const
Returns the document node's title. This is used for the page title.
*/
-QString DocNode::title() const
+
+/*!
+ Sets the document node's \a title. This is used for the page title.
+ */
+void DocNode::setTitle(const QString &title)
{
- return title_;
+ title_ = title;
+ parent()->addChild(this, title);
}
/*!
@@ -1669,9 +1712,6 @@ QString DocNode::fullTitle() const
else
return name() + " - " + title();
}
- else if (nodeSubtype_ == Collision) {
- return title();
- }
else {
return title();
}
@@ -1693,16 +1733,6 @@ QString DocNode::subTitle() const
}
/*!
- The constructor calls the DocNode constructor with
- \a parent, \a name, and Node::Example.
- */
-ExampleNode::ExampleNode(InnerNode* parent, const QString& name)
- : DocNode(parent, name, Node::Example, Node::ExamplePage)
-{
- // nothing
-}
-
-/*!
\class EnumNode
*/
@@ -2115,18 +2145,17 @@ bool QmlClassNode::qmlOnly = false;
QMultiMap<QString,Node*> QmlClassNode::inheritedBy;
/*!
- Constructs a Qml class node (i.e. a Document node with the
- subtype QmlClass. The new node has the given \a parent
- and \a name.
+ Constructs a Qml class node. The new node has the given
+ \a parent and \a name.
*/
QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name)
- : DocNode(parent, name, QmlClass, Node::ApiPage),
+ : InnerNode(QmlType, parent, name),
abstract_(false),
cnodeRequired_(false),
wrapper_(false),
cnode_(0),
qmlModule_(0),
- baseNode_(0)
+ qmlBaseNode_(0)
{
int i = 0;
if (name.startsWith("QML:")) {
@@ -2134,6 +2163,7 @@ QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name)
i = 4;
}
setTitle(name.mid(i));
+ setPageType(Node::ApiPage);
}
/*!
@@ -2198,6 +2228,14 @@ void QmlModuleNode::setQmlModuleInfo(const QString& arg)
}
}
+QmlClassNode* QmlClassNode::qmlBaseNode()
+{
+ if (!qmlBaseNode_ && !qmlBaseName_.isEmpty()) {
+ qmlBaseNode_ = QDocDatabase::qdocDB()->findQmlType(qmlBaseName_);
+ }
+ return qmlBaseNode_;
+}
+
/*!
If this QML type node has a base type node,
return the fully qualified name of that QML
@@ -2206,45 +2244,13 @@ void QmlModuleNode::setQmlModuleInfo(const QString& arg)
QString QmlClassNode::qmlFullBaseName() const
{
QString result;
- if (baseNode_) {
- result = baseNode_->qmlModuleName() + "::" + baseNode_->name();
+ if (qmlBaseNode_) {
+ result = qmlBaseNode_->qmlModuleName() + "::" + qmlBaseNode_->name();
}
return result;
}
/*!
- The name of this QML class node might be the same as the
- name of some other QML class node. If so, then this node's
- parent will be a NameCollisionNode.This function sets the
- NameCollisionNode's current child to this node. This is
- important when outputting the documentation for this node,
- when, for example, the documentation contains a link to
- the page being output. We don't want to generate a link
- to the disambiguation page if we can avoid it, and to be
- able to avoid it, the NameCollisionNode must maintain the
- current child pointer. That's the purpose of this function.
- */
-void QmlClassNode::setCurrentChild()
-{
- if (parent()) {
- InnerNode* n = parent();
- if (n->subType() == Node::Collision)
- n->setCurrentChild(this);
- }
-}
-
-/*!
- */
-void QmlClassNode::clearCurrentChild()
-{
- if (parent()) {
- InnerNode* n = parent();
- if (n->subType() == Node::Collision)
- n->clearCurrentChild();
- }
-}
-
-/*!
If the QML type's QML module pointer is set, return the QML
module name from the QML module node. Otherwise, return the
empty string.
@@ -2275,13 +2281,12 @@ QString QmlClassNode::qmlModuleIdentifier() const
}
/*!
- Constructs a Qml basic type node (i.e. a Document node with
- the subtype QmlBasicType. The new node has the given
+ Constructs a Qml basic type node. The new node has the given
\a parent and \a name.
*/
QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent,
const QString& name)
- : DocNode(parent, name, QmlBasicType, Node::ApiPage)
+ : InnerNode(QmlBasicType, parent, name)
{
setTitle(name);
}
@@ -2345,7 +2350,7 @@ QmlPropertyNode::QmlPropertyNode(InnerNode* parent,
...because the tokenizer gets confused on \e{explicit}.
*/
-bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
+bool QmlPropertyNode::isWritable()
{
if (readOnly_ != FlagValueDefault)
return !fromFlagValue(readOnly_, false);
@@ -2354,7 +2359,7 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
if (qcn) {
if (qcn->cppClassRequired()) {
if (qcn->classNode()) {
- PropertyNode* pn = correspondingProperty(qdb);
+ PropertyNode* pn = findCorrespondingCppProperty();
if (pn)
return pn->isWritable();
else
@@ -2377,157 +2382,61 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
Returns a pointer this QML property's corresponding C++
property, if it has one.
*/
-PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
+PropertyNode* QmlPropertyNode::findCorrespondingCppProperty()
{
PropertyNode* pn;
-
Node* n = parent();
- while (n && n->subType() != Node::QmlClass)
+ while (n && !n->isQmlType())
n = n->parent();
if (n) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(n);
ClassNode* cn = qcn->classNode();
if (cn) {
+ /*
+ If there is a dot in the property name, first
+ find the C++ property corresponding to the QML
+ property group.
+ */
QStringList dotSplit = name().split(QChar('.'));
pn = cn->findPropertyNode(dotSplit[0]);
if (pn) {
+ /*
+ Now find the C++ property corresponding to
+ the QML property in the QML property group,
+ <group>.<property>.
+ */
if (dotSplit.size() > 1) {
- // Find the C++ property corresponding to the QML property in
- // the property group, <group>.<property>.
-
QStringList path(extractClassName(pn->qualifiedDataType()));
- Node* nn = qdb->findClassNode(path);
+ Node* nn = QDocDatabase::qdocDB()->findClassNode(path);
if (nn) {
ClassNode* cn = static_cast<ClassNode*>(nn);
PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
- if (pn2)
- return pn2; // Return the property for the QML property.
- else
- return pn; // Return the property for the QML group.
+ /*
+ If found, return the C++ property
+ corresponding to the QML property.
+ Otherwise, return the C++ property
+ corresponding to the QML property
+ group.
+ */
+ return (pn2 ? pn2 : pn);
}
}
else
return pn;
}
- else {
- pn = cn->findPropertyNode(dotSplit[0]);
- if (pn)
- return pn;
- }
}
}
-
return 0;
}
-/*! \class NameCollisionNode
-
- An instance of this node is inserted in the tree
- whenever qdoc discovers that two nodes have the
- same name.
- */
-
/*!
- Constructs a name collision node containing \a child
- as its first child. The parent of \a child becomes
- this node's parent.
+ This returns the name of the owning QML type.
*/
-NameCollisionNode::NameCollisionNode(InnerNode* child)
- : DocNode(child->parent(), child->name(), Collision, Node::NoPageType)
+QString QmlPropertyNode::element() const
{
- setTitle("Name Collision: " + child->name());
- addCollision(child);
- current = 0;
-}
-
-/*!
- Add a collision to this collision node. \a child has
- the same name as the other children in this collision
- node. \a child becomes the current child.
- */
-void NameCollisionNode::addCollision(InnerNode* child)
-{
- if (child) {
- if (child->parent())
- child->parent()->removeChild(child);
- child->setParent((InnerNode*)this);
- children_.append(child);
- }
-}
-
-/*!
- The destructor does nothing.
- */
-NameCollisionNode::~NameCollisionNode()
-{
- // nothing.
-}
-
-/*! \fn const InnerNode* NameCollisionNode::currentChild() const
- Returns a pointer to the current child, which may be 0.
- */
-
-/*! \fn void NameCollisionNode::setCurrentChild(InnerNode* child)
- Sets the current child to \a child. The current child is
- valid only within the file where it is defined.
- */
-
-/*! \fn void NameCollisionNode::clearCurrentChild()
- Sets the current child to 0. This should be called at the
- end of each file, because the current child is only valid
- within the file where the child is defined.
- */
-
-/*!
- Returns \c true if this collision node's current node is a QML node.
- */
-bool NameCollisionNode::isQmlNode() const
-{
- if (current)
- return current->isQmlNode();
- return false;
-}
-
-/*!
- Find any of this collision node's children that has type \a t
- and subtype \a st and return a pointer to it.
-*/
-InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st)
-{
- if (current) {
- if (current->type() == t && current->subType() == st)
- return current;
- }
- const NodeList& cn = childNodes();
- NodeList::ConstIterator i = cn.constBegin();
- while (i != cn.constEnd()) {
- if ((*i)->type() == t && (*i)->subType() == st)
- return static_cast<InnerNode*>(*i);
- ++i;
- }
- return 0;
-}
-
-/*!
- This node is a name collision node. Find a child of this node
- such that the child's QML module name matches origin's QML module
- Name. Return the matching node, or return this node if there is
- no matching node.
- */
-const Node* NameCollisionNode::applyModuleName(const Node* origin) const
-{
- if (origin && !origin->qmlModuleName().isEmpty()) {
- const NodeList& cn = childNodes();
- NodeList::ConstIterator i = cn.constBegin();
- while (i != cn.constEnd()) {
- if ((*i)->type() == Node::Document && (*i)->subType() == Node::QmlClass) {
- if (origin->qmlModuleName() == (*i)->qmlModuleName())
- return (*i);
- }
- ++i;
- }
- }
- return this;
+ if (parent()->isQmlPropertyGroup())
+ return parent()->element();
+ return parent()->name();
}
/*!
@@ -2539,15 +2448,17 @@ QString Node::fullDocumentName() const
const Node* n = this;
do {
- if (!n->name().isEmpty() && n->type() != Node::QmlPropertyGroup)
+ if (!n->name().isEmpty() && !n->isQmlPropertyGroup())
pieces.insert(0, n->name());
- if (n->type() == Node::Document) {
- if ((n->subType() == Node::QmlClass) && !n->qmlModuleName().isEmpty())
- pieces.insert(0, n->qmlModuleName());
+ if (n->isQmlType() && !n->qmlModuleName().isEmpty()) {
+ pieces.insert(0, n->qmlModuleName());
break;
}
+ if (n->isDocNode())
+ break;
+
// Examine the parent node if one exists.
if (n->parent())
n = n->parent();
@@ -2557,7 +2468,10 @@ QString Node::fullDocumentName() const
// Create a name based on the type of the ancestor node.
QString concatenator = "::";
- if ((n->type() == Node::Document) && (n->subType() != Node::QmlClass))
+ if (n->isQmlType())
+ concatenator = QLatin1Char('.');
+
+ if (n->isDocNode())
concatenator = QLatin1Char('#');
return pieces.join(concatenator);
@@ -2732,16 +2646,15 @@ QString Node::idForNode() const
}
}
else if (parent_) {
- if (parent_->type() == Class)
+ if (parent_->isClass())
str = "class-member-" + func->name();
- else if (parent_->type() == Namespace)
+ else if (parent_->isNamespace())
str = "namespace-member-" + func->name();
+ else if (parent_->isQmlType())
+ str = "qml-method-" + parent_->name().toLower() + "-" + func->name();
else if (parent_->type() == Document) {
- if (parent_->subType() == QmlClass)
- str = "qml-method-" + parent_->name().toLower() + "-" + func->name();
- else
- qDebug() << "qdoc internal error: Node subtype not handled:"
- << parent_->subType() << func->name();
+ qDebug() << "qdoc internal error: Node subtype not handled:"
+ << parent_->subType() << func->name();
}
else
qDebug() << "qdoc internal error: Node type not handled:"
@@ -2752,15 +2665,16 @@ QString Node::idForNode() const
str += QLatin1Char('-') + QString::number(func->overloadNumber());
}
break;
+ case Node::QmlType:
+ str = "qml-class-" + name();
+ break;
+ case Node::QmlBasicType:
+ str = "qml-basic-type-" + name();
+ break;
case Node::Document:
{
switch (subType()) {
- case Node::QmlClass:
- str = "qml-class-" + name();
- break;
case Node::Page:
- case Node::Group:
- case Node::Module:
case Node::HeaderFile:
str = title();
if (str.isEmpty()) {
@@ -2778,16 +2692,6 @@ QString Node::idForNode() const
str = name();
str.replace(QLatin1Char('/'), QLatin1Char('-'));
break;
- case Node::QmlBasicType:
- str = "qml-basic-type-" + name();
- break;
- case Node::QmlModule:
- str = "qml-module-" + name();
- break;
- case Node::Collision:
- str = title();
- str.replace(": ","-");
- break;
default:
qDebug() << "ERROR: A case was not handled in Node::idForNode():"
<< "subType():" << subType() << "type():" << type();
@@ -2795,8 +2699,24 @@ QString Node::idForNode() const
}
}
break;
+ case Node::Group:
+ case Node::Module:
+ str = title();
+ if (str.isEmpty()) {
+ str = name();
+ if (str.endsWith(".html"))
+ str.remove(str.size()-5,5);
+ }
+ str.replace(QLatin1Char('/'), QLatin1Char('-'));
+ break;
+ case Node::QmlModule:
+ str = "qml-module-" + name();
+ break;
case Node::QmlProperty:
- str = "qml-property-" + name();
+ if (isAttached())
+ str = "qml-attached-property-" + name();
+ else
+ str = "qml-property-" + name();
break;
case Node::QmlPropertyGroup:
{
@@ -2855,10 +2775,93 @@ void InnerNode::printChildren(const QString& title)
}
/*!
- Prints the inner node's list of members.
+ Returns \c true if the collection node's member list is
+ not empty.
+ */
+bool CollectionNode::hasMembers() const
+{
+ return !members_.isEmpty();
+}
+
+/*!
+ Appends \a node to the collection node's member list, if
+ and only if it isn't already in the member list.
+ */
+void CollectionNode::addMember(Node* node)
+{
+ if (!members_.contains(node))
+ members_.append(node);
+}
+
+/*!
+ Returns \c true if this collection node contains at least
+ one namespace node.
+ */
+bool CollectionNode::hasNamespaces() const
+{
+ if (!members_.isEmpty()) {
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isNamespace())
+ return true;
+ ++i;
+ }
+ }
+ return false;
+}
+
+/*!
+ Returns \c true if this collection node contains at least
+ one class node.
+ */
+bool CollectionNode::hasClasses() const
+{
+ if (!members_.isEmpty()) {
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isClass())
+ return true;
+ ++i;
+ }
+ }
+ return false;
+}
+
+/*!
+ Loads \a out with all this collection node's members that
+ are namespace nodes.
+ */
+void CollectionNode::getMemberNamespaces(NodeMap& out)
+{
+ out.clear();
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isNamespace())
+ out.insert((*i)->name(),(*i));
+ ++i;
+ }
+}
+
+/*!
+ Loads \a out with all this collection node's members that
+ are class nodes.
+ */
+void CollectionNode::getMemberClasses(NodeMap& out)
+{
+ out.clear();
+ NodeList::const_iterator i = members_.begin();
+ while (i != members_.end()) {
+ if ((*i)->isClass())
+ out.insert((*i)->name(),(*i));
+ ++i;
+ }
+}
+
+/*!
+ Prints the collection node's list of members.
For debugging only.
*/
-void InnerNode::printMembers(const QString& title)
+void CollectionNode::printMembers(const QString& title)
{
qDebug() << title << name() << members_.size();
if (members_.size() > 0) {
@@ -2869,4 +2872,13 @@ void InnerNode::printMembers(const QString& title)
}
}
+/*!
+ Sets the document node's \a title. This is used for the page title.
+ */
+void CollectionNode::setTitle(const QString& title)
+{
+ title_ = title;
+ parent()->addChild(this, title);
+}
+
QT_END_NAMESPACE