예제 #1
0
QServiceProxy::QServiceProxy(const QByteArray& metadata, ObjectEndPoint* endPoint, QObject* parent)
    : QObject(parent)
{
    Q_ASSERT(endPoint);
    d = new QServiceProxyPrivate();
    d->metadata = metadata;
    d->meta = 0;
    d->endPoint = endPoint;

    QDataStream stream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;

    builder.deserialize(stream, refs);
    if (stream.status() != QDataStream::Ok) {
        qWarning() << "Invalid metaObject for service received";
    } else {
        QMetaMethodBuilder b = builder.addSignal("errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)");
        
        // After all methods are filled in, otherwise qvector won't be big enough
        localSignals.fill(false, builder.methodCount());        
        localSignals.replace(b.index(), true); // Call activate locally
        
        d->meta = builder.toMetaObject();
    }
}
예제 #2
0
			void WrapperObject::BuildMetaObject ()
			{
				QString path = QFileInfo (Path_).absolutePath ();
				QDir scriptDir (path);

				QMetaObjectBuilder builder;

				builder.setSuperClass (QObject::metaObject ());
				builder.setClassName (QString ("LeechCraft::Plugins::Qross::%1::%2")
							.arg (Type_)
							.arg (SCALL (QString) ("GetName").remove (' ')).toLatin1 ());

				int currentMetaMethod = 0;

				if (scriptDir.exists ("ExportedSlots"))
				{
					QFile slotsFile (scriptDir.filePath ("ExportedSlots"));
					slotsFile.open (QIODevice::ReadOnly);
					QList<QByteArray> sigSlots = slotsFile.readAll ().split ('\n');
					Q_FOREACH (QByteArray signature, sigSlots)
					{
						signature = signature.trimmed ();
						if (signature.isEmpty ())
							continue;
						Index2ExportedSignatures_ [currentMetaMethod++] = signature;
						builder.addSlot (signature);
					}
예제 #3
0
파일: test.cpp 프로젝트: romixlab/trunk
Test::Test(QObject *parent) :
    QObject(parent), d(new TestPrivate)
{
    QMetaObjectBuilder builder;
    builder.setClassName("Test");
    d->catchedSignalId = builder.addSignal("catched(QString,QVariantList)").index();
    d->meta = builder.toMetaObject();

    QDataStream ostream(&d->metadata, QIODevice::WriteOnly);
    builder.serialize(ostream);
}
void QDeclarative1OpenMetaObjectTypePrivate::init(const QMetaObject *metaObj)
{
    if (!mem) {
        mob.setSuperClass(metaObj);
        mob.setClassName(metaObj->className());
        mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);

        mem = mob.toMetaObject();

        propertyOffset = mem->propertyOffset();
        signalOffset = mem->methodOffset();
    }
}
예제 #5
0
QServiceProxy::QServiceProxy(const QByteArray& metadata, ObjectEndPoint* endPoint, QObject* parent)
    : QServiceProxyBase(endPoint, parent)
{
    Q_ASSERT(endPoint);
    d = new QServiceProxyPrivate();
    d->metadata = metadata;
    d->meta = 0;
    d->endPoint = endPoint;
    d->localToRemote = 0;
    d->remoteToLocal = 0;

    QDataStream stream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;

    builder.deserialize(stream, refs);
    if (stream.status() != QDataStream::Ok) {
        qWarning() << "Invalid metaObject for service received";
    } else {
        QMetaObject *remote = builder.toMetaObject();

        builder.setSuperClass(QServiceProxyBase::metaObject());

        QMetaObject *local = builder.toMetaObject();

        d->remoteToLocal = new int[local->methodCount()];
        d->localToRemote = new int[local->methodCount()];

        for (int i = 0; i < local->methodCount(); i++){
            const QMetaMethod m = local->method(i);
            int r = remote->indexOfMethod(m.methodSignature().constData());
            d->localToRemote[i] = r;
            if (r > 0)
                d->remoteToLocal[r] = i;
        }

#if defined(QT_SFW_IPC_DEBUG) && defined(QT_SFW_IPC_DEBUG_VERBOSE)
        QString mapping = QString::fromLatin1("%%% QWE Doing lookup table for ") + endPoint->objectName();
        for (int i = 0; i < local->methodCount(); i++){
            const QMetaMethod m = local->method(i);
            int r = d->localToRemote[i];
            mapping.append(QString::fromLatin1("\n%%%Mapping %1 from %2 to %3").arg(QString::fromLatin1(m.signature())).arg(i).arg(r));
        }
        QServiceDebugLog::instance()->appendToLog(mapping);
#endif

        d->meta = local;

        endPoint->setLookupTable(d->localToRemote, d->remoteToLocal);
    }
}
void QRemoteObjectReplicaPrivate::initializeMetaObject(const QMetaObjectBuilder &builder, const QVariantList &values)
{
    Q_ASSERT(!m_metaObject);

    m_metaObject = builder.toMetaObject();
    //rely on order of properties;
    setProperties(values);
}
예제 #7
0
QServiceProxyBase::QServiceProxyBase(ObjectEndPoint *endpoint, QObject *parent)
    : QObject(parent), d(0)
{

    d = new QServiceProxyBasePrivate();
    d->meta = 0;
    d->endPoint = endpoint;
    d->ipcfailure = -1;
    d->timerId = startTimer(1000);

    QMetaObjectBuilder sup;
    sup.setClassName("QServiceProxyBase");
    QMetaMethodBuilder b = sup.addSignal("errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)");
    d->ipcfailure = b.index();
    d->meta = sup.toMetaObject();
    d->ipcFailureSignal = d->meta->method(d->meta->methodOffset());
    Q_ASSERT(d->ipcFailureSignal.methodSignature() == "errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)");
}
예제 #8
0
파일: test.cpp 프로젝트: romixlab/trunk
bool Test::addSlot(const QString &slot)
{
    if (d->slotId2Name.key(slot, -1) != -1)
        return false;

    QDataStream istream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;
    builder.deserialize(istream, refs);

    int metaIndex = builder.addSlot(slot.toLocal8Bit()).index();
    d->slotId2Name.insert(metaIndex + d->meta->methodOffset(), slot);

    if (d->meta)
        free(d->meta);
    d->meta = builder.toMetaObject();
    QDataStream ostream(&d->metadata, QIODevice::WriteOnly);
    builder.serialize(ostream);

    return true;
}
예제 #9
0
파일: test.cpp 프로젝트: romixlab/trunk
bool Test::removeSignal(const QString &signal)
{
    if (d->signalName2Id.value(signal, -1) == -1)
        return false;

    QDataStream istream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;
    builder.deserialize(istream, refs);

    int metaIndex = d->signalName2Id.value(signal) - d->meta->methodOffset();
    d->signalName2Id.remove(signal);
    builder.removeMethod(metaIndex);

    if (d->meta)
        free(d->meta);
    d->meta = builder.toMetaObject();
    QDataStream ostream(&d->metadata, QIODevice::WriteOnly);
    builder.serialize(ostream);

    return true;
}
예제 #10
0
파일: test.cpp 프로젝트: romixlab/trunk
bool Test::addSignal(const QString &signal)
{
    if (d->signalName2Id.value(signal, -1) != -1)
        return false;

    QDataStream istream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;
    builder.deserialize(istream, refs);

    int metaIndex = builder.addSignal(signal.toLocal8Bit()).index()
            + d->meta->methodOffset();
    d->signalName2Id.insert(signal, metaIndex);

    if (d->meta)
        free(d->meta);
    d->meta = builder.toMetaObject();
    QDataStream ostream(&d->metadata, QIODevice::WriteOnly);
    builder.serialize(ostream);

    return true;
}
예제 #11
0
파일: test.cpp 프로젝트: romixlab/trunk
bool Test::removeSlot(const QString &slot)
{
    if (d->slotId2Name.key(slot, -1) == -1)
        return false;

    QDataStream istream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;
    builder.deserialize(istream, refs);

    int metaIndex = d->slotId2Name.key(slot);
    builder.removeMethod(metaIndex - d->meta->methodOffset());
    d->slotId2Name.remove(metaIndex);

    if (d->meta)
        free(d->meta);
    d->meta = builder.toMetaObject();
    QDataStream ostream(&d->metadata, QIODevice::WriteOnly);
    builder.serialize(ostream);

    return true;
}
예제 #12
0
void deserializeInitDynamicPacket(QDataStream &in, QMetaObjectBuilder &builder, QVariantList &values)
{
    quint32 numSignals = 0;
    quint32 numMethods = 0;
    quint32 numProperties = 0;

    in >> numSignals;
    in >> numMethods;

    int curIndex = 0;

    for (quint32 i = 0; i < numSignals; ++i) {
        QByteArray signature;
        in >> signature;
        ++curIndex;
        builder.addSignal(signature);
    }

    for (quint32 i = 0; i < numMethods; ++i) {
        QByteArray signature, returnType;

        in >> signature;
        in >> returnType;
        ++curIndex;
        const bool isVoid = returnType.isEmpty() || returnType == QByteArrayLiteral("void");
        if (isVoid)
            builder.addMethod(signature);
        else
            builder.addMethod(signature, QByteArrayLiteral("QRemoteObjectPendingCall"));
    }

    in >> numProperties;
    const quint32 initialListSize = values.size();
    if (static_cast<quint32>(values.size()) < numProperties)
        values.reserve(numProperties);
    else if (static_cast<quint32>(values.size()) > numProperties)
        for (quint32 i = numProperties; i < initialListSize; ++i)
            values.removeLast();

    for (quint32 i = 0; i < numProperties; ++i) {
        QByteArray name;
        QByteArray typeName;
        QByteArray signalName;
        in >> name;
        in >> typeName;
        in >> signalName;
        if (signalName.isEmpty())
            builder.addProperty(name, typeName);
        else
            builder.addProperty(name, typeName, builder.indexOfSignal(signalName));
        QVariant value;
        in >> value;
        if (i < initialListSize)
            values[i] = value;
        else
            values.append(value);
    }
}
예제 #13
0
// Create a universal proxy used as a slot.  Note that this will leak if there
// is no transmitter and this is not a single shot slot.  There will be no
// meta-object if there was a problem creating the proxy.  This is called
// without the GIL.
PyQtSlotProxy::PyQtSlotProxy(PyObject *slot, QObject *q_tx,
        const Chimera::Signature *slot_signature, bool single_shot)
    : QObject(), proxy_flags(single_shot ? PROXY_SINGLE_SHOT : 0),
        signature(slot_signature->signature), transmitter(q_tx)
{
    SIP_BLOCK_THREADS
    real_slot = new PyQtSlot(slot, slot_signature);
    SIP_UNBLOCK_THREADS

    // Create a new meta-object on the heap so that it looks like it has a slot
    // of the right name and signature.
    QMetaObjectBuilder builder;

    builder.setClassName("PyQtSlotProxy");
    builder.setSuperClass(&QObject::staticMetaObject);

    builder.addSlot("unislot()");
    builder.addSlot("disable()");

    meta_object = builder.toMetaObject();

    // Detect when any transmitter is destroyed.  (Note that we used to do this
    // by making the proxy a child of the transmitter.  This doesn't work as
    // expected because QWidget destroys its children before emitting the
    // destroyed signal.)  We use a queued connection in case the proxy is also
    // connected to the same signal and we want to make sure it has a chance to
    // invoke the slot before being destroyed.
    if (transmitter)
    {
        // Add this one to the global hash.
        mutex->lock();
        proxy_slots.insert(transmitter, this);
        mutex->unlock();

        connect(transmitter, SIGNAL(destroyed(QObject *)), SLOT(disable()),
                Qt::QueuedConnection);
    }
}
예제 #14
0
QMetaObject *DosQMetaObject::createMetaObject(const QString &className,
                                              const SignalDefinitions &signalDefinitions,
                                              const SlotDefinitions &slotDefinitions,
                                              const PropertyDefinitions &propertyDefinitions)
{
    QMetaObjectBuilder builder;
    builder.setClassName(className.toUtf8());
    builder.setSuperClass(m_superClassDosMetaObject->metaObject());

    for (const SignalDefinition &signal : signalDefinitions) {
        QMetaMethodBuilder signalBuilder = builder.addSignal(::createSignature(signal));
        signalBuilder.setReturnType(QMetaType::typeName(QMetaType::Void));
        signalBuilder.setAccess(QMetaMethod::Public);
        signalBuilder.setParameterNames(createParameterNames(signal));
        m_signalIndexByName[signal.name] = signalBuilder.index();
    }

    QHash<QString, int> methodIndexByName;
    for (const SlotDefinition &slot : slotDefinitions) {
        QMetaMethodBuilder methodBuilder = builder.addSlot(::createSignature(slot));
        methodBuilder.setReturnType(QMetaType::typeName(slot.returnType));
        methodBuilder.setAttributes(QMetaMethod::Scriptable);
        methodIndexByName[slot.name] = methodBuilder.index();
    }

    for (const PropertyDefinition &property : propertyDefinitions) {
        const int writer = methodIndexByName.value(property.writeSlot, -1);
        const int notifier = m_signalIndexByName.value(property.notifySignal, -1);
        const QByteArray name = property.name.toUtf8();
        const QByteArray typeName = QMetaObject::normalizedType(QMetaType::typeName(property.type));
        QMetaPropertyBuilder propertyBuilder = builder.addProperty(name, typeName, notifier);
        if (writer == -1)
            propertyBuilder.setWritable(false);
        if (notifier == -1)
            propertyBuilder.setConstant(true);
        m_propertySlots[property.name] = qMakePair(methodIndexByName.value(property.readSlot, -1),
                                                   methodIndexByName.value(property.writeSlot, -1));
    }

    return builder.toMetaObject();
}
예제 #15
0
파일: govalue.cpp 프로젝트: dengmin/go-qt5
QMetaObject *GoValue::metaObjectFor(GoTypeInfo *typeInfo)
{
    if (typeInfo->metaObject) {
            return reinterpret_cast<QMetaObject *>(typeInfo->metaObject);
    }

    QMetaObjectBuilder mob;
    mob.setSuperClass(&QObject::staticMetaObject);
    mob.setClassName(typeInfo->typeName);
    mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);

    GoMemberInfo *memberInfo;
    
    memberInfo = typeInfo->fields;
    int relativePropIndex = mob.propertyCount();
    for (int i = 0; i < typeInfo->fieldsLen; i++) {
        mob.addSignal("__" + QByteArray::number(relativePropIndex) + "()");
        QMetaPropertyBuilder propb = mob.addProperty(memberInfo->memberName, "QVariant", relativePropIndex);
        propb.setWritable(true);
        memberInfo->metaIndex = relativePropIndex;
        memberInfo++;
        relativePropIndex++;
    }

    memberInfo = typeInfo->methods;
    int relativeMethodIndex = mob.methodCount();
    for (int i = 0; i < typeInfo->methodsLen; i++) {
        if (*memberInfo->resultSignature) {
            mob.addMethod(memberInfo->methodSignature, memberInfo->resultSignature);
        } else {
            mob.addMethod(memberInfo->methodSignature);
        }
        memberInfo->metaIndex = relativeMethodIndex;
        memberInfo++;
        relativeMethodIndex++;
    }

    QMetaObject *mo = mob.toMetaObject();

    // Turn the relative indexes into absolute indexes.
    memberInfo = typeInfo->fields;
    int propOffset = mo->propertyOffset();
    for (int i = 0; i < typeInfo->fieldsLen; i++) {
        memberInfo->metaIndex += propOffset;
        memberInfo++;
    }
    memberInfo = typeInfo->methods;
    int methodOffset = mo->methodOffset();
    for (int i = 0; i < typeInfo->methodsLen; i++) {
        memberInfo->metaIndex += methodOffset;
        memberInfo++;
    }

    typeInfo->metaObject = mo;
    return mo;
}
예제 #16
0
// Create a dynamic meta-object for a Python type by introspecting its
// attributes.  Note that it leaks if the type is deleted.
static int create_dynamic_metaobject(pyqtWrapperType *pyqt_wt)
{
    PyTypeObject *pytype = (PyTypeObject *)pyqt_wt;
    qpycore_metaobject *qo = new qpycore_metaobject;
#if QT_VERSION >= 0x050000
    QMetaObjectBuilder builder;
#endif

    // Get any class info.
    QList<ClassInfo> class_info_list = qpycore_get_class_info_list();

    // Get the super-type's meta-object.
#if QT_VERSION >= 0x050000
    builder.setSuperClass(get_qmetaobject((pyqtWrapperType *)pytype->tp_base));
#else
    qo->mo.d.superdata = get_qmetaobject((pyqtWrapperType *)pytype->tp_base);
#endif

    // Get the name of the type.  Dynamic types have simple names.
#if QT_VERSION >= 0x050000
    builder.setClassName(pytype->tp_name);
#else
    qo->str_data = pytype->tp_name;
    qo->str_data.append('\0');
#endif

    // Go through the class dictionary getting all PyQt properties, slots,
    // signals or a (deprecated) sequence of signals.

    typedef QPair<PyObject *, PyObject *> prop_data;
    QMap<uint, prop_data> pprops;
    QList<QByteArray> psigs;
    SIP_SSIZE_T pos = 0;
    PyObject *key, *value;
#if QT_VERSION < 0x050000
    bool has_notify_signal = false;
    QList<const QMetaObject *> enum_scopes;
#endif

    while (PyDict_Next(pytype->tp_dict, &pos, &key, &value))
    {
        // See if it is a slot, ie. it has been decorated with pyqtSlot().
        PyObject *sig_obj = PyObject_GetAttr(value,
                qpycore_signature_attr_name);

        if (sig_obj)
        {
            // Make sure it is a list and not some legitimate attribute that
            // happens to use our special name.
            if (PyList_Check(sig_obj))
            {
                for (SIP_SSIZE_T i = 0; i < PyList_GET_SIZE(sig_obj); ++i)
                {
                    qpycore_slot slot;

                    // Set up the skeleton slot.
                    PyObject *decoration = PyList_GET_ITEM(sig_obj, i);
                    slot.signature = Chimera::Signature::fromPyObject(decoration);

                    slot.sip_slot.pyobj = 0;
                    slot.sip_slot.name = 0;
                    slot.sip_slot.meth.mfunc = value;
                    slot.sip_slot.meth.mself = 0;
#if PY_MAJOR_VERSION < 3
                    slot.sip_slot.meth.mclass = (PyObject *)pyqt_wt;
#endif
                    slot.sip_slot.weakSlot = 0;

                    qo->pslots.append(slot);
                }
            }

            Py_DECREF(sig_obj);
        }
        else
        {
            PyErr_Clear();

            // Make sure the key is an ASCII string.  Delay the error checking
            // until we know we actually need it.
            const char *ascii_key = sipString_AsASCIIString(&key);

            // See if the value is of interest.
            if (PyType_IsSubtype(Py_TYPE(value), &qpycore_pyqtProperty_Type))
            {
                // It is a property.

                if (!ascii_key)
                    return -1;

                Py_INCREF(value);

                qpycore_pyqtProperty *pp = (qpycore_pyqtProperty *)value;

                pprops.insert(pp->pyqtprop_sequence, prop_data(key, value));

                // See if the property has a scope.  If so, collect all
                // QMetaObject pointers that are not in the super-class
                // hierarchy.
                const QMetaObject *mo = get_scope_qmetaobject(pp->pyqtprop_parsed_type);

#if QT_VERSION >= 0x050000
                if (mo)
                    builder.addRelatedMetaObject(mo);
#else
                if (mo && !enum_scopes.contains(mo))
                    enum_scopes.append(mo);
#endif

#if QT_VERSION < 0x050000
                // See if the property has a notify signal so that we can
                // allocate space for it in the meta-object.  We will check if
                // it is valid later on.  If there is one property with a
                // notify signal then a signal index is stored for all
                // properties.
                if (pp->pyqtprop_notify)
                    has_notify_signal = true;
#endif
            }
            else if (PyType_IsSubtype(Py_TYPE(value), &qpycore_pyqtSignal_Type))
            {
                // It is a signal.

                if (!ascii_key)
                    return -1;

                qpycore_pyqtSignal *ps = (qpycore_pyqtSignal *)value;

                // Make sure the signal has a name.
                qpycore_set_signal_name(ps, pytype->tp_name, ascii_key);

                // Add all the overloads.
                do
                {
                    psigs.append(ps->signature->signature);

                    ps = ps->next;
                }
                while (ps);

                Py_DECREF(key);
            }
            else if (ascii_key && qstrcmp(ascii_key, "__pyqtSignals__") == 0)
            {
                // It is a sequence of signal signatures.  This is deprecated
                // in favour of pyqtSignal().

                if (PySequence_Check(value))
                {
                    SIP_SSIZE_T seq_sz = PySequence_Size(value);

                    for (SIP_SSIZE_T i = 0; i < seq_sz; ++i)
                    {
                        PyObject *itm = PySequence_ITEM(value, i);

                        if (!itm)
                        {
                            Py_DECREF(key);
                            return -1;
                        }

                        PyObject *ascii_itm = itm;
                        const char *ascii = sipString_AsASCIIString(&ascii_itm);
                        Py_DECREF(itm);

                        if (!ascii)
                        {
                            Py_DECREF(key);
                            return -1;
                        }

                        QByteArray old_sig = QMetaObject::normalizedSignature(ascii);
                        old_sig.prepend('2');
                        psigs.append(old_sig);

                        Py_DECREF(ascii_itm);
                    }
                }

                Py_DECREF(key);
            }
            else
            {
                PyErr_Clear();
            }
        }
    }

    qo->nr_signals = psigs.count();

#if QT_VERSION < 0x050000
    // Create and fill the extradata array.
    if (enum_scopes.isEmpty())
    {
        qo->mo.d.extradata = 0;
    }
    else
    {
        const QMetaObject **objects = new const QMetaObject *[enum_scopes.size() + 1];

        for (int i = 0; i < enum_scopes.size(); ++i)
            objects[i] = enum_scopes.at(i);

        objects[enum_scopes.size()] = 0;

#if QT_VERSION >= 0x040600
        qo->ed.objects = objects;
        qo->ed.static_metacall = 0;

        qo->mo.d.extradata = &qo->ed;
#else
        qo->mo.d.extradata = objects;
#endif
    }
#endif

    // Initialise the header section of the data table.  Note that Qt v4.5
    // introduced revision 2 which added constructors.  However the design is
    // broken in that the static meta-call function doesn't provide enough
    // information to determine which Python sub-class of a Qt class is to be
    // created.  So we stick with revision 1 (and don't allow pyqtSlot() to
    // decorate __init__).

#if QT_VERSION < 0x050000
#if QT_VERSION >= 0x040600
    const int revision = 4;
    const int header_size = 14;
#else
    const int revision = 1;
    const int header_size = 10;
#endif

    int data_len = header_size + class_info_list.count() * 2 +
            qo->nr_signals * 5 + qo->pslots.count() * 5 + 
            pprops.count() * (has_notify_signal ? 4 : 3) + 1;
    uint *data = new uint[data_len];
    int i_offset = header_size;
    int g_offset = i_offset + class_info_list.count() * 2;
    int s_offset = g_offset + qo->nr_signals * 5;
    int p_offset = s_offset + qo->pslots.count() * 5;
    int n_offset = p_offset + pprops.count() * 3;
    int empty = 0;

    for (int i = 0; i < data_len; ++i)
        data[i] = 0;

    // The revision number.
    data[0] = revision;
#endif

    // Set up any class information.
    if (class_info_list.count() > 0)
    {
#if QT_VERSION < 0x050000
        data[2] = class_info_list.count();
        data[3] = i_offset;
#endif

        for (int i = 0; i < class_info_list.count(); ++i)
        {
            const ClassInfo &ci = class_info_list.at(i);

#if QT_VERSION >= 0x050000
            builder.addClassInfo(ci.first, ci.second);
#else
            data[i_offset + (i * 2) + 0] = qo->str_data.size();
            qo->str_data.append(ci.first.constData());
            qo->str_data.append('\0');

            data[i_offset + (i * 2) + 1] = qo->str_data.size();
            qo->str_data.append(ci.second.constData());
            qo->str_data.append('\0');
#endif
        }
    }

#if QT_VERSION < 0x050000
    // Set up the methods count and offset.
    if (qo->nr_signals || qo->pslots.count())
    {
        data[4] = qo->nr_signals + qo->pslots.count();
        data[5] = g_offset;

        // We might need an empty string.
        empty = qo->str_data.size();
        qo->str_data.append('\0');
    }

    // Set up the properties count and offset.
    if (pprops.count())
    {
        data[6] = pprops.count();
        data[7] = p_offset;
    }

#if QT_VERSION >= 0x040600
    data[13] = qo->nr_signals;
#endif
#endif

    // Add the signals to the meta-object.
    for (int g = 0; g < qo->nr_signals; ++g)
    {
        const QByteArray &norm = psigs.at(g);

#if QT_VERSION >= 0x050000
        builder.addSignal(norm.mid(1));
#else
        // Add the (non-existent) argument names.
        data[g_offset + (g * 5) + 1] = add_arg_names(qo, norm, empty);

        // Add the full signature.
        data[g_offset + (g * 5) + 0] = qo->str_data.size();
        qo->str_data.append(norm.constData() + 1);
        qo->str_data.append('\0');

        // Add the type, tag and flags.
        data[g_offset + (g * 5) + 2] = empty;
        data[g_offset + (g * 5) + 3] = empty;
        data[g_offset + (g * 5) + 4] = 0x05;
#endif
    }

    // Add the slots to the meta-object.
    for (int s = 0; s < qo->pslots.count(); ++s)
    {
        const qpycore_slot &slot = qo->pslots.at(s);
        const QByteArray &sig = slot.signature->signature;

#if QT_VERSION >= 0x050000
        QMetaMethodBuilder slot_builder = builder.addSlot(sig);
#else
        // Add the (non-existent) argument names.
        data[s_offset + (s * 5) + 1] = add_arg_names(qo, sig, empty);

        // Add the full signature.
        data[s_offset + (s * 5) + 0] = qo->str_data.size();
        qo->str_data.append(sig);
        qo->str_data.append('\0');
#endif

        // Add any type.
        if (slot.signature->result)
        {
#if QT_VERSION >= 0x050000
            slot_builder.setReturnType(slot.signature->result->name());
#else
            data[s_offset + (s * 5) + 2] = qo->str_data.size();
            qo->str_data.append(slot.signature->result->name());
            qo->str_data.append('\0');
#endif
        }
#if QT_VERSION < 0x050000
        else
        {
            data[s_offset + (s * 5) + 2] = empty;
        }

        // Add the tag and flags.
        data[s_offset + (s * 5) + 3] = empty;
        data[s_offset + (s * 5) + 4] = 0x0a;
#endif
    }

    // Add the properties to the meta-object.
#if QT_VERSION < 0x050000
    QList<uint> notify_signals;
#endif
    QMapIterator<uint, prop_data> it(pprops);

    for (int p = 0; it.hasNext(); ++p)
    {
        it.next();

        const prop_data &pprop = it.value();
        const char *prop_name = SIPBytes_AS_STRING(pprop.first);
        qpycore_pyqtProperty *pp = (qpycore_pyqtProperty *)pprop.second;
        int notifier_id;
#if QT_VERSION < 0x050000
        uint flags = 0;
#endif

        if (pp->pyqtprop_notify)
        {
            qpycore_pyqtSignal *ps = (qpycore_pyqtSignal *)pp->pyqtprop_notify;
            const QByteArray &sig = ps->signature->signature;

#if QT_VERSION >= 0x050000
            notifier_id = builder.indexOfSignal(sig.mid(1));
#else
            notifier_id = psigs.indexOf(sig);
#endif

            if (notifier_id < 0)
            {
                PyErr_Format(PyExc_TypeError,
                        "the notify signal '%s' was not defined in this class",
                        sig.constData() + 1);

                // Note that we leak the property name.
                return -1;
            }

#if QT_VERSION < 0x050000
            notify_signals.append(notifier_id);
            flags |= 0x00400000;
#endif
        }
        else
        {
#if QT_VERSION >= 0x050000
            notifier_id = -1;
#else
            notify_signals.append(0);
#endif
        }

#if QT_VERSION >= 0x050000
        // A Qt v5 revision 7 meta-object holds the QMetaType::Type of the type
        // or its name if it is unresolved (ie. not known to the type system).
        // In Qt v4 both are held.  For QObject sub-classes Chimera will fall
        // back to the QMetaType::QObjectStar if there is no specific meta-type
        // for the sub-class.  This means that, for Qt v4,
        // QMetaProperty::read() can handle the type.  However, Qt v5 doesn't
        // know that the unresolved type is a QObject sub-class.  Therefore we
        // have to tell it that the property is a QObject, rather than the
        // sub-class.  This means that QMetaProperty.typeName() will always
        // return "QObject*".
        QByteArray prop_type;

        if (pp->pyqtprop_parsed_type->metatype() == QMetaType::QObjectStar)
            prop_type = "QObject*";
        else
            prop_type = pp->pyqtprop_parsed_type->name();

        QMetaPropertyBuilder prop_builder = builder.addProperty(prop_name,
                prop_type, notifier_id);

        // Reset the defaults.
        prop_builder.setReadable(false);
        prop_builder.setWritable(false);
#else
        // Add the property name.
        data[p_offset + (p * 3) + 0] = qo->str_data.size();
        qo->str_data.append(prop_name);
        qo->str_data.append('\0');

        // Add the name of the property type.
        data[p_offset + (p * 3) + 1] = qo->str_data.size();
        qo->str_data.append(pp->pyqtprop_parsed_type->name());
        qo->str_data.append('\0');

        // There are only 8 bits available for the type so use the special
        // value if more are required.
        uint metatype = pp->pyqtprop_parsed_type->metatype();

        if (metatype > 0xff)
        {
#if QT_VERSION >= 0x040600
            // Qt assumes it is an enum.
            metatype = 0;
            flags |= 0x00000008;
#else
            // This is the old PyQt behaviour.  It may not be correct, but
            // nobody has complained, and if it ain't broke...
            metatype = 0xff;
#endif
        }
#endif

        // Enum or flag.
        if (pp->pyqtprop_parsed_type->isEnum() || pp->pyqtprop_parsed_type->isFlag())
        {
#if QT_VERSION >= 0x050000
            prop_builder.setEnumOrFlag(true);
#else
#if QT_VERSION >= 0x040600
            metatype = 0;
#endif
            flags |= 0x00000008;
#endif
        }

#if QT_VERSION < 0x050000
        flags |= metatype << 24;
#endif

        if (pp->pyqtprop_get && PyCallable_Check(pp->pyqtprop_get))
            // Readable.
#if QT_VERSION >= 0x050000
            prop_builder.setReadable(true);
#else
            flags |= 0x00000001;
#endif

        if (pp->pyqtprop_set && PyCallable_Check(pp->pyqtprop_set))
        {
            // Writable.
#if QT_VERSION >= 0x050000
            prop_builder.setWritable(true);
#else
            flags |= 0x00000002;
#endif

            // See if the name of the setter follows the Designer convention.
            // If so tell the UI compilers not to use setProperty().
            PyObject *setter_name_obj = PyObject_GetAttr(pp->pyqtprop_set,
                    qpycore_name_attr_name);

            if (setter_name_obj)
            {
                PyObject *ascii_obj = setter_name_obj;
                const char *ascii = sipString_AsASCIIString(&ascii_obj);
                Py_DECREF(setter_name_obj);

                if (ascii)
                {
                    if (qstrlen(ascii) > 3 && ascii[0] == 's' &&
                            ascii[1] == 'e' && ascii[2] == 't' &&
                            ascii[3] == toupper(prop_name[0]) &&
                            qstrcmp(&ascii[4], &prop_name[1]) == 0)
#if QT_VERSION >= 0x050000
                        prop_builder.setStdCppSet(true);
#else
                        flags |= 0x00000100;
#endif
                }

                Py_DECREF(ascii_obj);
            }

            PyErr_Clear();
        }

        if (pp->pyqtprop_reset && PyCallable_Check(pp->pyqtprop_reset))
            // Resetable.
#if QT_VERSION >= 0x050000
            prop_builder.setResettable(true);
#else
            flags |= 0x00000004;
#endif

        // Add the property flags.
#if QT_VERSION >= 0x050000
        // Note that Qt4 always seems to have ResolveEditable set but
        // QMetaObjectBuilder doesn't provide an API call to do it.
        prop_builder.setDesignable(pp->pyqtprop_flags & 0x00001000);
        prop_builder.setScriptable(pp->pyqtprop_flags & 0x00004000);
        prop_builder.setStored(pp->pyqtprop_flags & 0x00010000);
        prop_builder.setUser(pp->pyqtprop_flags & 0x00100000);
        prop_builder.setConstant(pp->pyqtprop_flags & 0x00000400);
        prop_builder.setFinal(pp->pyqtprop_flags & 0x00000800);
#else
        flags |= pp->pyqtprop_flags;

        data[p_offset + (p * 3) + 2] = flags;
#endif

        // Save the property data for qt_metacall().  (We already have a
        // reference.)
        qo->pprops.append(pp);

        // We've finished with the property name.
        Py_DECREF(pprop.first);
    }

#if QT_VERSION < 0x050000
    // Add the indices of the notify signals.
    if (has_notify_signal)
    {
        QListIterator<uint> notify_it(notify_signals);

        while (notify_it.hasNext())
            data[n_offset++] = notify_it.next();
    }
#endif

    // Initialise the rest of the meta-object.
#if QT_VERSION >= 0x050000
    qo->mo = builder.toMetaObject();
#else
    qo->mo.d.stringdata = qo->str_data.constData();
    qo->mo.d.data = data;
#endif

    // Save the meta-object.
    pyqt_wt->metaobject = qo;

    return 0;
}
예제 #17
0
// Create a dynamic meta-object for a Python type by introspecting its
// attributes.  Note that it leaks if the type is deleted.
static int create_dynamic_metaobject(pyqtWrapperType *pyqt_wt)
{
    PyTypeObject *pytype = (PyTypeObject *)pyqt_wt;
    qpycore_metaobject *qo = new qpycore_metaobject;
    QMetaObjectBuilder builder;

    // Get any class info.
    QList<ClassInfo> class_info_list = qpycore_get_class_info_list();

    // Get any enums/flags.
    QList<EnumsFlags> enums_flags_list = qpycore_get_enums_flags_list();

    // Get the super-type's meta-object.
    builder.setSuperClass(get_qmetaobject((pyqtWrapperType *)pytype->tp_base));

    // Get the name of the type.  Dynamic types have simple names.
    builder.setClassName(pytype->tp_name);

    // Go through the class hierarchy getting all PyQt properties, slots and
    // signals.

    QList<const qpycore_pyqtSignal *> psigs;
    QMap<uint, PropertyData> pprops;

    if (trawl_hierarchy(pytype, qo, builder, psigs, pprops) < 0)
        return -1;

    qo->nr_signals = psigs.count();

    // Initialise the header section of the data table.  Note that Qt v4.5
    // introduced revision 2 which added constructors.  However the design is
    // broken in that the static meta-call function doesn't provide enough
    // information to determine which Python sub-class of a Qt class is to be
    // created.  So we stick with revision 1 (and don't allow pyqtSlot() to
    // decorate __init__).

    // Set up any class information.
    for (int i = 0; i < class_info_list.count(); ++i)
    {
        const ClassInfo &ci = class_info_list.at(i);

        builder.addClassInfo(ci.first, ci.second);
    }

    // Set up any enums/flags.
    for (int i = 0; i < enums_flags_list.count(); ++i)
    {
        const EnumsFlags &ef = enums_flags_list.at(i);

        QByteArray scoped_name(pytype->tp_name);
        scoped_name.append("::");
        scoped_name.append(ef.name);
        QMetaEnumBuilder enum_builder = builder.addEnumerator(scoped_name);

        enum_builder.setIsFlag(ef.isFlag);

        QHash<QByteArray, int>::const_iterator it = ef.keys.constBegin();

        while (it != ef.keys.constEnd())
        {
            enum_builder.addKey(it.key(), it.value());
            ++it;
        }
    }

    // Add the signals to the meta-object.
    for (int g = 0; g < qo->nr_signals; ++g)
    {
        const qpycore_pyqtSignal *ps = psigs.at(g);

        QMetaMethodBuilder signal_builder = builder.addSignal(
                ps->parsed_signature->signature.mid(1));

        if (ps->parameter_names)
            signal_builder.setParameterNames(*ps->parameter_names);

        signal_builder.setRevision(ps->revision);
    }

    // Add the slots to the meta-object.
    for (int s = 0; s < qo->pslots.count(); ++s)
    {
        const Chimera::Signature *slot_signature = qo->pslots.at(s)->slotSignature();
        const QByteArray &sig = slot_signature->signature;

        QMetaMethodBuilder slot_builder = builder.addSlot(sig);

        // Add any type.
        if (slot_signature->result)
            slot_builder.setReturnType(slot_signature->result->name());

        slot_builder.setRevision(slot_signature->revision);
    }

    // Add the properties to the meta-object.
    QMapIterator<uint, PropertyData> it(pprops);

    for (int p = 0; it.hasNext(); ++p)
    {
        it.next();

        const PropertyData &pprop = it.value();
        const char *prop_name = SIPBytes_AS_STRING(pprop.first);
        qpycore_pyqtProperty *pp = (qpycore_pyqtProperty *)pprop.second;
        int notifier_id;

        if (pp->pyqtprop_notify)
        {
            qpycore_pyqtSignal *ps = (qpycore_pyqtSignal *)pp->pyqtprop_notify;
            const QByteArray &sig = ps->parsed_signature->signature;

            notifier_id = builder.indexOfSignal(sig.mid(1));

            if (notifier_id < 0)
            {
                PyErr_Format(PyExc_TypeError,
                        "the notify signal '%s' was not defined in this class",
                        sig.constData() + 1);

                // Note that we leak the property name.
                return -1;
            }
        }
        else
        {
            notifier_id = -1;
        }

        // A Qt v5 revision 7 meta-object holds the QMetaType::Type of the type
        // or its name if it is unresolved (ie. not known to the type system).
        // In Qt v4 both are held.  For QObject sub-classes Chimera will fall
        // back to the QMetaType::QObjectStar if there is no specific meta-type
        // for the sub-class.  This means that, for Qt v4,
        // QMetaProperty::read() can handle the type.  However, Qt v5 doesn't
        // know that the unresolved type is a QObject sub-class.  Therefore we
        // have to tell it that the property is a QObject, rather than the
        // sub-class.  This means that QMetaProperty.typeName() will always
        // return "QObject*".
        QByteArray prop_type;

        if (pp->pyqtprop_parsed_type->metatype() == QMetaType::QObjectStar)
        {
            // However, if the type is a Python sub-class of QObject then we
            // use the name of the Python type.  This anticipates that the type
            // is one that will be proxied by QML at some point.
            if (pp->pyqtprop_parsed_type->typeDef() == sipType_QObject)
            {
                prop_type = ((PyTypeObject *)pp->pyqtprop_parsed_type->py_type())->tp_name;
                prop_type.append('*');
            }
            else
            {
                prop_type = "QObject*";
            }
        }
        else
        {
            prop_type = pp->pyqtprop_parsed_type->name();
        }

        QMetaPropertyBuilder prop_builder = builder.addProperty(prop_name,
                prop_type, notifier_id);

        // Reset the defaults.
        prop_builder.setReadable(false);
        prop_builder.setWritable(false);

        // Enum or flag.
        if (pp->pyqtprop_parsed_type->isEnum() || pp->pyqtprop_parsed_type->isFlag())
        {
            prop_builder.setEnumOrFlag(true);
        }

        if (pp->pyqtprop_get && PyCallable_Check(pp->pyqtprop_get))
        {
            // Readable.
            prop_builder.setReadable(true);
        }

        if (pp->pyqtprop_set && PyCallable_Check(pp->pyqtprop_set))
        {
            // Writable.
            prop_builder.setWritable(true);

            // See if the name of the setter follows the Designer convention.
            // If so tell the UI compilers not to use setProperty().
            PyObject *setter_name_obj = PyObject_GetAttr(pp->pyqtprop_set,
                    qpycore_dunder_name);

            if (setter_name_obj)
            {
                PyObject *ascii_obj = setter_name_obj;
                const char *ascii = sipString_AsASCIIString(&ascii_obj);
                Py_DECREF(setter_name_obj);

                if (ascii)
                {
                    if (qstrlen(ascii) > 3 && ascii[0] == 's' &&
                            ascii[1] == 'e' && ascii[2] == 't' &&
                            ascii[3] == toupper(prop_name[0]) &&
                            qstrcmp(&ascii[4], &prop_name[1]) == 0)
                        prop_builder.setStdCppSet(true);
                }

                Py_DECREF(ascii_obj);
            }

            PyErr_Clear();
        }

        if (pp->pyqtprop_reset && PyCallable_Check(pp->pyqtprop_reset))
        {
            // Resetable.
            prop_builder.setResettable(true);
        }

        // Add the property flags.  Note that Qt4 always seems to have
        // ResolveEditable set but QMetaObjectBuilder doesn't provide an API
        // call to do it.
        prop_builder.setDesignable(pp->pyqtprop_flags & 0x00001000);
        prop_builder.setScriptable(pp->pyqtprop_flags & 0x00004000);
        prop_builder.setStored(pp->pyqtprop_flags & 0x00010000);
        prop_builder.setUser(pp->pyqtprop_flags & 0x00100000);
        prop_builder.setConstant(pp->pyqtprop_flags & 0x00000400);
        prop_builder.setFinal(pp->pyqtprop_flags & 0x00000800);

        prop_builder.setRevision(pp->pyqtprop_revision);

        // Save the property data for qt_metacall().  (We already have a
        // reference.)
        qo->pprops.append(pp);

        // We've finished with the property name.
        Py_DECREF(pprop.first);
    }

    // Initialise the rest of the meta-object.
    qo->mo = builder.toMetaObject();

    // Save the meta-object.
    pyqt_wt->metaobject = qo;

    return 0;
}
예제 #18
0
// Trawl a type's dict looking for any slots, signals or properties.
static int trawl_type(PyTypeObject *pytype, qpycore_metaobject *qo,
        QMetaObjectBuilder &builder, QList<const qpycore_pyqtSignal *> &psigs,
        QMap<uint, PropertyData> &pprops)
{
    SIP_SSIZE_T pos = 0;
    PyObject *key, *value;

    while (PyDict_Next(pytype->tp_dict, &pos, &key, &value))
    {
        // See if it is a slot, ie. it has been decorated with pyqtSlot().
        PyObject *sig_obj = PyObject_GetAttr(value,
                qpycore_dunder_pyqtsignature);

        if (sig_obj)
        {
            // Make sure it is a list and not some legitimate attribute that
            // happens to use our special name.
            if (PyList_Check(sig_obj))
            {
                for (SIP_SSIZE_T i = 0; i < PyList_GET_SIZE(sig_obj); ++i)
                {
                    // Set up the skeleton slot.
                    PyObject *decoration = PyList_GET_ITEM(sig_obj, i);
                    Chimera::Signature *slot_signature = Chimera::Signature::fromPyObject(decoration);

                    PyQtSlot *slot = new PyQtSlot(value, (PyObject *)pytype,
                            slot_signature);;

                    qo->pslots.append(slot);
                }
            }

            Py_DECREF(sig_obj);
        }
        else
        {
            PyErr_Clear();

            // Make sure the key is an ASCII string.  Delay the error checking
            // until we know we actually need it.
            const char *ascii_key = sipString_AsASCIIString(&key);

            // See if the value is of interest.
            if (PyObject_TypeCheck(value, &qpycore_pyqtProperty_Type))
            {
                // It is a property.

                if (!ascii_key)
                    return -1;

                Py_INCREF(value);

                qpycore_pyqtProperty *pp = (qpycore_pyqtProperty *)value;

                pprops.insert(pp->pyqtprop_sequence, PropertyData(key, value));

                // See if the property has a scope.  If so, collect all
                // QMetaObject pointers that are not in the super-class
                // hierarchy.
                const QMetaObject *mo = get_scope_qmetaobject(pp->pyqtprop_parsed_type);

                if (mo)
                    builder.addRelatedMetaObject(mo);
            }
            else if (PyObject_TypeCheck(value, &qpycore_pyqtSignal_Type))
            {
                // It is a signal.

                if (!ascii_key)
                    return -1;

                qpycore_pyqtSignal *ps = (qpycore_pyqtSignal *)value;

                // Make sure the signal has a name.
                qpycore_set_signal_name(ps, pytype->tp_name, ascii_key);

                // Add all the overloads.
                do
                {
                    psigs.append(ps);
                    ps = ps->next;
                }
                while (ps);

                Py_DECREF(key);
            }
            else
            {
                PyErr_Clear();
            }
        }
    }

    return 0;
}
예제 #19
0
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, 
                  const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
{
    // Set classname
    builder.setClassName(ignoreEnd->className());

    // Clone Q_CLASSINFO
    for (int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) {
        QMetaClassInfo info = mo->classInfo(ii);

        int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
        if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
            // Skip 
        } else {
            builder.addClassInfo(info.name(), info.value());
        }
    }

    // Clone Q_PROPERTY
    for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) {
        QMetaProperty property = mo->property(ii);

        int otherIndex = ignoreEnd->indexOfProperty(property.name());
        if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
            builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void"));
            // Skip 
        } else {
            builder.addProperty(property);
        }
    }

    // Clone Q_METHODS
    for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) {
        QMetaMethod method = mo->method(ii);

        // More complex - need to search name
        QByteArray name = method.name();


        bool found = false;

        for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount(); 
             !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
             ++ii) {

            QMetaMethod other = ignoreEnd->method(ii);

            found = name == other.name();
        }

        QMetaMethodBuilder m = builder.addMethod(method);
        if (found) // SKIP
            m.setAccess(QMetaMethod::Private);
    }

    // Clone Q_ENUMS
    for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
        QMetaEnum enumerator = mo->enumerator(ii);

        int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
        if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
            // Skip 
        } else {
            builder.addEnumerator(enumerator);
        }
    }
}
예제 #20
0
QMetaObject *metaObjectFor(GoTypeInfo *typeInfo)
{
    if (typeInfo->metaObject) {
            return reinterpret_cast<QMetaObject *>(typeInfo->metaObject);
    }

    QMetaObjectBuilder mob;
    if (typeInfo->paint) {
        mob.setSuperClass(&QQuickPaintedItem::staticMetaObject);
    } else {
        mob.setSuperClass(&QObject::staticMetaObject);
    }
    mob.setClassName(typeInfo->typeName);
    mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);

    GoMemberInfo *memberInfo;
    
    memberInfo = typeInfo->fields;
    int relativePropIndex = mob.propertyCount();
    for (int i = 0; i < typeInfo->fieldsLen; i++) {
        mob.addSignal("__" + QByteArray::number(relativePropIndex) + "()");
        const char *typeName = "QVariant";
        if (memberInfo->memberType == DTListProperty) {
            typeName = "QQmlListProperty<QObject>";
        }
        QMetaPropertyBuilder propb = mob.addProperty(memberInfo->memberName, typeName, relativePropIndex);
        propb.setWritable(true);
        memberInfo->metaIndex = relativePropIndex;
        memberInfo++;
        relativePropIndex++;
    }

    memberInfo = typeInfo->methods;
    int relativeMethodIndex = mob.methodCount();
    for (int i = 0; i < typeInfo->methodsLen; i++) {
        if (*memberInfo->resultSignature) {
            mob.addMethod(memberInfo->methodSignature, memberInfo->resultSignature);
        } else {
            mob.addMethod(memberInfo->methodSignature);
        }
        memberInfo->metaIndex = relativeMethodIndex;
        memberInfo++;
        relativeMethodIndex++;
    }

    // TODO Support default properties.
    //mob.addClassInfo("DefaultProperty", "objects");

    QMetaObject *mo = mob.toMetaObject();

    // Turn the relative indexes into absolute indexes.
    memberInfo = typeInfo->fields;
    int propOffset = mo->propertyOffset();
    for (int i = 0; i < typeInfo->fieldsLen; i++) {
        memberInfo->metaIndex += propOffset;
        memberInfo++;
    }
    memberInfo = typeInfo->methods;
    int methodOffset = mo->methodOffset();
    for (int i = 0; i < typeInfo->methodsLen; i++) {
        memberInfo->metaIndex += methodOffset;
        memberInfo++;
    }

    typeInfo->metaObject = mo;
    return mo;
}
예제 #21
0
void QQmlTypePrivate::init() const
{
    if (m_isSetup) return;

    QWriteLocker lock(metaTypeDataLock());
    if (m_isSetup)
        return;

    const QMetaObject *mo = m_baseMetaObject;
    if (!mo) {
        // singleton type without metaobject information
        return;
    }

    // Setup extended meta object
    // XXX - very inefficient
    if (m_extFunc) {
        QMetaObjectBuilder builder;
        clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject);
        builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
        QMetaObject *mmo = builder.toMetaObject();
        mmo->d.superdata = mo;
        QQmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
        m_metaObjects << data;
    }

    mo = mo->d.superdata;
    while(mo) {
        QQmlType *t = metaTypeData()->metaObjectToType.value(mo);
        if (t) {
            if (t->d->m_extFunc) {
                QMetaObjectBuilder builder;
                clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
                builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
                QMetaObject *mmo = builder.toMetaObject();
                mmo->d.superdata = m_baseMetaObject;
                if (!m_metaObjects.isEmpty())
                    m_metaObjects.last().metaObject->d.superdata = mmo;
                QQmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
                m_metaObjects << data;
            }
        }
        mo = mo->d.superdata;
    }

    for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
        m_metaObjects[ii].propertyOffset =
            m_metaObjects.at(ii).metaObject->propertyOffset();
        m_metaObjects[ii].methodOffset =
            m_metaObjects.at(ii).metaObject->methodOffset();
    }
    
    // Check for revisioned details
    {
        const QMetaObject *mo = 0;
        if (m_metaObjects.isEmpty())
            mo = m_baseMetaObject;
        else
            mo = m_metaObjects.first().metaObject;

        for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
            if (isPropertyRevisioned(mo, ii))
                m_containsRevisionedAttributes = true;
        }

        for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
            if (mo->method(ii).revision() != 0)
                m_containsRevisionedAttributes = true;
        }
    }

    m_isSetup = true;
    lock.unlock();
}
예제 #22
0
{
    d_ptr = new QSensorGesturePrivate();
    Q_FOREACH (const QString &id, ids) {
        QSensorGestureRecognizer * rec = QSensorGestureManager::sensorGestureRecognizer(id);
        if (rec != 0) {
            d_ptr->m_sensorRecognizers.append(rec);
            d_ptr->availableIds.append(id);
        } else {
            d_ptr->invalidIds.append(id);
            //add to not available things
        }
    }

    d_ptr->meta = 0;

    QMetaObjectBuilder builder;
    builder.setSuperClass(&QObject::staticMetaObject);
    builder.setClassName("QSensorGesture");

    Q_FOREACH (QSensorGestureRecognizer *recognizer,  d_ptr->m_sensorRecognizers) {
        Q_FOREACH (const QString &gesture, recognizer->gestureSignals()) {
            QMetaMethodBuilder b =  builder.addSignal(gesture.toLatin1());
            if (!d_ptr->localGestureSignals.contains(QLatin1String(b.signature())))
                d_ptr->localGestureSignals.append(QLatin1String(b.signature()));
        }
        recognizer->createBackend();
    }
    d_ptr->meta = builder.toMetaObject();

    if (d_ptr->m_sensorRecognizers.count() > 0) {
        d_ptr->valid = true;
예제 #23
0
// Initialisation common to all ctors.
void PyQtProxy::init(QObject *qtx, PyQtProxy::ProxyHash *hash, void *key)
{
    // Create a new meta-object on the heap so that it looks like it has a
    // signal of the right name and signature.
#if QT_VERSION >= 0x050000
    QMetaObjectBuilder builder;

    builder.setClassName("PyQtProxy");
    builder.setSuperClass(&QObject::staticMetaObject);

    // Note that signals must be added before slots.
    if (type == ProxySignal)
        builder.addSignal(signature);
    else
        builder.addSlot("unislot()");

    builder.addSlot("disable()");

    meta_object = builder.toMetaObject();
#else
    if (type == ProxySignal)
    {
        QMetaObject *mo = new QMetaObject;
        mo->d.superdata = &QObject::staticMetaObject;
        mo->d.extradata = 0;

        // Calculate the size of the string meta-data as follows:
        // - "PyQtProxy" and its terminating '\0' (ie. 9 + 1 bytes),
        // - a '\0' used for any empty string,
        // - "disable()" and its terminating '\0' (ie. 9 + 1 bytes),
        // - the (non-existent) argument names (ie. use the empty string if
        //   there is less that two arguments, otherwise a comma between each
        //   argument and the terminating '\0'),
        // - the name and full signature, less the initial type character, plus
        //   the terminating '\0'.

        const size_t fixed_len = 9 + 1 + 1 + 9 + 1;
        const size_t empty_str = 9 + 1;

        int nr_commas = signature.count(',');

        size_t len = fixed_len
                    + (nr_commas >= 0 ? nr_commas + 1 : 0)
                    + signature.size() + 1;

        char *smd = new char[len];

        memcpy(smd, slot_meta_stringdata, fixed_len);

        uint i = fixed_len, args_pos;

        if (nr_commas > 0)
        {
            args_pos = i;

            for (int c = 0; c < nr_commas; ++c)
                smd[i++] = ',';

            smd[i++] = '\0';
        }
        else
        {
            args_pos = empty_str;
        }

        uint sig_pos = i;
        qstrcpy(&smd[i], signature.constData());

        mo->d.stringdata = smd;

        // Add the non-string data.
        uint *data = new uint[21];

        memcpy(data, slot_meta_data, 21 * sizeof (uint));

        // Replace the first method (ie. unislot()) with the new signal.
        data[10] = sig_pos;
        data[11] = args_pos;
        data[14] = 0x05;

        mo->d.data = data;

        meta_object = mo;
    }
    else
    {
        meta_object = &staticMetaObject;
    }
#endif

    hashed = true;
    saved_key = key;
    transmitter = qtx;

    // Add this one to the global hashes.
    mutex->lock();
    hash->insert(key, this);
    mutex->unlock();

    // Detect when the transmitter is destroyed.  (Note that we used to do this
    // by making the proxy a child of the transmitter.  This doesn't work as
    // expected because QWidget destroys its children before emitting the
    // destroyed signal.)  We use a queued connection in case the proxy is also
    // connected to the same signal and we want to make sure it has a chance
    // to invoke the slot before being destroyed.
    if (qtx)
        connect(qtx, SIGNAL(destroyed(QObject *)), SLOT(disable()),
                Qt::QueuedConnection);
}