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(); |
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()); |
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 */ |
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 */ |
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 ¶meter, 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 |