PageRenderTime 306ms CodeModel.GetById 111ms app.highlight 109ms RepoModel.GetById 82ms app.codeStats 0ms

/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
 26#ifndef QXTBOUNDFUNCTION_H
 27#define QXTBOUNDFUNCTION_H
 28
 29#include <QObject>
 30#include <QMetaObject>
 31#include <QGenericArgument>
 32#include <qxtmetaobject.h>
 33#include <qxtnull.h>
 34#include <QThread>
 35#include <QtDebug>
 36
 37/*!
 38\class QxtBoundFunction
 39
 40\inmodule QxtCore
 41
 42\brief Binds parameters to a function call
 43
 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.
 49 *
 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:
 52 * \code
 53 *     connect(button, SIGNAL(clicked()), lineEdit, SLOT(setText("Hello, world")));
 54 * \endcode
 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.
 59 *
 60 * QxtBoundFunction enables the previous connect statement to be written like this:
 61 * \code
 62 *     connect(button, SIGNAL(clicked()), QxtMetaObject::bind(lineEdit, SLOT(setText(QString)), Q_ARG(QString, "Hello, world!")));
 63 * \code
 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.
 66 *
 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.
 71 *
 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.
 77 *
 78 *
 79 */
 80class QXT_CORE_EXPORT QxtBoundFunction : public QObject
 81{
 82    Q_OBJECT
 83public:
 84    /*!
 85     * Invokes the bound function and returns a value.
 86     *
 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.
 89     */
 90    template <class T>
 91    inline QxtNullable<T> invoke(QXT_PROTO_10ARGS(QVariant))
 92    {
 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);
 97#else
 98        qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
 99        return QxtNull();
100#endif
101    }
102
103    /*!
104     * Invokes the bound function and returns a value.
105     *
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.
108     */
109    template <class T>
110    QxtNullable<T> invoke(Qt::ConnectionType type, QVariant p1, QXT_PROTO_9ARGS(QVariant))
111    {
112        if (type == Qt::QueuedConnection)
113        {
114            qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
115            return QxtNull();
116        }
117        T retval;
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))
121        {
122            return retval;
123        }
124        else
125        {
126            return QxtNull();
127        }
128    }
129
130    /*!
131     * Invokes the bound function, discarding the return value.
132     *
133     * This overload accepts QVariant parameters and will guess the data type of each
134     * parameter based on the type of the QVariant.
135     *
136     * This function returns true if the invocation was successful, otherwise it
137     * returns false.
138     */
139    inline bool invoke(QVariant p1, QXT_PROTO_9ARGS(QVariant))
140    {
141        return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
142    }
143    /*!
144     * Invokes the bound function, discarding the return value.
145     *
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
149     * the Qt event loop.
150     *
151     * This function returns true if the invocation was successful, otherwise it
152     * returns false.
153     */
154    bool invoke(Qt::ConnectionType, QVariant p1, QXT_PROTO_9ARGS(QVariant));
155
156    /*!
157     * Invokes the bound function, discarding the return value.
158     *
159     * This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
160     * macro.
161     *
162     * This function returns true if the invocation was successful, otherwise it
163     * returns false.
164     */
165    inline bool invoke(QXT_PROTO_10ARGS(QGenericArgument))
166    {
167        return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
168    }
169    /*!
170     * Invokes the bound function, discarding the return value.
171     *
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.
175     *
176     * This function returns true if the invocation was successful, otherwise it
177     * returns false.
178     */
179    inline bool invoke(Qt::ConnectionType type, QXT_PROTO_10ARGS(QGenericArgument))
180    {
181        return invoke(type, QGenericReturnArgument(), p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
182    }
183
184    /*!
185     * Invokes the bound function and assigns the return value to a parameter passed by reference.
186     *
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.
189     *
190     * This overload accepts QVariant parameters and will guess the data type of each
191     * parameter based on the type of the QVariant.
192     *
193     * This function returns true if the invocation was successful, otherwise it
194     * returns false.
195     */
196    inline bool invoke(QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant))
197    {
198        return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
199    }
200    /*!
201     * Invokes the bound function and assigns the return value to a parameter passed by reference.
202     *
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.
205     *
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
209     * the Qt event loop.
210     *
211     * This function returns true if the invocation was successful, otherwise it
212     * returns false.
213     */
214    bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant));
215
216    /*!
217     * Invokes the bound function and assigns the return value to a parameter passed by reference.
218     *
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.
221     *
222     * This overload accepts QGenericArgument parameters, expressed using the Q_ARG()
223     * macro.
224     *
225     * This function returns true if the invocation was successful, otherwise it
226     * returns false.
227     */
228    inline bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument))
229    {
230        return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
231    }
232    /*!
233     * Invokes the bound function and assigns the return value to a parameter passed by reference.
234     *
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.
237     *
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.
241     *
242     * This function returns true if the invocation was successful, otherwise it
243     * returns false.
244     */
245    bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument));
246
247protected:
248#ifndef QXT_DOXYGEN_RUN
249    QxtBoundFunction(QObject* parent = 0);
250#endif
251
252    /*!
253     * Performs the work of invoking the bound function.
254     *
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.
258     *
259     * This function should return true if the invocation is successful and false if an error occurs.
260     */
261    virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) = 0;
262};
263
264#endif