source: trunk/src/activeqt/control/qaxserver.cpp@ 123

Last change on this file since 123 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 47.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
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 Nokia Corporation and its Subsidiary(-ies) nor
21** the names of its contributors may be used to endorse or promote
22** products derived from this software without specific prior written
23** permission.
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** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qaxbindable.h"
41#include "qaxfactory.h"
42
43#ifndef QT_NO_WIN_ACTIVEQT
44
45#include <qapplication.h>
46#include <qdatetime.h>
47#include <qdir.h>
48#include <qmap.h>
49#include <qmenubar.h>
50#include <qmetaobject.h>
51#include <qsettings.h>
52#include <qvariant.h>
53#include <qtextstream.h>
54
55#include <qt_windows.h>
56#include <olectl.h>
57
58QT_BEGIN_NAMESPACE
59
60#define Q_REQUIRED_RPCNDR_H_VERSION 475
61
62// Some global variables to store module information
63bool qAxIsServer = false;
64HANDLE qAxInstance = 0;
65ITypeLib *qAxTypeLibrary = 0;
66char qAxModuleFilename[MAX_PATH];
67bool qAxOutProcServer = false;
68
69// The QAxFactory instance
70static QAxFactory* qax_factory = 0;
71extern CLSID CLSID_QRect;
72extern CLSID CLSID_QSize;
73extern CLSID CLSID_QPoint;
74extern void qax_shutDown();
75extern bool qax_ownQApp;
76
77
78extern QAxFactory *qax_instantiate();
79
80QAxFactory *qAxFactory()
81{
82 if (!qax_factory) {
83 bool hadQApp = qApp != 0;
84 qax_factory = qax_instantiate();
85 // QAxFactory created a QApplication
86 if (!hadQApp && qApp)
87 qax_ownQApp = true;
88
89 // register all types with metatype system as pointers
90 QStringList keys(qax_factory->featureList());
91 for (int i = 0; i < keys.count(); ++i) {
92 QString key(keys.at(i));
93 qRegisterMetaType((key + QLatin1String("*")).toLatin1(), (void**)0);
94 }
95 }
96 return qax_factory;
97}
98
99// Some local variables to handle module lifetime
100static unsigned long qAxModuleRef = 0;
101static CRITICAL_SECTION qAxModuleSection;
102
103
104/////////////////////////////////////////////////////////////////////////////
105// Server control
106/////////////////////////////////////////////////////////////////////////////
107
108static int initCount = 0;
109
110QString qAxInit()
111{
112 static QString libFile;
113
114 if (initCount++)
115 return libFile;
116
117 InitializeCriticalSection(&qAxModuleSection);
118
119 libFile = QString::fromLocal8Bit(qAxModuleFilename);
120 libFile = libFile.toLower();
121 if (LoadTypeLibEx((TCHAR*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
122 return libFile;
123
124 int lastDot = libFile.lastIndexOf(QLatin1Char('.'));
125 libFile = libFile.left(lastDot) + QLatin1String(".tlb");
126 if (LoadTypeLibEx((TCHAR*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
127 return libFile;
128
129 lastDot = libFile.lastIndexOf(QLatin1Char('.'));
130 libFile = libFile.left(lastDot) + QLatin1String(".olb");
131 if (LoadTypeLibEx((TCHAR*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
132 return libFile;
133
134 libFile = QString();
135 return libFile;
136}
137
138void qAxCleanup()
139{
140 if (!initCount)
141 qWarning("qAxInit/qAxCleanup mismatch");
142
143 if (--initCount)
144 return;
145
146 delete qax_factory;
147 qax_factory = 0;
148
149 if (qAxTypeLibrary) {
150 qAxTypeLibrary->Release();
151 qAxTypeLibrary = 0;
152 }
153
154 DeleteCriticalSection(&qAxModuleSection);
155}
156
157unsigned long qAxLock()
158{
159 EnterCriticalSection(&qAxModuleSection);
160 unsigned long ref = ++qAxModuleRef;
161 LeaveCriticalSection(&qAxModuleSection);
162 return ref;
163}
164
165unsigned long qAxUnlock()
166{
167 if (!initCount) // cleaned up already
168 return 0;
169
170 EnterCriticalSection(&qAxModuleSection);
171 unsigned long ref = --qAxModuleRef;
172 LeaveCriticalSection(&qAxModuleSection);
173
174 if (!ref)
175 qax_shutDown();
176 return ref;
177}
178
179unsigned long qAxLockCount()
180{
181 return qAxModuleRef;
182}
183
184/////////////////////////////////////////////////////////////////////////////
185// Registry
186/////////////////////////////////////////////////////////////////////////////
187
188extern bool qax_disable_inplaceframe;
189
190QString qax_clean_type(const QString &type, const QMetaObject *mo)
191{
192 if (mo) {
193 int classInfoIdx = mo->indexOfClassInfo("CoClassAlias");
194 if (classInfoIdx != -1) {
195 const QMetaClassInfo classInfo = mo->classInfo(classInfoIdx);
196 return QLatin1String(classInfo.value());
197 }
198 }
199
200 QString alias(type);
201 alias.remove(QLatin1String("::"));
202 return alias;
203}
204
205// (Un)Register the ActiveX server in the registry.
206// The QAxFactory implementation provides the information.
207HRESULT UpdateRegistry(BOOL bRegister)
208{
209 qAxIsServer = false;
210 QString file = QString::fromLocal8Bit(qAxModuleFilename);
211 QString path = file.left(file.lastIndexOf(QLatin1String("\\"))+1);
212 QString module = file.right(file.length() - path.length());
213 module = module.left(module.lastIndexOf(QLatin1String(".")));
214
215 const QString appId = qAxFactory()->appID().toString().toUpper();
216 const QString libId = qAxFactory()->typeLibID().toString().toUpper();
217
218 QString libFile = qAxInit();
219 QString typeLibVersion;
220
221 TLIBATTR *libAttr = 0;
222 if (qAxTypeLibrary)
223 qAxTypeLibrary->GetLibAttr(&libAttr);
224 if (!libAttr)
225 return SELFREG_E_TYPELIB;
226
227 DWORD major = libAttr->wMajorVerNum;
228 DWORD minor = libAttr->wMinorVerNum;
229 typeLibVersion = QString::number((uint)major) + QLatin1String(".") + QString::number((uint)minor);
230
231 if (bRegister)
232 RegisterTypeLib(qAxTypeLibrary, (TCHAR*)libFile.utf16(), 0);
233 else
234 UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind);
235
236 qAxTypeLibrary->ReleaseTLibAttr(libAttr);
237
238 if (typeLibVersion.isEmpty())
239 typeLibVersion = QLatin1String("1.0");
240
241 // check whether the user has permission to write to HKLM\Software\Classes
242 // if not, use HKCU\Software\Classes
243 QString keyPath(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"));
244 QSettings test(keyPath, QSettings::NativeFormat);
245 if (!test.isWritable())
246 keyPath = QLatin1String("HKEY_CURRENT_USER\\Software\\Classes");
247
248 QSettings settings(keyPath, QSettings::NativeFormat);
249
250 // we try to create the ActiveX widgets later on...
251 bool delete_qApp = false;
252 if (!qApp) {
253 int argc = 0;
254 (void)new QApplication(argc, 0);
255 delete_qApp = true;
256 }
257
258 if (bRegister) {
259 if (qAxOutProcServer) {
260 settings.setValue(QLatin1String("/AppID/") + appId + QLatin1String("/."), module);
261 settings.setValue(QLatin1String("/AppID/") + module + QLatin1String(".EXE/AppID"), appId);
262 }
263
264 QStringList keys = qAxFactory()->featureList();
265 for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
266 QString className = *key;
267 QObject *object = qAxFactory()->createObject(className);
268 const QMetaObject *mo = qAxFactory()->metaObject(className);
269 const QString classId = qAxFactory()->classID(className).toString().toUpper();
270
271 className = qax_clean_type(className, mo);
272
273 if (object) { // don't register subobject classes
274 QString classVersion = mo ? QString(QLatin1String(mo->classInfo(mo->indexOfClassInfo("Version")).value())) : QString();
275 if (classVersion.isNull())
276 classVersion = QLatin1String("1.0");
277 bool insertable = mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Insertable")).value(), "yes");
278 bool control = object->isWidgetType();
279 const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1String(".")));
280 uint olemisc = OLEMISC_SETCLIENTSITEFIRST
281 |OLEMISC_ACTIVATEWHENVISIBLE
282 |OLEMISC_INSIDEOUT
283 |OLEMISC_CANTLINKINSIDE
284 |OLEMISC_RECOMPOSEONRESIZE;
285 if (!control)
286 olemisc |= OLEMISC_INVISIBLEATRUNTIME;
287 else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe)
288 olemisc |= OLEMISC_WANTSTOMENUMERGE;
289
290 settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class"));
291 settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/CLSID/."), classId);
292 if (insertable)
293 settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
294
295 settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/."), className + QLatin1String(" Class"));
296 settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CLSID/."), classId);
297 settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CurVer/."), module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion);
298
299 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/."), className + QLatin1String(" Class"));
300 if (file.right(3).toLower() == QLatin1String("exe"))
301 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"), appId);
302 if (control)
303 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."), QVariant(QLatin1String("")));
304 if (insertable)
305 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
306 if (file.right(3).toLower() == QLatin1String("dll"))
307 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."), file);
308 else
309 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."),
310 QLatin1String("\"") + file + QLatin1String("\" -activex"));
311 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."), control ? QLatin1String("1") : QLatin1String("0"));
312 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."), QString::number(olemisc));
313 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."), QVariant(QLatin1String("")));
314 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."), QLatin1String("\"") +
315 file + QLatin1String("\", 101"));
316 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."), libId); settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."), classVersion);
317 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."), module + QLatin1String(".") + className);
318 settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."), module + QLatin1String(".") + className + QLatin1String(".") + classVersion.left(classVersion.indexOf(QLatin1Char('.'))));
319
320 QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
321 if (!mime.isEmpty()) {
322 QStringList mimeTypes = mime.split(QLatin1Char(';'));
323 for (int m = 0; m < mimeTypes.count(); ++m) {
324 mime = mimeTypes.at(m);
325 if (mime.isEmpty())
326 continue;
327 QString extension;
328 while (mime.contains(QLatin1Char(':'))) {
329 extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
330 mime = mime.left(mime.length() - extension.length() - 1);
331 // Prepend '.' before extension, if required.
332 extension = extension.trimmed();
333 if (extension[0] != QChar(QLatin1Char('.')))
334 extension = QLatin1String(".") + extension;
335 }
336
337 if (!extension.isEmpty()) {
338 settings.setValue(QLatin1String("/") + extension + QLatin1String("/."), module + QLatin1String(".") + className);
339 settings.setValue(QLatin1String("/") + extension + QLatin1String("/Content Type"), mime);
340
341 mime = mime.replace(QLatin1String("/"), QLatin1String("\\"));
342 settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"), classId);
343 settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"), extension);
344 }
345 }
346 }
347
348 delete object;
349 }
350
351 qAxFactory()->registerClass(*key, &settings);
352 }
353 } else {
354 QStringList keys = qAxFactory()->featureList();
355 for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
356 QString className = *key;
357 const QMetaObject *mo = qAxFactory()->metaObject(className);
358 const QString classId = qAxFactory()->classID(className).toString().toUpper();
359 className = qax_clean_type(className, mo);
360
361 QString classVersion = mo ? QString(QLatin1String(mo->classInfo(mo->indexOfClassInfo("Version")).value())) : QString();
362 if (classVersion.isNull())
363 classVersion = QLatin1String("1.0");
364 const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1String(".")));
365
366 qAxFactory()->unregisterClass(*key, &settings);
367
368 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/CLSID/."));
369 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/Insertable/."));
370 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/."));
371 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion);
372
373 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CLSID/."));
374 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CurVer/."));
375 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/."));
376 settings.remove(QLatin1String("/") + module + QLatin1String(".") + className);
377
378 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"));
379 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."));
380 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."));
381 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."));
382 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."));
383 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."));
384 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."));
385 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."));
386 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."));
387 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."));
388 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."));
389 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."));
390 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."));
391 settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/."));
392 settings.remove(QLatin1String("/CLSID/") + classId);
393
394 QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
395 if (!mime.isEmpty()) {
396 QStringList mimeTypes = mime.split(QLatin1Char(';'));
397 for (int m = 0; m < mimeTypes.count(); ++m) {
398 mime = mimeTypes.at(m);
399 if (mime.isEmpty())
400 continue;
401 QString extension;
402 while (mime.contains(QLatin1Char(':'))) {
403 extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
404 mime = mime.left(mime.length() - extension.length() - 1);
405 // Prepend '.' before extension, if required.
406 extension = extension.trimmed();
407 if (extension[0] != QChar(QLatin1Char('.')))
408 extension = QLatin1String(".") + extension;
409 }
410 if (!extension.isEmpty()) {
411 settings.remove(QLatin1String("/") + extension + QLatin1String("/Content Type"));
412 settings.remove(QLatin1String("/") + extension + QLatin1String("/."));
413 settings.remove(QLatin1String("/") + extension);
414 mime = mime.replace(QLatin1String("/"), QLatin1String("\\"));
415 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"));
416 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"));
417 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/."));
418 settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime);
419 }
420 }
421 }
422 }
423 }
424
425 if (delete_qApp)
426 delete qApp;
427
428 qAxCleanup();
429 if (settings.status() == QSettings::NoError)
430 return S_OK;
431 return SELFREG_E_CLASS;
432}
433
434/////////////////////////////////////////////////////////////////////////////
435// IDL generator
436/////////////////////////////////////////////////////////////////////////////
437
438static QList<QByteArray> enums;
439static QList<QByteArray> enumValues;
440static QList<QByteArray> subtypes;
441
442static const char* const type_map[][2] =
443{
444 // QVariant/Qt Value data types
445 { "QString", "BSTR" },
446 { "QCString", "BSTR" },
447 { "bool", "VARIANT_BOOL" },
448 { "int", "int" },
449 { "uint", "unsigned int" },
450 { "double", "double" },
451 { "QColor", "OLE_COLOR" },
452 { "QDate", "DATE" },
453 { "QTime", "DATE" },
454 { "QDateTime", "DATE" },
455 { "QFont", "IFontDisp*" },
456 { "QPixmap", "IPictureDisp*" },
457 { "QVariant", "VARIANT" },
458 { "QVariantList", "SAFEARRAY(VARIANT)" },
459 { "QList<QVariant>","SAFEARRAY(VARIANT)" },
460 { "quint64", "CY" },
461 { "qint64", "CY" },
462 { "qulonglong", "CY" },
463 { "qlonglong", "CY" },
464 { "QByteArray", "SAFEARRAY(BYTE)" },
465 { "QStringList", "SAFEARRAY(BSTR)" },
466 // Userdefined Qt datatypes - some not on Borland though
467 { "QCursor", "enum MousePointer" },
468 { "Qt::FocusPolicy","enum FocusPolicy" },
469#ifndef Q_CC_BOR
470# if __REQUIRED_RPCNDR_H_VERSION__ >= Q_REQUIRED_RPCNDR_H_VERSION
471 { "QRect", "struct QRect" },
472 { "QSize", "struct QSize" },
473 { "QPoint", "struct QPoint" },
474# endif
475#endif
476 // And we support COM data types
477 { "BOOL", "BOOL" },
478 { "BSTR", "BSTR" },
479 { "OLE_COLOR", "OLE_COLOR" },
480 { "DATE", "DATE" },
481 { "VARIANT", "VARIANT" },
482 { "IDispatch", "IDispatch*" },
483 { "IUnknown", "IUnknown*" },
484 { "IDispatch*", "IDispatch*" },
485 { "IUnknown*", "IUnknown*" },
486 { 0, 0 }
487};
488
489static QByteArray convertTypes(const QByteArray &qtype, bool *ok)
490{
491 qRegisterMetaType("IDispatch*", (void**)0);
492 qRegisterMetaType("IUnknown*", (void**)0);
493
494 *ok = false;
495
496 int i = 0;
497 while (type_map[i][0]) {
498 if (qtype == type_map[i][0] && type_map[i][1]) {
499 *ok = true;
500 return type_map[i][1];
501 }
502 ++i;
503 }
504 if (enums.contains(qtype)) {
505 *ok = true;
506 return "enum " + qtype;
507 }
508 if (subtypes.contains(qtype)) {
509 *ok = true;
510 } else if (qtype.endsWith('*')) {
511 QByteArray cleanType = qtype.left(qtype.length() - 1);
512 const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(cleanType.constData()));
513 if (mo) {
514 cleanType = qax_clean_type(QString::fromLatin1(cleanType), mo).toLatin1();
515 if (subtypes.contains(cleanType)) {
516 *ok = true;
517 return cleanType + '*';
518 }
519 }
520 }
521 return qtype;
522}
523
524static const char* const keyword_map[][2] =
525{
526 { "aggregatable", "aggregating" },
527 { "allocate", "alloc" },
528 { "appobject", "appObject" },
529 { "arrays", "array" },
530 { "async", "asynchronous" },
531 { "bindable", "binding" },
532 { "Boolean", "boolval" },
533 { "boolean", "boolval" },
534 { "broadcast", "broadCast" },
535 { "callback", "callBack" },
536 { "decode", "deCode" },
537 { "default", "defaulted" },
538 { "defaultbind", "defaultBind" },
539 { "defaultvalue", "defaultValue" },
540 { "encode" "enCode" },
541 { "endpoint", "endPoint" },
542 { "hidden", "isHidden" },
543 { "ignore", "ignore_" },
544 { "local", "local_" },
545 { "notify", "notify_" },
546 { "object", "object_" },
547 { "optimize", "optimize_" },
548 { "optional", "optional_" },
549 { "out", "out_" },
550 { "pipe", "pipe_" },
551 { "proxy", "proxy_" },
552 { "ptr", "pointer" },
553 { "readonly", "readOnly" },
554 { "small", "small_" },
555 { "source", "source_" },
556 { "string", "string_" },
557 { "uuid", "uuid_" },
558 { 0, 0 }
559};
560
561static QByteArray replaceKeyword(const QByteArray &name)
562{
563 int i = 0;
564 while (keyword_map[i][0]) {
565 if (name == keyword_map[i][0] && keyword_map[i][1])
566 return keyword_map[i][1];
567 ++i;
568 }
569 return name;
570}
571
572static QMap<QByteArray, int> mapping;
573
574static QByteArray renameOverloads(const QByteArray &name)
575{
576 QByteArray newName = name;
577
578 int n = mapping.value(name);
579 if (mapping.contains(name)) {
580 int n = mapping.value(name);
581 newName = name + "_" + QByteArray::number(n);
582 mapping.insert(name, n+1);
583 } else {
584 mapping.insert(name, 1);
585 }
586
587 return newName;
588}
589
590// filter out some properties
591static const char* const ignore_props[] =
592{
593 "name",
594 "objectName",
595 "isTopLevel",
596 "isDialog",
597 "isModal",
598 "isPopup",
599 "isDesktop",
600 "geometry",
601 "pos",
602 "frameSize",
603 "frameGeometry",
604 "size",
605 "sizeHint",
606 "minimumSizeHint",
607 "microFocusHint",
608 "rect",
609 "childrenRect",
610 "childrenRegion",
611 "minimumSize",
612 "maximumSize",
613 "sizeIncrement",
614 "baseSize",
615 "ownPalette",
616 "ownFont",
617 "ownCursor",
618 "visibleRect",
619 "isActiveWindow",
620 "underMouse",
621 "visible",
622 "hidden",
623 "minimized",
624 "focus",
625 "focusEnabled",
626 "customWhatsThis",
627 "shown",
628 "windowOpacity",
629 0
630};
631
632// filter out some slots
633static const char* const ignore_slots[] =
634{
635 "deleteLater",
636 "setMouseTracking",
637 "update",
638 "repaint",
639 "iconify",
640 "showMinimized",
641 "showMaximized",
642 "showFullScreen",
643 "showNormal",
644 "polish",
645 "constPolish",
646 "stackUnder",
647 "setShown",
648 "setHidden",
649 "move_1",
650 "resize_1",
651 "setGeometry_1",
652 0
653};
654
655static bool ignore(const char *test, const char *const *table)
656{
657 if (!test)
658 return true;
659 int i = 0;
660 while (table[i]) {
661 if (!strcmp(test, table[i]))
662 return true;
663 ++i;
664 }
665 return false;
666}
667
668bool ignoreSlots(const char *test)
669{
670 return ignore(test, ignore_slots);
671}
672
673bool ignoreProps(const char *test)
674{
675 return ignore(test, ignore_props);
676}
677
678#define STRIPCB(x) x = x.mid(1, x.length()-2)
679
680static QByteArray prototype(const QList<QByteArray> &parameterTypes, const QList<QByteArray> &parameterNames, bool *ok)
681{
682 QByteArray prototype;
683
684 for (int p = 0; p < parameterTypes.count() && *ok; ++p) {
685 bool out = false;
686 QByteArray type(parameterTypes.at(p));
687 QByteArray name(parameterNames.at(p));
688
689 if (type.endsWith("&")) {
690 out = true;
691 type.truncate(type.length() - 1);
692 } else if (type.endsWith("**")) {
693 out = true;
694 type.truncate(type.length() - 1);
695 } else if (type.endsWith("*") && !subtypes.contains(type)) {
696 type.truncate(type.length() - 1);
697 }
698 if (type.isEmpty()) {
699 *ok = false;
700 break;
701 }
702 type = convertTypes(type, ok);
703 if (!out)
704 prototype += "[in] " + type + " ";
705 else
706 prototype += "[in,out] " + type + " ";
707
708 if (out)
709 prototype += "*";
710 if (name.isEmpty())
711 prototype += "p" + QByteArray::number(p);
712 else
713 prototype += "p_" + replaceKeyword(name);
714
715 if (p < parameterTypes.count() - 1)
716 prototype += ", ";
717 }
718
719 return prototype;
720}
721
722static QByteArray addDefaultArguments(const QByteArray &prototype, int numDefArgs)
723{
724 // nothing to do, or unsupported anyway
725 if (!numDefArgs || prototype.contains("/**"))
726 return prototype;
727
728 QByteArray ptype(prototype);
729 int in = -1;
730 while (numDefArgs) {
731 in = ptype.lastIndexOf("]", in);
732 ptype.replace(in, 1, ",optional]");
733 in = ptype.indexOf(' ', in) + 1;
734 QByteArray type = ptype.mid(in, ptype.indexOf(' ', in) - in);
735 if (type == "enum")
736 type += " " + ptype.mid(in + 5, ptype.indexOf(' ', in + 5) - in - 5);
737 ptype.replace(in, type.length(), QByteArray("VARIANT /*was: ") + type + "*/");
738 --numDefArgs;
739 }
740
741 return ptype;
742}
743
744static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out)
745{
746 int id = 1;
747 int i = 0;
748 if (!mo)
749 return 3;
750
751 QString topclass = qAxFactory()->exposeToSuperClass(className);
752 if (topclass.isEmpty())
753 topclass = QLatin1String("QObject");
754 bool hasStockEvents = qAxFactory()->hasStockEvents(className);
755
756 const QMetaObject *pmo = mo;
757 do {
758 pmo = pmo->superClass();
759 } while (pmo && topclass != QString::fromLatin1(pmo->className()));
760
761 int enumoff = pmo ? pmo->enumeratorOffset() : mo->enumeratorOffset();
762 int methodoff = pmo ? pmo->methodOffset() : mo->methodOffset();
763 int propoff = pmo ? pmo->propertyOffset() : mo->propertyOffset();
764
765 int qtProps = 0;
766 int qtSlots = 0;
767
768 bool control = false;
769
770 if (o && o->isWidgetType()) {
771 qtProps = QWidget::staticMetaObject.propertyCount();
772 qtSlots = QWidget::staticMetaObject.methodCount();
773 control = true;
774 }
775
776 QString classID = qAxFactory()->classID(className).toString().toUpper();
777 if (QUuid(classID).isNull())
778 return 4;
779 STRIPCB(classID);
780 QString interfaceID = qAxFactory()->interfaceID(className).toString().toUpper();
781 if (QUuid(interfaceID).isNull())
782 return 5;
783 STRIPCB(interfaceID);
784 QString eventsID = qAxFactory()->eventsID(className).toString().toUpper();
785 bool hasEvents = !QUuid(eventsID).isNull();
786 STRIPCB(eventsID);
787
788 QString cleanClassName = qax_clean_type(className, mo);
789 QString defProp(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultProperty")).value()));
790 QString defSignal(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultSignal")).value()));
791
792 for (i = enumoff; i < mo->enumeratorCount(); ++i) {
793 const QMetaEnum enumerator = mo->enumerator(i);
794 if (enums.contains(enumerator.name()))
795 continue;
796
797 enums.append(enumerator.name());
798
799 out << "\tenum " << enumerator.name() << " {" << endl;
800
801 for (int j = 0; j < enumerator.keyCount(); ++j) {
802 QByteArray key(enumerator.key(j));
803 while (enumValues.contains(key)) {
804 key += "_";
805 }
806 enumValues.append(key);
807 uint value = (uint)enumerator.value(j);
808 key = key.leftJustified(20);
809 out << "\t\t" << key << "\t= ";
810 if (enumerator.isFlag())
811 out << "0x" << QByteArray::number(value, 16).rightJustified(8, '0');
812 else
813 out << value;
814 if (j < enumerator.keyCount()-1)
815 out << ", ";
816 out << endl;
817 }
818 out << "\t};" << endl << endl;
819 }
820
821 // mouse cursor enum for QCursor support
822 if (!enums.contains("MousePointer")) {
823 enums.append("MousePointer");
824 out << "\tenum MousePointer {" << endl;
825 out << "\t\tArrowCursor = " << Qt::ArrowCursor << "," << endl;
826 out << "\t\tUpArrowCursor = " << Qt::UpArrowCursor << "," << endl;
827 out << "\t\tCrossCursor = " << Qt::CrossCursor << "," << endl;
828 out << "\t\tWaitCursor = " << Qt::WaitCursor << "," << endl;
829 out << "\t\tIBeamCursor = " << Qt::IBeamCursor << "," << endl;
830 out << "\t\tSizeVerCursor = " << Qt::SizeVerCursor << "," << endl;
831 out << "\t\tSizeHorCursor = " << Qt::SizeHorCursor << "," << endl;
832 out << "\t\tSizeBDiagCursor = " << Qt::SizeBDiagCursor << "," << endl;
833 out << "\t\tSizeFDiagCursor = " << Qt::SizeFDiagCursor << "," << endl;
834 out << "\t\tSizeAllCursor = " << Qt::SizeAllCursor << "," << endl;
835 out << "\t\tBlankCursor = " << Qt::BlankCursor << "," << endl;
836 out << "\t\tSplitVCursor = " << Qt::SplitVCursor << "," << endl;
837 out << "\t\tSplitHCursor = " << Qt::SplitHCursor << "," << endl;
838 out << "\t\tPointingHandCursor = " << Qt::PointingHandCursor << "," << endl;
839 out << "\t\tForbiddenCursor = " << Qt::ForbiddenCursor << "," << endl;
840 out << "\t\tWhatsThisCursor = " << Qt::WhatsThisCursor << "," << endl;
841 out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl;
842 out << "\t};" << endl << endl;
843 }
844 if (!enums.contains("FocusPolicy")) {
845 enums.append("FocusPolicy");
846 out << "\tenum FocusPolicy {" << endl;
847 out << "\t\tNoFocus = " << Qt::NoFocus << "," << endl;
848 out << "\t\tTabFocus = " << Qt::TabFocus << "," << endl;
849 out << "\t\tClickFocus = " << Qt::ClickFocus << "," << endl;
850 out << "\t\tStrongFocus = " << Qt::StrongFocus << "," << endl;
851 out << "\t\tWheelFocus = " << Qt::WheelFocus << endl;
852 out << "\t};" << endl << endl;
853 }
854
855 out << endl;
856 out << "\t[" << endl;
857 out << "\t\tuuid(" << interfaceID << ")," << endl;
858 out << "\t\thelpstring(\"" << cleanClassName << " Interface\")" << endl;
859 out << "\t]" << endl;
860 out << "\tdispinterface I" << cleanClassName << endl;
861 out << "\t{" << endl;
862
863 out << "\tproperties:" << endl;
864 for (i = propoff; i < mo->propertyCount(); ++i) {
865 const QMetaProperty property = mo->property(i);
866 /* if (property.testFlags(QMetaProperty::Override))
867 continue;*/
868 if (i <= qtProps && ignoreProps(property.name()))
869 continue;
870 if (!property.name() || mo->indexOfProperty(property.name()) > i)
871 continue;
872
873 bool ok = true;
874 QByteArray type(convertTypes(property.typeName(), &ok));
875 QByteArray name(replaceKeyword(property.name()));
876
877 if (!ok)
878 out << "\t/****** Property is of unsupported datatype" << endl;
879
880 out << "\t\t[id(" << id << ")";
881 if (!property.isWritable())
882 out << ", readonly";
883 if (isBindable && property.isScriptable(o))
884 out << ", bindable";
885 if (!property.isDesignable(o))
886 out << ", nonbrowsable";
887 if (isBindable)
888 out << ", requestedit";
889 if (defProp == QString::fromLatin1(name.constData()))
890 out << ", uidefault";
891 out << "] " << type << " " << name << ";" << endl;
892
893 if (!ok)
894 out << "\t******/" << endl;
895 ++id;
896 }
897 out << endl;
898 out << "\tmethods:" << endl;
899 int numDefArgs = 0;
900 QByteArray outBuffer;
901 for (i = methodoff; i < mo->methodCount(); ++i) {
902 const QMetaMethod slot = mo->method(i);
903 if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal)
904 continue;
905
906 if (slot.attributes() & QMetaMethod::Cloned) {
907 ++numDefArgs;
908 continue;
909 }
910 if (!outBuffer.isEmpty()) {
911 outBuffer = addDefaultArguments(outBuffer, numDefArgs);
912 numDefArgs = 0;
913 out << outBuffer;
914 outBuffer = QByteArray();
915 }
916
917 QByteArray signature(slot.signature());
918 QByteArray name(signature.left(signature.indexOf('(')));
919 if (i <= qtSlots && ignoreSlots(name))
920 continue;
921
922 signature = signature.mid(name.length() + 1);
923 signature.truncate(signature.length() - 1);
924 name = renameOverloads(replaceKeyword(name));
925 if (ignoreSlots(name))
926 continue;
927
928 QList<QByteArray> parameterTypes(slot.parameterTypes());
929 QList<QByteArray> parameterNames(slot.parameterNames());
930
931 bool ok = true;
932 QByteArray type = slot.typeName();
933 if (type.isEmpty())
934 type = "void";
935 else
936 type = convertTypes(type, &ok);
937
938 QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
939 if (!ok)
940 outBuffer += "\t/****** Slot parameter uses unsupported datatype\n";
941
942 outBuffer += "\t\t[id(" + QString::number(id).toLatin1() + ")] " + type + " " + name + "(" + ptype + ");\n";
943
944 if (!ok)
945 outBuffer += "\t******/\n";
946 ++id;
947 }
948 if (!outBuffer.isEmpty()) {
949 outBuffer = addDefaultArguments(outBuffer, numDefArgs);
950 numDefArgs = 0;
951 out << outBuffer;
952 outBuffer = QByteArray();
953 }
954 out << "\t};" << endl << endl;
955
956 mapping.clear();
957 id = 1;
958
959 if (hasEvents) {
960 out << "\t[" << endl;
961 out << "\t\tuuid(" << eventsID << ")," << endl;
962 out << "\t\thelpstring(\"" << cleanClassName << " Events Interface\")" << endl;
963 out << "\t]" << endl;
964 out << "\tdispinterface I" << cleanClassName << "Events" << endl;
965 out << "\t{" << endl;
966 out << "\tproperties:" << endl;
967 out << "\tmethods:" << endl;
968
969 if (hasStockEvents) {
970 out << "\t/****** Stock events ******/" << endl;
971 out << "\t\t[id(DISPID_CLICK)] void Click();" << endl;
972 out << "\t\t[id(DISPID_DBLCLICK)] void DblClick();" << endl;
973 out << "\t\t[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);" << endl;
974 out << "\t\t[id(DISPID_KEYPRESS)] void KeyPress(short* KeyAscii);" << endl;
975 out << "\t\t[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);" << endl;
976 out << "\t\t[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
977 out << "\t\t[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
978 out << "\t\t[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl << endl;
979 }
980
981 for (i = methodoff; i < mo->methodCount(); ++i) {
982 const QMetaMethod signal = mo->method(i);
983 if (signal.methodType() != QMetaMethod::Signal)
984 continue;
985
986 QByteArray signature(signal.signature());
987 QByteArray name(signature.left(signature.indexOf('(')));
988 signature = signature.mid(name.length() + 1);
989 signature.truncate(signature.length() - 1);
990
991 QList<QByteArray> parameterTypes(signal.parameterTypes());
992 QList<QByteArray> parameterNames(signal.parameterNames());
993
994 bool isDefault = defSignal == QString::fromLatin1(name.constData());
995 name = renameOverloads(replaceKeyword(name));
996 bool ok = true;
997
998 QByteArray type = signal.typeName();
999 if (!type.isEmpty()) // signals with return value not supported
1000 continue;
1001
1002 QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
1003 if (!ok)
1004 out << "\t/****** Signal parameter uses unsupported datatype" << endl;
1005
1006 out << "\t\t[id(" << id << ")";
1007 if (isDefault)
1008 out << ", uidefault";
1009 out << "] void " << name << "(" << ptype << ");" << endl;
1010
1011 if (!ok)
1012 out << "\t******/" << endl;
1013 ++id;
1014 }
1015 out << "\t};" << endl << endl;
1016 }
1017
1018 out << "\t[" << endl;
1019
1020 if (qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no"))
1021 out << "\t\taggregatable," << endl;
1022 if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes"))
1023 out << "\t\tappobject," << endl;
1024 if (mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value())
1025 out << "\t\tlicensed," << endl;
1026 const char *helpString = mo->classInfo(mo->indexOfClassInfo("Description")).value();
1027 if (helpString)
1028 out << "\t\thelpstring(\"" << helpString << "\")," << endl;
1029 else
1030 out << "\t\thelpstring(\"" << cleanClassName << " Class\")," << endl;
1031 const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value();
1032 if (classVersion)
1033 out << "\t\tversion(" << classVersion << ")," << endl;
1034 out << "\t\tuuid(" << classID << ")";
1035 if (control) {
1036 out << ", " << endl;
1037 out << "\t\tcontrol";
1038 } else if (!o) {
1039 out << ", " << endl;
1040 out << "\t\tnoncreatable";
1041 }
1042 out << endl;
1043 out << "\t]" << endl;
1044 out << "\tcoclass " << cleanClassName << endl;
1045 out << "\t{" << endl;
1046 out << "\t\t[default] dispinterface I" << cleanClassName << ";" << endl;
1047 if (hasEvents)
1048 out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl;
1049 out << "\t};" << endl;
1050
1051 return S_OK;
1052}
1053
1054#if defined(Q_CC_BOR)
1055extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver)
1056#else
1057extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
1058#endif
1059{
1060 qAxIsServer = false;
1061 QTextStream out;
1062 if (outfile.contains(QLatin1String("\\"))) {
1063 QString outpath = outfile.left(outfile.lastIndexOf(QLatin1String("\\")));
1064 QDir dir;
1065 dir.mkpath(outpath);
1066 }
1067 QFile file(outfile);
1068 file.remove();
1069
1070 QString filebase = QString::fromLocal8Bit(qAxModuleFilename);
1071 filebase = filebase.left(filebase.lastIndexOf(QLatin1String(".")));
1072
1073 QString appID = qAxFactory()->appID().toString().toUpper();
1074 if (QUuid(appID).isNull())
1075 return 1;
1076 STRIPCB(appID);
1077 QString typeLibID = qAxFactory()->typeLibID().toString().toUpper();
1078 if (QUuid(typeLibID).isNull())
1079 return 2;
1080 STRIPCB(typeLibID);
1081 QString typelib = filebase.right(filebase.length() - filebase.lastIndexOf(QLatin1String("\\"))-1);
1082
1083 if (!file.open(QIODevice::WriteOnly))
1084 return -1;
1085
1086 out.setDevice(&file);
1087
1088 QString version(ver.unicode(), ver.length());
1089 while (version.count(QLatin1Char('.')) > 1) {
1090 int lastdot = version.lastIndexOf(QLatin1Char('.'));
1091 version = version.left(lastdot) + version.right(version.length() - lastdot - 1);
1092 }
1093 if (version.isEmpty())
1094 version = QLatin1String("1.0");
1095
1096 QString idQRect(QUuid(CLSID_QRect).toString());
1097 STRIPCB(idQRect);
1098 QString idQSize(QUuid(CLSID_QSize).toString());
1099 STRIPCB(idQSize);
1100 QString idQPoint(QUuid(CLSID_QPoint).toString());
1101 STRIPCB(idQPoint);
1102
1103 out << "/****************************************************************************" << endl;
1104 out << "** Interface definition generated for ActiveQt project" << endl;
1105 out << "**" << endl;
1106 out << "** '" << qAxModuleFilename << "'" << endl;
1107 out << "**" << endl;
1108 out << "** Created: " << QDateTime::currentDateTime().toString() << endl;
1109 out << "**" << endl;
1110 out << "** WARNING! All changes made in this file will be lost!" << endl;
1111 out << "****************************************************************************/" << endl << endl;
1112
1113 out << "import \"ocidl.idl\";" << endl;
1114 out << "#include <olectl.h>" << endl << endl;
1115
1116 // dummy application to create widgets
1117 bool delete_qApp = false;
1118 if (!qApp) {
1119 int argc;
1120 (void)new QApplication(argc, 0);
1121 delete_qApp = true;
1122 }
1123
1124 out << "[" << endl;
1125 out << "\tuuid(" << typeLibID << ")," << endl;
1126 out << "\tversion(" << version << ")," << endl;
1127 out << "\thelpstring(\"" << typelib << " " << version << " Type Library\")" << endl;
1128 out << "]" << endl;
1129 out << "library " << typelib << "Lib" << endl;
1130 out << "{" << endl;
1131 out << "\timportlib(\"stdole32.tlb\");" << endl;
1132 out << "\timportlib(\"stdole2.tlb\");" << endl << endl;
1133
1134 QStringList keys = qAxFactory()->featureList();
1135 QStringList::ConstIterator key;
1136
1137 out << "\t/************************************************************************" << endl;
1138 out << "\t** If this causes a compile error in MIDL you need to upgrade the" << endl;
1139 out << "\t** Platform SDK you are using. Download the SDK from msdn.microsoft.com" << endl;
1140 out << "\t** and make sure that both the system and the Visual Studio environment" << endl;
1141 out << "\t** use the correct files." << endl;
1142 out << "\t**" << endl;
1143
1144#ifndef Q_CC_BOR
1145#if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
1146 out << "\t** Required version of MIDL could not be verified. QRect, QSize and QPoint" << endl;
1147 out << "\t** support needs an updated Platform SDK to be installed." << endl;
1148 out << "\t*************************************************************************" << endl;
1149#else
1150 out << "\t************************************************************************/" << endl;
1151#endif
1152
1153 out << endl;
1154 out << "\t[uuid(" << idQRect << ")]" << endl;
1155 out << "\tstruct QRect {" << endl;
1156 out << "\t\tint left;" << endl;
1157 out << "\t\tint top;" << endl;
1158 out << "\t\tint right;" << endl;
1159 out << "\t\tint bottom;" << endl;
1160 out << "\t};" << endl << endl;
1161
1162 out << "\t[uuid(" << idQSize << ")]" << endl;
1163 out << "\tstruct QSize {" << endl;
1164 out << "\t\tint width;" << endl;
1165 out << "\t\tint height;" << endl;
1166 out << "\t};" << endl << endl;
1167
1168 out << "\t[uuid(" << idQPoint << ")]" << endl;
1169 out << "\tstruct QPoint {" << endl;
1170 out << "\t\tint x;" << endl;
1171 out << "\t\tint y;" << endl;
1172 out << "\t};" << endl;
1173#if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
1174 out << "\t*/" << endl;
1175#endif
1176#else
1177 out << "\t** Custom data types not supported with Borland." << endl;
1178 out << "\t*************************************************************************" << endl;
1179#endif
1180 out << endl;
1181
1182 out << "\t/* Forward declaration of classes that might be used as parameters */" << endl << endl;
1183
1184 int res = S_OK;
1185 for (key = keys.begin(); key != keys.end(); ++key) {
1186 QByteArray className = (*key).toLatin1();
1187 const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
1188 // We have meta object information for this type. Forward declare it.
1189 if (mo) {
1190 QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
1191 out << "\tcoclass " << cleanType << ";" << endl;
1192 subtypes.append(cleanType);
1193 subtypes.append(cleanType + "*");
1194 qRegisterMetaType(cleanType, (void**)0);
1195 qRegisterMetaType(cleanType + "*", (void**)0);
1196 }
1197 }
1198 out << endl;
1199
1200 for (key = keys.begin(); key != keys.end(); ++key) {
1201 QByteArray className = (*key).toLatin1();
1202 const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
1203 // We have meta object information for this type. Define it.
1204 if (mo) {
1205 QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
1206 // It's not a control class, so it is actually a subtype. Define it.
1207 if (!o)
1208 res = classIDL(0, mo, QString::fromLatin1(className), false, out);
1209 delete o;
1210 }
1211 }
1212
1213 out << endl;
1214 if (res != S_OK)
1215 goto ErrorInClass;
1216
1217 for (key = keys.begin(); key != keys.end(); ++key) {
1218 QByteArray className = (*key).toLatin1();
1219 QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
1220 if (!o)
1221 continue;
1222 const QMetaObject *mo = o->metaObject();
1223 QAxBindable *bind = (QAxBindable*)o->qt_metacast("QAxBindable");
1224 bool isBindable = bind != 0;
1225
1226 QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
1227 subtypes.append(cleanType);
1228 subtypes.append(cleanType + "*");
1229 res = classIDL(o, mo, QString::fromLatin1(className.constData()), isBindable, out);
1230 delete o;
1231 if (res != S_OK)
1232 break;
1233 }
1234
1235 out << "};" << endl;
1236 out.flush();
1237
1238ErrorInClass:
1239 if (delete_qApp)
1240 delete qApp;
1241
1242 if (res != S_OK) {
1243 file.close();
1244 file.remove();
1245 }
1246
1247 return res;
1248}
1249
1250QT_END_NAMESPACE
1251#endif // QT_NO_WIN_ACTIVEQT
Note: See TracBrowser for help on using the repository browser.