static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
{
    QString retval;

    // start with properties:
    if (flags & (QDBusConnection::ExportScriptableProperties |
                 QDBusConnection::ExportNonScriptableProperties)) {
        for (int i = propOffset; i < mo->propertyCount(); ++i) {
            static const char *accessvalues[] = {0, "read", "write", "readwrite"};

            QMetaProperty mp = mo->property(i);

            if (!((mp.isScriptable() && (flags & QDBusConnection::ExportScriptableProperties)) ||
                  (!mp.isScriptable() && (flags & QDBusConnection::ExportNonScriptableProperties))))
                continue;

            int access = 0;
            if (mp.isReadable())
                access |= 1;
            if (mp.isWritable())
                access |= 2;

            int typeId = qDBusNameToTypeId(mp.typeName());
            if (!typeId)
                continue;
            const char *signature = QDBusMetaType::typeToSignature(typeId);
            if (!signature)
                continue;

            retval += QString::fromLatin1("    <property name=\"%1\" type=\"%2\" access=\"%3\"")
                      .arg(QLatin1String(mp.name()))
                      .arg(QLatin1String(signature))
                      .arg(QLatin1String(accessvalues[access]));

            if (QDBusMetaType::signatureToType(signature) == QVariant::Invalid) {
                const char *typeName = QVariant::typeToName(QVariant::Type(typeId));
                retval += QString::fromLatin1(">\n      <annotation name=\"com.trolltech.QtDBus.QtTypeName\" value=\"%3\"/>\n    </property>\n")
                          .arg(typeNameToXml(typeName));
            } else {
                retval += QLatin1String("/>\n");
            }
        }
    }

    // now add methods:
    for (int i = methodOffset; i < mo->methodCount(); ++i) {
        QMetaMethod mm = mo->method(i);
        QByteArray signature = mm.signature();
        int paren = signature.indexOf('(');

        bool isSignal;
        if (mm.methodType() == QMetaMethod::Signal)
            // adding a signal
            isSignal = true;
        else if (mm.methodType() == QMetaMethod::Slot && mm.access() == QMetaMethod::Public)
            isSignal = false;
        else
            continue;           // neither signal nor public slot

        if (isSignal && !(flags & (QDBusConnection::ExportScriptableSignals |
                                   QDBusConnection::ExportNonScriptableSignals)))
            continue;           // we're not exporting any signals
        if (!isSignal && !(flags & (QDBusConnection::ExportScriptableSlots |
                                    QDBusConnection::ExportNonScriptableSlots)))
            continue;           // we're not exporting any slots

        QString xml = QString::fromLatin1("    <%1 name=\"%2\">\n")
                      .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"))
                      .arg(QLatin1String(signature.left(paren)));

        // check the return type first
        int typeId = qDBusNameToTypeId(mm.typeName());
        if (typeId) {
            const char *typeName = QDBusMetaType::typeToSignature(typeId);
            if (typeName) {
                xml += QString::fromLatin1("      <arg type=\"%1\" direction=\"out\"/>\n")
                       .arg(typeNameToXml(typeName));

                // do we need to describe this argument?
                if (QDBusMetaType::signatureToType(typeName) == QVariant::Invalid)
                    xml += QString::fromLatin1("      <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n")
                           .arg(typeNameToXml(mm.typeName()));
            } else
                continue;
        }
        else if (*mm.typeName())
            continue;           // wasn't a valid type

        QList<QByteArray> names = mm.parameterNames();
        QList<int> types;
        int inputCount = qDBusParametersForMethod(mm, types);
        if (inputCount == -1)
            continue;           // invalid form
        if (isSignal && inputCount + 1 != types.count())
            continue;           // signal with output arguments?
        if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message)
            continue;           // signal with QDBusMessage argument?
        if (isSignal && mm.attributes() & QMetaMethod::Cloned)
            continue;           // cloned signal?

        int j;
        bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
        for (j = 1; j < types.count(); ++j) {
            // input parameter for a slot or output for a signal
            if (types.at(j) == QDBusMetaTypeId::message) {
                isScriptable = true;
                continue;
            }

            QString name;
            if (!names.at(j - 1).isEmpty())
                name = QString::fromLatin1("name=\"%1\" ").arg(QLatin1String(names.at(j - 1)));

            bool isOutput = isSignal || j > inputCount;

            const char *signature = QDBusMetaType::typeToSignature(types.at(j));
            xml += QString::fromLatin1("      <arg %1type=\"%2\" direction=\"%3\"/>\n")
                   .arg(name)
                   .arg(QLatin1String(signature))
                   .arg(isOutput ? QLatin1String("out") : QLatin1String("in"));

            // do we need to describe this argument?
            if (QDBusMetaType::signatureToType(signature) == QVariant::Invalid) {
                const char *typeName = QVariant::typeToName( QVariant::Type(types.at(j)) );
                xml += QString::fromLatin1("      <annotation name=\"com.trolltech.QtDBus.QtTypeName.%1%2\" value=\"%3\"/>\n")
                       .arg(isOutput ? QLatin1String("Out") : QLatin1String("In"))
                       .arg(isOutput ? j - 1 : j - inputCount)
                       .arg(typeNameToXml(typeName));
            }
        }

        int wantedMask;
        if (isScriptable)
            wantedMask = isSignal ? QDBusConnection::ExportScriptableSignals
                                  : QDBusConnection::ExportScriptableSlots;
        else
            wantedMask = isSignal ? QDBusConnection::ExportNonScriptableSignals
                                  : QDBusConnection::ExportNonScriptableSlots;
        if ((flags & wantedMask) != wantedMask)
            continue;

        if (qDBusCheckAsyncTag(mm.tag()))
            // add the no-reply annotation
            xml += QLatin1String("      <annotation name=\"" ANNOTATION_NO_WAIT "\""
                                 " value=\"true\"/>\n");

        retval += xml;
        retval += QString::fromLatin1("    </%1>\n")
                  .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
    }

    return retval;
}
Exemple #2
0
QString qax_generateDocumentation(QAxBase *that)
{
    that->metaObject();

    if (that->isNull())
	return QString();

    ITypeInfo *typeInfo = 0;
    IDispatch *dispatch = 0;
    that->queryInterface(IID_IDispatch, (void**)&dispatch);
    if (dispatch)
	dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);

    QString docu;
    QTextStream stream(&docu, QIODevice::WriteOnly);

    const QMetaObject *mo = that->metaObject();
    QString coClass  = QLatin1String(mo->classInfo(mo->indexOfClassInfo("CoClass")).value());

    stream << "<h1 align=center>" << coClass << " Reference</h1>" << endl;
    stream << "<p>The " << coClass << " COM object is a " << that->qObject()->metaObject()->className();
    stream << " with the CLSID " <<  that->control() << ".</p>" << endl;

    stream << "<h3>Interfaces</h3>" << endl;
    stream << "<ul>" << endl;
    const char *inter = 0;
    int interCount = 1;
    while ((inter = mo->classInfo(mo->indexOfClassInfo("Interface " + QByteArray::number(interCount))).value())) {
	stream << "<li>" << inter << endl;
	interCount++;
    }
    stream << "</ul>" << endl;

    stream << "<h3>Event Interfaces</h3>" << endl;
    stream << "<ul>" << endl;
    interCount = 1;  
    while ((inter = mo->classInfo(mo->indexOfClassInfo("Event Interface " + QByteArray::number(interCount))).value())) {
	stream << "<li>" << inter << endl;
	interCount++;
    }
    stream << "</ul>" << endl;

    QList<QString> methodDetails, propDetails;

    const int slotCount = mo->methodCount();
    if (slotCount) {
	stream << "<h2>Public Slots:</h2>" << endl;
	stream << "<ul>" << endl;

        int defArgCount = 0;
	for (int islot = mo->methodOffset(); islot < slotCount; ++islot) {
	    const QMetaMethod slot = mo->method(islot);
            if (slot.methodType() != QMetaMethod::Slot)
                continue;

            if (slot.attributes() & QMetaMethod::Cloned) {
                ++defArgCount;
                continue;
            }

	    QByteArray returntype(slot.typeName());
            if (returntype.isEmpty())
                returntype = "void";
            QByteArray prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames(), defArgCount);
            QByteArray signature = slot.methodSignature();
	    QByteArray name = signature.left(signature.indexOf('('));
	    stream << "<li>" << returntype << " <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl;
            
            prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames());
	    QString detail = QString::fromLatin1("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
                             QLatin1String(returntype.constData()) + QLatin1Char(' ') +
                             QLatin1String(name.constData()) + QLatin1Char(' ') +
                             QString::fromLatin1(prototype.constData()) + QLatin1String("<tt> [slot]</tt></h3>\n");
            prototype = namedPrototype(slot.parameterTypes(), QList<QByteArray>());
	    detail += docuFromName(typeInfo, QString::fromLatin1(name.constData()));
	    detail += QLatin1String("<p>Connect a signal to this slot:<pre>\n");
	    detail += QString::fromLatin1("\tQObject::connect(sender, SIGNAL(someSignal") + QString::fromLatin1(prototype.constData()) +
                      QLatin1String("), object, SLOT(") + QString::fromLatin1(name.constData()) +
                      QString::fromLatin1(prototype.constData()) + QLatin1String("));");
	    detail += QLatin1String("</pre>\n");

            if (1) {
                detail += QLatin1String("<p>Or call the function directly:<pre>\n");

                bool hasParams = slot.parameterTypes().count() != 0;
                if (hasParams)
                    detail += QLatin1String("\tQVariantList params = ...\n");
                detail += QLatin1String("\t");
                QByteArray functionToCall = "dynamicCall";
                if (returntype == "IDispatch*" || returntype == "IUnknown*") {
                    functionToCall = "querySubObject";
                    returntype = "QAxObject *";
                }
                if (returntype != "void")
                    detail += QLatin1String(returntype.constData()) + QLatin1String(" result = ");
                detail += QLatin1String("object->") + QLatin1String(functionToCall.constData()) +
                          QLatin1String("(\"" + name + prototype + '\"');
                if (hasParams)
                    detail += QLatin1String(", params");
                detail += QLatin1Char(')');
                if (returntype != "void" && returntype != "QAxObject *" && returntype != "QVariant")
                    detail += QLatin1Char('.') + QLatin1String(toType(returntype));
	        detail += QLatin1String(";</pre>\n");
	    } else {
		detail += QLatin1String("<p>This function has parameters of unsupported types and cannot be called directly.");
	    }

	    methodDetails << detail;
            defArgCount = 0;
	}

	stream << "</ul>" << endl;
    }
    int signalCount = mo->methodCount();
    if (signalCount) {
        ITypeLib *typeLib = 0;
        if (typeInfo) {
            UINT index = 0;
            typeInfo->GetContainingTypeLib(&typeLib, &index);
            typeInfo->Release();
        }
        typeInfo = 0;

	stream << "<h2>Signals:</h2>" << endl;
	stream << "<ul>" << endl;

	for (int isignal = mo->methodOffset(); isignal < signalCount; ++isignal) {
	    const QMetaMethod signal(mo->method(isignal));
            if (signal.methodType() != QMetaMethod::Signal)
                continue;

            QByteArray prototype = namedPrototype(signal.parameterTypes(), signal.parameterNames());
            QByteArray signature = signal.methodSignature();
	    QByteArray name = signature.left(signature.indexOf('('));
	    stream << "<li>void <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl;

            QString detail = QLatin1String("<h3><a name=") + QLatin1String(name.constData()) + QLatin1String("></a>void ") +
                             QLatin1String(name.constData()) + QLatin1Char(' ') +
                             QLatin1String(prototype.constData()) + QLatin1String("<tt> [signal]</tt></h3>\n");
            if (typeLib) {
                interCount = 0;
                do {
                    if (typeInfo)
                        typeInfo->Release();
                    typeInfo = 0;
                    typeLib->GetTypeInfo(++interCount, &typeInfo);
                    QString typeLibDocu = docuFromName(typeInfo, QString::fromLatin1(name.constData()));
                    if (!typeLibDocu.isEmpty()) {
                        detail += typeLibDocu;
                        break;
                    }
                } while (typeInfo);
            }
            prototype = namedPrototype(signal.parameterTypes(), QList<QByteArray>());
	    detail += QLatin1String("<p>Connect a slot to this signal:<pre>\n");
	    detail += QLatin1String("\tQObject::connect(object, SIGNAL(") + QString::fromLatin1(name.constData()) +
                      QString::fromLatin1(prototype.constData()) +
                      QLatin1String("), receiver, SLOT(someSlot") + QString::fromLatin1(prototype.constData()) + QLatin1String("));");
	    detail += QLatin1String("</pre>\n");

	    methodDetails << detail;
            if (typeInfo)
                typeInfo->Release();
            typeInfo = 0;
	}
	stream << "</ul>" << endl;

        if (typeLib)
            typeLib->Release();
    }

    const int propCount = mo->propertyCount();
    if (propCount) {
        if (dispatch)
	    dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);
	stream << "<h2>Properties:</h2>" << endl;
	stream << "<ul>" << endl;

	for (int iprop = 0; iprop < propCount; ++iprop) {
	    const QMetaProperty prop = mo->property(iprop);
	    QByteArray name(prop.name());
	    QByteArray type(prop.typeName());

	    stream << "<li>" << type << " <a href=\"#" << name << "\"><b>" << name << "</b></a>;</li>" << endl;
	    QString detail = QLatin1String("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
                             QLatin1String(type.constData()) +
		             QLatin1Char(' ') + QLatin1String(name.constData()) + QLatin1String("</h3>\n");
	    detail += docuFromName(typeInfo, QString::fromLatin1(name));
	    QVariant::Type vartype = QVariant::nameToType(type);
	    if (!prop.isReadable())
		continue;

	    if (prop.isEnumType())
		vartype = QVariant::Int;

            if (vartype != QVariant::Invalid) {
		detail += QLatin1String("<p>Read this property's value using QObject::property:<pre>\n");
                if (prop.isEnumType())
		    detail += QLatin1String("\tint val = ");
                else
                    detail += QLatin1Char('\t') + QLatin1String(type.constData()) + QLatin1String(" val = ");
		detail += QLatin1String("object->property(\"") + QLatin1String(name.constData()) +
                          QLatin1String("\").") + QLatin1String(toType(type).constData()) + QLatin1String(";\n");
		detail += QLatin1String("</pre>\n");
	    } else if (type == "IDispatch*" || type == "IUnknown*") {
		detail += QLatin1String("<p>Get the subobject using querySubObject:<pre>\n");
		detail += QLatin1String("\tQAxObject *") + QLatin1String(name.constData()) +
                          QLatin1String(" = object->querySubObject(\"") + QLatin1String(name.constData()) + QLatin1String("\");\n");
		detail += QLatin1String("</pre>\n");
	    } else {
		detail += QLatin1String("<p>This property is of an unsupported type.\n");
	    }
	    if (prop.isWritable()) {
		detail += QLatin1String("Set this property' value using QObject::setProperty:<pre>\n");
                if (prop.isEnumType()) {
                    detail += QLatin1String("\tint newValue = ... // string representation of values also supported\n");
                } else {
		    detail += QLatin1String("\t") + QString::fromLatin1(type.constData()) + QLatin1String(" newValue = ...\n");
                }
		detail += QLatin1String("\tobject->setProperty(\"") + QString::fromLatin1(name) + QLatin1String("\", newValue);\n");
		detail += QLatin1String("</pre>\n");
		detail += QLatin1String("Or using the ");
		QByteArray setterSlot;
                if (isupper(name.at(0))) {
		    setterSlot = "Set" + name;
		} else {
		    QByteArray nameUp = name;
		    nameUp[0] = toupper(nameUp.at(0));
		    setterSlot = "set" + nameUp;
		}
		detail += QLatin1String("<a href=\"#") + QString::fromLatin1(setterSlot) + QLatin1String("\">") +
                          QString::fromLatin1(setterSlot.constData()) + QLatin1String("</a> slot.\n");
	    }
	    if (prop.isEnumType()) {
		detail += QLatin1String("<p>See also <a href=\"#") + QString::fromLatin1(type) +
                QLatin1String("\">") + QString::fromLatin1(type) + QLatin1String("</a>.\n");
	    }

	    propDetails << detail;
	}
	stream << "</ul>" << endl;
    }

    const int enumCount = mo->enumeratorCount();
    if (enumCount) {
	stream << "<hr><h2>Member Type Documentation</h2>" << endl;
	for (int i = 0; i < enumCount; ++i) {
	    const QMetaEnum enumdata = mo->enumerator(i);
	    stream << "<h3><a name=" << enumdata.name() << "></a>" << enumdata.name() << "</h3>" << endl;
	    stream << "<ul>" << endl;
	    for (int e = 0; e < enumdata.keyCount(); ++e) {
		stream << "<li>" << enumdata.key(e) << "\t=" << enumdata.value(e) << "</li>" << endl;
	    }
	    stream << "</ul>" << endl;
	}
    }
    if (methodDetails.count()) {
	stream << "<hr><h2>Member Function Documentation</h2>" << endl;
	for (int i = 0; i < methodDetails.count(); ++i)
	    stream << methodDetails.at(i) << endl;
    }
    if (propDetails.count()) {
	stream << "<hr><h2>Property Documentation</h2>" << endl;
	for (int i = 0; i < propDetails.count(); ++i)
	    stream << propDetails.at(i) << endl;
    }

    if (typeInfo)
        typeInfo->Release();
    if (dispatch)
        dispatch->Release();
    return docu;
}
Exemple #3
0
static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out)
{
    int id = 1;
    int i = 0;
    if (!mo)
        return 3;

    QString topclass = qAxFactory()->exposeToSuperClass(className);
    if (topclass.isEmpty())
        topclass = QLatin1String("QObject");
    bool hasStockEvents = qAxFactory()->hasStockEvents(className);

    const QMetaObject *pmo = mo;
    do {
        pmo = pmo->superClass();
    } while (pmo && topclass != QString::fromLatin1(pmo->className()));

    int enumoff = pmo ? pmo->enumeratorOffset() : mo->enumeratorOffset();
    int methodoff = pmo ? pmo->methodOffset() : mo->methodOffset();
    int propoff = pmo ? pmo->propertyOffset() : mo->propertyOffset();

    int qtProps = 0;
    int qtSlots = 0;

    bool control = false;

    if (o && o->isWidgetType()) {
        qtProps = QWidget::staticMetaObject.propertyCount();
        qtSlots = QWidget::staticMetaObject.methodCount();
        control = true;
    }

    const QString classID = stripCurlyBraces(qAxFactory()->classID(className));
    if (classID.isEmpty())
        return 4;
    const QString interfaceID = stripCurlyBraces(qAxFactory()->interfaceID(className));
    if (interfaceID.isEmpty())
        return 5;
    const QString eventsID = stripCurlyBraces(qAxFactory()->eventsID(className));
    const bool hasEvents = !eventsID.isEmpty();

    QString cleanClassName = qax_clean_type(className, mo);
    QString defProp(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultProperty")).value()));
    QString defSignal(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultSignal")).value()));

    for (i = enumoff; i < mo->enumeratorCount(); ++i) {
        const QMetaEnum enumerator = mo->enumerator(i);
        if (enums.contains(enumerator.name()))
            continue;

        enums.append(enumerator.name());

        out << "\tenum " << enumerator.name() << " {" << endl;

        for (int j = 0; j < enumerator.keyCount(); ++j) {
            QByteArray key(enumerator.key(j));
            while (enumValues.contains(key)) {
                key += '_';
            }
            enumValues.append(key);
            const uint value = uint(enumerator.value(j));
            key = key.leftJustified(20);
            out << "\t\t" << key << "\t= ";
            if (enumerator.isFlag())
                out << "0x" << QByteArray::number(value, 16).rightJustified(8, '0');
            else
                out << value;
            if (j < enumerator.keyCount()-1)
                out << ", ";
            out << endl;
        }
        out << "\t};" << endl << endl;
    }

    // mouse cursor enum for QCursor support
    if (!enums.contains("MousePointer")) {
        enums.append("MousePointer");
        out << "\tenum MousePointer {" << endl;
        out << "\t\tArrowCursor             = " << Qt::ArrowCursor << ',' << endl;
        out << "\t\tUpArrowCursor           = " << Qt::UpArrowCursor << ',' << endl;
        out << "\t\tCrossCursor             = " << Qt::CrossCursor << ',' << endl;
        out << "\t\tWaitCursor              = " << Qt::WaitCursor << ',' << endl;
        out << "\t\tIBeamCursor             = " << Qt::IBeamCursor << ',' << endl;
        out << "\t\tSizeVerCursor           = " << Qt::SizeVerCursor << ',' << endl;
        out << "\t\tSizeHorCursor           = " << Qt::SizeHorCursor << ',' << endl;
        out << "\t\tSizeBDiagCursor         = " << Qt::SizeBDiagCursor << ',' << endl;
        out << "\t\tSizeFDiagCursor         = " << Qt::SizeFDiagCursor << ',' << endl;
        out << "\t\tSizeAllCursor           = " << Qt::SizeAllCursor << ',' << endl;
        out << "\t\tBlankCursor             = " << Qt::BlankCursor << ',' << endl;
        out << "\t\tSplitVCursor            = " << Qt::SplitVCursor << ',' << endl;
        out << "\t\tSplitHCursor            = " << Qt::SplitHCursor << ',' << endl;
        out << "\t\tPointingHandCursor      = " << Qt::PointingHandCursor << ',' << endl;
        out << "\t\tForbiddenCursor         = " << Qt::ForbiddenCursor << ',' << endl;
        out << "\t\tWhatsThisCursor         = " << Qt::WhatsThisCursor << ',' << endl;
        out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl;
        out << "\t};" << endl << endl;
    }
    if (!enums.contains("FocusPolicy")) {
        enums.append("FocusPolicy");
        out << "\tenum FocusPolicy {" << endl;
        out << "\t\tNoFocus             = " << Qt::NoFocus << ',' << endl;
        out << "\t\tTabFocus            = " << Qt::TabFocus << ',' << endl;
        out << "\t\tClickFocus          = " << Qt::ClickFocus << ',' << endl;
        out << "\t\tStrongFocus         = " << Qt::StrongFocus << ',' << endl;
        out << "\t\tWheelFocus          = " << Qt::WheelFocus << endl;
        out << "\t};" << endl << endl;
    }

    out << endl;
    out << "\t[" << endl;
    out << "\t\tuuid(" << interfaceID << ")," << endl;
    out << "\t\thelpstring(\"" << cleanClassName << " Interface\")" << endl;
    out << "\t]" << endl;
    out << "\tdispinterface I" << cleanClassName  << endl;
    out << "\t{" << endl;

    out << "\tproperties:" << endl;
    for (i = propoff; i < mo->propertyCount(); ++i) {
        const QMetaProperty property = mo->property(i);
        /* if (property.testFlags(QMetaProperty::Override))
            continue;*/
        if (i <= qtProps && ignoreProps(property.name()))
            continue;
        if (!property.name() || mo->indexOfProperty(property.name()) > i)
            continue;

        bool ok = true;
        QByteArray type(convertTypes(property.typeName(), &ok));
        QByteArray name(replaceKeyword(property.name()));

        if (!ok)
            out << "\t/****** Property is of unsupported datatype" << endl;

        out << "\t\t[id(" << id << ')';
        if (!property.isWritable())
            out << ", readonly";
        if (isBindable && property.isScriptable(o))
            out << ", bindable";
        if (!property.isDesignable(o))
            out << ", nonbrowsable";
        if (isBindable)
            out << ", requestedit";
        if (defProp == QLatin1String(name))
            out << ", uidefault";
        out << "] " << type << ' ' << name << ';' << endl;

        if (!ok)
            out << "\t******/" << endl;
        ++id;
    }
    out << endl;
    out << "\tmethods:" << endl;
    int numDefArgs = 0;
    QByteArray outBuffer;
    for (i = methodoff; i < mo->methodCount(); ++i) {
        const QMetaMethod slot = mo->method(i);
        if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal)
            continue;

        if (slot.attributes() & QMetaMethod::Cloned) {
            ++numDefArgs;
            continue;
        }
        if (!outBuffer.isEmpty()) {
            outBuffer = addDefaultArguments(outBuffer, numDefArgs);
            numDefArgs = 0;
            out << outBuffer;
            outBuffer = QByteArray();
        }

        QByteArray signature(slot.methodSignature());
        QByteArray name(signature.left(signature.indexOf('(')));
        if (i <= qtSlots && ignoreSlots(name))
            continue;

        signature.remove(0, name.length() + 1);
        signature.truncate(signature.length() - 1);
        name = renameOverloads(replaceKeyword(name));
        if (ignoreSlots(name))
            continue;

        QList<QByteArray> parameterTypes(slot.parameterTypes());
        QList<QByteArray> parameterNames(slot.parameterNames());

        bool ok = true;
        QByteArray type = slot.typeName();
        if (type.isEmpty())
            type = "void";
        else
            type = convertTypes(type, &ok);

        QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
        if (!ok)
            outBuffer += "\t/****** Slot parameter uses unsupported datatype\n";

        outBuffer += "\t\t[id(" + QByteArray::number(id) + ")] " + type + ' '
            + name + '(' + ptype + ");\n";

        if (!ok)
            outBuffer += "\t******/\n";
        ++id;
    }
    if (!outBuffer.isEmpty()) {
        outBuffer = addDefaultArguments(outBuffer, numDefArgs);
        numDefArgs = 0;
        out << outBuffer;
        outBuffer = QByteArray();
    }
    out << "\t};" << endl << endl;

    mapping.clear();
    id = 1;

    if (hasEvents) {
        out << "\t[" << endl;
        out << "\t\tuuid(" << eventsID << ")," << endl;
        out << "\t\thelpstring(\"" << cleanClassName << " Events Interface\")" << endl;
        out << "\t]" << endl;
        out << "\tdispinterface I" << cleanClassName << "Events" << endl;
        out << "\t{" << endl;
        out << "\tproperties:" << endl;
        out << "\tmethods:" << endl;

        if (hasStockEvents) {
            out << "\t/****** Stock events ******/" << endl;
            out << "\t\t[id(DISPID_CLICK)] void Click();" << endl;
            out << "\t\t[id(DISPID_DBLCLICK)] void DblClick();" << endl;
            out << "\t\t[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);" << endl;
            out << "\t\t[id(DISPID_KEYPRESS)] void KeyPress(short* KeyAscii);" << endl;
            out << "\t\t[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);" << endl;
            out << "\t\t[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
            out << "\t\t[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
            out << "\t\t[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl << endl;
        }

        for (i = methodoff; i < mo->methodCount(); ++i) {
            const QMetaMethod signal = mo->method(i);
            if (signal.methodType() != QMetaMethod::Signal)
                continue;

            QByteArray signature(signal.methodSignature());
            QByteArray name(signature.left(signature.indexOf('(')));
            signature.remove(0, name.length() + 1);
            signature.truncate(signature.length() - 1);

            QList<QByteArray> parameterTypes(signal.parameterTypes());
            QList<QByteArray> parameterNames(signal.parameterNames());

            bool isDefault = defSignal == QLatin1String(name);
            name = renameOverloads(replaceKeyword(name));
            bool ok = true;

            QByteArray type = signal.typeName();
            if (!type.isEmpty() && type != "void") // signals with return value not supported
                continue;

            QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
            if (!ok)
                out << "\t/****** Signal parameter uses unsupported datatype" << endl;

            out << "\t\t[id(" << id << ')';
            if (isDefault)
                out << ", uidefault";
            out << "] void " << name << '(' << ptype << ");" << endl;

            if (!ok)
                out << "\t******/" << endl;
            ++id;
        }
        out << "\t};" << endl << endl;
    }

    out << "\t[" << endl;

    if (qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no"))
        out << "\t\taggregatable," << endl;
    if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes"))
        out << "\t\tappobject," << endl;
    if (mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value())
        out << "\t\tlicensed," << endl;
    const char *helpString = mo->classInfo(mo->indexOfClassInfo("Description")).value();
    if (helpString)
        out << "\t\thelpstring(\"" << helpString << "\")," << endl;
    else
        out << "\t\thelpstring(\"" << cleanClassName << " Class\")," << endl;
    const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value();
    if (classVersion)
        out << "\t\tversion(" << classVersion << ")," << endl;
    out << "\t\tuuid(" << classID << ')';
    if (control) {
        out << ", " << endl;
        out << "\t\tcontrol";
    } else if (!o) {
        out << ", " << endl;
        out << "\t\tnoncreatable";
    }
    out << endl;
    out << "\t]" << endl;
    out << "\tcoclass " << cleanClassName << endl;
    out << "\t{" << endl;
    out << "\t\t[default] dispinterface I" << cleanClassName << ';' << endl;
    if (hasEvents)
        out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl;
    out << "\t};" << endl;

    return S_OK;
}
Exemple #4
0
/*!
	Initialized the ProxyBase Object. This needs to be run before any other functions are called.

	See the class description for an example of how to use this function

	@param funclist A list of strings to be used when searching for functions calls
	@param callbacklist A list of strings to used when searching for callbacks
	@param eventlist A list of strings to used when searching for events
 */
void ProxyBase::init(QStringList functionlist, QStringList callbacklist, QStringList eventlist)
{
	QMutexLocker locker(&qxt_d().mutex);
	//Initialize method counters
	int numfunctions = 1000;

	//clear old lists in case init() is run twice
	qxt_d().signalHash.clear();
	qxt_d().functions.clear();
	qxt_d().callbacks.clear();
	qxt_d().asyncfunctions.clear();

	//Get the meta object so we can see signals and slots
	const QMetaObject *meta = metaObject();
	//Get the number of methods
	int methods = meta->methodCount();

	//loop through all the methods
	for (int i = 0; i < methods; i++)
	{
		QMetaMethod method = meta->method(i);
		QString type = method.typeName();
		Signature sig(method.signature());

		// This checks to see if it's a cloned signal, and continues if it is...
		// Undocumented private API ftl!!!
		if (method.attributes() && 2)
			continue;

		switch (method.methodType())
		{
			case QMetaMethod::Signal:
				if (functionlist.contains(type))
				{
					//If a function begins with QObject*, char*, then its an asyn function
					if (sig.numArgs() >= 2 && sig.arg(0) == "QObject*" && (sig.arg(1) == "const char*" || sig.arg(1) == "char*"))
					{
						qxt_d().asyncfunctions << numfunctions; //add this function id to the list of async functions

						QVector<QString> args = sig.args(); //get the list of arguments
						//remove the first two arguments
						args.erase(args.begin());
						args.erase(args.begin());
						sig.setArgs(args); //update the argument list with the new list
					}
					Q_ASSERT(sig.validate());
					//connect the signal to a local event
					meta->connect(this, i, this, numfunctions, Qt::DirectConnection);
					qxt_d().functions[numfunctions] = sig;
					qxt_d().functiontypes[numfunctions] = method.typeName();
					numfunctions++;
				}
				else if (eventlist.contains(type))
				{
					Q_ASSERT(sig.validate());
					qxt_d().signalHash[i] = sig;
				}
				//if its not one of the two, we don't care about it
				break;

			case QMetaMethod::Slot:
				if (callbacklist.contains(type))
				{
					Q_ASSERT(sig.validate());
					qxt_d().callbacks[i] = sig;
				}
				break;

			default:
				//We don't really care about other types of methods
				break;
		}
	}
}
Exemple #5
0
bool QObject::connect(const QObject *sender, const QMetaMethod &signalMetaMethod, const QObject *receiver, 
            const QMetaMethod &slotMetaMethod, Qt::ConnectionType type)
{
   if (sender == 0) {
       qWarning("QObject::connect() Can not connect as sender is null");
       return false;
   }

   if (receiver == 0) {
       qWarning("QObject::connect() Can not connect as receiver is null");
       return false;
   }
   // get signal name
   const char *senderClass   = sender->metaObject()->className();
   const char *receiverClass = receiver->metaObject()->className();

   const char *signalName = signalMetaMethod.signature();
   const char *slotName   = slotMetaMethod.signature();

   if (! signalName || signalName[0] == 0)  {
      qWarning("%s%s%s%s%s", "QObject::connect() ", senderClass, "::<Invalid Signal> ",
               " Unable to connect to receiver in ", receiverClass);

      return false;
   }

   if (! slotName || slotName[0] == 0 )  {
      qWarning("%s%s%s%s%s%s%s", "QObject::connect() ", senderClass, "::", signalName,
                        " Unable to connect to receiver in ", receiverClass, "::<Invalid Slot>");
      return false;
   }

   // is signalMethod a signal
   if (signalMetaMethod.methodType() != QMetaMethod::Signal) {
      qWarning("%s%s%s%s%s", "QObject::connect() ", senderClass, "::", signalName,
                        ": Is not a valid signal");
      return false;
   }

   // is slotMethod a clone, then there is a defualt parameter
   if (slotMetaMethod.attributes() & QMetaMethod::Cloned) {
      qWarning("%s%s%s%s%s", "QObject::connect() ", receiverClass, "::", slotName,
                        ": Unable to connect to a slot with a default parameter");
      return false;
   }

   // test arguments
   bool err = false;
   QList<QByteArray> typesSignal = signalMetaMethod.parameterTypes();
   QList<QByteArray> typesSlot   = slotMetaMethod.parameterTypes();

   if (typesSignal.count() < typesSlot.count() )  {
      err = true;

   } else {

      for(int index = 0; index != typesSlot.count(); ++index)   {

         if (typesSignal.at(index) != typesSlot.at(index)) {
            // unable to test if typeDefs are used
            err = true;
            break;
         }

      }
   }

   if (err) {
      qWarning("%s%s%s%s%s%s%s%s", "QObject::connect() ", senderClass, "::", signalName,
                        ": Incompatible signal/slot arguments ", receiverClass, "::", slotName);
      return false;
   }

   //
   if (type == Qt::AutoCompatConnection) {
       type = Qt::AutoConnection;
   }

   //
   const BentoAbstract *signalMethod_Bento = signalMetaMethod.getBentoBox();
   const BentoAbstract *slotMethod_Bento   = slotMetaMethod.getBentoBox();

   if (! signalMethod_Bento) {
      qWarning("%s%s%s%s%s", "QObject::connect() ", senderClass, "::", signalName,
                               " Unable to locate the requested signal, verify connect arguments and signal declaration");
      return false;
   }

   if (! slotMethod_Bento) {
      qWarning("%s%s%s%s%s", "QObject::connect() ", receiverClass, "::", slotName,
                               " Unable to locate the requested slot, verify connect arguments and slot declaration");
      return false;
   }

   std::unique_lock<std::mutex> senderLock{sender->m_mutex_ToReceiver};
   std::unique_lock<std::mutex> receiverLock{receiver->m_mutex_FromSender};

   if (type & Qt::UniqueConnection) {
      // user passed enum to ensure the connection is not added twice

      for(auto index = sender->m_connectList_ToReceiver.begin(); index != sender->m_connectList_ToReceiver.end(); ++index) {
         const ConnectStruct &temp = *index;

         if (temp.sender == 0) {
            // connection is marked for deletion
            continue;
         }

         if (temp.receiver != receiver) {
            continue;
         }

         if (*(temp.signalMethod) != *(signalMethod_Bento))  {
            continue;
         }

         if (*(temp.slotMethod) != *(slotMethod_Bento))  {
            continue;
         }

         // connection already exists
         return false;
      }

      // change type
      type = static_cast<Qt::ConnectionType>(type & ~Qt::UniqueConnection);
   }

   sender->addConnection(signalMethod_Bento, receiver, slotMethod_Bento, type);
   sender->connectNotify(signalMetaMethod);

   return true;
}