tools/qdoc3/node.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    42 /*
    42 /*
    43   node.cpp
    43   node.cpp
    44 */
    44 */
    45 
    45 
    46 #include "node.h"
    46 #include "node.h"
       
    47 #include "tree.h"
       
    48 #include "codemarker.h"
    47 #include <qdebug.h>
    49 #include <qdebug.h>
    48 
    50 
    49 QT_BEGIN_NAMESPACE
    51 QT_BEGIN_NAMESPACE
    50 
    52 
    51 /*!
    53 /*!
    99       rel(0),
   101       rel(0),
   100       nam(name)
   102       nam(name)
   101 {
   103 {
   102     if (par)
   104     if (par)
   103         par->addChild(this);
   105         par->addChild(this);
       
   106     //uuid = QUuid::createUuid();
   104 }
   107 }
   105 
   108 
   106 /*!
   109 /*!
   107   Returns the node's URL.
   110   Returns the node's URL.
   108  */
   111  */
   152     linkPair.second = desc;
   155     linkPair.second = desc;
   153     linkMap[linkType] = linkPair;
   156     linkMap[linkType] = linkPair;
   154 }
   157 }
   155 
   158 
   156 /*!
   159 /*!
       
   160   Returns a string representing the access specifier.
       
   161  */
       
   162 QString Node::accessString() const
       
   163 {
       
   164     switch (acc) {
       
   165     case Protected:
       
   166         return "protected";
       
   167     case Private:
       
   168         return "private";
       
   169     case Public:
       
   170     default:
       
   171         break;
       
   172     }
       
   173     return "public";
       
   174 }
       
   175 
       
   176 /*!
       
   177   Extract a class name from the type \a string and return it.
       
   178  */
       
   179 QString Node::extractClassName(const QString &string) const
       
   180 {
       
   181     QString result;
       
   182     for (int i=0; i<=string.size(); ++i) {
       
   183         QChar ch;
       
   184         if (i != string.size())
       
   185             ch = string.at(i);
       
   186 
       
   187         QChar lower = ch.toLower();
       
   188         if ((lower >= QLatin1Char('a') && lower <= QLatin1Char('z')) ||
       
   189             ch.digitValue() >= 0 ||
       
   190             ch == QLatin1Char('_') ||
       
   191             ch == QLatin1Char(':')) {
       
   192             result += ch;
       
   193         }
       
   194         else if (!result.isEmpty()) {
       
   195             if (result != QLatin1String("const"))
       
   196                 return result;
       
   197             result.clear();
       
   198         }
       
   199     }
       
   200     return result;
       
   201 }
       
   202 
       
   203 /*!
       
   204   Returns a string representing the access specifier.
       
   205  */
       
   206 QString RelatedClass::accessString() const
       
   207 {
       
   208     switch (access) {
       
   209     case Node::Protected:
       
   210         return "protected";
       
   211     case Node::Private:
       
   212         return "private";
       
   213     case Node::Public:
       
   214     default:
       
   215         break;
       
   216     }
       
   217     return "public";
       
   218 }
       
   219 
       
   220 /*!
   157  */
   221  */
   158 Node::Status Node::inheritedStatus() const
   222 Node::Status Node::inheritedStatus() const
   159 {
   223 {
   160     Status parentStatus = Commendable;
   224     Status parentStatus = Commendable;
   161     if (par)
   225     if (par)
   162         parentStatus = par->inheritedStatus();
   226         parentStatus = par->inheritedStatus();
   163     return (Status)qMin((int)sta, (int)parentStatus);
   227     return (Status)qMin((int)sta, (int)parentStatus);
   164 }
   228 }
   165 
   229 
   166 /*!
   230 /*!
       
   231   Returns the thread safeness value for whatever this node
       
   232   represents. But if this node has a parent and the thread
       
   233   safeness value of the parent is the same as the thread
       
   234   safeness value of this node, what is returned is the
       
   235   value \c{UnspecifiedSafeness}. Why?
   167  */
   236  */
   168 Node::ThreadSafeness Node::threadSafeness() const
   237 Node::ThreadSafeness Node::threadSafeness() const
   169 {
   238 {
   170     if (par && saf == par->inheritedThreadSafeness())
   239     if (par && saf == par->inheritedThreadSafeness())
   171         return UnspecifiedSafeness;
   240         return UnspecifiedSafeness;
   172     return saf;
   241     return saf;
   173 }
   242 }
   174 
   243 
   175 /*!
   244 /*!
       
   245   If this node has a parent, the parent's thread safeness
       
   246   value is returned. Otherwise, this node's thread safeness
       
   247   value is returned. Why?
   176  */
   248  */
   177 Node::ThreadSafeness Node::inheritedThreadSafeness() const
   249 Node::ThreadSafeness Node::inheritedThreadSafeness() const
   178 {
   250 {
   179     if (par && saf == UnspecifiedSafeness)
   251     if (par && saf == UnspecifiedSafeness)
   180         return par->inheritedThreadSafeness();
   252         return par->inheritedThreadSafeness();
   181     return saf;
   253     return saf;
   182 }
   254 }
   183 
   255 
   184 /*!
   256 /*!
       
   257   Returns the sanitized file name without the path.
       
   258   If the the file is an html file, the html suffix
       
   259   is removed. Why?
   185  */
   260  */
   186 QString Node::fileBase() const
   261 QString Node::fileBase() const
   187 {
   262 {
   188     QString base = name();
   263     QString base = name();
   189     if (base.endsWith(".html"))
   264     if (base.endsWith(".html"))
   193     base.replace(" ", "-");
   268     base.replace(" ", "-");
   194     return base.toLower();
   269     return base.toLower();
   195 }
   270 }
   196 
   271 
   197 /*!
   272 /*!
       
   273   Returns this node's Universally Unique IDentifier.
       
   274   If its UUID has not yet been created, it is created
       
   275   first.
       
   276  */
       
   277 QUuid Node::guid() const
       
   278 {
       
   279     if (uuid.isNull())
       
   280         uuid = QUuid::createUuid();
       
   281     return uuid;
       
   282 }
       
   283 
       
   284 /*!
       
   285   Composes a string to be used as an href attribute in DITA
       
   286   XML. It is composed of the file name and the UUID separated
       
   287   by a '#'. If this node is a class node, the file name is
       
   288   taken from this node; if this node is a function node, the
       
   289   file name is taken from the parent node of this node.
       
   290  */
       
   291 QString Node::ditaXmlHref()
       
   292 {
       
   293     QString href;
       
   294     if ((type() == Function) ||
       
   295         (type() == Property) ||
       
   296         (type() == Variable)) {
       
   297         href = parent()->fileBase();
       
   298     }
       
   299     else {
       
   300         href = fileBase();
       
   301     }
       
   302     if (!href.endsWith(".xml"))
       
   303         href += ".xml";
       
   304     return href + "#" + guid();
       
   305 }
       
   306 
       
   307 /*!
   198   \class InnerNode
   308   \class InnerNode
   199  */
   309  */
   200 
   310 
   201 /*!
   311 /*!
       
   312   The inner node destructor deletes the children and removes
       
   313   this node from its related nodes.
   202  */
   314  */
   203 InnerNode::~InnerNode()
   315 InnerNode::~InnerNode()
   204 {
   316 {
   205     deleteChildren();
   317     deleteChildren();
   206     removeFromRelated();
   318     removeFromRelated();
   213   group nodes. Return the matching node or 0.
   325   group nodes. Return the matching node or 0.
   214  */
   326  */
   215 Node *InnerNode::findNode(const QString& name)
   327 Node *InnerNode::findNode(const QString& name)
   216 {
   328 {
   217     Node *node = childMap.value(name);
   329     Node *node = childMap.value(name);
   218     if (node)
   330     if (node && node->subType() != QmlPropertyGroup)
   219         return node;
   331         return node;
   220     if ((type() == Fake) && (subType() == QmlClass)) {
   332     if ((type() == Fake) && (subType() == QmlClass)) {
   221         for (int i=0; i<children.size(); ++i) {
   333         for (int i=0; i<children.size(); ++i) {
   222             Node* n = children.at(i);
   334             Node* n = children.at(i);
   223             if (n->subType() == QmlPropertyGroup) {
   335             if (n->subType() == QmlPropertyGroup) {
   340 	}
   452 	}
   341     }
   453     }
   342 }
   454 }
   343 
   455 
   344 /*!
   456 /*!
       
   457   Mark all child nodes that have no documentation as having
       
   458   private access and internal status. qdoc will then ignore
       
   459   them for documentation purposes.
   345  */
   460  */
   346 void InnerNode::makeUndocumentedChildrenInternal()
   461 void InnerNode::makeUndocumentedChildrenInternal()
   347 {
   462 {
   348     foreach (Node *child, childNodes()) {
   463     foreach (Node *child, childNodes()) {
   349         if (child->doc().isEmpty()) {
   464         if (child->doc().isEmpty()) {
   540     if (type == Class)
   655     if (type == Class)
   541         setPageType(ApiPage);
   656         setPageType(ApiPage);
   542 }
   657 }
   543 
   658 
   544 /*!
   659 /*!
       
   660   Appends an \a include file to the list of include files.
   545  */
   661  */
   546 void InnerNode::addInclude(const QString& include)
   662 void InnerNode::addInclude(const QString& include)
   547 {
   663 {
   548     inc.append(include);
   664     inc.append(include);
   549 }
   665 }
   550 
   666 
   551 /*!
   667 /*!
       
   668   Sets the list of include files to \a includes.
   552  */
   669  */
   553 void InnerNode::setIncludes(const QStringList& includes)
   670 void InnerNode::setIncludes(const QStringList& includes)
   554 {
   671 {
   555     inc = includes;
   672     inc = includes;
   556 }
   673 }
   622     enumChildren.removeAll(child);
   739     enumChildren.removeAll(child);
   623     if (child->type() == Function) {
   740     if (child->type() == Function) {
   624 	QMap<QString, Node *>::Iterator prim =
   741 	QMap<QString, Node *>::Iterator prim =
   625 		primaryFunctionMap.find(child->name());
   742 		primaryFunctionMap.find(child->name());
   626 	NodeList& secs = secondaryFunctionMap[child->name()];
   743 	NodeList& secs = secondaryFunctionMap[child->name()];
   627 	if (*prim == child) {
   744 	if (prim != primaryFunctionMap.end() && *prim == child) {
   628 	    if (secs.isEmpty()) {
   745 	    if (secs.isEmpty()) {
   629 		primaryFunctionMap.remove(child->name());
   746 		primaryFunctionMap.remove(child->name());
   630 	    }
   747 	    }
   631             else {
   748             else {
   632 		primaryFunctionMap.insert(child->name(), secs.takeFirst());
   749 		primaryFunctionMap.insert(child->name(), secs.takeFirst());
   634 	}
   751 	}
   635         else {
   752         else {
   636 	    secs.removeAll(child);
   753 	    secs.removeAll(child);
   637 	}
   754 	}
   638         QMap<QString, Node *>::Iterator ent = childMap.find( child->name() );
   755         QMap<QString, Node *>::Iterator ent = childMap.find( child->name() );
   639         if ( *ent == child )
   756         if (ent != childMap.end() && *ent == child)
   640             childMap.erase( ent );
   757             childMap.erase( ent );
   641     }
   758     }
   642     else {
   759     else {
   643 	QMap<QString, Node *>::Iterator ent = childMap.find(child->name());
   760 	QMap<QString, Node *>::Iterator ent = childMap.find(child->name());
   644 	if (*ent == child)
   761 	if (ent != childMap.end() && *ent == child)
   645 	    childMap.erase(ent);
   762 	    childMap.erase(ent);
   646     }
   763     }
   647 }
   764 }
   648 
   765 
   649 /*!
   766 /*!
   743     setPageType(ApiPage);
   860     setPageType(ApiPage);
   744 }
   861 }
   745 
   862 
   746 /*!
   863 /*!
   747   \class ClassNode
   864   \class ClassNode
       
   865   \brief This class represents a C++ class.
   748  */
   866  */
   749 
   867 
   750 /*!
   868 /*!
   751   Constructs a class node. A class node will generate an API page.
   869   Constructs a class node. A class node will generate an API page.
   752  */
   870  */
   753 ClassNode::ClassNode(InnerNode *parent, const QString& name)
   871 ClassNode::ClassNode(InnerNode *parent, const QString& name)
   754     : InnerNode(Class, parent, name)
   872     : InnerNode(Class, parent, name)
   755 {
   873 {
   756     hidden = false;
   874     hidden = false;
       
   875     abstract = false;
   757     setPageType(ApiPage);
   876     setPageType(ApiPage);
   758 }
   877 }
   759 
   878 
   760 /*!
   879 /*!
   761  */
   880  */
   762 void ClassNode::addBaseClass(Access access,
   881 void ClassNode::addBaseClass(Access access,
   763                              ClassNode *node,
   882                              ClassNode *node,
   764                              const QString &dataTypeWithTemplateArgs)
   883                              const QString &dataTypeWithTemplateArgs)
   765 {
   884 {
   766     bas.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
   885     bases.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
   767     node->der.append(RelatedClass(access, this));
   886     node->derived.append(RelatedClass(access, this));
   768 }
   887 }
   769 
   888 
   770 /*!
   889 /*!
   771  */
   890  */
   772 void ClassNode::fixBaseClasses()
   891 void ClassNode::fixBaseClasses()
   773 {
   892 {
   774     int i;
   893     int i;
   775 
       
   776     i = 0;
   894     i = 0;
   777     while (i < bas.size()) {
   895     while (i < bases.size()) {
   778         ClassNode *baseClass = bas.at(i).node;
   896         ClassNode* bc = bases.at(i).node;
   779         if (baseClass->access() == Node::Private) {
   897         if (bc->access() == Node::Private) {
   780             bas.removeAt(i);
   898             RelatedClass rc = bases.at(i);
   781 
   899             bases.removeAt(i);
   782             const QList<RelatedClass> &basesBases = baseClass->baseClasses();
   900             ignoredBases.append(rc);
   783             for (int j = basesBases.size() - 1; j >= 0; --j)
   901             const QList<RelatedClass> &bb = bc->baseClasses();
   784                 bas.insert(i, basesBases.at(j));
   902             for (int j = bb.size() - 1; j >= 0; --j)
       
   903                 bases.insert(i, bb.at(j));
   785         }
   904         }
   786         else {
   905         else {
   787             ++i;
   906             ++i;
   788         }
   907         }
   789     }
   908     }
   790 
   909 
   791     i = 0;
   910     i = 0;
   792     while (i < der.size()) {
   911     while (i < derived.size()) {
   793         ClassNode *derivedClass = der.at(i).node;
   912         ClassNode* dc = derived.at(i).node;
   794         if (derivedClass->access() == Node::Private) {
   913         if (dc->access() == Node::Private) {
   795             der.removeAt(i);
   914             derived.removeAt(i);
   796 
   915             const QList<RelatedClass> &dd = dc->derivedClasses();
   797             const QList<RelatedClass> &dersDers =
   916             for (int j = dd.size() - 1; j >= 0; --j)
   798                 derivedClass->derivedClasses();
   917                 derived.insert(i, dd.at(j));
   799             for (int j = dersDers.size() - 1; j >= 0; --j)
       
   800                 der.insert(i, dersDers.at(j));
       
   801         }
   918         }
   802         else {
   919         else {
   803             ++i;
   920             ++i;
   804         }
   921         }
   805     }
   922     }
       
   923 }
       
   924 
       
   925 /*!
       
   926   Search the child list to find the property node with the
       
   927   specified \a name.
       
   928  */
       
   929 const PropertyNode* ClassNode::findPropertyNode(const QString& name) const
       
   930 {
       
   931     const Node* n = findNode(name,Node::Property);
       
   932     return (n ? static_cast<const PropertyNode*>(n) : 0);
   806 }
   933 }
   807 
   934 
   808 /*!
   935 /*!
   809   \class FakeNode
   936   \class FakeNode
   810  */
   937  */
   834         break;
   961         break;
   835     }
   962     }
   836 }
   963 }
   837 
   964 
   838 /*!
   965 /*!
       
   966   Returns the fake node's title. This is used for the page title.
       
   967 */
       
   968 QString FakeNode::title() const
       
   969 {
       
   970     return tle;
       
   971 }
       
   972 
       
   973 /*!
   839   Returns the fake node's full title, which is usually
   974   Returns the fake node's full title, which is usually
   840   just title(), but for some SubType values is different
   975   just title(), but for some SubType values is different
   841   from title()
   976   from title()
   842  */
   977  */
   843 QString FakeNode::fullTitle() const
   978 QString FakeNode::fullTitle() const
   883 /*!
  1018 /*!
   884   \class EnumNode
  1019   \class EnumNode
   885  */
  1020  */
   886 
  1021 
   887 /*!
  1022 /*!
       
  1023   The constructor for the node representing an enum type
       
  1024   has a \a parent class and an enum type \a name.
   888  */
  1025  */
   889 EnumNode::EnumNode(InnerNode *parent, const QString& name)
  1026 EnumNode::EnumNode(InnerNode *parent, const QString& name)
   890     : LeafNode(Enum, parent, name), ft(0)
  1027     : LeafNode(Enum, parent, name), ft(0)
   891 {
  1028 {
   892 }
  1029 }
   893 
  1030 
   894 /*!
  1031 /*!
       
  1032   Add \a item to the enum type's item list.
   895  */
  1033  */
   896 void EnumNode::addItem(const EnumItem& item)
  1034 void EnumNode::addItem(const EnumItem& item)
   897 {
  1035 {
   898     itms.append(item);
  1036     itms.append(item);
   899     names.insert(item.name());
  1037     names.insert(item.name());
   900 }
  1038 }
   901 
  1039 
   902 /*!
  1040 /*!
       
  1041   Returns the access level of the enumeration item named \a name.
       
  1042   Apparently it is private if it has been omitted by qdoc's
       
  1043   omitvalue command. Otherwise it is public.
   903  */
  1044  */
   904 Node::Access EnumNode::itemAccess(const QString &name) const
  1045 Node::Access EnumNode::itemAccess(const QString &name) const
   905 {
  1046 {
   906     if (doc().omitEnumItemNames().contains(name)) {
  1047     if (doc().omitEnumItemNames().contains(name))
   907         return Private;
  1048         return Private;
   908     }
  1049     return Public;
   909     else {
       
   910         return Public;
       
   911     }
       
   912 }
  1050 }
   913 
  1051 
   914 /*!
  1052 /*!
   915   Returns the enum value associated with the enum \a name.
  1053   Returns the enum value associated with the enum \a name.
   916  */
  1054  */
  1041 {
  1179 {
  1042     // nothing.
  1180     // nothing.
  1043 }
  1181 }
  1044 
  1182 
  1045 /*!
  1183 /*!
       
  1184   Sets the \a virtualness of this function. If the \a virtualness
       
  1185   is PureVirtual, and if the parent() is a ClassNode, set the parent's
       
  1186   \e abstract flag to true.
       
  1187  */
       
  1188 void FunctionNode::setVirtualness(Virtualness virtualness)
       
  1189 {
       
  1190     vir = virtualness;
       
  1191     if ((virtualness == PureVirtual) && parent() &&
       
  1192         (parent()->type() == Node::Class))
       
  1193         parent()->setAbstract(true);
       
  1194 }
       
  1195 
       
  1196 /*!
  1046  */
  1197  */
  1047 void FunctionNode::setOverload(bool overlode)
  1198 void FunctionNode::setOverload(bool overlode)
  1048 {
  1199 {
  1049     parent()->setOverload(this, overlode);
  1200     parent()->setOverload(this, overlode);
  1050     ove = overlode;
  1201     ove = overlode;
  1130     while (p != parameters().end()) {
  1281     while (p != parameters().end()) {
  1131         names << (*p).name();
  1282         names << (*p).name();
  1132         ++p;
  1283         ++p;
  1133     }
  1284     }
  1134     return names;
  1285     return names;
       
  1286 }
       
  1287 
       
  1288 /*!
       
  1289   Returns a raw list of parameters. If \a names is true, the
       
  1290   names are included. If \a values is true, the default values
       
  1291   are included, if any are present.
       
  1292  */
       
  1293 QString FunctionNode::rawParameters(bool names, bool values) const
       
  1294 {
       
  1295     QString raw;
       
  1296     foreach (const Parameter &parameter, parameters()) {
       
  1297         raw += parameter.leftType() + parameter.rightType();
       
  1298         if (names)
       
  1299             raw += parameter.name();
       
  1300         if (values)
       
  1301             raw += parameter.defaultValue();
       
  1302     }
       
  1303     return raw;
  1135 }
  1304 }
  1136 
  1305 
  1137 /*!
  1306 /*!
  1138   Returns the list of reconstructed parameters. If \a values
  1307   Returns the list of reconstructed parameters. If \a values
  1139   is true, the default values are included, if any are present.
  1308   is true, the default values are included, if any are present.
  1182             qPrintable(name()), qPrintable(rt), qPrintable(pp.join(" ")));
  1351             qPrintable(name()), qPrintable(rt), qPrintable(pp.join(" ")));
  1183 }
  1352 }
  1184 
  1353 
  1185 /*!
  1354 /*!
  1186   \class PropertyNode
  1355   \class PropertyNode
  1187  */
  1356 
  1188 
  1357   This class describes one instance of using the Q_PROPERTY macro.
  1189 /*!
  1358  */
       
  1359 
       
  1360 /*!
       
  1361   The constructor sets the \a parent and the \a name, but
       
  1362   everything else is set to default values.
  1190  */
  1363  */
  1191 PropertyNode::PropertyNode(InnerNode *parent, const QString& name)
  1364 PropertyNode::PropertyNode(InnerNode *parent, const QString& name)
  1192     : LeafNode(Property, parent, name),
  1365     : LeafNode(Property, parent, name),
  1193       sto(Trool_Default),
  1366       sto(Trool_Default),
  1194       des(Trool_Default),
  1367       des(Trool_Default),
       
  1368       scr(Trool_Default),
       
  1369       wri(Trool_Default),
       
  1370       usr(Trool_Default),
       
  1371       cst(false),
       
  1372       fnl(false),
  1195       overrides(0)
  1373       overrides(0)
  1196 {
  1374 {
  1197 }
  1375     // nothing.
  1198 
  1376 }
  1199 /*!
  1377 
  1200  */
  1378 /*!
  1201 void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty)
  1379   Sets this property's \e {overridden from} property to
       
  1380   \a baseProperty, which indicates that this property
       
  1381   overrides \a baseProperty. To begin with, all the values
       
  1382   in this property are set to the corresponding values in
       
  1383   \a baseProperty.
       
  1384 
       
  1385   We probably should ensure that the constant and final
       
  1386   attributes are not being overridden improperly.
       
  1387  */
       
  1388 void PropertyNode::setOverriddenFrom(const PropertyNode* baseProperty)
  1202 {
  1389 {
  1203     for (int i = 0; i < NumFunctionRoles; ++i) {
  1390     for (int i = 0; i < NumFunctionRoles; ++i) {
  1204         if (funcs[i].isEmpty())
  1391         if (funcs[i].isEmpty())
  1205             funcs[i] = baseProperty->funcs[i];
  1392             funcs[i] = baseProperty->funcs[i];
  1206     }
  1393     }
  1207     if (sto == Trool_Default)
  1394     if (sto == Trool_Default)
  1208         sto = baseProperty->sto;
  1395         sto = baseProperty->sto;
  1209     if (des == Trool_Default)
  1396     if (des == Trool_Default)
  1210         des = baseProperty->des;
  1397         des = baseProperty->des;
       
  1398     if (scr == Trool_Default)
       
  1399         scr = baseProperty->scr;
       
  1400     if (wri == Trool_Default)
       
  1401         wri = baseProperty->wri;
       
  1402     if (usr == Trool_Default)
       
  1403         usr = baseProperty->usr;
  1211     overrides = baseProperty;
  1404     overrides = baseProperty;
  1212 }
  1405 }
  1213 
  1406 
  1214 /*!
  1407 /*!
  1215  */
  1408  */
  1231     else {
  1424     else {
  1232         return dt;
  1425         return dt;
  1233     }
  1426     }
  1234 }
  1427 }
  1235 
  1428 
  1236 /*!
  1429 /*! Converts the \a boolean value to an enum representation
       
  1430   of the boolean type, which includes an enum  value for the
       
  1431   \e {default value} of the item, i.e. true, false, or default.
  1237  */
  1432  */
  1238 PropertyNode::Trool PropertyNode::toTrool(bool boolean)
  1433 PropertyNode::Trool PropertyNode::toTrool(bool boolean)
  1239 {
  1434 {
  1240     return boolean ? Trool_True : Trool_False;
  1435     return boolean ? Trool_True : Trool_False;
  1241 }
  1436 }
  1242 
  1437 
  1243 /*!
  1438 /*!
       
  1439   Converts the enum \a troolean back to a boolean value.
       
  1440   If \a troolean is neither the true enum value nor the
       
  1441   false enum value, the boolean value returned is
       
  1442   \a defaultValue.
       
  1443 
       
  1444   Note that runtimeDesignabilityFunction() should be called
       
  1445   first. If that function returns the name of a function, it
       
  1446   means the function must be called at runtime to determine
       
  1447   whether the property is Designable.
  1244  */
  1448  */
  1245 bool PropertyNode::fromTrool(Trool troolean, bool defaultValue)
  1449 bool PropertyNode::fromTrool(Trool troolean, bool defaultValue)
  1246 {
  1450 {
  1247     switch (troolean) {
  1451     switch (troolean) {
  1248     case Trool_True:
  1452     case Trool_True:
  1287 QmlClassNode::QmlClassNode(InnerNode *parent,
  1491 QmlClassNode::QmlClassNode(InnerNode *parent,
  1288                            const QString& name,
  1492                            const QString& name,
  1289                            const ClassNode* cn)
  1493                            const ClassNode* cn)
  1290     : FakeNode(parent, name, QmlClass), cnode(cn)
  1494     : FakeNode(parent, name, QmlClass), cnode(cn)
  1291 {
  1495 {
  1292     setTitle((qmlOnly ? "" : "QML ") + name + " Element");
  1496     if (name.startsWith(QLatin1String("QML:")))
       
  1497         setTitle((qmlOnly ? QLatin1String("") : QLatin1String("QML ")) + name.mid(4) + QLatin1String(" Element"));
       
  1498     else
       
  1499         setTitle((qmlOnly ? QLatin1String("") : QLatin1String("QML ")) + name + QLatin1String(" Element"));
  1293 }
  1500 }
  1294 
  1501 
  1295 /*!
  1502 /*!
  1296   I made this so I could print a debug message here.
  1503   I made this so I could print a debug message here.
  1297  */
  1504  */
  1416         return false;
  1623         return false;
  1417     default:
  1624     default:
  1418         return defaultValue;
  1625         return defaultValue;
  1419     }
  1626     }
  1420 }
  1627 }
       
  1628 
       
  1629 static QString valueType(const QString& n)
       
  1630 {
       
  1631     if (n == "QPoint")
       
  1632         return "QDeclarativePointValueType";
       
  1633     if (n == "QPointF")
       
  1634         return "QDeclarativePointFValueType";
       
  1635     if (n == "QSize")
       
  1636         return "QDeclarativeSizeValueType";
       
  1637     if (n == "QSizeF")
       
  1638         return "QDeclarativeSizeFValueType";
       
  1639     if (n == "QRect")
       
  1640         return "QDeclarativeRectValueType";
       
  1641     if (n == "QRectF")
       
  1642         return "QDeclarativeRectFValueType";
       
  1643     if (n == "QVector2D")
       
  1644         return "QDeclarativeVector2DValueType";
       
  1645     if (n == "QVector3D")
       
  1646         return "QDeclarativeVector3DValueType";
       
  1647     if (n == "QVector4D")
       
  1648         return "QDeclarativeVector4DValueType";
       
  1649     if (n == "QQuaternion")
       
  1650         return "QDeclarativeQuaternionValueType";
       
  1651     if (n == "QMatrix4x4")
       
  1652         return "QDeclarativeMatrix4x4ValueType";
       
  1653     if (n == "QEasingCurve")
       
  1654         return "QDeclarativeEasingValueType";
       
  1655     if (n == "QFont")
       
  1656         return "QDeclarativeFontValueType";
       
  1657     return QString();
       
  1658 }
       
  1659 
       
  1660 /*!
       
  1661   Returns true if a QML property or attached property is
       
  1662   read-only. The algorithm for figuring this out is long
       
  1663   amd tedious and almost certainly will break. It currently
       
  1664   doesn't work for qmlproperty bool PropertyChanges::explicit,
       
  1665   because the tokenized gets confused on "explicit" .
       
  1666  */
       
  1667 bool QmlPropertyNode::isWritable(const Tree* tree) const
       
  1668 {
       
  1669     Node* n = parent();
       
  1670     while (n && n->subType() != Node::QmlClass)
       
  1671         n = n->parent();
       
  1672     if (n) {
       
  1673         const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
       
  1674         const ClassNode* cn = qcn->classNode();
       
  1675         if (cn) {
       
  1676             QStringList dotSplit = name().split(QChar('.'));
       
  1677             const PropertyNode* pn = cn->findPropertyNode(dotSplit[0]);
       
  1678             if (pn) {
       
  1679                 if (dotSplit.size() > 1) {
       
  1680                     QStringList path(extractClassName(pn->qualifiedDataType()));
       
  1681                     const Node* nn = tree->findNode(path,Class);
       
  1682                     if (nn) {
       
  1683                         const ClassNode* cn = static_cast<const ClassNode*>(nn);
       
  1684                         pn = cn->findPropertyNode(dotSplit[1]);
       
  1685                         if (pn) {
       
  1686                             return pn->isWritable();
       
  1687                         }
       
  1688                         else {
       
  1689                             const QList<RelatedClass>& bases = cn->baseClasses();
       
  1690                             if (!bases.isEmpty()) {
       
  1691                                 for (int i=0; i<bases.size(); ++i) {
       
  1692                                     const ClassNode* cn = bases[i].node;
       
  1693                                     pn = cn->findPropertyNode(dotSplit[1]);
       
  1694                                     if (pn) {
       
  1695                                         return pn->isWritable();
       
  1696                                     }
       
  1697                                 }
       
  1698                             }
       
  1699                             const QList<RelatedClass>& ignoredBases = cn->ignoredBaseClasses();
       
  1700                             if (!ignoredBases.isEmpty()) {
       
  1701                                 for (int i=0; i<ignoredBases.size(); ++i) {
       
  1702                                     const ClassNode* cn = ignoredBases[i].node;
       
  1703                                     pn = cn->findPropertyNode(dotSplit[1]);
       
  1704                                     if (pn) {
       
  1705                                         return pn->isWritable();
       
  1706                                     }
       
  1707                                 }
       
  1708                             }
       
  1709                             QString vt = valueType(cn->name());
       
  1710                             if (!vt.isEmpty()) {
       
  1711                                 QStringList path(vt);
       
  1712                                 const Node* vtn = tree->findNode(path,Class);
       
  1713                                 if (vtn) {
       
  1714                                     const ClassNode* cn = static_cast<const ClassNode*>(vtn);
       
  1715                                     pn = cn->findPropertyNode(dotSplit[1]);
       
  1716                                     if (pn) {
       
  1717                                         return pn->isWritable();
       
  1718                                     }
       
  1719                                 }
       
  1720                             }
       
  1721                         }
       
  1722                     }
       
  1723                 }
       
  1724                 else {
       
  1725                     return pn->isWritable();
       
  1726                 }
       
  1727             }
       
  1728             else {
       
  1729                 const QList<RelatedClass>& bases = cn->baseClasses();
       
  1730                 if (!bases.isEmpty()) {
       
  1731                     for (int i=0; i<bases.size(); ++i) {
       
  1732                         const ClassNode* cn = bases[i].node;
       
  1733                         pn = cn->findPropertyNode(dotSplit[0]);
       
  1734                         if (pn) {
       
  1735                             return pn->isWritable();
       
  1736                         }
       
  1737                     }
       
  1738                 }
       
  1739                 const QList<RelatedClass>& ignoredBases = cn->ignoredBaseClasses();
       
  1740                 if (!ignoredBases.isEmpty()) {
       
  1741                     for (int i=0; i<ignoredBases.size(); ++i) {
       
  1742                         const ClassNode* cn = ignoredBases[i].node;
       
  1743                         pn = cn->findPropertyNode(dotSplit[0]);
       
  1744                         if (pn) {
       
  1745                             return pn->isWritable();
       
  1746                         }
       
  1747                     }
       
  1748                 }
       
  1749                 if (isAttached()) {
       
  1750                     QString classNameAttached = cn->name() + "Attached";
       
  1751                     QStringList path(classNameAttached);
       
  1752                     const Node* nn = tree->findNode(path,Class);
       
  1753                     const ClassNode* acn = static_cast<const ClassNode*>(nn);
       
  1754                     pn = acn->findPropertyNode(dotSplit[0]);
       
  1755                     if (pn) {
       
  1756                         return pn->isWritable();
       
  1757                     }
       
  1758                 }
       
  1759             }
       
  1760         }
       
  1761     }
       
  1762     location().warning(tr("Can't determine read-only status of QML property %1; writable assumed.").arg(name()));
       
  1763     return true;
       
  1764 }
       
  1765 
  1421 #endif
  1766 #endif
  1422 
  1767 
  1423 QT_END_NAMESPACE
  1768 QT_END_NAMESPACE