diff -r 000000000000 -r 1918ee327afb src/activeqt/container/qaxdump.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/activeqt/container/qaxdump.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the ActiveQt framework of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qaxbase.h" + +#ifndef QT_NO_WIN_ACTIVEQT + +#include +#include +#include +#include + +#include + +#include "../shared/qaxtypes.h" + +QT_BEGIN_NAMESPACE + +QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name) +{ + QString docu; + if (!typeInfo) + return docu; + + MEMBERID memId; + BSTR names = QStringToBSTR(name); + typeInfo->GetIDsOfNames((BSTR*)&names, 1, &memId); + SysFreeString(names); + if (memId != DISPID_UNKNOWN) { + BSTR docStringBstr, helpFileBstr; + ulong helpContext; + HRESULT hres = typeInfo->GetDocumentation(memId, 0, &docStringBstr, &helpContext, &helpFileBstr); + QString docString = QString::fromWCharArray(docStringBstr); + QString helpFile = QString::fromWCharArray(helpFileBstr); + SysFreeString(docStringBstr); + SysFreeString(helpFileBstr); + if (hres == S_OK) { + if (!docString.isEmpty()) + docu += docString + QLatin1String("\n"); + if (!helpFile.isEmpty()) + docu += QString::fromLatin1("For more information, see help context %1 in %2.").arg((uint)helpContext).arg(helpFile); + } + } + + return docu; +} + +static inline QString docuFromName(ITypeInfo *typeInfo, const QString &name) +{ + return QLatin1String("

") + qax_docuFromName(typeInfo, name) + QLatin1String("\n"); +} + +static QByteArray namedPrototype(const QList ¶meterTypes, const QList ¶meterNames, int numDefArgs = 0) +{ + QByteArray prototype("("); + for (int p = 0; p < parameterTypes.count(); ++p) { + QByteArray type(parameterTypes.at(p)); + prototype += type; + + if (p < parameterNames.count()) + prototype += ' ' + parameterNames.at(p); + + if (numDefArgs >= parameterTypes.count() - p) + prototype += " = 0"; + if (p < parameterTypes.count() - 1) + prototype += ", "; + } + prototype += ')'; + + return prototype; +} + +static QByteArray toType(const QByteArray &t) +{ + QByteArray type = t; + int vartype = QVariant::nameToType(type); + if (vartype == QVariant::Invalid) + type = "int"; + + if (type.at(0) == 'Q') + type = type.mid(1); + type[0] = toupper(type.at(0)); + if (type == "VariantList") + type = "List"; + else if (type == "Map") + type = "Map"; + else if (type == "Uint") + type = "UInt"; + + return "to" + type + "()"; +} + +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 << "

" << coClass << " Reference

" << endl; + stream << "

The " << coClass << " COM object is a " << that->qObject()->metaObject()->className(); + stream << " with the CLSID " << that->control() << ".

" << endl; + + stream << "

Interfaces

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

Event Interfaces

" << endl; + stream << "
    " << endl; + interCount = 1; + while ((inter = mo->classInfo(mo->indexOfClassInfo("Event Interface " + QByteArray::number(interCount))).value())) { + stream << "
  • " << inter << endl; + interCount++; + } + stream << "
" << endl; + + QList methodDetails, propDetails; + + const int slotCount = mo->methodCount(); + if (slotCount) { + stream << "

Public Slots:

" << endl; + stream << "
    " << 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.signature(); + QByteArray name = signature.left(signature.indexOf('(')); + stream << "
  • " << returntype << " " << name << "" << prototype << ";
  • " << endl; + + prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames()); + QString detail = QString::fromLatin1("

    ") + + QLatin1String(returntype.constData()) + QLatin1Char(' ') + + QLatin1String(name.constData()) + QLatin1Char(' ') + + QString::fromLatin1(prototype.constData()) + QLatin1String(" [slot]

    \n"); + prototype = namedPrototype(slot.parameterTypes(), QList()); + detail += docuFromName(typeInfo, QString::fromLatin1(name.constData())); + detail += QLatin1String("

    Connect a signal to this slot:

    \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("
    \n"); + + if (1) { + detail += QLatin1String("

    Or call the function directly:

    \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(";
    \n"); + } else { + detail += QLatin1String("

    This function has parameters of unsupported types and cannot be called directly."); + } + + methodDetails << detail; + defArgCount = 0; + } + + stream << "

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

Signals:

" << endl; + stream << "
    " << 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.signature(); + QByteArray name = signature.left(signature.indexOf('(')); + stream << "
  • void " << name << "" << prototype << ";
  • " << endl; + + QString detail = QLatin1String("

    void ") + + QLatin1String(name.constData()) + QLatin1Char(' ') + + QLatin1String(prototype.constData()) + QLatin1String(" [signal]

    \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()); + detail += QLatin1String("

    Connect a slot to this signal:

    \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("
    \n"); + + methodDetails << detail; + if (typeInfo) + typeInfo->Release(); + typeInfo = 0; + } + stream << "
" << endl; + + if (typeLib) + typeLib->Release(); + } + + const int propCount = mo->propertyCount(); + if (propCount) { + if (dispatch) + dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo); + stream << "

Properties:

" << endl; + stream << "
    " << endl; + + for (int iprop = 0; iprop < propCount; ++iprop) { + const QMetaProperty prop = mo->property(iprop); + QByteArray name(prop.name()); + QByteArray type(prop.typeName()); + + stream << "
  • " << type << " " << name << ";
  • " << endl; + QString detail = QLatin1String("

    ") + + QLatin1String(type.constData()) + + QLatin1Char(' ') + QLatin1String(name.constData()) + QLatin1String("

    \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("

    Read this property's value using QObject::property:

    \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("
    \n"); + } else if (type == "IDispatch*" || type == "IUnknown*") { + detail += QLatin1String("

    Get the subobject using querySubObject:

    \n");
    +		detail += QLatin1String("\tQAxObject *") + QLatin1String(name.constData()) +
    +                          QLatin1String(" = object->querySubObject(\"") + QLatin1String(name.constData()) + QLatin1String("\");\n");
    +		detail += QLatin1String("
    \n"); + } else { + detail += QLatin1String("

    This property is of an unsupported type.\n"); + } + if (prop.isWritable()) { + detail += QLatin1String("Set this property' value using QObject::setProperty:

    \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("
    \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("") + + QString::fromLatin1(setterSlot.constData()) + QLatin1String(" slot.\n"); + } + if (prop.isEnumType()) { + detail += QLatin1String("

    See also ") + QString::fromLatin1(type) + QLatin1String(".\n"); + } + + propDetails << detail; + } + stream << "

" << endl; + } + + const int enumCount = mo->enumeratorCount(); + if (enumCount) { + stream << "

Member Type Documentation

" << endl; + for (int i = 0; i < enumCount; ++i) { + const QMetaEnum enumdata = mo->enumerator(i); + stream << "

" << enumdata.name() << "

" << endl; + stream << "
    " << endl; + for (int e = 0; e < enumdata.keyCount(); ++e) { + stream << "
  • " << enumdata.key(e) << "\t=" << enumdata.value(e) << "
  • " << endl; + } + stream << "
" << endl; + } + } + if (methodDetails.count()) { + stream << "

Member Function Documentation

" << endl; + for (int i = 0; i < methodDetails.count(); ++i) + stream << methodDetails.at(i) << endl; + } + if (propDetails.count()) { + stream << "

Property Documentation

" << endl; + for (int i = 0; i < propDetails.count(); ++i) + stream << propDetails.at(i) << endl; + } + + if (typeInfo) + typeInfo->Release(); + if (dispatch) + dispatch->Release(); + return docu; +} + +QT_END_NAMESPACE +#endif // QT_NO_WIN_ACTIVEQT