source: trunk/src/corelib/kernel/qmetaobject.cpp@ 561

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

trunk: Merged in qt 4.6.1 sources.

File size: 79.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qmetaobject.h"
43#include "qmetatype.h"
44#include "qobject.h"
45
46#include <qcoreapplication.h>
47#include <qcoreevent.h>
48#include <qdatastream.h>
49#include <qstringlist.h>
50#include <qthread.h>
51#include <qvarlengtharray.h>
52#include <qvariant.h>
53#include <qhash.h>
54#include <qdebug.h>
55#include <qsemaphore.h>
56
57#include "private/qobject_p.h"
58#include "private/qmetaobject_p.h"
59
60#include <ctype.h>
61
62QT_BEGIN_NAMESPACE
63
64/*!
65 \class QMetaObject
66
67 \brief The QMetaObject class contains meta-information about Qt
68 objects.
69
70 \ingroup objectmodel
71
72 The Qt \l{Meta-Object System} in Qt is responsible for the
73 signals and slots inter-object communication mechanism, runtime
74 type information, and the Qt property system. A single
75 QMetaObject instance is created for each QObject subclass that is
76 used in an application, and this instance stores all the
77 meta-information for the QObject subclass. This object is
78 available as QObject::metaObject().
79
80 This class is not normally required for application programming,
81 but it is useful if you write meta-applications, such as scripting
82 engines or GUI builders.
83
84 The functions you are most likely to find useful are these:
85 \list
86 \o className() returns the name of a class.
87 \o superClass() returns the superclass's meta-object.
88 \o method() and methodCount() provide information
89 about a class's meta-methods (signals, slots and other
90 \l{Q_INVOKABLE}{invokable} member functions).
91 \o enumerator() and enumeratorCount() and provide information about
92 a class's enumerators.
93 \o propertyCount() and property() provide information about a
94 class's properties.
95 \o constructor() and constructorCount() provide information
96 about a class's meta-constructors.
97 \endlist
98
99 The index functions indexOfConstructor(), indexOfMethod(),
100 indexOfEnumerator(), and indexOfProperty() map names of constructors,
101 member functions, enumerators, or properties to indexes in the
102 meta-object. For example, Qt uses indexOfMethod() internally when you
103 connect a signal to a slot.
104
105 Classes can also have a list of \e{name}--\e{value} pairs of
106 additional class information, stored in QMetaClassInfo objects.
107 The number of pairs is returned by classInfoCount(), single pairs
108 are returned by classInfo(), and you can search for pairs with
109 indexOfClassInfo().
110
111 \sa QMetaClassInfo, QMetaEnum, QMetaMethod, QMetaProperty, QMetaType,
112 {Meta-Object System}
113*/
114
115/*!
116 \enum QMetaObject::Call
117
118 \internal
119
120 \value InvokeSlot
121 \value EmitSignal
122 \value ReadProperty
123 \value WriteProperty
124 \value ResetProperty
125 \value QueryPropertyDesignable
126 \value QueryPropertyScriptable
127 \value QueryPropertyStored
128 \value QueryPropertyEditable
129 \value QueryPropertyUser
130 \value CreateInstance
131*/
132
133/*!
134 \enum QMetaMethod::Access
135
136 This enum describes the access level of a method, following the conventions used in C++.
137
138 \value Private
139 \value Protected
140 \value Public
141*/
142
143static inline const QMetaObjectPrivate *priv(const uint* data)
144{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
145
146
147/*!
148 \since 4.5
149
150 Constructs a new instance of this class. You can pass up to ten arguments
151 (\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7,
152 \a val8, and \a val9) to the constructor. Returns the new object, or 0 if
153 no suitable constructor is available.
154
155 Note that only constructors that are declared with the Q_INVOKABLE
156 modifier are made available through the meta-object system.
157
158 \sa Q_ARG(), constructor()
159*/
160QObject *QMetaObject::newInstance(QGenericArgument val0,
161 QGenericArgument val1,
162 QGenericArgument val2,
163 QGenericArgument val3,
164 QGenericArgument val4,
165 QGenericArgument val5,
166 QGenericArgument val6,
167 QGenericArgument val7,
168 QGenericArgument val8,
169 QGenericArgument val9) const
170{
171 QByteArray constructorName = className();
172 {
173 int idx = constructorName.lastIndexOf(':');
174 if (idx != -1)
175 constructorName.remove(0, idx+1); // remove qualified part
176 }
177 QVarLengthArray<char, 512> sig;
178 sig.append(constructorName.constData(), constructorName.length());
179 sig.append('(');
180
181 enum { MaximumParamCount = 10 };
182 const char *typeNames[] = {val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
183 val5.name(), val6.name(), val7.name(), val8.name(), val9.name()};
184
185 int paramCount;
186 for (paramCount = 0; paramCount < MaximumParamCount; ++paramCount) {
187 int len = qstrlen(typeNames[paramCount]);
188 if (len <= 0)
189 break;
190 sig.append(typeNames[paramCount], len);
191 sig.append(',');
192 }
193 if (paramCount == 0)
194 sig.append(')'); // no parameters
195 else
196 sig[sig.size() - 1] = ')';
197 sig.append('\0');
198
199 int idx = indexOfConstructor(sig.constData());
200 if (idx < 0) {
201 QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
202 idx = indexOfConstructor(norm.constData());
203 }
204 if (idx < 0)
205 return 0;
206
207 QVariant ret(QMetaType::QObjectStar, (void*)0);
208 void *param[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
209 val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
210
211 if (static_metacall(CreateInstance, idx, param) >= 0)
212 return 0;
213 return *reinterpret_cast<QObject**>(param[0]);
214}
215
216/*!
217 \internal
218*/
219int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
220{
221 if (priv(d.data)->revision < 2)
222 return 0;
223 const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(d.extradata);
224 if (!extra || !extra->static_metacall)
225 return 0;
226 return extra->static_metacall(cl, idx, argv);
227}
228
229/*!
230 \internal
231*/
232int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
233{
234 if (QMetaObject *mo = object->d_ptr->metaObject)
235 return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv);
236 else
237 return object->qt_metacall(cl, idx, argv);
238}
239
240/*!
241 \fn const char *QMetaObject::className() const
242
243 Returns the class name.
244
245 \sa superClass()
246*/
247
248/*!
249 \fn QMetaObject *QMetaObject::superClass() const
250
251 Returns the meta-object of the superclass, or 0 if there is no
252 such object.
253
254 \sa className()
255*/
256
257/*!
258 \internal
259
260 Returns \a obj if object \a obj inherits from this
261 meta-object; otherwise returns 0.
262*/
263QObject *QMetaObject::cast(QObject *obj) const
264{
265 if (obj) {
266 const QMetaObject *m = obj->metaObject();
267 do {
268 if (m == this)
269 return const_cast<QObject*>(obj);
270 } while ((m = m->d.superdata));
271 }
272 return 0;
273}
274
275#ifndef QT_NO_TRANSLATION
276/*!
277 \internal
278*/
279QString QMetaObject::tr(const char *s, const char *c) const
280{
281 return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr);
282}
283
284/*!
285 \internal
286*/
287QString QMetaObject::tr(const char *s, const char *c, int n) const
288{
289 return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr, n);
290}
291
292/*!
293 \internal
294*/
295QString QMetaObject::trUtf8(const char *s, const char *c) const
296{
297 return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8);
298}
299
300/*!
301 \internal
302*/
303QString QMetaObject::trUtf8(const char *s, const char *c, int n) const
304{
305 return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8, n);
306}
307#endif // QT_NO_TRANSLATION
308
309/*!
310 Returns the method offset for this class; i.e. the index position
311 of this class's first member function.
312
313 The offset is the sum of all the methods in the class's
314 superclasses (which is always positive since QObject has the
315 deleteLater() slot and a destroyed() signal).
316
317 \sa method(), methodCount(), indexOfMethod()
318*/
319int QMetaObject::methodOffset() const
320{
321 int offset = 0;
322 const QMetaObject *m = d.superdata;
323 while (m) {
324 offset += priv(m->d.data)->methodCount;
325 m = m->d.superdata;
326 }
327 return offset;
328}
329
330
331/*!
332 Returns the enumerator offset for this class; i.e. the index
333 position of this class's first enumerator.
334
335 If the class has no superclasses with enumerators, the offset is
336 0; otherwise the offset is the sum of all the enumerators in the
337 class's superclasses.
338
339 \sa enumerator(), enumeratorCount(), indexOfEnumerator()
340*/
341int QMetaObject::enumeratorOffset() const
342{
343 int offset = 0;
344 const QMetaObject *m = d.superdata;
345 while (m) {
346 offset += priv(m->d.data)->enumeratorCount;
347 m = m->d.superdata;
348 }
349 return offset;
350}
351
352/*!
353 Returns the property offset for this class; i.e. the index
354 position of this class's first property.
355
356 The offset is the sum of all the properties in the class's
357 superclasses (which is always positive since QObject has the
358 name() property).
359
360 \sa property(), propertyCount(), indexOfProperty()
361*/
362int QMetaObject::propertyOffset() const
363{
364 int offset = 0;
365 const QMetaObject *m = d.superdata;
366 while (m) {
367 offset += priv(m->d.data)->propertyCount;
368 m = m->d.superdata;
369 }
370 return offset;
371}
372
373/*!
374 Returns the class information offset for this class; i.e. the
375 index position of this class's first class information item.
376
377 If the class has no superclasses with class information, the
378 offset is 0; otherwise the offset is the sum of all the class
379 information items in the class's superclasses.
380
381 \sa classInfo(), classInfoCount(), indexOfClassInfo()
382*/
383int QMetaObject::classInfoOffset() const
384{
385 int offset = 0;
386 const QMetaObject *m = d.superdata;
387 while (m) {
388 offset += priv(m->d.data)->classInfoCount;
389 m = m->d.superdata;
390 }
391 return offset;
392}
393
394/*!
395 \since 4.5
396
397 Returns the number of constructors in this class.
398
399 \sa constructor(), indexOfConstructor()
400*/
401int QMetaObject::constructorCount() const
402{
403 if (priv(d.data)->revision < 2)
404 return 0;
405 return priv(d.data)->constructorCount;
406}
407
408/*!
409 Returns the number of methods in this class, including the number of
410 properties provided by each base class. These include signals and slots
411 as well as normal member functions.
412
413 Use code like the following to obtain a QStringList containing the methods
414 specific to a given class:
415
416 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp methodCount
417
418 \sa method(), methodOffset(), indexOfMethod()
419*/
420int QMetaObject::methodCount() const
421{
422 int n = priv(d.data)->methodCount;
423 const QMetaObject *m = d.superdata;
424 while (m) {
425 n += priv(m->d.data)->methodCount;
426 m = m->d.superdata;
427 }
428 return n;
429}
430
431/*!
432 Returns the number of enumerators in this class.
433
434 \sa enumerator(), enumeratorOffset(), indexOfEnumerator()
435*/
436int QMetaObject::enumeratorCount() const
437{
438 int n = priv(d.data)->enumeratorCount;
439 const QMetaObject *m = d.superdata;
440 while (m) {
441 n += priv(m->d.data)->enumeratorCount;
442 m = m->d.superdata;
443 }
444 return n;
445}
446
447/*!
448 Returns the number of properties in this class, including the number of
449 properties provided by each base class.
450
451 Use code like the following to obtain a QStringList containing the properties
452 specific to a given class:
453
454 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp propertyCount
455
456 \sa property(), propertyOffset(), indexOfProperty()
457*/
458int QMetaObject::propertyCount() const
459{
460 int n = priv(d.data)->propertyCount;
461 const QMetaObject *m = d.superdata;
462 while (m) {
463 n += priv(m->d.data)->propertyCount;
464 m = m->d.superdata;
465 }
466 return n;
467}
468
469/*!
470 Returns the number of items of class information in this class.
471
472 \sa classInfo(), classInfoOffset(), indexOfClassInfo()
473*/
474int QMetaObject::classInfoCount() const
475{
476 int n = priv(d.data)->classInfoCount;
477 const QMetaObject *m = d.superdata;
478 while (m) {
479 n += priv(m->d.data)->classInfoCount;
480 m = m->d.superdata;
481 }
482 return n;
483}
484
485/*!
486 \since 4.5
487
488 Finds \a constructor and returns its index; otherwise returns -1.
489
490 Note that the \a constructor has to be in normalized form, as returned
491 by normalizedSignature().
492
493 \sa constructor(), constructorCount(), normalizedSignature()
494*/
495int QMetaObject::indexOfConstructor(const char *constructor) const
496{
497 if (priv(d.data)->revision < 2)
498 return -1;
499 for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) {
500 if (strcmp(constructor, d.stringdata
501 + d.data[priv(d.data)->constructorData + 5*i]) == 0) {
502 return i;
503 }
504 }
505 return -1;
506}
507
508/*!
509 Finds \a method and returns its index; otherwise returns -1.
510
511 Note that the \a method has to be in normalized form, as returned
512 by normalizedSignature().
513
514 \sa method(), methodCount(), methodOffset(), normalizedSignature()
515*/
516int QMetaObject::indexOfMethod(const char *method) const
517{
518 int i = -1;
519 const QMetaObject *m = this;
520 while (m && i < 0) {
521 for (i = priv(m->d.data)->methodCount-1; i >= 0; --i)
522 if (strcmp(method, m->d.stringdata
523 + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) {
524 i += m->methodOffset();
525 break;
526 }
527 m = m->d.superdata;
528 }
529 return i;
530}
531
532/*!
533 Finds \a signal and returns its index; otherwise returns -1.
534
535 This is the same as indexOfMethod(), except that it will return
536 -1 if the method exists but isn't a signal.
537
538 Note that the \a signal has to be in normalized form, as returned
539 by normalizedSignature().
540
541 \sa indexOfMethod(), normalizedSignature(), method(), methodCount(), methodOffset()
542*/
543int QMetaObject::indexOfSignal(const char *signal) const
544{
545 const QMetaObject *m = this;
546 int i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal);
547 if (i >= 0)
548 i += m->methodOffset();
549 return i;
550}
551
552/*! \internal
553 Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
554
555 \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
556*/
557int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject, const char *signal)
558{
559 int i = -1;
560 while (*baseObject) {
561 const QMetaObject *const m = *baseObject;
562 for (i = priv(m->d.data)->methodCount-1; i >= 0; --i)
563 if ((m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodSignal
564 && strcmp(signal, m->d.stringdata
565 + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) {
566 break;
567 }
568 if (i >= 0)
569 break;
570 *baseObject = m->d.superdata;
571 }
572#ifndef QT_NO_DEBUG
573 const QMetaObject *m = *baseObject;
574 if (i >= 0 && m && m->d.superdata) {
575 int conflict = m->d.superdata->indexOfMethod(signal);
576 if (conflict >= 0)
577 qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
578 signal, m->d.superdata->d.stringdata, m->d.stringdata);
579 }
580#endif
581 return i;
582}
583
584
585/*!
586 Finds \a slot and returns its index; otherwise returns -1.
587
588 This is the same as indexOfMethod(), except that it will return
589 -1 if the method exists but isn't a slot.
590
591 \sa indexOfMethod(), method(), methodCount(), methodOffset()
592*/
593int QMetaObject::indexOfSlot(const char *slot) const
594{
595 int i = -1;
596 const QMetaObject *m = this;
597 while (m && i < 0) {
598 for (i = priv(m->d.data)->methodCount-1; i >= 0; --i)
599 if ((m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodSlot
600 && strcmp(slot, m->d.stringdata
601 + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) {
602 i += m->methodOffset();
603 break;
604 }
605 m = m->d.superdata;
606 }
607 return i;
608}
609
610static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
611{
612 while (self) {
613 if (strcmp(self->d.stringdata, name) == 0)
614 return self;
615 if (self->d.extradata) {
616#ifdef Q_NO_DATA_RELOCATION
617 const QMetaObjectAccessor *e;
618 Q_ASSERT(priv(self->d.data)->revision >= 2);
619#else
620 const QMetaObject **e;
621 if (priv(self->d.data)->revision < 2) {
622 e = (const QMetaObject**)(self->d.extradata);
623 } else
624#endif
625 {
626 const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(self->d.extradata);
627 e = extra->objects;
628 }
629 if (e) {
630 while (*e) {
631#ifdef Q_NO_DATA_RELOCATION
632 if (const QMetaObject *m =QMetaObject_findMetaObject(&((*e)()), name))
633#else
634 if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
635#endif
636 return m;
637 ++e;
638 }
639 }
640 }
641 self = self->d.superdata;
642 }
643 return self;
644}
645
646/*!
647 Finds enumerator \a name and returns its index; otherwise returns
648 -1.
649
650 \sa enumerator(), enumeratorCount(), enumeratorOffset()
651*/
652int QMetaObject::indexOfEnumerator(const char *name) const
653{
654 int i = -1;
655 const QMetaObject *m = this;
656 while (m && i < 0) {
657 for (i = priv(m->d.data)->enumeratorCount-1; i >= 0; --i)
658 if (strcmp(name, m->d.stringdata
659 + m->d.data[priv(m->d.data)->enumeratorData + 4*i]) == 0) {
660 i += m->enumeratorOffset();
661 break;
662 }
663 m = m->d.superdata;
664 }
665 return i;
666}
667
668/*!
669 Finds property \a name and returns its index; otherwise returns
670 -1.
671
672 \sa property(), propertyCount(), propertyOffset()
673*/
674int QMetaObject::indexOfProperty(const char *name) const
675{
676 int i = -1;
677 const QMetaObject *m = this;
678 while (m && i < 0) {
679 for (i = priv(m->d.data)->propertyCount-1; i >= 0; --i)
680 if (strcmp(name, m->d.stringdata
681 + m->d.data[priv(m->d.data)->propertyData + 3*i]) == 0) {
682 i += m->propertyOffset();
683 break;
684 }
685 m = m->d.superdata;
686 }
687
688 if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){
689 QAbstractDynamicMetaObject *me =
690 const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
691
692 i = me->createProperty(name, 0);
693 }
694
695 return i;
696}
697
698/*!
699 Finds class information item \a name and returns its index;
700 otherwise returns -1.
701
702 \sa classInfo(), classInfoCount(), classInfoOffset()
703*/
704int QMetaObject::indexOfClassInfo(const char *name) const
705{
706 int i = -1;
707 const QMetaObject *m = this;
708 while (m && i < 0) {
709 for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
710 if (strcmp(name, m->d.stringdata
711 + m->d.data[priv(m->d.data)->classInfoData + 2*i]) == 0) {
712 i += m->classInfoOffset();
713 break;
714 }
715 m = m->d.superdata;
716 }
717 return i;
718}
719
720/*!
721 \since 4.5
722
723 Returns the meta-data for the constructor with the given \a index.
724
725 \sa constructorCount(), newInstance()
726*/
727QMetaMethod QMetaObject::constructor(int index) const
728{
729 int i = index;
730 QMetaMethod result;
731 if (priv(d.data)->revision >= 2 && i >= 0 && i < priv(d.data)->constructorCount) {
732 result.mobj = this;
733 result.handle = priv(d.data)->constructorData + 5*i;
734 }
735 return result;
736}
737
738/*!
739 Returns the meta-data for the method with the given \a index.
740
741 \sa methodCount(), methodOffset(), indexOfMethod()
742*/
743QMetaMethod QMetaObject::method(int index) const
744{
745 int i = index;
746 i -= methodOffset();
747 if (i < 0 && d.superdata)
748 return d.superdata->method(index);
749
750 QMetaMethod result;
751 if (i >= 0 && i < priv(d.data)->methodCount) {
752 result.mobj = this;
753 result.handle = priv(d.data)->methodData + 5*i;
754 }
755 return result;
756}
757
758/*!
759 Returns the meta-data for the enumerator with the given \a index.
760
761 \sa enumeratorCount(), enumeratorOffset(), indexOfEnumerator()
762*/
763QMetaEnum QMetaObject::enumerator(int index) const
764{
765 int i = index;
766 i -= enumeratorOffset();
767 if (i < 0 && d.superdata)
768 return d.superdata->enumerator(index);
769
770 QMetaEnum result;
771 if (i >= 0 && i < priv(d.data)->enumeratorCount) {
772 result.mobj = this;
773 result.handle = priv(d.data)->enumeratorData + 4*i;
774 }
775 return result;
776}
777
778/*!
779 Returns the meta-data for the property with the given \a index.
780 If no such property exists, a null QMetaProperty is returned.
781
782 \sa propertyCount(), propertyOffset(), indexOfProperty()
783*/
784QMetaProperty QMetaObject::property(int index) const
785{
786 int i = index;
787 i -= propertyOffset();
788 if (i < 0 && d.superdata)
789 return d.superdata->property(index);
790