QtGStreamer  0.10.1
 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 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 #ifdef Q_MOC_RUN
00023 #define BOOST_TT_HAS_OPERATOR_HPP_INCLUDED
00024 #endif
00025 
00026 
00027 #include "global.h"
00028 #include "quark.h"
00029 #include <QtCore/QObject>
00030 #include <QtCore/QSharedPointer>
00031 #include <QtCore/QFlags>
00032 #include <QtCore/QHash>
00033 #include <boost/type_traits.hpp>
00034 #include <boost/utility/enable_if.hpp>
00035 
00036 namespace QGlib {
00037 
00041 enum ConnectFlag { //codegen: skip=true
00047     ConnectAfter = 1,
00055     PassSender = 2
00056 };
00057 Q_DECLARE_FLAGS(ConnectFlags, ConnectFlag);
00058 Q_DECLARE_OPERATORS_FOR_FLAGS(ConnectFlags)
00059 
00060 #if defined(DOXYGEN_RUN)
00061 
00139 template <typename T, typename R, typename... Args>
00140 bool connect(void *instance, const char *detailedSignal,
00141              T *receiver, R (T::*slot)(Args...), ConnectFlags flags = 0);
00142 
00143 //Fake disconnect() declaration.
00144 //Doxygen should document a version with optional arguments. In reality we have to use
00145 //two versions to avoid having to type the template parameters in case the user wants
00146 //to use NULL for the receiver and slot arguments. Also, a version that takes void*
00147 //for everything is not possible since member function pointers do not cast to void*.
00148 
00195 template <typename T, typename R, typename... Args>
00196 bool disconnect(void *instance, const char *detailedSignal = 0,
00197                 T *receiver = 0, R (T::*slot)(Args...) = 0);
00198 
00199 #else //DOXYGEN_RUN
00200 
00201 namespace Private {
00202 
00203 //BEGIN ******** ClosureDataBase ********
00204 
00205 class QTGLIB_EXPORT ClosureDataBase
00206 {
00207 public:
00208     inline virtual ~ClosureDataBase() {}
00209     virtual void marshaller(Value &, const QList<Value> &) = 0;
00210 
00211     bool passSender; //whether to pass the sender instance as the first slot argument
00212 
00213 protected:
00214     inline ClosureDataBase(bool passSender)
00215         : passSender(passSender) {}
00216 };
00217 
00218 //END ******** ClosureDataBase ********
00219 
00220 
00221 /* This interface specifies the methods that will be used to connect/disconnect a
00222  * signal receiver to/from a slot that should be called when the receiver is destroyed.
00223  * This notification is used to disconnect the signal automatically.
00224  */
00225 class QTGLIB_EXPORT DestroyNotifierIface
00226 {
00227 public:
00228     virtual ~DestroyNotifierIface() {}
00229     virtual bool connect(void *receiver, QObject *notificationReceiver, const char *slot) = 0;
00230     virtual bool disconnect(void *receiver, QObject *notificationReceiver) = 0;
00231 };
00232 
00233 typedef QSharedPointer<DestroyNotifierIface> DestroyNotifierIfacePtr;
00234 
00235 /* This is DestroyNotifierIface that works for signal receivers that inherit QObject. */
00236 class QTGLIB_EXPORT QObjectDestroyNotifier : public DestroyNotifierIface
00237 {
00238 public:
00239     static DestroyNotifierIfacePtr instance();
00240 
00241     virtual bool connect(void *receiver, QObject *notificationReceiver, const char *slot);
00242     virtual bool disconnect(void *receiver, QObject *notificationReceiver);
00243 };
00244 
00245 /* This is provided for future expansion.
00246  * It should implement operator DestroyNotifierIfacePtr() and return
00247  * the appropriate DestroyNotifierIface for the given type T
00248  * (i.e. the signal receiver is of type T)
00249  */
00250 template <typename T, typename Enable = void>
00251 struct GetDestroyNotifier
00252 {
00253 };
00254 
00255 /* Partial specialization for QObjects (T inherits QObject) */
00256 template <typename T>
00257 struct GetDestroyNotifier<T, typename boost::enable_if< boost::is_base_of<QObject, T> >::type>
00258 {
00259     inline operator DestroyNotifierIfacePtr() { return QObjectDestroyNotifier::instance(); }
00260 };
00261 
00262 
00263 /* This method is used internally from QGlib::connect(). */
00264 QTGLIB_EXPORT ulong connect(void *instance, const char *signal, Quark detail,
00265                             void *receiver, const DestroyNotifierIfacePtr & notifier,
00266                             uint slotHash, ClosureDataBase *closureData, ConnectFlags flags);
00267 
00268 /* This method is used internally from QGlib::disconnect(). */
00269 QTGLIB_EXPORT bool disconnect(void *instance, const char *signal, Quark detail,
00270                               void *receiver, uint slotHash, ulong handlerId);
00271 
00272 
00273 /* This is a helper that returns a hash value for a member function pointer.
00274  * Because of the nature of member function pointers, it is not possible to cast
00275  * them to void* or any integral type and as a result we need to create a hash value
00276  * of their data to be able to store them in the connections store. This value is
00277  * only used for disconnection, so storing the real pointer is not necessary.
00278  */
00279 template <typename T>
00280 inline typename boost::enable_if< boost::is_member_function_pointer<T>, uint >::type
00281 hashMfp(const T & mfp)
00282 {
00283     const char *data = reinterpret_cast<const char*>(&mfp);
00284     return qHash(QByteArray::fromRawData(data, sizeof(T)));
00285 }
00286 
00287 template <typename T>
00288 inline typename boost::enable_if< boost::is_integral<T>, uint >::type
00289 hashMfp(const T & mfp)
00290 {
00291     Q_ASSERT(mfp == 0);
00292     return 0;
00293 }
00294 
00295 } //namespace Private
00296 
00297 
00298 //The real QGlib::disconnect
00299 
00300 inline bool disconnect(void *instance, const char *detailedSignal = 0, void *receiver = 0)
00301 {
00302     return Private::disconnect(instance, detailedSignal, Quark(), receiver, 0, 0);
00303 }
00304 
00305 template <typename T>
00306 inline bool disconnect(void *instance, const char *detailedSignal, void *receiver, T slot)
00307 {
00308     return Private::disconnect(instance, detailedSignal, Quark(), receiver, Private::hashMfp(slot), 0);
00309 }
00310 
00311 #endif //DOXYGEN_RUN
00312 
00313 } //namespace QGlib
00314 
00315 #if !QGLIB_HAVE_CXX0X
00316 //boost::bind restricts us to 9 arguments. if you need more,
00317 //consider using a modern compiler with variadic template support ;)
00318 # define QGLIB_CONNECT_MAX_ARGS 9
00319 #endif
00320 
00321 #define IN_QGLIB_CONNECT_H
00322 # include "connectimpl.h"
00323 #undef IN_QGLIB_CONNECT_H
00324 
00325 #if defined(QGLIB_CONNECT_MAX_ARGS)
00326 # undef QGLIB_CONNECT_MAX_ARGS
00327 #endif
00328 
00329 #endif //QGLIB_CONNECT_H
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator