Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmlpropertynode.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5
6#include "classnode.h"
7#include "enumnode.h"
8#include "genustypes.h"
9#include "propertynode.h"
10#include "qdocdatabase.h"
11#include "utilities.h"
12
13#include <utility>
14
15
17
18using namespace Qt::StringLiterals;
19
20/*!
21 Constructor for the QML property node.
22 */
23QmlPropertyNode::QmlPropertyNode(Aggregate *parent, const QString &name, QString type,
24 bool attached)
25 : Node(NodeType::QmlProperty, parent, name),
27 m_attached(attached)
28{
29 if (m_type == "alias")
30 m_isAlias = true;
31 if (name.startsWith("__"))
33 // Set the default prefix for enumerators
34 m_nativeEnum.setPrefix(parent->name());
35}
36
37/*!
38 Sets the data type of this property to \a dataType,
39 preserving the list property modifier if one is set
40 already.
41*/
42void QmlPropertyNode::setDataType(const QString &dataType)
43{
44 m_type = dataType;
45 // Re-apply list modifier if needed
46 if (auto is_list = m_isList; is_list == FlagValueTrue) {
47 m_isList = FlagValueDefault;
48 setIsList(true);
49 }
50}
51
52/*!
53 \fn bool QmlPropertyNode::isReadOnly() const
54
55 Returns \c true if this QML property node is marked as a
56 read-only property.
57*/
58
59/*!
60 Marks this property as a list if \a isList is \c true.
61 The \c m_type member of a list property is wrapped with
62 \c {list<>}.
63*/
64void QmlPropertyNode::setIsList(bool isList)
65{
66 if (m_isList != FlagValueDefault)
67 return;
68
69 if ((m_isList = toFlagValue(isList)))
70 m_type = "list<%1>"_L1.arg(m_type);
71}
72
73/*!
74 Returns \c true if this QML property or attached property is
75 read-only. If the read-only status is not set explicitly
76 using the \\readonly command, QDoc attempts to resolve it
77 from the associated C++ class instantiated by the QML type
78 that this property belongs to.
79
80 \note Depending on how the QML type is implemented, this
81 information may not be available to QDoc. If so, add a debug
82 line but do not treat it as a warning.
83 */
85{
86 if (m_readOnly != FlagValueDefault)
87 return fromFlagValue(m_readOnly, false);
88
89 // Find the parent QML type node
90 auto *parent{this->parent()};
91 while (parent && !(parent->isQmlType()))
92 parent = parent->parent();
93
94 bool readonly{false};
95 if (auto qcn = static_cast<QmlTypeNode *>(parent); qcn && qcn->classNode()) {
96 if (auto propertyNode = findCorrespondingCppProperty(); propertyNode)
97 readonly = !propertyNode->isWritable();
98 else
99 qCDebug(lcQdoc).nospace()
100 << qPrintable(defLocation().toString())
101 << ": Automatic resolution of QML property attributes failed for "
102 << name()
103 << " (Q_PROPERTY not found in the C++ class hierarchy known to QDoc. "
104 << "Likely, the type is replaced with a private implementation.)";
105 }
106 markReadOnly(readonly);
107 return readonly;
108}
109
110/*!
111 Returns \c true if this QML property is marked with \required or the
112 corresponding C++ property uses the REQUIRED keyword.
113
114 \note Like isReadOnly(), this method resolves and caches the attribute
115 from the associated C++ property on first call.
116*/
118{
119 if (m_required != FlagValueDefault)
120 return fromFlagValue(m_required, false);
121
122 PropertyNode *pn = findCorrespondingCppProperty();
123 bool required = pn != nullptr && pn->isRequired();
124 markRequired(required);
125 return required;
126}
127
128/*!
129 \internal
130
131 \fn bool QmlPropertyNode::isReadOnly() const
132 \fn bool QmlPropertyNode::isRequired() const
133
134 Const overloads that delegate to the resolving non-const versions
135 when the attribute hasn't been cached yet. This ensures consistent
136 behavior regardless of const-qualification at the call site.
137*/
139{
140 if (m_readOnly != FlagValueDefault)
141 return fromFlagValue(m_readOnly, false);
142
143 return const_cast<QmlPropertyNode *>(this)->isReadOnly();
144}
145
147{
148 if (m_required != FlagValueDefault)
149 return fromFlagValue(m_required, false);
150
151 return const_cast<QmlPropertyNode *>(this)->isRequired();
152}
153
154/*!
155 Returns a list of hint strings for this QML property, such as
156 "default", "read-only", or "required".
157
158 This method triggers resolution of attributes from associated C++
159 properties if they haven't been resolved yet.
160
161 \note The "attached" hint is not included here because attached
162 properties are already distinguished by their naming convention
163 (Type.property vs property).
164
165 \note The "default: value" hint is not included here as it requires
166 context-specific logic (avoiding "default default: value").
167*/
169{
170 QStringList result;
171 if (isDefault())
172 result << u"default"_s;
173 if (isReadOnly())
174 result << u"read-only"_s;
175 if (isRequired())
176 result << u"required"_s;
177
178 return result;
179}
180
181/*!
182 Returns a pointer this QML property's corresponding C++
183 property, if it has one.
184 */
185PropertyNode *QmlPropertyNode::findCorrespondingCppProperty()
186{
187 PropertyNode *pn;
188 Node *n = parent();
189 while (n && !(n->isQmlType()))
190 n = n->parent();
191 if (n) {
192 auto *qcn = static_cast<QmlTypeNode *>(n);
193 ClassNode *cn = qcn->classNode();
194 if (cn) {
195 /*
196 If there is a dot in the property name, first
197 find the C++ property corresponding to the QML
198 property group.
199 */
200 QStringList dotSplit = name().split(QChar('.'));
201 pn = cn->findPropertyNode(dotSplit[0]);
202 if (pn) {
203 /*
204 Now find the C++ property corresponding to
205 the QML property in the QML property group,
206 <group>.<property>.
207 */
208 if (dotSplit.size() > 1) {
209 QStringList path(extractClassName(pn->qualifiedDataType()));
210 Node *nn = QDocDatabase::qdocDB()->findClassNode(path);
211 if (nn) {
212 auto *cn = static_cast<ClassNode *>(nn);
213 PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
214 /*
215 If found, return the C++ property
216 corresponding to the QML property.
217 Otherwise, return the C++ property
218 corresponding to the QML property
219 group.
220 */
221 return (pn2 ? pn2 : pn);
222 }
223 } else
224 return pn;
225 }
226 }
227 }
228 return nullptr;
229}
230
231// Only define a mapping between C++ and QML value types with different names.
232QSet<QString> QmlPropertyNode::cppQmlValueTypes = {
233 "float",
234 "QColor",
235 "QDateTime",
236 "QFont",
237 "QMatrix4x4",
238 "QPoint",
239 "QPointF",
240 "QQuaternion",
241 "qreal",
242 "QRect",
243 "QRectF",
244 "QSize",
245 "QSizeF",
246 "QString",
247 "QUrl",
248 "QVector2D",
249 "QVector3D",
250 "QVector4D",
251 "unsigned int",
252};
253
254QRegularExpression QmlPropertyNode::qmlBasicList("^list<([^>]+)>$");
255QRegularExpression QmlPropertyNode::cppBasicList("^(Q[A-Za-z0-9]+)List$");
256
257/*!
258 Validates a QML property type for the property, returning true if the type
259 is a QML type or QML list type, returning false if the type is a Qt value
260 type or Qt list type.
261
262 Specifically, if the type name matches a known value or object type in
263 qdoc's database, true is returned immediately.
264
265 If the type name matches the syntax for a non-nested QML list of types,
266 true is returned if the item type of the list is valid; otherwise false is
267 returned.
268
269 If the type name is a C or C++ type with a corresponding QML type, or if it
270 matches the syntax of a Qt list type, such as QStringList, false is
271 returned.
272
273 If none of the above applied, the type name is assumed to be valid and true
274 is returned.
275*/
276bool QmlPropertyNode::validateDataType(const QString &type) const
277{
278 QString qmlType = type;
279 if (qmlType.isNull())
280 qmlType = dataType();
281
282 if (QDocDatabase::qdocDB()->getQmlValueTypes().contains(qmlType) ||
283 QDocDatabase::qdocDB()->findQmlType(qmlType))
284 return true;
285
286 auto match = qmlBasicList.match(qmlType);
287 if (match.hasMatch())
288 return validateDataType(match.captured(1));
289
290 if (cppQmlValueTypes.contains(qmlType) ||
291 cppBasicList.match(qmlType).hasMatch())
292 return false;
293
294 return true;
295}
296
297QT_END_NAMESPACE
The ClassNode represents a C++ class.
Definition classnode.h:23
This class describes one instance of using the Q_PROPERTY macro.
bool isRequired() const
bool isWritable() const
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
NodeMultiMap & getQmlValueTypes()
Returns a reference to the map of QML basic types.
Status
Specifies the status of the QQmlIncubator.
QStringList hints() const
Returns a list of hint strings for this QML property, such as "default", "read-only",...
void markReadOnly(bool flag) override
If this node is a QmlPropertyNode, then the property's read-only flag is set to flag.
bool isReadOnly() const
Returns true if this QML property node is marked as a read-only property.
bool isRequired()
Returns true if this QML property is marked with \required or the corresponding C++ property uses the...
void setIsList(bool isList)
Marks this property as a list if isList is true.
bool isRequired() const
Const overloads that delegate to the resolving non-const versions when the attribute hasn't been cach...
void setDataType(const QString &dataType) override
Sets the data type of this property to dataType, preserving the list property modifier if one is set ...
QmlPropertyNode(Aggregate *parent, const QString &name, QString type, bool attached)
Constructor for the QML property node.
bool isReadOnly()
Returns true if this QML property or attached property is read-only.
bool validateDataType(const QString &type=QString()) const
Validates a QML property type for the property, returning true if the type is a QML type or QML list ...
void markRequired(bool flag)
NodeType
Definition genustypes.h:150
Combined button and popup list for selecting options.
@ Internal
Definition status.h:15
The Node class is the base class for all the nodes in QDoc's parse tree.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
Definition node.h:121
Aggregate * parent() const
Returns the node's parent pointer.
Definition node.h:208
static bool fromFlagValue(FlagValue fv, bool defaultValue)
Converts the enum fv back to a boolean value.
Definition node.cpp:761
@ FlagValueDefault
Definition node.h:75
@ FlagValueTrue
Definition node.h:75
void setStatus(Status t)
Sets the node's status to t.
Definition node.cpp:570