Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*
43 node.cpp
44*/
45
46#include "node.h"
47#include "tree.h"
48#include "codemarker.h"
49#include <QUuid>
50#include <qdebug.h>
51
52QT_BEGIN_NAMESPACE
53
54ExampleNodeMap ExampleNode::exampleNodeMap;
55
56/*!
57 \class Node
58 \brief The Node class is a node in the Tree.
59
60 A Node represents a class or function or something else
61 from the source code..
62 */
63
64/*!
65 When this Node is destroyed, if it has a parent Node, it
66 removes itself from the parent node's child list.
67 */
68Node::~Node()
69{
70 if (par)
71 par->removeChild(this);
72 if (rel)
73 rel->removeRelated(this);
74}
75
76/*!
77 Sets this Node's Doc to \a doc. If \a replace is false and
78 this Node already has a Doc, a warning is reported that the
79 Doc is being overridden, and it reports where the previous
80 Doc was found. If \a replace is true, the Doc is replaced
81 silently.
82 */
83void Node::setDoc(const Doc& doc, bool replace)
84{
85 if (!d.isEmpty() && !replace) {
86 doc.location().warning(tr("Overrides a previous doc"));
87 d.location().warning(tr("(The previous doc is here)"));
88 }
89 d = doc;
90}
91
92/*!
93 Construct a node with the given \a type and having the
94 given \a parent and \a name. The new node is added to the
95 parent's child list.
96 */
97Node::Node(Type type, InnerNode *parent, const QString& name)
98 : typ(type),
99 acc(Public),
100 saf(UnspecifiedSafeness),
101 pageTyp(NoPageType),
102 sta(Commendable),
103 par(parent),
104 rel(0),
105 nam(name)
106{
107 if (par)
108 par->addChild(this);
109}
110
111/*!
112 Returns the node's URL.
113 */
114QString Node::url() const
115{
116 return u;
117}
118
119/*!
120 Sets the node's URL to \a url
121 */
122void Node::setUrl(const QString &url)
123{
124 u = url;
125}
126
127void Node::setPageType(const QString& t)
128{
129 if ((t == "API") || (t == "api"))
130 pageTyp = ApiPage;
131 else if (t == "article")
132 pageTyp = ArticlePage;
133 else if (t == "example")
134 pageTyp = ExamplePage;
135}
136
137/*!
138 Sets the pointer to the node that this node relates to.
139 */
140void Node::setRelates(InnerNode *pseudoParent)
141{
142 if (rel)
143 rel->removeRelated(this);
144 rel = pseudoParent;
145 pseudoParent->related.append(this);
146}
147
148/*!
149 This function creates a pair that describes a link.
150 The pair is composed from \a link and \a desc. The
151 \a linkType is the map index the pair is filed under.
152 */
153void Node::setLink(LinkType linkType, const QString &link, const QString &desc)
154{
155 QPair<QString,QString> linkPair;
156 linkPair.first = link;
157 linkPair.second = desc;
158 linkMap[linkType] = linkPair;
159}
160
161/*!
162 Sets the information about the project and version a node was introduced
163 in. The string is simplified, removing excess whitespace before being
164 stored.
165*/
166void Node::setSince(const QString &since)
167{
168 sinc = since.simplified();
169}
170
171/*!
172 Returns a string representing the access specifier.
173 */
174QString Node::accessString() const
175{
176 switch (acc) {
177 case Protected:
178 return "protected";
179 case Private:
180 return "private";
181 case Public:
182 default:
183 break;
184 }
185 return "public";
186}
187
188/*!
189 Extract a class name from the type \a string and return it.
190 */
191QString Node::extractClassName(const QString &string) const
192{
193 QString result;
194 for (int i=0; i<=string.size(); ++i) {
195 QChar ch;
196 if (i != string.size())
197 ch = string.at(i);
198
199 QChar lower = ch.toLower();
200 if ((lower >= QLatin1Char('a') && lower <= QLatin1Char('z')) ||
201 ch.digitValue() >= 0 ||
202 ch == QLatin1Char('_') ||
203 ch == QLatin1Char(':')) {
204 result += ch;
205 }
206 else if (!result.isEmpty()) {
207 if (result != QLatin1String("const"))
208 return result;
209 result.clear();
210 }
211 }
212 return result;
213}
214
215/*!
216 Returns a string representing the access specifier.
217 */
218QString RelatedClass::accessString() const
219{
220 switch (access) {
221 case Node::Protected:
222 return "protected";
223 case Node::Private:
224 return "private";
225 case Node::Public:
226 default:
227 break;
228 }
229 return "public";
230}
231
232/*!
233 */
234Node::Status Node::inheritedStatus() const
235{
236 Status parentStatus = Commendable;
237 if (par)
238 parentStatus = par->inheritedStatus();
239 return (Status)qMin((int)sta, (int)parentStatus);
240}
241
242/*!
243 Returns the thread safeness value for whatever this node
244 represents. But if this node has a parent and the thread
245 safeness value of the parent is the same as the thread
246 safeness value of this node, what is returned is the
247 value \c{UnspecifiedSafeness}. Why?
248 */
249Node::ThreadSafeness Node::threadSafeness() const
250{
251 if (par && saf == par->inheritedThreadSafeness())
252 return UnspecifiedSafeness;
253 return saf;
254}
255
256/*!
257 If this node has a parent, the parent's thread safeness
258 value is returned. Otherwise, this node's thread safeness
259 value is returned. Why?
260 */
261Node::ThreadSafeness Node::inheritedThreadSafeness() const
262{
263 if (par && saf == UnspecifiedSafeness)
264 return par->inheritedThreadSafeness();
265 return saf;
266}
267
268/*!
269 Returns the sanitized file name without the path.
270 If the the file is an html file, the html suffix
271 is removed. Why?
272 */
273QString Node::fileBase() const
274{
275 QString base = name();
276 if (base.endsWith(".html"))
277 base.chop(5);
278 base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
279 base = base.trimmed();
280 base.replace(" ", "-");
281 return base.toLower();
282}
283
284/*!
285 Returns this node's Universally Unique IDentifier as a
286 QString. Creates the UUID first, if it has not been created.
287 */
288QString Node::guid() const
289{
290 if (uuid.isEmpty()) {
291 QUuid quuid = QUuid::createUuid();
292 QString t = quuid.toString();
293 uuid = "id-" + t.mid(1,t.length()-2);
294 }
295 return uuid;
296}
297
298/*!
299 Composes a string to be used as an href attribute in DITA
300 XML. It is composed of the file name and the UUID separated
301 by a '#'. If this node is a class node, the file name is
302 taken from this node; if this node is a function node, the
303 file name is taken from the parent node of this node.
304 */
305QString Node::ditaXmlHref()
306{
307 QString href;
308 if ((type() == Function) ||
309 (type() == Property) ||
310 (type() == Variable)) {
311 href = parent()->fileBase();
312 }
313 else {
314 href = fileBase();
315 }
316 if (!href.endsWith(".xml"))
317 href += ".xml";
318 return href + "#" + guid();
319}
320
321/*!
322 If this node is a QML class node, return a pointer to it.
323 If it is a child of a QML class node, return a pointer to
324 the QML class node. Otherwise, return 0;
325 */
326const QmlClassNode* Node::qmlClassNode() const
327{
328 if (isQmlNode()) {
329 const Node* n = this;
330 while (n && n->subType() != Node::QmlClass)
331 n = n->parent();
332 if (n && n->subType() == Node::QmlClass)
333 return static_cast<const QmlClassNode*>(n);
334 }
335 return 0;
336}
337
338/*!
339 If this node is a QML node, find its QML class node,
340 and return a pointer to the C++ class node from the
341 QML class node. That pointer will be null if the QML
342 class node is a component. It will be non-null if
343 the QML class node is a QML element.
344 */
345const ClassNode* Node::declarativeCppNode() const
346{
347 const QmlClassNode* qcn = qmlClassNode();
348 if (qcn)
349 return qcn->classNode();
350 return 0;
351}
352
353/*!
354 \class InnerNode
355 */
356
357/*!
358 The inner node destructor deletes the children and removes
359 this node from its related nodes.
360 */
361InnerNode::~InnerNode()
362{
363 deleteChildren();
364 removeFromRelated();
365}
366
367/*!
368 Find the node in this node's children that has the
369 given \a name. If this node is a QML class node, be
370 sure to also look in the children of its property
371 group nodes. Return the matching node or 0.
372 */
373Node *InnerNode::findNode(const QString& name)
374{
375 Node *node = childMap.value(name);
376 if (node && node->subType() != QmlPropertyGroup)
377 return node;
378 if ((type() == Fake) && (subType() == QmlClass)) {
379 for (int i=0; i<children.size(); ++i) {
380 Node* n = children.at(i);
381 if (n->subType() == QmlPropertyGroup) {
382 node = static_cast<InnerNode*>(n)->findNode(name);
383 if (node)
384 return node;
385 }
386 }
387 }
388 return primaryFunctionMap.value(name);
389}
390
391/*!
392 Same as the other findNode(), but if the node with the
393 specified \a name is not of the specified \a type, return
394 0.
395 */
396Node *InnerNode::findNode(const QString& name, Type type)
397{
398 if (type == Function) {
399 return primaryFunctionMap.value(name);
400 }
401 else {
402 Node *node = childMap.value(name);
403 if (node && node->type() == type) {
404 return node;
405 }
406 else {
407 return 0;
408 }
409 }
410}
411
412/*!
413 Find the function node in this node for the function named \a name.
414 */
415FunctionNode *InnerNode::findFunctionNode(const QString& name)
416{
417 return static_cast<FunctionNode *>(primaryFunctionMap.value(name));
418}
419
420/*!
421 Find the function node in this node that has the same name as \a clone.
422 */
423FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone)
424{
425 QMap<QString, Node *>::ConstIterator c =
426 primaryFunctionMap.find(clone->name());
427 if (c != primaryFunctionMap.end()) {
428 if (isSameSignature(clone, (FunctionNode *) *c)) {
429 return (FunctionNode *) *c;
430 }
431 else if (secondaryFunctionMap.contains(clone->name())) {
432 const NodeList& secs = secondaryFunctionMap[clone->name()];
433 NodeList::ConstIterator s = secs.begin();
434 while (s != secs.end()) {
435 if (isSameSignature(clone, (FunctionNode *) *s))
436 return (FunctionNode *) *s;
437 ++s;
438 }
439 }
440 }
441 return 0;
442}
443
444/*!
445 Returns the list of keys from the primary function map.
446 */
447QStringList InnerNode::primaryKeys()
448{
449 QStringList t;
450 QMap<QString, Node*>::iterator i = primaryFunctionMap.begin();
451 while (i != primaryFunctionMap.end()) {
452 t.append(i.key());
453 ++i;
454 }
455 return t;
456}
457
458/*!
459 Returns the list of keys from the secondary function map.
460 */
461QStringList InnerNode::secondaryKeys()
462{
463 QStringList t;
464 QMap<QString, NodeList>::iterator i = secondaryFunctionMap.begin();
465 while (i != secondaryFunctionMap.end()) {
466 t.append(i.key());
467 ++i;
468 }
469 return t;
470}
471
472/*!
473 */
474void InnerNode::setOverload(const FunctionNode *func, bool overlode)
475{
476 Node *node = (Node *) func;
477 Node *&primary = primaryFunctionMap[func->name()];
478
479 if (secondaryFunctionMap.contains(func->name())) {
480 NodeList& secs = secondaryFunctionMap[func->name()];
481 if (overlode) {
482 if (primary == node) {
483 primary = secs.first();
484 secs.erase(secs.begin());
485 secs.append(node);
486 }
487 else {
488 secs.removeAll(node);
489 secs.append(node);
490 }
491 }
492 else {
493 if (primary != node) {
494 secs.removeAll(node);
495 secs.prepend(primary);
496 primary = node;
497 }
498 }
499 }
500}
501
502/*!
503 Mark all child nodes that have no documentation as having
504 private access and internal status. qdoc will then ignore
505 them for documentation purposes.
506 */
507void InnerNode::makeUndocumentedChildrenInternal()
508{
509 foreach (Node *child, childNodes()) {
510 if (child->doc().isEmpty()) {
511 child->setAccess(Node::Private);
512 child->setStatus(Node::Internal);
513 }
514 }
515}
516
517/*!
518 */
519void InnerNode::normalizeOverloads()
520{
521 QMap<QString, Node *>::Iterator p1 = primaryFunctionMap.begin();
522 while (p1 != primaryFunctionMap.end()) {
523 FunctionNode *primaryFunc = (FunctionNode *) *p1;
524 if (secondaryFunctionMap.contains(primaryFunc->name()) &&
525 (primaryFunc->status() != Commendable ||
526 primaryFunc->access() == Private)) {
527
528 NodeList& secs = secondaryFunctionMap[primaryFunc->name()];
529 NodeList::ConstIterator s = secs.begin();
530 while (s != secs.end()) {
531 FunctionNode *secondaryFunc = (FunctionNode *) *s;
532
533 // Any non-obsolete, non-compatibility, non-private functions
534 // (i.e, visible functions) are preferable to the primary
535 // function.
536
537 if (secondaryFunc->status() == Commendable &&
538 secondaryFunc->access() != Private) {
539
540 *p1 = secondaryFunc;
541 int index = secondaryFunctionMap[primaryFunc->name()].indexOf(secondaryFunc);
542 secondaryFunctionMap[primaryFunc->name()].replace(index, primaryFunc);
543 break;
544 }
545 ++s;
546 }
547 }
548 ++p1;
549 }
550
551 QMap<QString, Node *>::ConstIterator p = primaryFunctionMap.begin();
552 while (p != primaryFunctionMap.end()) {
553 FunctionNode *primaryFunc = (FunctionNode *) *p;
554 if (primaryFunc->isOverload())
555 primaryFunc->ove = false;
556 if (secondaryFunctionMap.contains(primaryFunc->name())) {
557 NodeList& secs = secondaryFunctionMap[primaryFunc->name()];
558 NodeList::ConstIterator s = secs.begin();
559 while (s != secs.end()) {
560 FunctionNode *secondaryFunc = (FunctionNode *) *s;
561 if (!secondaryFunc->isOverload())
562 secondaryFunc->ove = true;
563 ++s;
564 }
565 }
566 ++p;
567 }
568
569 NodeList::ConstIterator c = childNodes().begin();
570 while (c != childNodes().end()) {
571 if ((*c)->isInnerNode())
572 ((InnerNode *) *c)->normalizeOverloads();
573 ++c;
574 }
575}
576
577/*!
578 */
579void InnerNode::removeFromRelated()
580{
581 while (!related.isEmpty()) {
582 Node *p = static_cast<Node *>(related.takeFirst());
583
584 if (p != 0 && p->relates() == this) p->clearRelated();
585 }
586}
587
588/*!
589 */
590void InnerNode::deleteChildren()
591{
592 NodeList childrenCopy = children; // `children` will be changed in ~Node()
593 qDeleteAll(childrenCopy);
594}
595
596/*!
597 Returns true because this is an inner node.
598 */
599bool InnerNode::isInnerNode() const
600{
601 return true;
602}
603
604/*!
605 */
606const Node *InnerNode::findNode(const QString& name) const
607{
608 InnerNode *that = (InnerNode *) this;
609 return that->findNode(name);
610}
611
612/*!
613 */
614const Node *InnerNode::findNode(const QString& name, Type type) const
615{
616 InnerNode *that = (InnerNode *) this;
617 return that->findNode(name, type);
618}
619
620/*!
621 Find the function node in this node that has the given \a name.
622 */
623const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
624{
625 InnerNode *that = (InnerNode *) this;
626 return that->findFunctionNode(name);
627}
628
629/*!
630 Find the function node in this node that has the same name as \a clone.
631 */
632const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
633{
634 InnerNode *that = (InnerNode *) this;
635 return that->findFunctionNode(clone);
636}
637
638/*!
639 */
640const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
641{
642 foreach (const Node *node, enumChildren) {
643 const EnumNode *enume = static_cast<const EnumNode *>(node);
644 if (enume->hasItem(enumValue))
645 return enume;
646 }
647 return 0;
648}
649
650/*!
651 Returnds the sequence number of the function node \a func
652 in the list of overloaded functions for a class, such that
653 all the functions have the same name as the \a func.
654 */
655int InnerNode::overloadNumber(const FunctionNode *func) const
656{
657 Node *node = (Node *) func;
658 if (primaryFunctionMap[func->name()] == node) {
659 return 1;
660 }
661 else {
662 return secondaryFunctionMap[func->name()].indexOf(node) + 2;
663 }
664}
665
666/*!
667 Returns the number of member functions of a class such that
668 the functions are all named \a funcName.
669 */
670int InnerNode::numOverloads(const QString& funcName) const
671{
672 if (primaryFunctionMap.contains(funcName)) {
673 return secondaryFunctionMap[funcName].count() + 1;
674 }
675 else {
676 return 0;
677 }
678}
679
680/*!
681 Returns a node list containing all the member functions of
682 some class such that the functions overload the name \a funcName.
683 */
684NodeList InnerNode::overloads(const QString &funcName) const
685{
686 NodeList result;
687 Node *primary = primaryFunctionMap.value(funcName);
688 if (primary) {
689 result << primary;
690 result += secondaryFunctionMap[funcName];
691 }
692 return result;
693}
694
695/*!
696 Construct an inner node (i.e., not a leaf node) of the
697 given \a type and having the given \a parent and \a name.
698 */
699InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name)
700 : Node(type, parent, name)
701{
702 switch (type) {
703 case Class:
704 case Namespace:
705 setPageType(ApiPage);
706 break;
707 default:
708 break;
709 }
710}
711
712/*!
713 Appends an \a include file to the list of include files.
714 */
715void InnerNode::addInclude(const QString& include)
716{
717 inc.append(include);
718}
719
720/*!
721 Sets the list of include files to \a includes.
722 */
723void InnerNode::setIncludes(const QStringList& includes)
724{
725 inc = includes;
726}
727
728/*!
729 f1 is always the clone
730 */
731bool InnerNode::isSameSignature(const FunctionNode *f1, const FunctionNode *f2)
732{
733 if (f1->parameters().count() != f2->parameters().count())
734 return false;
735 if (f1->isConst() != f2->isConst())
736 return false;
737
738 QList<Parameter>::ConstIterator p1 = f1->parameters().begin();
739 QList<Parameter>::ConstIterator p2 = f2->parameters().begin();
740 while (p2 != f2->parameters().end()) {
741 if ((*p1).hasType() && (*p2).hasType()) {
742 if ((*p1).rightType() != (*p2).rightType())
743 return false;
744
745 QString t1 = p1->leftType();
746 QString t2 = p2->leftType();
747
748 if (t1.length() < t2.length())
749 qSwap(t1, t2);
750
751 /*
752 ### hack for C++ to handle superfluous
753 "Foo::" prefixes gracefully
754 */
755 if (t1 != t2 && t1 != (f2->parent()->name() + "::" + t2))
756 return false;
757 }
758 ++p1;
759 ++p2;
760 }
761 return true;
762}
763
764/*!
765 Adds the \a child to this node's child list.
766 */
767void InnerNode::addChild(Node *child)
768{
769 children.append(child);
770 if ((child->type() == Function) || (child->type() == QmlMethod)) {
771 FunctionNode *func = (FunctionNode *) child;
772 if (!primaryFunctionMap.contains(func->name())) {
773 primaryFunctionMap.insert(func->name(), func);
774 }
775 else {
776 NodeList &secs = secondaryFunctionMap[func->name()];
777 secs.append(func);
778 }
779 }
780 else {
781 if (child->type() == Enum)
782 enumChildren.append(child);
783 childMap.insert(child->name(), child);
784 }
785}
786
787/*!
788 */
789void InnerNode::removeChild(Node *child)
790{
791 children.removeAll(child);
792 enumChildren.removeAll(child);
793 if (child->type() == Function) {
794 QMap<QString, Node *>::Iterator prim =
795 primaryFunctionMap.find(child->name());
796 NodeList& secs = secondaryFunctionMap[child->name()];
797 if (prim != primaryFunctionMap.end() && *prim == child) {
798 if (secs.isEmpty()) {
799 primaryFunctionMap.remove(child->name());
800 }
801 else {
802 primaryFunctionMap.insert(child->name(), secs.takeFirst());
803 }
804 }
805 else {
806 secs.removeAll(child);
807 }
808 QMap<QString, Node *>::Iterator ent = childMap.find( child->name() );
809 if (ent != childMap.end() && *ent == child)
810 childMap.erase( ent );
811 }
812 else {
813 QMap<QString, Node *>::Iterator ent = childMap.find(child->name());
814 if (ent != childMap.end() && *ent == child)
815 childMap.erase(ent);
816 }
817}
818
819/*!
820 Find the module (QtCore, QtGui, etc.) to which the class belongs.
821 We do this by obtaining the full path to the header file's location
822 and examine everything between "src/" and the filename. This is
823 semi-dirty because we are assuming a particular directory structure.
824
825 This function is only really useful if the class's module has not
826 been defined in the header file with a QT_MODULE macro or with an
827 \inmodule command in the documentation.
828*/
829QString Node::moduleName() const
830{
831 if (!mod.isEmpty())
832 return mod;
833
834 QString path = location().filePath();
835 QString pattern = QString("src") + QDir::separator();
836 int start = path.lastIndexOf(pattern);
837
838 if (start == -1)
839 return "";
840
841 QString moduleDir = path.mid(start + pattern.size());
842 int finish = moduleDir.indexOf(QDir::separator());
843
844 if (finish == -1)
845 return "";
846
847 QString moduleName = moduleDir.left(finish);
848
849 if (moduleName == "corelib")
850 return "QtCore";
851 else if (moduleName == "uitools")
852 return "QtUiTools";
853 else if (moduleName == "gui")
854 return "QtGui";
855 else if (moduleName == "network")
856 return "QtNetwork";
857 else if (moduleName == "opengl")
858 return "QtOpenGL";
859 else if (moduleName == "qt3support")
860 return "Qt3Support";
861 else if (moduleName == "svg")
862 return "QtSvg";
863 else if (moduleName == "sql")
864 return "QtSql";
865 else if (moduleName == "qtestlib")
866 return "QtTest";
867 else if (moduleDir.contains("webkit"))
868 return "QtWebKit";
869 else if (moduleName == "xml")
870 return "QtXml";
871 else
872 return "";
873}
874
875/*!
876 */
877void InnerNode::removeRelated(Node *pseudoChild)
878{
879 related.removeAll(pseudoChild);
880}
881
882/*!
883 \class LeafNode
884 */
885
886/*!
887 Returns false because this is a LeafNode.
888 */
889bool LeafNode::isInnerNode() const
890{
891 return false;
892}
893
894/*!
895 Constructs a leaf node named \a name of the specified
896 \a type. The new leaf node becomes a child of \a parent.
897 */
898LeafNode::LeafNode(Type type, InnerNode *parent, const QString& name)
899 : Node(type, parent, name)
900{
901 switch (type) {
902 case Enum:
903 case Function:
904 case Typedef:
905 case Variable:
906 case QmlProperty:
907 case QmlSignal:
908 case QmlMethod:
909 setPageType(ApiPage);
910 break;
911 default:
912 break;
913 }
914}
915
916/*!
917 \class NamespaceNode
918 */
919
920/*!
921 Constructs a namespace node.
922 */
923NamespaceNode::NamespaceNode(InnerNode *parent, const QString& name)
924 : InnerNode(Namespace, parent, name)
925{
926 setPageType(ApiPage);
927}
928
929/*!
930 \class ClassNode
931 \brief This class represents a C++ class.
932 */
933
934/*!
935 Constructs a class node. A class node will generate an API page.
936 */
937ClassNode::ClassNode(InnerNode *parent, const QString& name)
938 : InnerNode(Class, parent, name)
939{
940 hidden = false;
941 abstract = false;
942 setPageType(ApiPage);
943}
944
945/*!
946 */
947void ClassNode::addBaseClass(Access access,
948 ClassNode *node,
949 const QString &dataTypeWithTemplateArgs)
950{
951 bases.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
952 node->derived.append(RelatedClass(access, this));
953}
954
955/*!
956 */
957void ClassNode::fixBaseClasses()
958{
959 int i;
960 i = 0;
961 while (i < bases.size()) {
962 ClassNode* bc = bases.at(i).node;
963 if (bc->access() == Node::Private) {
964 RelatedClass rc = bases.at(i);
965 bases.removeAt(i);
966 ignoredBases.append(rc);
967 const QList<RelatedClass> &bb = bc->baseClasses();
968 for (int j = bb.size() - 1; j >= 0; --j)
969 bases.insert(i, bb.at(j));
970 }
971 else {
972 ++i;
973 }
974 }
975
976 i = 0;
977 while (i < derived.size()) {
978 ClassNode* dc = derived.at(i).node;
979 if (dc->access() == Node::Private) {
980 derived.removeAt(i);
981 const QList<RelatedClass> &dd = dc->derivedClasses();
982 for (int j = dd.size() - 1; j >= 0; --j)
983 derived.insert(i, dd.at(j));
984 }
985 else {
986 ++i;
987 }
988 }
989}
990
991/*!
992 Search the child list to find the property node with the
993 specified \a name.
994 */
995const PropertyNode *ClassNode::findPropertyNode(const QString &name) const
996{
997 const Node *n = findNode(name, Node::Property);
998
999 if (n)
1000 return static_cast<const PropertyNode*>(n);
1001
1002 const PropertyNode *pn = 0;
1003
1004 const QList<RelatedClass> &bases = baseClasses();
1005 if (!bases.isEmpty()) {
1006 for (int i = 0; i < bases.size(); ++i) {
1007 const ClassNode *cn = bases[i].node;
1008 pn = cn->findPropertyNode(name);
1009 if (pn)
1010 break;
1011 }
1012 }
1013 const QList<RelatedClass>& ignoredBases = ignoredBaseClasses();
1014 if (!ignoredBases.isEmpty()) {
1015 for (int i = 0; i < ignoredBases.size(); ++i) {
1016 const ClassNode *cn = ignoredBases[i].node;
1017 pn = cn->findPropertyNode(name);
1018 if (pn)
1019 break;
1020 }
1021 }
1022
1023 return pn;
1024}
1025
1026/*!
1027 \class FakeNode
1028 */
1029
1030/*!
1031 The type of a FakeNode is Fake, and it has a \a subtype,
1032 which specifies the type of FakeNode. The page type for
1033 the page index is set here.
1034 */
1035FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subtype)
1036 : InnerNode(Fake, parent, name), sub(subtype)
1037{
1038 switch (subtype) {
1039 case Module:
1040 case Page:
1041 case Group:
1042 setPageType(ArticlePage);
1043 break;
1044 case QmlClass:
1045 case QmlBasicType:
1046 setPageType(ApiPage);
1047 break;
1048 case Example:
1049 setPageType(ExamplePage);
1050 break;
1051 default:
1052 break;
1053 }
1054}
1055
1056/*!
1057 Returns the fake node's title. This is used for the page title.
1058*/
1059QString FakeNode::title() const
1060{
1061 return tle;
1062}
1063
1064/*!
1065 Returns the fake node's full title, which is usually
1066 just title(), but for some SubType values is different
1067 from title()
1068 */
1069QString FakeNode::fullTitle() const
1070{
1071 if (sub == File) {
1072 if (title().isEmpty())
1073 return name().mid(name().lastIndexOf('/') + 1) + " Example File";
1074 else
1075 return title();
1076 }
1077 else if (sub == Image) {
1078 if (title().isEmpty())
1079 return name().mid(name().lastIndexOf('/') + 1) + " Image File";
1080 else
1081 return title();
1082 }
1083 else if (sub == HeaderFile) {
1084 if (title().isEmpty())
1085 return name();
1086 else
1087 return name() + " - " + title();
1088 }
1089 else {
1090 return title();
1091 }
1092}
1093
1094/*!
1095 Returns the subtitle.
1096 */
1097QString FakeNode::subTitle() const
1098{
1099 if (!stle.isEmpty())
1100 return stle;
1101
1102 if ((sub == File) || (sub == Image)) {
1103 if (title().isEmpty() && name().contains("/"))
1104 return name();
1105 }
1106 return QString();
1107}
1108
1109/*!
1110 The constructor calls the FakeNode constructor with
1111 \a parent, \a name, and Node::Example.
1112 */
1113ExampleNode::ExampleNode(InnerNode* parent, const QString& name)
1114 : FakeNode(parent, name, Node::Example)
1115{
1116 // nothing
1117}
1118
1119/*!
1120 \class EnumNode
1121 */
1122
1123/*!
1124 The constructor for the node representing an enum type
1125 has a \a parent class and an enum type \a name.
1126 */
1127EnumNode::EnumNode(InnerNode *parent, const QString& name)
1128 : LeafNode(Enum, parent, name), ft(0)
1129{
1130}
1131
1132/*!
1133 Add \a item to the enum type's item list.
1134 */
1135void EnumNode::addItem(const EnumItem& item)
1136{
1137 itms.append(item);
1138 names.insert(item.name());
1139}
1140
1141/*!
1142 Returns the access level of the enumeration item named \a name.
1143 Apparently it is private if it has been omitted by qdoc's
1144 omitvalue command. Otherwise it is public.
1145 */
1146Node::Access EnumNode::itemAccess(const QString &name) const
1147{
1148 if (doc().omitEnumItemNames().contains(name))
1149 return Private;
1150 return Public;
1151}
1152
1153/*!
1154 Returns the enum value associated with the enum \a name.
1155 */
1156QString EnumNode::itemValue(const QString &name) const
1157{
1158 foreach (const EnumItem &item, itms) {
1159 if (item.name() == name)
1160 return item.value();
1161 }
1162 return QString();
1163}
1164
1165/*!
1166 \class TypedefNode
1167 */
1168
1169/*!
1170 */
1171TypedefNode::TypedefNode(InnerNode *parent, const QString& name)
1172 : LeafNode(Typedef, parent, name), ae(0)
1173{
1174}
1175
1176/*!
1177 */
1178void TypedefNode::setAssociatedEnum(const EnumNode *enume)
1179{
1180 ae = enume;
1181}
1182
1183/*!
1184 \class Parameter
1185 \brief The class Parameter contains one parameter.
1186
1187 A parameter can be a function parameter or a macro
1188 parameter.
1189 */
1190
1191/*!
1192 Constructs this parameter from the left and right types
1193 \a leftType and rightType, the parameter \a name, and the
1194 \a defaultValue. In practice, \a rightType is not used,
1195 and I don't know what is was meant for.
1196 */
1197Parameter::Parameter(const QString& leftType,
1198 const QString& rightType,
1199 const QString& name,
1200 const QString& defaultValue)
1201 : lef(leftType), rig(rightType), nam(name), def(defaultValue)
1202{
1203}
1204
1205/*!
1206 The standard copy constructor copies the strings from \a p.
1207 */
1208Parameter::Parameter(const Parameter& p)
1209 : lef(p.lef), rig(p.rig), nam(p.nam), def(p.def)
1210{
1211}
1212
1213/*!
1214 Assigning Parameter \a p to this Parameter copies the
1215 strings across.
1216 */
1217Parameter& Parameter::operator=(const Parameter& p)
1218{
1219 lef = p.lef;
1220 rig = p.rig;
1221 nam = p.nam;
1222 def = p.def;
1223 return *this;
1224}
1225
1226/*!
1227 Reconstructs the text describing the parameter and
1228 returns it. If \a value is true, the default value
1229 will be included, if there is one.
1230 */
1231QString Parameter::reconstruct(bool value) const
1232{
1233 QString p = lef + rig;
1234 if (!p.endsWith(QChar('*')) && !p.endsWith(QChar('&')) && !p.endsWith(QChar(' ')))
1235 p += " ";
1236 p += nam;
1237 if (value && !def.isEmpty())
1238 p += " = " + def;
1239 return p;
1240}
1241
1242
1243/*!
1244 \class FunctionNode
1245 */
1246
1247/*!
1248 Construct a function node for a C++ function. It's parent
1249 is \a parent, and it's name is \a name.
1250 */
1251FunctionNode::FunctionNode(InnerNode *parent, const QString& name)
1252 : LeafNode(Function, parent, name),
1253 met(Plain),
1254 vir(NonVirtual),
1255 con(false),
1256 sta(false),
1257 ove(false),
1258 att(false),
1259 rf(0),
1260 ap(0)
1261{
1262 // nothing.
1263}
1264
1265/*!
1266 Construct a function node for a QML method or signal, specified
1267 by \a type. It's parent is \a parent, and it's name is \a name.
1268 If \a attached is true, it is an attached method or signal.
1269 */
1270FunctionNode::FunctionNode(Type type, InnerNode *parent, const QString& name, bool attached)
1271 : LeafNode(type, parent, name),
1272 met(Plain),
1273 vir(NonVirtual),
1274 con(false),
1275 sta(false),
1276 ove(false),
1277 att(attached),
1278 rf(0),
1279 ap(0)
1280{
1281 // nothing.
1282}
1283
1284/*!
1285 Sets the \a virtualness of this function. If the \a virtualness
1286 is PureVirtual, and if the parent() is a ClassNode, set the parent's
1287 \e abstract flag to true.
1288 */
1289void FunctionNode::setVirtualness(Virtualness virtualness)
1290{
1291 vir = virtualness;
1292 if ((virtualness == PureVirtual) && parent() &&
1293 (parent()->type() == Node::Class))
1294 parent()->setAbstract(true);
1295}
1296
1297/*!
1298 */
1299void FunctionNode::setOverload(bool overlode)
1300{
1301 parent()->setOverload(this, overlode);
1302 ove = overlode;
1303}
1304
1305/*!
1306 Sets the function node's reimplementation flag to \a r.
1307 When \a r is true, it is supposed to mean that this function
1308 is a reimplementation of a virtual function in a base class,
1309 but it really just means the \e reimp command was seen in the
1310 qdoc comment.
1311 */
1312void FunctionNode::setReimp(bool r)
1313{
1314 reimp = r;
1315}
1316
1317/*!
1318 */
1319void FunctionNode::addParameter(const Parameter& parameter)
1320{
1321 params.append(parameter);
1322}
1323
1324/*!
1325 */
1326void FunctionNode::borrowParameterNames(const FunctionNode *source)
1327{
1328 QList<Parameter>::Iterator t = params.begin();
1329 QList<Parameter>::ConstIterator s = source->params.begin();
1330 while (s != source->params.end() && t != params.end()) {
1331 if (!(*s).name().isEmpty())
1332 (*t).setName((*s).name());
1333 ++s;
1334 ++t;
1335 }
1336}
1337
1338/*!
1339 If this function is a reimplementation, \a from points
1340 to the FunctionNode of the function being reimplemented.
1341 */
1342void FunctionNode::setReimplementedFrom(FunctionNode *from)
1343{
1344 rf = from;
1345 from->rb.append(this);
1346}
1347
1348/*!
1349 Sets the "associated" property to \a property. The function
1350 might be the setter or getter for a property, for example.
1351 */
1352void FunctionNode::setAssociatedProperty(PropertyNode *property)
1353{
1354 ap = property;
1355}
1356
1357/*!
1358 Returns the overload number for this function obtained
1359 from the parent.
1360 */
1361int FunctionNode::overloadNumber() const
1362{
1363 return parent()->overloadNumber(this);
1364}
1365
1366/*!
1367 Returns the number of times this function name has been
1368 overloaded, obtained from the parent.
1369 */
1370int FunctionNode::numOverloads() const
1371{
1372 return parent()->numOverloads(name());
1373}
1374
1375/*!
1376 Returns the list of parameter names.
1377 */
1378QStringList FunctionNode::parameterNames() const
1379{
1380 QStringList names;
1381 QList<Parameter>::ConstIterator p = parameters().begin();
1382 while (p != parameters().end()) {
1383 names << (*p).name();
1384 ++p;
1385 }
1386 return names;
1387}
1388
1389/*!
1390 Returns a raw list of parameters. If \a names is true, the
1391 names are included. If \a values is true, the default values
1392 are included, if any are present.
1393 */
1394QString FunctionNode::rawParameters(bool names, bool values) const
1395{
1396 QString raw;
1397 foreach (const Parameter &parameter, parameters()) {
1398 raw += parameter.leftType() + parameter.rightType();
1399 if (names)
1400 raw += parameter.name();
1401 if (values)
1402 raw += parameter.defaultValue();
1403 }
1404 return raw;
1405}
1406
1407/*!
1408 Returns the list of reconstructed parameters. If \a values
1409 is true, the default values are included, if any are present.
1410 */
1411QStringList FunctionNode::reconstructParams(bool values) const
1412{
1413 QStringList params;
1414 QList<Parameter>::ConstIterator p = parameters().begin();
1415 while (p != parameters().end()) {
1416 params << (*p).reconstruct(values);
1417 ++p;
1418 }
1419 return params;
1420}
1421
1422/*!
1423 Reconstructs and returns the function's signature. If \a values
1424 is true, the default values of the parameters are included, if
1425 present.
1426 */
1427QString FunctionNode::signature(bool values) const
1428{
1429 QString s;
1430 if (!returnType().isEmpty())
1431 s = returnType() + " ";
1432 s += name() + "(";
1433 QStringList params = reconstructParams(values);
1434 int p = params.size();
1435 if (p > 0) {
1436 for (int i=0; i<p; i++) {
1437 s += params[i];
1438 if (i < (p-1))
1439 s += ", ";
1440 }
1441 }
1442 s += ")";
1443 return s;
1444}
1445
1446/*!
1447 Returns true if the node's status is Internal, or if its
1448 parent is a class with internal status.
1449 */
1450bool FunctionNode::isInternal() const
1451{
1452 if (status() == Internal)
1453 return true;
1454 if (parent() && parent()->status() == Internal)
1455 return true;
1456 if (relates() && relates()->status() == Internal)
1457 return true;
1458 return false;
1459}
1460
1461/*!
1462 Print some debugging stuff.
1463 */
1464void FunctionNode::debug() const
1465{
1466 qDebug("QML METHOD %s rt %s pp %s",
1467 qPrintable(name()), qPrintable(rt), qPrintable(pp.join(" ")));
1468}
1469
1470/*!
1471 \class PropertyNode
1472
1473 This class describes one instance of using the Q_PROPERTY macro.
1474 */
1475
1476/*!
1477 The constructor sets the \a parent and the \a name, but
1478 everything else is set to default values.
1479 */
1480PropertyNode::PropertyNode(InnerNode *parent, const QString& name)
1481 : LeafNode(Property, parent, name),
1482 sto(Trool_Default),
1483 des(Trool_Default),
1484 scr(Trool_Default),
1485 wri(Trool_Default),
1486 usr(Trool_Default),
1487 cst(false),
1488 fnl(false),
1489 rev(-1),
1490 overrides(0)
1491{
1492 // nothing.
1493}
1494
1495/*!
1496 Sets this property's \e {overridden from} property to
1497 \a baseProperty, which indicates that this property
1498 overrides \a baseProperty. To begin with, all the values
1499 in this property are set to the corresponding values in
1500 \a baseProperty.
1501
1502 We probably should ensure that the constant and final
1503 attributes are not being overridden improperly.
1504 */
1505void PropertyNode::setOverriddenFrom(const PropertyNode* baseProperty)
1506{
1507 for (int i = 0; i < NumFunctionRoles; ++i) {
1508 if (funcs[i].isEmpty())
1509 funcs[i] = baseProperty->funcs[i];
1510 }
1511 if (sto == Trool_Default)
1512 sto = baseProperty->sto;
1513 if (des == Trool_Default)
1514 des = baseProperty->des;
1515 if (scr == Trool_Default)
1516 scr = baseProperty->scr;
1517 if (wri == Trool_Default)
1518 wri = baseProperty->wri;
1519 if (usr == Trool_Default)
1520 usr = baseProperty->usr;
1521 overrides = baseProperty;
1522}
1523
1524/*!
1525 */
1526QString PropertyNode::qualifiedDataType() const
1527{
1528 if (setters().isEmpty() && resetters().isEmpty()) {
1529 if (dt.contains("*") || dt.contains("&")) {
1530 // 'QWidget *' becomes 'QWidget *' const
1531 return dt + " const";
1532 }
1533 else {
1534 /*
1535 'int' becomes 'const int' ('int const' is
1536 correct C++, but looks wrong)
1537 */
1538 return "const " + dt;
1539 }
1540 }
1541 else {
1542 return dt;
1543 }
1544}
1545
1546/*! Converts the \a boolean value to an enum representation
1547 of the boolean type, which includes an enum value for the
1548 \e {default value} of the item, i.e. true, false, or default.
1549 */
1550PropertyNode::Trool PropertyNode::toTrool(bool boolean)
1551{
1552 return boolean ? Trool_True : Trool_False;
1553}
1554
1555/*!
1556 Converts the enum \a troolean back to a boolean value.
1557 If \a troolean is neither the true enum value nor the
1558 false enum value, the boolean value returned is
1559 \a defaultValue.
1560
1561 Note that runtimeDesignabilityFunction() should be called
1562 first. If that function returns the name of a function, it
1563 means the function must be called at runtime to determine
1564 whether the property is Designable.
1565 */
1566bool PropertyNode::fromTrool(Trool troolean, bool defaultValue)
1567{
1568 switch (troolean) {
1569 case Trool_True:
1570 return true;
1571 case Trool_False:
1572 return false;
1573 default:
1574 return defaultValue;
1575 }
1576}
1577
1578/*!
1579 \class TargetNode
1580 */
1581
1582/*!
1583 */
1584TargetNode::TargetNode(InnerNode *parent, const QString& name)
1585 : LeafNode(Target, parent, name)
1586{
1587}
1588
1589/*!
1590 Returns false because this is a TargetNode.
1591 */
1592bool TargetNode::isInnerNode() const
1593{
1594 return false;
1595}
1596
1597#ifdef QDOC_QML
1598bool QmlClassNode::qmlOnly = false;
1599QMultiMap<QString,Node*> QmlClassNode::inheritedBy;
1600
1601/*!
1602 Constructs a Qml class node (i.e. a Fake node with the
1603 subtype QmlClass. The new node has the given \a parent
1604 and \a name and is associated with the C++ class node
1605 specified by \a cn which may be null if the the Qml
1606 class node is not associated with a C++ class node.
1607 */
1608QmlClassNode::QmlClassNode(InnerNode *parent,
1609 const QString& name,
1610 const ClassNode* cn)
1611 : FakeNode(parent, name, QmlClass), cnode(cn)
1612{
1613 if (name.startsWith(QLatin1String("QML:")))
1614 setTitle((qmlOnly ? QLatin1String("") : QLatin1String("QML ")) + name.mid(4) + QLatin1String(" Element"));
1615 else
1616 setTitle((qmlOnly ? QLatin1String("") : QLatin1String("QML ")) + name + QLatin1String(" Element"));
1617}
1618
1619/*!
1620 I made this so I could print a debug message here.
1621 */
1622QmlClassNode::~QmlClassNode()
1623{
1624#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
1625 qDebug() << "Deleting QmlClassNode:" << name();
1626#endif
1627}
1628
1629/*!
1630 Clear the multimap so that subsequent runs don't try to use
1631 nodes from a previous run.
1632 */
1633void QmlClassNode::clear()
1634{
1635 inheritedBy.clear();
1636}
1637
1638/*!
1639 The base file name for this kind of node has "qml_"
1640 prepended to it.
1641
1642 But not yet. Still testing.
1643 */
1644QString QmlClassNode::fileBase() const
1645{
1646 return Node::fileBase();
1647}
1648
1649/*!
1650 Record the fact that QML class \a base is inherited by
1651 QML class \a sub.
1652 */
1653void QmlClassNode::addInheritedBy(const QString& base, Node* sub)
1654{
1655 inheritedBy.insert(base,sub);
1656#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
1657 qDebug() << "QmlClassNode::addInheritedBy(): insert" << base << sub->name() << inheritedBy.size();
1658#endif
1659}
1660
1661/*!
1662 Loads the list \a subs with the nodes of all the subclasses of \a base.
1663 */
1664void QmlClassNode::subclasses(const QString& base, NodeList& subs)
1665{
1666 subs.clear();
1667 if (inheritedBy.count(base) > 0) {
1668 subs = inheritedBy.values(base);
1669#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
1670 qDebug() << "QmlClassNode::subclasses():" << inheritedBy.count(base) << base
1671 << "subs:" << subs.size() << "total size:" << inheritedBy.size();
1672#endif
1673 }
1674}
1675
1676/*!
1677 Constructs a Qml basic type node (i.e. a Fake node with
1678 the subtype QmlBasicType. The new node has the given
1679 \a parent and \a name.
1680 */
1681QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent,
1682 const QString& name)
1683 : FakeNode(parent, name, QmlBasicType)
1684{
1685 setTitle(name);
1686}
1687
1688/*!
1689 Constructor for the Qml property group node. \a parent is
1690 always a QmlClassNode.
1691 */
1692QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent,
1693 const QString& name,
1694 bool attached)
1695 : FakeNode(parent, name, QmlPropertyGroup),
1696 isdefault(false),
1697 att(attached)
1698{
1699 // nothing.
1700}
1701
1702/*!
1703 Constructor for the QML property node.
1704 */
1705QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent,
1706 const QString& name,
1707 const QString& type,
1708 bool attached)
1709 : LeafNode(QmlProperty, parent, name),
1710 dt(type),
1711 sto(Trool_Default),
1712 des(Trool_Default),
1713 att(attached)
1714{
1715 setPageType(ApiPage);
1716}
1717
1718/*!
1719 I don't know what this is.
1720 */
1721QmlPropertyNode::Trool QmlPropertyNode::toTrool(bool boolean)
1722{
1723 return boolean ? Trool_True : Trool_False;
1724}
1725
1726/*!
1727 I don't know what this is either.
1728 */
1729bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue)
1730{
1731 switch (troolean) {
1732 case Trool_True:
1733 return true;
1734 case Trool_False:
1735 return false;
1736 default:
1737 return defaultValue;
1738 }
1739}
1740
1741/*!
1742 Returns true if a QML property or attached property is
1743 read-only. The algorithm for figuring this out is long
1744 amd tedious and almost certainly will break. It currently
1745 doesn't work for qmlproperty bool PropertyChanges::explicit,
1746 because the tokenizer gets confused on "explicit".
1747 */
1748bool QmlPropertyNode::isWritable(const Tree* tree) const
1749{
1750 if (wri != Trool_Default)
1751 return fromTrool(wri, false);
1752
1753 const PropertyNode *pn = correspondingProperty(tree);
1754 if (pn)
1755 return pn->isWritable();
1756 else {
1757 location().warning(tr("Can't determine read-only status of QML property %1; writable assumed.").arg(name()));
1758 return true;
1759 }
1760}
1761
1762const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) const
1763{
1764 const PropertyNode *pn;
1765
1766 Node* n = parent();
1767 while (n && n->subType() != Node::QmlClass)
1768 n = n->parent();
1769 if (n) {
1770 const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
1771 const ClassNode* cn = qcn->classNode();
1772 if (cn) {
1773 QStringList dotSplit = name().split(QChar('.'));
1774 pn = cn->findPropertyNode(dotSplit[0]);
1775 if (pn) {
1776 if (dotSplit.size() > 1) {
1777 // Find the C++ property corresponding to the QML property in
1778 // the property group, <group>.<property>.
1779
1780 QStringList path(extractClassName(pn->qualifiedDataType()));
1781 const Node* nn = tree->findNode(path,Class);
1782 if (nn) {
1783 const ClassNode* cn = static_cast<const ClassNode*>(nn);
1784 const PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
1785 if (pn2)
1786 return pn2; // Return the property for the QML property.
1787 else
1788 return pn; // Return the property for the QML group.
1789 }
1790 }
1791 else
1792 return pn;
1793 }
1794 else {
1795 pn = cn->findPropertyNode(dotSplit[0]);
1796 if (pn)
1797 return pn;
1798 }
1799 }
1800 }
1801
1802 return 0;
1803}
1804
1805#endif
1806
1807QT_END_NAMESPACE
1808

Warning: That file was not part of the compilation database. It may have many parsing errors.