aboutsummaryrefslogtreecommitdiffstats
path: root/PySide/QtCore/glue/qobject_connect.cpp
blob: 96177322f64d9e668190e957c34fd018f8332e3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
static int qobjectGetMethodIndex(QObject* source, const char* signature, QMetaMethod::MethodType type)
{
    const QMetaObject* metaObject = source->metaObject();
    int methodIndex = metaObject->indexOfMethod(signature);
    // Create the dynamic signal is needed
    if (methodIndex == -1) {
        SbkBaseWrapper* self = (SbkBaseWrapper*) BindingManager::instance().retrieveWrapper(source);
        if (!self->containsCppWrapper) {
            qWarning() << "You can't add dynamic signals or slots on an object originated from C++.";
            return false;
        }
        PySide::DynamicQMetaObject* dynMetaObj = reinterpret_cast<PySide::DynamicQMetaObject*>(const_cast<QMetaObject*>(metaObject));
        if (type == QMetaMethod::Signal)
            dynMetaObj->addSignal(signature);
        else
            dynMetaObj->addSlot(signature);
        methodIndex = metaObject->indexOfMethod(signature);
    }
    return methodIndex;
}

static bool qobjectConnect(QObject* source, const char* signal, QObject* receiver, const char* slot, Qt::ConnectionType type)
{
    if (!PySide::checkSignal(signal))
        return false;
    signal++;

    const QMetaObject* metaObject = source->metaObject();
    int signalIndex = qobjectGetMethodIndex(source, signal, QMetaMethod::Signal);

    bool isSignal = PySide::isSignal(slot);
    slot++;
    metaObject = receiver->metaObject();
    int slotIndex = qobjectGetMethodIndex(receiver, slot, isSignal ? QMetaMethod::Signal : QMetaMethod::Slot);
    return QMetaObject::connect(source, signalIndex, receiver, slotIndex, type);
}

static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType type)
{
    if (!PySide::checkSignal(signal))
        return false;
    signal++;

    const QMetaObject* metaObject = source->metaObject();
    int signalIndex = qobjectGetMethodIndex(source, signal, QMetaMethod::Signal);

    PySide::SignalManager& signalManager = PySide::SignalManager::instance();

    // Extract receiver from callback
    bool usingGlobalReceiver;
    QObject* receiver = 0;
    PyObject* self;
    if (PyMethod_Check(callback)) {
        self = PyMethod_GET_SELF(callback);
        if (SbkQObject_Check(self))
            receiver = SbkQObject_cptr(self);
    } else if (PyCFunction_Check(callback)) {
        self = PyCFunction_GET_SELF(callback);
        if (self && SbkQObject_Check(self))
            receiver = SbkQObject_cptr(self);
    }
    usingGlobalReceiver = !receiver;
    if (usingGlobalReceiver)
        receiver = signalManager.globalReceiver();

    metaObject = receiver->metaObject();
    const QByteArray callbackSig = PySide::getCallbackSignature(signal, callback, usingGlobalReceiver).toAscii();
    const char* slot = callbackSig.constData();
    int slotIndex = metaObject->indexOfSlot(slot);
    if (slotIndex == -1) {
        if (!usingGlobalReceiver and !((SbkBaseWrapper*)self)->containsCppWrapper) {
            qWarning() << "You cant add dynamic slots on an object originated from C++.";
            return false;
        }
        if (usingGlobalReceiver) {
            signalManager.addGlobalSlot(slot, callback);
        } else {
            PySide::DynamicQMetaObject* dynMetaObj = reinterpret_cast<PySide::DynamicQMetaObject*>(const_cast<QMetaObject*>(metaObject));
            dynMetaObj->addSlot(slot);
        }
        slotIndex = metaObject->indexOfSlot(slot);
    }
    if (QMetaObject::connect(source, signalIndex, receiver, slotIndex, type)) {
        if (usingGlobalReceiver)
            signalManager.globalReceiverConnectNotify(slotIndex);

        return true;
    }
    return false;
}


static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObject* callback)
{
    if (!PySide::checkSignal(signal))
        return false;

    PySide::SignalManager& signalManager = PySide::SignalManager::instance();

    // Extract receiver from callback
    bool usingGlobalReceiver;
    QObject* receiver = 0;
    PyObject* self;
    if (PyMethod_Check(callback)) {
        self = PyMethod_GET_SELF(callback);
        if (SbkQObject_Check(self))
            receiver = SbkQObject_cptr(self);
    }
    usingGlobalReceiver = !receiver;
    if (usingGlobalReceiver)
        receiver = signalManager.globalReceiver();

    const QMetaObject* metaObject = receiver->metaObject();
    const QByteArray callbackSig = PySide::getCallbackSignature(signal, callback, usingGlobalReceiver).toAscii();
    QByteArray qtSlotName(callbackSig);
    qtSlotName = qtSlotName.prepend('1');

    if (QObject::disconnect(source, signal, receiver, qtSlotName.constData())) {
        if (usingGlobalReceiver) {
            int slotIndex = metaObject->indexOfSlot(callbackSig.constData());
            signalManager.globalReceiverDisconnectNotify(slotIndex);
        }
        return true;
    }
    return false;
}