src/activeqt/container/qaxdump.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the ActiveQt framework of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:BSD$
       
    10 ** You may use this file under the terms of the BSD license as follows:
       
    11 **
       
    12 ** "Redistribution and use in source and binary forms, with or without
       
    13 ** modification, are permitted provided that the following conditions are
       
    14 ** met:
       
    15 **   * Redistributions of source code must retain the above copyright
       
    16 **     notice, this list of conditions and the following disclaimer.
       
    17 **   * Redistributions in binary form must reproduce the above copyright
       
    18 **     notice, this list of conditions and the following disclaimer in
       
    19 **     the documentation and/or other materials provided with the
       
    20 **     distribution.
       
    21 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
       
    22 **     the names of its contributors may be used to endorse or promote
       
    23 **     products derived from this software without specific prior written
       
    24 **     permission.
       
    25 **
       
    26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
       
    37 ** $QT_END_LICENSE$
       
    38 **
       
    39 ****************************************************************************/
       
    40 
       
    41 #include "qaxbase.h"
       
    42 
       
    43 #ifndef QT_NO_WIN_ACTIVEQT
       
    44 
       
    45 #include <qmetaobject.h>
       
    46 #include <quuid.h>
       
    47 #include <qt_windows.h>
       
    48 #include <qtextstream.h>
       
    49 
       
    50 #include <ctype.h>
       
    51 
       
    52 #include "../shared/qaxtypes.h"
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 
       
    56 QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name)
       
    57 {
       
    58     QString docu;
       
    59     if (!typeInfo)
       
    60         return docu;
       
    61 
       
    62     MEMBERID memId;
       
    63     BSTR names = QStringToBSTR(name);
       
    64     typeInfo->GetIDsOfNames((BSTR*)&names, 1, &memId);
       
    65     SysFreeString(names);
       
    66     if (memId != DISPID_UNKNOWN) {
       
    67         BSTR docStringBstr, helpFileBstr;
       
    68         ulong helpContext;
       
    69         HRESULT hres = typeInfo->GetDocumentation(memId, 0, &docStringBstr, &helpContext, &helpFileBstr);
       
    70         QString docString = QString::fromWCharArray(docStringBstr);
       
    71         QString helpFile = QString::fromWCharArray(helpFileBstr);
       
    72         SysFreeString(docStringBstr);
       
    73         SysFreeString(helpFileBstr);
       
    74         if (hres == S_OK) {
       
    75             if (!docString.isEmpty())
       
    76                 docu += docString + QLatin1String("\n");
       
    77             if (!helpFile.isEmpty())
       
    78                 docu += QString::fromLatin1("For more information, see help context %1 in %2.").arg((uint)helpContext).arg(helpFile);
       
    79         }
       
    80     }
       
    81 
       
    82     return docu;
       
    83 }
       
    84 
       
    85 static inline QString docuFromName(ITypeInfo *typeInfo, const QString &name)
       
    86 {
       
    87     return QLatin1String("<p>") + qax_docuFromName(typeInfo, name) + QLatin1String("\n");
       
    88 }
       
    89 
       
    90 static QByteArray namedPrototype(const QList<QByteArray> &parameterTypes, const QList<QByteArray> &parameterNames, int numDefArgs = 0)
       
    91 {
       
    92     QByteArray prototype("(");
       
    93     for (int p = 0; p < parameterTypes.count(); ++p) {
       
    94         QByteArray type(parameterTypes.at(p));
       
    95         prototype += type;
       
    96 
       
    97         if (p < parameterNames.count())
       
    98             prototype += ' ' + parameterNames.at(p);
       
    99          
       
   100         if (numDefArgs >= parameterTypes.count() - p)
       
   101             prototype += " = 0";
       
   102         if (p < parameterTypes.count() - 1)
       
   103             prototype += ", ";
       
   104     }
       
   105     prototype += ')';
       
   106 
       
   107     return prototype;
       
   108 }
       
   109 
       
   110 static QByteArray toType(const QByteArray &t)
       
   111 {
       
   112     QByteArray type = t;
       
   113     int vartype = QVariant::nameToType(type);
       
   114     if (vartype == QVariant::Invalid)
       
   115         type = "int";
       
   116     
       
   117     if (type.at(0) == 'Q')
       
   118         type = type.mid(1);
       
   119     type[0] = toupper(type.at(0));
       
   120     if (type == "VariantList")
       
   121         type = "List";
       
   122     else if (type == "Map<QVariant,QVariant>")
       
   123         type = "Map";
       
   124     else if (type == "Uint")
       
   125         type = "UInt";
       
   126     
       
   127     return "to" + type + "()";
       
   128 }
       
   129 
       
   130 QString qax_generateDocumentation(QAxBase *that)
       
   131 {
       
   132     that->metaObject();
       
   133 
       
   134     if (that->isNull())
       
   135 	return QString();
       
   136 
       
   137     ITypeInfo *typeInfo = 0;
       
   138     IDispatch *dispatch = 0;
       
   139     that->queryInterface(IID_IDispatch, (void**)&dispatch);
       
   140     if (dispatch)
       
   141 	dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);
       
   142 
       
   143     QString docu;
       
   144     QTextStream stream(&docu, QIODevice::WriteOnly);
       
   145 
       
   146     const QMetaObject *mo = that->metaObject();
       
   147     QString coClass  = QLatin1String(mo->classInfo(mo->indexOfClassInfo("CoClass")).value());
       
   148 
       
   149     stream << "<h1 align=center>" << coClass << " Reference</h1>" << endl;
       
   150     stream << "<p>The " << coClass << " COM object is a " << that->qObject()->metaObject()->className();
       
   151     stream << " with the CLSID " <<  that->control() << ".</p>" << endl;
       
   152 
       
   153     stream << "<h3>Interfaces</h3>" << endl;
       
   154     stream << "<ul>" << endl;
       
   155     const char *inter = 0;
       
   156     int interCount = 1;
       
   157     while ((inter = mo->classInfo(mo->indexOfClassInfo("Interface " + QByteArray::number(interCount))).value())) {
       
   158 	stream << "<li>" << inter << endl;
       
   159 	interCount++;
       
   160     }
       
   161     stream << "</ul>" << endl;
       
   162 
       
   163     stream << "<h3>Event Interfaces</h3>" << endl;
       
   164     stream << "<ul>" << endl;
       
   165     interCount = 1;  
       
   166     while ((inter = mo->classInfo(mo->indexOfClassInfo("Event Interface " + QByteArray::number(interCount))).value())) {
       
   167 	stream << "<li>" << inter << endl;
       
   168 	interCount++;
       
   169     }
       
   170     stream << "</ul>" << endl;
       
   171 
       
   172     QList<QString> methodDetails, propDetails;
       
   173 
       
   174     const int slotCount = mo->methodCount();
       
   175     if (slotCount) {
       
   176 	stream << "<h2>Public Slots:</h2>" << endl;
       
   177 	stream << "<ul>" << endl;
       
   178 
       
   179         int defArgCount = 0;
       
   180 	for (int islot = mo->methodOffset(); islot < slotCount; ++islot) {
       
   181 	    const QMetaMethod slot = mo->method(islot);
       
   182             if (slot.methodType() != QMetaMethod::Slot)
       
   183                 continue;
       
   184 
       
   185             if (slot.attributes() & QMetaMethod::Cloned) {
       
   186                 ++defArgCount;
       
   187                 continue;
       
   188             }
       
   189 
       
   190 	    QByteArray returntype(slot.typeName());
       
   191             if (returntype.isEmpty())
       
   192                 returntype = "void";
       
   193             QByteArray prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames(), defArgCount);
       
   194             QByteArray signature = slot.signature();
       
   195 	    QByteArray name = signature.left(signature.indexOf('('));
       
   196 	    stream << "<li>" << returntype << " <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl;
       
   197             
       
   198             prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames());
       
   199 	    QString detail = QString::fromLatin1("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
       
   200                              QLatin1String(returntype.constData()) + QLatin1Char(' ') +
       
   201                              QLatin1String(name.constData()) + QLatin1Char(' ') +
       
   202                              QString::fromLatin1(prototype.constData()) + QLatin1String("<tt> [slot]</tt></h3>\n");
       
   203             prototype = namedPrototype(slot.parameterTypes(), QList<QByteArray>());
       
   204 	    detail += docuFromName(typeInfo, QString::fromLatin1(name.constData()));
       
   205 	    detail += QLatin1String("<p>Connect a signal to this slot:<pre>\n");
       
   206 	    detail += QString::fromLatin1("\tQObject::connect(sender, SIGNAL(someSignal") + QString::fromLatin1(prototype.constData()) +
       
   207                       QLatin1String("), object, SLOT(") + QString::fromLatin1(name.constData()) +
       
   208                       QString::fromLatin1(prototype.constData()) + QLatin1String("));");
       
   209 	    detail += QLatin1String("</pre>\n");
       
   210 
       
   211             if (1) {
       
   212                 detail += QLatin1String("<p>Or call the function directly:<pre>\n");
       
   213 
       
   214                 bool hasParams = slot.parameterTypes().count() != 0;
       
   215                 if (hasParams)
       
   216                     detail += QLatin1String("\tQVariantList params = ...\n");
       
   217                 detail += QLatin1String("\t");
       
   218                 QByteArray functionToCall = "dynamicCall";
       
   219                 if (returntype == "IDispatch*" || returntype == "IUnknown*") {
       
   220                     functionToCall = "querySubObject";
       
   221                     returntype = "QAxObject *";
       
   222                 }
       
   223                 if (returntype != "void")
       
   224                     detail += QLatin1String(returntype.constData()) + QLatin1String(" result = ");
       
   225                 detail += QLatin1String("object->") + QLatin1String(functionToCall.constData()) +
       
   226                           QLatin1String("(\"" + name + prototype + '\"');
       
   227                 if (hasParams)
       
   228                     detail += QLatin1String(", params");
       
   229                 detail += QLatin1Char(')');
       
   230                 if (returntype != "void" && returntype != "QAxObject *" && returntype != "QVariant")
       
   231                     detail += QLatin1Char('.') + QLatin1String(toType(returntype));
       
   232 	        detail += QLatin1String(";</pre>\n");
       
   233 	    } else {
       
   234 		detail += QLatin1String("<p>This function has parameters of unsupported types and cannot be called directly.");
       
   235 	    }
       
   236 
       
   237 	    methodDetails << detail;
       
   238             defArgCount = 0;
       
   239 	}
       
   240 
       
   241 	stream << "</ul>" << endl;
       
   242     }
       
   243     int signalCount = mo->methodCount();
       
   244     if (signalCount) {
       
   245         ITypeLib *typeLib = 0;
       
   246         if (typeInfo) {
       
   247             UINT index = 0;
       
   248             typeInfo->GetContainingTypeLib(&typeLib, &index);
       
   249             typeInfo->Release();
       
   250         }
       
   251         typeInfo = 0;
       
   252 
       
   253 	stream << "<h2>Signals:</h2>" << endl;
       
   254 	stream << "<ul>" << endl;
       
   255 
       
   256 	for (int isignal = mo->methodOffset(); isignal < signalCount; ++isignal) {
       
   257 	    const QMetaMethod signal(mo->method(isignal));
       
   258             if (signal.methodType() != QMetaMethod::Signal)
       
   259                 continue;
       
   260 
       
   261             QByteArray prototype = namedPrototype(signal.parameterTypes(), signal.parameterNames());
       
   262 	    QByteArray signature = signal.signature();
       
   263 	    QByteArray name = signature.left(signature.indexOf('('));
       
   264 	    stream << "<li>void <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl;
       
   265 
       
   266             QString detail = QLatin1String("<h3><a name=") + QLatin1String(name.constData()) + QLatin1String("></a>void ") +
       
   267                              QLatin1String(name.constData()) + QLatin1Char(' ') +
       
   268                              QLatin1String(prototype.constData()) + QLatin1String("<tt> [signal]</tt></h3>\n");
       
   269             if (typeLib) {
       
   270                 interCount = 0;
       
   271                 do {
       
   272                     if (typeInfo)
       
   273                         typeInfo->Release();
       
   274                     typeInfo = 0;
       
   275                     typeLib->GetTypeInfo(++interCount, &typeInfo);
       
   276                     QString typeLibDocu = docuFromName(typeInfo, QString::fromLatin1(name.constData()));
       
   277                     if (!typeLibDocu.isEmpty()) {
       
   278                         detail += typeLibDocu;
       
   279                         break;
       
   280                     }
       
   281                 } while (typeInfo);
       
   282             }
       
   283             prototype = namedPrototype(signal.parameterTypes(), QList<QByteArray>());
       
   284 	    detail += QLatin1String("<p>Connect a slot to this signal:<pre>\n");
       
   285 	    detail += QLatin1String("\tQObject::connect(object, SIGNAL(") + QString::fromLatin1(name.constData()) +
       
   286                       QString::fromLatin1(prototype.constData()) +
       
   287                       QLatin1String("), receiver, SLOT(someSlot") + QString::fromLatin1(prototype.constData()) + QLatin1String("));");
       
   288 	    detail += QLatin1String("</pre>\n");
       
   289 
       
   290 	    methodDetails << detail;
       
   291             if (typeInfo)
       
   292                 typeInfo->Release();
       
   293             typeInfo = 0;
       
   294 	}
       
   295 	stream << "</ul>" << endl;
       
   296 
       
   297         if (typeLib)
       
   298             typeLib->Release();
       
   299     }
       
   300 
       
   301     const int propCount = mo->propertyCount();
       
   302     if (propCount) {
       
   303         if (dispatch)
       
   304 	    dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);
       
   305 	stream << "<h2>Properties:</h2>" << endl;
       
   306 	stream << "<ul>" << endl;
       
   307 
       
   308 	for (int iprop = 0; iprop < propCount; ++iprop) {
       
   309 	    const QMetaProperty prop = mo->property(iprop);
       
   310 	    QByteArray name(prop.name());
       
   311 	    QByteArray type(prop.typeName());
       
   312 
       
   313 	    stream << "<li>" << type << " <a href=\"#" << name << "\"><b>" << name << "</b></a>;</li>" << endl;
       
   314 	    QString detail = QLatin1String("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
       
   315                              QLatin1String(type.constData()) +
       
   316 		             QLatin1Char(' ') + QLatin1String(name.constData()) + QLatin1String("</h3>\n");
       
   317 	    detail += docuFromName(typeInfo, QString::fromLatin1(name));
       
   318 	    QVariant::Type vartype = QVariant::nameToType(type);
       
   319 	    if (!prop.isReadable())
       
   320 		continue;
       
   321 
       
   322 	    if (prop.isEnumType())
       
   323 		vartype = QVariant::Int;
       
   324 
       
   325             if (vartype != QVariant::Invalid) {
       
   326 		detail += QLatin1String("<p>Read this property's value using QObject::property:<pre>\n");
       
   327                 if (prop.isEnumType())
       
   328 		    detail += QLatin1String("\tint val = ");
       
   329                 else
       
   330                     detail += QLatin1Char('\t') + QLatin1String(type.constData()) + QLatin1String(" val = ");
       
   331 		detail += QLatin1String("object->property(\"") + QLatin1String(name.constData()) +
       
   332                           QLatin1String("\").") + QLatin1String(toType(type).constData()) + QLatin1String(";\n");
       
   333 		detail += QLatin1String("</pre>\n");
       
   334 	    } else if (type == "IDispatch*" || type == "IUnknown*") {
       
   335 		detail += QLatin1String("<p>Get the subobject using querySubObject:<pre>\n");
       
   336 		detail += QLatin1String("\tQAxObject *") + QLatin1String(name.constData()) +
       
   337                           QLatin1String(" = object->querySubObject(\"") + QLatin1String(name.constData()) + QLatin1String("\");\n");
       
   338 		detail += QLatin1String("</pre>\n");
       
   339 	    } else {
       
   340 		detail += QLatin1String("<p>This property is of an unsupported type.\n");
       
   341 	    }
       
   342 	    if (prop.isWritable()) {
       
   343 		detail += QLatin1String("Set this property' value using QObject::setProperty:<pre>\n");
       
   344                 if (prop.isEnumType()) {
       
   345                     detail += QLatin1String("\tint newValue = ... // string representation of values also supported\n");
       
   346                 } else {
       
   347 		    detail += QLatin1String("\t") + QString::fromLatin1(type.constData()) + QLatin1String(" newValue = ...\n");
       
   348                 }
       
   349 		detail += QLatin1String("\tobject->setProperty(\"") + QString::fromLatin1(name) + QLatin1String("\", newValue);\n");
       
   350 		detail += QLatin1String("</pre>\n");
       
   351 		detail += QLatin1String("Or using the ");
       
   352 		QByteArray setterSlot;
       
   353                 if (isupper(name.at(0))) {
       
   354 		    setterSlot = "Set" + name;
       
   355 		} else {
       
   356 		    QByteArray nameUp = name;
       
   357 		    nameUp[0] = toupper(nameUp.at(0));
       
   358 		    setterSlot = "set" + nameUp;
       
   359 		}
       
   360 		detail += QLatin1String("<a href=\"#") + QString::fromLatin1(setterSlot) + QLatin1String("\">") +
       
   361                           QString::fromLatin1(setterSlot.constData()) + QLatin1String("</a> slot.\n");
       
   362 	    }
       
   363 	    if (prop.isEnumType()) {
       
   364 		detail += QLatin1String("<p>See also <a href=\"#") + QString::fromLatin1(type) +
       
   365                 QLatin1String("\">") + QString::fromLatin1(type) + QLatin1String("</a>.\n");
       
   366 	    }
       
   367 
       
   368 	    propDetails << detail;
       
   369 	}
       
   370 	stream << "</ul>" << endl;
       
   371     }
       
   372 
       
   373     const int enumCount = mo->enumeratorCount();
       
   374     if (enumCount) {
       
   375 	stream << "<hr><h2>Member Type Documentation</h2>" << endl;
       
   376 	for (int i = 0; i < enumCount; ++i) {
       
   377 	    const QMetaEnum enumdata = mo->enumerator(i);
       
   378 	    stream << "<h3><a name=" << enumdata.name() << "></a>" << enumdata.name() << "</h3>" << endl;
       
   379 	    stream << "<ul>" << endl;
       
   380 	    for (int e = 0; e < enumdata.keyCount(); ++e) {
       
   381 		stream << "<li>" << enumdata.key(e) << "\t=" << enumdata.value(e) << "</li>" << endl;
       
   382 	    }
       
   383 	    stream << "</ul>" << endl;
       
   384 	}
       
   385     }
       
   386     if (methodDetails.count()) {
       
   387 	stream << "<hr><h2>Member Function Documentation</h2>" << endl;
       
   388 	for (int i = 0; i < methodDetails.count(); ++i)
       
   389 	    stream << methodDetails.at(i) << endl;
       
   390     }
       
   391     if (propDetails.count()) {
       
   392 	stream << "<hr><h2>Property Documentation</h2>" << endl;
       
   393 	for (int i = 0; i < propDetails.count(); ++i)
       
   394 	    stream << propDetails.at(i) << endl;
       
   395     }
       
   396 
       
   397     if (typeInfo)
       
   398         typeInfo->Release();
       
   399     if (dispatch)
       
   400         dispatch->Release();
       
   401     return docu;
       
   402 }
       
   403 
       
   404 QT_END_NAMESPACE
       
   405 #endif // QT_NO_WIN_ACTIVEQT