1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qmetaobjectbuilder_p.h"
41
42 #include "qobject_p.h"
43 #include "qmetaobject_p.h"
44
45 #include <vector>
46 #include <stdlib.h>
47
48 QT_BEGIN_NAMESPACE
49
50 /*!
51 \class QMetaObjectBuilder
52 \inmodule QtCore
53 \internal
54 \brief The QMetaObjectBuilder class supports building QMetaObject objects at runtime.
55
56 */
57
58 /*!
59 \enum QMetaObjectBuilder::AddMember
60 This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
61
62 \value ClassName Add the class name.
63 \value SuperClass Add the super class.
64 \value Methods Add methods that aren't signals or slots.
65 \value Signals Add signals.
66 \value Slots Add slots.
67 \value Constructors Add constructors.
68 \value Properties Add properties.
69 \value Enumerators Add enumerators.
70 \value ClassInfos Add items of class information.
71 \value RelatedMetaObjects Add related meta objects.
72 \value StaticMetacall Add the static metacall function.
73 \value PublicMethods Add public methods (ignored for signals).
74 \value ProtectedMethods Add protected methods (ignored for signals).
75 \value PrivateMethods All private methods (ignored for signals).
76 \value AllMembers Add all members.
77 \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
78 */
79
80 // copied from moc's generator.cpp
81 namespace QtPrivate {
isBuiltinType(const QByteArray & type)82 Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type)
83 {
84 int id = QMetaType::type(type);
85 if (!id && !type.isEmpty() && type != "void")
86 return false;
87 return (id < QMetaType::User);
88 }
89 } // namespace QtPrivate
90
91 // copied from qmetaobject.cpp
priv(const uint * data)92 static inline Q_DECL_UNUSED const QMetaObjectPrivate *priv(const uint* data)
93 { return reinterpret_cast<const QMetaObjectPrivate*>(data); }
94
95 class QMetaMethodBuilderPrivate
96 {
97 public:
QMetaMethodBuilderPrivate(QMetaMethod::MethodType _methodType,const QByteArray & _signature,const QByteArray & _returnType=QByteArray ("void"),QMetaMethod::Access _access=QMetaMethod::Public,int _revision=0)98 QMetaMethodBuilderPrivate
99 (QMetaMethod::MethodType _methodType,
100 const QByteArray& _signature,
101 const QByteArray& _returnType = QByteArray("void"),
102 QMetaMethod::Access _access = QMetaMethod::Public,
103 int _revision = 0)
104 : signature(QMetaObject::normalizedSignature(_signature.constData())),
105 returnType(QMetaObject::normalizedType(_returnType)),
106 attributes(((int)_access) | (((int)_methodType) << 2)),
107 revision(_revision)
108 {
109 Q_ASSERT((_methodType == QMetaMethod::Constructor) == returnType.isNull());
110 }
111
112 QByteArray signature;
113 QByteArray returnType;
114 QList<QByteArray> parameterNames;
115 QByteArray tag;
116 int attributes;
117 int revision;
118
methodType() const119 QMetaMethod::MethodType methodType() const
120 {
121 return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
122 }
123
access() const124 QMetaMethod::Access access() const
125 {
126 return (QMetaMethod::Access)(attributes & AccessMask);
127 }
128
setAccess(QMetaMethod::Access value)129 void setAccess(QMetaMethod::Access value)
130 {
131 attributes = ((attributes & ~AccessMask) | (int)value);
132 }
133
parameterTypes() const134 QList<QByteArray> parameterTypes() const
135 {
136 return QMetaObjectPrivate::parameterTypeNamesFromSignature(signature);
137 }
138
parameterCount() const139 int parameterCount() const
140 {
141 return parameterTypes().size();
142 }
143
name() const144 QByteArray name() const
145 {
146 return signature.left(qMax(signature.indexOf('('), 0));
147 }
148 };
149 Q_DECLARE_TYPEINFO(QMetaMethodBuilderPrivate, Q_MOVABLE_TYPE);
150
151 class QMetaPropertyBuilderPrivate
152 {
153 public:
QMetaPropertyBuilderPrivate(const QByteArray & _name,const QByteArray & _type,int notifierIdx=-1,int _revision=0)154 QMetaPropertyBuilderPrivate
155 (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1,
156 int _revision = 0)
157 : name(_name),
158 type(QMetaObject::normalizedType(_type.constData())),
159 flags(Readable | Writable | Scriptable), notifySignal(-1),
160 revision(_revision)
161 {
162 if (notifierIdx >= 0) {
163 flags |= Notify;
164 notifySignal = notifierIdx;
165 }
166 }
167
168 QByteArray name;
169 QByteArray type;
170 int flags;
171 int notifySignal;
172 int revision;
173
flag(int f) const174 bool flag(int f) const
175 {
176 return ((flags & f) != 0);
177 }
178
setFlag(int f,bool value)179 void setFlag(int f, bool value)
180 {
181 if (value)
182 flags |= f;
183 else
184 flags &= ~f;
185 }
186 };
187 Q_DECLARE_TYPEINFO(QMetaPropertyBuilderPrivate, Q_MOVABLE_TYPE);
188
189 class QMetaEnumBuilderPrivate
190 {
191 public:
QMetaEnumBuilderPrivate(const QByteArray & _name)192 QMetaEnumBuilderPrivate(const QByteArray& _name)
193 : name(_name), enumName(_name), isFlag(false), isScoped(false)
194 {
195 }
196
197 QByteArray name;
198 QByteArray enumName;
199 bool isFlag;
200 bool isScoped;
201 QList<QByteArray> keys;
202 QVector<int> values;
203 };
204 Q_DECLARE_TYPEINFO(QMetaEnumBuilderPrivate, Q_MOVABLE_TYPE);
205
206 class QMetaObjectBuilderPrivate
207 {
208 public:
QMetaObjectBuilderPrivate()209 QMetaObjectBuilderPrivate()
210 : flags(0)
211 {
212 superClass = &QObject::staticMetaObject;
213 staticMetacallFunction = nullptr;
214 }
215
216 bool hasRevisionedProperties() const;
217 bool hasRevisionedMethods() const;
218
219 QByteArray className;
220 const QMetaObject *superClass;
221 QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
222 std::vector<QMetaMethodBuilderPrivate> methods;
223 std::vector<QMetaMethodBuilderPrivate> constructors;
224 std::vector<QMetaPropertyBuilderPrivate> properties;
225 QList<QByteArray> classInfoNames;
226 QList<QByteArray> classInfoValues;
227 std::vector<QMetaEnumBuilderPrivate> enumerators;
228 QList<const QMetaObject *> relatedMetaObjects;
229 int flags;
230 };
231
hasRevisionedProperties() const232 bool QMetaObjectBuilderPrivate::hasRevisionedProperties() const
233 {
234 for (const auto &property : properties) {
235 if (property.revision)
236 return true;
237 }
238 return false;
239 }
240
hasRevisionedMethods() const241 bool QMetaObjectBuilderPrivate::hasRevisionedMethods() const
242 {
243 for (const auto &method : methods) {
244 if (method.revision)
245 return true;
246 }
247 return false;
248 }
249
250 /*!
251 Constructs a new QMetaObjectBuilder.
252 */
QMetaObjectBuilder()253 QMetaObjectBuilder::QMetaObjectBuilder()
254 {
255 d = new QMetaObjectBuilderPrivate();
256 }
257
258 /*!
259 Constructs a new QMetaObjectBuilder which is a copy of the
260 meta object information in \a prototype. Note: the super class
261 contents for \a prototype are not copied, only the immediate
262 class that is defined by \a prototype.
263
264 The \a members parameter indicates which members of \a prototype
265 should be added. The default is AllMembers.
266
267 \sa addMetaObject()
268 */
QMetaObjectBuilder(const QMetaObject * prototype,QMetaObjectBuilder::AddMembers members)269 QMetaObjectBuilder::QMetaObjectBuilder
270 (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
271 {
272 d = new QMetaObjectBuilderPrivate();
273 addMetaObject(prototype, members);
274 }
275
276 /*!
277 Destroys this meta object builder.
278 */
~QMetaObjectBuilder()279 QMetaObjectBuilder::~QMetaObjectBuilder()
280 {
281 delete d;
282 }
283
284 /*!
285 Returns the name of the class being constructed by this
286 meta object builder. The default value is an empty QByteArray.
287
288 \sa setClassName(), superClass()
289 */
className() const290 QByteArray QMetaObjectBuilder::className() const
291 {
292 return d->className;
293 }
294
295 /*!
296 Sets the \a name of the class being constructed by this
297 meta object builder.
298
299 \sa className(), setSuperClass()
300 */
setClassName(const QByteArray & name)301 void QMetaObjectBuilder::setClassName(const QByteArray& name)
302 {
303 d->className = name;
304 }
305
306 /*!
307 Returns the superclass meta object of the class being constructed
308 by this meta object builder. The default value is the meta object
309 for QObject.
310
311 \sa setSuperClass(), className()
312 */
superClass() const313 const QMetaObject *QMetaObjectBuilder::superClass() const
314 {
315 return d->superClass;
316 }
317
318 /*!
319 Sets the superclass meta object of the class being constructed
320 by this meta object builder to \a meta. The \a meta parameter
321 must not be null.
322
323 \sa superClass(), setClassName()
324 */
setSuperClass(const QMetaObject * meta)325 void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
326 {
327 Q_ASSERT(meta);
328 d->superClass = meta;
329 }
330
331 /*!
332 Returns the flags of the class being constructed by this meta object
333 builder.
334
335 \sa setFlags()
336 */
flags() const337 QMetaObjectBuilder::MetaObjectFlags QMetaObjectBuilder::flags() const
338 {
339 return (QMetaObjectBuilder::MetaObjectFlags)d->flags;
340 }
341
342 /*!
343 Sets the \a flags of the class being constructed by this meta object
344 builder.
345
346 \sa flags()
347 */
setFlags(MetaObjectFlags flags)348 void QMetaObjectBuilder::setFlags(MetaObjectFlags flags)
349 {
350 d->flags = flags;
351 }
352
353 /*!
354 Returns the number of methods in this class, excluding the number
355 of methods in the base class. These include signals and slots
356 as well as normal member functions.
357
358 \sa addMethod(), method(), removeMethod(), indexOfMethod()
359 */
methodCount() const360 int QMetaObjectBuilder::methodCount() const
361 {
362 return int(d->methods.size());
363 }
364
365 /*!
366 Returns the number of constructors in this class.
367
368 \sa addConstructor(), constructor(), removeConstructor(), indexOfConstructor()
369 */
constructorCount() const370 int QMetaObjectBuilder::constructorCount() const
371 {
372 return int(d->constructors.size());
373 }
374
375 /*!
376 Returns the number of properties in this class, excluding the number
377 of properties in the base class.
378
379 \sa addProperty(), property(), removeProperty(), indexOfProperty()
380 */
propertyCount() const381 int QMetaObjectBuilder::propertyCount() const
382 {
383 return int(d->properties.size());
384 }
385
386 /*!
387 Returns the number of enumerators in this class, excluding the
388 number of enumerators in the base class.
389
390 \sa addEnumerator(), enumerator(), removeEnumerator()
391 \sa indexOfEnumerator()
392 */
enumeratorCount() const393 int QMetaObjectBuilder::enumeratorCount() const
394 {
395 return int(d->enumerators.size());
396 }
397
398 /*!
399 Returns the number of items of class information in this class,
400 exclusing the number of items of class information in the base class.
401
402 \sa addClassInfo(), classInfoName(), classInfoValue(), removeClassInfo()
403 \sa indexOfClassInfo()
404 */
classInfoCount() const405 int QMetaObjectBuilder::classInfoCount() const
406 {
407 return d->classInfoNames.size();
408 }
409
410 /*!
411 Returns the number of related meta objects that are associated
412 with this class.
413
414 Related meta objects are used when resolving the enumerated type
415 associated with a property, where the enumerated type is in a
416 different class from the property.
417
418 \sa addRelatedMetaObject(), relatedMetaObject()
419 \sa removeRelatedMetaObject()
420 */
relatedMetaObjectCount() const421 int QMetaObjectBuilder::relatedMetaObjectCount() const
422 {
423 return d->relatedMetaObjects.size();
424 }
425
426 /*!
427 Adds a new public method to this class with the specified \a signature.
428 Returns an object that can be used to adjust the other attributes
429 of the method. The \a signature will be normalized before it is
430 added to the class.
431
432 \sa method(), methodCount(), removeMethod(), indexOfMethod()
433 */
addMethod(const QByteArray & signature)434 QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
435 {
436 int index = int(d->methods.size());
437 d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
438 return QMetaMethodBuilder(this, index);
439 }
440
441 /*!
442 Adds a new public method to this class with the specified
443 \a signature and \a returnType. Returns an object that can be
444 used to adjust the other attributes of the method. The \a signature
445 and \a returnType will be normalized before they are added to
446 the class.
447
448 \sa method(), methodCount(), removeMethod(), indexOfMethod()
449 */
addMethod(const QByteArray & signature,const QByteArray & returnType)450 QMetaMethodBuilder QMetaObjectBuilder::addMethod
451 (const QByteArray& signature, const QByteArray& returnType)
452 {
453 int index = int(d->methods.size());
454 d->methods.push_back(QMetaMethodBuilderPrivate
455 (QMetaMethod::Method, signature, returnType));
456 return QMetaMethodBuilder(this, index);
457 }
458
459 /*!
460 Adds a new public method to this class that has the same information as
461 \a prototype. This is used to clone the methods of an existing
462 QMetaObject. Returns an object that can be used to adjust the
463 attributes of the method.
464
465 This function will detect if \a prototype is an ordinary method,
466 signal, slot, or constructor and act accordingly.
467
468 \sa method(), methodCount(), removeMethod(), indexOfMethod()
469 */
addMethod(const QMetaMethod & prototype)470 QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
471 {
472 QMetaMethodBuilder method;
473 if (prototype.methodType() == QMetaMethod::Method)
474 method = addMethod(prototype.methodSignature());
475 else if (prototype.methodType() == QMetaMethod::Signal)
476 method = addSignal(prototype.methodSignature());
477 else if (prototype.methodType() == QMetaMethod::Slot)
478 method = addSlot(prototype.methodSignature());
479 else if (prototype.methodType() == QMetaMethod::Constructor)
480 method = addConstructor(prototype.methodSignature());
481 method.setReturnType(prototype.typeName());
482 method.setParameterNames(prototype.parameterNames());
483 method.setTag(prototype.tag());
484 method.setAccess(prototype.access());
485 method.setAttributes(prototype.attributes());
486 method.setRevision(prototype.revision());
487 return method;
488 }
489
490 /*!
491 Adds a new public slot to this class with the specified \a signature.
492 Returns an object that can be used to adjust the other attributes
493 of the slot. The \a signature will be normalized before it is
494 added to the class.
495
496 \sa addMethod(), addSignal(), indexOfSlot()
497 */
addSlot(const QByteArray & signature)498 QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
499 {
500 int index = int(d->methods.size());
501 d->methods.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
502 return QMetaMethodBuilder(this, index);
503 }
504
505 /*!
506 Adds a new signal to this class with the specified \a signature.
507 Returns an object that can be used to adjust the other attributes
508 of the signal. The \a signature will be normalized before it is
509 added to the class.
510
511 \sa addMethod(), addSlot(), indexOfSignal()
512 */
addSignal(const QByteArray & signature)513 QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
514 {
515 int index = int(d->methods.size());
516 d->methods.push_back(QMetaMethodBuilderPrivate
517 (QMetaMethod::Signal, signature, QByteArray("void"), QMetaMethod::Public));
518 return QMetaMethodBuilder(this, index);
519 }
520
521 /*!
522 Adds a new constructor to this class with the specified \a signature.
523 Returns an object that can be used to adjust the other attributes
524 of the constructor. The \a signature will be normalized before it is
525 added to the class.
526
527 \sa constructor(), constructorCount(), removeConstructor()
528 \sa indexOfConstructor()
529 */
addConstructor(const QByteArray & signature)530 QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
531 {
532 int index = int(d->constructors.size());
533 d->constructors.push_back(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature,
534 /*returnType=*/QByteArray()));
535 return QMetaMethodBuilder(this, -(index + 1));
536 }
537
538 /*!
539 Adds a new constructor to this class that has the same information as
540 \a prototype. This is used to clone the constructors of an existing
541 QMetaObject. Returns an object that can be used to adjust the
542 attributes of the constructor.
543
544 This function requires that \a prototype be a constructor.
545
546 \sa constructor(), constructorCount(), removeConstructor()
547 \sa indexOfConstructor()
548 */
addConstructor(const QMetaMethod & prototype)549 QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
550 {
551 Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
552 QMetaMethodBuilder ctor = addConstructor(prototype.methodSignature());
553 ctor.setReturnType(prototype.typeName());
554 ctor.setParameterNames(prototype.parameterNames());
555 ctor.setTag(prototype.tag());
556 ctor.setAccess(prototype.access());
557 ctor.setAttributes(prototype.attributes());
558 return ctor;
559 }
560
561 /*!
562 Adds a new readable/writable property to this class with the
563 specified \a name and \a type. Returns an object that can be used
564 to adjust the other attributes of the property. The \a type will
565 be normalized before it is added to the class. \a notifierId will
566 be registered as the property's \e notify signal.
567
568 \sa property(), propertyCount(), removeProperty(), indexOfProperty()
569 */
addProperty(const QByteArray & name,const QByteArray & type,int notifierId)570 QMetaPropertyBuilder QMetaObjectBuilder::addProperty
571 (const QByteArray& name, const QByteArray& type, int notifierId)
572 {
573 int index = int(d->properties.size());
574 d->properties.push_back(QMetaPropertyBuilderPrivate(name, type, notifierId));
575 return QMetaPropertyBuilder(this, index);
576 }
577
578 #if QT_DEPRECATED_SINCE(5, 15)
579 QT_WARNING_PUSH
580 QT_WARNING_DISABLE_DEPRECATED
deprecatedIsEditable(const QMetaProperty & prototype)581 static bool deprecatedIsEditable(const QMetaProperty &prototype)
582 {
583 return prototype.isEditable();
584 }
585 QT_WARNING_POP
586 #endif
587
588 /*!
589 Adds a new property to this class that has the same information as
590 \a prototype. This is used to clone the properties of an existing
591 QMetaObject. Returns an object that can be used to adjust the
592 attributes of the property.
593
594 \sa property(), propertyCount(), removeProperty(), indexOfProperty()
595 */
addProperty(const QMetaProperty & prototype)596 QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
597 {
598 QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
599 property.setReadable(prototype.isReadable());
600 property.setWritable(prototype.isWritable());
601 property.setResettable(prototype.isResettable());
602 property.setDesignable(prototype.isDesignable());
603 property.setScriptable(prototype.isScriptable());
604 property.setStored(prototype.isStored());
605 property.setEditable(deprecatedIsEditable(prototype));
606 property.setUser(prototype.isUser());
607 property.setStdCppSet(prototype.hasStdCppSet());
608 property.setEnumOrFlag(prototype.isEnumType());
609 property.setConstant(prototype.isConstant());
610 property.setFinal(prototype.isFinal());
611 property.setRevision(prototype.revision());
612 if (prototype.hasNotifySignal()) {
613 // Find an existing method for the notify signal, or add a new one.
614 QMetaMethod method = prototype.notifySignal();
615 int index = indexOfMethod(method.methodSignature());
616 if (index == -1)
617 index = addMethod(method).index();
618 d->properties[property._index].notifySignal = index;
619 d->properties[property._index].setFlag(Notify, true);
620 }
621 return property;
622 }
623
624 /*!
625 Adds a new enumerator to this class with the specified
626 \a name. Returns an object that can be used to adjust
627 the other attributes of the enumerator.
628
629 \sa enumerator(), enumeratorCount(), removeEnumerator()
630 \sa indexOfEnumerator()
631 */
addEnumerator(const QByteArray & name)632 QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
633 {
634 int index = int(d->enumerators.size());
635 d->enumerators.push_back(QMetaEnumBuilderPrivate(name));
636 return QMetaEnumBuilder(this, index);
637 }
638
639 /*!
640 Adds a new enumerator to this class that has the same information as
641 \a prototype. This is used to clone the enumerators of an existing
642 QMetaObject. Returns an object that can be used to adjust the
643 attributes of the enumerator.
644
645 \sa enumerator(), enumeratorCount(), removeEnumerator()
646 \sa indexOfEnumerator()
647 */
addEnumerator(const QMetaEnum & prototype)648 QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
649 {
650 QMetaEnumBuilder en = addEnumerator(prototype.name());
651 en.setEnumName(prototype.enumName());
652 en.setIsFlag(prototype.isFlag());
653 en.setIsScoped(prototype.isScoped());
654 int count = prototype.keyCount();
655 for (int index = 0; index < count; ++index)
656 en.addKey(prototype.key(index), prototype.value(index));
657 return en;
658 }
659
660 /*!
661 Adds \a name and \a value as an item of class information to this class.
662 Returns the index of the new item of class information.
663
664 \sa classInfoCount(), classInfoName(), classInfoValue(), removeClassInfo()
665 \sa indexOfClassInfo()
666 */
addClassInfo(const QByteArray & name,const QByteArray & value)667 int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
668 {
669 int index = d->classInfoNames.size();
670 d->classInfoNames += name;
671 d->classInfoValues += value;
672 return index;
673 }
674
675 /*!
676 Adds \a meta to this class as a related meta object. Returns
677 the index of the new related meta object entry.
678
679 Related meta objects are used when resolving the enumerated type
680 associated with a property, where the enumerated type is in a
681 different class from the property.
682
683 \sa relatedMetaObjectCount(), relatedMetaObject()
684 \sa removeRelatedMetaObject()
685 */
addRelatedMetaObject(const QMetaObject * meta)686 int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
687 {
688 Q_ASSERT(meta);
689 int index = d->relatedMetaObjects.size();
690 d->relatedMetaObjects.append(meta);
691 return index;
692 }
693
694 /*!
695 Adds the contents of \a prototype to this meta object builder.
696 This function is useful for cloning the contents of an existing QMetaObject.
697
698 The \a members parameter indicates which members of \a prototype
699 should be added. The default is AllMembers.
700 */
addMetaObject(const QMetaObject * prototype,QMetaObjectBuilder::AddMembers members)701 void QMetaObjectBuilder::addMetaObject
702 (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
703 {
704 Q_ASSERT(prototype);
705 int index;
706
707 if ((members & ClassName) != 0)
708 d->className = prototype->className();
709
710 if ((members & SuperClass) != 0)
711 d->superClass = prototype->superClass();
712
713 if ((members & (Methods | Signals | Slots)) != 0) {
714 for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
715 QMetaMethod method = prototype->method(index);
716 if (method.methodType() != QMetaMethod::Signal) {
717 if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
718 continue;
719 if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
720 continue;
721 if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
722 continue;
723 }
724 if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
725 addMethod(method);
726 } else if (method.methodType() == QMetaMethod::Signal &&
727 (members & Signals) != 0) {
728 addMethod(method);
729 } else if (method.methodType() == QMetaMethod::Slot &&
730 (members & Slots) != 0) {
731 addMethod(method);
732 }
733 }
734 }
735
736 if ((members & Constructors) != 0) {
737 for (index = 0; index < prototype->constructorCount(); ++index)
738 addConstructor(prototype->constructor(index));
739 }
740
741 if ((members & Properties) != 0) {
742 for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
743 addProperty(prototype->property(index));
744 }
745
746 if ((members & Enumerators) != 0) {
747 for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
748 addEnumerator(prototype->enumerator(index));
749 }
750
751 if ((members & ClassInfos) != 0) {
752 for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
753 QMetaClassInfo ci = prototype->classInfo(index);
754 addClassInfo(ci.name(), ci.value());
755 }
756 }
757
758 if ((members & RelatedMetaObjects) != 0) {
759 Q_ASSERT(priv(prototype->d.data)->revision >= 2);
760 const auto *objects = prototype->d.relatedMetaObjects;
761 if (objects) {
762 while (*objects != nullptr) {
763 addRelatedMetaObject(*objects);
764 ++objects;
765 }
766 }
767 }
768
769 if ((members & StaticMetacall) != 0) {
770 Q_ASSERT(priv(prototype->d.data)->revision >= 6);
771 if (prototype->d.static_metacall)
772 setStaticMetacallFunction(prototype->d.static_metacall);
773 }
774 }
775
776 /*!
777 Returns the method at \a index in this class.
778
779 \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
780 */
method(int index) const781 QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
782 {
783 if (uint(index) < d->methods.size())
784 return QMetaMethodBuilder(this, index);
785 else
786 return QMetaMethodBuilder();
787 }
788
789 /*!
790 Returns the constructor at \a index in this class.
791
792 \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
793 */
constructor(int index) const794 QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
795 {
796 if (uint(index) < d->constructors.size())
797 return QMetaMethodBuilder(this, -(index + 1));
798 else
799 return QMetaMethodBuilder();
800 }
801
802 /*!
803 Returns the property at \a index in this class.
804
805 \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
806 */
property(int index) const807 QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
808 {
809 if (uint(index) < d->properties.size())
810 return QMetaPropertyBuilder(this, index);
811 else
812 return QMetaPropertyBuilder();
813 }
814
815 /*!
816 Returns the enumerator at \a index in this class.
817
818 \sa enumeratorCount(), addEnumerator(), removeEnumerator()
819 \sa indexOfEnumerator()
820 */
enumerator(int index) const821 QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
822 {
823 if (uint(index) < d->enumerators.size())
824 return QMetaEnumBuilder(this, index);
825 else
826 return QMetaEnumBuilder();
827 }
828
829 /*!
830 Returns the related meta object at \a index in this class.
831
832 Related meta objects are used when resolving the enumerated type
833 associated with a property, where the enumerated type is in a
834 different class from the property.
835
836 \sa relatedMetaObjectCount(), addRelatedMetaObject()
837 \sa removeRelatedMetaObject()
838 */
relatedMetaObject(int index) const839 const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
840 {
841 if (index >= 0 && index < d->relatedMetaObjects.size())
842 return d->relatedMetaObjects[index];
843 else
844 return nullptr;
845 }
846
847 /*!
848 Returns the name of the item of class information at \a index
849 in this class.
850
851 \sa classInfoCount(), addClassInfo(), classInfoValue(), removeClassInfo()
852 \sa indexOfClassInfo()
853 */
classInfoName(int index) const854 QByteArray QMetaObjectBuilder::classInfoName(int index) const
855 {
856 if (index >= 0 && index < d->classInfoNames.size())
857 return d->classInfoNames[index];
858 else
859 return QByteArray();
860 }
861
862 /*!
863 Returns the value of the item of class information at \a index
864 in this class.
865
866 \sa classInfoCount(), addClassInfo(), classInfoName(), removeClassInfo()
867 \sa indexOfClassInfo()
868 */
classInfoValue(int index) const869 QByteArray QMetaObjectBuilder::classInfoValue(int index) const
870 {
871 if (index >= 0 && index < d->classInfoValues.size())
872 return d->classInfoValues[index];
873 else
874 return QByteArray();
875 }
876
877 /*!
878 Removes the method at \a index from this class. The indices of
879 all following methods will be adjusted downwards by 1. If the
880 method is registered as a notify signal on a property, then the
881 notify signal will be removed from the property.
882
883 \sa methodCount(), addMethod(), method(), indexOfMethod()
884 */
removeMethod(int index)885 void QMetaObjectBuilder::removeMethod(int index)
886 {
887 if (uint(index) < d->methods.size()) {
888 d->methods.erase(d->methods.begin() + index);
889 for (auto &property : d->properties) {
890 // Adjust the indices of property notify signal references.
891 if (property.notifySignal == index) {
892 property.notifySignal = -1;
893 property.setFlag(Notify, false);
894 } else if (property.notifySignal > index)
895 property.notifySignal--;
896 }
897 }
898 }
899
900 /*!
901 Removes the constructor at \a index from this class. The indices of
902 all following constructors will be adjusted downwards by 1.
903
904 \sa constructorCount(), addConstructor(), constructor()
905 \sa indexOfConstructor()
906 */
removeConstructor(int index)907 void QMetaObjectBuilder::removeConstructor(int index)
908 {
909 if (uint(index) < d->constructors.size())
910 d->constructors.erase(d->constructors.begin() + index);
911 }
912
913 /*!
914 Removes the property at \a index from this class. The indices of
915 all following properties will be adjusted downwards by 1.
916
917 \sa propertyCount(), addProperty(), property(), indexOfProperty()
918 */
removeProperty(int index)919 void QMetaObjectBuilder::removeProperty(int index)
920 {
921 if (uint(index) < d->properties.size())
922 d->properties.erase(d->properties.begin() + index);
923 }
924
925 /*!
926 Removes the enumerator at \a index from this class. The indices of
927 all following enumerators will be adjusted downwards by 1.
928
929 \sa enumertorCount(), addEnumerator(), enumerator()
930 \sa indexOfEnumerator()
931 */
removeEnumerator(int index)932 void QMetaObjectBuilder::removeEnumerator(int index)
933 {
934 if (uint(index) < d->enumerators.size())
935 d->enumerators.erase(d->enumerators.begin() + index);
936 }
937
938 /*!
939 Removes the item of class information at \a index from this class.
940 The indices of all following items will be adjusted downwards by 1.
941
942 \sa classInfoCount(), addClassInfo(), classInfoName(), classInfoValue()
943 \sa indexOfClassInfo()
944 */
removeClassInfo(int index)945 void QMetaObjectBuilder::removeClassInfo(int index)
946 {
947 if (index >= 0 && index < d->classInfoNames.size()) {
948 d->classInfoNames.removeAt(index);
949 d->classInfoValues.removeAt(index);
950 }
951 }
952
953 /*!
954 Removes the related meta object at \a index from this class.
955 The indices of all following related meta objects will be adjusted
956 downwards by 1.
957
958 Related meta objects are used when resolving the enumerated type
959 associated with a property, where the enumerated type is in a
960 different class from the property.
961
962 \sa relatedMetaObjectCount(), addRelatedMetaObject()
963 \sa relatedMetaObject()
964 */
removeRelatedMetaObject(int index)965 void QMetaObjectBuilder::removeRelatedMetaObject(int index)
966 {
967 if (index >= 0 && index < d->relatedMetaObjects.size())
968 d->relatedMetaObjects.removeAt(index);
969 }
970
971 /*!
972 Finds a method with the specified \a signature and returns its index;
973 otherwise returns -1. The \a signature will be normalized by this method.
974
975 \sa method(), methodCount(), addMethod(), removeMethod()
976 */
indexOfMethod(const QByteArray & signature)977 int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
978 {
979 QByteArray sig = QMetaObject::normalizedSignature(signature);
980 for (const auto &method : d->methods) {
981 if (sig == method.signature)
982 return int(&method - &d->methods.front());
983 }
984 return -1;
985 }
986
987 /*!
988 Finds a signal with the specified \a signature and returns its index;
989 otherwise returns -1. The \a signature will be normalized by this method.
990
991 \sa indexOfMethod(), indexOfSlot()
992 */
indexOfSignal(const QByteArray & signature)993 int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
994 {
995 QByteArray sig = QMetaObject::normalizedSignature(signature);
996 for (const auto &method : d->methods) {
997 if (method.methodType() == QMetaMethod::Signal && sig == method.signature)
998 return int(&method - &d->methods.front());
999 }
1000 return -1;
1001 }
1002
1003 /*!
1004 Finds a slot with the specified \a signature and returns its index;
1005 otherwise returns -1. The \a signature will be normalized by this method.
1006
1007 \sa indexOfMethod(), indexOfSignal()
1008 */
indexOfSlot(const QByteArray & signature)1009 int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
1010 {
1011 QByteArray sig = QMetaObject::normalizedSignature(signature);
1012 for (const auto &method : d->methods) {
1013 if (method.methodType() == QMetaMethod::Slot && sig == method.signature)
1014 return int(&method - &d->methods.front());
1015 }
1016 return -1;
1017 }
1018
1019 /*!
1020 Finds a constructor with the specified \a signature and returns its index;
1021 otherwise returns -1. The \a signature will be normalized by this method.
1022
1023 \sa constructor(), constructorCount(), addConstructor(), removeConstructor()
1024 */
indexOfConstructor(const QByteArray & signature)1025 int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
1026 {
1027 QByteArray sig = QMetaObject::normalizedSignature(signature);
1028 for (const auto &constructor : d->constructors) {
1029 if (sig == constructor.signature)
1030 return int(&constructor - &d->constructors.front());
1031 }
1032 return -1;
1033 }
1034
1035 /*!
1036 Finds a property with the specified \a name and returns its index;
1037 otherwise returns -1.
1038
1039 \sa property(), propertyCount(), addProperty(), removeProperty()
1040 */
indexOfProperty(const QByteArray & name)1041 int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
1042 {
1043 for (const auto &property : d->properties) {
1044 if (name == property.name)
1045 return int(&property - &d->properties.front());
1046 }
1047 return -1;
1048 }
1049
1050 /*!
1051 Finds an enumerator with the specified \a name and returns its index;
1052 otherwise returns -1.
1053
1054 \sa enumertor(), enumeratorCount(), addEnumerator(), removeEnumerator()
1055 */
indexOfEnumerator(const QByteArray & name)1056 int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
1057 {
1058 for (const auto &enumerator : d->enumerators) {
1059 if (name == enumerator.name)
1060 return int(&enumerator - &d->enumerators.front());
1061 }
1062 return -1;
1063 }
1064
1065 /*!
1066 Finds an item of class information with the specified \a name and
1067 returns its index; otherwise returns -1.
1068
1069 \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
1070 \sa removeClassInfo()
1071 */
indexOfClassInfo(const QByteArray & name)1072 int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
1073 {
1074 for (int index = 0; index < d->classInfoNames.size(); ++index) {
1075 if (name == d->classInfoNames[index])
1076 return index;
1077 }
1078 return -1;
1079 }
1080
1081 // Align on a specific type boundary.
1082 #define ALIGN(size,type) \
1083 (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
1084
1085 /*!
1086 \class QMetaStringTable
1087 \inmodule QtCore
1088 \internal
1089 \brief The QMetaStringTable class can generate a meta-object string table at runtime.
1090 */
1091
QMetaStringTable(const QByteArray & className)1092 QMetaStringTable::QMetaStringTable(const QByteArray &className)
1093 : m_index(0)
1094 , m_className(className)
1095 {
1096 const int index = enter(m_className);
1097 Q_ASSERT(index == 0);
1098 Q_UNUSED(index);
1099 }
1100
1101 // Enters the given value into the string table (if it hasn't already been
1102 // entered). Returns the index of the string.
enter(const QByteArray & value)1103 int QMetaStringTable::enter(const QByteArray &value)
1104 {
1105 Entries::iterator it = m_entries.find(value);
1106 if (it != m_entries.end())
1107 return it.value();
1108 int pos = m_index;
1109 m_entries.insert(value, pos);
1110 ++m_index;
1111 return pos;
1112 }
1113
preferredAlignment()1114 int QMetaStringTable::preferredAlignment()
1115 {
1116 return Q_ALIGNOF(QByteArrayData);
1117 }
1118
1119 // Returns the size (in bytes) required for serializing this string table.
blobSize() const1120 int QMetaStringTable::blobSize() const
1121 {
1122 int size = m_entries.size() * sizeof(QByteArrayData);
1123 Entries::const_iterator it;
1124 for (it = m_entries.constBegin(); it != m_entries.constEnd(); ++it)
1125 size += it.key().size() + 1;
1126 return size;
1127 }
1128
writeString(char * out,int i,const QByteArray & str,const int offsetOfStringdataMember,int & stringdataOffset)1129 static void writeString(char *out, int i, const QByteArray &str,
1130 const int offsetOfStringdataMember, int &stringdataOffset)
1131 {
1132 int size = str.size();
1133 qptrdiff offset = offsetOfStringdataMember + stringdataOffset
1134 - i * sizeof(QByteArrayData);
1135 const QByteArrayData data =
1136 Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset);
1137
1138 memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData));
1139
1140 memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size);
1141 out[offsetOfStringdataMember + stringdataOffset + size] = '\0';
1142
1143 stringdataOffset += size + 1;
1144 }
1145
1146 // Writes strings to string data struct.
1147 // The struct consists of an array of QByteArrayData, followed by a char array
1148 // containing the actual strings. This format must match the one produced by
1149 // moc (see generator.cpp).
writeBlob(char * out) const1150 void QMetaStringTable::writeBlob(char *out) const
1151 {
1152 Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment()-1)));
1153
1154 int offsetOfStringdataMember = m_entries.size() * sizeof(QByteArrayData);
1155 int stringdataOffset = 0;
1156
1157 // qt_metacast expects the first string in the string table to be the class name.
1158 writeString(out, /*index*/0, m_className, offsetOfStringdataMember, stringdataOffset);
1159
1160 for (Entries::ConstIterator it = m_entries.constBegin(), end = m_entries.constEnd();
1161 it != end; ++it) {
1162 const int i = it.value();
1163 if (i == 0)
1164 continue;
1165 const QByteArray &str = it.key();
1166
1167 writeString(out, i, str, offsetOfStringdataMember, stringdataOffset);
1168 }
1169 }
1170
1171 // Returns the sum of all parameters (including return type) for the given
1172 // \a methods. This is needed for calculating the size of the methods'
1173 // parameter type/name meta-data.
aggregateParameterCount(const std::vector<QMetaMethodBuilderPrivate> & methods)1174 static int aggregateParameterCount(const std::vector<QMetaMethodBuilderPrivate> &methods)
1175 {
1176 int sum = 0;
1177 for (const auto &method : methods)
1178 sum += method.parameterCount() + 1; // +1 for return type
1179 return sum;
1180 }
1181
1182 // Build a QMetaObject in "buf" based on the information in "d".
1183 // If "buf" is null, then return the number of bytes needed to
1184 // build the QMetaObject. Returns -1 if the metaobject if
1185 // relocatable is set, but the metaobject contains relatedMetaObjects.
buildMetaObject(QMetaObjectBuilderPrivate * d,char * buf,int expectedSize,bool relocatable)1186 static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
1187 int expectedSize, bool relocatable)
1188 {
1189 Q_UNUSED(expectedSize); // Avoid warning in release mode
1190 int size = 0;
1191 int dataIndex;
1192 int paramsIndex;
1193 int enumIndex;
1194 int index;
1195 bool hasRevisionedMethods = d->hasRevisionedMethods();
1196 bool hasRevisionedProperties = d->hasRevisionedProperties();
1197 bool hasNotifySignals = false;
1198
1199 if (relocatable &&
1200 (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction))
1201 return -1;
1202
1203 // Create the main QMetaObject structure at the start of the buffer.
1204 QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
1205 size += sizeof(QMetaObject);
1206 ALIGN(size, int);
1207 if (buf) {
1208 if (!relocatable) meta->d.superdata = d->superClass;
1209 meta->d.relatedMetaObjects = nullptr;
1210 meta->d.extradata = nullptr;
1211 meta->d.static_metacall = d->staticMetacallFunction;
1212 }
1213
1214 // Populate the QMetaObjectPrivate structure.
1215 QMetaObjectPrivate *pmeta
1216 = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
1217 int pmetaSize = size;
1218 dataIndex = MetaObjectPrivateFieldCount;
1219 for (const auto &property : d->properties) {
1220 if (property.notifySignal != -1) {
1221 hasNotifySignals = true;
1222 break;
1223 }
1224 }
1225 int methodParametersDataSize =
1226 ((aggregateParameterCount(d->methods)
1227 + aggregateParameterCount(d->constructors)) * 2) // types and parameter names
1228 - int(d->methods.size()) // return "parameters" don't have names
1229 - int(d->constructors.size()); // "this" parameters don't have names
1230 if (buf) {
1231 Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QMetaObjectBuilder should generate the same version as moc");
1232 pmeta->revision = QMetaObjectPrivate::OutputRevision;
1233 pmeta->flags = d->flags;
1234 pmeta->className = 0; // Class name is always the first string.
1235 //pmeta->signalCount is handled in the "output method loop" as an optimization.
1236
1237 pmeta->classInfoCount = d->classInfoNames.size();
1238 pmeta->classInfoData = dataIndex;
1239 dataIndex += 2 * d->classInfoNames.size();
1240
1241 pmeta->methodCount = int(d->methods.size());
1242 pmeta->methodData = dataIndex;
1243 dataIndex += 5 * int(d->methods.size());
1244 if (hasRevisionedMethods)
1245 dataIndex += int(d->methods.size());
1246 paramsIndex = dataIndex;
1247 dataIndex += methodParametersDataSize;
1248
1249 pmeta->propertyCount = int(d->properties.size());
1250 pmeta->propertyData = dataIndex;
1251 dataIndex += 3 * int(d->properties.size());
1252 if (hasNotifySignals)
1253 dataIndex += int(d->properties.size());
1254 if (hasRevisionedProperties)
1255 dataIndex += int(d->properties.size());
1256
1257 pmeta->enumeratorCount = int(d->enumerators.size());
1258 pmeta->enumeratorData = dataIndex;
1259 dataIndex += 5 * int(d->enumerators.size());
1260
1261 pmeta->constructorCount = int(d->constructors.size());
1262 pmeta->constructorData = dataIndex;
1263 dataIndex += 5 * int(d->constructors.size());
1264 } else {
1265 dataIndex += 2 * int(d->classInfoNames.size());
1266 dataIndex += 5 * int(d->methods.size());
1267 if (hasRevisionedMethods)
1268 dataIndex += int(d->methods.size());
1269 paramsIndex = dataIndex;
1270 dataIndex += methodParametersDataSize;
1271 dataIndex += 3 * int(d->properties.size());
1272 if (hasNotifySignals)
1273 dataIndex += int(d->properties.size());
1274 if (hasRevisionedProperties)
1275 dataIndex += int(d->properties.size());
1276 dataIndex += 5 * int(d->enumerators.size());
1277 dataIndex += 5 * int(d->constructors.size());
1278 }
1279
1280 // Allocate space for the enumerator key names and values.
1281 enumIndex = dataIndex;
1282 for (const auto &enumerator : d->enumerators)
1283 dataIndex += 2 * enumerator.keys.size();
1284
1285 // Zero terminator at the end of the data offset table.
1286 ++dataIndex;
1287
1288 // Find the start of the data and string tables.
1289 int *data = reinterpret_cast<int *>(pmeta);
1290 size += dataIndex * sizeof(int);
1291 ALIGN(size, void *);
1292 char *str = reinterpret_cast<char *>(buf + size);
1293 if (buf) {
1294 if (relocatable) {
1295 meta->d.stringdata = reinterpret_cast<const QByteArrayData *>((quintptr)size);
1296 meta->d.data = reinterpret_cast<uint *>((quintptr)pmetaSize);
1297 } else {
1298 meta->d.stringdata = reinterpret_cast<const QByteArrayData *>(str);
1299 meta->d.data = reinterpret_cast<uint *>(data);
1300 }
1301 }
1302
1303 // Reset the current data position to just past the QMetaObjectPrivate.
1304 dataIndex = MetaObjectPrivateFieldCount;
1305
1306 QMetaStringTable strings(d->className);
1307
1308 // Output the class infos,
1309 Q_ASSERT(!buf || dataIndex == pmeta->classInfoData);
1310 for (index = 0; index < d->classInfoNames.size(); ++index) {
1311 int name = strings.enter(d->classInfoNames[index]);
1312 int value = strings.enter(d->classInfoValues[index]);
1313 if (buf) {
1314 data[dataIndex] = name;
1315 data[dataIndex + 1] = value;
1316 }
1317 dataIndex += 2;
1318 }
1319
1320 // Output the methods in the class.
1321 Q_ASSERT(!buf || dataIndex == pmeta->methodData);
1322 for (const auto &method : d->methods) {
1323 int name = strings.enter(method.name());
1324 int argc = method.parameterCount();
1325 int tag = strings.enter(method.tag);
1326 int attrs = method.attributes;
1327 if (buf) {
1328 data[dataIndex] = name;
1329 data[dataIndex + 1] = argc;
1330 data[dataIndex + 2] = paramsIndex;
1331 data[dataIndex + 3] = tag;
1332 data[dataIndex + 4] = attrs;
1333 if (method.methodType() == QMetaMethod::Signal)
1334 pmeta->signalCount++;
1335 }
1336 dataIndex += 5;
1337 paramsIndex += 1 + argc * 2;
1338 }
1339 if (hasRevisionedMethods) {
1340 for (const auto &method : d->methods) {
1341 if (buf)
1342 data[dataIndex] = method.revision;
1343 ++dataIndex;
1344 }
1345 }
1346
1347 // Output the method parameters in the class.
1348 Q_ASSERT(!buf || dataIndex == pmeta->methodData + int(d->methods.size()) * 5
1349 + (hasRevisionedMethods ? int(d->methods.size()) : 0));
1350 for (int x = 0; x < 2; ++x) {
1351 const std::vector<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors;
1352 for (const auto &method : methods) {
1353 const QList<QByteArray> paramTypeNames = method.parameterTypes();
1354 int paramCount = paramTypeNames.size();
1355 for (int i = -1; i < paramCount; ++i) {
1356 const QByteArray &typeName = (i < 0) ? method.returnType : paramTypeNames.at(i);
1357 int typeInfo;
1358 if (QtPrivate::isBuiltinType(typeName))
1359 typeInfo = QMetaType::type(typeName);
1360 else
1361 typeInfo = IsUnresolvedType | strings.enter(typeName);
1362 if (buf)
1363 data[dataIndex] = typeInfo;
1364 ++dataIndex;
1365 }
1366
1367 QList<QByteArray> paramNames = method.parameterNames;
1368 while (paramNames.size() < paramCount)
1369 paramNames.append(QByteArray());
1370 for (int i = 0; i < paramCount; ++i) {
1371 int stringIndex = strings.enter(paramNames.at(i));
1372 if (buf)
1373 data[dataIndex] = stringIndex;
1374 ++dataIndex;
1375 }
1376 }
1377 }
1378
1379 // Output the properties in the class.
1380 Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
1381 for (const auto &prop : d->properties) {
1382 int name = strings.enter(prop.name);
1383
1384 int typeInfo;
1385 if (QtPrivate::isBuiltinType(prop.type))
1386 typeInfo = QMetaType::type(prop.type);
1387 else
1388 typeInfo = IsUnresolvedType | strings.enter(prop.type);
1389
1390 int flags = prop.flags;
1391
1392 if (!QtPrivate::isBuiltinType(prop.type))
1393 flags |= EnumOrFlag;
1394
1395 if (buf) {
1396 data[dataIndex] = name;
1397 data[dataIndex + 1] = typeInfo;
1398 data[dataIndex + 2] = flags;
1399 }
1400 dataIndex += 3;
1401 }
1402 if (hasNotifySignals) {
1403 for (const auto &prop : d->properties) {
1404 if (buf) {
1405 if (prop.notifySignal != -1)
1406 data[dataIndex] = prop.notifySignal;
1407 else
1408 data[dataIndex] = 0;
1409 }
1410 ++dataIndex;
1411 }
1412 }
1413 if (hasRevisionedProperties) {
1414 for (const auto &prop : d->properties) {
1415 if (buf)
1416 data[dataIndex] = prop.revision;
1417 ++dataIndex;
1418 }
1419 }
1420
1421 // Output the enumerators in the class.
1422 Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
1423 for (const auto &enumerator : d->enumerators) {
1424 int name = strings.enter(enumerator.name);
1425 int enumName = strings.enter(enumerator.enumName);
1426 int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
1427 int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
1428 int count = enumerator.keys.size();
1429 int enumOffset = enumIndex;
1430 if (buf) {
1431 data[dataIndex] = name;
1432 data[dataIndex + 1] = enumName;
1433 data[dataIndex + 2] = isFlag | isScoped;
1434 data[dataIndex + 3] = count;
1435 data[dataIndex + 4] = enumOffset;
1436 }
1437 for (int key = 0; key < count; ++key) {
1438 int keyIndex = strings.enter(enumerator.keys[key]);
1439 if (buf) {
1440 data[enumOffset++] = keyIndex;
1441 data[enumOffset++] = enumerator.values[key];
1442 }
1443 }
1444 dataIndex += 5;
1445 enumIndex += 2 * count;
1446 }
1447
1448 // Output the constructors in the class.
1449 Q_ASSERT(!buf || dataIndex == pmeta->constructorData);
1450 for (const auto &ctor : d->constructors) {
1451 int name = strings.enter(ctor.name());
1452 int argc = ctor.parameterCount();
1453 int tag = strings.enter(ctor.tag);
1454 int attrs = ctor.attributes;
1455 if (buf) {
1456 data[dataIndex] = name;
1457 data[dataIndex + 1] = argc;
1458 data[dataIndex + 2] = paramsIndex;
1459 data[dataIndex + 3] = tag;
1460 data[dataIndex + 4] = attrs;
1461 }
1462 dataIndex += 5;
1463 paramsIndex += 1 + argc * 2;
1464 }
1465
1466 size += strings.blobSize();
1467
1468 if (buf)
1469 strings.writeBlob(str);
1470
1471 // Output the zero terminator in the data array.
1472 if (buf)
1473 data[enumIndex] = 0;
1474
1475 // Create the relatedMetaObjects block if we need one.
1476 if (d->relatedMetaObjects.size() > 0) {
1477 using SuperData = QMetaObject::SuperData;
1478 ALIGN(size, SuperData);
1479 auto objects = reinterpret_cast<SuperData *>(buf + size);
1480 if (buf) {
1481 meta->d.relatedMetaObjects = objects;
1482 for (index = 0; index < d->relatedMetaObjects.size(); ++index)
1483 objects[index] = d->relatedMetaObjects[index];
1484 objects[index] = nullptr;
1485 }
1486 size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1);
1487 }
1488
1489 // Align the final size and return it.
1490 ALIGN(size, void *);
1491 Q_ASSERT(!buf || size == expectedSize);
1492 return size;
1493 }
1494
1495 /*!
1496 Converts this meta object builder into a concrete QMetaObject.
1497 The return value should be deallocated using free() once it
1498 is no longer needed.
1499
1500 The returned meta object is a snapshot of the state of the
1501 QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
1502 will not be reflected in previous meta objects returned by
1503 this method.
1504 */
toMetaObject() const1505 QMetaObject *QMetaObjectBuilder::toMetaObject() const
1506 {
1507 int size = buildMetaObject(d, nullptr, 0, false);
1508 char *buf = reinterpret_cast<char *>(malloc(size));
1509 memset(buf, 0, size);
1510 buildMetaObject(d, buf, size, false);
1511 return reinterpret_cast<QMetaObject *>(buf);
1512 }
1513
1514 /*
1515 \internal
1516
1517 Converts this meta object builder into relocatable data. This data can
1518 be stored, copied and later passed to fromRelocatableData() to create a
1519 concrete QMetaObject.
1520
1521 The data is specific to the architecture on which it was created, but is not
1522 specific to the process that created it. Not all meta object builder's can
1523 be converted to data in this way. If \a ok is provided, it will be set to
1524 true if the conversion succeeds, and false otherwise. If a
1525 staticMetacallFunction() or any relatedMetaObject()'s are specified the
1526 conversion to relocatable data will fail.
1527 */
toRelocatableData(bool * ok) const1528 QByteArray QMetaObjectBuilder::toRelocatableData(bool *ok) const
1529 {
1530 int size = buildMetaObject(d, nullptr, 0, true);
1531 if (size == -1) {
1532 if (ok) *ok = false;
1533 return QByteArray();
1534 }
1535
1536 QByteArray data;
1537 data.resize(size);
1538 char *buf = data.data();
1539 memset(buf, 0, size);
1540 buildMetaObject(d, buf, size, true);
1541 if (ok) *ok = true;
1542 return data;
1543 }
1544
1545 /*
1546 \internal
1547
1548 Sets the \a data returned from toRelocatableData() onto a concrete
1549 QMetaObject instance, \a output. As the meta object's super class is not
1550 saved in the relocatable data, it must be passed as \a superClass.
1551 */
fromRelocatableData(QMetaObject * output,const QMetaObject * superclass,const QByteArray & data)1552 void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
1553 const QMetaObject *superclass,
1554 const QByteArray &data)
1555 {
1556 if (!output)
1557 return;
1558
1559 const char *buf = data.constData();
1560 const QMetaObject *dataMo = reinterpret_cast<const QMetaObject *>(buf);
1561
1562 quintptr stringdataOffset = (quintptr)dataMo->d.stringdata;
1563 quintptr dataOffset = (quintptr)dataMo->d.data;
1564
1565 output->d.superdata = superclass;
1566 output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset);
1567 output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
1568 output->d.extradata = nullptr;
1569 output->d.relatedMetaObjects = nullptr;
1570 output->d.static_metacall = nullptr;
1571 }
1572
1573 /*!
1574 \typedef QMetaObjectBuilder::StaticMetacallFunction
1575
1576 Typedef for static metacall functions. The three parameters are
1577 the call type value, the constructor index, and the
1578 array of parameters.
1579 */
1580
1581 /*!
1582 Returns the static metacall function to use to construct objects
1583 of this class. The default value is null.
1584
1585 \sa setStaticMetacallFunction()
1586 */
staticMetacallFunction() const1587 QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
1588 {
1589 return d->staticMetacallFunction;
1590 }
1591
1592 /*!
1593 Sets the static metacall function to use to construct objects
1594 of this class to \a value. The default value is null.
1595
1596 \sa staticMetacallFunction()
1597 */
setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value)1598 void QMetaObjectBuilder::setStaticMetacallFunction
1599 (QMetaObjectBuilder::StaticMetacallFunction value)
1600 {
1601 d->staticMetacallFunction = value;
1602 }
1603
1604 #ifndef QT_NO_DATASTREAM
1605
1606 /*!
1607 Serializes the contents of the meta object builder onto \a stream.
1608
1609 \sa deserialize()
1610 */
serialize(QDataStream & stream) const1611 void QMetaObjectBuilder::serialize(QDataStream& stream) const
1612 {
1613 int index;
1614
1615 // Write the class and super class names.
1616 stream << d->className;
1617 if (d->superClass)
1618 stream << QByteArray(d->superClass->className());
1619 else
1620 stream << QByteArray();
1621
1622 // Write the counts for each type of class member.
1623 stream << d->classInfoNames.size();
1624 stream << int(d->methods.size());
1625 stream << int(d->properties.size());
1626 stream << int(d->enumerators.size());
1627 stream << int(d->constructors.size());
1628 stream << d->relatedMetaObjects.size();
1629
1630 // Write the items of class information.
1631 for (index = 0; index < d->classInfoNames.size(); ++index) {
1632 stream << d->classInfoNames[index];
1633 stream << d->classInfoValues[index];
1634 }
1635
1636 // Write the methods.
1637 for (const auto &method : d->methods) {
1638 stream << method.signature;
1639 stream << method.returnType;
1640 stream << method.parameterNames;
1641 stream << method.tag;
1642 stream << method.attributes;
1643 if (method.revision)
1644 stream << method.revision;
1645 }
1646
1647 // Write the properties.
1648 for (const auto &property : d->properties) {
1649 stream << property.name;
1650 stream << property.type;
1651 stream << property.flags;
1652 stream << property.notifySignal;
1653 if (property.revision)
1654 stream << property.revision;
1655 }
1656
1657 // Write the enumerators.
1658 for (const auto &enumerator : d->enumerators) {
1659 stream << enumerator.name;
1660 stream << enumerator.isFlag;
1661 stream << enumerator.isScoped;
1662 stream << enumerator.keys;
1663 stream << enumerator.values;
1664 }
1665
1666 // Write the constructors.
1667 for (const auto &ctor : d->constructors) {
1668 stream << ctor.signature;
1669 stream << ctor.returnType;
1670 stream << ctor.parameterNames;
1671 stream << ctor.tag;
1672 stream << ctor.attributes;
1673 }
1674
1675 // Write the related meta objects.
1676 for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
1677 const QMetaObject *meta = d->relatedMetaObjects[index];
1678 stream << QByteArray(meta->className());
1679 }
1680
1681 // Add an extra empty QByteArray for additional data in future versions.
1682 // This should help maintain backwards compatibility, allowing older
1683 // versions to read newer data.
1684 stream << QByteArray();
1685 }
1686
1687 // Resolve a class name using the name reference map.
resolveClassName(const QMap<QByteArray,const QMetaObject * > & references,const QByteArray & name)1688 static const QMetaObject *resolveClassName
1689 (const QMap<QByteArray, const QMetaObject *>& references,
1690 const QByteArray& name)
1691 {
1692 if (name == QByteArray("QObject"))
1693 return &QObject::staticMetaObject;
1694 else
1695 return references.value(name, 0);
1696 }
1697
1698 /*!
1699 Deserializes a meta object builder from \a stream into
1700 this meta object builder.
1701
1702 The \a references parameter specifies a mapping from class names
1703 to QMetaObject instances for resolving the super class name and
1704 related meta objects in the object that is deserialized.
1705 The meta object for QObject is implicitly added to \a references
1706 and does not need to be supplied.
1707
1708 The QDataStream::status() value on \a stream will be set to
1709 QDataStream::ReadCorruptData if the input data is corrupt.
1710 The status will be set to QDataStream::ReadPastEnd if the
1711 input was exhausted before the full meta object was read.
1712
1713 \sa serialize()
1714 */
deserialize(QDataStream & stream,const QMap<QByteArray,const QMetaObject * > & references)1715 void QMetaObjectBuilder::deserialize
1716 (QDataStream& stream,
1717 const QMap<QByteArray, const QMetaObject *>& references)
1718 {
1719 QByteArray name;
1720 const QMetaObject *cl;
1721 int index;
1722
1723 // Clear all members in the builder to their default states.
1724 d->className.clear();
1725 d->superClass = &QObject::staticMetaObject;
1726 d->classInfoNames.clear();
1727 d->classInfoValues.clear();
1728 d->methods.clear();
1729 d->properties.clear();
1730 d->enumerators.clear();
1731 d->constructors.clear();
1732 d->relatedMetaObjects.clear();
1733 d->staticMetacallFunction = nullptr;
1734
1735 // Read the class and super class names.
1736 stream >> d->className;
1737 stream >> name;
1738 if (name.isEmpty()) {
1739 d->superClass = nullptr;
1740 } else if ((cl = resolveClassName(references, name)) != nullptr) {
1741 d->superClass = cl;
1742 } else {
1743 stream.setStatus(QDataStream::ReadCorruptData);
1744 return;
1745 }
1746
1747 // Read the counts for each type of class member.
1748 int classInfoCount, methodCount, propertyCount;
1749 int enumeratorCount, constructorCount, relatedMetaObjectCount;
1750 stream >> classInfoCount;
1751 stream >> methodCount;
1752 stream >> propertyCount;
1753 stream >> enumeratorCount;
1754 stream >> constructorCount;
1755 stream >> relatedMetaObjectCount;
1756 if (classInfoCount < 0 || methodCount < 0 ||
1757 propertyCount < 0 || enumeratorCount < 0 ||
1758 constructorCount < 0 || relatedMetaObjectCount < 0) {
1759 stream.setStatus(QDataStream::ReadCorruptData);
1760 return;
1761 }
1762
1763 // Read the items of class information.
1764 for (index = 0; index < classInfoCount; ++index) {
1765 if (stream.status() != QDataStream::Ok)
1766 return;
1767 QByteArray value;
1768 stream >> name;
1769 stream >> value;
1770 addClassInfo(name, value);
1771 }
1772
1773 // Read the member methods.
1774 for (index = 0; index < methodCount; ++index) {
1775 if (stream.status() != QDataStream::Ok)
1776 return;
1777 stream >> name;
1778 addMethod(name);
1779 QMetaMethodBuilderPrivate &method = d->methods[index];
1780 stream >> method.returnType;
1781 stream >> method.parameterNames;
1782 stream >> method.tag;
1783 stream >> method.attributes;
1784 if (method.attributes & MethodRevisioned)
1785 stream >> method.revision;
1786 if (method.methodType() == QMetaMethod::Constructor) {
1787 // Cannot add a constructor in this set of methods.
1788 stream.setStatus(QDataStream::ReadCorruptData);
1789 return;
1790 }
1791 }
1792
1793 // Read the properties.
1794 for (index = 0; index < propertyCount; ++index) {
1795 if (stream.status() != QDataStream::Ok)
1796 return;
1797 QByteArray type;
1798 stream >> name;
1799 stream >> type;
1800 addProperty(name, type);
1801 QMetaPropertyBuilderPrivate &property = d->properties[index];
1802 stream >> property.flags;
1803 stream >> property.notifySignal;
1804 if (property.notifySignal < -1 ||
1805 property.notifySignal >= int(d->methods.size())) {
1806 // Notify signal method index is out of range.
1807 stream.setStatus(QDataStream::ReadCorruptData);
1808 return;
1809 }
1810 if (property.notifySignal >= 0 &&
1811 d->methods[property.notifySignal].methodType() != QMetaMethod::Signal) {
1812 // Notify signal method index does not refer to a signal.
1813 stream.setStatus(QDataStream::ReadCorruptData);
1814 return;
1815 }
1816 if (property.flags & Revisioned)
1817 stream >> property.revision;
1818 }
1819
1820 // Read the enumerators.
1821 for (index = 0; index < enumeratorCount; ++index) {
1822 if (stream.status() != QDataStream::Ok)
1823 return;
1824 stream >> name;
1825 addEnumerator(name);
1826 QMetaEnumBuilderPrivate &enumerator = d->enumerators[index];
1827 stream >> enumerator.isFlag;
1828 stream >> enumerator.isScoped;
1829 stream >> enumerator.keys;
1830 stream >> enumerator.values;
1831 if (enumerator.keys.size() != enumerator.values.size()) {
1832 // Mismatch between number of keys and number of values.
1833 stream.setStatus(QDataStream::ReadCorruptData);
1834 return;
1835 }
1836 }
1837
1838 // Read the constructor methods.
1839 for (index = 0; index < constructorCount; ++index) {
1840 if (stream.status() != QDataStream::Ok)
1841 return;
1842 stream >> name;
1843 addConstructor(name);
1844 QMetaMethodBuilderPrivate &method = d->constructors[index];
1845 stream >> method.returnType;
1846 stream >> method.parameterNames;
1847 stream >> method.tag;
1848 stream >> method.attributes;
1849 if (method.methodType() != QMetaMethod::Constructor) {
1850 // The type must be Constructor.
1851 stream.setStatus(QDataStream::ReadCorruptData);
1852 return;
1853 }
1854 }
1855
1856 // Read the related meta objects.
1857 for (index = 0; index < relatedMetaObjectCount; ++index) {
1858 if (stream.status() != QDataStream::Ok)
1859 return;
1860 stream >> name;
1861 cl = resolveClassName(references, name);
1862 if (!cl) {
1863 stream.setStatus(QDataStream::ReadCorruptData);
1864 return;
1865 }
1866 addRelatedMetaObject(cl);
1867 }
1868
1869 // Read the extra data block, which is reserved for future use.
1870 stream >> name;
1871 }
1872
1873 #endif // !QT_NO_DATASTREAM
1874
1875 /*!
1876 \class QMetaMethodBuilder
1877 \inmodule QtCore
1878 \internal
1879 \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
1880 */
1881
d_func() const1882 QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
1883 {
1884 // Positive indices indicate methods, negative indices indicate constructors.
1885 if (_mobj && _index >= 0 && _index < int(_mobj->d->methods.size()))
1886 return &(_mobj->d->methods[_index]);
1887 else if (_mobj && -_index >= 1 && -_index <= int(_mobj->d->constructors.size()))
1888 return &(_mobj->d->constructors[(-_index) - 1]);
1889 else
1890 return nullptr;
1891 }
1892
1893 /*!
1894 \fn QMetaMethodBuilder::QMetaMethodBuilder()
1895 \internal
1896 */
1897
1898 /*!
1899 Returns the index of this method within its QMetaObjectBuilder.
1900 */
index() const1901 int QMetaMethodBuilder::index() const
1902 {
1903 if (_index >= 0)
1904 return _index; // Method, signal, or slot
1905 else
1906 return (-_index) - 1; // Constructor
1907 }
1908
1909 /*!
1910 Returns the type of this method (signal, slot, method, or constructor).
1911 */
methodType() const1912 QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
1913 {
1914 QMetaMethodBuilderPrivate *d = d_func();
1915 if (d)
1916 return d->methodType();
1917 else
1918 return QMetaMethod::Method;
1919 }
1920
1921 /*!
1922 Returns the signature of this method.
1923
1924 \sa parameterNames(), returnType()
1925 */
signature() const1926 QByteArray QMetaMethodBuilder::signature() const
1927 {
1928 QMetaMethodBuilderPrivate *d = d_func();
1929 if (d)
1930 return d->signature;
1931 else
1932 return QByteArray();
1933 }
1934
1935 /*!
1936 Returns the return type for this method; empty if the method's
1937 return type is \c{void}.
1938
1939 \sa setReturnType(), signature()
1940 */
returnType() const1941 QByteArray QMetaMethodBuilder::returnType() const
1942 {
1943 QMetaMethodBuilderPrivate *d = d_func();
1944 if (d)
1945 return d->returnType;
1946 else
1947 return QByteArray();
1948 }
1949
1950 /*!
1951 Sets the return type for this method to \a value. If \a value
1952 is empty, then the method's return type is \c{void}. The \a value
1953 will be normalized before it is added to the method.
1954
1955 \sa returnType(), parameterTypes(), signature()
1956 */
setReturnType(const QByteArray & value)1957 void QMetaMethodBuilder::setReturnType(const QByteArray& value)
1958 {
1959 QMetaMethodBuilderPrivate *d = d_func();
1960 if (d)
1961 d->returnType = QMetaObject::normalizedType(value);
1962 }
1963
1964 /*!
1965 Returns the list of parameter types for this method.
1966
1967 \sa returnType(), parameterNames()
1968 */
parameterTypes() const1969 QList<QByteArray> QMetaMethodBuilder::parameterTypes() const
1970 {
1971 QMetaMethodBuilderPrivate *d = d_func();
1972 if (d)
1973 return d->parameterTypes();
1974 else
1975 return QList<QByteArray>();
1976 }
1977
1978 /*!
1979 Returns the list of parameter names for this method.
1980
1981 \sa setParameterNames()
1982 */
parameterNames() const1983 QList<QByteArray> QMetaMethodBuilder::parameterNames() const
1984 {
1985 QMetaMethodBuilderPrivate *d = d_func();
1986 if (d)
1987 return d->parameterNames;
1988 else
1989 return QList<QByteArray>();
1990 }
1991
1992 /*!
1993 Sets the list of parameter names for this method to \a value.
1994
1995 \sa parameterNames()
1996 */
setParameterNames(const QList<QByteArray> & value)1997 void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
1998 {
1999 QMetaMethodBuilderPrivate *d = d_func();
2000 if (d)
2001 d->parameterNames = value;
2002 }
2003
2004 /*!
2005 Returns the tag associated with this method.
2006
2007 \sa setTag()
2008 */
tag() const2009 QByteArray QMetaMethodBuilder::tag() const
2010 {
2011 QMetaMethodBuilderPrivate *d = d_func();
2012 if (d)
2013 return d->tag;
2014 else
2015 return QByteArray();
2016 }
2017
2018 /*!
2019 Sets the tag associated with this method to \a value.
2020
2021 \sa setTag()
2022 */
setTag(const QByteArray & value)2023 void QMetaMethodBuilder::setTag(const QByteArray& value)
2024 {
2025 QMetaMethodBuilderPrivate *d = d_func();
2026 if (d)
2027 d->tag = value;
2028 }
2029
2030 /*!
2031 Returns the access specification of this method (private, protected,
2032 or public). The default value is QMetaMethod::Public for methods,
2033 slots, signals and constructors.
2034
2035 \sa setAccess()
2036 */
access() const2037 QMetaMethod::Access QMetaMethodBuilder::access() const
2038 {
2039 QMetaMethodBuilderPrivate *d = d_func();
2040 if (d)
2041 return d->access();
2042 else
2043 return QMetaMethod::Public;
2044 }
2045
2046 /*!
2047 Sets the access specification of this method (private, protected,
2048 or public) to \a value. If the method is a signal, this function
2049 will be ignored.
2050
2051 \sa access()
2052 */
setAccess(QMetaMethod::Access value)2053 void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
2054 {
2055 QMetaMethodBuilderPrivate *d = d_func();
2056 if (d && d->methodType() != QMetaMethod::Signal)
2057 d->setAccess(value);
2058 }
2059
2060 /*!
2061 Returns the additional attributes for this method.
2062
2063 \sa setAttributes()
2064 */
attributes() const2065 int QMetaMethodBuilder::attributes() const
2066 {
2067 QMetaMethodBuilderPrivate *d = d_func();
2068 if (d)
2069 return (d->attributes >> 4);
2070 else
2071 return 0;
2072 }
2073
2074 /*!
2075 Sets the additional attributes for this method to \a value.
2076
2077 \sa attributes()
2078 */
setAttributes(int value)2079 void QMetaMethodBuilder::setAttributes(int value)
2080 {
2081 QMetaMethodBuilderPrivate *d = d_func();
2082 if (d)
2083 d->attributes = ((d->attributes & 0x0f) | (value << 4));
2084 }
2085
2086 /*!
2087 Returns the revision of this method.
2088
2089 \sa setRevision()
2090 */
revision() const2091 int QMetaMethodBuilder::revision() const
2092 {
2093 QMetaMethodBuilderPrivate *d = d_func();
2094 if (d)
2095 return d->revision;
2096 return 0;
2097
2098 }
2099
2100 /*!
2101 Sets the \a revision of this method.
2102
2103 \sa revision()
2104 */
setRevision(int revision)2105 void QMetaMethodBuilder::setRevision(int revision)
2106 {
2107 QMetaMethodBuilderPrivate *d = d_func();
2108 if (d) {
2109 d->revision = revision;
2110 if (revision)
2111 d->attributes |= MethodRevisioned;
2112 else
2113 d->attributes &= ~MethodRevisioned;
2114 }
2115 }
2116
2117 /*!
2118 \class QMetaPropertyBuilder
2119 \inmodule QtCore
2120 \internal
2121 \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
2122 */
2123
d_func() const2124 QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
2125 {
2126 if (_mobj && _index >= 0 && _index < int(_mobj->d->properties.size()))
2127 return &(_mobj->d->properties[_index]);
2128 else
2129 return nullptr;
2130 }
2131
2132 /*!
2133 \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
2134 \internal
2135 */
2136
2137 /*!
2138 \fn int QMetaPropertyBuilder::index() const
2139
2140 Returns the index of this property within its QMetaObjectBuilder.
2141 */
2142
2143 /*!
2144 Returns the name associated with this property.
2145
2146 \sa type()
2147 */
name() const2148 QByteArray QMetaPropertyBuilder::name() const
2149 {
2150 QMetaPropertyBuilderPrivate *d = d_func();
2151 if (d)
2152 return d->name;
2153 else
2154 return QByteArray();
2155 }
2156
2157 /*!
2158 Returns the type associated with this property.
2159
2160 \sa name()
2161 */
type() const2162 QByteArray QMetaPropertyBuilder::type() const
2163 {
2164 QMetaPropertyBuilderPrivate *d = d_func();
2165 if (d)
2166 return d->type;
2167 else
2168 return QByteArray();
2169 }
2170
2171 /*!
2172 Returns \c true if this property has a notify signal; false otherwise.
2173
2174 \sa notifySignal(), setNotifySignal(), removeNotifySignal()
2175 */
hasNotifySignal() const2176 bool QMetaPropertyBuilder::hasNotifySignal() const
2177 {
2178 QMetaPropertyBuilderPrivate *d = d_func();
2179 if (d)
2180 return d->flag(Notify);
2181 else
2182 return false;
2183 }
2184
2185 /*!
2186 Returns the notify signal associated with this property.
2187
2188 \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
2189 */
notifySignal() const2190 QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
2191 {
2192 QMetaPropertyBuilderPrivate *d = d_func();
2193 if (d && d->notifySignal >= 0)
2194 return QMetaMethodBuilder(_mobj, d->notifySignal);
2195 else
2196 return QMetaMethodBuilder();
2197 }
2198
2199 /*!
2200 Sets the notify signal associated with this property to \a value.
2201
2202 \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
2203 */
setNotifySignal(const QMetaMethodBuilder & value)2204 void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
2205 {
2206 QMetaPropertyBuilderPrivate *d = d_func();
2207 if (d) {
2208 if (value._mobj) {
2209 d->notifySignal = value._index;
2210 d->setFlag(Notify, true);
2211 } else {
2212 d->notifySignal = -1;
2213 d->setFlag(Notify, false);
2214 }
2215 }
2216 }
2217
2218 /*!
2219 Removes the notify signal from this property.
2220
2221 \sa hasNotifySignal(), notifySignal(), setNotifySignal()
2222 */
removeNotifySignal()2223 void QMetaPropertyBuilder::removeNotifySignal()
2224 {
2225 QMetaPropertyBuilderPrivate *d = d_func();
2226 if (d) {
2227 d->notifySignal = -1;
2228 d->setFlag(Notify, false);
2229 }
2230 }
2231
2232 /*!
2233 Returns \c true if this property is readable; otherwise returns \c false.
2234 The default value is true.
2235
2236 \sa setReadable(), isWritable()
2237 */
isReadable() const2238 bool QMetaPropertyBuilder::isReadable() const
2239 {
2240 QMetaPropertyBuilderPrivate *d = d_func();
2241 if (d)
2242 return d->flag(Readable);
2243 else
2244 return false;
2245 }
2246
2247 /*!
2248 Returns \c true if this property is writable; otherwise returns \c false.
2249 The default value is true.
2250
2251 \sa setWritable(), isReadable()
2252 */
isWritable() const2253 bool QMetaPropertyBuilder::isWritable() const
2254 {
2255 QMetaPropertyBuilderPrivate *d = d_func();
2256 if (d)
2257 return d->flag(Writable);
2258 else
2259 return false;
2260 }
2261
2262 /*!
2263 Returns \c true if this property can be reset to a default value; otherwise
2264 returns \c false. The default value is false.
2265
2266 \sa setResettable()
2267 */
isResettable() const2268 bool QMetaPropertyBuilder::isResettable() const
2269 {
2270 QMetaPropertyBuilderPrivate *d = d_func();
2271 if (d)
2272 return d->flag(Resettable);
2273 else
2274 return false;
2275 }
2276
2277 /*!
2278 Returns \c true if this property is designable; otherwise returns \c false.
2279 This default value is false.
2280
2281 \sa setDesignable(), isScriptable(), isStored()
2282 */
isDesignable() const2283 bool QMetaPropertyBuilder::isDesignable() const
2284 {
2285 QMetaPropertyBuilderPrivate *d = d_func();
2286 if (d)
2287 return d->flag(Designable);
2288 else
2289 return false;
2290 }
2291
2292 /*!
2293 Returns \c true if the property is scriptable; otherwise returns \c false.
2294 This default value is true.
2295
2296 \sa setScriptable(), isDesignable(), isStored()
2297 */
isScriptable() const2298 bool QMetaPropertyBuilder::isScriptable() const
2299 {
2300 QMetaPropertyBuilderPrivate *d = d_func();
2301 if (d)
2302 return d->flag(Scriptable);
2303 else
2304 return false;
2305 }
2306
2307 /*!
2308 Returns \c true if the property is stored; otherwise returns \c false.
2309 This default value is false.
2310
2311 \sa setStored(), isDesignable(), isScriptable()
2312 */
isStored() const2313 bool QMetaPropertyBuilder::isStored() const
2314 {
2315 QMetaPropertyBuilderPrivate *d = d_func();
2316 if (d)
2317 return d->flag(Stored);
2318 else
2319 return false;
2320 }
2321
2322 /*!
2323 Returns \c true if the property is editable; otherwise returns \c false.
2324 This default value is false.
2325
2326 \sa setEditable(), isDesignable(), isScriptable(), isStored()
2327 */
isEditable() const2328 bool QMetaPropertyBuilder::isEditable() const
2329 {
2330 QMetaPropertyBuilderPrivate *d = d_func();
2331 if (d)
2332 return d->flag(Editable);
2333 else
2334 return false;
2335 }
2336
2337 /*!
2338 Returns \c true if this property is designated as the \c USER
2339 property, i.e., the one that the user can edit or that is
2340 significant in some other way. Otherwise it returns
2341 false. This default value is false.
2342
2343 \sa setUser(), isDesignable(), isScriptable()
2344 */
isUser() const2345 bool QMetaPropertyBuilder::isUser() const
2346 {
2347 QMetaPropertyBuilderPrivate *d = d_func();
2348 if (d)
2349 return d->flag(User);
2350 else
2351 return false;
2352 }
2353
2354 /*!
2355 Returns \c true if the property has a C++ setter function that
2356 follows Qt's standard "name" / "setName" pattern. Designer and uic
2357 query hasStdCppSet() in order to avoid expensive
2358 QObject::setProperty() calls. All properties in Qt [should] follow
2359 this pattern. The default value is false.
2360
2361 \sa setStdCppSet()
2362 */
hasStdCppSet() const2363 bool QMetaPropertyBuilder::hasStdCppSet() const
2364 {
2365 QMetaPropertyBuilderPrivate *d = d_func();
2366 if (d)
2367 return d->flag(StdCppSet);
2368 else
2369 return false;
2370 }
2371
2372 /*!
2373 Returns \c true if the property is an enumerator or flag type;
2374 otherwise returns \c false. This default value is false.
2375
2376 \sa setEnumOrFlag()
2377 */
isEnumOrFlag() const2378 bool QMetaPropertyBuilder::isEnumOrFlag() const
2379 {
2380 QMetaPropertyBuilderPrivate *d = d_func();
2381 if (d)
2382 return d->flag(EnumOrFlag);
2383 else
2384 return false;
2385 }
2386
2387 /*!
2388 Returns \c true if the property is constant; otherwise returns \c false.
2389 The default value is false.
2390 */
isConstant() const2391 bool QMetaPropertyBuilder::isConstant() const
2392 {
2393 QMetaPropertyBuilderPrivate *d = d_func();
2394 if (d)
2395 return d->flag(Constant);
2396 else
2397 return false;
2398 }
2399
2400 /*!
2401 Returns \c true if the property is final; otherwise returns \c false.
2402 The default value is false.
2403 */
isFinal() const2404 bool QMetaPropertyBuilder::isFinal() const
2405 {
2406 QMetaPropertyBuilderPrivate *d = d_func();
2407 if (d)
2408 return d->flag(Final);
2409 else
2410 return false;
2411 }
2412
2413 /*!
2414 Sets this property to readable if \a value is true.
2415
2416 \sa isReadable(), setWritable()
2417 */
setReadable(bool value)2418 void QMetaPropertyBuilder::setReadable(bool value)
2419 {
2420 QMetaPropertyBuilderPrivate *d = d_func();
2421 if (d)
2422 d->setFlag(Readable, value);
2423 }
2424
2425 /*!
2426 Sets this property to writable if \a value is true.
2427
2428 \sa isWritable(), setReadable()
2429 */
setWritable(bool value)2430 void QMetaPropertyBuilder::setWritable(bool value)
2431 {
2432 QMetaPropertyBuilderPrivate *d = d_func();
2433 if (d)
2434 d->setFlag(Writable, value);
2435 }
2436
2437 /*!
2438 Sets this property to resettable if \a value is true.
2439
2440 \sa isResettable()
2441 */
setResettable(bool value)2442 void QMetaPropertyBuilder::setResettable(bool value)
2443 {
2444 QMetaPropertyBuilderPrivate *d = d_func();
2445 if (d)
2446 d->setFlag(Resettable, value);
2447 }
2448
2449 /*!
2450 Sets this property to designable if \a value is true.
2451
2452 \sa isDesignable(), setScriptable(), setStored()
2453 */
setDesignable(bool value)2454 void QMetaPropertyBuilder::setDesignable(bool value)
2455 {
2456 QMetaPropertyBuilderPrivate *d = d_func();
2457 if (d)
2458 d->setFlag(Designable, value);
2459 }
2460
2461 /*!
2462 Sets this property to scriptable if \a value is true.
2463
2464 \sa isScriptable(), setDesignable(), setStored()
2465 */
setScriptable(bool value)2466 void QMetaPropertyBuilder::setScriptable(bool value)
2467 {
2468 QMetaPropertyBuilderPrivate *d = d_func();
2469 if (d)
2470 d->setFlag(Scriptable, value);
2471 }
2472
2473 /*!
2474 Sets this property to storable if \a value is true.
2475
2476 \sa isStored(), setDesignable(), setScriptable()
2477 */
setStored(bool value)2478 void QMetaPropertyBuilder::setStored(bool value)
2479 {
2480 QMetaPropertyBuilderPrivate *d = d_func();
2481 if (d)
2482 d->setFlag(Stored, value);
2483 }
2484
2485 /*!
2486 Sets this property to editable if \a value is true.
2487
2488 \sa isEditable(), setDesignable(), setScriptable(), setStored()
2489 */
setEditable(bool value)2490 void QMetaPropertyBuilder::setEditable(bool value)
2491 {
2492 QMetaPropertyBuilderPrivate *d = d_func();
2493 if (d)
2494 d->setFlag(Editable, value);
2495 }
2496
2497 /*!
2498 Sets the \c USER flag on this property to \a value.
2499
2500 \sa isUser(), setDesignable(), setScriptable()
2501 */
setUser(bool value)2502 void QMetaPropertyBuilder::setUser(bool value)
2503 {
2504 QMetaPropertyBuilderPrivate *d = d_func();
2505 if (d)
2506 d->setFlag(User, value);
2507 }
2508
2509 /*!
2510 Sets the C++ setter flag on this property to \a value, which is
2511 true if the property has a C++ setter function that follows Qt's
2512 standard "name" / "setName" pattern.
2513
2514 \sa hasStdCppSet()
2515 */
setStdCppSet(bool value)2516 void QMetaPropertyBuilder::setStdCppSet(bool value)
2517 {
2518 QMetaPropertyBuilderPrivate *d = d_func();
2519 if (d)
2520 d->setFlag(StdCppSet, value);
2521 }
2522
2523 /*!
2524 Sets this property to be of an enumerator or flag type if
2525 \a value is true.
2526
2527 \sa isEnumOrFlag()
2528 */
setEnumOrFlag(bool value)2529 void QMetaPropertyBuilder::setEnumOrFlag(bool value)
2530 {
2531 QMetaPropertyBuilderPrivate *d = d_func();
2532 if (d)
2533 d->setFlag(EnumOrFlag, value);
2534 }
2535
2536 /*!
2537 Sets the \c CONSTANT flag on this property to \a value.
2538
2539 \sa isConstant()
2540 */
setConstant(bool value)2541 void QMetaPropertyBuilder::setConstant(bool value)
2542 {
2543 QMetaPropertyBuilderPrivate *d = d_func();
2544 if (d)
2545 d->setFlag(Constant, value);
2546 }
2547
2548 /*!
2549 Sets the \c FINAL flag on this property to \a value.
2550
2551 \sa isFinal()
2552 */
setFinal(bool value)2553 void QMetaPropertyBuilder::setFinal(bool value)
2554 {
2555 QMetaPropertyBuilderPrivate *d = d_func();
2556 if (d)
2557 d->setFlag(Final, value);
2558 }
2559
2560 /*!
2561 Returns the revision of this property.
2562
2563 \sa setRevision()
2564 */
revision() const2565 int QMetaPropertyBuilder::revision() const
2566 {
2567 QMetaPropertyBuilderPrivate *d = d_func();
2568 if (d)
2569 return d->revision;
2570 return 0;
2571
2572 }
2573
2574 /*!
2575 Sets the \a revision of this property.
2576
2577 \sa revision()
2578 */
setRevision(int revision)2579 void QMetaPropertyBuilder::setRevision(int revision)
2580 {
2581 QMetaPropertyBuilderPrivate *d = d_func();
2582 if (d) {
2583 d->revision = revision;
2584 d->setFlag(Revisioned, revision != 0);
2585 }
2586 }
2587
2588
2589 /*!
2590 \class QMetaEnumBuilder
2591 \inmodule QtCore
2592 \internal
2593 \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
2594 */
2595
d_func() const2596 QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
2597 {
2598 if (_mobj && _index >= 0 && _index < int(_mobj->d->enumerators.size()))
2599 return &(_mobj->d->enumerators[_index]);
2600 else
2601 return nullptr;
2602 }
2603
2604 /*!
2605 \fn QMetaEnumBuilder::QMetaEnumBuilder()
2606 \internal
2607 */
2608
2609 /*!
2610 \fn int QMetaEnumBuilder::index() const
2611
2612 Returns the index of this enumerator within its QMetaObjectBuilder.
2613 */
2614
2615 /*!
2616 Returns the type name of the enumerator (without the scope).
2617 */
name() const2618 QByteArray QMetaEnumBuilder::name() const
2619 {
2620 QMetaEnumBuilderPrivate *d = d_func();
2621 if (d)
2622 return d->name;
2623 else
2624 return QByteArray();
2625 }
2626
2627 /*!
2628 Returns the enum name of the enumerator (without the scope).
2629
2630 \since 5.12
2631 */
enumName() const2632 QByteArray QMetaEnumBuilder::enumName() const
2633 {
2634 QMetaEnumBuilderPrivate *d = d_func();
2635 if (d)
2636 return d->enumName;
2637 else
2638 return QByteArray();
2639 }
2640
2641 /*!
2642 Sets this enumerator to have the enum name \c alias.
2643
2644 \since 5.12
2645 \sa isFlag(), enumName()
2646 */
setEnumName(const QByteArray & alias)2647 void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
2648 {
2649 QMetaEnumBuilderPrivate *d = d_func();
2650 if (d)
2651 d->enumName = alias;
2652 }
2653
2654 /*!
2655 Returns \c true if this enumerator is used as a flag; otherwise returns
2656 false.
2657
2658 \sa setIsFlag()
2659 */
isFlag() const2660 bool QMetaEnumBuilder::isFlag() const
2661 {
2662 QMetaEnumBuilderPrivate *d = d_func();
2663 if (d)
2664 return d->isFlag;
2665 else
2666 return false;
2667 }
2668
2669 /*!
2670 Sets this enumerator to be used as a flag if \a value is true.
2671
2672 \sa isFlag()
2673 */
setIsFlag(bool value)2674 void QMetaEnumBuilder::setIsFlag(bool value)
2675 {
2676 QMetaEnumBuilderPrivate *d = d_func();
2677 if (d)
2678 d->isFlag = value;
2679 }
2680
2681 /*!
2682 Return \c true if this enumerator should be considered scoped (C++11 enum class).
2683
2684 \sa setIsScoped()
2685 */
isScoped() const2686 bool QMetaEnumBuilder::isScoped() const
2687 {
2688 QMetaEnumBuilderPrivate *d = d_func();
2689 if (d)
2690 return d->isScoped;
2691 return false;
2692 }
2693
2694 /*!
2695 Sets this enumerator to be a scoped enum if \value is true
2696
2697 \sa isScoped()
2698 */
setIsScoped(bool value)2699 void QMetaEnumBuilder::setIsScoped(bool value)
2700 {
2701 QMetaEnumBuilderPrivate *d = d_func();
2702 if (d)
2703 d->isScoped = value;
2704 }
2705
2706 /*!
2707 Returns the number of keys.
2708
2709 \sa key(), addKey()
2710 */
keyCount() const2711 int QMetaEnumBuilder::keyCount() const
2712 {
2713 QMetaEnumBuilderPrivate *d = d_func();
2714 if (d)
2715 return d->keys.size();
2716 else
2717 return 0;
2718 }
2719
2720 /*!
2721 Returns the key with the given \a index, or an empty QByteArray
2722 if no such key exists.
2723
2724 \sa keyCount(), addKey(), value()
2725 */
key(int index) const2726 QByteArray QMetaEnumBuilder::key(int index) const
2727 {
2728 QMetaEnumBuilderPrivate *d = d_func();
2729 if (d && index >= 0 && index < d->keys.size())
2730 return d->keys[index];
2731 else
2732 return QByteArray();
2733 }
2734
2735 /*!
2736 Returns the value with the given \a index; or returns -1 if there
2737 is no such value.
2738
2739 \sa keyCount(), addKey(), key()
2740 */
value(int index) const2741 int QMetaEnumBuilder::value(int index) const
2742 {
2743 QMetaEnumBuilderPrivate *d = d_func();
2744 if (d && index >= 0 && index < d->keys.size())
2745 return d->values[index];
2746 else
2747 return -1;
2748 }
2749
2750 /*!
2751 Adds a new key called \a name to this enumerator, associated
2752 with \a value. Returns the index of the new key.
2753
2754 \sa keyCount(), key(), value(), removeKey()
2755 */
addKey(const QByteArray & name,int value)2756 int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
2757 {
2758 QMetaEnumBuilderPrivate *d = d_func();
2759 if (d) {
2760 int index = d->keys.size();
2761 d->keys += name;
2762 d->values += value;
2763 return index;
2764 } else {
2765 return -1;
2766 }
2767 }
2768
2769 /*!
2770 Removes the key at \a index from this enumerator.
2771
2772 \sa addKey()
2773 */
removeKey(int index)2774 void QMetaEnumBuilder::removeKey(int index)
2775 {
2776 QMetaEnumBuilderPrivate *d = d_func();
2777 if (d && index >= 0 && index < d->keys.size()) {
2778 d->keys.removeAt(index);
2779 d->values.removeAt(index);
2780 }
2781 }
2782
2783 QT_END_NAMESPACE
2784