source: trunk/tools/qdoc3/node.cpp@ 674

Last change on this file since 674 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 28.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the tools applications of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*
43 node.cpp
44*/
45
46#include <QtCore>
47#include "node.h"
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \class Node
53 \brief The Node class is a node in the Tree.
54
55 A Node represents a class or function or something else
56 from the source code..
57 */
58
59/*!
60 When this Node is destroyed, if it has a parent Node, it
61 removes itself from the parent node's child list.
62 */
63Node::~Node()
64{
65 if (par)
66 par->removeChild(this);
67 if (rel)
68 rel->removeRelated(this);
69}
70
71/*!
72 Sets this Node's Doc to \a doc. If \a replace is false and
73 this Node already has a Doc, a warning is reported that the
74 Doc is being overridden, and it reports where the previous
75 Doc was found. If \a replace is true, the Doc is replaced
76 silently.
77 */
78void Node::setDoc(const Doc& doc, bool replace)
79{
80 if (!d.isEmpty() && !replace) {
81 doc.location().warning(tr("Overrides a previous doc"));
82 d.location().warning(tr("(The previous doc is here)"));
83 }
84 d = doc;
85}
86
87/*!
88 */
89Node::Node(Type type, InnerNode *parent, const QString& name)
90 : typ(type),
91 acc(Public),
92 sta(Commendable),
93 saf(UnspecifiedSafeness),
94 par(parent),
95 rel(0),
96 nam(name)
97{
98 if (par)
99 par->addChild(this);
100}
101
102/*!
103 */
104QString Node::url() const
105{
106 return u;
107}
108
109/*!
110 */
111void Node::setUrl(const QString &url)
112{
113 u = url;
114}
115
116/*!
117 */
118void Node::setRelates(InnerNode *pseudoParent)
119{
120 if (rel)
121 rel->removeRelated(this);
122 rel = pseudoParent;
123 pseudoParent->related.append(this);
124}
125
126/*!
127 This function creates a pair that describes a link.
128 The pair is composed from \a link and \a desc. The
129 \a linkType is the map index the pair is filed under.
130 */
131void Node::setLink(LinkType linkType, const QString &link, const QString &desc)
132{
133 QPair<QString,QString> linkPair;
134 linkPair.first = link;
135 linkPair.second = desc;
136 linkMap[linkType] = linkPair;
137}
138
139/*!
140 */
141Node::Status Node::inheritedStatus() const
142{
143 Status parentStatus = Commendable;
144 if (par)
145 parentStatus = par->inheritedStatus();
146 return (Status)qMin((int)sta, (int)parentStatus);
147}
148
149/*!
150 */
151Node::ThreadSafeness Node::threadSafeness() const
152{
153 if (par && saf == par->inheritedThreadSafeness())
154 return UnspecifiedSafeness;
155 return saf;
156}
157
158/*!
159 */
160Node::ThreadSafeness Node::inheritedThreadSafeness() const
161{
162 if (par && saf == UnspecifiedSafeness)
163 return par->inheritedThreadSafeness();
164 return saf;
165}
166
167/*!
168 */
169QString Node::fileBase() const
170{
171 QString base = name();
172 if (base.endsWith(".html"))
173 base.chop(5);
174 base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
175 base = base.trimmed();
176 base.replace(" ", "-");
177 return base.toLower();
178}
179
180/*!
181 \class InnerNode
182 */
183
184/*!
185 */
186InnerNode::~InnerNode()
187{
188 deleteChildren();
189 removeFromRelated();
190}
191
192/*!
193 */
194Node *InnerNode::findNode(const QString& name)
195{
196 Node *node = childMap.value(name);
197 if (node)
198 return node;
199 return primaryFunctionMap.value(name);
200}
201
202/*!
203 */
204Node *InnerNode::findNode(const QString& name, Type type)
205{
206 if (type == Function) {
207 return primaryFunctionMap.value(name);
208 }
209 else {
210 Node *node = childMap.value(name);
211 if (node && node->type() == type) {
212 return node;
213 }
214 else {
215 return 0;
216 }
217 }
218}
219
220/*!
221 Find the function node in this node for the function named \a name.
222 */
223FunctionNode *InnerNode::findFunctionNode(const QString& name)
224{
225 return static_cast<FunctionNode *>(primaryFunctionMap.value(name));
226}
227
228/*!
229 Find the function node in this node that has the same name as \a clone.
230 */
231FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone)
232{
233 QMap<QString, Node *>::ConstIterator c =
234 primaryFunctionMap.find(clone->name());
235 if (c != primaryFunctionMap.end()) {
236 if (isSameSignature(clone, (FunctionNode *) *c)) {
237 return (FunctionNode *) *c;
238 }
239 else if (secondaryFunctionMap.contains(clone->name())) {
240 const NodeList& secs = secondaryFunctionMap[clone->name()];
241 NodeList::ConstIterator s = secs.begin();
242 while (s != secs.end()) {
243 if (isSameSignature(clone, (FunctionNode *) *s))
244 return (FunctionNode *) *s;
245 ++s;
246 }
247 }
248 }
249 return 0;
250}
251
252/*!
253 Returns the list of keys from the primary function map.
254 */
255QStringList InnerNode::primaryKeys()
256{
257 QStringList t;
258 QMap<QString, Node*>::iterator i = primaryFunctionMap.begin();
259 while (i != primaryFunctionMap.end()) {
260 t.append(i.key());
261 ++i;
262 }
263 return t;
264}
265
266/*!
267 Returns the list of keys from the secondary function map.
268 */
269QStringList InnerNode::secondaryKeys()
270{
271 QStringList t;
272 QMap<QString, NodeList>::iterator i = secondaryFunctionMap.begin();
273 while (i != secondaryFunctionMap.end()) {
274 t.append(i.key());
275 ++i;
276 }
277 return t;
278}
279
280/*!
281 */
282void InnerNode::setOverload(const FunctionNode *func, bool overlode)
283{
284 Node *node = (Node *) func;
285 Node *&primary = primaryFunctionMap[func->name()];
286
287 if (secondaryFunctionMap.contains(func->name())) {
288 NodeList& secs = secondaryFunctionMap[func->name()];
289 if (overlode) {
290 if (primary == node) {
291 primary = secs.first();
292 secs.erase(secs.begin());
293 secs.append(node);
294 }
295 else {
296 secs.removeAll(node);
297 secs.append(node);
298 }
299 }
300 else {
301 if (primary != node) {
302 secs.removeAll(node);
303 secs.prepend(primary);
304 primary = node;
305 }
306 }
307 }
308}
309
310/*!
311 */
312void InnerNode::makeUndocumentedChildrenInternal()
313{
314 foreach (Node *child, childNodes()) {
315 if (child->doc().isEmpty()) {
316 child->setAccess(Node::Private);
317 child->setStatus(Node::Internal);
318 }
319 }
320}
321
322/*!
323 */
324void InnerNode::normalizeOverloads()
325{
326 QMap<QString, Node *>::Iterator p1 = primaryFunctionMap.begin();
327 while (p1 != primaryFunctionMap.end()) {
328 FunctionNode *primaryFunc = (FunctionNode *) *p1;
329 if (secondaryFunctionMap.contains(primaryFunc->name()) &&
330 (primaryFunc->status() != Commendable ||
331 primaryFunc->access() == Private)) {
332
333 NodeList& secs = secondaryFunctionMap[primaryFunc->name()];
334 NodeList::ConstIterator s = secs.begin();
335 while (s != secs.end()) {
336 FunctionNode *secondaryFunc = (FunctionNode *) *s;
337
338 // Any non-obsolete, non-compatibility, non-private functions
339 // (i.e, visible functions) are preferable to the primary
340 // function.
341
342 if (secondaryFunc->status() == Commendable &&
343 secondaryFunc->access() != Private) {
344
345 *p1 = secondaryFunc;
346 int index = secondaryFunctionMap[primaryFunc->name()].indexOf(secondaryFunc);
347 secondaryFunctionMap[primaryFunc->name()].replace(index, primaryFunc);
348 break;
349 }
350 ++s;
351 }
352 }
353 ++p1;
354 }
355
356 QMap<QString, Node *>::ConstIterator p = primaryFunctionMap.begin();
357 while (p != primaryFunctionMap.end()) {
358 FunctionNode *primaryFunc = (FunctionNode *) *p;
359 if (primaryFunc->isOverload())
360 primaryFunc->ove = false;
361 if (secondaryFunctionMap.contains(primaryFunc->name())) {
362 NodeList& secs = secondaryFunctionMap[primaryFunc->name()];
363 NodeList::ConstIterator s = secs.begin();
364 while (s != secs.end()) {
365 FunctionNode *secondaryFunc = (FunctionNode *) *s;
366 if (!secondaryFunc->isOverload())
367 secondaryFunc->ove = true;
368 ++s;
369 }
370 }
371 ++p;
372 }
373
374 NodeList::ConstIterator c = childNodes().begin();
375 while (c != childNodes().end()) {
376 if ((*c)->isInnerNode())
377 ((InnerNode *) *c)->normalizeOverloads();
378 ++c;
379 }
380}
381
382/*!
383 */
384void InnerNode::removeFromRelated()
385{
386 while (!related.isEmpty()) {
387 Node *p = static_cast<Node *>(related.takeFirst());
388
389 if (p != 0 && p->relates() == this) p->clearRelated();
390 }
391}
392
393/*!
394 */
395void InnerNode::deleteChildren()
396{
397 qDeleteAll(children);
398}
399
400/*!
401 Returns true.
402 */
403bool InnerNode::isInnerNode() const
404{
405 return true;
406}
407
408/*!
409 */
410const Node *InnerNode::findNode(const QString& name) const
411{
412 InnerNode *that = (InnerNode *) this;
413 return that->findNode(name);
414}
415
416/*!
417 */
418const Node *InnerNode::findNode(const QString& name, Type type) const
419{
420 InnerNode *that = (InnerNode *) this;
421 return that->findNode(name, type);
422}
423
424/*!
425 Find the function node in this node that has the given \a name.
426 */
427const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
428{
429 InnerNode *that = (InnerNode *) this;
430 return that->findFunctionNode(name);
431}
432
433/*!
434 Find the function node in this node that has the same name as \a clone.
435 */
436const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
437{
438 InnerNode *that = (InnerNode *) this;
439 return that->findFunctionNode(clone);
440}
441
442/*!
443 */
444const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
445{
446 foreach (const Node *node, enumChildren) {
447 const EnumNode *enume = static_cast<const EnumNode *>(node);
448 if (enume->hasItem(enumValue))
449 return enume;
450 }
451 return 0;
452}
453
454/*!
455 */
456int InnerNode::overloadNumber(const FunctionNode *func) const
457{
458 Node *node = (Node *) func;
459 if (primaryFunctionMap[func->name()] == node) {
460 return 1;
461 }
462 else {
463 return secondaryFunctionMap[func->name()].indexOf(node) + 2;
464 }
465}
466
467/*!
468 */
469int InnerNode::numOverloads(const QString& funcName) const
470{
471 if (primaryFunctionMap.contains(funcName)) {
472 return secondaryFunctionMap[funcName].count() + 1;
473 }
474 else {
475 return 0;
476 }
477}
478
479/*!
480 */
481NodeList InnerNode::overloads(const QString &funcName) const
482{
483 NodeList result;
484 Node *primary = primaryFunctionMap.value(funcName);
485 if (primary) {
486 result << primary;
487 result += secondaryFunctionMap[funcName];
488 }
489 return result;
490}
491
492/*!
493 */
494InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name)
495 : Node(type, parent, name)
496{
497}
498
499/*!
500 */
501void InnerNode::addInclude(const QString& include)
502{
503 inc.append(include);
504}
505
506/*!
507 */
508void InnerNode::setIncludes(const QStringList& includes)
509{
510 inc = includes;
511}
512
513/*!
514 f1 is always the clone
515 */
516bool InnerNode::isSameSignature(const FunctionNode *f1, const FunctionNode *f2)
517{
518 if (f1->parameters().count() != f2->parameters().count())
519 return false;
520 if (f1->isConst() != f2->isConst())
521 return false;
522
523 QList<Parameter>::ConstIterator p1 = f1->parameters().begin();
524 QList<Parameter>::ConstIterator p2 = f2->parameters().begin();
525 while (p2 != f2->parameters().end()) {
526 if ((*p1).hasType() && (*p2).hasType()) {
527 if ((*p1).rightType() != (*p2).rightType())
528 return false;
529
530 QString t1 = p1->leftType();
531 QString t2 = p2->leftType();
532
533 if (t1.length() < t2.length())
534 qSwap(t1, t2);
535
536 /*
537 ### hack for C++ to handle superfluous
538 "Foo::" prefixes gracefully
539 */
540 if (t1 != t2 && t1 != (f2->parent()->name() + "::" + t2))
541 return false;
542 }
543 ++p1;
544 ++p2;
545 }
546 return true;
547}
548
549/*!
550 */
551void InnerNode::addChild(Node *child)
552{
553 children.append(child);
554 if ((child->type() == Function) || (child->type() == QmlMethod)) {
555 FunctionNode *func = (FunctionNode *) child;
556 if (!primaryFunctionMap.contains(func->name())) {
557 primaryFunctionMap.insert(func->name(), func);
558 }
559 else {
560 NodeList &secs = secondaryFunctionMap[func->name()];
561 secs.append(func);
562 }
563 }
564 else {
565 if (child->type() == Enum)
566 enumChildren.append(child);
567 childMap.insert(child->name(), child);
568 }
569}
570
571/*!
572 */
573void InnerNode::removeChild(Node *child)
574{
575 children.removeAll(child);
576 enumChildren.removeAll(child);
577 if (child->type() == Function) {
578 QMap<QString, Node *>::Iterator prim =
579 primaryFunctionMap.find(child->name());
580 NodeList& secs = secondaryFunctionMap[child->name()];
581 if (*prim == child) {
582 if (secs.isEmpty()) {
583 primaryFunctionMap.remove(child->name());
584 }
585 else {
586 primaryFunctionMap.insert(child->name(), secs.takeFirst());
587 }
588 }
589 else {
590 secs.removeAll(child);
591 }
592 QMap<QString, Node *>::Iterator ent = childMap.find( child->name() );
593 if ( *ent == child )
594 childMap.erase( ent );
595 }
596 else {
597 QMap<QString, Node *>::Iterator ent = childMap.find(child->name());
598 if (*ent == child)
599 childMap.erase(ent);
600 }
601}
602
603/*!
604 Find the module (QtCore, QtGui, etc.) to which the class belongs.
605 We do this by obtaining the full path to the header file's location
606 and examine everything between "src/" and the filename. This is
607 semi-dirty because we are assuming a particular directory structure.
608
609 This function is only really useful if the class's module has not
610 been defined in the header file with a QT_MODULE macro or with an
611 \inmodule command in the documentation.
612*/
613QString Node::moduleName() const
614{
615 if (!mod.isEmpty())
616 return mod;
617
618 QString path = location().filePath();
619 QString pattern = QString("src") + QDir::separator();
620 int start = path.lastIndexOf(pattern);
621
622 if (start == -1)
623 return "";
624
625 QString moduleDir = path.mid(start + pattern.size());
626 int finish = moduleDir.indexOf(QDir::separator());
627
628 if (finish == -1)
629 return "";
630
631 QString moduleName = moduleDir.left(finish);
632
633 if (moduleName == "corelib")
634 return "QtCore";
635 else if (moduleName == "uitools")
636 return "QtUiTools";
637 else if (moduleName == "gui")
638 return "QtGui";
639 else if (moduleName == "network")
640 return "QtNetwork";
641 else if (moduleName == "opengl")
642 return "QtOpenGL";
643 else if (moduleName == "qt3support")
644 return "Qt3Support";
645 else if (moduleName == "svg")
646 return "QtSvg";
647 else if (moduleName == "sql")
648 return "QtSql";
649 else if (moduleName == "qtestlib")
650 return "QtTest";
651 else if (moduleDir.contains("webkit"))
652 return "QtWebKit";
653 else if (moduleName == "xml")
654 return "QtXml";
655 else
656 return "";
657}
658
659/*!
660 */
661void InnerNode::removeRelated(Node *pseudoChild)
662{
663 related.removeAll(pseudoChild);
664}
665
666/*!
667 \class LeafNode
668 */
669
670/*!
671 Returns false because this is a LeafNode.
672 */
673bool LeafNode::isInnerNode() const
674{
675 return false;
676}
677
678/*!
679 */
680LeafNode::LeafNode(Type type, InnerNode *parent, const QString& name)
681 : Node(type, parent, name)
682{
683}
684
685/*!
686 \class NamespaceNode
687 */
688
689/*!
690 */
691NamespaceNode::NamespaceNode(InnerNode *parent, const QString& name)
692 : InnerNode(Namespace, parent, name)
693{
694}
695
696/*!
697 \class ClassNode
698 */
699
700/*!
701 */
702ClassNode::ClassNode(InnerNode *parent, const QString& name)
703 : InnerNode(Class, parent, name)
704{
705 hidden = false;
706}
707
708/*!
709 */
710void ClassNode::addBaseClass(Access access,
711 ClassNode *node,
712 const QString &dataTypeWithTemplateArgs)
713{
714 bas.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
715 node->der.append(RelatedClass(access, this));
716}
717
718/*!
719 */
720void ClassNode::fixBaseClasses()
721{
722 int i;
723
724 i = 0;
725 while (i < bas.size()) {
726 ClassNode *baseClass = bas.at(i).node;
727 if (baseClass->access() == Node::Private) {
728 bas.removeAt(i);
729
730 const QList<RelatedClass> &basesBases = baseClass->baseClasses();
731 for (int j = basesBases.size() - 1; j >= 0; --j)
732 bas.insert(i, basesBases.at(j));
733 }
734 else {
735 ++i;
736 }
737 }
738
739 i = 0;
740 while (i < der.size()) {
741 ClassNode *derivedClass = der.at(i).node;
742 if (derivedClass->access() == Node::Private) {
743 der.removeAt(i);
744
745 const QList<RelatedClass> &dersDers =
746 derivedClass->derivedClasses();
747 for (int j = dersDers.size() - 1; j >= 0; --j)
748 der.insert(i, dersDers.at(j));
749 }
750 else {
751 ++i;
752 }
753 }
754}
755
756/*!
757 \class FakeNode
758 */
759
760/*!
761 The type of a FakeNode is Fake, and it has a \a subtype,
762 which specifies the type of FakeNode.
763 */
764FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subtype)
765 : InnerNode(Fake, parent, name), sub(subtype)
766{
767}
768
769/*!
770 Returns the fake node's full title, which is usually
771 just title(), but for some SubType values is different
772 from title()
773 */
774QString FakeNode::fullTitle() const
775{
776 if (sub == File) {
777 if (title().isEmpty())
778 return name().mid(name().lastIndexOf('/') + 1) + " Example File";
779 else
780 return title();
781 }
782 else if (sub == Image) {
783 if (title().isEmpty())
784 return name().mid(name().lastIndexOf('/') + 1) + " Image File";
785 else
786 return title();
787 }
788 else if (sub == HeaderFile) {
789 if (title().isEmpty())
790 return name();
791 else
792 return name() + " - " + title();
793 }
794 else {
795 return title();
796 }
797}
798
799/*!
800 Returns the subtitle.
801 */
802QString FakeNode::subTitle() const
803{
804 if (!stle.isEmpty())
805 return stle;
806
807 if ((sub == File) || (sub == Image)) {
808 if (title().isEmpty() && name().contains("/"))
809 return name();
810 }
811 return QString();
812}
813
814/*!
815 \class EnumNode
816 */
817
818/*!
819 */
820EnumNode::EnumNode(InnerNode *parent, const QString& name)
821 : LeafNode(Enum, parent, name), ft(0)
822{
823}
824
825/*!
826 */
827void EnumNode::addItem(const EnumItem& item)
828{
829 itms.append(item);
830 names.insert(item.name());
831}
832
833/*!
834 */
835Node::Access EnumNode::itemAccess(const QString &name) const
836{
837 if (doc().omitEnumItemNames().contains(name)) {
838 return Private;
839 }
840 else {
841 return Public;
842 }
843}
844
845/*!
846 Returns the enum value associated with the enum \a name.
847 */
848QString EnumNode::itemValue(const QString &name) const
849{
850 foreach (const EnumItem &item, itms) {
851 if (item.name() == name)
852 return item.value();
853 }
854 return QString();
855}
856
857/*!
858 \class TypedefNode
859 */
860
861/*!
862 */
863TypedefNode::TypedefNode(InnerNode *parent, const QString& name)
864 : LeafNode(Typedef, parent, name), ae(0)
865{
866}
867
868/*!
869 */
870void TypedefNode::setAssociatedEnum(const EnumNode *enume)
871{
872 ae = enume;
873}
874
875/*!
876 \class Parameter
877 \brief The class Parameter contains one parameter.
878
879 A parameter can be a function parameter or a macro
880 parameter.
881 */
882
883/*!
884 Constructs this parameter from the left and right types
885 \a leftType and rightType, the parameter \a name, and the
886 \a defaultValue. In practice, \a rightType is not used,
887 and I don't know what is was meant for.
888 */
889Parameter::Parameter(const QString& leftType,
890 const QString& rightType,
891 const QString& name,
892 const QString& defaultValue)
893 : lef(leftType), rig(rightType), nam(name), def(defaultValue)
894{
895}
896
897/*!
898 The standard copy constructor copies the strings from \a p.
899 */
900Parameter::Parameter(const Parameter& p)
901 : lef(p.lef), rig(p.rig), nam(p.nam), def(p.def)
902{
903}
904
905/*!
906 Assigning Parameter \a p to this Parameter copies the
907 strings across.
908 */
909Parameter& Parameter::operator=(const Parameter& p)
910{
911 lef = p.lef;
912 rig = p.rig;
913 nam = p.nam;
914 def = p.def;
915 return *this;
916}
917
918/*!
919 Reconstructs the text describing the parameter and
920 returns it. If \a value is true, the default value
921 will be included, if there is one.
922 */
923QString Parameter::reconstruct(bool value) const
924{
925 QString p = lef + rig;
926 if (!p.endsWith(QChar('*')) && !p.endsWith(QChar('&')) && !p.endsWith(QChar(' ')))
927 p += " ";
928 p += nam;
929 if (value)
930 p += def;
931 return p;
932}
933
934
935/*!
936 \class FunctionNode
937 */
938
939/*!
940 Construct a function node for a C++ function. It's parent
941 is \a parent, and it's name is \a name.
942 */
943FunctionNode::FunctionNode(InnerNode *parent, const QString& name)
944 : LeafNode(Function, parent, name),
945 met(Plain),
946 vir(NonVirtual),
947 con(false),
948 sta(false),
949 ove(false),
950 att(false),
951 rf(0),
952 ap(0)
953{
954 // nothing.
955}
956
957/*!
958 Construct a function node for a QML method or signal, specified
959 by \a type. It's parent is \a parent, and it's name is \a name.
960 If \a attached is true, it is an attached method or signal.
961 */
962FunctionNode::FunctionNode(Type type, InnerNode *parent, const QString& name, bool attached)
963 : LeafNode(type, parent, name),
964 met(Plain),
965 vir(NonVirtual),
966 con(false),
967 sta(false),
968 ove(false),
969 att(attached),
970 rf(0),
971 ap(0)
972{
973 // nothing.
974}
975
976/*!
977 */
978void FunctionNode::setOverload(bool overlode)
979{
980 parent()->setOverload(this, overlode);
981 ove = overlode;
982}
983
984/*!
985 Sets the function node's reimplementation flag to \a r.
986 When \a r is true, it is supposed to mean that this function
987 is a reimplementation of a virtual function in a base class,
988 but it really just means the \e reimp command was seen in the
989 qdoc comment.
990 */
991void FunctionNode::setReimp(bool r)
992{
993 reimp = r;
994}
995
996/*!
997 */
998void FunctionNode::addParameter(const Parameter& parameter)
999{
1000 params.append(parameter);
1001}
1002
1003/*!
1004 */
1005void FunctionNode::borrowParameterNames(const FunctionNode *source)
1006{
1007 QList<Parameter>::Iterator t = params.begin();
1008 QList<Parameter>::ConstIterator s = source->params.begin();
1009 while (s != source->params.end() && t != params.end()) {
1010 if (!(*s).name().isEmpty())
1011 (*t).setName((*s).name());
1012 ++s;
1013 ++t;
1014 }
1015}
1016
1017/*!
1018 If this function is a reimplementation, \a from points
1019 to the FunctionNode of the function being reimplemented.
1020 */
1021void FunctionNode::setReimplementedFrom(FunctionNode *from)
1022{
1023 rf = from;
1024 from->rb.append(this);
1025}
1026
1027/*!
1028 Sets the "associated" property to \a property. The function
1029 might be the setter or getter for a property, for example.
1030 */
1031void FunctionNode::setAssociatedProperty(PropertyNode *property)
1032{
1033 ap = property;
1034}
1035
1036/*!
1037 Returns the overload number for this function obtained
1038 from the parent.
1039 */
1040int FunctionNode::overloadNumber() const
1041{
1042 return parent()->overloadNumber(this);
1043}
1044
1045/*!
1046 Returns the number of times this function name has been
1047 overloaded, obtained from the parent.
1048 */
1049int FunctionNode::numOverloads() const
1050{
1051 return parent()->numOverloads(name());
1052}
1053
1054/*!
1055 Returns the list of parameter names.
1056 */
1057QStringList FunctionNode::parameterNames() const
1058{
1059 QStringList names;
1060 QList<Parameter>::ConstIterator p = parameters().begin();
1061 while (p != parameters().end()) {
1062 names << (*p).name();
1063 ++p;
1064 }
1065 return names;
1066}
1067
1068/*!
1069 Returns the list of reconstructed parameters. If \a values
1070 is true, the default values are included, if any are present.
1071 */
1072QStringList FunctionNode::reconstructParams(bool values) const
1073{
1074 QStringList params;
1075 QList<Parameter>::ConstIterator p = parameters().begin();
1076 while (p != parameters().end()) {
1077 params << (*p).reconstruct(values);
1078 ++p;
1079 }
1080 return params;
1081}
1082
1083/*!
1084 Reconstructs and returns the function's signature. If \a values
1085 is true, the default values of the parameters are included, if
1086 present.
1087 */
1088QString FunctionNode::signature(bool values) const
1089{
1090 QString s;
1091 if (!returnType().isEmpty())
1092 s = returnType() + " ";
1093 s += name() + "(";
1094 QStringList params = reconstructParams(values);
1095 int p = params.size();
1096 if (p > 0) {
1097 for (int i=0; i<p; i++) {
1098 s += params[i];
1099 if (i < (p-1))
1100 s += ", ";
1101 }
1102 }
1103 s += ")";
1104 return s;
1105}
1106
1107/*!
1108 Print some debugging stuff.
1109 */
1110void FunctionNode::debug() const
1111{
1112 qDebug() << "QML METHOD" << name() << "rt" << rt << "pp" << pp;
1113}
1114
1115/*!
1116 \class PropertyNode
1117 */
1118
1119/*!
1120 */
1121PropertyNode::PropertyNode(InnerNode *parent, const QString& name)
1122 : LeafNode(Property, parent, name),
1123 sto(Trool_Default),
1124 des(Trool_Default),
1125 overrides(0)
1126{
1127}
1128
1129/*!
1130 */
1131void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty)
1132{
1133 for (int i = 0; i < NumFunctionRoles; ++i) {
1134 if (funcs[i].isEmpty())
1135 funcs[i] = baseProperty->funcs[i];
1136 }
1137 if (sto == Trool_Default)
1138 sto = baseProperty->sto;
1139 if (des == Trool_Default)
1140 des = baseProperty->des;
1141 overrides = baseProperty;
1142}
1143
1144/*!
1145 */
1146QString PropertyNode::qualifiedDataType() const
1147{
1148 if (setters().isEmpty() && resetters().isEmpty()) {
1149 if (dt.contains("*") || dt.contains("&")) {
1150 // 'QWidget *' becomes 'QWidget *' const
1151 return dt + " const";
1152 }
1153 else {
1154 /*
1155 'int' becomes 'const int' ('int const' is
1156 correct C++, but looks wrong)
1157 */
1158 return "const " + dt;
1159 }
1160 }
1161 else {
1162 return dt;
1163 }
1164}
1165
1166/*!
1167 */
1168PropertyNode::Trool PropertyNode::toTrool(bool boolean)
1169{
1170 return boolean ? Trool_True : Trool_False;
1171}
1172
1173/*!
1174 */
1175bool PropertyNode::fromTrool(Trool troolean, bool defaultValue)
1176{
1177 switch (troolean) {
1178 case Trool_True:
1179 return true;
1180 case Trool_False:
1181 return false;
1182 default:
1183 return defaultValue;
1184 }
1185}
1186
1187/*!
1188 \class TargetNode
1189 */
1190
1191/*!
1192 */
1193TargetNode::TargetNode(InnerNode *parent, const QString& name)
1194 : LeafNode(Target, parent, name)
1195{
1196}
1197
1198/*!
1199 Returns false because this is a TargetNode.
1200 */
1201bool TargetNode::isInnerNode() const
1202{
1203 return false;
1204}
1205
1206#ifdef QDOC_QML
1207bool QmlClassNode::qmlOnly = false;
1208
1209/*!
1210 Constructor for the Qml class node.
1211 */
1212QmlClassNode::QmlClassNode(InnerNode *parent,
1213 const QString& name,
1214 const ClassNode* cn)
1215 : FakeNode(parent, name, QmlClass), cnode(cn)
1216{
1217 setTitle((qmlOnly ? "" : "QML ") + name + " Element Reference");
1218}
1219
1220/*!
1221 The base file name for this kind of node has "qml_"
1222 prepended to it.
1223
1224 But not yet. Still testing.
1225 */
1226QString QmlClassNode::fileBase() const
1227{
1228#if 0
1229 if (Node::fileBase() == "item")
1230 qDebug() << "FILEBASE: qmlitem" << name();
1231 return "qml_" + Node::fileBase();
1232#endif
1233 return Node::fileBase();
1234}
1235
1236/*!
1237 Constructor for the Qml property group node. \a parent is
1238 always a QmlClassNode.
1239 */
1240QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent,
1241 const QString& name,
1242 bool attached)
1243 : FakeNode(parent, name, QmlPropertyGroup),
1244 isdefault(false),
1245 att(attached)
1246{
1247 // nothing.
1248}
1249
1250/*!
1251 Constructor for the QML property node.
1252 */
1253QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent,
1254 const QString& name,
1255 const QString& type,
1256 bool attached)
1257 : LeafNode(QmlProperty, parent, name),
1258 dt(type),
1259 sto(Trool_Default),
1260 des(Trool_Default),
1261 att(attached)
1262{
1263 // nothing.
1264}
1265
1266/*!
1267 I don't know what this is.
1268 */
1269QmlPropertyNode::Trool QmlPropertyNode::toTrool(bool boolean)
1270{
1271 return boolean ? Trool_True : Trool_False;
1272}
1273
1274/*!
1275 I don't know what this is either.
1276 */
1277bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue)
1278{
1279 switch (troolean) {
1280 case Trool_True:
1281 return true;
1282 case Trool_False:
1283 return false;
1284 default:
1285 return defaultValue;
1286 }
1287}
1288#endif
1289
1290QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.