1
/****************************************************************************
3
** Copyright (C) Qxt Foundation. Some rights reserved.
5
** This file is part of the QxtCore module of the Qxt library.
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.
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.
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.
22
** <http://libqxt.org> <foundation@libqxt.org>
24
****************************************************************************/
26
#ifndef QXTBOUNDFUNCTION_H
27
#define QXTBOUNDFUNCTION_H
30
#include <QMetaObject>
31
#include <QGenericArgument>
32
#include <qxtmetaobject.h>
38
\class QxtBoundFunction
42
\brief Binds parameters to a function call
44
* A bound function is very similar to what the C++ FAQ Lite refers to as "functionoids."
45
* (http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10)
46
* It is similar in use to a function pointer, but allows any or all parameters to be
47
* pre-filled with constant values. The remaining parameters are specified when the
48
* function is invoked, for instance, by a Qt signal connection.
50
* By far, the most common expected use is to provide a parameter to a slot when the
51
* signal doesn't have offer one. Many developers new to Qt try to write code like this:
53
* connect(button, SIGNAL(clicked()), lineEdit, SLOT(setText("Hello, world")));
55
* Experienced Qt developers will immediately spot the flaw here. The typical solution
56
* is to create a short, one-line wrapper slot that invokes the desired function. Some
57
* clever developers may even use QSignalMapper to handle slots that only need one
58
* int or QString parameter.
60
* QxtBoundFunction enables the previous connect statement to be written like this:
62
* connect(button, SIGNAL(clicked()), QxtMetaObject::bind(lineEdit, SLOT(setText(QString)), Q_ARG(QString, "Hello, world!")));
64
* This accomplishes the same result without having to create a new slot, or worse,
65
* an entire object, just to pass a constant value.
67
* Additionally, through the use of the QXT_BIND macro, parameters from the signal
68
* can be rearranged, skipped, or passed alongside constant arguments provided
69
* with the Q_ARG macro. This can be used to provide stateful callbacks to a
70
* generic function, for example.
72
* Many kinds of functions can be bound. The most common binding applies to
73
* Qt signals and slots, but standard C/C++ functions can be bound as well.
74
* Future development may add the ability to bind to C++ member functions,
75
* and developers can make custom QxtBoundFunction subclasses for even more
76
* flexibility if necessary.
80
class QXT_CORE_EXPORT QxtBoundFunction : public QObject
85
* Invokes the bound function and returns a value.
87
* The template parameter should be the return type of the invoked function. This overload accepts
88
* QVariant parameters and will guess the data type of each parameter based on the type of the QVariant.
91
inline QxtNullable<T> invoke(QXT_PROTO_10ARGS(QVariant))
93
if (!parent() || QThread::currentThread() == parent()->thread())
94
return invoke<T>(Qt::DirectConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
95
#if QT_VERSION >= 0x040300
96
return invoke<T>(Qt::BlockingQueuedConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
98
qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
104
* Invokes the bound function and returns a value.
106
* The template parameter should be the return type of the invoked function. This overload accepts
107
* QGenericArgument parameters, expressed using the Q_ARG() macro.
110
QxtNullable<T> invoke(Qt::ConnectionType type, QVariant p1, QXT_PROTO_9ARGS(QVariant))
112
if (type == Qt::QueuedConnection)
114
qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
118
// I know this is a totally ugly function call
119
if (invoke(type, QGenericReturnArgument(qVariantFromValue<T>(*reinterpret_cast<T*>(0)).typeName(), reinterpret_cast<void*>(&retval)),
120
p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
131
* Invokes the bound function, discarding the return value.
133
* This overload accepts QVariant parameters and will guess the data type of each
134
* parameter based on the type of the QVariant.
136
* This function returns true if the invocation was successful, otherwise it
139
inline bool invoke(QVariant p1, QXT_PROTO_9ARGS(QVariant))
141
return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
144
* Invokes the bound function, discarding the return value.
146
* This overload accepts QVariant parameters and will guess the data type of each
147
* parameter based on the type of the QVariant. It also allows you to specify the
148
* connection type, allowing the bound function to be invoked across threads using
151
* This function returns true if the invocation was successful, otherwise it
154
bool invoke(Qt::ConnectionType, QVariant p1, QXT_PROTO_9ARGS(QVariant));
157
* Invokes the bound function, discarding the return value.
159
* This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
162
* This function returns true if the invocation was successful, otherwise it
165
inline bool invoke(QXT_PROTO_10ARGS(QGenericArgument))
167
return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
170
* Invokes the bound function, discarding the return value.
172
* This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
173
* macro. It also allows you to specify the connection type, allowing the bound
174
* function to be invoked across threads using the Qt event loop.
176
* This function returns true if the invocation was successful, otherwise it
179
inline bool invoke(Qt::ConnectionType type, QXT_PROTO_10ARGS(QGenericArgument))
181
return invoke(type, QGenericReturnArgument(), p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
185
* Invokes the bound function and assigns the return value to a parameter passed by reference.
187
* Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
188
* return type. When the function completes, its return value will be stored in that object.
190
* This overload accepts QVariant parameters and will guess the data type of each
191
* parameter based on the type of the QVariant.
193
* This function returns true if the invocation was successful, otherwise it
196
inline bool invoke(QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant))
198
return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
201
* Invokes the bound function and assigns the return value to a parameter passed by reference.
203
* Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
204
* return type. When the function completes, its return value will be stored in that object.
206
* This overload accepts QVariant parameters and will guess the data type of each
207
* parameter based on the type of the QVariant. It also allows you to specify the
208
* connection type, allowing the bound function to be invoked across threads using
211
* This function returns true if the invocation was successful, otherwise it
214
bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant));
217
* Invokes the bound function and assigns the return value to a parameter passed by reference.
219
* Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
220
* return type. When the function completes, its return value will be stored in that object.
222
* This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
225
* This function returns true if the invocation was successful, otherwise it
228
inline bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument))
230
return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
233
* Invokes the bound function and assigns the return value to a parameter passed by reference.
235
* Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's
236
* return type. When the function completes, its return value will be stored in that object.
238
* This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
239
* macro. It also allows you to specify the connection type, allowing the bound
240
* function to be invoked across threads using the Qt event loop.
242
* This function returns true if the invocation was successful, otherwise it
245
bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument));
248
#ifndef QXT_DOXYGEN_RUN
249
QxtBoundFunction(QObject* parent = 0);
253
* Performs the work of invoking the bound function.
255
* This function is pure virtual. The various QxtMetaObject::bind() functions return opaque subclasses
256
* of QxtBoundFunction. If you wish to create a new kind of bound function, reimplement this function to
257
* perform the invocation and assign the function's return value, if any, to the returnValue parameter.
259
* This function should return true if the invocation is successful and false if an error occurs.
261
virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) = 0;