diff options
Diffstat (limited to 'src/tools/qdoc/node.cpp')
-rw-r--r-- | src/tools/qdoc/node.cpp | 779 |
1 files changed, 413 insertions, 366 deletions
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index c88ebfc760..ce97ffec01 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -50,7 +50,6 @@ QT_BEGIN_NAMESPACE int Node::propertyGroupCount_ = 0; -ExampleNodeMap ExampleNode::exampleNodeMap; QStringMap Node::operators_; /*! @@ -127,14 +126,14 @@ QString Node::plainFullName(const Node* relative) const */ QString Node::fullName(const Node* relative) const { - if (type() == Node::Document) { + if (isDocNode() || isCollectionNode()) { 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) { + else if (isClass()) { const ClassNode* cn = static_cast<const ClassNode*>(this); if (!cn->serviceName().isEmpty()) return cn->serviceName(); @@ -143,6 +142,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 +194,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 +247,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 +324,12 @@ QString Node::nodeTypeString(unsigned t) return "property"; case Variable: return "variable"; + case Group: + return "group"; + case Module: + return "module"; + case QmlModule: + return "QML module"; case QmlProperty: return "QML property"; case QmlPropertyGroup: @@ -351,10 +372,6 @@ 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: @@ -363,8 +380,6 @@ QString Node::nodeSubtypeString(unsigned t) return "QML type"; case QmlBasicType: return "QML basic type"; - case QmlModule: - return "QML module"; case DitaMap: return "ditamap"; case Collision: @@ -515,7 +530,7 @@ QString Node::extractClassName(const QString &string) const */ QString RelatedClass::accessString() const { - switch (access) { + switch (access_) { case Node::Protected: return "protected"; case Node::Private: @@ -654,101 +669,21 @@ InnerNode::~InnerNode() } /*! - Returns \c true if this node's members coolection is not empty. - */ -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. - */ -void InnerNode::addMember(Node* node) -{ - if (!members_.contains(node)) - members_.append(node); -} - -/*! - Returns \c true if this node's members collection contains at - least one namespace node. - */ -bool InnerNode::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 node's members collection contains at - least one class node. - */ -bool InnerNode::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 node's member nodes that are namespace nodes. - */ -void InnerNode::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 node's member nodes that are class nodes. - */ -void InnerNode::getMemberClasses(NodeMap& out) -{ - out.clear(); - NodeList::const_iterator i = members_.begin(); - while (i != members_.end()) { - if ((*i)->isClass()) - out.insert((*i)->name(),(*i)); - ++i; - } -} - -/*! 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 *InnerNode::findChildNode(const QString& name) const { Node *node = childMap.value(name); - if (node && node->type() != QmlPropertyGroup) + if (node && !node->isQmlPropertyGroup()) return node; - if ((type() == Document) && (subType() == QmlClass)) { + if (isQmlType()) { 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 (n->isQmlPropertyGroup()) { + node = static_cast<InnerNode*>(n)->findChildNode(name); if (node) return node; } @@ -756,58 +691,6 @@ Node *InnerNode::findChildNodeByName(const QString& name) } return primaryFunctionMap.value(name); } -void InnerNode::findNodes(const QString& name, QList<Node*>& n) -{ - n.clear(); - Node* node = 0; - QList<Node*> 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 - 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)) { - 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) { - n.append(node); - return; - } - } - } - } - } - else { - /* - If the childMap does contain one or more nodes named - name, traverse the list of matching nodes. Append each - matching node that is not a property group node to the - output list. Search each property group node for a node - named name and append that node to the output list. - This is overkill, I think, but should produce a useful - list. - */ - for (int i=0; i<nodes.size(); ++i) { - node = nodes.at(i); - if (node->type() != QmlPropertyGroup) - n.append(node); - else { - node = static_cast<InnerNode*>(node)->findChildNodeByName(name); - if (node) - n.append(node); - } - } - } - if (!n.isEmpty()) - return; - node = primaryFunctionMap.value(name); - if (node) - n.append(node); -} /*! Find the node in this node's children that has the given \a name. If @@ -819,7 +702,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n) 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) +Node* InnerNode::findChildNode(const QString& name, bool qml) const { QList<Node*> nodes = childMap.values(name); if (!nodes.isEmpty()) { @@ -829,15 +712,15 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml) if (!node->isQmlNode()) return node; } - else if (node->isQmlNode() && (node->type() != QmlPropertyGroup)) + else if (node->isQmlNode()) return node; } } - if (qml && (type() == Document) && (subType() == QmlClass)) { + if (qml && isQmlType()) { 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->isQmlPropertyGroup()) { + node = static_cast<InnerNode*>(node)->findChildNode(name); if (node) return node; } @@ -847,7 +730,7 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml) } /*! - This function is like findChildNodeByName(), but if a node + 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. @@ -857,7 +740,7 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml) node because it looks up \a name in the child map, not the list. */ -Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) +Node* InnerNode::findChildNode(const QString& name, Type type) { if (type == Function) return primaryFunctionMap.value(name); @@ -873,10 +756,65 @@ Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) } /*! + */ +void InnerNode::findNodes(const QString& name, QList<Node*>& n) +{ + n.clear(); + Node* node = 0; + QList<Node*> nodes = childMap.values(name); + /* + <sigh> If this node's child map contains no nodes named + 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 (isQmlType()) { + for (int i=0; i<children_.size(); ++i) { + node = children_.at(i); + if (node->isQmlPropertyGroup()) { + node = static_cast<InnerNode*>(node)->findChildNode(name); + if (node) { + n.append(node); + return; + } + } + } + } + } + else { + /* + If the childMap does contain one or more nodes named + name, traverse the list of matching nodes. Append each + matching node that is not a property group node to the + output list. Search each property group node for a node + named name and append that node to the output list. + This is overkill, I think, but should produce a useful + list. + */ + for (int i=0; i<nodes.size(); ++i) { + node = nodes.at(i); + if (!node->isQmlPropertyGroup()) + n.append(node); + else { + node = static_cast<InnerNode*>(node)->findChildNode(name); + if (node) + n.append(node); + } + } + } + if (!n.isEmpty()) + return; + node = primaryFunctionMap.value(name); + if (node) + n.append(node); +} + +/*! 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)); } @@ -985,19 +923,6 @@ void InnerNode::makeUndocumentedChildrenInternal() } /*! - 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(); - } - } -} - -/*! */ void InnerNode::normalizeOverloads() { @@ -1092,64 +1017,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; } @@ -1278,6 +1156,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 +1196,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 +1280,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; @@ -1480,13 +1379,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::addResolvedBaseClass(Access access, ClassNode* node) +{ + 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::addBaseClass(Access access, - ClassNode *node, - const QString &dataTypeWithTemplateArgs) +void ClassNode::addUnresolvedBaseClass(Access access, + const QStringList& path, + const QString& signature) { - bases.append(RelatedClass(access, node, dataTypeWithTemplateArgs)); - node->derived.append(RelatedClass(access, this)); + bases_.append(RelatedClass(access, path, signature)); } /*! @@ -1498,15 +1420,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 +1437,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 +1452,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 +1489,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 +1525,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,13 +1562,6 @@ 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); @@ -1636,12 +1577,17 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node:: } } -/*! +/*! \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); } /*! @@ -1693,16 +1639,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 */ @@ -2126,7 +2062,7 @@ QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name) wrapper_(false), cnode_(0), qmlModule_(0), - baseNode_(0) + qmlBaseNode_(0) { int i = 0; if (name.startsWith("QML:")) { @@ -2198,6 +2134,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 +2150,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. @@ -2345,7 +2257,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 +2266,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,10 +2289,9 @@ 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) n = n->parent(); @@ -2388,38 +2299,53 @@ PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb) 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; } +/*! + This returns the name of the owning QML type. + */ +QString QmlPropertyNode::element() const +{ + if (parent()->isQmlPropertyGroup()) + return parent()->element(); + return parent()->name(); +} + /*! \class NameCollisionNode An instance of this node is inserted in the tree @@ -2437,7 +2363,6 @@ NameCollisionNode::NameCollisionNode(InnerNode* child) { setTitle("Name Collision: " + child->name()); addCollision(child); - current = 0; } /*! @@ -2463,28 +2388,11 @@ 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; } @@ -2494,10 +2402,6 @@ bool NameCollisionNode::isQmlNode() const */ 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()) { @@ -2520,7 +2424,7 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const const NodeList& cn = childNodes(); NodeList::ConstIterator i = cn.constBegin(); while (i != cn.constEnd()) { - if ((*i)->type() == Node::Document && (*i)->subType() == Node::QmlClass) { + if ((*i)->isQmlType()) { if (origin->qmlModuleName() == (*i)->qmlModuleName()) return (*i); } @@ -2531,6 +2435,49 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const } /*! + First, find all the colliding nodes that have the correct + type \a t and subtype \a st. If there is only one node + having the correct type and subtype, return that one. + If there is more than one node having the correct type + and subtype, then, in that subset, if there is only one + non-index node, return that one. If there are multiple + non-index nodes, return this collision node because we + can't disambiguate. Otherwise, if there are multiple + nodes having the correct type and subtype, return this + collision node because, again, we can't disambiguate. + But if there are no nodes at all that have the correct + type and subtype, return 0. + */ +Node* NameCollisionNode::disambiguate(Type t, SubType st) +{ + NodeList nl; + const NodeList& cn = childNodes(); + NodeList::ConstIterator i = cn.constBegin(); + while (i != cn.constEnd()) { + if ((*i)->type() == t) { + if ((st == NoSubType) || ((*i)->subType() == st)) + nl.append((*i)); + } + ++i; + } + Node* n = 0; + if (!nl.isEmpty()) { + i = nl.constBegin(); + if (nl.size() == 1) + return (*i); + while (i != nl.constEnd()) { + if (!(*i)->isIndexNode()) { + if (n) + return this; + n = (*i); + } + ++i; + } + } + return n; +} + +/*! Construct the full document name for this node and return it. */ QString Node::fullDocumentName() const @@ -2539,7 +2486,7 @@ 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) { @@ -2759,8 +2706,6 @@ QString Node::idForNode() const str = "qml-class-" + name(); break; case Node::Page: - case Node::Group: - case Node::Module: case Node::HeaderFile: str = title(); if (str.isEmpty()) { @@ -2781,9 +2726,6 @@ QString Node::idForNode() const case Node::QmlBasicType: str = "qml-basic-type-" + name(); break; - case Node::QmlModule: - str = "qml-module-" + name(); - break; case Node::Collision: str = title(); str.replace(": ","-"); @@ -2795,6 +2737,19 @@ 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(); break; @@ -2855,10 +2810,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 +2907,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 |