PageRenderTime 70ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/qt/qtbase/src/corelib/kernel/qmetaobject.cpp

https://code.google.com/
C++ | 3398 lines | 1734 code | 249 blank | 1415 comment | 487 complexity | 692bb25d9f11fb6cc585321634091d29 MD5 | raw file
Possible License(s): LGPL-3.0, CC-BY-SA-4.0, MIT, AGPL-3.0, BSD-3-Clause, LGPL-2.1, CC0-1.0, GPL-2.0, LGPL-2.0, GPL-3.0
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  4. ** Contact: http://www.qt-project.org/legal
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:LGPL$
  9. ** Commercial License Usage
  10. ** Licensees holding valid commercial Qt licenses may use this file in
  11. ** accordance with the commercial license agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and Digia. For licensing terms and
  14. ** conditions see http://qt.digia.com/licensing. For further information
  15. ** use the contact form at http://qt.digia.com/contact-us.
  16. **
  17. ** GNU Lesser General Public License Usage
  18. ** Alternatively, this file may be used under the terms of the GNU Lesser
  19. ** General Public License version 2.1 as published by the Free Software
  20. ** Foundation and appearing in the file LICENSE.LGPL included in the
  21. ** packaging of this file. Please review the following information to
  22. ** ensure the GNU Lesser General Public License version 2.1 requirements
  23. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  24. **
  25. ** In addition, as a special exception, Digia gives you certain additional
  26. ** rights. These rights are described in the Digia Qt LGPL Exception
  27. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  28. **
  29. ** GNU General Public License Usage
  30. ** Alternatively, this file may be used under the terms of the GNU
  31. ** General Public License version 3.0 as published by the Free Software
  32. ** Foundation and appearing in the file LICENSE.GPL included in the
  33. ** packaging of this file. Please review the following information to
  34. ** ensure the GNU General Public License version 3.0 requirements will be
  35. ** met: http://www.gnu.org/copyleft/gpl.html.
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qmetaobject.h"
  42. #include "qmetatype.h"
  43. #include "qobject.h"
  44. #include "qmetaobject_p.h"
  45. #include <qcoreapplication.h>
  46. #include <qcoreevent.h>
  47. #include <qdatastream.h>
  48. #include <qstringlist.h>
  49. #include <qthread.h>
  50. #include <qvariant.h>
  51. #include <qhash.h>
  52. #include <qdebug.h>
  53. #include <qsemaphore.h>
  54. #include "private/qobject_p.h"
  55. #include "private/qmetaobject_p.h"
  56. // for normalizeTypeInternal
  57. #include "private/qmetaobject_moc_p.h"
  58. #include <ctype.h>
  59. QT_BEGIN_NAMESPACE
  60. /*!
  61. \class QMetaObject
  62. \inmodule QtCore
  63. \brief The QMetaObject class contains meta-information about Qt
  64. objects.
  65. \ingroup objectmodel
  66. The Qt \l{Meta-Object System} in Qt is responsible for the
  67. signals and slots inter-object communication mechanism, runtime
  68. type information, and the Qt property system. A single
  69. QMetaObject instance is created for each QObject subclass that is
  70. used in an application, and this instance stores all the
  71. meta-information for the QObject subclass. This object is
  72. available as QObject::metaObject().
  73. This class is not normally required for application programming,
  74. but it is useful if you write meta-applications, such as scripting
  75. engines or GUI builders.
  76. The functions you are most likely to find useful are these:
  77. \list
  78. \li className() returns the name of a class.
  79. \li superClass() returns the superclass's meta-object.
  80. \li method() and methodCount() provide information
  81. about a class's meta-methods (signals, slots and other
  82. \l{Q_INVOKABLE}{invokable} member functions).
  83. \li enumerator() and enumeratorCount() and provide information about
  84. a class's enumerators.
  85. \li propertyCount() and property() provide information about a
  86. class's properties.
  87. \li constructor() and constructorCount() provide information
  88. about a class's meta-constructors.
  89. \endlist
  90. The index functions indexOfConstructor(), indexOfMethod(),
  91. indexOfEnumerator(), and indexOfProperty() map names of constructors,
  92. member functions, enumerators, or properties to indexes in the
  93. meta-object. For example, Qt uses indexOfMethod() internally when you
  94. connect a signal to a slot.
  95. Classes can also have a list of \e{name}--\e{value} pairs of
  96. additional class information, stored in QMetaClassInfo objects.
  97. The number of pairs is returned by classInfoCount(), single pairs
  98. are returned by classInfo(), and you can search for pairs with
  99. indexOfClassInfo().
  100. \sa QMetaClassInfo, QMetaEnum, QMetaMethod, QMetaProperty, QMetaType,
  101. {Meta-Object System}
  102. */
  103. /*!
  104. \enum QMetaObject::Call
  105. \internal
  106. \value InvokeSlot
  107. \value EmitSignal
  108. \value ReadProperty
  109. \value WriteProperty
  110. \value ResetProperty
  111. \value QueryPropertyDesignable
  112. \value QueryPropertyScriptable
  113. \value QueryPropertyStored
  114. \value QueryPropertyEditable
  115. \value QueryPropertyUser
  116. \value CreateInstance
  117. */
  118. /*!
  119. \enum QMetaMethod::Access
  120. This enum describes the access level of a method, following the conventions used in C++.
  121. \value Private
  122. \value Protected
  123. \value Public
  124. */
  125. static inline const QMetaObjectPrivate *priv(const uint* data)
  126. { return reinterpret_cast<const QMetaObjectPrivate*>(data); }
  127. static inline const QByteArray stringData(const QMetaObject *mo, int index)
  128. {
  129. Q_ASSERT(priv(mo->d.data)->revision >= 7);
  130. const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) };
  131. Q_ASSERT(data.ptr->ref.isStatic());
  132. Q_ASSERT(data.ptr->alloc == 0);
  133. Q_ASSERT(data.ptr->capacityReserved == 0);
  134. Q_ASSERT(data.ptr->size >= 0);
  135. return data;
  136. }
  137. static inline const char *rawStringData(const QMetaObject *mo, int index)
  138. {
  139. return stringData(mo, index).data();
  140. }
  141. static inline int stringSize(const QMetaObject *mo, int index)
  142. {
  143. return stringData(mo, index).size();
  144. }
  145. static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
  146. {
  147. if (typeInfo & IsUnresolvedType) {
  148. return stringData(mo, typeInfo & TypeNameIndexMask);
  149. } else {
  150. // ### Use the QMetaType::typeName() that returns QByteArray
  151. const char *t = QMetaType::typeName(typeInfo);
  152. return QByteArray::fromRawData(t, qstrlen(t));
  153. }
  154. }
  155. static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
  156. {
  157. return typeNameFromTypeInfo(mo, typeInfo).constData();
  158. }
  159. static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
  160. {
  161. if (!(typeInfo & IsUnresolvedType))
  162. return typeInfo;
  163. return QMetaType::type(stringData(mo, typeInfo & TypeNameIndexMask));
  164. }
  165. class QMetaMethodPrivate : public QMetaMethod
  166. {
  167. public:
  168. static const QMetaMethodPrivate *get(const QMetaMethod *q)
  169. { return static_cast<const QMetaMethodPrivate *>(q); }
  170. inline QByteArray signature() const;
  171. inline QByteArray name() const;
  172. inline int typesDataIndex() const;
  173. inline const char *rawReturnTypeName() const;
  174. inline int returnType() const;
  175. inline int parameterCount() const;
  176. inline int parametersDataIndex() const;
  177. inline uint parameterTypeInfo(int index) const;
  178. inline int parameterType(int index) const;
  179. inline void getParameterTypes(int *types) const;
  180. inline QList<QByteArray> parameterTypes() const;
  181. inline QList<QByteArray> parameterNames() const;
  182. inline QByteArray tag() const;
  183. inline int ownMethodIndex() const;
  184. private:
  185. QMetaMethodPrivate();
  186. };
  187. /*!
  188. \since 4.5
  189. Constructs a new instance of this class. You can pass up to ten arguments
  190. (\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7,
  191. \a val8, and \a val9) to the constructor. Returns the new object, or 0 if
  192. no suitable constructor is available.
  193. Note that only constructors that are declared with the Q_INVOKABLE
  194. modifier are made available through the meta-object system.
  195. \sa Q_ARG(), constructor()
  196. */
  197. QObject *QMetaObject::newInstance(QGenericArgument val0,
  198. QGenericArgument val1,
  199. QGenericArgument val2,
  200. QGenericArgument val3,
  201. QGenericArgument val4,
  202. QGenericArgument val5,
  203. QGenericArgument val6,
  204. QGenericArgument val7,
  205. QGenericArgument val8,
  206. QGenericArgument val9) const
  207. {
  208. QByteArray constructorName = className();
  209. {
  210. int idx = constructorName.lastIndexOf(':');
  211. if (idx != -1)
  212. constructorName.remove(0, idx+1); // remove qualified part
  213. }
  214. QVarLengthArray<char, 512> sig;
  215. sig.append(constructorName.constData(), constructorName.length());
  216. sig.append('(');
  217. enum { MaximumParamCount = 10 };
  218. const char *typeNames[] = {val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
  219. val5.name(), val6.name(), val7.name(), val8.name(), val9.name()};
  220. int paramCount;
  221. for (paramCount = 0; paramCount < MaximumParamCount; ++paramCount) {
  222. int len = qstrlen(typeNames[paramCount]);
  223. if (len <= 0)
  224. break;
  225. sig.append(typeNames[paramCount], len);
  226. sig.append(',');
  227. }
  228. if (paramCount == 0)
  229. sig.append(')'); // no parameters
  230. else
  231. sig[sig.size() - 1] = ')';
  232. sig.append('\0');
  233. int idx = indexOfConstructor(sig.constData());
  234. if (idx < 0) {
  235. QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
  236. idx = indexOfConstructor(norm.constData());
  237. }
  238. if (idx < 0)
  239. return 0;
  240. QObject *returnValue = 0;
  241. void *param[] = {&returnValue, val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
  242. val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
  243. if (static_metacall(CreateInstance, idx, param) >= 0)
  244. return 0;
  245. return returnValue;
  246. }
  247. /*!
  248. \internal
  249. */
  250. int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
  251. {
  252. Q_ASSERT(priv(d.data)->revision >= 6);
  253. if (!d.static_metacall)
  254. return 0;
  255. d.static_metacall(0, cl, idx, argv);
  256. return -1;
  257. }
  258. /*!
  259. \internal
  260. */
  261. int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
  262. {
  263. if (object->d_ptr->metaObject)
  264. return object->d_ptr->metaObject->metaCall(object, cl, idx, argv);
  265. else
  266. return object->qt_metacall(cl, idx, argv);
  267. }
  268. /*!
  269. Returns the class name.
  270. \sa superClass()
  271. */
  272. const char *QMetaObject::className() const
  273. {
  274. return rawStringData(this, 0);
  275. }
  276. /*!
  277. \fn QMetaObject *QMetaObject::superClass() const
  278. Returns the meta-object of the superclass, or 0 if there is no
  279. such object.
  280. \sa className()
  281. */
  282. /*!
  283. \internal
  284. Returns \a obj if object \a obj inherits from this
  285. meta-object; otherwise returns 0.
  286. */
  287. QObject *QMetaObject::cast(QObject *obj) const
  288. {
  289. if (obj) {
  290. const QMetaObject *m = obj->metaObject();
  291. do {
  292. if (m == this)
  293. return obj;
  294. } while ((m = m->d.superdata));
  295. }
  296. return 0;
  297. }
  298. /*!
  299. \internal
  300. Returns \a obj if object \a obj inherits from this
  301. meta-object; otherwise returns 0.
  302. */
  303. const QObject *QMetaObject::cast(const QObject *obj) const
  304. {
  305. if (obj) {
  306. const QMetaObject *m = obj->metaObject();
  307. do {
  308. if (m == this)
  309. return obj;
  310. } while ((m = m->d.superdata));
  311. }
  312. return 0;
  313. }
  314. #ifndef QT_NO_TRANSLATION
  315. /*!
  316. \internal
  317. */
  318. QString QMetaObject::tr(const char *s, const char *c, int n) const
  319. {
  320. return QCoreApplication::translate(rawStringData(this, 0), s, c, n);
  321. }
  322. #endif // QT_NO_TRANSLATION
  323. /*!
  324. Returns the method offset for this class; i.e. the index position
  325. of this class's first member function.
  326. The offset is the sum of all the methods in the class's
  327. superclasses (which is always positive since QObject has the
  328. deleteLater() slot and a destroyed() signal).
  329. \sa method(), methodCount(), indexOfMethod()
  330. */
  331. int QMetaObject::methodOffset() const
  332. {
  333. int offset = 0;
  334. const QMetaObject *m = d.superdata;
  335. while (m) {
  336. offset += priv(m->d.data)->methodCount;
  337. m = m->d.superdata;
  338. }
  339. return offset;
  340. }
  341. /*!
  342. Returns the enumerator offset for this class; i.e. the index
  343. position of this class's first enumerator.
  344. If the class has no superclasses with enumerators, the offset is
  345. 0; otherwise the offset is the sum of all the enumerators in the
  346. class's superclasses.
  347. \sa enumerator(), enumeratorCount(), indexOfEnumerator()
  348. */
  349. int QMetaObject::enumeratorOffset() const
  350. {
  351. int offset = 0;
  352. const QMetaObject *m = d.superdata;
  353. while (m) {
  354. offset += priv(m->d.data)->enumeratorCount;
  355. m = m->d.superdata;
  356. }
  357. return offset;
  358. }
  359. /*!
  360. Returns the property offset for this class; i.e. the index
  361. position of this class's first property.
  362. The offset is the sum of all the properties in the class's
  363. superclasses (which is always positive since QObject has the
  364. name() property).
  365. \sa property(), propertyCount(), indexOfProperty()
  366. */
  367. int QMetaObject::propertyOffset() const
  368. {
  369. int offset = 0;
  370. const QMetaObject *m = d.superdata;
  371. while (m) {
  372. offset += priv(m->d.data)->propertyCount;
  373. m = m->d.superdata;
  374. }
  375. return offset;
  376. }
  377. /*!
  378. Returns the class information offset for this class; i.e. the
  379. index position of this class's first class information item.
  380. If the class has no superclasses with class information, the
  381. offset is 0; otherwise the offset is the sum of all the class
  382. information items in the class's superclasses.
  383. \sa classInfo(), classInfoCount(), indexOfClassInfo()
  384. */
  385. int QMetaObject::classInfoOffset() const
  386. {
  387. int offset = 0;
  388. const QMetaObject *m = d.superdata;
  389. while (m) {
  390. offset += priv(m->d.data)->classInfoCount;
  391. m = m->d.superdata;
  392. }
  393. return offset;
  394. }
  395. /*!
  396. \since 4.5
  397. Returns the number of constructors in this class.
  398. \sa constructor(), indexOfConstructor()
  399. */
  400. int QMetaObject::constructorCount() const
  401. {
  402. Q_ASSERT(priv(d.data)->revision >= 2);
  403. return priv(d.data)->constructorCount;
  404. }
  405. /*!
  406. Returns the number of methods in this class, including the number of
  407. methods provided by each base class. These include signals and slots
  408. as well as normal member functions.
  409. Use code like the following to obtain a QStringList containing the methods
  410. specific to a given class:
  411. \snippet code/src_corelib_kernel_qmetaobject.cpp methodCount
  412. \sa method(), methodOffset(), indexOfMethod()
  413. */
  414. int QMetaObject::methodCount() const
  415. {
  416. int n = priv(d.data)->methodCount;
  417. const QMetaObject *m = d.superdata;
  418. while (m) {
  419. n += priv(m->d.data)->methodCount;
  420. m = m->d.superdata;
  421. }
  422. return n;
  423. }
  424. /*!
  425. Returns the number of enumerators in this class.
  426. \sa enumerator(), enumeratorOffset(), indexOfEnumerator()
  427. */
  428. int QMetaObject::enumeratorCount() const
  429. {
  430. int n = priv(d.data)->enumeratorCount;
  431. const QMetaObject *m = d.superdata;
  432. while (m) {
  433. n += priv(m->d.data)->enumeratorCount;
  434. m = m->d.superdata;
  435. }
  436. return n;
  437. }
  438. /*!
  439. Returns the number of properties in this class, including the number of
  440. properties provided by each base class.
  441. Use code like the following to obtain a QStringList containing the properties
  442. specific to a given class:
  443. \snippet code/src_corelib_kernel_qmetaobject.cpp propertyCount
  444. \sa property(), propertyOffset(), indexOfProperty()
  445. */
  446. int QMetaObject::propertyCount() const
  447. {
  448. int n = priv(d.data)->propertyCount;
  449. const QMetaObject *m = d.superdata;
  450. while (m) {
  451. n += priv(m->d.data)->propertyCount;
  452. m = m->d.superdata;
  453. }
  454. return n;
  455. }
  456. /*!
  457. Returns the number of items of class information in this class.
  458. \sa classInfo(), classInfoOffset(), indexOfClassInfo()
  459. */
  460. int QMetaObject::classInfoCount() const
  461. {
  462. int n = priv(d.data)->classInfoCount;
  463. const QMetaObject *m = d.superdata;
  464. while (m) {
  465. n += priv(m->d.data)->classInfoCount;
  466. m = m->d.superdata;
  467. }
  468. return n;
  469. }
  470. // Returns \c true if the method defined by the given meta-object&handle
  471. // matches the given name, argument count and argument types, otherwise
  472. // returns \c false.
  473. static bool methodMatch(const QMetaObject *m, int handle,
  474. const QByteArray &name, int argc,
  475. const QArgumentType *types)
  476. {
  477. Q_ASSERT(priv(m->d.data)->revision >= 7);
  478. if (int(m->d.data[handle + 1]) != argc)
  479. return false;
  480. if (stringData(m, m->d.data[handle]) != name)
  481. return false;
  482. int paramsIndex = m->d.data[handle + 2] + 1;
  483. for (int i = 0; i < argc; ++i) {
  484. uint typeInfo = m->d.data[paramsIndex + i];
  485. if (types[i].type()) {
  486. if (types[i].type() != typeFromTypeInfo(m, typeInfo))
  487. return false;
  488. } else {
  489. if (types[i].name() != typeNameFromTypeInfo(m, typeInfo))
  490. return false;
  491. }
  492. }
  493. return true;
  494. }
  495. /**
  496. * \internal
  497. * helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
  498. * the baseObject
  499. * \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything.
  500. */
  501. template<int MethodType>
  502. static inline int indexOfMethodRelative(const QMetaObject **baseObject,
  503. const QByteArray &name, int argc,
  504. const QArgumentType *types)
  505. {
  506. for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
  507. Q_ASSERT(priv(m->d.data)->revision >= 7);
  508. int i = (MethodType == MethodSignal)
  509. ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
  510. const int end = (MethodType == MethodSlot)
  511. ? (priv(m->d.data)->signalCount) : 0;
  512. for (; i >= end; --i) {
  513. int handle = priv(m->d.data)->methodData + 5*i;
  514. if (methodMatch(m, handle, name, argc, types)) {
  515. *baseObject = m;
  516. return i;
  517. }
  518. }
  519. }
  520. return -1;
  521. }
  522. /*!
  523. \since 4.5
  524. Finds \a constructor and returns its index; otherwise returns -1.
  525. Note that the \a constructor has to be in normalized form, as returned
  526. by normalizedSignature().
  527. \sa constructor(), constructorCount(), normalizedSignature()
  528. */
  529. int QMetaObject::indexOfConstructor(const char *constructor) const
  530. {
  531. Q_ASSERT(priv(d.data)->revision >= 7);
  532. QArgumentTypeArray types;
  533. QByteArray name = QMetaObjectPrivate::decodeMethodSignature(constructor, types);
  534. return QMetaObjectPrivate::indexOfConstructor(this, name, types.size(), types.constData());
  535. }
  536. /*!
  537. Finds \a method and returns its index; otherwise returns -1.
  538. Note that the \a method has to be in normalized form, as returned
  539. by normalizedSignature().
  540. \sa method(), methodCount(), methodOffset(), normalizedSignature()
  541. */
  542. int QMetaObject::indexOfMethod(const char *method) const
  543. {
  544. const QMetaObject *m = this;
  545. int i;
  546. Q_ASSERT(priv(m->d.data)->revision >= 7);
  547. QArgumentTypeArray types;
  548. QByteArray name = QMetaObjectPrivate::decodeMethodSignature(method, types);
  549. i = indexOfMethodRelative<0>(&m, name, types.size(), types.constData());
  550. if (i >= 0)
  551. i += m->methodOffset();
  552. return i;
  553. }
  554. // Parses a string of comma-separated types into QArgumentTypes.
  555. // No normalization of the type names is performed.
  556. static void argumentTypesFromString(const char *str, const char *end,
  557. QArgumentTypeArray &types)
  558. {
  559. Q_ASSERT(str <= end);
  560. while (str != end) {
  561. if (!types.isEmpty())
  562. ++str; // Skip comma
  563. const char *begin = str;
  564. int level = 0;
  565. while (str != end && (level > 0 || *str != ',')) {
  566. if (*str == '<')
  567. ++level;
  568. else if (*str == '>')
  569. --level;
  570. ++str;
  571. }
  572. types += QArgumentType(QByteArray(begin, str - begin));
  573. }
  574. }
  575. // Given a method \a signature (e.g. "foo(int,double)"), this function
  576. // populates the argument \a types array and returns the method name.
  577. QByteArray QMetaObjectPrivate::decodeMethodSignature(
  578. const char *signature, QArgumentTypeArray &types)
  579. {
  580. Q_ASSERT(signature != 0);
  581. const char *lparens = strchr(signature, '(');
  582. if (!lparens)
  583. return QByteArray();
  584. const char *rparens = strrchr(lparens + 1, ')');
  585. if (!rparens || *(rparens+1))
  586. return QByteArray();
  587. int nameLength = lparens - signature;
  588. argumentTypesFromString(lparens + 1, rparens, types);
  589. return QByteArray::fromRawData(signature, nameLength);
  590. }
  591. /*!
  592. Finds \a signal and returns its index; otherwise returns -1.
  593. This is the same as indexOfMethod(), except that it will return
  594. -1 if the method exists but isn't a signal.
  595. Note that the \a signal has to be in normalized form, as returned
  596. by normalizedSignature().
  597. \sa indexOfMethod(), normalizedSignature(), method(), methodCount(), methodOffset()
  598. */
  599. int QMetaObject::indexOfSignal(const char *signal) const
  600. {
  601. const QMetaObject *m = this;
  602. int i;
  603. Q_ASSERT(priv(m->d.data)->revision >= 7);
  604. QArgumentTypeArray types;
  605. QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signal, types);
  606. i = QMetaObjectPrivate::indexOfSignalRelative(&m, name, types.size(), types.constData());
  607. if (i >= 0)
  608. i += m->methodOffset();
  609. return i;
  610. }
  611. /*!
  612. \internal
  613. Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
  614. \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
  615. */
  616. int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
  617. const QByteArray &name, int argc,
  618. const QArgumentType *types)
  619. {
  620. int i = indexOfMethodRelative<MethodSignal>(baseObject, name, argc, types);
  621. #ifndef QT_NO_DEBUG
  622. const QMetaObject *m = *baseObject;
  623. if (i >= 0 && m && m->d.superdata) {
  624. int conflict = indexOfMethod(m->d.superdata, name, argc, types);
  625. if (conflict >= 0) {
  626. QMetaMethod conflictMethod = m->d.superdata->method(conflict);
  627. qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
  628. conflictMethod.methodSignature().constData(),
  629. rawStringData(m->d.superdata, 0), rawStringData(m, 0));
  630. }
  631. }
  632. #endif
  633. return i;
  634. }
  635. /*!
  636. Finds \a slot and returns its index; otherwise returns -1.
  637. This is the same as indexOfMethod(), except that it will return
  638. -1 if the method exists but isn't a slot.
  639. \sa indexOfMethod(), method(), methodCount(), methodOffset()
  640. */
  641. int QMetaObject::indexOfSlot(const char *slot) const
  642. {
  643. const QMetaObject *m = this;
  644. int i;
  645. Q_ASSERT(priv(m->d.data)->revision >= 7);
  646. QArgumentTypeArray types;
  647. QByteArray name = QMetaObjectPrivate::decodeMethodSignature(slot, types);
  648. i = QMetaObjectPrivate::indexOfSlotRelative(&m, name, types.size(), types.constData());
  649. if (i >= 0)
  650. i += m->methodOffset();
  651. return i;
  652. }
  653. // same as indexOfSignalRelative but for slots.
  654. int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
  655. const QByteArray &name, int argc,
  656. const QArgumentType *types)
  657. {
  658. return indexOfMethodRelative<MethodSlot>(m, name, argc, types);
  659. }
  660. int QMetaObjectPrivate::indexOfSignal(const QMetaObject *m, const QByteArray &name,
  661. int argc, const QArgumentType *types)
  662. {
  663. int i = indexOfSignalRelative(&m, name, argc, types);
  664. if (i >= 0)
  665. i += m->methodOffset();
  666. return i;
  667. }
  668. int QMetaObjectPrivate::indexOfSlot(const QMetaObject *m, const QByteArray &name,
  669. int argc, const QArgumentType *types)
  670. {
  671. int i = indexOfSlotRelative(&m, name, argc, types);
  672. if (i >= 0)
  673. i += m->methodOffset();
  674. return i;
  675. }
  676. int QMetaObjectPrivate::indexOfMethod(const QMetaObject *m, const QByteArray &name,
  677. int argc, const QArgumentType *types)
  678. {
  679. int i = indexOfMethodRelative<0>(&m, name, argc, types);
  680. if (i >= 0)
  681. i += m->methodOffset();
  682. return i;
  683. }
  684. int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArray &name,
  685. int argc, const QArgumentType *types)
  686. {
  687. for (int i = priv(m->d.data)->constructorCount-1; i >= 0; --i) {
  688. int handle = priv(m->d.data)->constructorData + 5*i;
  689. if (methodMatch(m, handle, name, argc, types))
  690. return i;
  691. }
  692. return -1;
  693. }
  694. /*!
  695. \internal
  696. \since 5.0
  697. Returns the signal offset for the class \a m; i.e., the index position
  698. of the class's first signal.
  699. Similar to QMetaObject::methodOffset(), but non-signal methods are
  700. excluded.
  701. */
  702. int QMetaObjectPrivate::signalOffset(const QMetaObject *m)
  703. {
  704. Q_ASSERT(m != 0);
  705. int offset = 0;
  706. for (m = m->d.superdata; m; m = m->d.superdata)
  707. offset += priv(m->d.data)->signalCount;
  708. return offset;
  709. }
  710. /*!
  711. \internal
  712. \since 5.0
  713. Returns the number of signals for the class \a m, including the signals
  714. for the base class.
  715. Similar to QMetaObject::methodCount(), but non-signal methods are
  716. excluded.
  717. */
  718. int QMetaObjectPrivate::absoluteSignalCount(const QMetaObject *m)
  719. {
  720. Q_ASSERT(m != 0);
  721. int n = priv(m->d.data)->signalCount;
  722. for (m = m->d.superdata; m; m = m->d.superdata)
  723. n += priv(m->d.data)->signalCount;
  724. return n;
  725. }
  726. /*!
  727. \internal
  728. \since 5.0
  729. Returns the index of the signal method \a m.
  730. Similar to QMetaMethod::methodIndex(), but non-signal methods are
  731. excluded.
  732. */
  733. int QMetaObjectPrivate::signalIndex(const QMetaMethod &m)
  734. {
  735. if (!m.mobj)
  736. return -1;
  737. return QMetaMethodPrivate::get(&m)->ownMethodIndex() + signalOffset(m.mobj);
  738. }
  739. /*!
  740. \internal
  741. \since 5.0
  742. Returns the signal for the given meta-object \a m at \a signal_index.
  743. It it different from QMetaObject::method(); the index should not include
  744. non-signal methods.
  745. */
  746. QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *m, int signal_index)
  747. {
  748. QMetaMethod result;
  749. if (signal_index < 0)
  750. return result;
  751. Q_ASSERT(m != 0);
  752. int i = signal_index;
  753. i -= signalOffset(m);
  754. if (i < 0 && m->d.superdata)
  755. return signal(m->d.superdata, signal_index);
  756. if (i >= 0 && i < priv(m->d.data)->signalCount) {
  757. result.mobj = m;
  758. result.handle = priv(m->d.data)->methodData + 5*i;
  759. }
  760. return result;
  761. }
  762. /*!
  763. \internal
  764. Returns \c true if the \a signalTypes and \a methodTypes are
  765. compatible; otherwise returns \c false.
  766. */
  767. bool QMetaObjectPrivate::checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
  768. int methodArgc, const QArgumentType *methodTypes)
  769. {
  770. if (signalArgc < methodArgc)
  771. return false;
  772. for (int i = 0; i < methodArgc; ++i) {
  773. if (signalTypes[i] != methodTypes[i])
  774. return false;
  775. }
  776. return true;
  777. }
  778. /*!
  779. \internal
  780. Returns \c true if the \a signal and \a method arguments are
  781. compatible; otherwise returns \c false.
  782. */
  783. bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
  784. const QMetaMethodPrivate *method)
  785. {
  786. if (signal->methodType() != QMetaMethod::Signal)
  787. return false;
  788. if (signal->parameterCount() < method->parameterCount())
  789. return false;
  790. const QMetaObject *smeta = signal->enclosingMetaObject();
  791. const QMetaObject *rmeta = method->enclosingMetaObject();
  792. for (int i = 0; i < method->parameterCount(); ++i) {
  793. uint sourceTypeInfo = signal->parameterTypeInfo(i);
  794. uint targetTypeInfo = method->parameterTypeInfo(i);
  795. if ((sourceTypeInfo & IsUnresolvedType)
  796. || (targetTypeInfo & IsUnresolvedType)) {
  797. QByteArray sourceName = typeNameFromTypeInfo(smeta, sourceTypeInfo);
  798. QByteArray targetName = typeNameFromTypeInfo(rmeta, targetTypeInfo);
  799. if (sourceName != targetName)
  800. return false;
  801. } else {
  802. int sourceType = typeFromTypeInfo(smeta, sourceTypeInfo);
  803. int targetType = typeFromTypeInfo(rmeta, targetTypeInfo);
  804. if (sourceType != targetType)
  805. return false;
  806. }
  807. }
  808. return true;
  809. }
  810. static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
  811. {
  812. while (self) {
  813. if (strcmp(rawStringData(self, 0), name) == 0)
  814. return self;
  815. if (self->d.relatedMetaObjects) {
  816. Q_ASSERT(priv(self->d.data)->revision >= 2);
  817. const QMetaObject * const *e = self->d.relatedMetaObjects;
  818. if (e) {
  819. while (*e) {
  820. if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
  821. return m;
  822. ++e;
  823. }
  824. }
  825. }
  826. self = self->d.superdata;
  827. }
  828. return self;
  829. }
  830. /*!
  831. Finds enumerator \a name and returns its index; otherwise returns
  832. -1.
  833. \sa enumerator(), enumeratorCount(), enumeratorOffset()
  834. */
  835. int QMetaObject::indexOfEnumerator(const char *name) const
  836. {
  837. const QMetaObject *m = this;
  838. while (m) {
  839. const QMetaObjectPrivate *d = priv(m->d.data);
  840. for (int i = d->enumeratorCount - 1; i >= 0; --i) {
  841. const char *prop = rawStringData(m, m->d.data[d->enumeratorData + 4*i]);
  842. if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
  843. i += m->enumeratorOffset();
  844. return i;
  845. }
  846. }
  847. m = m->d.superdata;
  848. }
  849. return -1;
  850. }
  851. /*!
  852. Finds property \a name and returns its index; otherwise returns
  853. -1.
  854. \sa property(), propertyCount(), propertyOffset()
  855. */
  856. int QMetaObject::indexOfProperty(const char *name) const
  857. {
  858. const QMetaObject *m = this;
  859. while (m) {
  860. const QMetaObjectPrivate *d = priv(m->d.data);
  861. for (int i = d->propertyCount-1; i >= 0; --i) {
  862. const char *prop = rawStringData(m, m->d.data[d->propertyData + 3*i]);
  863. if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
  864. i += m->propertyOffset();
  865. return i;
  866. }
  867. }
  868. m = m->d.superdata;
  869. }
  870. Q_ASSERT(priv(this->d.data)->revision >= 3);
  871. if (priv(this->d.data)->flags & DynamicMetaObject) {
  872. QAbstractDynamicMetaObject *me =
  873. const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
  874. return me->createProperty(name, 0);
  875. }
  876. return -1;
  877. }
  878. /*!
  879. Finds class information item \a name and returns its index;
  880. otherwise returns -1.
  881. \sa classInfo(), classInfoCount(), classInfoOffset()
  882. */
  883. int QMetaObject::indexOfClassInfo(const char *name) const
  884. {
  885. int i = -1;
  886. const QMetaObject *m = this;
  887. while (m && i < 0) {
  888. for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
  889. if (strcmp(name, rawStringData(m, m->d.data[priv(m->d.data)->classInfoData + 2*i])) == 0) {
  890. i += m->classInfoOffset();
  891. break;
  892. }
  893. m = m->d.superdata;
  894. }
  895. return i;
  896. }
  897. /*!
  898. \since 4.5
  899. Returns the meta-data for the constructor with the given \a index.
  900. \sa constructorCount(), newInstance()
  901. */
  902. QMetaMethod QMetaObject::constructor(int index) const
  903. {
  904. int i = index;
  905. QMetaMethod result;
  906. Q_ASSERT(priv(d.data)->revision >= 2);
  907. if (i >= 0 && i < priv(d.data)->constructorCount) {
  908. result.mobj = this;
  909. result.handle = priv(d.data)->constructorData + 5*i;
  910. }
  911. return result;
  912. }
  913. /*!
  914. Returns the meta-data for the method with the given \a index.
  915. \sa methodCount(), methodOffset(), indexOfMethod()
  916. */
  917. QMetaMethod QMetaObject::method(int index) const
  918. {
  919. int i = index;
  920. i -= methodOffset();
  921. if (i < 0 && d.superdata)
  922. return d.superdata->method(index);
  923. QMetaMethod result;
  924. if (i >= 0 && i < priv(d.data)->methodCount) {
  925. result.mobj = this;
  926. result.handle = priv(d.data)->methodData + 5*i;
  927. }
  928. return result;
  929. }
  930. /*!
  931. Returns the meta-data for the enumerator with the given \a index.
  932. \sa enumeratorCount(), enumeratorOffset(), indexOfEnumerator()
  933. */
  934. QMetaEnum QMetaObject::enumerator(int index) const
  935. {
  936. int i = index;
  937. i -= enumeratorOffset();
  938. if (i < 0 && d.superdata)
  939. return d.superdata->enumerator(index);
  940. QMetaEnum result;
  941. if (i >= 0 && i < priv(d.data)->enumeratorCount) {
  942. result.mobj = this;
  943. result.handle = priv(d.data)->enumeratorData + 4*i;
  944. }
  945. return result;
  946. }
  947. /*!
  948. Returns the meta-data for the property with the given \a index.
  949. If no such property exists, a null QMetaProperty is returned.
  950. \sa propertyCount(), propertyOffset(), indexOfProperty()
  951. */
  952. QMetaProperty QMetaObject::property(int index) const
  953. {
  954. int i = index;
  955. i -= propertyOffset();
  956. if (i < 0 && d.superdata)
  957. return d.superdata->property(index);
  958. QMetaProperty result;
  959. if (i >= 0 && i < priv(d.data)->propertyCount) {
  960. int handle = priv(d.data)->propertyData + 3*i;
  961. int flags = d.data[handle + 2];
  962. result.mobj = this;
  963. result.handle = handle;
  964. result.idx = i;
  965. if (flags & EnumOrFlag) {
  966. const char *type = rawTypeNameFromTypeInfo(this, d.data[handle + 1]);
  967. result.menum = enumerator(indexOfEnumerator(type));
  968. if (!result.menum.isValid()) {
  969. const char *enum_name = type;
  970. const char *scope_name = rawStringData(this, 0);
  971. char *scope_buffer = 0;
  972. const char *colon = strrchr(enum_name, ':');
  973. // ':' will always appear in pairs
  974. Q_ASSERT(colon <= enum_name || *(colon-1) == ':');
  975. if (colon > enum_name) {
  976. int len = colon-enum_name-1;
  977. scope_buffer = (char *)malloc(len+1);
  978. memcpy(scope_buffer, enum_name, len);
  979. scope_buffer[len] = '\0';
  980. scope_name = scope_buffer;
  981. enum_name = colon+1;
  982. }
  983. const QMetaObject *scope = 0;
  984. if (qstrcmp(scope_name, "Qt") == 0)
  985. scope = &QObject::staticQtMetaObject;
  986. else
  987. scope = QMetaObject_findMetaObject(this, scope_name);
  988. if (scope)
  989. result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
  990. if (scope_buffer)
  991. free(scope_buffer);
  992. }
  993. }
  994. }
  995. return result;
  996. }
  997. /*!
  998. \since 4.2
  999. Returns the property that has the \c USER flag set to true.
  1000. \sa QMetaProperty::isUser()
  1001. */
  1002. QMetaProperty QMetaObject::userProperty() const
  1003. {
  1004. const int propCount = propertyCount();
  1005. for (int i = propCount - 1; i >= 0; --i) {
  1006. const QMetaProperty prop = property(i);
  1007. if (prop.isUser())
  1008. return prop;
  1009. }
  1010. return QMetaProperty();
  1011. }
  1012. /*!
  1013. Returns the meta-data for the item of class information with the
  1014. given \a index.
  1015. Example:
  1016. \snippet code/src_corelib_kernel_qmetaobject.cpp 0
  1017. \sa classInfoCount(), classInfoOffset(), indexOfClassInfo()
  1018. */
  1019. QMetaClassInfo QMetaObject::classInfo(int index) const
  1020. {
  1021. int i = index;
  1022. i -= classInfoOffset();
  1023. if (i < 0 && d.superdata)
  1024. return d.superdata->classInfo(index);
  1025. QMetaClassInfo result;
  1026. if (i >= 0 && i < priv(d.data)->classInfoCount) {
  1027. result.mobj = this;
  1028. result.handle = priv(d.data)->classInfoData + 2*i;
  1029. }
  1030. return result;
  1031. }
  1032. /*!
  1033. Returns \c true if the \a signal and \a method arguments are
  1034. compatible; otherwise returns \c false.
  1035. Both \a signal and \a method are expected to be normalized.
  1036. \sa normalizedSignature()
  1037. */
  1038. bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
  1039. {
  1040. const char *s1 = signal;
  1041. const char *s2 = method;
  1042. while (*s1++ != '(') { } // scan to first '('
  1043. while (*s2++ != '(') { }
  1044. if (*s2 == ')' || qstrcmp(s1,s2) == 0) // method has no args or
  1045. return true; // exact match
  1046. int s1len = qstrlen(s1);
  1047. int s2len = qstrlen(s2);
  1048. if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
  1049. return true; // method has less args
  1050. return false;
  1051. }
  1052. /*!
  1053. \since 5.0
  1054. \overload
  1055. Returns \c true if the \a signal and \a method arguments are
  1056. compatible; otherwise returns \c false.
  1057. */
  1058. bool QMetaObject::checkConnectArgs(const QMetaMethod &signal,
  1059. const QMetaMethod &method)
  1060. {
  1061. return QMetaObjectPrivate::checkConnectArgs(
  1062. QMetaMethodPrivate::get(&signal),
  1063. QMetaMethodPrivate::get(&method));
  1064. }
  1065. static void qRemoveWhitespace(const char *s, char *d)
  1066. {
  1067. char last = 0;
  1068. while (*s && is_space(*s))
  1069. s++;
  1070. while (*s) {
  1071. while (*s && !is_space(*s))
  1072. last = *d++ = *s++;
  1073. while (*s && is_space(*s))
  1074. s++;
  1075. if (*s && ((is_ident_char(*s) && is_ident_char(last))
  1076. || ((*s == ':') && (last == '<')))) {
  1077. last = *d++ = ' ';
  1078. }
  1079. }
  1080. *d = '\0';
  1081. }
  1082. static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
  1083. {
  1084. const char *t = d;
  1085. while (*d && (templdepth
  1086. || (*d != ',' && *d != ')'))) {
  1087. if (*d == '<')
  1088. ++templdepth;
  1089. if (*d == '>')
  1090. --templdepth;
  1091. ++d;
  1092. }
  1093. // "void" should only be removed if this is part of a signature that has
  1094. // an explicit void argument; e.g., "void foo(void)" --> "void foo()"
  1095. if (strncmp("void)", t, d - t + 1) != 0)
  1096. result += normalizeTypeInternal(t, d);
  1097. return d;
  1098. }
  1099. /*!
  1100. \since 4.2
  1101. Normalizes a \a type.
  1102. See QMetaObject::normalizedSignature() for a description on how
  1103. Qt normalizes.
  1104. Example:
  1105. \snippet code/src_corelib_kernel_qmetaobject.cpp 1
  1106. \sa normalizedSignature()
  1107. */
  1108. QByteArray QMetaObject::normalizedType(const char *type)
  1109. {
  1110. QByteArray result;
  1111. if (!type || !*type)
  1112. return result;
  1113. QVarLengthArray<char> stackbuf(qstrlen(type) + 1);
  1114. qRemoveWhitespace(type, stackbuf.data());
  1115. int templdepth = 0;
  1116. qNormalizeType(stackbuf.data(), templdepth, result);
  1117. return result;
  1118. }
  1119. /*!
  1120. Normalizes the signature of the given \a method.
  1121. Qt uses normalized signatures to decide whether two given signals
  1122. and slots are compatible. Normalization reduces whitespace to a
  1123. minimum, moves 'const' to the front where appropriate, removes
  1124. 'const' from value types and replaces const references with
  1125. values.
  1126. \sa checkConnectArgs(), normalizedType()
  1127. */
  1128. QByteArray QMetaObject::normalizedSignature(const char *method)
  1129. {
  1130. QByteArray result;
  1131. if (!method || !*method)
  1132. return result;
  1133. int len = int(strlen(method));
  1134. QVarLengthArray<char> stackbuf(len + 1);
  1135. char *d = stackbuf.data();
  1136. qRemoveWhitespace(method, d);
  1137. result.reserve(len);
  1138. int argdepth = 0;
  1139. int templdepth = 0;
  1140. while (*d) {
  1141. if (argdepth == 1) {
  1142. d = qNormalizeType(d, templdepth, result);
  1143. if (!*d) //most likely an invalid signature.
  1144. break;
  1145. }
  1146. if (*d == '(')
  1147. ++argdepth;
  1148. if (*d == ')')
  1149. --argdepth;
  1150. result += *d++;
  1151. }
  1152. return result;
  1153. }
  1154. enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
  1155. /*!
  1156. Invokes the \a member (a signal or a slot name) on the object \a
  1157. obj. Returns \c true if the member could be invoked. Returns \c false
  1158. if there is no such member or the parameters did not match.
  1159. The invocation can be either synchronous or asynchronous,
  1160. depending on \a type:
  1161. \list
  1162. \li If \a type is Qt::DirectConnection, the member will be invoked immediately.
  1163. \li If \a type is Qt::QueuedConnection,
  1164. a QEvent will be sent and the member is invoked as soon as the application
  1165. enters the main event loop.
  1166. \li If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
  1167. the same way as for Qt::QueuedConnection, except that the current thread
  1168. will block until the event is delivered. Using this connection type to
  1169. communicate between objects in the same thread will lead to deadlocks.
  1170. \li If \a type is Qt::AutoConnection, the member is invoked
  1171. synchronously if \a obj lives in the same thread as the
  1172. caller; otherwise it will invoke the member asynchronously.
  1173. \endlist
  1174. The return value of the \a member function call is placed in \a
  1175. ret. If the invocation is asynchronous, the return value cannot
  1176. be evaluated. You can pass up to ten arguments (\a val0, \a val1,
  1177. \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
  1178. and \a val9) to the \a member function.
  1179. QGenericArgument and QGenericReturnArgument are internal
  1180. helper classes. Because signals and slots can be dynamically
  1181. invoked, you must enclose the arguments using the Q_ARG() and
  1182. Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
  1183. const reference of that type; Q_RETURN_ARG() takes a type name
  1184. and a non-const reference.
  1185. You only need to pass the name of the signal or slot to this function,
  1186. not the entire signature. For example, to asynchronously invoke
  1187. the \l{QThread::quit()}{quit()} slot on a
  1188. QThread, use the following code:
  1189. \snippet code/src_corelib_kernel_qmetaobject.cpp 2
  1190. With asynchronous method invocations, the parameters must be of
  1191. types that are known to Qt's meta-object system, because Qt needs
  1192. to copy the arguments to store them in an event behind the
  1193. scenes. If you try to use a queued connection and get the error
  1194. message
  1195. \snippet code/src_corelib_kernel_qmetaobject.cpp 3
  1196. call qRegisterMetaType() to register the data type before you
  1197. call invokeMethod().
  1198. To synchronously invoke the \c compute(QString, int, double) slot on
  1199. some arbitrary object \c obj retrieve its return value:
  1200. \snippet code/src_corelib_kernel_qmetaobject.cpp 4
  1201. If the "compute" slot does not take exactly one QString, one int
  1202. and one double in the specified order, the call will fail.
  1203. \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaMethod::invoke()
  1204. */
  1205. bool QMetaObject::invokeMethod(QObject *obj,
  1206. const char *member,
  1207. Qt::ConnectionType type,
  1208. QGenericReturnArgument ret,
  1209. QGenericArgument val0,
  1210. QGenericArgument val1,
  1211. QGenericArgument val2,
  1212. QGenericArgument val3,
  1213. QGenericArgument val4,
  1214. QGenericArgument val5,
  1215. QGenericArgument val6,
  1216. QGenericArgument val7,
  1217. QGenericArgument val8,
  1218. QGenericArgument val9)
  1219. {
  1220. if (!obj)
  1221. return false;
  1222. QVarLengthArray<char, 512> sig;
  1223. int len = qstrlen(member);
  1224. if (len <= 0)
  1225. return false;
  1226. sig.append(member, len);
  1227. sig.append('(');
  1228. const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
  1229. val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
  1230. val9.name()};
  1231. int paramCount;
  1232. for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
  1233. len = qstrlen(typeNames[paramCount]);
  1234. if (len <= 0)
  1235. break;
  1236. sig.append(typeNames[paramCount], len);
  1237. sig.append(',');
  1238. }
  1239. if (paramCount == 1)
  1240. sig.append(')'); // no parameters
  1241. else
  1242. sig[sig.size() - 1] = ')';
  1243. sig.append('\0');
  1244. const QMetaObject *meta = obj->metaObject();
  1245. int idx = meta->indexOfMethod(sig.constData());
  1246. if (idx < 0) {
  1247. QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
  1248. idx = meta->indexOfMethod(norm.constData());
  1249. }
  1250. if (idx < 0 || idx >= meta->methodCount()) {
  1251. qWarning("QMetaObject::invokeMethod: No such method %s::%s",
  1252. meta->className(), sig.constData());
  1253. return false;
  1254. }
  1255. QMetaMethod method = meta->method(idx);
  1256. return method.invoke(obj, type, ret,
  1257. val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
  1258. }
  1259. /*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
  1260. QGenericReturnArgument ret,
  1261. QGenericArgument val0 = QGenericArgument(0),
  1262. QGenericArgument val1 = QGenericArgument(),
  1263. QGenericArgument val2 = QGenericArgument(),
  1264. QGenericArgument val3 = QGenericArgument(),
  1265. QGenericArgument val4 = QGenericArgument(),
  1266. QGenericArgument val5 = QGenericArgument(),
  1267. QGenericArgument val6 = QGenericArgument(),
  1268. QGenericArgument val7 = QGenericArgument(),
  1269. QGenericArgument val8 = QGenericArgument(),
  1270. QGenericArgument val9 = QGenericArgument());
  1271. \overload invokeMethod()
  1272. This overload always invokes the member using the connection type Qt::AutoConnection.
  1273. */
  1274. /*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
  1275. Qt::ConnectionType type,
  1276. QGenericArgument val0 = QGenericArgument(0),
  1277. QGenericArgument val1 = QGenericArgument(),
  1278. QGenericArgument val2 = QGenericArgument(),
  1279. QGenericArgument val3 = QGenericArgument(),
  1280. QGenericArgument val4 = QGenericArgument(),
  1281. QGenericArgument val5 = QGenericArgument(),
  1282. QGenericArgument val6 = QGenericArgument(),
  1283. QGenericArgument val7 = QGenericArgument(),
  1284. QGenericArgument val8 = QGenericArgument(),
  1285. QGenericArgument val9 = QGenericArgument())
  1286. \overload invokeMethod()
  1287. This overload can be used if the return value of the member is of no interest.
  1288. */
  1289. /*!
  1290. \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
  1291. QGenericArgument val0 = QGenericArgument(0),
  1292. QGenericArgument val1 = QGenericArgument(),
  1293. QGenericArgument val2 = QGenericArgument(),
  1294. QGenericArgument val3 = QGenericArgument(),
  1295. QGenericArgument val4 = QGenericArgument(),
  1296. QGenericArgument val5 = QGenericArgument(),
  1297. QGenericArgument val6 = QGenericArgument(),
  1298. QGenericArgument val7 = QGenericArgument(),
  1299. QGenericArgument val8 = QGenericArgument(),
  1300. QGenericArgument val9 = QGenericArgument())
  1301. \overload invokeMethod()
  1302. This overload invokes the member using the connection type Qt::AutoConnection and
  1303. ignores return values.
  1304. */
  1305. /*!
  1306. \class QMetaMethod
  1307. \inmodule QtCore
  1308. \brief The QMetaMethod class provides meta-data about a member
  1309. function.
  1310. \ingroup objectmodel
  1311. A QMetaMethod has a methodType(), a methodSignature(), a list of
  1312. parameterTypes() and parameterNames(), a return typeName(), a
  1313. tag(), and an access() specifier. You can use invoke() to invoke
  1314. the method on an arbitrary QObject.
  1315. \sa QMetaObject, QMetaEnum, QMetaProperty, {Qt's Property System}
  1316. */
  1317. /*!
  1318. \enum QMetaMethod::Attributes
  1319. \internal
  1320. \value Compatibility
  1321. \value Cloned
  1322. \value Scriptable
  1323. */
  1324. /*!
  1325. \fn bool QMetaMethod::isValid() const
  1326. \since 5.0
  1327. Returns \c true if this method is valid (can be introspected and
  1328. invoked), otherwise returns \c false.
  1329. */
  1330. /*! \fn bool operator==(const QMetaMethod &m1, const QMetaMethod &m2)
  1331. \since 5.0
  1332. \relates QMetaMethod
  1333. \overload
  1334. Returns \c true if method \a m1 is equal to method \a m2,
  1335. otherwise returns \c false.
  1336. */
  1337. /*! \fn bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2)
  1338. \since 5.0
  1339. \relates QMetaMethod
  1340. \overload
  1341. Returns \c true if method \a m1 is not equal to method \a m2,
  1342. otherwise returns \c false.
  1343. */
  1344. /*!
  1345. \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const
  1346. \internal
  1347. */
  1348. /*!
  1349. \enum QMetaMethod::MethodType
  1350. \value Method The function is a plain member function.
  1351. \value Signal The function is a signal.
  1352. \value Slot The function is a slot.
  1353. \value Constructor The function is a constructor.
  1354. */
  1355. /*!
  1356. \fn QMetaMethod::QMetaMethod()
  1357. \internal
  1358. */
  1359. /*!
  1360. \macro Q_METAMETHOD_INVOKE_MAX_ARGS
  1361. \relates QMetaMethod
  1362. Equals maximum number of arguments available for
  1363. execution of the method via QMetaMethod::invoke()
  1364. */
  1365. QByteArray QMetaMethodPrivate::signature() const
  1366. {
  1367. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1368. QByteArray result;
  1369. result.reserve(256);
  1370. result += name();
  1371. result += '(';
  1372. QList<QByteArray> argTypes = parameterTypes();
  1373. for (int i = 0; i < argTypes.size(); ++i) {
  1374. if (i)
  1375. result += ',';
  1376. result += argTypes.at(i);
  1377. }
  1378. result += ')';
  1379. return result;
  1380. }
  1381. QByteArray QMetaMethodPrivate::name() const
  1382. {
  1383. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1384. return stringData(mobj, mobj->d.data[handle]);
  1385. }
  1386. int QMetaMethodPrivate::typesDataIndex() const
  1387. {
  1388. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1389. return mobj->d.data[handle + 2];
  1390. }
  1391. const char *QMetaMethodPrivate::rawReturnTypeName() const
  1392. {
  1393. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1394. uint typeInfo = mobj->d.data[typesDataIndex()];
  1395. if (typeInfo & IsUnresolvedType)
  1396. return rawStringData(mobj, typeInfo & TypeNameIndexMask);
  1397. else
  1398. return QMetaType::typeName(typeInfo);
  1399. }
  1400. int QMetaMethodPrivate::returnType() const
  1401. {
  1402. return parameterType(-1);
  1403. }
  1404. int QMetaMethodPrivate::parameterCount() const
  1405. {
  1406. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1407. return mobj->d.data[handle + 1];
  1408. }
  1409. int QMetaMethodPrivate::parametersDataIndex() const
  1410. {
  1411. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1412. return typesDataIndex() + 1;
  1413. }
  1414. uint QMetaMethodPrivate::parameterTypeInfo(int index) const
  1415. {
  1416. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1417. return mobj->d.data[parametersDataIndex() + index];
  1418. }
  1419. int QMetaMethodPrivate::parameterType(int index) const
  1420. {
  1421. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1422. return typeFromTypeInfo(mobj, parameterTypeInfo(index));
  1423. }
  1424. void QMetaMethodPrivate::getParameterTypes(int *types) const
  1425. {
  1426. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1427. int dataIndex = parametersDataIndex();
  1428. int argc = parameterCount();
  1429. for (int i = 0; i < argc; ++i) {
  1430. int id = typeFromTypeInfo(mobj, mobj->d.data[dataIndex++]);
  1431. *(types++) = id;
  1432. }
  1433. }
  1434. QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
  1435. {
  1436. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1437. int argc = parameterCount();
  1438. QList<QByteArray> list;
  1439. list.reserve(argc);
  1440. int paramsIndex = parametersDataIndex();
  1441. for (int i = 0; i < argc; ++i)
  1442. list += typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + i]);
  1443. return list;
  1444. }
  1445. QList<QByteArray> QMetaMethodPrivate::parameterNames() const
  1446. {
  1447. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1448. int argc = parameterCount();
  1449. QList<QByteArray> list;
  1450. list.reserve(argc);
  1451. int namesIndex = parametersDataIndex() + argc;
  1452. for (int i = 0; i < argc; ++i)
  1453. list += stringData(mobj, mobj->d.data[namesIndex + i]);
  1454. return list;
  1455. }
  1456. QByteArray QMetaMethodPrivate::tag() const
  1457. {
  1458. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  1459. return stringData(mobj, mobj->d.data[handle + 3]);
  1460. }
  1461. int QMetaMethodPrivate::ownMethodIndex() const
  1462. {
  1463. // recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
  1464. return (handle - priv(mobj->d.data)->methodData) / 5;
  1465. }
  1466. /*!
  1467. \since 5.0
  1468. Returns the signature of this method (e.g.,
  1469. \c{setValue(double)}).
  1470. \sa parameterTypes(), parameterNames()
  1471. */
  1472. QByteArray QMetaMethod::methodSignature() const
  1473. {
  1474. if (!mobj)
  1475. return QByteArray();
  1476. return QMetaMethodPrivate::get(this)->signature();
  1477. }
  1478. /*!
  1479. \since 5.0
  1480. Returns the name of this method.
  1481. \sa methodSignature(), parameterCount()
  1482. */
  1483. QByteArray QMetaMethod::name() const
  1484. {
  1485. if (!mobj)
  1486. return QByteArray();
  1487. return QMetaMethodPrivate::get(this)->name();
  1488. }
  1489. /*!
  1490. \since 5.0
  1491. Returns the return type of this method.
  1492. The return value is one of the types that are registered
  1493. with QMetaType, or QMetaType::UnknownType if the type is not registered.
  1494. \sa parameterType(), QMetaType, typeName()
  1495. */
  1496. int QMetaMethod::returnType() const
  1497. {
  1498. if (!mobj)
  1499. return QMetaType::UnknownType;
  1500. return QMetaMethodPrivate::get(this)->returnType();
  1501. }
  1502. /*!
  1503. \since 5.0
  1504. Returns the number of parameters of this method.
  1505. \sa parameterType(), parameterNames()
  1506. */
  1507. int QMetaMethod::parameterCount() const
  1508. {
  1509. if (!mobj)
  1510. return 0;
  1511. return QMetaMethodPrivate::get(this)->parameterCount();
  1512. }
  1513. /*!
  1514. \since 5.0
  1515. Returns the type of the parameter at the given \a index.
  1516. The return value is one of the types that are registered
  1517. with QMetaType, or QMetaType::UnknownType if the type is not registered.
  1518. \sa parameterCount(), returnType(), QMetaType
  1519. */
  1520. int QMetaMethod::parameterType(int index) const
  1521. {
  1522. if (!mobj || index < 0)
  1523. return QMetaType::UnknownType;
  1524. if (index >= QMetaMethodPrivate::get(this)->parameterCount())
  1525. return QMetaType::UnknownType;
  1526. int type = QMetaMethodPrivate::get(this)->parameterType(index);
  1527. if (type != QMetaType::UnknownType)
  1528. return type;
  1529. void *argv[] = { &type, &index };
  1530. mobj->static_metacall(QMetaObject::RegisterMethodArgumentMetaType, QMetaMethodPrivate::get(this)->ownMethodIndex(), argv);
  1531. if (type != -1)
  1532. return type;
  1533. return QMetaType::UnknownType;
  1534. }
  1535. /*!
  1536. \since 5.0
  1537. \internal
  1538. Gets the parameter \a types of this method. The storage
  1539. for \a types must be able to hold parameterCount() items.
  1540. \sa parameterCount(), returnType(), parameterType()
  1541. */
  1542. void QMetaMethod::getParameterTypes(int *types) const
  1543. {
  1544. if (!mobj)
  1545. return;
  1546. QMetaMethodPrivate::get(this)->getParameterTypes(types);
  1547. }
  1548. /*!
  1549. Returns a list of parameter types.
  1550. \sa parameterNames(), methodSignature()
  1551. */
  1552. QList<QByteArray> QMetaMethod::parameterTypes() const
  1553. {
  1554. if (!mobj)
  1555. return QList<QByteArray>();
  1556. return QMetaMethodPrivate::get(this)->parameterTypes();
  1557. }
  1558. /*!
  1559. Returns a list of parameter names.
  1560. \sa parameterTypes(), methodSignature()
  1561. */
  1562. QList<QByteArray> QMetaMethod::parameterNames() const
  1563. {
  1564. QList<QByteArray> list;
  1565. if (!mobj)
  1566. return list;
  1567. return QMetaMethodPrivate::get(this)->parameterNames();
  1568. }
  1569. /*!
  1570. Returns the return type name of this method.
  1571. \sa returnType(), QMetaType::type()
  1572. */
  1573. const char *QMetaMethod::typeName() const
  1574. {
  1575. if (!mobj)
  1576. return 0;
  1577. return QMetaMethodPrivate::get(this)->rawReturnTypeName();
  1578. }
  1579. /*!
  1580. Returns the tag associated with this method.
  1581. Tags are special macros recognized by \c moc that make it
  1582. possible to add extra information about a method.
  1583. Tag information can be added in the following
  1584. way in the function declaration:
  1585. \code
  1586. #ifndef Q_MOC_RUN
  1587. // define the tag text
  1588. # define THISISTESTTAG
  1589. #endif
  1590. ...
  1591. private slots:
  1592. THISISTESTTAG void testFunc();
  1593. \endcode
  1594. and the information can be accessed by using:
  1595. \code
  1596. MainWindow win;
  1597. win.show();
  1598. int functionIndex = win.metaObject()->indexOfSlot("testFunc()");
  1599. QMetaMethod mm = metaObject()->method(functionIndex);
  1600. qDebug() << mm.tag(); // prints THISISTESTTAG
  1601. \endcode
  1602. For the moment, \c moc will extract and record all tags, but it will not
  1603. handle any of them specially.
  1604. \note Since Qt 5.0, \c moc expands preprocessor macros, so it is necessary
  1605. to surround the definition with \c #ifndef \c Q_MOC_RUN, as shown in the
  1606. example above. This was not required in Qt 4. The code as shown above works
  1607. with Qt 4 too.
  1608. */
  1609. const char *QMetaMethod::tag() const
  1610. {
  1611. if (!mobj)
  1612. return 0;
  1613. return QMetaMethodPrivate::get(this)->tag().constData();
  1614. }
  1615. /*!
  1616. \internal
  1617. */
  1618. int QMetaMethod::attributes() const
  1619. {
  1620. if (!mobj)
  1621. return false;
  1622. return ((mobj->d.data[handle + 4])>>4);
  1623. }
  1624. /*!
  1625. \since 4.6
  1626. Returns this method's index.
  1627. */
  1628. int QMetaMethod::methodIndex() const
  1629. {
  1630. if (!mobj)
  1631. return -1;
  1632. return QMetaMethodPrivate::get(this)->ownMethodIndex() + mobj->methodOffset();
  1633. }
  1634. // This method has been around for a while, but the documentation was marked \internal until 5.1
  1635. /*!
  1636. \since 5.1
  1637. Returns the method revision if one was
  1638. specified by Q_REVISION, otherwise returns 0.
  1639. */
  1640. int QMetaMethod::revision() const
  1641. {
  1642. if (!mobj)
  1643. return 0;
  1644. if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) {
  1645. int offset = priv(mobj->d.data)->methodData
  1646. + priv(mobj->d.data)->methodCount * 5
  1647. + QMetaMethodPrivate::get(this)->ownMethodIndex();
  1648. return mobj->d.data[offset];
  1649. }
  1650. return 0;
  1651. }
  1652. /*!
  1653. Returns the access specification of this method (private,
  1654. protected, or public).
  1655. Signals are always protected, meaning that you can only emit them
  1656. from the class or from a subclass.
  1657. \sa methodType()
  1658. */
  1659. QMetaMethod::Access QMetaMethod::access() const
  1660. {
  1661. if (!mobj)
  1662. return Private;
  1663. return (QMetaMethod::Access)(mobj->d.data[handle + 4] & AccessMask);
  1664. }
  1665. /*!
  1666. Returns the type of this method (signal, slot, or method).
  1667. \sa access()
  1668. */
  1669. QMetaMethod::MethodType QMetaMethod::methodType() const
  1670. {
  1671. if (!mobj)
  1672. return QMetaMethod::Method;
  1673. return (QMetaMethod::MethodType)((mobj->d.data[handle + 4] & MethodTypeMask)>>2);
  1674. }
  1675. /*!
  1676. \fn QMetaMethod QMetaMethod::fromSignal(PointerToMemberFunction signal)
  1677. \since 5.0
  1678. Returns the meta-method that corresponds to the given \a signal, or an
  1679. invalid QMetaMethod if \a signal is not a signal of the class.
  1680. Example:
  1681. \snippet code/src_corelib_kernel_qmetaobject.cpp 9
  1682. */
  1683. /*!
  1684. \internal
  1685. Implementation of the fromSignal() function.
  1686. \a metaObject is the class's meta-object
  1687. \a signal is a pointer to a pointer to a member signal of the class
  1688. */
  1689. QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **signal)
  1690. {
  1691. int i = -1;
  1692. void *args[] = { &i, signal };
  1693. QMetaMethod result;
  1694. for (const QMetaObject *m = metaObject; m; m = m->d.superdata) {
  1695. m->static_metacall(QMetaObject::IndexOfMethod, 0, args);
  1696. if (i >= 0) {
  1697. result.mobj = m;
  1698. result.handle = priv(m->d.data)->methodData + 5*i;
  1699. break;
  1700. }
  1701. }
  1702. return result;
  1703. }
  1704. /*!
  1705. Invokes this method on the object \a object. Returns \c true if the member could be invoked.
  1706. Returns \c false if there is no such member or the parameters did not match.
  1707. The invocation can be either synchronous or asynchronous, depending on the
  1708. \a connectionType:
  1709. \list
  1710. \li If \a connectionType is Qt::DirectConnection, the member will be invoked immediately.
  1711. \li If \a connectionType is Qt::QueuedConnection,
  1712. a QEvent will be posted and the member is invoked as soon as the application
  1713. enters the main event loop.
  1714. \li If \a connectionType is Qt::AutoConnection, the member is invoked
  1715. synchronously if \a object lives in the same thread as the
  1716. caller; otherwise it will invoke the member asynchronously.
  1717. \endlist
  1718. The return value of this method call is placed in \a
  1719. returnValue. If the invocation is asynchronous, the return value cannot
  1720. be evaluated. You can pass up to ten arguments (\a val0, \a val1,
  1721. \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
  1722. and \a val9) to this method call.
  1723. QGenericArgument and QGenericReturnArgument are internal
  1724. helper classes. Because signals and slots can be dynamically
  1725. invoked, you must enclose the arguments using the Q_ARG() and
  1726. Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
  1727. const reference of that type; Q_RETURN_ARG() takes a type name
  1728. and a non-const reference.
  1729. To asynchronously invoke the
  1730. \l{QPushButton::animateClick()}{animateClick()} slot on a
  1731. QPushButton:
  1732. \snippet code/src_corelib_kernel_qmetaobject.cpp 6
  1733. With asynchronous method invocations, the parameters must be of
  1734. types that are known to Qt's meta-object system, because Qt needs
  1735. to copy the arguments to store them in an event behind the
  1736. scenes. If you try to use a queued connection and get the error
  1737. message
  1738. \snippet code/src_corelib_kernel_qmetaobject.cpp 7
  1739. call qRegisterMetaType() to register the data type before you
  1740. call QMetaMethod::invoke().
  1741. To synchronously invoke the \c compute(QString, int, double) slot on
  1742. some arbitrary object \c obj retrieve its return value:
  1743. \snippet code/src_corelib_kernel_qmetaobject.cpp 8
  1744. QMetaObject::normalizedSignature() is used here to ensure that the format
  1745. of the signature is what invoke() expects. E.g. extra whitespace is
  1746. removed.
  1747. If the "compute" slot does not take exactly one QString, one int
  1748. and one double in the specified order, the call will fail.
  1749. \warning this method will not test the validity of the arguments: \a object
  1750. must be an instance of the class of the QMetaObject of which this QMetaMethod
  1751. has been constructed with. The arguments must have the same type as the ones
  1752. expected by the method, else, the behaviour is undefined.
  1753. \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
  1754. */
  1755. bool QMetaMethod::invoke(QObject *object,
  1756. Qt::ConnectionType connectionType,
  1757. QGenericReturnArgument returnValue,
  1758. QGenericArgument val0,
  1759. QGenericArgument val1,
  1760. QGenericArgument val2,
  1761. QGenericArgument val3,
  1762. QGenericArgument val4,
  1763. QGenericArgument val5,
  1764. QGenericArgument val6,
  1765. QGenericArgument val7,
  1766. QGenericArgument val8,
  1767. QGenericArgument val9) const
  1768. {
  1769. if (!object || !mobj)
  1770. return false;
  1771. Q_ASSERT(mobj->cast(object));
  1772. // check return type
  1773. if (returnValue.data()) {
  1774. const char *retType = typeName();
  1775. if (qstrcmp(returnValue.name(), retType) != 0) {
  1776. // normalize the return value as well
  1777. QByteArray normalized = QMetaObject::normalizedType(returnValue.name());
  1778. if (qstrcmp(normalized.constData(), retType) != 0) {
  1779. // String comparison failed, try compare the metatype.
  1780. int t = returnType();
  1781. if (t == QMetaType::UnknownType || t != QMetaType::type(normalized))
  1782. return false;
  1783. }
  1784. }
  1785. }
  1786. // check argument count (we don't allow invoking a method if given too few arguments)
  1787. const char *typeNames[] = {
  1788. returnValue.name(),
  1789. val0.name(),
  1790. val1.name(),
  1791. val2.name(),
  1792. val3.name(),
  1793. val4.name(),
  1794. val5.name(),
  1795. val6.name(),
  1796. val7.name(),
  1797. val8.name(),
  1798. val9.name()
  1799. };
  1800. int paramCount;
  1801. for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
  1802. if (qstrlen(typeNames[paramCount]) <= 0)
  1803. break;
  1804. }
  1805. if (paramCount <= QMetaMethodPrivate::get(this)->parameterCount())
  1806. return false;
  1807. // check connection type
  1808. QThread *currentThread = QThread::currentThread();
  1809. QThread *objectThread = object->thread();
  1810. if (connectionType == Qt::AutoConnection) {
  1811. connectionType = currentThread == objectThread
  1812. ? Qt::DirectConnection
  1813. : Qt::QueuedConnection;
  1814. }
  1815. #ifdef QT_NO_THREAD
  1816. if (connectionType == Qt::BlockingQueuedConnection) {
  1817. connectionType = Qt::DirectConnection;
  1818. }
  1819. #endif
  1820. // invoke!
  1821. void *param[] = {
  1822. returnValue.data(),
  1823. val0.data(),
  1824. val1.data(),
  1825. val2.data(),
  1826. val3.data(),
  1827. val4.data(),
  1828. val5.data(),
  1829. val6.data(),
  1830. val7.data(),
  1831. val8.data(),
  1832. val9.data()
  1833. };
  1834. int idx_relative = QMetaMethodPrivate::get(this)->ownMethodIndex();
  1835. int idx_offset = mobj->methodOffset();
  1836. Q_ASSERT(QMetaObjectPrivate::get(mobj)->revision >= 6);
  1837. QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.static_metacall;
  1838. if (connectionType == Qt::DirectConnection) {
  1839. if (callFunction) {
  1840. callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
  1841. return true;
  1842. } else {
  1843. return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) < 0;
  1844. }
  1845. } else if (connectionType == Qt::QueuedConnection) {
  1846. if (returnValue.data()) {
  1847. qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
  1848. "queued connections");
  1849. return false;
  1850. }
  1851. int nargs = 1; // include return type
  1852. void **args = (void **) malloc(paramCount * sizeof(void *));
  1853. Q_CHECK_PTR(args);
  1854. int *types = (int *) malloc(paramCount * sizeof(int));
  1855. Q_CHECK_PTR(types);
  1856. types[0] = 0; // return type
  1857. args[0] = 0;
  1858. for (int i = 1; i < paramCount; ++i) {
  1859. types[i] = QMetaType::type(typeNames[i]);
  1860. if (types[i] != QMetaType::UnknownType) {
  1861. args[i] = QMetaType::create(types[i], param[i]);
  1862. ++nargs;
  1863. } else if (param[i]) {
  1864. // Try to register the type and try again before reporting an error.
  1865. void *argv[] = { &types[i], &i };
  1866. QMetaObject::metacall(object, QMetaObject::RegisterMethodArgumentMetaType,
  1867. idx_relative + idx_offset, argv);
  1868. if (types[i] == -1) {
  1869. qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
  1870. typeNames[i]);
  1871. for (int x = 1; x < i; ++x) {
  1872. if (types[x] && args[x])
  1873. QMetaType::destroy(types[x], args[x]);
  1874. }
  1875. free(types);
  1876. free(args);
  1877. return false;
  1878. }
  1879. }
  1880. }
  1881. QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
  1882. 0, -1, nargs, types, args));
  1883. } else { // blocking queued connection
  1884. #ifndef QT_NO_THREAD
  1885. if (currentThread == objectThread) {
  1886. qWarning("QMetaMethod::invoke: Dead lock detected in "
  1887. "BlockingQueuedConnection: Receiver is %s(%p)",
  1888. mobj->className(), object);
  1889. }
  1890. QSemaphore semaphore;
  1891. QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
  1892. 0, -1, 0, 0, param, &semaphore));
  1893. semaphore.acquire();
  1894. #endif // QT_NO_THREAD
  1895. }
  1896. return true;
  1897. }
  1898. /*! \fn bool QMetaMethod::invoke(QObject *object,
  1899. QGenericReturnArgument returnValue,
  1900. QGenericArgument val0 = QGenericArgument(0),
  1901. QGenericArgument val1 = QGenericArgument(),
  1902. QGenericArgument val2 = QGenericArgument(),
  1903. QGenericArgument val3 = QGenericArgument(),
  1904. QGenericArgument val4 = QGenericArgument(),
  1905. QGenericArgument val5 = QGenericArgument(),
  1906. QGenericArgument val6 = QGenericArgument(),
  1907. QGenericArgument val7 = QGenericArgument(),
  1908. QGenericArgument val8 = QGenericArgument(),
  1909. QGenericArgument val9 = QGenericArgument()) const
  1910. \overload invoke()
  1911. This overload always invokes this method using the connection type Qt::AutoConnection.
  1912. */
  1913. /*! \fn bool QMetaMethod::invoke(QObject *object,
  1914. Qt::ConnectionType connectionType,
  1915. QGenericArgument val0 = QGenericArgument(0),
  1916. QGenericArgument val1 = QGenericArgument(),
  1917. QGenericArgument val2 = QGenericArgument(),
  1918. QGenericArgument val3 = QGenericArgument(),
  1919. QGenericArgument val4 = QGenericArgument(),
  1920. QGenericArgument val5 = QGenericArgument(),
  1921. QGenericArgument val6 = QGenericArgument(),
  1922. QGenericArgument val7 = QGenericArgument(),
  1923. QGenericArgument val8 = QGenericArgument(),
  1924. QGenericArgument val9 = QGenericArgument()) const
  1925. \overload invoke()
  1926. This overload can be used if the return value of the member is of no interest.
  1927. */
  1928. /*!
  1929. \fn bool QMetaMethod::invoke(QObject *object,
  1930. QGenericArgument val0 = QGenericArgument(0),
  1931. QGenericArgument val1 = QGenericArgument(),
  1932. QGenericArgument val2 = QGenericArgument(),
  1933. QGenericArgument val3 = QGenericArgument(),
  1934. QGenericArgument val4 = QGenericArgument(),
  1935. QGenericArgument val5 = QGenericArgument(),
  1936. QGenericArgument val6 = QGenericArgument(),
  1937. QGenericArgument val7 = QGenericArgument(),
  1938. QGenericArgument val8 = QGenericArgument(),
  1939. QGenericArgument val9 = QGenericArgument()) const
  1940. \overload invoke()
  1941. This overload invokes this method using the
  1942. connection type Qt::AutoConnection and ignores return values.
  1943. */
  1944. /*!
  1945. \class QMetaEnum
  1946. \inmodule QtCore
  1947. \brief The QMetaEnum class provides meta-data about an enumerator.
  1948. \ingroup objectmodel
  1949. Use name() for the enumerator's name. The enumerator's keys (names
  1950. of each enumerated item) are returned by key(); use keyCount() to find
  1951. the number of keys. isFlag() returns whether the enumerator is
  1952. meant to be used as a flag, meaning that its values can be combined
  1953. using the OR operator.
  1954. The conversion functions keyToValue(), valueToKey(), keysToValue(),
  1955. and valueToKeys() allow conversion between the integer
  1956. representation of an enumeration or set value and its literal
  1957. representation. The scope() function returns the class scope this
  1958. enumerator was declared in.
  1959. \sa QMetaObject, QMetaMethod, QMetaProperty
  1960. */
  1961. /*!
  1962. \fn bool QMetaEnum::isValid() const
  1963. Returns \c true if this enum is valid (has a name); otherwise returns
  1964. false.
  1965. \sa name()
  1966. */
  1967. /*!
  1968. \fn const QMetaObject *QMetaEnum::enclosingMetaObject() const
  1969. \internal
  1970. */
  1971. /*!
  1972. \fn QMetaEnum::QMetaEnum()
  1973. \internal
  1974. */
  1975. /*!
  1976. Returns the name of the enumerator (without the scope).
  1977. For example, the Qt::AlignmentFlag enumeration has \c
  1978. AlignmentFlag as the name and \l Qt as the scope.
  1979. \sa isValid(), scope()
  1980. */
  1981. const char *QMetaEnum::name() const
  1982. {
  1983. if (!mobj)
  1984. return 0;
  1985. return rawStringData(mobj, mobj->d.data[handle]);
  1986. }
  1987. /*!
  1988. Returns the number of keys.
  1989. \sa key()
  1990. */
  1991. int QMetaEnum::keyCount() const
  1992. {
  1993. if (!mobj)
  1994. return 0;
  1995. return mobj->d.data[handle + 2];
  1996. }
  1997. /*!
  1998. Returns the key with the given \a index, or 0 if no such key exists.
  1999. \sa keyCount(), value(), valueToKey()
  2000. */
  2001. const char *QMetaEnum::key(int index) const
  2002. {
  2003. if (!mobj)
  2004. return 0;
  2005. int count = mobj->d.data[handle + 2];
  2006. int data = mobj->d.data[handle + 3];
  2007. if (index >= 0 && index < count)
  2008. return rawStringData(mobj, mobj->d.data[data + 2*index]);
  2009. return 0;
  2010. }
  2011. /*!
  2012. Returns the value with the given \a index; or returns -1 if there
  2013. is no such value.
  2014. \sa keyCount(), key(), keyToValue()
  2015. */
  2016. int QMetaEnum::value(int index) const
  2017. {
  2018. if (!mobj)
  2019. return 0;
  2020. int count = mobj->d.data[handle + 2];
  2021. int data = mobj->d.data[handle + 3];
  2022. if (index >= 0 && index < count)
  2023. return mobj->d.data[data + 2*index + 1];
  2024. return -1;
  2025. }
  2026. /*!
  2027. Returns \c true if this enumerator is used as a flag; otherwise returns
  2028. false.
  2029. When used as flags, enumerators can be combined using the OR
  2030. operator.
  2031. \sa keysToValue(), valueToKeys()
  2032. */
  2033. bool QMetaEnum::isFlag() const
  2034. {
  2035. return mobj && mobj->d.data[handle + 1];
  2036. }
  2037. /*!
  2038. Returns the scope this enumerator was declared in.
  2039. For example, the Qt::AlignmentFlag enumeration has \c Qt as
  2040. the scope and \c AlignmentFlag as the name.
  2041. \sa name()
  2042. */
  2043. const char *QMetaEnum::scope() const
  2044. {
  2045. return mobj?rawStringData(mobj, 0) : 0;
  2046. }
  2047. /*!
  2048. Returns the integer value of the given enumeration \a key, or -1
  2049. if \a key is not defined.
  2050. If \a key is not defined, *\a{ok} is set to false; otherwise
  2051. *\a{ok} is set to true.
  2052. For flag types, use keysToValue().
  2053. \sa valueToKey(), isFlag(), keysToValue()
  2054. */
  2055. int QMetaEnum::keyToValue(const char *key, bool *ok) const
  2056. {
  2057. if (ok != 0)
  2058. *ok = false;
  2059. if (!mobj || !key)
  2060. return -1;
  2061. uint scope = 0;
  2062. const char *qualified_key = key;
  2063. const char *s = key + qstrlen(key);
  2064. while (s > key && *s != ':')
  2065. --s;
  2066. if (s > key && *(s-1)==':') {
  2067. scope = s - key - 1;
  2068. key += scope + 2;
  2069. }
  2070. int count = mobj->d.data[handle + 2];
  2071. int data = mobj->d.data[handle + 3];
  2072. for (int i = 0; i < count; ++i) {
  2073. if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key, rawStringData(mobj, 0), scope) == 0))
  2074. && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
  2075. if (ok != 0)
  2076. *ok = true;
  2077. return mobj->d.data[data + 2*i + 1];
  2078. }
  2079. }
  2080. return -1;
  2081. }
  2082. /*!
  2083. Returns the string that is used as the name of the given
  2084. enumeration \a value, or 0 if \a value is not defined.
  2085. For flag types, use valueToKeys().
  2086. \sa isFlag(), valueToKeys()
  2087. */
  2088. const char* QMetaEnum::valueToKey(int value) const
  2089. {
  2090. if (!mobj)
  2091. return 0;
  2092. int count = mobj->d.data[handle + 2];
  2093. int data = mobj->d.data[handle + 3];
  2094. for (int i = 0; i < count; ++i)
  2095. if (value == (int)mobj->d.data[data + 2*i + 1])
  2096. return rawStringData(mobj, mobj->d.data[data + 2*i]);
  2097. return 0;
  2098. }
  2099. /*!
  2100. Returns the value derived from combining together the values of
  2101. the \a keys using the OR operator, or -1 if \a keys is not
  2102. defined. Note that the strings in \a keys must be '|'-separated.
  2103. If \a keys is not defined, *\a{ok} is set to false; otherwise
  2104. *\a{ok} is set to true.
  2105. \sa isFlag(), valueToKey(), valueToKeys()
  2106. */
  2107. int QMetaEnum::keysToValue(const char *keys, bool *ok) const
  2108. {
  2109. if (ok != 0)
  2110. *ok = false;
  2111. if (!mobj || !keys)
  2112. return -1;
  2113. if (ok != 0)
  2114. *ok = true;
  2115. QStringList l = QString::fromLatin1(keys).split(QLatin1Char('|'));
  2116. if (l.isEmpty())
  2117. return 0;
  2118. //#### TODO write proper code, do not use QStringList
  2119. int value = 0;
  2120. int count = mobj->d.data[handle + 2];
  2121. int data = mobj->d.data[handle + 3];
  2122. for (int li = 0; li < l.size(); ++li) {
  2123. QString trimmed = l.at(li).trimmed();
  2124. QByteArray qualified_key = trimmed.toLatin1();
  2125. const char *key = qualified_key.constData();
  2126. uint scope = 0;
  2127. const char *s = key + qstrlen(key);
  2128. while (s > key && *s != ':')
  2129. --s;
  2130. if (s > key && *(s-1)==':') {
  2131. scope = s - key - 1;
  2132. key += scope + 2;
  2133. }
  2134. int i;
  2135. for (i = count-1; i >= 0; --i)
  2136. if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key.constData(), rawStringData(mobj, 0), scope) == 0))
  2137. && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
  2138. value |= mobj->d.data[data + 2*i + 1];
  2139. break;
  2140. }
  2141. if (i < 0) {
  2142. if (ok != 0)
  2143. *ok = false;
  2144. value |= -1;
  2145. }
  2146. }
  2147. return value;
  2148. }
  2149. /*!
  2150. Returns a byte array of '|'-separated keys that represents the
  2151. given \a value.
  2152. \sa isFlag(), valueToKey(), keysToValue()
  2153. */
  2154. QByteArray QMetaEnum::valueToKeys(int value) const
  2155. {
  2156. QByteArray keys;
  2157. if (!mobj)
  2158. return keys;
  2159. int count = mobj->d.data[handle + 2];
  2160. int data = mobj->d.data[handle + 3];
  2161. int v = value;
  2162. for(int i = 0; i < count; i++) {
  2163. int k = mobj->d.data[data + 2*i + 1];
  2164. if ((k != 0 && (v & k) == k ) || (k == value)) {
  2165. v = v & ~k;
  2166. if (!keys.isEmpty())
  2167. keys += '|';
  2168. keys += stringData(mobj, mobj->d.data[data + 2*i]);
  2169. }
  2170. }
  2171. return keys;
  2172. }
  2173. static QByteArray qualifiedName(const QMetaEnum &e)
  2174. {
  2175. return QByteArray(e.scope()) + "::" + e.name();
  2176. }
  2177. /*!
  2178. \class QMetaProperty
  2179. \inmodule QtCore
  2180. \brief The QMetaProperty class provides meta-data about a property.
  2181. \ingroup objectmodel
  2182. Property meta-data is obtained from an object's meta-object. See
  2183. QMetaObject::property() and QMetaObject::propertyCount() for
  2184. details.
  2185. \section1 Property Meta-Data
  2186. A property has a name() and a type(), as well as various
  2187. attributes that specify its behavior: isReadable(), isWritable(),
  2188. isDesignable(), isScriptable(), revision(), and isStored().
  2189. If the property is an enumeration, isEnumType() returns \c true; if the
  2190. property is an enumeration that is also a flag (i.e. its values
  2191. can be combined using the OR operator), isEnumType() and
  2192. isFlagType() both return true. The enumerator for these types is
  2193. available from enumerator().
  2194. The property's values are set and retrieved with read(), write(),
  2195. and reset(); they can also be changed through QObject's set and get
  2196. functions. See QObject::setProperty() and QObject::property() for
  2197. details.
  2198. \section1 Copying and Assignment
  2199. QMetaProperty objects can be copied by value. However, each copy will
  2200. refer to the same underlying property meta-data.
  2201. \sa QMetaObject, QMetaEnum, QMetaMethod, {Qt's Property System}
  2202. */
  2203. /*!
  2204. \fn bool QMetaProperty::isValid() const
  2205. Returns \c true if this property is valid (readable); otherwise
  2206. returns \c false.
  2207. \sa isReadable()
  2208. */
  2209. /*!
  2210. \fn const QMetaObject *QMetaProperty::enclosingMetaObject() const
  2211. \internal
  2212. */
  2213. /*!
  2214. \internal
  2215. */
  2216. QMetaProperty::QMetaProperty()
  2217. : mobj(0), handle(0), idx(0)
  2218. {
  2219. }
  2220. /*!
  2221. Returns this property's name.
  2222. \sa type(), typeName()
  2223. */
  2224. const char *QMetaProperty::name() const
  2225. {
  2226. if (!mobj)
  2227. return 0;
  2228. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2229. return rawStringData(mobj, mobj->d.data[handle]);
  2230. }
  2231. /*!
  2232. Returns the name of this property's type.
  2233. \sa type(), name()
  2234. */
  2235. const char *QMetaProperty::typeName() const
  2236. {
  2237. if (!mobj)
  2238. return 0;
  2239. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2240. return rawTypeNameFromTypeInfo(mobj, mobj->d.data[handle + 1]);
  2241. }
  2242. /*!
  2243. Returns this property's type. The return value is one
  2244. of the values of the QVariant::Type enumeration.
  2245. \sa userType(), typeName(), name()
  2246. */
  2247. QVariant::Type QMetaProperty::type() const
  2248. {
  2249. if (!mobj)
  2250. return QVariant::Invalid;
  2251. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2252. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  2253. uint type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]);
  2254. if (type >= QMetaType::User)
  2255. return QVariant::UserType;
  2256. if (type != QMetaType::UnknownType)
  2257. return QVariant::Type(type);
  2258. if (isEnumType()) {
  2259. int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
  2260. if (enumMetaTypeId == QMetaType::UnknownType)
  2261. return QVariant::Int;
  2262. }
  2263. #ifdef QT_COORD_TYPE
  2264. // qreal metatype must be resolved at runtime.
  2265. if (strcmp(typeName(), "qreal") == 0)
  2266. return QVariant::Type(qMetaTypeId<qreal>());
  2267. #endif
  2268. return QVariant::UserType;
  2269. }
  2270. /*!
  2271. \since 4.2
  2272. Returns this property's user type. The return value is one
  2273. of the values that are registered with QMetaType, or QMetaType::UnknownType if
  2274. the type is not registered.
  2275. \sa type(), QMetaType, typeName()
  2276. */
  2277. int QMetaProperty::userType() const
  2278. {
  2279. if (!mobj)
  2280. return QMetaType::UnknownType;
  2281. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  2282. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2283. int type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]);
  2284. if (type != QMetaType::UnknownType)
  2285. return type;
  2286. if (isEnumType()) {
  2287. type = QMetaType::type(qualifiedName(menum));
  2288. if (type == QMetaType::UnknownType) {
  2289. void *argv[] = { &type };
  2290. mobj->static_metacall(QMetaObject::RegisterPropertyMetaType, idx, argv);
  2291. if (type == -1 || type == QMetaType::UnknownType)
  2292. return QVariant::Int; // Match behavior of QMetaType::type()
  2293. }
  2294. return type;
  2295. }
  2296. type = QMetaType::type(typeName());
  2297. if (type != QMetaType::UnknownType)
  2298. return type;
  2299. void *argv[] = { &type };
  2300. mobj->static_metacall(QMetaObject::RegisterPropertyMetaType, idx, argv);
  2301. if (type != -1)
  2302. return type;
  2303. return QMetaType::UnknownType;
  2304. }
  2305. /*!
  2306. \since 4.6
  2307. Returns this property's index.
  2308. */
  2309. int QMetaProperty::propertyIndex() const
  2310. {
  2311. if (!mobj)
  2312. return -1;
  2313. return idx + mobj->propertyOffset();
  2314. }
  2315. /*!
  2316. Returns \c true if the property's type is an enumeration value that
  2317. is used as a flag; otherwise returns \c false.
  2318. Flags can be combined using the OR operator. A flag type is
  2319. implicitly also an enum type.
  2320. \sa isEnumType(), enumerator(), QMetaEnum::isFlag()
  2321. */
  2322. bool QMetaProperty::isFlagType() const
  2323. {
  2324. return isEnumType() && menum.isFlag();
  2325. }
  2326. /*!
  2327. Returns \c true if the property's type is an enumeration value;
  2328. otherwise returns \c false.
  2329. \sa enumerator(), isFlagType()
  2330. */
  2331. bool QMetaProperty::isEnumType() const
  2332. {
  2333. if (!mobj)
  2334. return false;
  2335. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2336. int flags = mobj->d.data[handle + 2];
  2337. return (flags & EnumOrFlag) && menum.name();
  2338. }
  2339. /*!
  2340. \internal
  2341. Returns \c true if the property has a C++ setter function that
  2342. follows Qt's standard "name" / "setName" pattern. Designer and uic
  2343. query hasStdCppSet() in order to avoid expensive
  2344. QObject::setProperty() calls. All properties in Qt [should] follow
  2345. this pattern.
  2346. */
  2347. bool QMetaProperty::hasStdCppSet() const
  2348. {
  2349. if (!mobj)
  2350. return false;
  2351. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2352. int flags = mobj->d.data[handle + 2];
  2353. return (flags & StdCppSet);
  2354. }
  2355. /*!
  2356. Returns the enumerator if this property's type is an enumerator
  2357. type; otherwise the returned value is undefined.
  2358. \sa isEnumType(), isFlagType()
  2359. */
  2360. QMetaEnum QMetaProperty::enumerator() const
  2361. {
  2362. return menum;
  2363. }
  2364. /*!
  2365. Reads the property's value from the given \a object. Returns the value
  2366. if it was able to read it; otherwise returns an invalid variant.
  2367. \sa write(), reset(), isReadable()
  2368. */
  2369. QVariant QMetaProperty::read(const QObject *object) const
  2370. {
  2371. if (!object || !mobj)
  2372. return QVariant();
  2373. uint t = QVariant::Int;
  2374. if (isEnumType()) {
  2375. /*
  2376. try to create a QVariant that can be converted to this enum
  2377. type (only works if the enum has already been registered
  2378. with QMetaType)
  2379. */
  2380. int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
  2381. if (enumMetaTypeId != QMetaType::UnknownType)
  2382. t = enumMetaTypeId;
  2383. } else {
  2384. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2385. const char *typeName = 0;
  2386. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  2387. uint typeInfo = mobj->d.data[handle + 1];
  2388. if (!(typeInfo & IsUnresolvedType))
  2389. t = typeInfo;
  2390. else {
  2391. typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask);
  2392. t = QMetaType::type(typeName);
  2393. }
  2394. if (t == QMetaType::UnknownType) {
  2395. // Try to register the type and try again before reporting an error.
  2396. int registerResult = -1;
  2397. void *argv[] = { &registerResult };
  2398. QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::RegisterPropertyMetaType,
  2399. idx + mobj->propertyOffset(), argv);
  2400. if (registerResult == -1) {
  2401. qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
  2402. return QVariant();
  2403. }
  2404. t = registerResult;
  2405. }
  2406. }
  2407. // the status variable is changed by qt_metacall to indicate what it did
  2408. // this feature is currently only used by Qt D-Bus and should not be depended
  2409. // upon. Don't change it without looking into QDBusAbstractInterface first
  2410. // -1 (unchanged): normal qt_metacall, result stored in argv[0]
  2411. // changed: result stored directly in value
  2412. int status = -1;
  2413. QVariant value;
  2414. void *argv[] = { 0, &value, &status };
  2415. if (t == QMetaType::QVariant) {
  2416. argv[0] = &value;
  2417. } else {
  2418. value = QVariant(t, (void*)0);
  2419. argv[0] = value.data();
  2420. }
  2421. QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
  2422. idx + mobj->propertyOffset(), argv);
  2423. if (status != -1)
  2424. return value;
  2425. if (t != QMetaType::QVariant && argv[0] != value.data())
  2426. // pointer or reference
  2427. return QVariant((QVariant::Type)t, argv[0]);
  2428. return value;
  2429. }
  2430. /*!
  2431. Writes \a value as the property's value to the given \a object. Returns
  2432. true if the write succeeded; otherwise returns \c false.
  2433. \sa read(), reset(), isWritable()
  2434. */
  2435. bool QMetaProperty::write(QObject *object, const QVariant &value) const
  2436. {
  2437. if (!object || !isWritable())
  2438. return false;
  2439. QVariant v = value;
  2440. uint t = QVariant::Invalid;
  2441. if (isEnumType()) {
  2442. if (v.type() == QVariant::String) {
  2443. bool ok;
  2444. if (isFlagType())
  2445. v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
  2446. else
  2447. v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
  2448. if (!ok)
  2449. return false;
  2450. } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
  2451. int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
  2452. if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData())
  2453. return false;
  2454. v = QVariant(*reinterpret_cast<const int *>(v.constData()));
  2455. }
  2456. v.convert(QVariant::Int);
  2457. } else {
  2458. int handle = priv(mobj->d.data)->propertyData + 3*idx;
  2459. const char *typeName = 0;
  2460. Q_ASSERT(priv(mobj->d.data)->revision >= 7);
  2461. uint typeInfo = mobj->d.data[handle + 1];
  2462. if (!(typeInfo & IsUnresolvedType))
  2463. t = typeInfo;
  2464. else {
  2465. typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask);
  2466. t = QMetaType::type(typeName);
  2467. }
  2468. if (t == QMetaType::UnknownType) {
  2469. Q_ASSERT(typeName != 0);
  2470. const char *vtypeName = value.typeName();
  2471. if (vtypeName && strcmp(typeName, vtypeName) == 0)
  2472. t = value.userType();
  2473. else
  2474. t = QVariant::nameToType(typeName);
  2475. }
  2476. if (t == QVariant::Invalid)
  2477. return false;
  2478. if (t != QMetaType::QVariant && t != (uint)value.userType() && (t < QMetaType::User && !v.convert((QVariant::Type)t)))
  2479. return false;
  2480. }
  2481. // the status variable is changed by qt_metacall to indicate what it did
  2482. // this feature is currently only used by Qt D-Bus and should not be depended
  2483. // upon. Don't change it without looking into QDBusAbstractInterface first
  2484. // -1 (unchanged): normal qt_metacall, result stored in argv[0]
  2485. // changed: result stored directly in value, return the value of status
  2486. int status = -1;
  2487. // the flags variable is used by the declarative module to implement
  2488. // interception of property writes.
  2489. int flags = 0;
  2490. void *argv[] = { 0, &v, &status, &flags };
  2491. if (t == QMetaType::QVariant)
  2492. argv[0] = &v;
  2493. else
  2494. argv[0] = v.data();
  2495. QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
  2496. return status;
  2497. }
  2498. /*!
  2499. Resets the property for the given \a object with a reset method.
  2500. Returns \c true if the reset worked; otherwise returns \c false.
  2501. Reset methods are optional; only a few properties support them.
  2502. \sa read(), write()
  2503. */
  2504. bool QMetaProperty::reset(QObject *object) const
  2505. {
  2506. if (!object || !mobj || !isResettable())
  2507. return false;
  2508. void *argv[] = { 0 };
  2509. QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
  2510. return true;
  2511. }
  2512. /*!
  2513. Returns \c true if this property can be reset to a default value; otherwise
  2514. returns \c false.
  2515. \sa reset()
  2516. */
  2517. bool QMetaProperty::isResettable() const
  2518. {
  2519. if (!mobj)
  2520. return false;
  2521. int flags = mobj->d.data[handle + 2];
  2522. return flags & Resettable;
  2523. }
  2524. /*!
  2525. Returns \c true if this property is readable; otherwise returns \c false.
  2526. \sa isWritable(), read(), isValid()
  2527. */
  2528. bool QMetaProperty::isReadable() const
  2529. {
  2530. if (!mobj)
  2531. return false;
  2532. int flags = mobj->d.data[handle + 2];
  2533. return flags & Readable;
  2534. }
  2535. /*!
  2536. Returns \c true if this property has a corresponding change notify signal;
  2537. otherwise returns \c false.
  2538. \sa notifySignal()
  2539. */
  2540. bool QMetaProperty::hasNotifySignal() const
  2541. {
  2542. if (!mobj)
  2543. return false;
  2544. int flags = mobj->d.data[handle + 2];
  2545. return flags & Notify;
  2546. }
  2547. /*!
  2548. \since 4.5
  2549. Returns the QMetaMethod instance of the property change notifying signal if
  2550. one was specified, otherwise returns an invalid QMetaMethod.
  2551. \sa hasNotifySignal()
  2552. */
  2553. QMetaMethod QMetaProperty::notifySignal() const
  2554. {
  2555. int id = notifySignalIndex();
  2556. if (id != -1)
  2557. return mobj->method(id);
  2558. else
  2559. return QMetaMethod();
  2560. }
  2561. /*!
  2562. \since 4.6
  2563. Returns the index of the property change notifying signal if one was
  2564. specified, otherwise returns -1.
  2565. \sa hasNotifySignal()
  2566. */
  2567. int QMetaProperty::notifySignalIndex() const
  2568. {
  2569. if (hasNotifySignal()) {
  2570. int offset = priv(mobj->d.data)->propertyData +
  2571. priv(mobj->d.data)->propertyCount * 3 + idx;
  2572. return mobj->d.data[offset] + mobj->methodOffset();
  2573. } else {
  2574. return -1;
  2575. }
  2576. }
  2577. // This method has been around for a while, but the documentation was marked \internal until 5.1
  2578. /*!
  2579. \since 5.1
  2580. Returns the property revision if one was
  2581. specified by REVISION, otherwise returns 0.
  2582. */
  2583. int QMetaProperty::revision() const
  2584. {
  2585. if (!mobj)
  2586. return 0;
  2587. int flags = mobj->d.data[handle + 2];
  2588. if (flags & Revisioned) {
  2589. int offset = priv(mobj->d.data)->propertyData +
  2590. priv(mobj->d.data)->propertyCount * 3 + idx;
  2591. // Revision data is placed after NOTIFY data, if present.
  2592. // Iterate through properties to discover whether we have NOTIFY signals.
  2593. for (int i = 0; i < priv(mobj->d.data)->propertyCount; ++i) {
  2594. int handle = priv(mobj->d.data)->propertyData + 3*i;
  2595. if (mobj->d.data[handle + 2] & Notify) {
  2596. offset += priv(mobj->d.data)->propertyCount;
  2597. break;
  2598. }
  2599. }
  2600. return mobj->d.data[offset];
  2601. } else {
  2602. return 0;
  2603. }
  2604. }
  2605. /*!
  2606. Returns \c true if this property is writable; otherwise returns
  2607. false.
  2608. \sa isReadable(), write()
  2609. */
  2610. bool QMetaProperty::isWritable() const
  2611. {
  2612. if (!mobj)
  2613. return false;
  2614. int flags = mobj->d.data[handle + 2];
  2615. return flags & Writable;
  2616. }
  2617. /*!
  2618. Returns \c true if this property is designable for the given \a object;
  2619. otherwise returns \c false.
  2620. If no \a object is given, the function returns \c false if the
  2621. \c{Q_PROPERTY()}'s \c DESIGNABLE attribute is false; otherwise
  2622. returns \c true (if the attribute is true or is a function or expression).
  2623. \sa isScriptable(), isStored()
  2624. */
  2625. bool QMetaProperty::isDesignable(const QObject *object) const
  2626. {
  2627. if (!mobj)
  2628. return false;
  2629. int flags = mobj->d.data[handle + 2];
  2630. bool b = flags & Designable;
  2631. if (object) {
  2632. void *argv[] = { &b };
  2633. QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable,
  2634. idx + mobj->propertyOffset(), argv);
  2635. }
  2636. return b;
  2637. }
  2638. /*!
  2639. Returns \c true if the property is scriptable for the given \a object;
  2640. otherwise returns \c false.
  2641. If no \a object is given, the function returns \c false if the
  2642. \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute is false; otherwise returns
  2643. true (if the attribute is true or is a function or expression).
  2644. \sa isDesignable(), isStored()
  2645. */
  2646. bool QMetaProperty::isScriptable(const QObject *object) const
  2647. {
  2648. if (!mobj)
  2649. return false;
  2650. int flags = mobj->d.data[handle + 2];
  2651. bool b = flags & Scriptable;
  2652. if (object) {
  2653. void *argv[] = { &b };
  2654. QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable,
  2655. idx + mobj->propertyOffset(), argv);
  2656. }
  2657. return b;
  2658. }
  2659. /*!
  2660. Returns \c true if the property is stored for \a object; otherwise returns
  2661. false.
  2662. If no \a object is given, the function returns \c false if the
  2663. \c{Q_PROPERTY()}'s \c STORED attribute is false; otherwise returns
  2664. true (if the attribute is true or is a function or expression).
  2665. \sa isDesignable(), isScriptable()
  2666. */
  2667. bool QMetaProperty::isStored(const QObject *object) const
  2668. {
  2669. if (!mobj)
  2670. return false;
  2671. int flags = mobj->d.data[handle + 2];
  2672. bool b = flags & Stored;
  2673. if (object) {
  2674. void *argv[] = { &b };
  2675. QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored,
  2676. idx + mobj->propertyOffset(), argv);
  2677. }
  2678. return b;
  2679. }
  2680. /*!
  2681. Returns \c true if this property is designated as the \c USER
  2682. property, i.e., the one that the user can edit for \a object or
  2683. that is significant in some other way. Otherwise it returns
  2684. false. e.g., the \c text property is the \c USER editable property
  2685. of a QLineEdit.
  2686. If \a object is null, the function returns \c false if the \c
  2687. {Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns
  2688. true.
  2689. \sa QMetaObject::userProperty(), isDesignable(), isScriptable()
  2690. */
  2691. bool QMetaProperty::isUser(const QObject *object) const
  2692. {
  2693. if (!mobj)
  2694. return false;
  2695. int flags = mobj->d.data[handle + 2];
  2696. bool b = flags & User;
  2697. if (object) {
  2698. void *argv[] = { &b };
  2699. QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser,
  2700. idx + mobj->propertyOffset(), argv);
  2701. }
  2702. return b;
  2703. }
  2704. /*!
  2705. \since 4.6
  2706. Returns \c true if the property is constant; otherwise returns \c false.
  2707. A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute
  2708. is set.
  2709. */
  2710. bool QMetaProperty::isConstant() const
  2711. {
  2712. if (!mobj)
  2713. return false;
  2714. int flags = mobj->d.data[handle + 2];
  2715. return flags & Constant;
  2716. }
  2717. /*!
  2718. \since 4.6
  2719. Returns \c true if the property is final; otherwise returns \c false.
  2720. A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute
  2721. is set.
  2722. */
  2723. bool QMetaProperty::isFinal() const
  2724. {
  2725. if (!mobj)
  2726. return false;
  2727. int flags = mobj->d.data[handle + 2];
  2728. return flags & Final;
  2729. }
  2730. /*!
  2731. \obsolete
  2732. Returns \c true if the property is editable for the given \a object;
  2733. otherwise returns \c false.
  2734. If no \a object is given, the function returns \c false if the
  2735. \c{Q_PROPERTY()}'s \c EDITABLE attribute is false; otherwise returns
  2736. true (if the attribute is true or is a function or expression).
  2737. \sa isDesignable(), isScriptable(), isStored()
  2738. */
  2739. bool QMetaProperty::isEditable(const QObject *object) const
  2740. {
  2741. if (!mobj)
  2742. return false;
  2743. int flags = mobj->d.data[handle + 2];
  2744. bool b = flags & Editable;
  2745. if (object) {
  2746. void *argv[] = { &b };
  2747. QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable,
  2748. idx + mobj->propertyOffset(), argv);
  2749. }
  2750. return b;
  2751. }
  2752. /*!
  2753. \class QMetaClassInfo
  2754. \inmodule QtCore
  2755. \brief The QMetaClassInfo class provides additional information
  2756. about a class.
  2757. \ingroup objectmodel
  2758. Class information items are simple \e{name}--\e{value} pairs that
  2759. are specified using Q_CLASSINFO() in the source code. The
  2760. information can be retrieved using name() and value(). For example:
  2761. \snippet code/src_corelib_kernel_qmetaobject.cpp 5
  2762. This mechanism is free for you to use in your Qt applications. Qt
  2763. doesn't use it for any of its classes.
  2764. \sa QMetaObject
  2765. */
  2766. /*!
  2767. \fn QMetaClassInfo::QMetaClassInfo()
  2768. \internal
  2769. */
  2770. /*!
  2771. \fn const QMetaObject *QMetaClassInfo::enclosingMetaObject() const
  2772. \internal
  2773. */
  2774. /*!
  2775. Returns the name of this item.
  2776. \sa value()
  2777. */
  2778. const char *QMetaClassInfo::name() const
  2779. {
  2780. if (!mobj)
  2781. return 0;
  2782. return rawStringData(mobj, mobj->d.data[handle]);
  2783. }
  2784. /*!
  2785. Returns the value of this item.
  2786. \sa name()
  2787. */
  2788. const char* QMetaClassInfo::value() const
  2789. {
  2790. if (!mobj)
  2791. return 0;
  2792. return rawStringData(mobj, mobj->d.data[handle + 1]);
  2793. }
  2794. /*!
  2795. \macro QGenericArgument Q_ARG(Type, const Type &value)
  2796. \relates QMetaObject
  2797. This macro takes a \a Type and a \a value of that type and
  2798. returns a \l QGenericArgument object that can be passed to
  2799. QMetaObject::invokeMethod().
  2800. \sa Q_RETURN_ARG()
  2801. */
  2802. /*!
  2803. \macro QGenericReturnArgument Q_RETURN_ARG(Type, Type &value)
  2804. \relates QMetaObject
  2805. This macro takes a \a Type and a non-const reference to a \a
  2806. value of that type and returns a QGenericReturnArgument object
  2807. that can be passed to QMetaObject::invokeMethod().
  2808. \sa Q_ARG()
  2809. */
  2810. /*!
  2811. \class QGenericArgument
  2812. \inmodule QtCore
  2813. \brief The QGenericArgument class is an internal helper class for
  2814. marshalling arguments.
  2815. This class should never be used directly. Please use the \l Q_ARG()
  2816. macro instead.
  2817. \sa Q_ARG(), QMetaObject::invokeMethod(), QGenericReturnArgument
  2818. */
  2819. /*!
  2820. \fn QGenericArgument::QGenericArgument(const char *name, const void *data)
  2821. Constructs a QGenericArgument object with the given \a name and \a data.
  2822. */
  2823. /*!
  2824. \fn QGenericArgument::data () const
  2825. Returns the data set in the constructor.
  2826. */
  2827. /*!
  2828. \fn QGenericArgument::name () const
  2829. Returns the name set in the constructor.
  2830. */
  2831. /*!
  2832. \class QGenericReturnArgument
  2833. \inmodule QtCore
  2834. \brief The QGenericReturnArgument class is an internal helper class for
  2835. marshalling arguments.
  2836. This class should never be used directly. Please use the
  2837. Q_RETURN_ARG() macro instead.
  2838. \sa Q_RETURN_ARG(), QMetaObject::invokeMethod(), QGenericArgument
  2839. */
  2840. /*!
  2841. \fn QGenericReturnArgument::QGenericReturnArgument(const char *name, void *data)
  2842. Constructs a QGenericReturnArgument object with the given \a name
  2843. and \a data.
  2844. */
  2845. /*!
  2846. \internal
  2847. If the local_method_index is a cloned method, return the index of the original.
  2848. Example: if the index of "destroyed()" is passed, the index of "destroyed(QObject*)" is returned
  2849. */
  2850. int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
  2851. {
  2852. Q_ASSERT(local_method_index < get(mobj)->methodCount);
  2853. int handle = get(mobj)->methodData + 5 * local_method_index;
  2854. while (mobj->d.data[handle + 4] & MethodCloned) {
  2855. Q_ASSERT(local_method_index > 0);
  2856. handle -= 5;
  2857. local_method_index--;
  2858. }
  2859. return local_method_index;
  2860. }
  2861. /*!
  2862. \internal
  2863. Returns the parameter type names extracted from the given \a signature.
  2864. */
  2865. QList<QByteArray> QMetaObjectPrivate::parameterTypeNamesFromSignature(const char *signature)
  2866. {
  2867. QList<QByteArray> list;
  2868. while (*signature && *signature != '(')
  2869. ++signature;
  2870. while (*signature && *signature != ')' && *++signature != ')') {
  2871. const char *begin = signature;
  2872. int level = 0;
  2873. while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
  2874. if (*signature == '<')
  2875. ++level;
  2876. else if (*signature == '>')
  2877. --level;
  2878. ++signature;
  2879. }
  2880. list += QByteArray(begin, signature - begin);
  2881. }
  2882. return list;
  2883. }
  2884. QT_END_NAMESPACE