PageRenderTime 75ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/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

Large files files are truncated, but you can click here to view the full file

  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()…

Large files files are truncated, but you can click here to view the full file