Qt 4.8
qaxdump.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the ActiveQt framework of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
19 ** distribution.
20 ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 ** of its contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
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 
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 
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;
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));
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 
405 #endif // QT_NO_WIN_ACTIVEQT
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
QTextStream & endl(QTextStream &stream)
Writes &#39; &#39; to the stream and flushes the stream.
bool isNull() const
Returns true if there is no COM object loaded by this wrapper; otherwise return false.
Definition: qaxbase.cpp:4412
int type
Definition: qmetatype.cpp:239
bool isWritable() const
Returns true if this property is writable; otherwise returns false.
The QMetaEnum class provides meta-data about an enumerator.
Definition: qmetaobject.h:147
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual const QMetaObject * metaObject() const
The metaobject is generated on the fly from the information provided by the IDispatch and ITypeInfo i...
Definition: qaxbase.cpp:3245
QString control() const
the name of the COM object wrapped by this QAxBase object.
Definition: qaxbase.cpp:1029
virtual QObject * qObject() const =0
QMetaClassInfo classInfo(int index) const
Returns the meta-data for the item of class information with the given index.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
const char * key(int index) const
Returns the key with the given index, or 0 if no such key exists.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
int propertyCount() const
Returns the number of properties in this class, including the number of properties provided by each b...
The QString class provides a Unicode character string.
Definition: qstring.h:83
const char * typeName() const
Returns the return type of this method, or an empty string if the return type is void.
QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name)
Definition: qaxdump.cpp:56
const char * name() const
Returns the name of the enumerator (without the scope).
QString qax_generateDocumentation(QAxBase *that)
Definition: qaxdump.cpp:130
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isEnumType() const
Returns true if the property&#39;s type is an enumeration value; otherwise returns false.
static FILE * stream
QList< QByteArray > parameterNames() const
Returns a list of parameter names.
int methodOffset() const
Returns the method offset for this class; i.e.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const char * name
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
unsigned int uint
Definition: qglobal.h:996
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
int enumeratorCount() const
Returns the number of enumerators in this class.
unsigned long ulong
Definition: qglobal.h:997
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
int keyCount() const
Returns the number of keys.
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
static QByteArray prototype(const QList< QByteArray > &parameterTypes, const QList< QByteArray > &parameterNames, bool *ok)
Definition: qaxserver.cpp:685
QList< QByteArray > parameterTypes() const
Returns a list of parameter types.
long HRESULT
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
const char * name() const
Returns this property&#39;s name.
The QTextStream class provides a convenient interface for reading and writing text.
Definition: qtextstream.h:73
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
static BSTR QStringToBSTR(const QString &str)
Definition: qaxtypes.h:76
static QString docuFromName(ITypeInfo *typeInfo, const QString &name)
Definition: qaxdump.cpp:85
const char * className() const
Returns the class name.
Definition: qobjectdefs.h:491
QMetaEnum enumerator(int index) const
Returns the meta-data for the enumerator with the given index.
int attributes() const
bool isReadable() const
Returns true if this property is readable; otherwise returns false.
quint16 index
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
The QMetaProperty class provides meta-data about a property.
Definition: qmetaobject.h:176
const char * signature() const
Returns the signature of this method (e.g., setValue(double)).
static QByteArray namedPrototype(const QList< QByteArray > &parameterTypes, const QList< QByteArray > &parameterNames, int numDefArgs=0)
Definition: qaxdump.cpp:90
char at(int i) const
Returns the character at index position i in the byte array.
Definition: qbytearray.h:413
static Type nameToType(const char *name)
Converts the string representation of the storage type given in name, to its enum representation...
Definition: qvariant.cpp:2026
long queryInterface(const QUuid &, void **) const
Requests the interface uuid from the COM object and sets the value of iface to the provided interface...
Definition: qaxbase.cpp:1479
int indexOfClassInfo(const char *name) const
Finds class information item name and returns its index; otherwise returns -1.
The QAxBase class is an abstract class that provides an API to initialize and access a COM object...
Definition: qaxbase.h:66
int methodCount() const
Returns the number of methods known to the meta-object system in this class, including the number of ...
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
const char * typeName() const
Returns the name of this property&#39;s type.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
static QByteArray toType(const QByteArray &t)
Definition: qaxdump.cpp:110
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
QMetaProperty property(int index) const
Returns the meta-data for the property with the given index.
int value(int index) const
Returns the value with the given index; or returns -1 if there is no such value.