QtGStreamer  0.10.2
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
connect.h
00001 /*
00002     Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
00003     Copyright (C) 2010 Collabora Ltd.
00004       @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
00005 
00006     This library is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU Lesser General Public License as published
00008     by the Free Software Foundation; either version 2.1 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public License
00017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 #ifndef QGLIB_CONNECT_H
00020 #define QGLIB_CONNECT_H
00021 
00022 #include "global.h"
00023 #include "quark.h"
00024 #include <QtCore/QObject>
00025 #include <QtCore/QSharedPointer>
00026 #include <QtCore/QFlags>
00027 #include <QtCore/QHash>
00028 #include <boost/type_traits.hpp>
00029 #include <boost/utility/enable_if.hpp>
00030 
00031 namespace QGlib {
00032 
00036 enum ConnectFlag { //codegen: skip=true
00042     ConnectAfter = 1,
00050     PassSender = 2
00051 };
00052 Q_DECLARE_FLAGS(ConnectFlags, ConnectFlag);
00053 Q_DECLARE_OPERATORS_FOR_FLAGS(ConnectFlags)
00054 
00055 #if defined(DOXYGEN_RUN)
00056 
00134 template <typename T, typename R, typename... Args>
00135 bool connect(void *instance, const char *detailedSignal,
00136              T *receiver, R (T::*slot)(Args...), ConnectFlags flags = 0);
00137 
00138 //Fake disconnect() declaration.
00139 //Doxygen should document a version with optional arguments. In reality we have to use
00140 //two versions to avoid having to type the template parameters in case the user wants
00141 //to use NULL for the receiver and slot arguments. Also, a version that takes void*
00142 //for everything is not possible since member function pointers do not cast to void*.
00143 
00190 template <typename T, typename R, typename... Args>
00191 bool disconnect(void *instance, const char *detailedSignal = 0,
00192                 T *receiver = 0, R (T::*slot)(Args...) = 0);
00193 
00194 #else //DOXYGEN_RUN
00195 
00196 namespace Private {
00197 
00198 //BEGIN ******** ClosureDataBase ********
00199 
00200 class QTGLIB_EXPORT ClosureDataBase
00201 {
00202 public:
00203     inline virtual ~ClosureDataBase() {}
00204     virtual void marshaller(Value &, const QList<Value> &) = 0;
00205 
00206     bool passSender; //whether to pass the sender instance as the first slot argument
00207 
00208 protected:
00209     inline ClosureDataBase(bool passSender)
00210         : passSender(passSender) {}
00211 };
00212 
00213 //END ******** ClosureDataBase ********
00214 
00215 
00216 /* This interface specifies the methods that will be used to connect/disconnect a
00217  * signal receiver to/from a slot that should be called when the receiver is destroyed.
00218  * This notification is used to disconnect the signal automatically.
00219  */
00220 class QTGLIB_EXPORT DestroyNotifierIface
00221 {
00222 public:
00223     virtual ~DestroyNotifierIface() {}
00224     virtual bool connect(void *receiver, QObject *notificationReceiver, const char *slot) = 0;
00225     virtual bool disconnect(void *receiver, QObject *notificationReceiver) = 0;
00226 };
00227 
00228 typedef QSharedPointer<DestroyNotifierIface> DestroyNotifierIfacePtr;
00229 
00230 /* This is DestroyNotifierIface that works for signal receivers that inherit QObject. */
00231 class QTGLIB_EXPORT QObjectDestroyNotifier : public DestroyNotifierIface
00232 {
00233 public:
00234     static DestroyNotifierIfacePtr instance();
00235 
00236     virtual bool connect(void *receiver, QObject *notificationReceiver, const char *slot);
00237     virtual bool disconnect(void *receiver, QObject *notificationReceiver);
00238 };
00239 
00240 /* This is provided for future expansion.
00241  * It should implement operator DestroyNotifierIfacePtr() and return
00242  * the appropriate DestroyNotifierIface for the given type T
00243  * (i.e. the signal receiver is of type T)
00244  */
00245 template <typename T, typename Enable = void>
00246 struct GetDestroyNotifier
00247 {
00248 };
00249 
00250 /* Partial specialization for QObjects (T inherits QObject) */
00251 template <typename T>
00252 struct GetDestroyNotifier<T, typename boost::enable_if< boost::is_base_of<QObject, T> >::type>
00253 {
00254     inline operator DestroyNotifierIfacePtr() { return QObjectDestroyNotifier::instance(); }
00255 };
00256 
00257 
00258 /* This method is used internally from QGlib::connect(). */
00259 QTGLIB_EXPORT ulong connect(void *instance, const char *signal, Quark detail,
00260                             void *receiver, const DestroyNotifierIfacePtr & notifier,
00261                             uint slotHash, ClosureDataBase *closureData, ConnectFlags flags);
00262 
00263 /* This method is used internally from QGlib::disconnect(). */
00264 QTGLIB_EXPORT bool disconnect(void *instance, const char *signal, Quark detail,
00265                               void *receiver, uint slotHash, ulong handlerId);
00266 
00267 
00268 /* This is a helper that returns a hash value for a member function pointer.
00269  * Because of the nature of member function pointers, it is not possible to cast
00270  * them to void* or any integral type and as a result we need to create a hash value
00271  * of their data to be able to store them in the connections store. This value is
00272  * only used for disconnection, so storing the real pointer is not necessary.
00273  */
00274 template <typename T>
00275 inline typename boost::enable_if< boost::is_member_function_pointer<T>, uint >::type
00276 hashMfp(const T & mfp)
00277 {
00278     const char *data = reinterpret_cast<const char*>(&mfp);
00279     return qHash(QByteArray::fromRawData(data, sizeof(T)));
00280 }
00281 
00282 template <typename T>
00283 inline typename boost::enable_if< boost::is_integral<T>, uint >::type
00284 hashMfp(const T & mfp)
00285 {
00286     Q_ASSERT(mfp == 0);
00287     return 0;
00288 }
00289 
00290 } //namespace Private
00291 
00292 
00293 //The real QGlib::disconnect
00294 
00295 inline bool disconnect(void *instance, const char *detailedSignal = 0, void *receiver = 0)
00296 {
00297     return Private::disconnect(instance, detailedSignal, Quark(), receiver, 0, 0);
00298 }
00299 
00300 template <typename T>
00301 inline bool disconnect(void *instance, const char *detailedSignal, void *receiver, T slot)
00302 {
00303     return Private::disconnect(instance, detailedSignal, Quark(), receiver, Private::hashMfp(slot), 0);
00304 }
00305 
00306 #endif //DOXYGEN_RUN
00307 
00308 } //namespace QGlib
00309 
00310 #if !QGLIB_HAVE_CXX0X
00311 //boost::bind restricts us to 9 arguments. if you need more,
00312 //consider using a modern compiler with variadic template support ;)
00313 # define QGLIB_CONNECT_MAX_ARGS 9
00314 #endif
00315 
00316 #define IN_QGLIB_CONNECT_H
00317 # include "connectimpl.h"
00318 #undef IN_QGLIB_CONNECT_H
00319 
00320 #if defined(QGLIB_CONNECT_MAX_ARGS)
00321 # undef QGLIB_CONNECT_MAX_ARGS
00322 #endif
00323 
00324 #endif //QGLIB_CONNECT_H