1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the QtCore module of the Qt Toolkit. |
7 ** This file is part of the QtCore module of the Qt Toolkit. |
8 ** |
8 ** |
2454 two signals are emitted for duplicate connections. You can break |
2454 two signals are emitted for duplicate connections. You can break |
2455 all of these connections with a single disconnect() call. |
2455 all of these connections with a single disconnect() call. |
2456 If you pass the Qt::UniqueConnection \a type, the connection will only |
2456 If you pass the Qt::UniqueConnection \a type, the connection will only |
2457 be made if it is not a duplicate. If there is already a duplicate |
2457 be made if it is not a duplicate. If there is already a duplicate |
2458 (exact same signal to the exact same slot on the same objects), |
2458 (exact same signal to the exact same slot on the same objects), |
2459 the connection will fail and connect will return false |
2459 the connection will fail and connect will return false. |
2460 |
2460 |
2461 The optional \a type parameter describes the type of connection |
2461 The optional \a type parameter describes the type of connection |
2462 to establish. In particular, it determines whether a particular |
2462 to establish. In particular, it determines whether a particular |
2463 signal is delivered to a slot immediately or queued for delivery |
2463 signal is delivered to a slot immediately or queued for delivery |
2464 at a later time. If the signal is queued, the parameters must be |
2464 at a later time. If the signal is queued, the parameters must be |
2943 } |
2943 } |
2944 |
2944 |
2945 return true; |
2945 return true; |
2946 } |
2946 } |
2947 |
2947 |
2948 |
|
2949 /*!\internal |
2948 /*!\internal |
2950 */ |
2949 */ |
2951 bool QMetaObject::disconnect(const QObject *sender, int signal_index, |
2950 bool QMetaObject::disconnect(const QObject *sender, int signal_index, |
2952 const QObject *receiver, int method_index) |
2951 const QObject *receiver, int method_index) |
2953 { |
2952 { |
2954 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index); |
2953 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index); |
2955 return QMetaObjectPrivate::disconnect(sender, signal_index, |
2954 return QMetaObjectPrivate::disconnect(sender, signal_index, |
2956 receiver, method_index); |
2955 receiver, method_index); |
|
2956 } |
|
2957 |
|
2958 /*!\internal |
|
2959 |
|
2960 Disconnect a single signal connection. If QMetaObject::connect() has been called |
|
2961 multiple times for the same sender, signal_index, receiver and method_index only |
|
2962 one of these connections will be removed. |
|
2963 */ |
|
2964 bool QMetaObject::disconnectOne(const QObject *sender, int signal_index, |
|
2965 const QObject *receiver, int method_index) |
|
2966 { |
|
2967 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index); |
|
2968 return QMetaObjectPrivate::disconnect(sender, signal_index, |
|
2969 receiver, method_index, |
|
2970 QMetaObjectPrivate::DisconnectOne); |
2957 } |
2971 } |
2958 |
2972 |
2959 /*! \internal |
2973 /*! \internal |
2960 Helper function to remove the connection from the senders list and setting the receivers to 0 |
2974 Helper function to remove the connection from the senders list and setting the receivers to 0 |
2961 */ |
2975 */ |
2962 bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, |
2976 bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, |
2963 const QObject *receiver, int method_index, |
2977 const QObject *receiver, int method_index, |
2964 QMutex *senderMutex) |
2978 QMutex *senderMutex, DisconnectType disconnectType) |
2965 { |
2979 { |
2966 bool success = false; |
2980 bool success = false; |
2967 while (c) { |
2981 while (c) { |
2968 if (c->receiver |
2982 if (c->receiver |
2969 && (receiver == 0 || (c->receiver == receiver |
2983 && (receiver == 0 || (c->receiver == receiver |
2985 receiverMutex->unlock(); |
2999 receiverMutex->unlock(); |
2986 |
3000 |
2987 c->receiver = 0; |
3001 c->receiver = 0; |
2988 |
3002 |
2989 success = true; |
3003 success = true; |
|
3004 |
|
3005 if (disconnectType == DisconnectOne) |
|
3006 return success; |
2990 } |
3007 } |
2991 c = c->nextConnectionList; |
3008 c = c->nextConnectionList; |
2992 } |
3009 } |
2993 return success; |
3010 return success; |
2994 } |
3011 } |
2995 |
3012 |
2996 /*! \internal |
3013 /*! \internal |
2997 Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex |
3014 Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex |
2998 */ |
3015 */ |
2999 bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index, |
3016 bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index, |
3000 const QObject *receiver, int method_index) |
3017 const QObject *receiver, int method_index, |
|
3018 DisconnectType disconnectType) |
3001 { |
3019 { |
3002 if (!sender) |
3020 if (!sender) |
3003 return false; |
3021 return false; |
3004 |
3022 |
3005 QObject *s = const_cast<QObject *>(sender); |
3023 QObject *s = const_cast<QObject *>(sender); |
3019 if (signal_index < 0) { |
3037 if (signal_index < 0) { |
3020 // remove from all connection lists |
3038 // remove from all connection lists |
3021 for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) { |
3039 for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) { |
3022 QObjectPrivate::Connection *c = |
3040 QObjectPrivate::Connection *c = |
3023 (*connectionLists)[signal_index].first; |
3041 (*connectionLists)[signal_index].first; |
3024 if (disconnectHelper(c, receiver, method_index, senderMutex)) { |
3042 if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) { |
3025 success = true; |
3043 success = true; |
3026 connectionLists->dirty = true; |
3044 connectionLists->dirty = true; |
3027 } |
3045 } |
3028 } |
3046 } |
3029 } else if (signal_index < connectionLists->count()) { |
3047 } else if (signal_index < connectionLists->count()) { |
3030 QObjectPrivate::Connection *c = |
3048 QObjectPrivate::Connection *c = |
3031 (*connectionLists)[signal_index].first; |
3049 (*connectionLists)[signal_index].first; |
3032 if (disconnectHelper(c, receiver, method_index, senderMutex)) { |
3050 if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) { |
3033 success = true; |
3051 success = true; |
3034 connectionLists->dirty = true; |
3052 connectionLists->dirty = true; |
3035 } |
3053 } |
3036 } |
3054 } |
3037 |
3055 |
3244 continue; |
3262 continue; |
3245 } |
3263 } |
3246 |
3264 |
3247 const int method = c->method; |
3265 const int method = c->method; |
3248 QObjectPrivate::Sender currentSender; |
3266 QObjectPrivate::Sender currentSender; |
3249 currentSender.sender = sender; |
3267 const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; |
3250 currentSender.signal = signal_absolute_index; |
|
3251 currentSender.ref = 1; |
|
3252 QObjectPrivate::Sender *previousSender = 0; |
3268 QObjectPrivate::Sender *previousSender = 0; |
3253 if (currentThreadData == receiver->d_func()->threadData) |
3269 if (receiverInSameThread) { |
|
3270 currentSender.sender = sender; |
|
3271 currentSender.signal = signal_absolute_index; |
|
3272 currentSender.ref = 1; |
3254 previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); |
3273 previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); |
|
3274 } |
3255 locker.unlock(); |
3275 locker.unlock(); |
3256 |
3276 |
3257 if (qt_signal_spy_callback_set.slot_begin_callback != 0) { |
3277 if (qt_signal_spy_callback_set.slot_begin_callback != 0) { |
3258 qt_signal_spy_callback_set.slot_begin_callback(receiver, |
3278 qt_signal_spy_callback_set.slot_begin_callback(receiver, |
3259 method, |
3279 method, |
3265 #else |
3285 #else |
3266 QT_TRY { |
3286 QT_TRY { |
3267 metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); |
3287 metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); |
3268 } QT_CATCH(...) { |
3288 } QT_CATCH(...) { |
3269 locker.relock(); |
3289 locker.relock(); |
3270 |
3290 if (receiverInSameThread) |
3271 QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); |
3291 QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); |
3272 |
3292 |
3273 --connectionLists->inUse; |
3293 --connectionLists->inUse; |
3274 Q_ASSERT(connectionLists->inUse >= 0); |
3294 Q_ASSERT(connectionLists->inUse >= 0); |
3275 if (connectionLists->orphaned && !connectionLists->inUse) |
3295 if (connectionLists->orphaned && !connectionLists->inUse) |
3276 delete connectionLists; |
3296 delete connectionLists; |
3281 if (qt_signal_spy_callback_set.slot_end_callback != 0) |
3301 if (qt_signal_spy_callback_set.slot_end_callback != 0) |
3282 qt_signal_spy_callback_set.slot_end_callback(receiver, method); |
3302 qt_signal_spy_callback_set.slot_end_callback(receiver, method); |
3283 |
3303 |
3284 locker.relock(); |
3304 locker.relock(); |
3285 |
3305 |
3286 QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); |
3306 if (receiverInSameThread) |
|
3307 QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); |
3287 |
3308 |
3288 if (connectionLists->orphaned) |
3309 if (connectionLists->orphaned) |
3289 break; |
3310 break; |
3290 } while (c != last && (c = c->nextConnectionList) != 0); |
3311 } while (c != last && (c = c->nextConnectionList) != 0); |
3291 |
3312 |