Example #1
0
/*
 * Convert a valid Python signal or slot to an existing universal slot.
 */
void *sipGetRx(sipSimpleWrapper *txSelf, const char *sigargs, PyObject *rxObj,
           const char *slot, const char **memberp)
{
    if (slot != NULL)
        if (isQtSlot(slot) || isQtSignal(slot))
        {
            void *rx;

            *memberp = slot;

            if ((rx = sip_api_get_cpp_ptr((sipSimpleWrapper *)rxObj, sipQObjectType)) == NULL)
                return NULL;

            if (isQtSignal(slot))
                rx = findSignal(rx, memberp);

            return rx;
        }

    /*
     * The slot was either a Python callable or PyQt3 Python signal so there
     * should be a universal slot.
     */
    return sipQtSupport->qt_find_slot(sip_api_get_address(txSelf), sigargs, rxObj, slot, memberp);
}
Example #2
0
/*
 * Convert a Python receiver (either a Python signal or slot or a Qt signal or
 * slot) to a Qt receiver.  It is only ever called when the signal is a Qt
 * signal.  Return NULL is there was an error.
 */
void *sip_api_convert_rx(sipWrapper *txSelf, const char *sigargs,
        PyObject *rxObj, const char *slot, const char **memberp, int flags)
{
    assert(sipQtSupport);

    if (slot == NULL)
        return createUniversalSlot(txSelf, sigargs, rxObj, NULL, memberp, flags);

    if (isQtSlot(slot) || isQtSignal(slot))
    {
        void *rx;

        *memberp = slot;

        if ((rx = sip_api_get_cpp_ptr((sipSimpleWrapper *)rxObj, sipQObjectType)) == NULL)
            return NULL;

        if (isQtSignal(slot))
            rx = newSignal(rx, memberp);

        return rx;
    }

    /* The slot is a Python signal so we need a universal slot to catch it. */
    return createUniversalSlot(txSelf, sigargs, rxObj, slot, memberp, 0);
}
Example #3
0
/*
 * Initialise a slot, returning 0 if there was no error.  If the signal was a
 * Qt signal, then the slot may be a Python signal or a Python slot.  If the
 * signal was a Python signal, then the slot may be anything.
 */
int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot)
{
    sp -> weakSlot = NULL;

    if (slot == NULL)
    {
        sp -> name = NULL;

        if (PyMethod_Check(rxObj))
        {
            /*
             * Python creates methods on the fly.  We could increment the
             * reference count to keep it alive, but that would keep "self"
             * alive as well and would probably be a circular reference.
             * Instead we remember the component parts and hope they are still
             * valid when we re-create the method when we need it.
             */
            sipSaveMethod(&sp -> meth,rxObj);

            /* Notice if the class instance disappears. */
            sp -> weakSlot = getWeakRef(sp -> meth.mself);

            /* This acts a flag to say that the slot is a method. */
            sp -> pyobj = NULL;
        }
        else
        {
            PyObject *self;

            /*
             * We know that it is another type of callable, ie. a
             * function/builtin.
             */

            if (PyCFunction_Check(rxObj) &&
                (self = PyCFunction_GET_SELF(rxObj)) != NULL &&
                PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type))
            {
                /*
                 * It is a wrapped C++ class method.  We can't keep a copy
                 * because they are generated on the fly and we can't take a
                 * reference as that may keep the instance (ie. self) alive.
                 * We therefore treat it as if the user had specified the slot
                 * at "obj, SLOT('meth()')" rather than "obj.meth" (see below).
                 */

                const char *meth;

                /* Get the method name. */
                meth = ((PyCFunctionObject *)rxObj) -> m_ml -> ml_name;

                if ((sp -> name = (char *)sip_api_malloc(strlen(meth) + 2)) == NULL)
                    return -1;

                /*
                 * Copy the name and set the marker that it needs converting to
                 * a built-in method.
                 */
                sp -> name[0] = '\0';
                strcpy(&sp -> name[1],meth);

                sp -> pyobj = self;
                sp -> weakSlot = getWeakRef(self);
            }
            else
            {
                /*
                 * Give the slot an extra reference to keep it alive and
                 * remember we have done so by treating weakSlot specially.
                 */
                Py_INCREF(rxObj);
                sp->pyobj = rxObj;

                Py_INCREF(Py_True);
                sp->weakSlot = Py_True;
            }
        }
    }
    else if ((sp -> name = sipStrdup(slot)) == NULL)
        return -1;
    else if (isQtSlot(slot))
    {
        /*
         * The user has decided to connect a Python signal to a Qt slot and
         * specified the slot as "obj, SLOT('meth()')" rather than "obj.meth".
         */

        char *tail;

        /* Remove any arguments. */
        if ((tail = strchr(sp -> name,'(')) != NULL)
            *tail = '\0';

        /*
         * A bit of a hack to indicate that this needs converting to a built-in
         * method.
         */
        sp -> name[0] = '\0';

        /* Notice if the class instance disappears. */
        sp -> weakSlot = getWeakRef(rxObj);

        sp -> pyobj = rxObj;
    }
    else
        /* It's a Qt signal. */
        sp -> pyobj = rxObj;

    return 0;
}