예제 #1
0
// The type init slot.
static int pyqtWrapperType_init(pyqtWrapperType *self, PyObject *args,
        PyObject *kwds)
{
    // Let the super-type complete the basic initialisation.
    if (sipWrapperType_Type->tp_init((PyObject *)self, args, kwds) < 0)
        return -1;

    const pyqt4ClassPluginDef *pyqt_td = reinterpret_cast<const pyqt4ClassPluginDef *>(sipTypePluginData(((sipWrapperType *)self)->wt_td));

    if (pyqt_td && !sipIsExactWrappedType((sipWrapperType *)self))
    {
        // Create a dynamic meta-object as its base wrapped type has a static
        // Qt meta-object.
        if (pyqt_td->static_metaobject && create_dynamic_metaobject(self) < 0)
            return -1;
    }

    return 0;
}
예제 #2
0
// The type init slot.
static int pyqtWrapperType_init(pyqtWrapperType *self, PyObject *args,
        PyObject *kwds)
{
    // Let the super-type complete the basic initialisation.
    if (sipWrapperType_Type->tp_init((PyObject *)self, args, kwds) < 0)
        return -1;

    pyqt4ClassTypeDef *pyqt_td = (pyqt4ClassTypeDef *)((sipWrapperType *)self)->type;

    if (pyqt_td && !sipIsExactWrappedType((sipWrapperType *)self))
    {
        // Create a dynamic meta-object as its base wrapped type has a static
        // Qt meta-object.
        if (pyqt_td->qt4_static_metaobject && create_dynamic_metaobject(self) < 0)
            return -1;
    }

    return 0;
}
예제 #3
0
// Parse the given Python type object.
bool Chimera::parse_py_type(PyTypeObject *type_obj)
{
    const sipTypeDef *td = sipTypeFromPyTypeObject(type_obj);

    if (td)
    {
        if (sipTypeIsNamespace(td))
            return false;

        _type = td;
        _name = sipTypeName(td);

        if (sipTypeIsClass(td))
            set_flag();

        if (sipTypeIsEnum(td) || isFlag())
        {
            _metatype = QMetaType::Int;
        }
        else
        {
            bool is_a_QObject = PyType_IsSubtype(type_obj, sipTypeAsPyTypeObject(sipType_QObject));

            // If there is no assignment helper then assume it is a
            // pointer-type.
            if (!get_assign_helper())
                _name.append('*');

            _metatype = QMetaType::type(_name.constData());

            // This will deal with cases where the registered type is a
            // super-class and specifically allows for multiple inheritance.
            // The problem we are solving is that we want a QGraphicsWidget to
            // be handled as a QGraphicsItem (which Qt registers) rather than a
            // QObject, specifically in the value passed as a QVariant to
            // QGraphicsItem::itemChange().  This solution means that it will
            // always be passed as a QGraphicsItem, even if there are
            // circumstances where it should be passed as a QObject.  If we
            // come across such a circumstance then we may need to remove this
            // and implement a more specific solution in %MethodCode for the
            // various itemChange() implementations.
            if (_metatype == 0 && is_a_QObject)
            {
                PyObject *mro = type_obj->tp_mro;

                Q_ASSERT(PyTuple_Check(mro));
                Q_ASSERT(PyTuple_GET_SIZE(mro) >= 3);

                for (SIP_SSIZE_T i = 1; i < PyTuple_GET_SIZE(mro) - 1; ++i)
                {
                    PyTypeObject *sc = (PyTypeObject *)PyTuple_GET_ITEM(mro, i);

                    if (sc == sipSimpleWrapper_Type || sc == sipWrapper_Type)
                        continue;

                    QByteArray sc_name(sc->tp_name);

                    // QObjects are always pointers.
                    sc_name.append('*');

                    _metatype = QMetaType::type(sc_name.constData());

                    if (_metatype >= QMetaType::User)
                    {
                        _type = sipTypeFromPyTypeObject(sc);
                        _name = sc_name;

                        _py_type = (PyObject *)sc;
                        Py_INCREF(_py_type);

                        return true;
                    }
                }
            }

            // If it is a user type then it must be a type that SIP knows
            // about but was registered by Qt.
            if (_metatype < QMetaType::User)
            {
                if (sipType_QWidget && PyType_IsSubtype(type_obj, sipTypeAsPyTypeObject(sipType_QWidget)))
                {
                    _metatype = QMetaType::QWidgetStar;
                }
                else if (is_a_QObject)
                {
                    _metatype = QMetaType::QObjectStar;
                }
                else if (!sipIsExactWrappedType((sipWrapperType *)type_obj))
                {
                    // It must be a (non-QObject, non-QWidget) Python
                    // sub-class so make sure it gets wrapped in a
                    // PyQt_PyObject.
                    _type = 0;
                    _metatype = PyQt_PyObject::metatype;
                    _name.clear();
                }
            }
        }
    }
#if PY_MAJOR_VERSION >= 3
    else if (type_obj == &PyUnicode_Type)
    {
        _type = sipType_QString;
        _metatype = QMetaType::QString;
    }
#else
    else if (type_obj == &PyString_Type || type_obj == &PyUnicode_Type)
    {
        // In this case we accept that the reverse conversion will result in an
        // object of a different type (i.e. a QString rather than a Python
        // string).
        _type = sipType_QString;
        _metatype = QMetaType::QString;
    }
#endif
    else if (type_obj == &PyBool_Type)
    {
        _metatype = QMetaType::Bool;
    }
#if PY_MAJOR_VERSION < 3
    else if (type_obj == &PyInt_Type)
    {
        // We choose to map to a C++ int, even though a Python int is
        // potentially much larger, as it represents the most common usage in
        // Qt.  However we will allow a larger type to be used if the context
        // is right.
        _metatype = QMetaType::Int;
        _inexact = true;
    }
#endif
    else if (type_obj == &PyLong_Type)
    {
        // We choose to map to a C++ int for the same reasons as above and to
        // be consistent with Python3 where everything is a long object.  If
        // this isn't appropriate the user can always use a string to specify
        // the exact C++ type they want.
        _metatype = QMetaType::Int;
        _inexact = true;
    }
    else if (type_obj == &PyFloat_Type)
    {
        _metatype = QMetaType::Double;
    }

    // Fallback to using a PyQt_PyObject.
    if (_metatype == QMetaType::Void)
        _metatype = PyQt_PyObject::metatype;

    // If there is no name so far then use the meta-type name.
    if (_name.isEmpty())
        _name = QMetaType::typeName(_metatype);

    _py_type = (PyObject *)type_obj;
    Py_INCREF(_py_type);

    return true;
}