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
791 QMetaProperty result;
792 if (i >= 0 && i < priv(d.data)->propertyCount) {
793 int handle = priv(d.data)->propertyData + 3*i;
794 int flags = d.data[handle + 2];
795 const char *type = d.stringdata + d.data[handle + 1];
796 result.mobj = this;
797 result.handle = handle;
798 result.idx = i;
799
800 if (flags & EnumOrFlag) {
801 result.menum = enumerator(indexOfEnumerator(type));
802 if (!result.menum.isValid()) {
803 QByteArray enum_name = type;
804 QByteArray scope_name = d.stringdata;
805 int s = enum_name.lastIndexOf("::");
806 if (s > 0) {
807 scope_name = enum_name.left(s);
808 enum_name = enum_name.mid(s + 2);
809 }
810 const QMetaObject *scope = 0;
811 if (scope_name == "Qt")
812 scope = &QObject::staticQtMetaObject;
813 else
814 scope = QMetaObject_findMetaObject(this, scope_name);
815 if (scope)
816 result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
817 }
818 }
819 }
820 return result;
821}
822
823/*!
824 \since 4.2
825
826 Returns the property that has the \c USER flag set to true.
827
828 \sa QMetaProperty::isUser()
829*/
830QMetaProperty QMetaObject::userProperty() const
831{
832 const int propCount = propertyCount();
833 for (int i = propCount - 1; i >= 0; --i) {
834 const QMetaProperty prop = property(i);
835 if (prop.isUser())
836 return prop;
837 }
838 return QMetaProperty();
839}
840
841/*!
842 Returns the meta-data for the item of class information with the
843 given \a index.
844
845 Example:
846
847 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 0
848
849 \sa classInfoCount(), classInfoOffset(), indexOfClassInfo()
850 */
851QMetaClassInfo QMetaObject::classInfo(int index) const
852{
853 int i = index;
854 i -= classInfoOffset();
855 if (i < 0 && d.superdata)
856 return d.superdata->classInfo(index);
857
858 QMetaClassInfo result;
859 if (i >= 0 && i < priv(d.data)->classInfoCount) {
860 result.mobj = this;
861 result.handle = priv(d.data)->classInfoData + 2*i;
862 }
863 return result;
864}
865
866/*!
867 Returns true if the \a signal and \a method arguments are
868 compatible; otherwise returns false.
869
870 Both \a signal and \a method are expected to be normalized.
871
872 \sa normalizedSignature()
873*/
874bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
875{
876 const char *s1 = signal;
877 const char *s2 = method;
878 while (*s1++ != '(') { } // scan to first '('
879 while (*s2++ != '(') { }
880 if (*s2 == ')' || qstrcmp(s1,s2) == 0) // method has no args or
881 return true; // exact match
882 int s1len = qstrlen(s1);
883 int s2len = qstrlen(s2);
884 if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
885 return true; // method has less args
886 return false;
887}
888
889static void qRemoveWhitespace(const char *s, char *d)
890{
891 char last = 0;
892 while (*s && is_space(*s))
893 s++;
894 while (*s) {
895 while (*s && !is_space(*s))
896 last = *d++ = *s++;
897 while (*s && is_space(*s))
898 s++;
899 if (*s && ((is_ident_char(*s) && is_ident_char(last))
900 || ((*s == ':') && (last == '<')))) {
901 last = *d++ = ' ';
902 }
903 }
904 *d = '\0';
905}
906
907static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
908{
909 const char *t = d;
910 while (*d && (templdepth
911 || (*d != ',' && *d != ')'))) {
912 if (*d == '<')
913 ++templdepth;
914 if (*d == '>')
915 --templdepth;
916 ++d;
917 }
918 if (strncmp("void", t, d - t) != 0)
919 result += normalizeTypeInternal(t, d);
920
921 return d;
922}
923
924
925/*!
926 \since 4.2
927
928 Normalizes a \a type.
929
930 See QMetaObject::normalizedSignature() for a description on how
931 Qt normalizes.
932
933 Example:
934
935 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 1
936
937 \sa normalizedSignature()
938 */
939QByteArray QMetaObject::normalizedType(const char *type)
940{
941 QByteArray result;
942
943 if (!type || !*type)
944 return result;
945
946 QVarLengthArray<char> stackbuf(int(strlen(type)) + 1);
947 qRemoveWhitespace(type, stackbuf.data());
948 int templdepth = 0;
949 qNormalizeType(stackbuf.data(), templdepth, result);
950
951 return result;
952}
953
954/*!
955 Normalizes the signature of the given \a method.
956
957 Qt uses normalized signatures to decide whether two given signals
958 and slots are compatible. Normalization reduces whitespace to a
959 minimum, moves 'const' to the front where appropriate, removes
960 'const' from value types and replaces const references with
961 values.
962
963 \sa checkConnectArgs(), normalizedType()
964 */
965QByteArray QMetaObject::normalizedSignature(const char *method)
966{
967 QByteArray result;
968 if (!method || !*method)
969 return result;
970 int len = int(strlen(method));
971 QVarLengthArray<char> stackbuf(len + 1);
972 char *d = stackbuf.data();
973 qRemoveWhitespace(method, d);
974
975 result.reserve(len);
976
977 int argdepth = 0;
978 int templdepth = 0;
979 while (*d) {
980 if (argdepth == 1)
981 d = qNormalizeType(d, templdepth, result);
982 if (*d == '(')
983 ++argdepth;
984 if (*d == ')')
985 --argdepth;
986 result += *d++;
987 }
988
989 return result;
990}
991
992enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
993
994/*!
995 Invokes the \a member (a signal or a slot name) on the object \a
996 obj. Returns true if the member could be invoked. Returns false
997 if there is no such member or the parameters did not match.
998
999 The invocation can be either synchronous or asynchronous,
1000 depending on \a type:
1001
1002 \list
1003 \o If \a type is Qt::DirectConnection, the member will be invoked immediately.
1004
1005 \o If \a type is Qt::QueuedConnection,
1006 a QEvent will be sent and the member is invoked as soon as the application
1007 enters the main event loop.
1008
1009 \o If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
1010 the same way as for Qt::QueuedConnection, except that the current thread
1011 will block until the event is delivered. Using this connection type to
1012 communicate between objects in the same thread will lead to deadlocks.
1013
1014 \o If \a type is Qt::AutoConnection, the member is invoked
1015 synchronously if \a obj lives in the same thread as the
1016 caller; otherwise it will invoke the member asynchronously.
1017 \endlist
1018
1019 The return value of the \a member function call is placed in \a
1020 ret. If the invocation is asynchronous, the return value cannot
1021 be evaluated. You can pass up to ten arguments (\a val0, \a val1,
1022 \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
1023 and \a val9) to the \a member function.
1024
1025 QGenericArgument and QGenericReturnArgument are internal
1026 helper classes. Because signals and slots can be dynamically
1027 invoked, you must enclose the arguments using the Q_ARG() and
1028 Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
1029 const reference of that type; Q_RETURN_ARG() takes a type name
1030 and a non-const reference.
1031
1032 You only need to pass the name of the signal or slot to this function,
1033 not the entire signature. For example, to asynchronously invoke
1034 the \l{QPushButton::animateClick()}{animateClick()} slot on a
1035 QPushButton, use the following code:
1036
1037 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 2
1038
1039 With asynchronous method invocations, the parameters must be of
1040 types that are known to Qt's meta-object system, because Qt needs
1041 to copy the arguments to store them in an event behind the
1042 scenes. If you try to use a queued connection and get the error
1043 message
1044
1045 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 3
1046
1047 call qRegisterMetaType() to register the data type before you
1048 call invokeMethod().
1049
1050 To synchronously invoke the \c compute(QString, int, double) slot on
1051 some arbitrary object \c obj retrieve its return value:
1052
1053 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 4
1054
1055 If the "compute" slot does not take exactly one QString, one int
1056 and one double in the specified order, the call will fail.
1057
1058 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaMethod::invoke()
1059*/
1060bool QMetaObject::invokeMethod(QObject *obj,
1061 const char *member,
1062 Qt::ConnectionType type,
1063 QGenericReturnArgument ret,
1064 QGenericArgument val0,
1065 QGenericArgument val1,
1066 QGenericArgument val2,
1067 QGenericArgument val3,
1068 QGenericArgument val4,
1069 QGenericArgument val5,
1070 QGenericArgument val6,
1071 QGenericArgument val7,
1072 QGenericArgument val8,
1073 QGenericArgument val9)
1074{
1075 if (!obj)
1076 return false;
1077
1078 QVarLengthArray<char, 512> sig;
1079 int len = qstrlen(member);
1080 if (len <= 0)
1081 return false;
1082 sig.append(member, len);
1083 sig.append('(');
1084
1085 const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
1086 val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
1087 val9.name()};
1088
1089 int paramCount;
1090 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
1091 len = qstrlen(typeNames[paramCount]);
1092 if (len <= 0)
1093 break;
1094 sig.append(typeNames[paramCount], len);
1095 sig.append(',');
1096 }
1097 if (paramCount == 1)
1098 sig.append(')'); // no parameters
1099 else
1100 sig[sig.size() - 1] = ')';
1101 sig.append('\0');
1102
1103 int idx = obj->metaObject()->indexOfMethod(sig.constData());
1104 if (idx < 0) {
1105 QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
1106 idx = obj->metaObject()->indexOfMethod(norm.constData());
1107 }
1108
1109 if (idx < 0 || idx >= obj->metaObject()->methodCount())
1110 return false;
1111 QMetaMethod method = obj->metaObject()->method(idx);
1112 return method.invoke(obj, type, ret,
1113 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
1114}
1115
1116/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1117 QGenericReturnArgument ret,
1118 QGenericArgument val0 = QGenericArgument(0),
1119 QGenericArgument val1 = QGenericArgument(),
1120 QGenericArgument val2 = QGenericArgument(),
1121 QGenericArgument val3 = QGenericArgument(),
1122 QGenericArgument val4 = QGenericArgument(),
1123 QGenericArgument val5 = QGenericArgument(),
1124 QGenericArgument val6 = QGenericArgument(),
1125 QGenericArgument val7 = QGenericArgument(),
1126 QGenericArgument val8 = QGenericArgument(),
1127 QGenericArgument val9 = QGenericArgument());
1128 \overload invokeMethod()
1129
1130 This overload always invokes the member using the connection type Qt::AutoConnection.
1131*/
1132
1133/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1134 Qt::ConnectionType type,
1135 QGenericArgument val0 = QGenericArgument(0),
1136 QGenericArgument val1 = QGenericArgument(),
1137 QGenericArgument val2 = QGenericArgument(),
1138 QGenericArgument val3 = QGenericArgument(),
1139 QGenericArgument val4 = QGenericArgument(),
1140 QGenericArgument val5 = QGenericArgument(),
1141 QGenericArgument val6 = QGenericArgument(),
1142 QGenericArgument val7 = QGenericArgument(),
1143 QGenericArgument val8 = QGenericArgument(),
1144 QGenericArgument val9 = QGenericArgument())
1145
1146 \overload invokeMethod()
1147
1148 This overload can be used if the return value of the member is of no interest.
1149*/
1150
1151/*!
1152 \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1153 QGenericArgument val0 = QGenericArgument(0),
1154 QGenericArgument val1 = QGenericArgument(),
1155 QGenericArgument val2 = QGenericArgument(),
1156 QGenericArgument val3 = QGenericArgument(),
1157 QGenericArgument val4 = QGenericArgument(),
1158 QGenericArgument val5 = QGenericArgument(),
1159 QGenericArgument val6 = QGenericArgument(),
1160 QGenericArgument val7 = QGenericArgument(),
1161 QGenericArgument val8 = QGenericArgument(),
1162 QGenericArgument val9 = QGenericArgument())
1163
1164 \overload invokeMethod()
1165
1166 This overload invokes the member using the connection type Qt::AutoConnection and
1167 ignores return values.
1168*/
1169
1170/*!
1171 \class QMetaMethod
1172
1173 \brief The QMetaMethod class provides meta-data about a member
1174 function.
1175
1176 \ingroup objectmodel
1177
1178 A QMetaMethod has a methodType(), a signature(), a list of
1179 parameterTypes() and parameterNames(), a return typeName(), a
1180 tag(), and an access() specifier. You can use invoke() to invoke
1181 the method on an arbitrary QObject.
1182
1183 \sa QMetaObject, QMetaEnum, QMetaProperty, {Qt's Property System}
1184*/
1185
1186/*!
1187 \enum QMetaMethod::Attributes
1188
1189 \internal
1190
1191 \value Compatibility
1192 \value Cloned
1193 \value Scriptable
1194*/
1195
1196/*!
1197 \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const
1198 \internal
1199*/
1200
1201/*!
1202 \enum QMetaMethod::MethodType
1203
1204 \value Method The function is a plain member function.
1205 \value Signal The function is a signal.
1206 \value Slot The function is a slot.
1207 \value Constructor The function is a constructor.
1208*/
1209
1210/*!
1211 \fn QMetaMethod::QMetaMethod()
1212 \internal
1213*/
1214
1215/*!
1216 Returns the signature of this method (e.g.,
1217 \c{setValue(double)}).
1218
1219 \sa parameterTypes(), parameterNames()
1220*/
1221const char *QMetaMethod::signature() const
1222{
1223 if (!mobj)
1224 return 0;
1225 return mobj->d.stringdata + mobj->d.data[handle];
1226}
1227
1228/*!
1229 Returns a list of parameter types.
1230
1231 \sa parameterNames(), signature()
1232*/
1233QList<QByteArray> QMetaMethod::parameterTypes() const
1234{
1235 QList<QByteArray> list;
1236 if (!mobj)
1237 return list;
1238 const char *signature = mobj->d.stringdata + mobj->d.data[handle];
1239 while (*signature && *signature != '(')
1240 ++signature;
1241 while (*signature && *signature != ')' && *++signature != ')') {
1242 const char *begin = signature;
1243 int level = 0;
1244 while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
1245 if (*signature == '<')
1246 ++level;
1247 else if (*signature == '>')
1248 --level;
1249 ++signature;
1250 }
1251 list += QByteArray(begin, signature - begin);
1252 }
1253 return list;
1254}
1255
1256/*!
1257 Returns a list of parameter names.
1258
1259 \sa parameterTypes(), signature()
1260*/
1261QList<QByteArray> QMetaMethod::parameterNames() const
1262{
1263 QList<QByteArray> list;
1264 if (!mobj)
1265 return list;
1266 const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
1267 if (*names == 0) {
1268 // do we have one or zero arguments?
1269 const char *signature = mobj->d.stringdata + mobj->d.data[handle];
1270 while (*signature && *signature != '(')
1271 ++signature;
1272 if (*++signature != ')')
1273 list += QByteArray();
1274 } else {
1275 --names;
1276 do {
1277 const char *begin = ++names;
1278 while (*names && *names != ',')
1279 ++names;
1280 list += QByteArray(begin, names - begin);
1281 } while (*names);
1282 }
1283 return list;
1284}
1285
1286
1287/*!
1288 Returns the return type of this method, or an empty string if the
1289 return type is \e void.
1290*/
1291const char *QMetaMethod::typeName() const
1292{
1293 if (!mobj)
1294 return 0;
1295 return mobj->d.stringdata + mobj->d.data[handle + 2];
1296}
1297
1298/*!
1299 Returns the tag associated with this method.
1300
1301 Tags are special macros recognized by \c moc that make it
1302 possible to add extra information about a method. For the moment,
1303 \c moc doesn't support any special tags.
1304*/
1305const char *QMetaMethod::tag() const
1306{
1307 if (!mobj)
1308 return 0;
1309 return mobj->d.stringdata + mobj->d.data[handle + 3];
1310}
1311
1312
1313/*! \internal */
1314int QMetaMethod::attributes() const
1315{
1316 if (!mobj)
1317 return false;
1318 return ((mobj->d.data[handle + 4])>>4);
1319}
1320
1321/*!
1322 \since 4.6
1323
1324 Returns this method's index.
1325*/
1326int QMetaMethod::methodIndex() const
1327{
1328 if (!mobj)
1329 return -1;
1330 return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
1331}
1332
1333/*!
1334 Returns the access specification of this method (private,
1335 protected, or public).
1336
1337 Signals are always protected, meaning that you can only emit them
1338 from the class or from a subclass.
1339
1340 \sa methodType()
1341*/
1342QMetaMethod::Access QMetaMethod::access() const
1343{
1344 if (!mobj)
1345 return Private;
1346 return (QMetaMethod::Access)(mobj->d.data[handle + 4] & AccessMask);
1347}
1348
1349/*!
1350 Returns the type of this method (signal, slot, or method).
1351
1352 \sa access()
1353*/
1354QMetaMethod::MethodType QMetaMethod::methodType() const
1355{
1356 if (!mobj)
1357 return QMetaMethod::Method;
1358 return (QMetaMethod::MethodType)((mobj->d.data[handle + 4] & MethodTypeMask)>>2);
1359}
1360
1361/*!
1362 Invokes this method on the object \a object. Returns true if the member could be invoked.
1363 Returns false if there is no such member or the parameters did not match.
1364
1365 The invocation can be either synchronous or asynchronous, depending on the
1366 \a connectionType:
1367
1368 \list
1369 \o If \a connectionType is Qt::DirectConnection, the member will be invoked immediately.
1370
1371 \o If \a connectionType is Qt::QueuedConnection,
1372 a QEvent will be posted and the member is invoked as soon as the application
1373 enters the main event loop.
1374
1375 \o If \a connectionType is Qt::AutoConnection, the member is invoked
1376 synchronously if \a object lives in the same thread as the
1377 caller; otherwise it will invoke the member asynchronously.
1378 \endlist
1379
1380 The return value of this method call is placed in \a
1381 returnValue. If the invocation is asynchronous, the return value cannot
1382 be evaluated. You can pass up to ten arguments (\a val0, \a val1,
1383 \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
1384 and \a val9) to this method call.
1385
1386 QGenericArgument and QGenericReturnArgument are internal
1387 helper classes. Because signals and slots can be dynamically
1388 invoked, you must enclose the arguments using the Q_ARG() and
1389 Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
1390 const reference of that type; Q_RETURN_ARG() takes a type name
1391 and a non-const reference.
1392
1393 To asynchronously invoke the
1394 \l{QPushButton::animateClick()}{animateClick()} slot on a
1395 QPushButton:
1396
1397 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 6
1398
1399 With asynchronous method invocations, the parameters must be of
1400 types that are known to Qt's meta-object system, because Qt needs
1401 to copy the arguments to store them in an event behind the
1402 scenes. If you try to use a queued connection and get the error
1403 message
1404
1405 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 7
1406
1407 call qRegisterMetaType() to register the data type before you
1408 call QMetaMethod::invoke().
1409
1410 To synchronously invoke the \c compute(QString, int, double) slot on
1411 some arbitrary object \c obj retrieve its return value:
1412
1413 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 8
1414
1415 QMetaObject::normalizedSignature() is used here to ensure that the format
1416 of the signature is what invoke() expects. E.g. extra whitespace is
1417 removed.
1418
1419 If the "compute" slot does not take exactly one QString, one int
1420 and one double in the specified order, the call will fail.
1421
1422 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
1423*/
1424bool QMetaMethod::invoke(QObject *object,
1425 Qt::ConnectionType connectionType,
1426 QGenericReturnArgument returnValue,
1427 QGenericArgument val0,
1428 QGenericArgument val1,
1429 QGenericArgument val2,
1430 QGenericArgument val3,
1431 QGenericArgument val4,
1432 QGenericArgument val5,
1433 QGenericArgument val6,
1434 QGenericArgument val7,
1435 QGenericArgument val8,
1436 QGenericArgument val9) const
1437{
1438 if (!object || !mobj)
1439 return false;
1440
1441 // check return type
1442 if (returnValue.data()) {
1443 const char *retType = typeName();
1444 if (qstrcmp(returnValue.name(), retType) != 0) {
1445 // normalize the return value as well
1446 // the trick here is to make a function signature out of the return type
1447 // so that we can call normalizedSignature() and avoid duplicating code
1448 QByteArray unnormalized;
1449 int len = qstrlen(returnValue.name());
1450
1451 unnormalized.reserve(len + 3);
1452 unnormalized = "_("; // the function is called "_"
1453 unnormalized.append(returnValue.name());
1454 unnormalized.append(')');
1455
1456 QByteArray normalized = QMetaObject::normalizedSignature(unnormalized.constData());
1457 normalized.truncate(normalized.length() - 1); // drop the ending ')'
1458
1459 if (qstrcmp(normalized.constData() + 2, retType) != 0)
1460 return false;
1461 }
1462 }
1463
1464 // check argument count (we don't allow invoking a method if given too few arguments)
1465 const char *typeNames[] = {
1466 returnValue.name(),
1467 val0.name(),
1468 val1.name(),
1469 val2.name(),
1470 val3.name(),
1471 val4.name(),
1472 val5.name(),
1473 val6.name(),
1474 val7.name(),
1475 val8.name(),
1476 val9.name()
1477 };
1478 int paramCount;
1479 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
1480 if (qstrlen(typeNames[paramCount]) <= 0)
1481 break;
1482 }
1483 int metaMethodArgumentCount = 0;
1484 {
1485 // based on QMetaObject::parameterNames()
1486 const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
1487 if (*names == 0) {
1488 // do we have one or zero arguments?
1489 const char *signature = mobj->d.stringdata + mobj->d.data[handle];
1490 while (*signature && *signature != '(')
1491 ++signature;
1492 if (*++signature != ')')
1493 ++metaMethodArgumentCount;
1494 } else {
1495 --names;
1496 do {
1497 ++names;
1498 while (*names && *names != ',')
1499 ++names;
1500 ++metaMethodArgumentCount;
1501 } while (*names);
1502 }
1503 }
1504 if (paramCount <= metaMethodArgumentCount)
1505 return false;
1506
1507 // check connection type
1508 QThread *currentThread = QThread::currentThread();
1509 QThread *objectThread = object->thread();
1510 if (connectionType == Qt::AutoConnection) {
1511 connectionType = currentThread == objectThread
1512 ? Qt::DirectConnection
1513 : Qt::QueuedConnection;
1514 }
1515
1516 // invoke!
1517 void *param[] = {
1518 returnValue.data(),
1519 val0.data(),
1520 val1.data(),
1521 val2.data(),
1522 val3.data(),
1523 val4.data(),
1524 val5.data(),
1525 val6.data(),
1526 val7.data(),
1527 val8.data(),
1528 val9.data()
1529 };
1530 // recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
1531 int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
1532 if (connectionType == Qt::DirectConnection) {
1533 return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
1534 } else {
1535 if (returnValue.data()) {
1536 qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
1537 "queued connections");
1538 return false;
1539 }
1540
1541 int nargs = 1; // include return type
1542 void **args = (void **) qMalloc(paramCount * sizeof(void *));
1543 Q_CHECK_PTR(args);
1544 int *types = (int *) qMalloc(paramCount * sizeof(int));
1545 Q_CHECK_PTR(types);
1546 types[0] = 0; // return type
1547 args[0] = 0;
1548
1549 for (int i = 1; i < paramCount; ++i) {
1550 types[i] = QMetaType::type(typeNames[i]);
1551 if (types[i]) {
1552 args[i] = QMetaType::construct(types[i], param[i]);
1553 ++nargs;
1554 } else if (param[i]) {
1555 qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
1556 typeNames[i]);
1557 for (int x = 1; x < i; ++x) {
1558 if (types[x] && args[x])
1559 QMetaType::destroy(types[x], args[x]);
1560 }
1561 qFree(types);
1562 qFree(args);
1563 return false;
1564 }
1565 }
1566
1567 if (connectionType == Qt::QueuedConnection) {
1568 QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
1569 0,
1570 -1,
1571 nargs,
1572 types,
1573 args));
1574 } else {
1575 if (currentThread == objectThread) {
1576 qWarning("QMetaMethod::invoke: Dead lock detected in "
1577 "BlockingQueuedConnection: Receiver is %s(%p)",
1578 mobj->className(), object);
1579 }
1580
1581 // blocking queued connection
1582#ifdef QT_NO_THREAD
1583 QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
1584 0,
1585 -1,
1586 nargs,
1587 types,
1588 args));
1589#else
1590 QSemaphore semaphore;
1591 QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
1592 0,
1593 -1,
1594 nargs,
1595 types,
1596 args,
1597 &semaphore));
1598 semaphore.acquire();
1599#endif // QT_NO_THREAD
1600 }
1601 }
1602 return true;
1603}
1604
1605/*! \fn bool QMetaMethod::invoke(QObject *object,
1606 QGenericReturnArgument returnValue,
1607 QGenericArgument val0 = QGenericArgument(0),
1608 QGenericArgument val1 = QGenericArgument(),
1609 QGenericArgument val2 = QGenericArgument(),
1610 QGenericArgument val3 = QGenericArgument(),
1611 QGenericArgument val4 = QGenericArgument(),
1612 QGenericArgument val5 = QGenericArgument(),
1613 QGenericArgument val6 = QGenericArgument(),
1614 QGenericArgument val7 = QGenericArgument(),
1615 QGenericArgument val8 = QGenericArgument(),
1616 QGenericArgument val9 = QGenericArgument()) const
1617 \overload invoke()
1618
1619 This overload always invokes this method using the connection type Qt::AutoConnection.
1620*/
1621
1622/*! \fn bool QMetaMethod::invoke(QObject *object,
1623 Qt::ConnectionType connectionType,
1624 QGenericArgument val0 = QGenericArgument(0),
1625 QGenericArgument val1 = QGenericArgument(),
1626 QGenericArgument val2 = QGenericArgument(),
1627 QGenericArgument val3 = QGenericArgument(),
1628 QGenericArgument val4 = QGenericArgument(),
1629 QGenericArgument val5 = QGenericArgument(),
1630 QGenericArgument val6 = QGenericArgument(),
1631 QGenericArgument val7 = QGenericArgument(),
1632 QGenericArgument val8 = QGenericArgument(),
1633 QGenericArgument val9 = QGenericArgument()) const
1634
1635 \overload invoke()
1636
1637 This overload can be used if the return value of the member is of no interest.
1638*/
1639
1640/*!
1641 \fn bool QMetaMethod::invoke(QObject *object,
1642 QGenericArgument val0 = QGenericArgument(0),
1643 QGenericArgument val1 = QGenericArgument(),
1644 QGenericArgument val2 = QGenericArgument(),
1645 QGenericArgument val3 = QGenericArgument(),
1646 QGenericArgument val4 = QGenericArgument(),
1647 QGenericArgument val5 = QGenericArgument(),
1648 QGenericArgument val6 = QGenericArgument(),
1649 QGenericArgument val7 = QGenericArgument(),
1650 QGenericArgument val8 = QGenericArgument(),
1651 QGenericArgument val9 = QGenericArgument()) const
1652
1653 \overload invoke()
1654
1655 This overload invokes this method using the
1656 connection type Qt::AutoConnection and ignores return values.
1657*/
1658
1659/*!
1660 \class QMetaEnum
1661 \brief The QMetaEnum class provides meta-data about an enumerator.
1662
1663 \ingroup objectmodel
1664
1665 Use name() for the enumerator's name. The enumerator's keys (names
1666 of each enumerated item) are returned by key(); use keyCount() to find
1667 the number of keys. isFlag() returns whether the enumerator is
1668 meant to be used as a flag, meaning that its values can be combined
1669 using the OR operator.
1670
1671 The conversion functions keyToValue(), valueToKey(), keysToValue(),
1672 and valueToKeys() allow conversion between the integer
1673 representation of an enumeration or set value and its literal
1674 representation. The scope() function returns the class scope this
1675 enumerator was declared in.
1676
1677 \sa QMetaObject, QMetaMethod, QMetaProperty
1678*/
1679
1680/*!
1681 \fn bool QMetaEnum::isValid() const
1682
1683 Returns true if this enum is valid (has a name); otherwise returns
1684 false.
1685
1686 \sa name()
1687*/
1688
1689/*!
1690 \fn const QMetaObject *QMetaEnum::enclosingMetaObject() const
1691 \internal
1692*/
1693
1694
1695/*!
1696 \fn QMetaEnum::QMetaEnum()
1697 \internal
1698*/
1699
1700/*!
1701 Returns the name of the enumerator (without the scope).
1702
1703 For example, the Qt::AlignmentFlag enumeration has \c
1704 AlignmentFlag as the name and \l Qt as the scope.
1705
1706 \sa isValid(), scope()
1707*/
1708const char *QMetaEnum::name() const
1709{
1710 if (!mobj)
1711 return 0;
1712 return mobj->d.stringdata + mobj->d.data[handle];
1713}
1714
1715/*!
1716 Returns the number of keys.
1717
1718 \sa key()
1719*/
1720int QMetaEnum::keyCount() const
1721{
1722 if (!mobj)
1723 return 0;
1724 return mobj->d.data[handle + 2];
1725}
1726
1727
1728/*!
1729 Returns the key with the given \a index, or 0 if no such key exists.
1730
1731 \sa keyCount(), value(), valueToKey()
1732*/
1733const char *QMetaEnum::key(int index) const
1734{
1735 if (!mobj)
1736 return 0;
1737 int count = mobj->d.data[handle + 2];
1738 int data = mobj->d.data[handle + 3];
1739 if (index >= 0 && index < count)
1740 return mobj->d.stringdata + mobj->d.data[data + 2*index];
1741 return 0;
1742}
1743
1744/*!
1745 Returns the value with the given \a index; or returns -1 if there
1746 is no such value.
1747
1748 \sa keyCount(), key(), keyToValue()
1749*/
1750int QMetaEnum::value(int index) const
1751{
1752 if (!mobj)
1753 return 0;
1754 int count = mobj->d.data[handle + 2];
1755 int data = mobj->d.data[handle + 3];
1756 if (index >= 0 && index < count)
1757 return mobj->d.data[data + 2*index + 1];
1758 return -1;
1759}
1760
1761
1762/*!
1763 Returns true if this enumerator is used as a flag; otherwise returns
1764 false.
1765
1766 When used as flags, enumerators can be combined using the OR
1767 operator.
1768
1769 \sa keysToValue(), valueToKeys()
1770*/
1771bool QMetaEnum::isFlag() const
1772{
1773 return mobj && mobj->d.data[handle + 1];
1774}
1775
1776
1777/*!
1778 Returns the scope this enumerator was declared in.
1779
1780 For example, the Qt::AlignmentFlag enumeration has \c Qt as
1781 the scope and \c AlignmentFlag as the name.
1782
1783 \sa name()
1784*/
1785const char *QMetaEnum::scope() const
1786{
1787 return mobj?mobj->d.stringdata : 0;
1788}
1789
1790/*!
1791 Returns the integer value of the given enumeration \a key, or -1
1792 if \a key is not defined.
1793
1794 For flag types, use keysToValue().
1795
1796 \sa valueToKey(), isFlag(), keysToValue()
1797*/
1798int QMetaEnum::keyToValue(const char *key) const
1799{
1800 if (!mobj || !key)
1801 return -1;
1802 uint scope = 0;
1803 const char *qualified_key = key;
1804 const char *s = key + qstrlen(key);
1805 while (s > key && *s != ':')
1806 --s;
1807 if (s > key && *(s-1)==':') {
1808 scope = s - key - 1;
1809 key += scope + 2;
1810 }
1811 int count = mobj->d.data[handle + 2];
1812 int data = mobj->d.data[handle + 3];
1813 for (int i = 0; i < count; ++i)
1814 if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key, mobj->d.stringdata, scope) == 0))
1815 && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0)
1816 return mobj->d.data[data + 2*i + 1];
1817 return -1;
1818}
1819
1820/*!
1821 Returns the string that is used as the name of the given
1822 enumeration \a value, or 0 if \a value is not defined.
1823
1824 For flag types, use valueToKeys().
1825
1826 \sa isFlag(), valueToKeys()
1827*/
1828const char* QMetaEnum::valueToKey(int value) const
1829{
1830 if (!mobj)
1831 return 0;
1832 int count = mobj->d.data[handle + 2];
1833 int data = mobj->d.data[handle + 3];
1834 for (int i = 0; i < count; ++i)
1835 if (value == (int)mobj->d.data[data + 2*i + 1])
1836 return mobj->d.stringdata + mobj->d.data[data + 2*i];
1837 return 0;
1838}
1839
1840/*!
1841 Returns the value derived from combining together the values of
1842 the \a keys using the OR operator, or -1 if \a keys is not
1843 defined. Note that the strings in \a keys must be '|'-separated.
1844
1845 \sa isFlag(), valueToKey(), valueToKeys()
1846*/
1847int QMetaEnum::keysToValue(const char *keys) const
1848{
1849 if (!mobj)
1850 return -1;
1851 QStringList l = QString::fromLatin1(keys).split(QLatin1Char('|'));
1852 //#### TODO write proper code, do not use QStringList
1853 int value = 0;
1854 int count = mobj->d.data[handle + 2];
1855 int data = mobj->d.data[handle + 3];
1856 for (int li = 0; li < l.size(); ++li) {
1857 QString trimmed = l.at(li).trimmed();
1858 QByteArray qualified_key = trimmed.toLatin1();
1859 const char *key = qualified_key.constData();
1860 uint scope = 0;
1861 const char *s = key + qstrlen(key);
1862 while (s > key && *s != ':')
1863 --s;
1864 if (s > key && *(s-1)==':') {
1865 scope = s - key - 1;
1866 key += scope + 2;
1867 }
1868 int i;
1869 for (i = count-1; i >= 0; --i)
1870 if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key.constData(), mobj->d.stringdata, scope) == 0))
1871 && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0) {
1872 value |= mobj->d.data[data + 2*i + 1];
1873 break;
1874 }
1875 if (i < 0)
1876 value |= -1;
1877 }
1878 return value;
1879}
1880
1881/*!
1882 Returns a byte array of '|'-separated keys that represents the
1883 given \a value.
1884
1885 \sa isFlag(), valueToKey(), keysToValue()
1886*/
1887QByteArray QMetaEnum::valueToKeys(int value) const
1888{
1889 QByteArray keys;
1890 if (!mobj)
1891 return keys;
1892 int count = mobj->d.data[handle + 2];
1893 int data = mobj->d.data[handle + 3];
1894 int v = value;
1895 for(int i = 0; i < count; i++) {
1896 int k = mobj->d.data[data + 2*i + 1];
1897 if ((k != 0 && (v & k) == k ) || (k == value)) {
1898 v = v & ~k;
1899 if (!keys.isEmpty())
1900 keys += '|';
1901 keys += mobj->d.stringdata + mobj->d.data[data + 2*i];
1902 }
1903 }
1904 return keys;
1905}
1906
1907static QByteArray qualifiedName(const QMetaEnum &e)
1908{
1909 return QByteArray(e.scope()) + "::" + e.name();
1910}
1911
1912/*!
1913 \class QMetaProperty
1914 \brief The QMetaProperty class provides meta-data about a property.
1915
1916 \ingroup objectmodel
1917
1918 Property meta-data is obtained from an object's meta-object. See
1919 QMetaObject::property() and QMetaObject::propertyCount() for
1920 details.
1921
1922 \section1 Property Meta-Data
1923
1924 A property has a name() and a type(), as well as various
1925 attributes that specify its behavior: isReadable(), isWritable(),
1926 isDesignable(), isScriptable(), and isStored().
1927
1928 If the property is an enumeration, isEnumType() returns true; if the
1929 property is an enumeration that is also a flag (i.e. its values
1930 can be combined using the OR operator), isEnumType() and
1931 isFlagType() both return true. The enumerator for these types is
1932 available from enumerator().
1933
1934 The property's values are set and retrieved with read(), write(),
1935 and reset(); they can also be changed through QObject's set and get
1936 functions. See QObject::setProperty() and QObject::property() for
1937 details.
1938
1939 \section1 Copying and Assignment
1940
1941 QMetaProperty objects can be copied by value. However, each copy will
1942 refer to the same underlying property meta-data.
1943
1944 \sa QMetaObject, QMetaEnum, QMetaMethod, {Qt's Property System}
1945*/
1946
1947/*!
1948 \fn bool QMetaProperty::isValid() const
1949
1950 Returns true if this property is valid (readable); otherwise
1951 returns false.
1952
1953 \sa isReadable()
1954*/
1955
1956/*!
1957 \fn const QMetaObject *QMetaProperty::enclosingMetaObject() const
1958 \internal
1959*/
1960
1961/*!
1962 \internal
1963*/
1964QMetaProperty::QMetaProperty()
1965 : mobj(0), handle(0), idx(0)
1966{
1967}
1968
1969
1970/*!
1971 Returns this property's name.
1972
1973 \sa type(), typeName()
1974*/
1975const char *QMetaProperty::name() const
1976{
1977 if (!mobj)
1978 return 0;
1979 int handle = priv(mobj->d.data)->propertyData + 3*idx;
1980 return mobj->d.stringdata + mobj->d.data[handle];
1981}
1982
1983/*!
1984 Returns the name of this property's type.
1985
1986 \sa type(), name()
1987*/
1988const char *QMetaProperty::typeName() const
1989{
1990 if (!mobj)
1991 return 0;
1992 int handle = priv(mobj->d.data)->propertyData + 3*idx;
1993 return mobj->d.stringdata + mobj->d.data[handle + 1];
1994}
1995
1996/*!
1997 Returns this property's type. The return value is one
1998 of the values of the QVariant::Type enumeration.
1999
2000 \sa userType(), typeName(), name()
2001*/
2002QVariant::Type QMetaProperty::type() const
2003{
2004 if (!mobj)
2005 return QVariant::Invalid;
2006 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2007 uint flags = mobj->d.data[handle + 2];
2008
2009 uint type = flags >> 24;
2010 if (type == 0xff) // special value for QVariant
2011 type = QVariant::LastType;
2012 if (type)
2013 return QVariant::Type(type);
2014 if (isEnumType()) {
2015 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2016 if (enumMetaTypeId == 0)
2017 return QVariant::Int;
2018 }
2019#ifdef QT_COORD_TYPE
2020 // qreal metatype must be resolved at runtime.
2021 if (strcmp(typeName(), "qreal") == 0)
2022 return QVariant::Type(qMetaTypeId<qreal>());
2023#endif
2024
2025 return QVariant::UserType;
2026}
2027
2028/*!
2029 \since 4.2
2030
2031 Returns this property's user type. The return value is one
2032 of the values that are registered with QMetaType, or 0 if
2033 the type is not registered.
2034
2035 \sa type(), QMetaType, typeName()
2036 */
2037int QMetaProperty::userType() const
2038{
2039 QVariant::Type tp = type();
2040 if (tp != QVariant::UserType)
2041 return tp;
2042 if (isEnumType()) {
2043 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2044 return enumMetaTypeId;
2045 }
2046 return QMetaType::type(typeName());
2047}
2048
2049/*!
2050 \since 4.6
2051
2052 Returns this property's index.
2053*/
2054int QMetaProperty::propertyIndex() const
2055{
2056 if (!mobj)
2057 return -1;
2058 return idx + mobj->propertyOffset();
2059}
2060
2061/*!
2062 Returns true if the property's type is an enumeration value that
2063 is used as a flag; otherwise returns false.
2064
2065 Flags can be combined using the OR operator. A flag type is
2066 implicitly also an enum type.
2067
2068 \sa isEnumType(), enumerator(), QMetaEnum::isFlag()
2069*/
2070
2071bool QMetaProperty::isFlagType() const
2072{
2073 return isEnumType() && menum.isFlag();
2074}
2075
2076/*!
2077 Returns true if the property's type is an enumeration value;
2078 otherwise returns false.
2079
2080 \sa enumerator(), isFlagType()
2081*/
2082bool QMetaProperty::isEnumType() const
2083{
2084 if (!mobj)
2085 return false;
2086 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2087 int flags = mobj->d.data[handle + 2];
2088 return (flags & EnumOrFlag) && menum.name();
2089}
2090
2091/*!
2092 \internal
2093
2094 Returns true if the property has a C++ setter function that
2095 follows Qt's standard "name" / "setName" pattern. Designer and uic
2096 query hasStdCppSet() in order to avoid expensive
2097 QObject::setProperty() calls. All properties in Qt [should] follow
2098 this pattern.
2099*/
2100bool QMetaProperty::hasStdCppSet() const
2101{
2102 if (!mobj)
2103 return false;
2104 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2105 int flags = mobj->d.data[handle + 2];
2106 return (flags & StdCppSet);
2107}
2108
2109/*!
2110 Returns the enumerator if this property's type is an enumerator
2111 type; otherwise the returned value is undefined.
2112
2113 \sa isEnumType(), isFlagType()
2114*/
2115QMetaEnum QMetaProperty::enumerator() const
2116{
2117 return menum;
2118}
2119
2120/*!
2121 Reads the property's value from the given \a object. Returns the value
2122 if it was able to read it; otherwise returns an invalid variant.
2123
2124 \sa write(), reset(), isReadable()
2125*/
2126QVariant QMetaProperty::read(const QObject *object) const
2127{
2128 if (!object || !mobj)
2129 return QVariant();
2130
2131 uint t = QVariant::Int;
2132 if (isEnumType()) {
2133 /*
2134 try to create a QVariant that can be converted to this enum
2135 type (only works if the enum has already been registered
2136 with QMetaType)
2137 */
2138 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2139 if (enumMetaTypeId != 0)
2140 t = enumMetaTypeId;
2141 } else {
2142 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2143 uint flags = mobj->d.data[handle + 2];
2144 const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
2145 t = (flags >> 24);
2146 if (t == 0xff) // special value for QVariant
2147 t = QVariant::LastType;
2148 if (t == QVariant::Invalid)
2149 t = QMetaType::type(typeName);
2150 if (t == QVariant::Invalid)
2151 t = QVariant::nameToType(typeName);
2152 if (t == QVariant::Invalid || t == QVariant::UserType) {
2153 if (t == QVariant::Invalid)
2154 qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
2155 return QVariant();
2156 }
2157 }
2158
2159 // the status variable is changed by qt_metacall to indicate what it did
2160 // this feature is currently only used by QtDBus and should not be depended
2161 // upon. Don't change it without looking into QDBusAbstractInterface first
2162 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
2163 // changed: result stored directly in value
2164 int status = -1;
2165 QVariant value;
2166 void *argv[] = { 0, &value, &status };
2167 if (t == QVariant::LastType) {
2168 argv[0] = &value;
2169 } else {
2170 value = QVariant(t, (void*)0);
2171 argv[0] = value.data();
2172 }
2173 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
2174 idx + mobj->propertyOffset(), argv);
2175
2176 if (status != -1)
2177 return value;
2178 if (t != QVariant::LastType && argv[0] != value.data())
2179 // pointer or reference
2180 return QVariant((QVariant::Type)t, argv[0]);
2181 return value;
2182}
2183
2184/*!
2185 Writes \a value as the property's value to the given \a object. Returns
2186 true if the write succeeded; otherwise returns false.
2187
2188 \sa read(), reset(), isWritable()
2189*/
2190bool QMetaProperty::write(QObject *object, const QVariant &value) const
2191{
2192 if (!object || !isWritable())
2193 return false;
2194
2195 QVariant v = value;
2196 uint t = QVariant::Invalid;
2197 if (isEnumType()) {
2198 if (v.type() == QVariant::String
2199#ifdef QT3_SUPPORT
2200 || v.type() == QVariant::CString
2201#endif
2202 ) {
2203 if (isFlagType())
2204 v = QVariant(menum.keysToValue(value.toByteArray()));
2205 else
2206 v = QVariant(menum.keyToValue(value.toByteArray()));
2207 } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
2208 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2209 if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
2210 return false;
2211 v = QVariant(*reinterpret_cast<const int *>(v.constData()));
2212 }
2213 v.convert(QVariant::Int);
2214 } else {
2215 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2216 uint flags = mobj->d.data[handle + 2];
2217 t = flags >> 24;
2218 if (t == 0xff) // special value for QVariant
2219 t = QVariant::LastType;
2220 if (t == QVariant::Invalid) {
2221 const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
2222 const char *vtypeName = value.typeName();
2223 if (vtypeName && strcmp(typeName, vtypeName) == 0)
2224 t = value.userType();
2225 else
2226 t = QVariant::nameToType(typeName);
2227 }
2228 if (t == QVariant::Invalid)
2229 return false;
2230 if (t != QVariant::LastType && t != (uint)value.userType() && (t < QMetaType::User && !v.convert((QVariant::Type)t)))
2231 return false;
2232 }
2233
2234 // the status variable is changed by qt_metacall to indicate what it did
2235 // this feature is currently only used by QtDBus and should not be depended
2236 // upon. Don't change it without looking into QDBusAbstractInterface first
2237 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
2238 // changed: result stored directly in value, return the value of status
2239 int status = -1;
2240 // the flags variable is used by the declarative module to implement
2241 // interception of property writes.
2242 int flags = 0;
2243 void *argv[] = { 0, &v, &status, &flags };
2244 if (t == QVariant::LastType)
2245 argv[0] = &v;
2246 else
2247 argv[0] = v.data();
2248 QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
2249 return status;
2250}
2251
2252/*!
2253 Resets the property for the given \a object with a reset method.
2254 Returns true if the reset worked; otherwise returns false.
2255
2256 Reset methods are optional; only a few properties support them.
2257
2258 \sa read(), write()
2259*/
2260bool QMetaProperty::reset(QObject *object) const
2261{
2262 if (!object || !mobj || !isResettable())
2263 return false;
2264 void *argv[] = { 0 };
2265 QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
2266 return true;
2267}
2268
2269/*!
2270 Returns true if this property can be reset to a default value; otherwise
2271 returns false.
2272
2273 \sa reset()
2274*/
2275bool QMetaProperty::isResettable() const
2276{
2277 if (!mobj)
2278 return false;
2279 int flags = mobj->d.data[handle + 2];
2280 return flags & Resettable;
2281}
2282
2283/*!
2284 Returns true if this property is readable; otherwise returns false.
2285
2286 \sa isWritable(), read(), isValid()
2287 */
2288bool QMetaProperty::isReadable() const
2289{
2290 if (!mobj)
2291 return false;
2292 int flags = mobj->d.data[handle + 2];
2293 return flags & Readable;
2294}
2295
2296/*!
2297 Returns true if this property has a corresponding change notify signal;
2298 otherwise returns false.
2299
2300 \sa notifySignal()
2301 */
2302bool QMetaProperty::hasNotifySignal() const
2303{
2304 if (!mobj)
2305 return false;
2306 int flags = mobj->d.data[handle + 2];
2307 return flags & Notify;
2308}
2309
2310/*!
2311 \since 4.5
2312
2313 Returns the QMetaMethod instance of the property change notifying signal if
2314 one was specified, otherwise returns an invalid QMetaMethod.
2315
2316 \sa hasNotifySignal()
2317 */
2318QMetaMethod QMetaProperty::notifySignal() const
2319{
2320 int id = notifySignalIndex();
2321 if (id != -1)
2322 return mobj->method(id);
2323 else
2324 return QMetaMethod();
2325}
2326
2327/*!
2328 \since 4.6
2329
2330 Returns the index of the property change notifying signal if one was
2331 specified, otherwise returns -1.
2332
2333 \sa hasNotifySignal()
2334 */
2335int QMetaProperty::notifySignalIndex() const
2336{
2337 if (hasNotifySignal()) {
2338 int offset = priv(mobj->d.data)->propertyData +
2339 priv(mobj->d.data)->propertyCount * 3 + idx;
2340 return mobj->d.data[offset] + mobj->methodOffset();
2341 } else {
2342 return -1;
2343 }
2344}
2345
2346/*!
2347 Returns true if this property is writable; otherwise returns
2348 false.
2349
2350 \sa isReadable(), write()
2351 */
2352bool QMetaProperty::isWritable() const
2353{
2354 if (!mobj)
2355 return false;
2356 int flags = mobj->d.data[handle + 2];
2357 return flags & Writable;
2358}
2359
2360
2361/*!
2362 Returns true if this property is designable for the given \a object;
2363 otherwise returns false.
2364
2365 If no \a object is given, the function returns false if the
2366 \c{Q_PROPERTY()}'s \c DESIGNABLE attribute is false; otherwise
2367 returns true (if the attribute is true or is a function or expression).
2368
2369 \sa isScriptable(), isStored()
2370*/
2371bool QMetaProperty::isDesignable(const QObject *object) const
2372{
2373 if (!mobj)
2374 return false;
2375 int flags = mobj->d.data[handle + 2];
2376 bool b = flags & Designable;
2377 if (object) {
2378 void *argv[] = { &b };
2379 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable,
2380 idx + mobj->propertyOffset(), argv);
2381 }
2382 return b;
2383
2384
2385}
2386
2387/*!
2388 Returns true if the property is scriptable for the given \a object;
2389 otherwise returns false.
2390
2391 If no \a object is given, the function returns false if the
2392 \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute is false; otherwise returns
2393 true (if the attribute is true or is a function or expression).
2394
2395 \sa isDesignable(), isStored()
2396*/
2397bool QMetaProperty::isScriptable(const QObject *object) const
2398{
2399 if (!mobj)
2400 return false;
2401 int flags = mobj->d.data[handle + 2];
2402 bool b = flags & Scriptable;
2403 if (object) {
2404 void *argv[] = { &b };
2405 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable,
2406 idx + mobj->propertyOffset(), argv);
2407 }
2408 return b;
2409}
2410
2411/*!
2412 Returns true if the property is stored for \a object; otherwise returns
2413 false.
2414
2415 If no \a object is given, the function returns false if the
2416 \c{Q_PROPERTY()}'s \c STORED attribute is false; otherwise returns
2417 true (if the attribute is true or is a function or expression).
2418
2419 \sa isDesignable(), isScriptable()
2420*/
2421bool QMetaProperty::isStored(const QObject *object) const
2422{
2423 if (!mobj)
2424 return false;
2425 int flags = mobj->d.data[handle + 2];
2426 bool b = flags & Stored;
2427 if (object) {
2428 void *argv[] = { &b };
2429 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored,
2430 idx + mobj->propertyOffset(), argv);
2431 }
2432 return b;
2433}
2434
2435/*!
2436 Returns true if this property is designated as the \c USER
2437 property, i.e., the one that the user can edit for \a object or
2438 that is significant in some other way. Otherwise it returns
2439 false. e.g., the \c text property is the \c USER editable property
2440 of a QLineEdit.
2441
2442 If \a object is null, the function returns false if the \c
2443 {Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns
2444 true.
2445
2446 \sa QMetaObject::userProperty(), isDesignable(), isScriptable()
2447*/
2448bool QMetaProperty::isUser(const QObject *object) const
2449{
2450 if (!mobj)
2451 return false;
2452 int flags = mobj->d.data[handle + 2];
2453 bool b = flags & User;
2454 if (object) {
2455 void *argv[] = { &b };
2456 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser,
2457 idx + mobj->propertyOffset(), argv);
2458 }
2459 return b;
2460}
2461
2462/*!
2463 \since 4.6
2464 Returns true if the property is constant; otherwise returns false.
2465
2466 A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute
2467 is set.
2468*/
2469bool QMetaProperty::isConstant() const
2470{
2471 if (!mobj)
2472 return false;
2473 int flags = mobj->d.data[handle + 2];
2474 return flags & Constant;
2475}
2476
2477/*!
2478 \since 4.6
2479 Returns true if the property is final; otherwise returns false.
2480
2481 A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute
2482 is set.
2483*/
2484bool QMetaProperty::isFinal() const
2485{
2486 if (!mobj)
2487 return false;
2488 int flags = mobj->d.data[handle + 2];
2489 return flags & Final;
2490}
2491
2492/*!
2493 \obsolete
2494
2495 Returns true if the property is editable for the given \a object;
2496 otherwise returns false.
2497
2498 If no \a object is given, the function returns false if the
2499 \c{Q_PROPERTY()}'s \c EDITABLE attribute is false; otherwise returns
2500 true (if the attribute is true or is a function or expression).
2501
2502 \sa isDesignable(), isScriptable(), isStored()
2503*/
2504bool QMetaProperty::isEditable(const QObject *object) const
2505{
2506 if (!mobj)
2507 return false;
2508 int flags = mobj->d.data[handle + 2];
2509 bool b = flags & Editable;
2510 if (object) {
2511 void *argv[] = { &b };
2512 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable,
2513 idx + mobj->propertyOffset(), argv);
2514 }
2515 return b;
2516}
2517
2518/*!
2519 \class QMetaClassInfo
2520
2521 \brief The QMetaClassInfo class provides additional information
2522 about a class.
2523
2524 \ingroup objectmodel
2525
2526 Class information items are simple \e{name}--\e{value} pairs that
2527 are specified using Q_CLASSINFO() in the source code. The
2528 information can be retrieved using name() and value(). For example:
2529
2530 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 5
2531
2532 This mechanism is free for you to use in your Qt applications. Qt
2533 doesn't use it for any of its classes.
2534
2535 \sa QMetaObject
2536*/
2537
2538
2539/*!
2540 \fn QMetaClassInfo::QMetaClassInfo()
2541 \internal
2542*/
2543
2544/*!
2545 \fn const QMetaObject *QMetaClassInfo::enclosingMetaObject() const
2546 \internal
2547*/
2548
2549/*!
2550 Returns the name of this item.
2551
2552 \sa value()
2553*/
2554const char *QMetaClassInfo::name() const
2555{
2556 if (!mobj)
2557 return 0;
2558 return mobj->d.stringdata + mobj->d.data[handle];
2559}
2560
2561/*!
2562 Returns the value of this item.
2563
2564 \sa name()
2565*/
2566const char* QMetaClassInfo::value() const
2567{
2568 if (!mobj)
2569 return 0;
2570 return mobj->d.stringdata + mobj->d.data[handle + 1];
2571}
2572
2573/*!
2574 \macro QGenericArgument Q_ARG(Type, const Type &value)
2575 \relates QMetaObject
2576
2577 This macro takes a \a Type and a \a value of that type and
2578 returns a \l QGenericArgument object that can be passed to
2579 QMetaObject::invokeMethod().
2580
2581 \sa Q_RETURN_ARG()
2582*/
2583
2584/*!
2585 \macro QGenericReturnArgument Q_RETURN_ARG(Type, Type &value)
2586 \relates QMetaObject
2587
2588 This macro takes a \a Type and a non-const reference to a \a
2589 value of that type and returns a QGenericReturnArgument object
2590 that can be passed to QMetaObject::invokeMethod().
2591
2592 \sa Q_ARG()
2593*/
2594
2595/*!
2596 \class QGenericArgument
2597
2598 \brief The QGenericArgument class is an internal helper class for
2599 marshalling arguments.
2600
2601 This class should never be used directly. Please use the \l Q_ARG()
2602 macro instead.
2603
2604 \sa Q_ARG(), QMetaObject::invokeMethod(), QGenericReturnArgument
2605*/
2606
2607/*!
2608 \fn QGenericArgument::QGenericArgument(const char *name, const void *data)
2609
2610 Constructs a QGenericArgument object with the given \a name and \a data.
2611*/
2612
2613/*!
2614 \fn QGenericArgument::data () const
2615
2616 Returns the data set in the constructor.
2617*/
2618
2619/*!
2620 \fn QGenericArgument::name () const
2621
2622 Returns the name set in the constructor.
2623*/
2624
2625/*!
2626 \class QGenericReturnArgument
2627
2628 \brief The QGenericReturnArgument class is an internal helper class for
2629 marshalling arguments.
2630
2631 This class should never be used directly. Please use the
2632 Q_RETURN_ARG() macro instead.
2633
2634 \sa Q_RETURN_ARG(), QMetaObject::invokeMethod(), QGenericArgument
2635*/
2636
2637/*!
2638 \fn QGenericReturnArgument::QGenericReturnArgument(const char *name, void *data)
2639
2640 Constructs a QGenericReturnArgument object with the given \a name
2641 and \a data.
2642*/
2643
2644/*! \internal
2645 If the local_method_index is a cloned method, return the index of the original.
2646
2647 Example: if the index of "destroyed()" is passed, the index of "destroyed(QObject*)" is returned
2648 */
2649int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
2650{
2651 Q_ASSERT(local_method_index < get(mobj)->methodCount);
2652 int handle = get(mobj)->methodData + 5 * local_method_index;
2653 while (mobj->d.data[handle + 4] & MethodCloned) {
2654 Q_ASSERT(local_method_index > 0);
2655 handle -= 5;
2656 local_method_index--;
2657 }
2658 return local_method_index;
2659}
2660
2661QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.