/thirdparty/qxt/qxtweb-standalone/qxtweb/qxtboundfunction.h

http://github.com/tomahawk-player/tomahawk · C Header · 264 lines · 74 code · 11 blank · 179 comment · 6 complexity · 6171defc7e1f2f7d95260a77f1e4b0a6 MD5 · raw file

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) Qxt Foundation. Some rights reserved.
  4. **
  5. ** This file is part of the QxtCore module of the Qxt library.
  6. **
  7. ** This library is free software; you can redistribute it and/or modify it
  8. ** under the terms of the Common Public License, version 1.0, as published
  9. ** by IBM, and/or under the terms of the GNU Lesser General Public License,
  10. ** version 2.1, as published by the Free Software Foundation.
  11. **
  12. ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
  13. ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
  14. ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
  15. ** FITNESS FOR A PARTICULAR PURPOSE.
  16. **
  17. ** You should have received a copy of the CPL and the LGPL along with this
  18. ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
  19. ** included with the source distribution for more information.
  20. ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
  21. **
  22. ** <http://libqxt.org> <foundation@libqxt.org>
  23. **
  24. ****************************************************************************/
  25. #ifndef QXTBOUNDFUNCTION_H
  26. #define QXTBOUNDFUNCTION_H
  27. #include <QObject>
  28. #include <QMetaObject>
  29. #include <QGenericArgument>
  30. #include <qxtmetaobject.h>
  31. #include <qxtnull.h>
  32. #include <QThread>
  33. #include <QtDebug>
  34. /*!
  35. \class QxtBoundFunction
  36. \inmodule QxtCore
  37. \brief Binds parameters to a function call
  38. * A bound function is very similar to what the C++ FAQ Lite refers to as "functionoids."
  39. * (http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10)
  40. * It is similar in use to a function pointer, but allows any or all parameters to be
  41. * pre-filled with constant values. The remaining parameters are specified when the
  42. * function is invoked, for instance, by a Qt signal connection.
  43. *
  44. * By far, the most common expected use is to provide a parameter to a slot when the
  45. * signal doesn't have offer one. Many developers new to Qt try to write code like this:
  46. * \code
  47. * connect(button, SIGNAL(clicked()), lineEdit, SLOT(setText("Hello, world")));
  48. * \endcode
  49. * Experienced Qt developers will immediately spot the flaw here. The typical solution
  50. * is to create a short, one-line wrapper slot that invokes the desired function. Some
  51. * clever developers may even use QSignalMapper to handle slots that only need one
  52. * int or QString parameter.
  53. *
  54. * QxtBoundFunction enables the previous connect statement to be written like this:
  55. * \code
  56. * connect(button, SIGNAL(clicked()), QxtMetaObject::bind(lineEdit, SLOT(setText(QString)), Q_ARG(QString, "Hello, world!")));
  57. * \code
  58. * This accomplishes the same result without having to create a new slot, or worse,
  59. * an entire object, just to pass a constant value.
  60. *
  61. * Additionally, through the use of the QXT_BIND macro, parameters from the signal
  62. * can be rearranged, skipped, or passed alongside constant arguments provided
  63. * with the Q_ARG macro. This can be used to provide stateful callbacks to a
  64. * generic function, for example.
  65. *
  66. * Many kinds of functions can be bound. The most common binding applies to
  67. * Qt signals and slots, but standard C/C++ functions can be bound as well.
  68. * Future development may add the ability to bind to C++ member functions,
  69. * and developers can make custom QxtBoundFunction subclasses for even more
  70. * flexibility if necessary.
  71. *
  72. *
  73. */
  74. class QXT_CORE_EXPORT QxtBoundFunction : public QObject
  75. {
  76. Q_OBJECT
  77. public:
  78. /*!
  79. * Invokes the bound function and returns a value.
  80. *
  81. * The template parameter should be the return type of the invoked function. This overload accepts
  82. * QVariant parameters and will guess the data type of each parameter based on the type of the QVariant.
  83. */
  84. template <class T>
  85. inline QxtNullable<T> invoke(QXT_PROTO_10ARGS(QVariant))
  86. {
  87. if (!parent() || QThread::currentThread() == parent()->thread())
  88. return invoke<T>(Qt::DirectConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  89. #if QT_VERSION >= 0x040300
  90. return invoke<T>(Qt::BlockingQueuedConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  91. #else
  92. qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
  93. return QxtNull();
  94. #endif
  95. }
  96. /*!
  97. * Invokes the bound function and returns a value.
  98. *
  99. * The template parameter should be the return type of the invoked function. This overload accepts
  100. * QGenericArgument parameters, expressed using the Q_ARG() macro.
  101. */
  102. template <class T>
  103. QxtNullable<T> invoke(Qt::ConnectionType type, QVariant p1, QXT_PROTO_9ARGS(QVariant))
  104. {
  105. if (type == Qt::QueuedConnection)
  106. {
  107. qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
  108. return QxtNull();
  109. }
  110. T retval;
  111. // I know this is a totally ugly function call
  112. if (invoke(type, QGenericReturnArgument(qVariantFromValue<T>(*reinterpret_cast<T*>(0)).typeName(), reinterpret_cast<void*>(&retval)),
  113. p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
  114. {
  115. return retval;
  116. }
  117. else
  118. {
  119. return QxtNull();
  120. }
  121. }
  122. /*!
  123. * Invokes the bound function, discarding the return value.
  124. *
  125. * This overload accepts QVariant parameters and will guess the data type of each
  126. * parameter based on the type of the QVariant.
  127. *
  128. * This function returns true if the invocation was successful, otherwise it
  129. * returns false.
  130. */
  131. inline bool invoke(QVariant p1, QXT_PROTO_9ARGS(QVariant))
  132. {
  133. return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  134. }
  135. /*!
  136. * Invokes the bound function, discarding the return value.
  137. *
  138. * This overload accepts QVariant parameters and will guess the data type of each
  139. * parameter based on the type of the QVariant. It also allows you to specify the
  140. * connection type, allowing the bound function to be invoked across threads using
  141. * the Qt event loop.
  142. *
  143. * This function returns true if the invocation was successful, otherwise it
  144. * returns false.
  145. */
  146. bool invoke(Qt::ConnectionType, QVariant p1, QXT_PROTO_9ARGS(QVariant));
  147. /*!
  148. * Invokes the bound function, discarding the return value.
  149. *
  150. * This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
  151. * macro.
  152. *
  153. * This function returns true if the invocation was successful, otherwise it
  154. * returns false.
  155. */
  156. inline bool invoke(QXT_PROTO_10ARGS(QGenericArgument))
  157. {
  158. return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  159. }
  160. /*!
  161. * Invokes the bound function, discarding the return value.
  162. *
  163. * This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
  164. * macro. It also allows you to specify the connection type, allowing the bound
  165. * function to be invoked across threads using the Qt event loop.
  166. *
  167. * This function returns true if the invocation was successful, otherwise it
  168. * returns false.
  169. */
  170. inline bool invoke(Qt::ConnectionType type, QXT_PROTO_10ARGS(QGenericArgument))
  171. {
  172. return invoke(type, QGenericReturnArgument(), p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  173. }
  174. /*!
  175. * Invokes the bound function and assigns the return value to a parameter passed by reference.
  176. *
  177. * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
  178. * return type. When the function completes, its return value will be stored in that object.
  179. *
  180. * This overload accepts QVariant parameters and will guess the data type of each
  181. * parameter based on the type of the QVariant.
  182. *
  183. * This function returns true if the invocation was successful, otherwise it
  184. * returns false.
  185. */
  186. inline bool invoke(QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant))
  187. {
  188. return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  189. }
  190. /*!
  191. * Invokes the bound function and assigns the return value to a parameter passed by reference.
  192. *
  193. * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
  194. * return type. When the function completes, its return value will be stored in that object.
  195. *
  196. * This overload accepts QVariant parameters and will guess the data type of each
  197. * parameter based on the type of the QVariant. It also allows you to specify the
  198. * connection type, allowing the bound function to be invoked across threads using
  199. * the Qt event loop.
  200. *
  201. * This function returns true if the invocation was successful, otherwise it
  202. * returns false.
  203. */
  204. bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant));
  205. /*!
  206. * Invokes the bound function and assigns the return value to a parameter passed by reference.
  207. *
  208. * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
  209. * return type. When the function completes, its return value will be stored in that object.
  210. *
  211. * This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
  212. * macro.
  213. *
  214. * This function returns true if the invocation was successful, otherwise it
  215. * returns false.
  216. */
  217. inline bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument))
  218. {
  219. return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
  220. }
  221. /*!
  222. * Invokes the bound function and assigns the return value to a parameter passed by reference.
  223. *
  224. * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
  225. * return type. When the function completes, its return value will be stored in that object.
  226. *
  227. * This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
  228. * macro. It also allows you to specify the connection type, allowing the bound
  229. * function to be invoked across threads using the Qt event loop.
  230. *
  231. * This function returns true if the invocation was successful, otherwise it
  232. * returns false.
  233. */
  234. bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument));
  235. protected:
  236. #ifndef QXT_DOXYGEN_RUN
  237. QxtBoundFunction(QObject* parent = 0);
  238. #endif
  239. /*!
  240. * Performs the work of invoking the bound function.
  241. *
  242. * This function is pure virtual. The various QxtMetaObject::bind() functions return opaque subclasses
  243. * of QxtBoundFunction. If you wish to create a new kind of bound function, reimplement this function to
  244. * perform the invocation and assign the function's return value, if any, to the returnValue parameter.
  245. *
  246. * This function should return true if the invocation is successful and false if an error occurs.
  247. */
  248. virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) = 0;
  249. };
  250. #endif