1
/****************************************************************************
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
7
** This file is part of the ActiveQt framework of the Qt Toolkit.
9
** $QT_BEGIN_LICENSE:BSD$
10
** You may use this file under the terms of the BSD license as follows:
12
** "Redistribution and use in source and binary forms, with or without
13
** modification, are permitted provided that the following conditions are
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
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
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."
39
****************************************************************************/
43
#ifndef QT_NO_WIN_ACTIVEQT
45
#include <qmetaobject.h>
47
#include <qt_windows.h>
48
#include <qtextstream.h>
52
#include "../shared/qaxtypes.h"
56
QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name)
63
BSTR names = QStringToBSTR(name);
64
typeInfo->GetIDsOfNames((BSTR*)&names, 1, &memId);
66
if (memId != DISPID_UNKNOWN) {
67
BSTR docStringBstr, helpFileBstr;
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);
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);
85
static inline QString docuFromName(ITypeInfo *typeInfo, const QString &name)
87
return QLatin1String("<p>") + qax_docuFromName(typeInfo, name) + QLatin1String("\n");
90
static QByteArray namedPrototype(const QList<QByteArray> ¶meterTypes, const QList<QByteArray> ¶meterNames, int numDefArgs = 0)
92
QByteArray prototype("(");
93
for (int p = 0; p < parameterTypes.count(); ++p) {
94
QByteArray type(parameterTypes.at(p));
97
if (p < parameterNames.count())
98
prototype += ' ' + parameterNames.at(p);
100
if (numDefArgs >= parameterTypes.count() - p)
102
if (p < parameterTypes.count() - 1)
110
static QByteArray toType(const QByteArray &t)
113
int vartype = QVariant::nameToType(type);
114
if (vartype == QVariant::Invalid)
117
if (type.at(0) == 'Q')
119
type[0] = toupper(type.at(0));
120
if (type == "VariantList")
122
else if (type == "Map<QVariant,QVariant>")
124
else if (type == "Uint")
127
return "to" + type + "()";
130
QString qax_generateDocumentation(QAxBase *that)
137
ITypeInfo *typeInfo = 0;
138
IDispatch *dispatch = 0;
139
that->queryInterface(IID_IDispatch, (void**)&dispatch);
141
dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);
144
QTextStream stream(&docu, QIODevice::WriteOnly);
146
const QMetaObject *mo = that->metaObject();
147
QString coClass = QLatin1String(mo->classInfo(mo->indexOfClassInfo("CoClass")).value());
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;
153
stream << "<h3>Interfaces</h3>" << endl;
154
stream << "<ul>" << endl;
155
const char *inter = 0;
157
while ((inter = mo->classInfo(mo->indexOfClassInfo("Interface " + QByteArray::number(interCount))).value())) {
158
stream << "<li>" << inter << endl;
161
stream << "</ul>" << endl;
163
stream << "<h3>Event Interfaces</h3>" << endl;
164
stream << "<ul>" << endl;
166
while ((inter = mo->classInfo(mo->indexOfClassInfo("Event Interface " + QByteArray::number(interCount))).value())) {
167
stream << "<li>" << inter << endl;
170
stream << "</ul>" << endl;
172
QList<QString> methodDetails, propDetails;
174
const int slotCount = mo->methodCount();
176
stream << "<h2>Public Slots:</h2>" << endl;
177
stream << "<ul>" << endl;
180
for (int islot = mo->methodOffset(); islot < slotCount; ++islot) {
181
const QMetaMethod slot = mo->method(islot);
182
if (slot.methodType() != QMetaMethod::Slot)
185
if (slot.attributes() & QMetaMethod::Cloned) {
190
QByteArray returntype(slot.typeName());
191
if (returntype.isEmpty())
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;
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");
212
detail += QLatin1String("<p>Or call the function directly:<pre>\n");
214
bool hasParams = slot.parameterTypes().count() != 0;
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 *";
223
if (returntype != "void")
224
detail += QLatin1String(returntype.constData()) + QLatin1String(" result = ");
225
detail += QLatin1String("object->") + QLatin1String(functionToCall.constData()) +
226
QLatin1String("(\"" + name + prototype + '\"');
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");
234
detail += QLatin1String("<p>This function has parameters of unsupported types and cannot be called directly.");
237
methodDetails << detail;
241
stream << "</ul>" << endl;
243
int signalCount = mo->methodCount();
245
ITypeLib *typeLib = 0;
248
typeInfo->GetContainingTypeLib(&typeLib, &index);
253
stream << "<h2>Signals:</h2>" << endl;
254
stream << "<ul>" << endl;
256
for (int isignal = mo->methodOffset(); isignal < signalCount; ++isignal) {
257
const QMetaMethod signal(mo->method(isignal));
258
if (signal.methodType() != QMetaMethod::Signal)
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;
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");
275
typeLib->GetTypeInfo(++interCount, &typeInfo);
276
QString typeLibDocu = docuFromName(typeInfo, QString::fromLatin1(name.constData()));
277
if (!typeLibDocu.isEmpty()) {
278
detail += typeLibDocu;
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");
290
methodDetails << detail;
295
stream << "</ul>" << endl;
301
const int propCount = mo->propertyCount();
304
dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);
305
stream << "<h2>Properties:</h2>" << endl;
306
stream << "<ul>" << endl;
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());
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())
322
if (prop.isEnumType())
323
vartype = QVariant::Int;
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 = ");
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");
340
detail += QLatin1String("<p>This property is of an unsupported type.\n");
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");
347
detail += QLatin1String("\t") + QString::fromLatin1(type.constData()) + QLatin1String(" newValue = ...\n");
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;
356
QByteArray nameUp = name;
357
nameUp[0] = toupper(nameUp.at(0));
358
setterSlot = "set" + nameUp;
360
detail += QLatin1String("<a href=\"#") + QString::fromLatin1(setterSlot) + QLatin1String("\">") +
361
QString::fromLatin1(setterSlot.constData()) + QLatin1String("</a> slot.\n");
363
if (prop.isEnumType()) {
364
detail += QLatin1String("<p>See also <a href=\"#") + QString::fromLatin1(type) +
365
QLatin1String("\">") + QString::fromLatin1(type) + QLatin1String("</a>.\n");
368
propDetails << detail;
370
stream << "</ul>" << endl;
373
const int enumCount = mo->enumeratorCount();
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;
383
stream << "</ul>" << endl;
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;
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;
405
#endif // QT_NO_WIN_ACTIVEQT