summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Liu <net147@gmail.com>2011-11-07 20:40:13 +1100
committerQt by Nokia <qt-info@nokia.com>2012-02-20 11:38:57 +0100
commitb35de91c05f67da3b22f9f5b0d69530bb79b8797 (patch)
treed83eca78523fe4c26337411a34b1a6e2e565a555
parentbad8ed60958f476329e39c4a90575e786364cac8 (diff)
downloadqtactiveqt-b35de91c05f67da3b22f9f5b0d69530bb79b8797.tar.gz
ActiveQt: Add support for setting properties by reference
Add support for setting properties by reference to allow properties that can only be set by reference to be changed. Change-Id: I2f39f8720ecd1ba97139ab42756d686db2211cad Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
-rw-r--r--qtactiveqt.pro7
-rw-r--r--src/activeqt/container/qaxbase.cpp54
-rw-r--r--tests/auto/auto.pro3
-rw-r--r--tests/auto/qaxobject/qaxobject.pro3
-rw-r--r--tests/auto/qaxobject/tst_qaxobject.cpp77
-rw-r--r--tests/tests.pro2
6 files changed, 137 insertions, 9 deletions
diff --git a/qtactiveqt.pro b/qtactiveqt.pro
index 91317de..8fd1d20 100644
--- a/qtactiveqt.pro
+++ b/qtactiveqt.pro
@@ -3,6 +3,12 @@ TEMPLATE = subdirs
activeqt_src.subdir = $$IN_PWD/src
activeqt_src.target = sub-src
+activeqt_tests.subdir = $$IN_PWD/tests
+activeqt_tests.target = sub-tests
+activeqt_tests.depends = activeqt_src
+activeqt_tests.CONFIG = no_default_install
+!contains(QT_BUILD_PARTS,tests):activeqt_tests.CONFIG += no_default_target
+
activeqt_tools.subdir = $$IN_PWD/tools
activeqt_tools.target = sub-tools
activeqt_tools.depends = activeqt_src
@@ -13,6 +19,7 @@ activeqt_examples.depends = activeqt_src
win32 {
SUBDIRS = activeqt_src \
+ activeqt_tests \
activeqt_tools \
activeqt_examples
}
diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp
index f4ae696..9034ad6 100644
--- a/src/activeqt/container/qaxbase.cpp
+++ b/src/activeqt/container/qaxbase.cpp
@@ -68,6 +68,36 @@
QT_BEGIN_NAMESPACE
+static inline HRESULT Invoke(IDispatch *disp,
+ DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ DWORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ unsigned int *puArgErr)
+{
+ if ((wFlags & DISPATCH_PROPERTYPUT) &&
+ pDispParams &&
+ pDispParams->cArgs == 1 &&
+ pDispParams->cNamedArgs == 1 &&
+ pDispParams->rgdispidNamedArgs &&
+ *pDispParams->rgdispidNamedArgs == DISPID_PROPERTYPUT &&
+ pDispParams->rgvarg) {
+ VARTYPE vt = pDispParams->rgvarg->vt;
+
+ if (vt == VT_UNKNOWN || vt == VT_DISPATCH || (vt & VT_ARRAY) || (vt & VT_BYREF)) {
+ HRESULT hr = disp->Invoke(dispIdMember, riid, lcid, (wFlags & ~DISPATCH_PROPERTYPUT) | DISPATCH_PROPERTYPUTREF,
+ pDispParams, pVarResult, pExcepInfo, puArgErr);
+ if (SUCCEEDED(hr))
+ return hr;
+ }
+ }
+
+ return disp->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
/*
\internal
\class QAxMetaObject
@@ -2371,7 +2401,9 @@ QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *t
const QByteArray hresult("HRESULT");
// get function prototype
type = guessTypes(funcdesc->elemdescFunc.tdesc, typeinfo, function);
- if ((type.isEmpty() || type == hresult) && funcdesc->invkind == INVOKE_PROPERTYPUT && funcdesc->lprgelemdescParam) {
+ if ((type.isEmpty() || type == hresult) &&
+ (funcdesc->invkind == INVOKE_PROPERTYPUT || funcdesc->invkind == INVOKE_PROPERTYPUTREF) &&
+ funcdesc->lprgelemdescParam) {
type = guessTypes(funcdesc->lprgelemdescParam->tdesc, typeinfo, function);
}
@@ -2413,7 +2445,8 @@ QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *t
if (!prototype.isEmpty()) {
if (prototype.endsWith(',')) {
- if (funcdesc->invkind == INVOKE_PROPERTYPUT && p == funcdesc->cParams) {
+ if ((funcdesc->invkind == INVOKE_PROPERTYPUT || funcdesc->invkind == INVOKE_PROPERTYPUTREF) &&
+ p == funcdesc->cParams) {
TYPEDESC tdesc = funcdesc->lprgelemdescParam[p-1].tdesc;
QByteArray ptype = guessTypes(tdesc, typeinfo, function);
prototype += ptype;
@@ -2484,6 +2517,7 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
switch(funcdesc->invkind) {
case INVOKE_PROPERTYGET: // property
case INVOKE_PROPERTYPUT:
+ case INVOKE_PROPERTYPUTREF:
if (funcdesc->cParams - funcdesc->cParamsOpt <= 1) {
bool dontBreak = false;
// getter with non-default-parameters -> fall through to function handling
@@ -2526,11 +2560,13 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
break;
// generate setter slot
- if (funcdesc->invkind == INVOKE_PROPERTYPUT && hasProperty(function)) {
+ if ((funcdesc->invkind == INVOKE_PROPERTYPUT || funcdesc->invkind == INVOKE_PROPERTYPUTREF) &&
+ hasProperty(function)) {
addSetterSlot(function);
break;
}
- } else if (funcdesc->invkind == INVOKE_PROPERTYPUT && hasProperty(function)) {
+ } else if ((funcdesc->invkind == INVOKE_PROPERTYPUT || funcdesc->invkind == INVOKE_PROPERTYPUTREF) &&
+ hasProperty(function)) {
addSetterSlot(function);
// more parameters -> function handling
if (funcdesc->cParams > 1)
@@ -2539,7 +2575,7 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
if (!dontBreak)
break;
}
- if (funcdesc->invkind == INVOKE_PROPERTYPUT) {
+ if (funcdesc->invkind == INVOKE_PROPERTYPUT || funcdesc->invkind == INVOKE_PROPERTYPUTREF) {
// remove the typename guessed for property setters
// its done only for setter's with more than one parameter.
if (funcdesc->cParams - funcdesc->cParamsOpt > 1) {
@@ -3503,7 +3539,7 @@ int QAxBase::internalProperty(QMetaObject::Call call, int index, void **v)
params.rgdispidNamedArgs = 0;
params.rgvarg = 0;
- hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params, &arg, &excepinfo, 0);
+ hres = Invoke(disp, dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params, &arg, &excepinfo, 0);
// map result VARIANTARG to void*
uint type = QVariant::Int;
@@ -3549,7 +3585,7 @@ int QAxBase::internalProperty(QMetaObject::Call call, int index, void **v)
break;
}
}
- hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, 0, &excepinfo, &argerr);
+ hres = Invoke(disp, dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, 0, &excepinfo, &argerr);
clearVARIANT(&arg);
break;
@@ -3647,7 +3683,7 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v)
memset(&excepinfo, 0, sizeof(excepinfo));
WORD wFlags = isProperty ? DISPATCH_PROPERTYPUT : DISPATCH_METHOD | DISPATCH_PROPERTYGET;
- hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, wFlags, &params, &ret, &excepinfo, &argerr);
+ hres = Invoke(disp, dispid, IID_NULL, LOCALE_USER_DEFAULT, wFlags, &params, &ret, &excepinfo, &argerr);
// get return value
if (hres == S_OK && ret.vt != VT_EMPTY)
@@ -3947,7 +3983,7 @@ bool QAxBase::dynamicCallHelper(const char *name, void *inout, QList<QVariant> &
memset(&excepinfo, 0, sizeof(excepinfo));
UINT argerr = 0;
- HRESULT hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, disptype, &params, res, &excepinfo, &argerr);
+ HRESULT hres = Invoke(disp, dispid, IID_NULL, LOCALE_USER_DEFAULT, disptype, &params, res, &excepinfo, &argerr);
if (disptype == (DISPATCH_METHOD|DISPATCH_PROPERTYGET) && hres == S_OK && varc) {
for (int i = 0; i < varc; ++i)
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
new file mode 100644
index 0000000..8e3a63f
--- /dev/null
+++ b/tests/auto/auto.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS += \
+ qaxobject
diff --git a/tests/auto/qaxobject/qaxobject.pro b/tests/auto/qaxobject/qaxobject.pro
new file mode 100644
index 0000000..7e0fd69
--- /dev/null
+++ b/tests/auto/qaxobject/qaxobject.pro
@@ -0,0 +1,3 @@
+CONFIG += testcase qaxcontainer
+QT += testlib
+SOURCES += tst_qaxobject.cpp
diff --git a/tests/auto/qaxobject/tst_qaxobject.cpp b/tests/auto/qaxobject/tst_qaxobject.cpp
new file mode 100644
index 0000000..d0ad298
--- /dev/null
+++ b/tests/auto/qaxobject/tst_qaxobject.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QAxObject>
+#include <QByteArray>
+
+class tst_QAxObject : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void propertyByRefWritable();
+ void setPropertyByRef();
+};
+
+void tst_QAxObject::propertyByRefWritable()
+{
+ const QAxObject speak("SAPI.SPVoice");
+ const QMetaObject *metaObject = speak.metaObject();
+
+ for (int i = 0; i < metaObject->propertyCount(); ++i) {
+ if (qstrcmp(metaObject->property(i).name(), "Voice") == 0) {
+ QVERIFY(metaObject->property(i).isWritable());
+ break;
+ }
+ }
+}
+
+void tst_QAxObject::setPropertyByRef()
+{
+ QAxObject speak("SAPI.SPVoice");
+
+ QVERIFY(speak.setProperty("Voice", speak.property("Voice")));
+}
+
+QTEST_MAIN(tst_QAxObject)
+#include "tst_qaxobject.moc"
diff --git a/tests/tests.pro b/tests/tests.pro
new file mode 100644
index 0000000..157ef34
--- /dev/null
+++ b/tests/tests.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += auto