[PyKDE] PyQt ActiveX support: can't pass some types of parameters
Mike Thompson
mike.spam.filter at day8.com.au
Tue Oct 12 00:53:17 BST 2004
I'm trying to manipulate ActiveX objects using pyQt, but I've hit the
following brick wall:
Methods on ActiveX objects can only be called with parameters that
can be wrapped by QVariant. Which is a show-stopper of an issue
unless there is a work around.
You can call methods (on activeX objects) with parameters which are
strings, ints and dates - they are all wrapable by QVariant - but you
can't pass one ActiveX object to another's method as a parameter because
QVariant can't wrap a QaxObject.
To demonstrate what I'm struggling with, consider the following python
code fragment written in terms of Mark Hammond's semi-official
'win32com' package (http://www.python.org/windows/win32com/)
#-----------------------------------------------------------------------
# Try to initialise a 'RecordSet' (represents rows in a database table)
# from an in-memory xml document which specifies table schema and some
# rows.
# Both 'ReacordSet' and 'Stream' are stock-standard ActiveX components
# from Microsoft.
#
import win32com.client # http://www.python.org/windows/win32com/
# real string content omitted because its large and complicated
aStringWhichContinsXmlInRightFormat = "..."
# STEP 1: create and initialise the Stream object, so it
# contains the xml document.
streamObj = win32com.client.Dispatch("ADODB.Stream")
streamObj.Open()
streamObj.WriteText(aStringWhichContinsXmlInRightFormat)
streamObj.Position = 0
# STEP 2: create and intialise a RecordSet object
# from the xml document in the stream object.
#
recordSetObj = win32com.client.Dispatch("ADODB.Recordset")
recordSetObj.Open(streamObj) # XXXXXXX note: object parameter
# print out what's in the RecordSet
while not recordSetObj.EOF:
strFieldValues = [str(f) for f in recordSetObj.Fields]
print "\t".join(strFieldValues)
recordSetObj.MoveNext()
#-----------------------------------------------------------------------
This win32com-based code works well enough.
My attempt to emulate this code with pyQt looks like this ....
#-----------------------------------------------------------------------
import qt
import qtaxcontainer
# STEP 1: create and initialise the Stream object, so it
# contains the xml document.
#
streamObj = qtaxcontainer.QAxObject("ADODB.Stream")
streamObj.dynamicCall( "Open()" );
streamObj.dynamicCall( "WriteText(QString&)",
qt.QVariant(aStringWhichContinsXmlInRightFormat) );
streamObj.dynamicCall( "SetPosition(int)", qt.QVariant(0) );
# STEP 2: create and intialise a RecordSet object
# from the xml document in the stream object.
#
recordSetObj = qtaxcontainer.QAxObject("ADODB.Recordset")
paramObj = qt.QVariant(streamObj) # YYYYYYYYY
recordSetObj.dynamicCall( "Open(IDispatch*)", paramObj);
#.... haven't tried to emulate the win32com final loop yet
#-----------------------------------------------------------------------
This script fails on the line marked YYYYYYY with the error:
TypeError: too many arguments to QVariant(), 0 at most expected
which is because QVariant can't wrap 'streamObj' which is a QAxObject.
Am I missing something about ActiveX method calls? Is there a work
around? It seems to mne that Qt MUST provide this sort of functionality
if its serious about ActiveX support, but I've had a look into the Qt
documentation and it simply acknowledges the issue - but there's no
solution.
Why do I need this? Why not just use win32com? Well, I need the
occasional ActiveX component in the pyQt GUI's I build, which means
I need to manipulate QAxObjects.
Solutions:
1. Obvious: find a way to pass one QAxObject to another's
method.
2. Perhaps: find a way to grab the "IDispatch*" out of the
QAxObject and then wrap it in win32com. (This is stretching
my thin ActiveX understanding).
3. other?
--
Mike
BTW, in the interests of suppling all the code, here is the full
definition of 'aStringWhichContinsXmlInRightFormat' which I omitted
from the code fragments.
aStringWhichContinsXmlInRightFormat="""<xml
xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
<s:ElementType name='row' content='eltOnly'>
<s:AttributeType name='CustomerID' rs:number='1' rs:nullable='true'
rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='string' dt:maxLength='5'/>
</s:AttributeType>
<s:AttributeType name='Company' rs:number='2' rs:nullable='true'
rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='string' dt:maxLength='40'/>
</s:AttributeType>
<s:AttributeType name='ContactName' rs:number='3' rs:nullable='true'
rs:maydefer='true' rs:writeunknown='true'>
<s:datatype dt:type='string' dt:maxLength='30'/>
</s:AttributeType>
<s:extends type='rs:rowbase'/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row CustomerID='ALFKI' Company='Alfreds' ContactName='Maria Anders' />
<z:row CustomerID='AROUT' Company='Horn Inc' ContactName='Thomas Hardy' />
<z:row CustomerID='BLAUS' Company='Delikates' ContactName='Hanna Moos' />
<z:row CustomerID='BOTTM' Company='Dollar Markets' ContactName='Eliz
Lincoln' />
<z:row CustomerID='WILMK' Company='Wilman Kala' ContactName='Matti Kart'/>
<z:row CustomerID='WOLZA' Company='Wolski Zajazd' ContactName='Zbyszek
Piest' />
</rs:data>
</xml>
"""
More information about the PyQt
mailing list