diff options
-rw-r--r-- | src/activeqt/container/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/activeqt/container/container.pro | 1 | ||||
-rw-r--r-- | src/activeqt/container/qaxbase.cpp | 301 | ||||
-rw-r--r-- | src/activeqt/container/qaxbase.h | 30 | ||||
-rw-r--r-- | src/activeqt/container/qaxbase_p.h | 12 | ||||
-rw-r--r-- | src/activeqt/container/qaxdump.cpp | 4 | ||||
-rw-r--r-- | src/activeqt/container/qaxobject.cpp | 146 | ||||
-rw-r--r-- | src/activeqt/container/qaxobject.h | 33 | ||||
-rw-r--r-- | src/activeqt/container/qaxobjectinterface.h | 75 | ||||
-rw-r--r-- | src/activeqt/container/qaxobjectinterface.qdoc | 112 | ||||
-rw-r--r-- | src/activeqt/container/qaxwidget.cpp | 188 | ||||
-rw-r--r-- | src/activeqt/container/qaxwidget.h | 30 | ||||
-rw-r--r-- | tools/dumpcpp/main.cpp | 2 | ||||
-rw-r--r-- | tools/testcon/invokemethod.cpp | 4 | ||||
-rw-r--r-- | tools/testcon/mainwindow.cpp | 14 |
15 files changed, 635 insertions, 318 deletions
diff --git a/src/activeqt/container/CMakeLists.txt b/src/activeqt/container/CMakeLists.txt index f9b72b4..ddb16d8 100644 --- a/src/activeqt/container/CMakeLists.txt +++ b/src/activeqt/container/CMakeLists.txt @@ -13,6 +13,7 @@ qt_add_module(AxContainer qaxbase.cpp qaxbase.h qaxbase_p.h qaxdump.cpp qaxobject.cpp qaxobject.h + qaxobjectinterface.h qaxscript.cpp qaxscript.h qaxscriptwrapper.cpp qaxselect.cpp qaxselect.h qaxselect.ui diff --git a/src/activeqt/container/container.pro b/src/activeqt/container/container.pro index 3606e87..a5cf33a 100644 --- a/src/activeqt/container/container.pro +++ b/src/activeqt/container/container.pro @@ -9,6 +9,7 @@ HEADERS = ../control/qaxaggregated.h \ qaxbase_p.h \ qaxwidget.h \ qaxobject.h \ + qaxobjectinterface.h \ qaxscript.h \ qaxselect.h \ ../shared/qaxtypes_p.h diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp index cb4893f..dc0a63d 100644 --- a/src/activeqt/container/qaxbase.cpp +++ b/src/activeqt/container/qaxbase.cpp @@ -387,21 +387,13 @@ public: if (qobject->signalsBlocked()) return S_OK; - const QMetaObject *meta = combase->metaObject(); + const QMetaObject *meta = combase->axBaseMetaObject(); const QMetaObjectExtra &moExtra = moextra_cache.value(meta); int index = -1; // emit the generic signal "as is" - if (signalHasReceivers(qobject, "signal(QString,int,void*)")) { - index = meta->indexOfSignal("signal(QString,int,void*)"); - Q_ASSERT(index != -1); - - QString nameString = QLatin1String(signame); - void *argv[] = {nullptr, &nameString, &pDispParams->cArgs, &pDispParams->rgvarg}; - QAxBase::qt_static_metacall(combase, QMetaObject::InvokeMetaMethod, - index - meta->methodOffset(), argv); - } - + combase->d->signalBridge->emitSignal(QLatin1String(signame), + pDispParams->cArgs, pDispParams->rgvarg); HRESULT hres = S_OK; // get the signal information from the metaobject @@ -472,7 +464,7 @@ public: if (ok) { // emit the generated signal if everything went well - QAxBase::qt_static_metacall(combase, QMetaObject::InvokeMetaMethod, index - meta->methodOffset(), argv); + QAxBase::axBase_qt_static_metacall(combase, QMetaObject::InvokeMetaMethod, index - meta->methodOffset(), argv); // update the VARIANT for references and free memory for (p = 0; p < pcount; ++p) { bool out; @@ -504,7 +496,7 @@ public: if (dispID == DISPID_UNKNOWN || !combase) return S_OK; - const QMetaObject *meta = combase->metaObject(); + const QMetaObject *meta = combase->axBaseMetaObject(); if (!meta) return S_OK; @@ -517,19 +509,13 @@ public: return S_OK; // emit the generic signal - int index = meta->indexOfSignal("propertyChanged(QString)"); - if (index != -1) { - QString propnameString = QString::fromLatin1(propname); - void *argv[] = {nullptr, &propnameString}; - QAxBase::qt_static_metacall(combase, QMetaObject::InvokeMetaMethod, - index - meta->methodOffset(), argv); - } + combase->d->signalBridge->emitPropertyChanged(QString::fromLatin1(propname)); QByteArray signame = propsigs.value(dispID); if (signame.isEmpty()) return S_OK; - index = meta->indexOfSignal(signame); + const int index = meta->indexOfSignal(signame); if (index == -1) // bindable but not marked as bindable in typelib return S_OK; @@ -546,8 +532,8 @@ public: argv[1] = &var; // emit the "changed" signal - QAxBase::qt_static_metacall(combase, QMetaObject::InvokeMetaMethod, - index - meta->methodOffset(), argv); + QAxBase::axBase_qt_static_metacall(combase, QMetaObject::InvokeMetaMethod, + index - meta->methodOffset(), argv); } return S_OK; } @@ -612,6 +598,7 @@ QAxBasePrivate::~QAxBasePrivate() } CoFreeUnusedLibraries(); + delete signalBridge; } QByteArray QAxEventSink::findProperty(DISPID dispID) @@ -637,7 +624,7 @@ QByteArray QAxEventSink::findProperty(DISPID dispID) typeinfo->Release(); QByteArray propsignal(propname + "Changed("); - const QMetaObject *mo = combase->metaObject(); + const QMetaObject *mo = combase->axBaseMetaObject(); int index = mo->indexOfProperty(propname); const QMetaProperty prop = mo->property(index); propsignal += prop.typeName(); @@ -894,60 +881,6 @@ void QAxBase::initializeFrom(QAxBase *that) } } -/*! - \property QAxBase::control - \brief the name of the COM object wrapped by this QAxBase object. - - Setting this property initializes the COM object. Any COM object - previously set is shut down. - - The most efficient way to set this property is by using the - registered component's UUID, e.g. - - \snippet src_activeqt_container_qaxbase.cpp 7 - - The second fastest way is to use the registered control's class - name (with or without version number), e.g. - - \snippet src_activeqt_container_qaxbase.cpp 8 - - The slowest, but easiest way to use is to use the control's full - name, e.g. - - \snippet src_activeqt_container_qaxbase.cpp 9 - - It is also possible to initialize the object from a file, e.g. - - \snippet src_activeqt_container_qaxbase.cpp 10 - - If the component's UUID is used the following patterns can be used - to initialize the control on a remote machine, to initialize a - licensed control or to connect to a running object: - \list - \li To initialize the control on a different machine use the following - pattern: - - \snippet src_activeqt_container_qaxbase.cpp 11 - - \li To initialize a licensed control use the following pattern: - - \snippet src_activeqt_container_qaxbase.cpp 12 - - \li To connect to an already running object use the following pattern: - - \snippet src_activeqt_container_qaxbase.cpp 13 - - \endlist - The first two patterns can be combined, e.g. to initialize a licensed - control on a remote machine: - - \snippet src_activeqt_container_qaxbase.cpp 14 - - The control's read function always returns the control's UUID, if provided including the license - key, and the name of the server, but not including the username, the domain or the password. - - \sa setClassContext() -*/ bool QAxBase::setControl(const QString &c) { if (!c.compare(d->ctrl, Qt::CaseInsensitive)) @@ -1029,7 +962,7 @@ void QAxBase::disableEventSink() \return the context the ActiveX control will run in (default CLSCTX_SERVER). */ -unsigned long QAxBase::classContext() const +ulong QAxBase::classContext() const { return d->classContext; } @@ -1047,7 +980,7 @@ unsigned long QAxBase::classContext() const Note that this function must be called before setControl() to have any effect. */ -void QAxBase::setClassContext(unsigned long classContext) +void QAxBase::setClassContext(ulong classContext) { d->classContext = classContext; } @@ -1185,7 +1118,7 @@ long QAxBase::indexOfVerb(const QString &verb) const if remote or licensed initialization fails, CoCreateInstance is used directly to create the object. - See the \l control property documentation for details about + See the \l QAxBaseWidget::control property documentation for details about supported patterns. The interface returned in \a ptr must be referenced exactly once @@ -1236,6 +1169,14 @@ bool QAxBase::initialize(IUnknown **ptr) } /*! + \internal +*/ +void QAxBase::axBaseInit(QAxBasePrivateSignalBridge *b) +{ + d->signalBridge = b; +} + +/*! Creates an instance of a licensed control, and returns the IUnknown interface to the object in \a ptr. This functions returns true if successful, otherwise returns false. @@ -1247,10 +1188,11 @@ bool QAxBase::initialize(IUnknown **ptr) */ bool QAxBase::initializeLicensed(IUnknown** ptr) { - int at = control().lastIndexOf(QLatin1String("}:")); + const QString ctl = control(); + int at = ctl.lastIndexOf(QLatin1String("}:")); - QString clsid(control().left(at)); - QString key(control().mid(at+2)); + QString clsid(ctl.left(at)); + QString key(ctl.mid(at+2)); IClassFactory *factory = nullptr; CoGetClassObject(QUuid(clsid), CLSCTX_SERVER, nullptr, IID_IClassFactory, @@ -1330,8 +1272,9 @@ bool QAxBase::initializeLicensedHelper(void *f, const QString &key, IUnknown **p */ bool QAxBase::initializeActive(IUnknown** ptr) { - int at = control().lastIndexOf(QLatin1String("}&")); - QString clsid(control().left(at)); + const QString ctl = control(); + int at = ctl.lastIndexOf(QLatin1String("}&")); + QString clsid(ctl.left(at)); GetActiveObject(QUuid(clsid), nullptr, ptr); @@ -1399,10 +1342,11 @@ static inline void setIdentityString(const QString &v, ULONG &length, USHORT *&t */ bool QAxBase::initializeRemote(IUnknown** ptr) { - int at = control().lastIndexOf(QLatin1String("/{")); + const QString ctl = control(); + int at = ctl.lastIndexOf(QLatin1String("/{")); - QString server(control().left(at)); - QString clsid(control().mid(at+1)); + QString server(ctl.left(at)); + QString clsid(ctl.mid(at+1)); QString user; QString domain; @@ -1482,7 +1426,7 @@ bool QAxBase::initializeRemote(IUnknown** ptr) Returns the result of the QueryInterface implementation of the COM object. - \sa control + \sa control() */ long QAxBase::queryInterface(const QUuid &uuid, void **iface) const { @@ -2945,20 +2889,6 @@ QMetaObject *MetaObjectGenerator::tryCache() return nullptr; } -static int nameToBuiltinType(const QByteArray &typeName) -{ - int id = QMetaType::type(typeName); - return (id < QMetaType::User) ? id : QMetaType::UnknownType; -} - -static uint nameToTypeInfo(const QByteArray &typeName, QMetaStringTable &strings) -{ - int id = nameToBuiltinType(typeName); - const int result = id != QMetaType::UnknownType - ? id : (IsUnresolvedType) | strings.enter(typeName); - return uint(result); -} - static void addMetaProperty(QMetaObjectBuilder &builder, const QByteArray &name, const QByteArray &type, uint flags) { @@ -3055,19 +2985,9 @@ QMetaObject *MetaObjectGenerator::metaObject(const QMetaObject *parentObject, co for (auto it = classinfo_list.cbegin(), cend = classinfo_list.cend(); it != cend; ++it) builder.addClassInfo(it.key(), it.value()); - // add each method. Signals must be added before other methods, to match moc. - addMetaMethod(builder, &QMetaObjectBuilder::addSignal, - "exception(int,QString,QString,QString)", "code,source,desc,help"); - addMetaMethod(builder, &QMetaObjectBuilder::addSignal, - "propertyChanged(QString)", "name"); - addMetaMethod(builder, &QMetaObjectBuilder::addSignal, - "signal(QString,int,void*)", "name,argc,argv"); buildMethods(signal_list, moExtra, builder, &QMetaObjectBuilder::addSignal); buildMethods(slot_list, moExtra, builder, &QMetaObjectBuilder::addSlot); - // each property - addMetaProperty(builder, "control", "QString", - Readable | Writable | Designable | Scriptable | Stored | Editable | StdCppSet); for (auto it = property_list.cbegin(), end = property_list.cend(); it != end; ++it) { const QByteArray &name = it.key(); const QByteArray &type = it.value().type; @@ -3108,31 +3028,6 @@ QMetaObject *MetaObjectGenerator::metaObject(const QMetaObject *parentObject, co return metaobj; } -#define QT_MOC_LITERAL(ofs, len) \ - uint(offsetof(qt_meta_stringdata_QAxBase_t, stringdata) + ofs), len - -const QAxBase::qt_meta_stringdata_QAxBase_t QAxBase::qt_meta_stringdata_QAxBase = { - { -QT_MOC_LITERAL(0, 7), -QT_MOC_LITERAL(8, 6), -QT_MOC_LITERAL(15, 0), -QT_MOC_LITERAL(16, 4), -QT_MOC_LITERAL(21, 4), -QT_MOC_LITERAL(26, 4), -QT_MOC_LITERAL(31, 15), -QT_MOC_LITERAL(47, 9), -QT_MOC_LITERAL(57, 4), -QT_MOC_LITERAL(62, 6), -QT_MOC_LITERAL(69, 4), -QT_MOC_LITERAL(74, 4), -QT_MOC_LITERAL(79, 7) - }, - "QAxBase\0signal\0\0name\0argc\0argv\0" - "propertyChanged\0exception\0code\0source\0" - "desc\0help\0control\0" -}; -#undef QT_MOC_LITERAL - /*! \fn const QMetaObject *QAxBase::fallbackMetaObject() const \internal @@ -3140,46 +3035,12 @@ QT_MOC_LITERAL(79, 7) /*! \internal - \class QAxBase::qt_meta_stringdata_QAxBase_t -*/ - -const uint QAxBase::qt_meta_data_QAxBase[] = { - - // content: - 7, // revision - 0, // classname - 0, 0, // classinfo - 3, 14, // methods - 1, 48, // properties - 0, 0, // enums/sets - 0, 0, // constructors - 0, // flags - 3, // signalCount - - // signals: name, argc, parameters, tag, flags - 1, 3, 29, 2, 0x05, - 6, 1, 36, 2, 0x05, - 7, 4, 39, 2, 0x05, - - // signals: parameters - QMetaType::Void, QMetaType::QString, QMetaType::Int, QMetaType::VoidStar, 3, 4, 5, - QMetaType::Void, QMetaType::QString, 3, - QMetaType::Void, QMetaType::Int, QMetaType::QString, QMetaType::QString, QMetaType::QString, 8, 9, 10, 11, - - // properties: name, type, flags - 12, QMetaType::QString, 0x00095000, - - 0 // eod -}; - -/*! - \internal The metaobject is generated on the fly from the information provided by the IDispatch and ITypeInfo interface implementations in the COM object. */ -const QMetaObject *QAxBase::metaObject() const +const QMetaObject *QAxBase::axBaseMetaObject() const { if (d->metaobj) return d->metaobj; @@ -3324,8 +3185,6 @@ void QAxBase::connectNotify() void QAxBasePrivate::handleException(tagEXCEPINFO *exc, const QString &name) { - const QMetaObject *mo = metaObject(); - const int exceptionSignal = mo->indexOfSignal("exception(int,QString,QString,QString)"); if (exc->pfnDeferredFillIn) exc->pfnDeferredFillIn(exc); int code = exc->wCode ? exc->wCode : exc->scode; @@ -3336,11 +3195,8 @@ void QAxBasePrivate::handleException(tagEXCEPINFO *exc, const QString &name) if (helpContext && !help.isEmpty()) help += QString::fromLatin1(" [%1]").arg(helpContext); - if (QAxEventSink::signalHasReceivers(q->qObject(), "exception(int,QString,QString,QString)")) { - void *argv[] = {nullptr, &code, &source, &desc, &help}; - QAxBase::qt_static_metacall(q, QMetaObject::InvokeMetaMethod, - exceptionSignal - mo->methodOffset(), argv); - } else { + signalBridge->emitException(code, source, desc, help); + if (!QAxEventSink::signalHasReceivers(q->qObject(), "exception(int,QString,QString,QString)")) { qWarning(R"(QAxBase: Error calling IDispatch member %s: Exception thrown by server Code : %d Source : %s @@ -3412,28 +3268,10 @@ bool QAxBasePrivate::checkHRESULT(HRESULT hres, EXCEPINFO *exc, const QString &n */ int QAxBase::internalProperty(QMetaObject::Call call, int index, void **v) { - const QMetaObject *mo = metaObject(); + const QMetaObject *mo = axBaseMetaObject(); const QMetaProperty prop = mo->property(index + mo->propertyOffset()); QByteArray propname = prop.name(); - // hardcoded control property - if (propname == "control") { - switch(call) { - case QMetaObject::ReadProperty: - *static_cast<QString*>(*v) = control(); - break; - case QMetaObject::WriteProperty: - setControl(*static_cast<const QString*>(*v)); - break; - case QMetaObject::ResetProperty: - clear(); - break; - default: - break; - } - return index - mo->propertyCount(); - } - // get the IDispatch if (!d->ptr || !prop.isValid()) return index; @@ -3534,7 +3372,7 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v) if (!disp) return index; - const QMetaObject *mo = metaObject(); + const QMetaObject *mo = axBaseMetaObject(); // get the slot information const QMetaMethod slot = mo->method(index + mo->methodOffset()); Q_ASSERT(slot.methodType() == QMetaMethod::Slot); @@ -3650,12 +3488,12 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v) /*! \internal */ -int QAxBase::qt_static_metacall(QAxBase *_t, QMetaObject::Call _c, int _id, void **_a) +int QAxBase::axBase_qt_static_metacall(QAxBase *_t, QMetaObject::Call _c, int _id, void **_a) { if (_c != QMetaObject::InvokeMetaMethod) return 0; Q_ASSERT(_t != nullptr); - const QMetaObject *mo = _t->metaObject(); + const QMetaObject *mo = _t->axBaseMetaObject(); switch (mo->method(_id + mo->methodOffset()).methodType()) { case QMetaMethod::Signal: QMetaObject::activate(_t->qObject(), mo, _id, _a); @@ -3672,9 +3510,9 @@ int QAxBase::qt_static_metacall(QAxBase *_t, QMetaObject::Call _c, int _id, void /*! \internal */ -int QAxBase::qt_metacall(QMetaObject::Call call, int id, void **v) +int QAxBase::axBase_qt_metacall(QMetaObject::Call call, int id, void **v) { - const QMetaObject *mo = metaObject(); + const QMetaObject *mo = axBaseMetaObject(); if (isNull() && mo->property(id + mo->propertyOffset()).name() != QByteArray("control")) { qWarning("QAxBase::qt_metacall: Object is not initialized, or initialization failed"); return id; @@ -3682,7 +3520,7 @@ int QAxBase::qt_metacall(QMetaObject::Call call, int id, void **v) switch(call) { case QMetaObject::InvokeMetaMethod: - id = qt_static_metacall(this, call, id, v); + id = axBase_qt_static_metacall(this, call, id, v); break; case QMetaObject::ReadProperty: case QMetaObject::WriteProperty: @@ -3706,7 +3544,7 @@ int QAxBase::qt_metacall(QMetaObject::Call call, int id, void **v) #ifdef QT_CHECK_STATE static void qax_noSuchFunction(int disptype, const QByteArray &name, const QByteArray &function, const QAxBase *that) { - const QMetaObject *metaObject = that->metaObject(); + const QMetaObject *metaObject = that->axBaseMetaObject(); const char *coclass = metaObject->classInfo(metaObject->indexOfClassInfo("CoClass")).value(); if (disptype == DISPATCH_METHOD) { @@ -3754,8 +3592,7 @@ bool QAxBase::dynamicCallHelper(const char *name, void *inout, QList<QVariant> & return false; } - const QMetaObject *mo = metaObject(); - d->metaObject(); + const QMetaObject *mo = axBaseMetaObject(); Q_ASSERT(d->metaobj); const QMetaObjectExtra &moExtra = moextra_cache.value(d->metaobj); @@ -4192,7 +4029,7 @@ QAxObject *QAxBase::querySubObject(const char *name, QList<QVariant> &vars) case VT_EMPTY: #ifdef QT_CHECK_STATE { - auto mo = metaObject(); + auto mo = axBaseMetaObject(); const char *coclass = mo->classInfo(mo->indexOfClassInfo("CoClass")).value(); qWarning("QAxBase::querySubObject: %s: Error calling function or property in %s (%s)" , name, control().toLatin1().data(), coclass ? coclass: "unknown"); @@ -4202,7 +4039,7 @@ QAxObject *QAxBase::querySubObject(const char *name, QList<QVariant> &vars) default: #ifdef QT_CHECK_STATE { - auto mo = metaObject(); + auto mo = axBaseMetaObject(); const char *coclass = mo->classInfo(mo->indexOfClassInfo("CoClass")).value(); qWarning("QAxBase::querySubObject: %s: Method or property is not of interface type in %s (%s)" , name, control().toLatin1().data(), coclass ? coclass: "unknown"); @@ -4309,7 +4146,7 @@ QAxBase::PropertyBag QAxBase::propertyBag() const persist->Release(); return result; } - const QMetaObject *mo = metaObject(); + const QMetaObject *mo = axBaseMetaObject(); for (int p = mo->propertyOffset(); p < mo->propertyCount(); ++p) { const QMetaProperty property = mo->property(p); QVariant var = qObject()->property(property.name()); @@ -4349,7 +4186,7 @@ void QAxBase::setPropertyBag(const PropertyBag &bag) pbag->Release(); persist->Release(); } else { - const QMetaObject *mo = metaObject(); + const QMetaObject *mo = axBaseMetaObject(); for (int p = mo->propertyOffset(); p < mo->propertyCount(); ++p) { const QMetaProperty property = mo->property(p); QVariant var = bag.value(QLatin1String(property.name())); @@ -4366,7 +4203,7 @@ void QAxBase::setPropertyBag(const PropertyBag &bag) Depending on the control implementation this setting might be ignored for some properties. - \sa setPropertyWritable(), propertyChanged() + \sa setPropertyWritable(), QAxBaseWidget::propertyChanged(), QAxBaseObject::propertyChanged() */ bool QAxBase::propertyWritable(const char *prop) const { @@ -4382,7 +4219,7 @@ bool QAxBase::propertyWritable(const char *prop) const Depending on the control implementation this setting might be ignored for some properties. - \sa propertyWritable(), propertyChanged() + \sa propertyWritable(), QAxBaseWidget::propertyChanged(), QAxBaseObject::propertyChanged() */ void QAxBase::setPropertyWritable(const char *prop, bool ok) { @@ -4393,7 +4230,7 @@ void QAxBase::setPropertyWritable(const char *prop, bool ok) Returns true if there is no COM object loaded by this wrapper; otherwise return false. - \sa control + \sa control() */ bool QAxBase::isNull() const { @@ -4450,38 +4287,6 @@ void *qax_createObjectWrapper(int metaType, IUnknown *iface) } /*! - \fn void QAxBase::signal(const QString &name, int argc, void *argv) - - This generic signal gets emitted when the COM object issues the - event \a name. \a argc is the number of parameters provided by the - event (DISPPARAMS.cArgs), and \a argv is the pointer to the - parameter values (DISPPARAMS.rgvarg). Note that the order of parameter - values is turned around, ie. the last element of the array is the first - parameter in the function. - - \snippet src_activeqt_container_qaxbase.cpp 20 - - Use this signal if the event has parameters of unsupported data - types. Otherwise, connect directly to the signal \a name. -*/ - -/*! - \fn void QAxBase::propertyChanged(const QString &name) - - If the COM object supports property notification, this signal gets - emitted when the property called \a name is changed. -*/ - -/*! - \fn void QAxBase::exception(int code, const QString &source, const QString &desc, const QString &help) - - This signal is emitted when the COM object throws an exception while called using the OLE automation - interface IDispatch. \a code, \a source, \a desc and \a help provide information about the exception as - provided by the COM server and can be used to provide useful feedback to the end user. \a help includes - the help file, and the help context ID in brackets, e.g. "filename [id]". -*/ - -/*! \fn QObject *QAxBase::qObject() const \internal */ diff --git a/src/activeqt/container/qaxbase.h b/src/activeqt/container/qaxbase.h index 049ee57..498e9ee 100644 --- a/src/activeqt/container/qaxbase.h +++ b/src/activeqt/container/qaxbase.h @@ -65,11 +65,10 @@ class QUuid; class QAxEventSink; class QAxObject; class QAxBasePrivate; +class QAxBasePrivateSignalBridge; class QAxBase { - QDOC_PROPERTY(QString control READ control WRITE setControl) - public: using PropertyBag = QMap<QString, QVariant>; @@ -99,9 +98,9 @@ public: const QVariant &v8 = QVariant()); QAxObject* querySubObject(const char *name, QList<QVariant> &vars); - virtual const QMetaObject *metaObject() const; - virtual int qt_metacall(QMetaObject::Call, int, void **); - static int qt_static_metacall(QAxBase *, QMetaObject::Call, int, void **); + const QMetaObject *axBaseMetaObject() const; + int axBase_qt_metacall(QMetaObject::Call, int, void **); + static int axBase_qt_static_metacall(QAxBase *, QMetaObject::Call, int, void **); virtual QObject *qObject() const = 0; virtual const char *className() const = 0; @@ -120,23 +119,16 @@ public: QVariant asVariant() const; -#ifdef Q_QDOC -Q_SIGNALS: - void signal(const QString&,int,void*); - void propertyChanged(const QString&); - void exception(int,const QString&,const QString&,const QString&); -#endif - public: - virtual void clear(); + void clear(); bool setControl(const QString&); void disableMetaObject(); void disableClassInfo(); void disableEventSink(); - unsigned long classContext() const; - void setClassContext(unsigned long classContext); + ulong classContext() const; + void setClassContext(ulong classContext); protected: virtual bool initialize(IUnknown** ptr); @@ -156,13 +148,7 @@ protected: const QVariant &var7, const QVariant &var8); virtual const QMetaObject *fallbackMetaObject() const = 0; - - struct qt_meta_stringdata_QAxBase_t { - const uint offsetsAndSize[26]; - char stringdata[88]; - }; - static const qt_meta_stringdata_QAxBase_t qt_meta_stringdata_QAxBase; - static const uint qt_meta_data_QAxBase[]; + void axBaseInit(QAxBasePrivateSignalBridge *b); private: enum DynamicCallHelperFlags { diff --git a/src/activeqt/container/qaxbase_p.h b/src/activeqt/container/qaxbase_p.h index fc347b7..d9c49cb 100644 --- a/src/activeqt/container/qaxbase_p.h +++ b/src/activeqt/container/qaxbase_p.h @@ -76,6 +76,17 @@ QT_BEGIN_NAMESPACE class QAxBase; class QAxEventSink; +class QAxBasePrivateSignalBridge +{ +public: + virtual ~QAxBasePrivateSignalBridge() = default; + + virtual void emitException(int code, const QString &source, const QString &desc, + const QString &help) = 0; + virtual void emitPropertyChanged(const QString &name) = 0; + virtual void emitSignal(const QString &name, int argc, void *argv) = 0; +}; + class QAxBasePrivate { Q_DISABLE_COPY_MOVE(QAxBasePrivate) @@ -124,6 +135,7 @@ public: mutable QMap<QString, LONG> verbs; QMetaObject *metaobj = nullptr; + QAxBasePrivateSignalBridge *signalBridge = nullptr; }; QT_END_NAMESPACE diff --git a/src/activeqt/container/qaxdump.cpp b/src/activeqt/container/qaxdump.cpp index 5adbb6a..98be9b6 100644 --- a/src/activeqt/container/qaxdump.cpp +++ b/src/activeqt/container/qaxdump.cpp @@ -139,7 +139,7 @@ static QByteArray toType(const QByteArray &t) QString qax_generateDocumentation(QAxBase *that) { - that->metaObject(); + that->axBaseMetaObject(); if (that->isNull()) return QString(); @@ -153,7 +153,7 @@ QString qax_generateDocumentation(QAxBase *that) QString docu; QTextStream stream(&docu, QIODevice::WriteOnly); - const QMetaObject *mo = that->metaObject(); + const QMetaObject *mo = that->axBaseMetaObject(); QString coClass = QLatin1String(mo->classInfo(mo->indexOfClassInfo("CoClass")).value()); stream << "<h1 align=center>" << coClass << " Reference</h1>" << Qt::endl; diff --git a/src/activeqt/container/qaxobject.cpp b/src/activeqt/container/qaxobject.cpp index 8f309b3..317f83b 100644 --- a/src/activeqt/container/qaxobject.cpp +++ b/src/activeqt/container/qaxobject.cpp @@ -49,6 +49,7 @@ ****************************************************************************/ #include "qaxobject.h" +#include "qaxbase_p.h" #include <quuid.h> #include <qmetaobject.h> @@ -58,6 +59,97 @@ QT_BEGIN_NAMESPACE +class QAxObjectSignalBridge : public QAxBasePrivateSignalBridge +{ +public: + explicit QAxObjectSignalBridge(QAxBaseObject *o) : m_o(o) {} + + void emitException(int code, const QString &source, const QString &desc, + const QString &help) override + { + emit m_o->exception(code, source, desc, help); + } + + void emitPropertyChanged(const QString &name) override + { + emit m_o->propertyChanged(name); + } + + void emitSignal(const QString &name, int argc, void *argv) override + { + emit m_o->signal(name, argc, argv); + } + +private: + QAxBaseObject *m_o; +}; + +/*! + \class QAxBaseObject + \brief QAxBaseObject provides static properties and signals for QAxObject. + \inmodule QAxContainer + \since 6.0 +*/ + +/*! + \property QAxBaseObject::classContext + \brief the context the ActiveX control will run in (default CLSCTX_SERVER). + + The property affects the "dwClsContext" argument when calling + CoCreateInstance. This can be used to control in-proc vs. out-of-proc + startup for controls supporting both alternatives. Also, it can be used to + modify/reduce control permissions when used with CLSCTX_ENABLE_CLOAKING + and an impersonation token. + + Note that it must be set before setControl() to have any effect. + \sa QAxBaseWidget::control +*/ + +/*! + \property QAxBaseObject::control + \brief the name of the COM object wrapped by this QAxBaseObject object. + + Setting this property initializes the COM object. Any COM object + previously set is shut down. + + The most efficient way to set this property is by using the + registered component's UUID, e.g. + \sa QAxBaseWidget::control, QAxBaseWidget::classContext +*/ + +/*! + \fn void QAxBaseObject::signal(const QString &name, int argc, void *argv) + + This generic signal gets emitted when the COM object issues the + event \a name. \a argc is the number of parameters provided by the + event (DISPPARAMS.cArgs), and \a argv is the pointer to the + parameter values (DISPPARAMS.rgvarg). Note that the order of parameter + values is turned around, ie. the last element of the array is the first + parameter in the function. + + \sa QAxBaseWidget::signal() +*/ + +/*! + \fn void QAxBaseObject::propertyChanged(const QString &name) + + If the COM object supports property notification, this signal gets + emitted when the property called \a name is changed. + + \sa QAxBaseWidget::propertyChanged() +*/ + +/*! + \fn void QAxBaseObject::exception(int code, const QString &source, const QString &desc, const QString &help) + + This signal is emitted when the COM object throws an exception while called using the OLE automation + interface IDispatch. \a code, \a source, \a desc and \a help provide information about the exception as + provided by the COM server and can be used to provide useful feedback to the end user. \a help includes + the help file, and the help context ID in brackets, e.g. "filename [id]". + + \sa QAxBaseWidget::exception() +*/ + /*! \class QAxObject \brief The QAxObject class provides a QObject that wraps a COM object. @@ -90,19 +182,14 @@ QT_BEGIN_NAMESPACE \sa QAxBase, QAxWidget, QAxScript, {ActiveQt Framework} */ -const QMetaObject QAxObject::staticMetaObject = { - { &QObject::staticMetaObject, qt_meta_stringdata_QAxBase.offsetsAndSize, - qt_meta_data_QAxBase, qt_static_metacall, nullptr, nullptr } -}; - /*! Creates an empty COM object and propagates \a parent to the - QObject constructor. To initialize the object, call \link - QAxBase::setControl() setControl \endlink. + QObject constructor. To initialize the object, call setControl(). */ QAxObject::QAxObject(QObject *parent) -: QObject(parent) +: QAxBaseObject(parent) { + axBaseInit(new QAxObjectSignalBridge(this)); } /*! @@ -112,8 +199,9 @@ QAxObject::QAxObject(QObject *parent) \sa setControl() */ QAxObject::QAxObject(const QString &c, QObject *parent) -: QObject(parent) +: QAxBaseObject(parent) { + axBaseInit(new QAxObjectSignalBridge(this)); setControl(c); } @@ -122,8 +210,9 @@ QAxObject::QAxObject(const QString &c, QObject *parent) iface. \a parent is propagated to the QObject constructor. */ QAxObject::QAxObject(IUnknown *iface, QObject *parent) -: QObject(parent), QAxBase(iface) +: QAxBaseObject(parent), QAxBase(iface) { + axBaseInit(new QAxObjectSignalBridge(this)); } /*! @@ -135,12 +224,37 @@ QAxObject::~QAxObject() clear(); } +unsigned long QAxObject::classContext() const +{ + return QAxBase::classContext(); +} + +void QAxObject::setClassContext(ulong classContext) +{ + QAxBase::setClassContext(classContext); +} + +QString QAxObject::control() const +{ + return QAxBase::control(); +} + +bool QAxObject::setControl(const QString &c) +{ + return QAxBase::setControl(c); +} + +void QAxObject::clear() +{ + QAxBase::clear(); +} + /*! \internal */ void QAxObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) { - QAxBase::qt_static_metacall(qobject_cast<QAxObject*>(_o), _c, _id, _a); + QAxBase::axBase_qt_static_metacall(static_cast<QAxObject *>(_o), _c, _id, _a); } /*! @@ -156,7 +270,7 @@ const QMetaObject *QAxObject::fallbackMetaObject() const */ const QMetaObject *QAxObject::metaObject() const { - return QAxBase::metaObject(); + return QAxBase::axBaseMetaObject(); } /*! @@ -164,7 +278,7 @@ const QMetaObject *QAxObject::metaObject() const */ const QMetaObject *QAxObject::parentMetaObject() const { - return &QObject::staticMetaObject; + return &QAxBaseObject::staticMetaObject; } /*! @@ -174,7 +288,7 @@ void *QAxObject::qt_metacast(const char *cname) { if (!qstrcmp(cname, "QAxObject")) return static_cast<void *>(this); if (!qstrcmp(cname, "QAxBase")) return static_cast<QAxBase *>(this); - return QObject::qt_metacast(cname); + return QAxBaseObject::qt_metacast(cname); } /*! @@ -190,10 +304,10 @@ const char *QAxObject::className() const */ int QAxObject::qt_metacall(QMetaObject::Call call, int id, void **v) { - id = QObject::qt_metacall(call, id, v); + id = QAxBaseObject::qt_metacall(call, id, v); if (id < 0) return id; - return QAxBase::qt_metacall(call, id, v); + return QAxBase::axBase_qt_metacall(call, id, v); } /*! diff --git a/src/activeqt/container/qaxobject.h b/src/activeqt/container/qaxobject.h index 049747c..56275c0 100644 --- a/src/activeqt/container/qaxobject.h +++ b/src/activeqt/container/qaxobject.h @@ -52,13 +52,30 @@ #define QAXOBJECT_H #include <QtAxContainer/qaxbase.h> +#include <QtAxContainer/qaxobjectinterface.h> QT_BEGIN_NAMESPACE -class QAxObject : public QObject, public QAxBase +class QAxBaseObject : public QObject, public QAxObjectInterface +{ + Q_OBJECT + Q_PROPERTY(ulong classContext READ classContext WRITE setClassContext) + Q_PROPERTY(QString control READ control WRITE setControl RESET clear) + +protected: + using QObject::QObject; + +public: + +Q_SIGNALS: + void exception(int code, const QString &source, const QString &desc, const QString &help); + void propertyChanged(const QString &name); + void signal(const QString &name, int argc, void *argv); +}; + +class QAxObject : public QAxBaseObject, public QAxBase { friend class QAxEventSink; - Q_OBJECT_FAKE public: QObject* qObject() const override { return static_cast<QObject *>(const_cast<QAxObject *>(this)); } const char *className() const override; @@ -68,8 +85,20 @@ public: explicit QAxObject(IUnknown *iface, QObject *parent = nullptr); ~QAxObject() override; + ulong classContext() const override; + void setClassContext(ulong classContext) override; + + QString control() const override; + bool setControl(const QString &c) override; + void clear() override; + bool doVerb(const QString &verb); + const QMetaObject *metaObject() const override; + int qt_metacall(QMetaObject::Call call, int id, void **v) override; + Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a); + void *qt_metacast(const char *) override; + protected: void connectNotify(const QMetaMethod &signal) override; const QMetaObject *fallbackMetaObject() const override; diff --git a/src/activeqt/container/qaxobjectinterface.h b/src/activeqt/container/qaxobjectinterface.h new file mode 100644 index 0000000..d6e7239 --- /dev/null +++ b/src/activeqt/container/qaxobjectinterface.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the ActiveQt framework of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QAXOBJECTINTERFACE_H +#define QAXOBJECTINTERFACE_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +class QString; + +class QAxObjectInterface +{ +public: + virtual ~QAxObjectInterface() = default; + + virtual ulong classContext() const = 0; + virtual void setClassContext(ulong classContext) = 0; + + virtual QString control() const = 0; + virtual void clear() = 0; + virtual bool setControl(const QString &c) = 0; +}; + +QT_END_NAMESPACE + +#endif // QAXOBJECTINTERFACE_H diff --git a/src/activeqt/container/qaxobjectinterface.qdoc b/src/activeqt/container/qaxobjectinterface.qdoc new file mode 100644 index 0000000..f9b2004 --- /dev/null +++ b/src/activeqt/container/qaxobjectinterface.qdoc @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the ActiveQt framework of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QAxObjectInterface + \brief QAxObjectInterface is an interface providing common properties of QAxObject and QAxWidget. + \inmodule QAxContainer + \since 6.0 +*/ + +/*! + \fn QAxObjectInterface::~QAxObjectInterface() + + Destroys the QAxObjectInterface. +*/ + +/*! + \fn virtual ulong QAxObjectInterface::classContext() const + + \return the context the ActiveX control will run in (default CLSCTX_SERVER). + + \sa QAxBaseWidget::classContext, QAxBaseObject::classContext +*/ + +/*! + \fn virtual void QAxObjectInterface::setClassContext(ulong classContext) + + Sets the context the ActiveX control will run in to \a classContext + + Affects the "dwClsContext" argument when calling CoCreateInstance. + This can be used to control in-proc vs. out-of-proc startup for controls + supporting both alternatives. Also, it can be used to modify/reduce control + permissions when used with CLSCTX_ENABLE_CLOAKING and an impersonation token. + + Note that this function must be called before setControl() to have any + effect. + + \sa QAxBaseWidget::classContext, QAxBaseObject::classContext +*/ + +/*! + \fn virtual QString QAxObjectInterface::control() const + + \return the name of the COM object wrapped by this QAxBase object. + + \sa QAxBaseWidget::control, QAxBaseObject::control +*/ + +/*! + \fn virtual bool QAxObjectInterface::setControl(const QString &c) + + \return whether setting the COM object succeeded. + + Sets the name of the COM object wrapped by this QAxBase object to \a c. + + \sa QAxBaseWidget::control, QAxBaseObject::control +*/ + +/*! + \fn virtual void QAxObjectInterface::clear() + + Disconnects and destroys the COM object. + + \sa QAxBaseWidget::control, QAxBaseObject::control +*/ diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index abc9948..4e2ca46 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -49,6 +49,7 @@ ****************************************************************************/ #include "qaxwidget.h" +#include "qaxbase_p.h" #include <QtAxBase/private/qaxutils_p.h> #include <QtAxBase/private/qaxtypefunctions_p.h> @@ -109,6 +110,31 @@ QT_BEGIN_NAMESPACE +class QAxWidgetSignalBridge : public QAxBasePrivateSignalBridge +{ +public: + explicit QAxWidgetSignalBridge(QAxBaseWidget *w) : m_w(w) {} + + void emitException(int code, const QString &source, const QString &desc, + const QString &help) override + { + emit m_w->exception(code, source, desc, help); + } + + void emitPropertyChanged(const QString &name) override + { + emit m_w->propertyChanged(name); + } + + void emitSignal(const QString &name, int argc, void *argv) override + { + emit m_w->signal(name, argc, argv); + } + +private: + QAxBaseWidget *m_w; +}; + /* \class QAxHostWidget \brief The QAxHostWidget class is the actual container widget. @@ -1873,6 +1899,120 @@ void QAxHostWidget::paintEvent(QPaintEvent*) } /*! + \class QAxBaseWidget + \brief QAxBaseWidget provides static properties and signals for QAxWidget. + \inmodule QAxContainer + \since 6.0 +*/ + +/*! + \property QAxBaseWidget::classContext + \brief the context the ActiveX control will run in (default CLSCTX_SERVER). + + The property affects the "dwClsContext" argument when calling + CoCreateInstance. This can be used to control in-proc vs. out-of-proc + startup for controls supporting both alternatives. Also, it can be used to + modify/reduce control permissions when used with CLSCTX_ENABLE_CLOAKING + and an impersonation token. + + Note that it must be set before setControl() to have any effect. + \sa control +*/ + +/*! + \property QAxBaseWidget::control + \brief the name of the COM object wrapped by this QAxBaseWidget object. + + Setting this property initializes the COM object. Any COM object + previously set is shut down. + + The most efficient way to set this property is by using the + registered component's UUID, e.g. + + \snippet src_activeqt_container_qaxbase.cpp 7 + + The second fastest way is to use the registered control's class + name (with or without version number), e.g. + + \snippet src_activeqt_container_qaxbase.cpp 8 + + The slowest, but easiest way to use is to use the control's full + name, e.g. + + \snippet src_activeqt_container_qaxbase.cpp 9 + + It is also possible to initialize the object from a file, e.g. + + \snippet src_activeqt_container_qaxbase.cpp 10 + + If the component's UUID is used the following patterns can be used + to initialize the control on a remote machine, to initialize a + licensed control or to connect to a running object: + \list + \li To initialize the control on a different machine use the following + pattern: + + \snippet src_activeqt_container_qaxbase.cpp 11 + + \li To initialize a licensed control use the following pattern: + + \snippet src_activeqt_container_qaxbase.cpp 12 + + \li To connect to an already running object use the following pattern: + + \snippet src_activeqt_container_qaxbase.cpp 13 + + \endlist + The first two patterns can be combined, e.g. to initialize a licensed + control on a remote machine: + + \snippet src_activeqt_container_qaxbase.cpp 14 + + The control's read function always returns the control's UUID, if provided including the license + key, and the name of the server, but not including the username, the domain or the password. + + \sa classContext +*/ + +/*! + \fn void QAxBaseWidget::signal(const QString &name, int argc, void *argv) + + This generic signal gets emitted when the COM object issues the + event \a name. \a argc is the number of parameters provided by the + event (DISPPARAMS.cArgs), and \a argv is the pointer to the + parameter values (DISPPARAMS.rgvarg). Note that the order of parameter + values is turned around, ie. the last element of the array is the first + parameter in the function. + + \snippet src_activeqt_container_qaxbase.cpp 20 + + Use this signal if the event has parameters of unsupported data + types. Otherwise, connect directly to the signal \a name. + + \sa QAxBaseObject::signal() +*/ + +/*! + \fn void QAxBaseWidget::propertyChanged(const QString &name) + + If the COM object supports property notification, this signal gets + emitted when the property called \a name is changed. + + \sa QAxBaseObject::propertyChanged() +*/ + +/*! + \fn void QAxBaseWidget::exception(int code, const QString &source, const QString &desc, const QString &help) + + This signal is emitted when the COM object throws an exception while called using the OLE automation + interface IDispatch. \a code, \a source, \a desc and \a help provide information about the exception as + provided by the COM server and can be used to provide useful feedback to the end user. \a help includes + the help file, and the help context ID in brackets, e.g. "filename [id]". + + \sa QAxBaseObject::exception() +*/ + +/*! \class QAxWidget \brief The QAxWidget class is a QWidget that wraps an ActiveX control. @@ -1914,19 +2054,15 @@ void QAxHostWidget::paintEvent(QPaintEvent*) \sa QAxBase, QAxObject, QAxScript, {ActiveQt Framework} */ -const QMetaObject QAxWidget::staticMetaObject = { - { &QWidget::staticMetaObject, qt_meta_stringdata_QAxBase.offsetsAndSize, - qt_meta_data_QAxBase, qt_static_metacall, nullptr, nullptr } -}; - /*! Creates an empty QAxWidget widget and propagates \a parent and \a f to the QWidget constructor. To initialize a control, call setControl(). */ QAxWidget::QAxWidget(QWidget *parent, Qt::WindowFlags f) -: QWidget(parent, f) +: QAxBaseWidget(parent, f) { + axBaseInit(new QAxWidgetSignalBridge(this)); } /*! @@ -1936,8 +2072,9 @@ QAxWidget::QAxWidget(QWidget *parent, Qt::WindowFlags f) \sa setControl() */ QAxWidget::QAxWidget(const QString &c, QWidget *parent, Qt::WindowFlags f) -: QWidget(parent, f) +: QAxBaseWidget(parent, f) { + axBaseInit(new QAxWidgetSignalBridge(this)); setControl(c); } @@ -1946,8 +2083,9 @@ QAxWidget::QAxWidget(const QString &c, QWidget *parent, Qt::WindowFlags f) \a parent and \a f are propagated to the QWidget contructor. */ QAxWidget::QAxWidget(IUnknown *iface, QWidget *parent, Qt::WindowFlags f) -: QWidget(parent, f), QAxBase(iface) +: QAxBaseWidget(parent, f), QAxBase(iface) { + axBaseInit(new QAxWidgetSignalBridge(this)); } /*! @@ -2043,6 +2181,26 @@ QAxAggregated *QAxWidget::createAggregate() return nullptr; } +ulong QAxWidget::classContext() const +{ + return QAxBase::classContext(); +} + +void QAxWidget::setClassContext(ulong classContext) +{ + QAxBase::setClassContext(classContext); +} + +QString QAxWidget::control() const +{ + return QAxBase::control(); +} + +bool QAxWidget::setControl(const QString &c) +{ + return QAxBase::setControl(c); +} + /*! \reimp @@ -2052,7 +2210,7 @@ void QAxWidget::clear() { if (isNull()) return; - if (!control().isEmpty()) { + if (!QAxBase::control().isEmpty()) { ATOM filter_ref = FindAtom(qaxatom); if (filter_ref) DeleteAtom(filter_ref); @@ -2102,7 +2260,7 @@ bool QAxWidget::doVerb(const QString &verb) */ void QAxWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) { - QAxBase::qt_static_metacall(qobject_cast<QAxWidget*>(_o), _c, _id, _a); + QAxBase::axBase_qt_static_metacall(static_cast<QAxWidget *>(_o), _c, _id, _a); } /*! @@ -2118,7 +2276,7 @@ const QMetaObject *QAxWidget::fallbackMetaObject() const */ const QMetaObject *QAxWidget::metaObject() const { - return QAxBase::metaObject(); + return QAxBase::axBaseMetaObject(); } /*! @@ -2126,7 +2284,7 @@ const QMetaObject *QAxWidget::metaObject() const */ const QMetaObject *QAxWidget::parentMetaObject() const { - return &QWidget::staticMetaObject; + return &QAxBaseWidget::staticMetaObject; } /*! @@ -2136,7 +2294,7 @@ void *QAxWidget::qt_metacast(const char *cname) { if (!qstrcmp(cname, "QAxWidget")) return static_cast<void *>(this); if (!qstrcmp(cname, "QAxBase")) return static_cast<QAxBase *>(this); - return QWidget::qt_metacast(cname); + return QAxBaseWidget::qt_metacast(cname); } /*! @@ -2152,10 +2310,10 @@ const char *QAxWidget::className() const */ int QAxWidget::qt_metacall(QMetaObject::Call call, int id, void **v) { - id = QWidget::qt_metacall(call, id, v); + id = QAxBaseWidget::qt_metacall(call, id, v); if (id < 0) return id; - return QAxBase::qt_metacall(call, id, v); + return QAxBase::axBase_qt_metacall(call, id, v); } /*! diff --git a/src/activeqt/container/qaxwidget.h b/src/activeqt/container/qaxwidget.h index 2bcf3c7..a161246 100644 --- a/src/activeqt/container/qaxwidget.h +++ b/src/activeqt/container/qaxwidget.h @@ -52,6 +52,7 @@ #define QAXWIDGET_H #include <QtAxContainer/qaxbase.h> +#include <QtAxContainer/qaxobjectinterface.h> #include <QtWidgets/qwidget.h> QT_BEGIN_NAMESPACE @@ -62,9 +63,24 @@ class QAxAggregated; class QAxClientSite; class QAxWidgetPrivate; -class QAxWidget : public QWidget, public QAxBase +class QAxBaseWidget : public QWidget, public QAxObjectInterface +{ + Q_OBJECT + Q_PROPERTY(ulong classContext READ classContext WRITE setClassContext) + Q_PROPERTY(QString control READ control WRITE setControl RESET clear) +protected: + using QWidget::QWidget; + +public: + +Q_SIGNALS: + void exception(int code, const QString &source, const QString &desc, const QString &help); + void propertyChanged(const QString &name); + void signal(const QString &name, int argc, void *argv); +}; + +class QAxWidget : public QAxBaseWidget, public QAxBase { - Q_OBJECT_FAKE public: QObject* qObject() const override { return const_cast<QAxWidget *>(this); } const char *className() const override; @@ -74,6 +90,11 @@ public: explicit QAxWidget(IUnknown *iface, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); ~QAxWidget() override; + ulong classContext() const override; + void setClassContext(ulong classContext) override; + + QString control() const override; + bool setControl(const QString &) override; void clear() override; bool doVerb(const QString &verb); @@ -82,6 +103,11 @@ public: virtual QAxAggregated *createAggregate(); + const QMetaObject *metaObject() const override; + int qt_metacall(QMetaObject::Call call, int id, void **v) override; + Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a); + void *qt_metacast(const char *) override; + protected: bool initialize(IUnknown **) override; virtual bool createHostWindow(bool); diff --git a/tools/dumpcpp/main.cpp b/tools/dumpcpp/main.cpp index d50c65d..baabdb4 100644 --- a/tools/dumpcpp/main.cpp +++ b/tools/dumpcpp/main.cpp @@ -272,7 +272,7 @@ void generateClassDecl(QTextStream &out, const QMetaObject *mo, continue; QByteArray propertyName(property.name()); - if (propertyName == "control" || propertyName == className) + if (propertyName == className) continue; if (!(category & OnlyInlines)) { diff --git a/tools/testcon/invokemethod.cpp b/tools/testcon/invokemethod.cpp index 32021ea..1651537 100644 --- a/tools/testcon/invokemethod.cpp +++ b/tools/testcon/invokemethod.cpp @@ -68,7 +68,7 @@ void InvokeMethod::setControl(QAxBase *ax) return; } - const QMetaObject *mo = activex->metaObject(); + const QMetaObject *mo = activex->axBaseMetaObject(); if (mo->methodCount()) { for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) { const QMetaMethod method = mo->method(i); @@ -113,7 +113,7 @@ void InvokeMethod::on_comboMethods_textActivated(const QString &method) return; listParameters->clear(); - const QMetaObject *mo = activex->metaObject(); + const QMetaObject *mo = activex->axBaseMetaObject(); const QMetaMethod slot = mo->method(mo->indexOfSlot(method.toLatin1())); QString signature = QString::fromLatin1(slot.methodSignature()); signature.remove(0, signature.indexOf(QLatin1Char('(')) + 1); diff --git a/tools/testcon/mainwindow.cpp b/tools/testcon/mainwindow.cpp index 7bcc483..00a33a4 100644 --- a/tools/testcon/mainwindow.cpp +++ b/tools/testcon/mainwindow.cpp @@ -549,17 +549,15 @@ void MainWindow::updateGUI() const auto axw = axWidgets(); for (QAxWidget *container : axw) { - container->disconnect(SIGNAL(signal(QString,int,void*))); + disconnect(container, &QAxWidget::signal, this, nullptr); if (actionLogSignals->isChecked()) - connect(container, SIGNAL(signal(QString,int,void*)), this, SLOT(logSignal(QString,int,void*))); + connect(container, &QAxWidget::signal, this, &MainWindow::logSignal); + disconnect(container, &QAxWidget::exception, this, nullptr); + connect(container, &QAxWidget::exception, this, &MainWindow::logException); - container->disconnect(SIGNAL(exception(int,QString,QString,QString))); - connect(container, SIGNAL(exception(int,QString,QString,QString)), - this, SLOT(logException(int,QString,QString,QString))); - - container->disconnect(SIGNAL(propertyChanged(QString))); + disconnect(container, &QAxWidget::propertyChanged, this, nullptr); if (actionLogProperties->isChecked()) - connect(container, SIGNAL(propertyChanged(QString)), this, SLOT(logPropertyChanged(QString))); + connect(container, &QAxWidget::propertyChanged, this, &MainWindow::logPropertyChanged); container->blockSignals(actionFreezeEvents->isChecked()); } } |