summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit41c8d3db370a2f26644303e797ba5bc63e98d760 (patch)
treed9b8b9b55ae4a129923e685b2f0765e4cf9c02ac
downloadqtactiveqt-41c8d3db370a2f26644303e797ba5bc63e98d760.tar.gz
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
-rw-r--r--doc/src/activeqt-container.qdoc205
-rw-r--r--doc/src/activeqt-server.qdoc837
-rw-r--r--doc/src/activeqt.qdoc94
-rw-r--r--doc/src/examples/comapp.qdoc110
-rw-r--r--doc/src/examples/dotnet.qdoc341
-rw-r--r--doc/src/examples/hierarchy-demo-snippet.qdoc68
-rw-r--r--doc/src/examples/hierarchy-demo.qdocinc41
-rw-r--r--doc/src/examples/hierarchy.qdoc88
-rw-r--r--doc/src/examples/menus.qdoc60
-rw-r--r--doc/src/examples/multiple-demo.qdocinc39
-rw-r--r--doc/src/examples/multiple.qdoc70
-rw-r--r--doc/src/examples/opengl-demo.qdocinc27
-rw-r--r--doc/src/examples/opengl.qdoc131
-rw-r--r--doc/src/examples/qutlook.qdoc102
-rw-r--r--doc/src/examples/simple-demo.qdocinc45
-rw-r--r--doc/src/examples/simple.qdoc116
-rw-r--r--doc/src/examples/webbrowser.qdoc73
-rw-r--r--doc/src/examples/wrapper-demo.qdocinc51
-rw-r--r--doc/src/examples/wrapper.qdoc63
-rw-r--r--doc/src/snippets/code/doc_src_examples_activeqt_comapp.qdoc79
-rw-r--r--doc/src/snippets/code/doc_src_examples_activeqt_dotnet.qdoc44
-rw-r--r--doc/src/snippets/code/doc_src_examples_activeqt_menus.qdoc46
-rw-r--r--doc/src/snippets/code/doc_src_qaxcontainer.pro48
-rw-r--r--doc/src/snippets/code/doc_src_qaxserver.cpp218
-rw-r--r--doc/src/snippets/code/doc_src_qaxserver.pro64
-rw-r--r--doc/src/snippets/code/doc_src_qaxserver.qdoc57
-rw-r--r--doc/src/snippets/code/src_activeqt_container_qaxbase.cpp199
-rw-r--r--doc/src/snippets/code/src_activeqt_container_qaxscript.cpp58
-rw-r--r--doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp100
-rw-r--r--doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp195
-rw-r--r--examples/activeqt/README39
-rw-r--r--examples/activeqt/activeqt.pro20
-rw-r--r--examples/activeqt/comapp/comapp.pro13
-rw-r--r--examples/activeqt/comapp/comapp.rc1
-rw-r--r--examples/activeqt/comapp/main.cpp271
-rw-r--r--examples/activeqt/dotnet/walkthrough/Form1.cs127
-rw-r--r--examples/activeqt/dotnet/walkthrough/Form1.resx131
-rw-r--r--examples/activeqt/dotnet/walkthrough/Form1.vb88
-rw-r--r--examples/activeqt/dotnet/walkthrough/csharp.csproj143
-rw-r--r--examples/activeqt/dotnet/walkthrough/vb.vbproj147
-rw-r--r--examples/activeqt/dotnet/wrapper/app.csproj93
-rw-r--r--examples/activeqt/dotnet/wrapper/lib/lib.vcproj149
-rw-r--r--examples/activeqt/dotnet/wrapper/lib/networker.cpp69
-rw-r--r--examples/activeqt/dotnet/wrapper/lib/networker.h66
-rw-r--r--examples/activeqt/dotnet/wrapper/lib/tools.cpp60
-rw-r--r--examples/activeqt/dotnet/wrapper/lib/tools.h53
-rw-r--r--examples/activeqt/dotnet/wrapper/lib/worker.cpp58
-rw-r--r--examples/activeqt/dotnet/wrapper/lib/worker.h68
-rw-r--r--examples/activeqt/dotnet/wrapper/main.cs40
-rw-r--r--examples/activeqt/dotnet/wrapper/wrapper.sln28
-rw-r--r--examples/activeqt/hierarchy/hierarchy.inf9
-rw-r--r--examples/activeqt/hierarchy/hierarchy.pro16
-rw-r--r--examples/activeqt/hierarchy/main.cpp49
-rw-r--r--examples/activeqt/hierarchy/objects.cpp107
-rw-r--r--examples/activeqt/hierarchy/objects.h99
-rw-r--r--examples/activeqt/menus/fileopen.xpm22
-rw-r--r--examples/activeqt/menus/filesave.xpm22
-rw-r--r--examples/activeqt/menus/main.cpp63
-rw-r--r--examples/activeqt/menus/menus.cpp177
-rw-r--r--examples/activeqt/menus/menus.h75
-rw-r--r--examples/activeqt/menus/menus.inf9
-rw-r--r--examples/activeqt/menus/menus.pro14
-rw-r--r--examples/activeqt/multiple/ax1.h86
-rw-r--r--examples/activeqt/multiple/ax2.h93
-rw-r--r--examples/activeqt/multiple/main.cpp52
-rw-r--r--examples/activeqt/multiple/multiple.inf9
-rw-r--r--examples/activeqt/multiple/multiple.pro16
-rw-r--r--examples/activeqt/multiple/multipleax.rc32
-rw-r--r--examples/activeqt/opengl/glbox.cpp249
-rw-r--r--examples/activeqt/opengl/glbox.h89
-rw-r--r--examples/activeqt/opengl/globjwin.cpp110
-rw-r--r--examples/activeqt/opengl/globjwin.h61
-rw-r--r--examples/activeqt/opengl/main.cpp90
-rw-r--r--examples/activeqt/opengl/opengl.inf9
-rw-r--r--examples/activeqt/opengl/opengl.pro19
-rw-r--r--examples/activeqt/qutlook/addressview.cpp288
-rw-r--r--examples/activeqt/qutlook/addressview.h78
-rw-r--r--examples/activeqt/qutlook/fileopen.xpm22
-rw-r--r--examples/activeqt/qutlook/fileprint.xpm24
-rw-r--r--examples/activeqt/qutlook/filesave.xpm22
-rw-r--r--examples/activeqt/qutlook/main.cpp55
-rw-r--r--examples/activeqt/qutlook/qutlook.pro23
-rw-r--r--examples/activeqt/simple/main.cpp136
-rw-r--r--examples/activeqt/simple/simple.inf11
-rw-r--r--examples/activeqt/simple/simple.pro13
-rw-r--r--examples/activeqt/webbrowser/main.cpp188
-rw-r--r--examples/activeqt/webbrowser/mainwindow.ui306
-rw-r--r--examples/activeqt/webbrowser/mainwindow_windowsmobile.ui299
-rw-r--r--examples/activeqt/webbrowser/webaxwidget.h66
-rw-r--r--examples/activeqt/webbrowser/webbrowser.pro17
-rw-r--r--examples/activeqt/wrapper/main.cpp160
-rw-r--r--examples/activeqt/wrapper/wrapper.inf9
-rw-r--r--examples/activeqt/wrapper/wrapper.pro15
-rw-r--r--examples/activeqt/wrapper/wrapperax.rc32
-rw-r--r--examples/examples.pro2
-rw-r--r--src/activeqt/activeqt.pro5
-rw-r--r--src/activeqt/container/container.pro41
-rw-r--r--src/activeqt/container/qaxbase.cpp4472
-rw-r--r--src/activeqt/container/qaxbase.h227
-rw-r--r--src/activeqt/container/qaxdump.cpp405
-rw-r--r--src/activeqt/container/qaxobject.cpp210
-rw-r--r--src/activeqt/container/qaxobject.h106
-rw-r--r--src/activeqt/container/qaxscript.cpp1290
-rw-r--r--src/activeqt/container/qaxscript.h249
-rw-r--r--src/activeqt/container/qaxscriptwrapper.cpp65
-rw-r--r--src/activeqt/container/qaxselect.cpp157
-rw-r--r--src/activeqt/container/qaxselect.h76
-rw-r--r--src/activeqt/container/qaxselect.ui174
-rw-r--r--src/activeqt/container/qaxwidget.cpp2257
-rw-r--r--src/activeqt/container/qaxwidget.h126
-rw-r--r--src/activeqt/control/control.pro39
-rw-r--r--src/activeqt/control/qaxaggregated.h94
-rw-r--r--src/activeqt/control/qaxbindable.cpp325
-rw-r--r--src/activeqt/control/qaxbindable.h88
-rw-r--r--src/activeqt/control/qaxfactory.cpp592
-rw-r--r--src/activeqt/control/qaxfactory.h311
-rw-r--r--src/activeqt/control/qaxmain.cpp55
-rw-r--r--src/activeqt/control/qaxserver.cpp1257
-rw-r--r--src/activeqt/control/qaxserver.def8
-rw-r--r--src/activeqt/control/qaxserver.icobin0 -> 766 bytes
-rw-r--r--src/activeqt/control/qaxserver.rc2
-rw-r--r--src/activeqt/control/qaxserverbase.cpp4444
-rw-r--r--src/activeqt/control/qaxserverdll.cpp139
-rw-r--r--src/activeqt/control/qaxservermain.cpp273
-rw-r--r--src/activeqt/shared/qaxtypes.cpp1484
-rw-r--r--src/activeqt/shared/qaxtypes.h101
-rw-r--r--tools/dumpcpp/dumpcpp.pro6
-rw-r--r--tools/dumpcpp/main.cpp1504
-rw-r--r--tools/dumpdoc/dumpdoc.pro5
-rw-r--r--tools/dumpdoc/main.cpp146
-rw-r--r--tools/testcon/ambientproperties.cpp125
-rw-r--r--tools/testcon/ambientproperties.h71
-rw-r--r--tools/testcon/ambientproperties.ui299
-rw-r--r--tools/testcon/changeproperties.cpp286
-rw-r--r--tools/testcon/changeproperties.h74
-rw-r--r--tools/testcon/changeproperties.ui211
-rw-r--r--tools/testcon/controlinfo.cpp122
-rw-r--r--tools/testcon/controlinfo.h61
-rw-r--r--tools/testcon/controlinfo.ui134
-rw-r--r--tools/testcon/docuwindow.cpp161
-rw-r--r--tools/testcon/docuwindow.h67
-rw-r--r--tools/testcon/invokemethod.cpp170
-rw-r--r--tools/testcon/invokemethod.h73
-rw-r--r--tools/testcon/invokemethod.ui270
-rw-r--r--tools/testcon/main.cpp64
-rw-r--r--tools/testcon/mainwindow.cpp461
-rw-r--r--tools/testcon/mainwindow.h106
-rw-r--r--tools/testcon/mainwindow.ui682
-rw-r--r--tools/testcon/scripts/javascript.js25
-rw-r--r--tools/testcon/scripts/perlscript.pl65
-rw-r--r--tools/testcon/scripts/pythonscript.py57
-rw-r--r--tools/testcon/scripts/vbscript.vbs20
-rw-r--r--tools/testcon/testcon.idl44
-rw-r--r--tools/testcon/testcon.pro21
-rw-r--r--tools/testcon/testcon.rc35
-rw-r--r--tools/tools.pro8
156 files changed, 33121 insertions, 0 deletions
diff --git a/doc/src/activeqt-container.qdoc b/doc/src/activeqt-container.qdoc
new file mode 100644
index 0000000..862408b
--- /dev/null
+++ b/doc/src/activeqt-container.qdoc
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page activeqt-container.html
+ \title Using ActiveX controls and COM in Qt
+ \ingroup qt-activex
+
+ \brief A Windows-only extension for accessing ActiveX controls and
+ COM objects.
+
+ The QAxContainer module is part of the \l ActiveQt framework. It
+ provides a library implementing a QWidget subclass, QAxWidget,
+ that acts as a container for ActiveX controls, and a QObject
+ subclass, QAxObject, that can be used to easily access non-visual
+ COM objects. Scripting COM objects embedded using these classes
+ is possible through the QAxScript, QAxScriptManager and
+ QAxScriptEngine classes, and a set of \l{Tools for ActiveQt}{tools}
+ makes it easy to access COM objects programmatically.
+
+ The module consists of six classes
+ \list 1
+ \o QAxBase is an abstract class that provides an API to initialize
+ and access a COM object or ActiveX control.
+ \o QAxObject provides a QObject that wraps a COM object.
+ \o QAxWidget is a QWidget that wraps an ActiveX control.
+ \o QAxScriptManager, QAxScript and QAxScriptEngine provide an
+ interface to the Windows Script Host.
+ \endlist
+
+ Some \l{ActiveQt Examples}{example applications} that use
+ standard ActiveX controls to provide high-level user interface
+ functionality are provided.
+
+ \sa {ActiveQt Framework}
+
+ Topics:
+
+ \tableofcontents
+
+ \section1 Using the Library
+
+ To build Qt applications that can host COM objects and ActiveX controls
+ link the application against the QAxContainer module by adding
+
+ \snippet doc/src/snippets/code/doc_src_qaxcontainer.pro 0
+
+ to your application's \c .pro file.
+
+ \section2 Distributing QAxContainer Applications
+
+ The QAxContainer library is static, so there is no need to redistribute
+ any additional files when using this module. Note however that the
+ ActiveX server binaries you are using might not be installed on the
+ target system, so you have to ship them with your package and register
+ them during the installation process of your application.
+
+ \section1 Instantiating COM Objects
+
+ To instantiate a COM object use the QAxBase::setControl() API, or pass
+ the name of the object directly into the constructor of the QAxBase
+ subclass you are using.
+
+ The control can be specified in a variety of formats, but the fastest
+ and most powerful format is to use the class ID (CLSID) of the object
+ directly. The class ID can be prepended with information about a remote
+ machine that the object should run on, and can include a license key
+ for licensed controls.
+
+ \section2 Typical Error Messages
+
+ ActiveQt prints error messages to the debug output when it
+ encounters error situations at runtime. Usually you must run
+ your program in the debugger to see these messages (e.g. in Visual
+ Studio's Debug output).
+
+ \section3 Requested control could not be instantiated
+
+ The control requested in QAxBase::setControl() is not installed
+ on this system, or is not accessible for the current user.
+
+ The control might require administrator rights, or a license key.
+ If the control is licensed, pass the license key to QAxBase::setControl
+ as documented.
+
+ \section1 Accessing the Object API
+
+ ActiveQt provides a Qt API to the COM object, and replaces COM
+ datatypes with Qt equivalents.
+
+ There are four ways to call APIs on the COM object:
+
+ \list
+ \o Generating a C++ namespace
+ \o Call-by-name
+ \o Through a script engine
+ \o Using the native COM interfaces
+ \endlist
+
+ \section2 Generating a C++ Namespace
+
+ To generate a C++ namespace for the type library you want to access,
+ use the \l dumpcpp tool. Run this tool manually on the type library you
+ want to use, or integrate it into the build system by adding the type
+ libraries to the \c TYPELIBS variable in your application's \c .pro file:
+
+ \snippet doc/src/snippets/code/doc_src_qaxcontainer.pro 1
+
+ Note that \l dumpcpp might not be able to expose all APIs in the type
+ library.
+
+ Include the resulting header file in your code to access the
+ object APIs through the generated C++ classes. See the
+ \l{activeqt/qutlook}{Qutlook} example for more information.
+
+ \section2 Call-by-Name
+
+ Use QAxBase::dynamicCall() and QAxBase::querySubObject() as well as
+ the QObject::setProperty() and QObject::property() APIs to call the
+ methods and properties of the COM object through their name. Use the
+ \l dumpdoc tool to get the documentation of the Qt API for any COM
+ object and its subobjects; note that not all of the COM object's APIs
+ might be available.
+
+ See the \l{activeqt/webbrowser}{Webbrowser} example for more information.
+
+ \section2 Calling Function Through a Script Engine
+
+ A Qt application can host any ActiveScript engine installed on the system.
+ The script engine can then run script code that accesses the COM objects.
+
+ To instantiate a script engine, use QAxScriptManager::addObject() to
+ register the COM objects you want to access from script, and
+ QAxScriptManager::load() to load the script code into the engine. Then
+ call the script functions using QAxScriptManager::call() or
+ QAxScript::call().
+
+ Which APIs of the COM object are available through scripting depends on
+ the script language used.
+
+ The \l{testcon - An ActiveX Test Container (ActiveQt)}{ActiveX Test Container}
+ demonstrates loading of script files.
+
+ \section2 Calling a Function Using the Native COM Interfaces
+
+ To call functions of the COM object that can not be accessed via any
+ of the above methods it is possible to request the COM interface directly
+ using QAxBase::queryInterface(). To get a C++ definition of the respective
+ interface classes use the \c #import directive with the type library
+ provided with the control; see your compiler manual for details.
+
+ \section2 Typical Error Messages
+
+ ActiveQt prints error messages to the debug output when it
+ encounters error situations at runtime. Usually you must run
+ your program in the debugger to see these messages (e.g. in Visual
+ Studio's Debug output).
+
+ \section3 QAxBase::internalInvoke: No such method
+
+ A QAxBase::dynamicCall() failed - the function prototype did not
+ match any function available in the object's API.
+
+ \section3 Error calling IDispatch member: Non-optional parameter missing
+
+ A QAxBase::dynamicCall() failed - the function prototype was correct,
+ but too few parameters were provided.
+
+ \section3 Error calling IDispatch member: Type mismatch in parameter n
+
+ A QAxBase::dynamicCall() failed - the function prototype was correct,
+ but the paramter at index \c n was of the wrong type and could
+ not be coerced to the correct type.
+
+ \section3 QAxScriptManager::call(): No script provides this function
+
+ You try to call a function that is provided through an engine
+ that doesn't provide introspection (ie. ActivePython or
+ ActivePerl). You need to call the function directly on the
+ respective QAxScript object.
+*/
diff --git a/doc/src/activeqt-server.qdoc b/doc/src/activeqt-server.qdoc
new file mode 100644
index 0000000..77cacf8
--- /dev/null
+++ b/doc/src/activeqt-server.qdoc
@@ -0,0 +1,837 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page activeqt-server.html
+ \title Building ActiveX servers in Qt
+ \ingroup qt-activex
+
+ \brief A Windows-only static library for turning a Qt binary into a COM server.
+
+ The QAxServer module is part of the \l ActiveQt framework. It
+ consists of three classes:
+
+ \list
+ \o QAxFactory defines a factory for the creation of COM objects.
+ \o QAxBindable provides an interface between the Qt widget and the
+ COM object.
+ \o QAxAggregated can be subclassed to implement additional COM interfaces.
+ \endlist
+
+ Some \l{ActiveQt Examples}{example implementations} of ActiveX
+ controls and COM objects are provided.
+
+ \sa {ActiveQt Framework}
+
+ Topics:
+
+ \tableofcontents
+
+ \section1 Using the Library
+
+ To turn a standard Qt application into a COM server using the
+ QAxServer library you must add \c qaxserver as a CONFIG setting
+ in your \c .pro file.
+
+ An out-of-process executable server is generated from a \c .pro
+ file like this:
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.pro 0
+
+ To build an in-process server, use a \c .pro file like this:
+ \snippet doc/src/snippets/code/doc_src_qaxserver.pro 1
+
+ The files \c qaxserver.rc and \c qaxserver.def are part of the
+ framework and can be used from their usual location (specify a
+ path in the \c .pro file), or copied into the project directory.
+ You can modify these files as long as it includes any file as the
+ type library entry, ie. you can add version information or specify
+ a different toolbox icon.
+
+ The \c qaxserver configuration will cause the \c qmake tool to add the
+ required build steps to the build system:
+
+ \list
+ \o Link the binary against \c qaxserver.lib instead of \c qtmain.lib
+ \o Call the \l idc tool to generate an IDL file for the COM server
+ \o Compile the IDL into a type library using the MIDL tool (part of the
+ compiler installation)
+ \o Attach the resulting type library as a binary resource to the server
+ binary (again using the \l idc tool)
+ \o Register the server
+ \endlist
+
+ To skip the post-processing step, also set the \c qaxserver_no_postlink
+ configuration.
+
+ Additionally you can specify a version number using the \c VERSION
+ variable, e.g.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.pro 2
+
+ The version number specified will be used as the version of the type
+ library and of the server when registering.
+
+ \section2 Out-of-Process vs. In-Process
+
+ Whether your COM server should run as a stand-alone executable
+ or as a shared library in the client process depends mainly on the
+ type of COM objects you want to provide in the server.
+
+ An executable server has the advantage of being able to run as a
+ stand-alone application, but adds considerable overhead to the
+ communication between the COM client and the COM object. If the
+ control has a programming error only the server process running
+ the control will crash, and the client application will probably
+ continue to run. Not all COM clients support executable servers.
+
+ An in-process server is usually smaller and has faster startup
+ time. The communication between client and server is done directly
+ through virtual function calls and does not introduce the overhead
+ required for remote procedure calls. However, if the server crashes the
+ client application is likely to crash as well, and not every
+ functionality is available for in-process servers (i.e. register in
+ the COM's running-object-table).
+
+ Both server types can use Qt either as a shared library, or statically
+ linked into the server binary.
+
+ \section2 Typical Errors During the Post-Build Steps
+
+ For the ActiveQt specific post-processing steps to work the
+ server has to meet some requirements:
+
+ \list
+ \o All controls exposed can be created with nothing but a QApplication
+ instance being present
+ \o The initial linking of the server includes a temporary type
+ library resource
+ \o All dependencies required to run the server are in the system path
+ (or in the path used by the calling environment; note that Visual
+ Studio has its own set of environment variables listed in the
+ Tools|Options|Directories dialog).
+ \endlist
+
+ If those requirements are not met one ore more of the following
+ errors are likely to occur:
+
+ \section3 The Server Executable Crashes
+
+ To generate the IDL the widgets exposed as ActiveX controls need to
+ be instantiated (the constructor is called). At this point, nothing
+ else but a QApplication object exists. Your widget constructor must
+ not rely on any other objects to be created, e.g. it should check for
+ null-pointers.
+
+ To debug your server run it with -dumpidl outputfile and check where
+ it crashes.
+
+ Note that no functions of the control are called.
+
+ \section3 The Server Executable Is Not a Valid Win32 Application
+
+ Attaching the type library corrupted the server binary. This is a
+ bug in Windows and happens only with release builds.
+
+ The first linking step has to link a dummy type library into the
+ executable that can later be replaced by idc. Add a resource file
+ with a type library to your project as demonstrated in the examples.
+
+ \section3 "Unable to locate DLL"
+
+ The build system needs to run the server executable to generate
+ the interface definition, and to register the server. If a dynamic
+ link library the server links against is not in the path this
+ might fail (e.g. Visual Studio calls the server using the
+ enivronment settings specified in the "Directories" option). Make
+ sure that all DLLs required by your server are located in a
+ directory that is listed in the path as printed in the error
+ message box.
+
+ \section3 "Cannot open file ..."
+
+ The ActiveX server could not shut down properly when the last
+ client stopped using it. It usually takes about two seconds for
+ the application to terminate, but you might have to use the task
+ manager to kill the process (e.g. when a client doesn't release
+ the controls properly).
+
+ \section1 Implementing Controls
+
+ To implement a COM object with Qt, create a subclass of QObject
+ or any existing QObject subclass. If the class is a subclass of QWidget,
+ the COM object will be an ActiveX control.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 3
+
+ The Q_OBJECT macro is required to provide the meta object information
+ about the widget to the ActiveQt framework.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 4
+
+ Use the Q_CLASSINFO() macro to specify the COM identifiers for the COM
+ object. \c ClassID and \c InterfaceID are required, while \c EventsID is
+ only necessary when your object has signals. To generate these identifiers,
+ use system tools like \c uuidgen or \c guidgen.
+
+ You can specify additional attributes for each of your classes; see
+ \l{Class Information and Tuning} for details.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 5
+
+ Use the Q_PROPERTY() macro to declare properties for the ActiveX control.
+
+ Declare a standard constructor taking a parent object, and functions,
+ signals and slots like for any QObject subclass.
+ \footnote
+ If a standard constructor is not present the compiler will issue
+ an error "no overloaded function takes 2 parameters" when using
+ the default factory through the QAXFACTORY_DEFAULT() macro. If you
+ cannot provide a standard constructor you must implement a
+ QAxFactory custom factory and call the constructor you have in
+ your implementation of QAxFactory::create.
+ \endfootnote
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 6
+
+ The ActiveQt framework will expose properties and public slots as ActiveX
+ properties and methods, and signals as ActiveX events, and convert between
+ the Qt data types and the equivalent COM data types.
+
+ \section2 Data Types
+
+ The Qt data types that are supported for properties are:
+
+ \table
+ \header
+ \o Qt data type
+ \o COM property
+ \row
+ \o bool
+ \o VARIANT_BOOL
+ \row
+ \o QString
+ \o BSTR
+ \row
+ \o int
+ \o int
+ \row
+ \o uint
+ \o unsigned int
+ \row
+ \o double
+ \o double
+ \row
+ \o \l qlonglong
+ \o CY
+ \row
+ \o \l qulonglong
+ \o CY
+ \row
+ \o QColor
+ \o OLE_COLOR
+ \row
+ \o QDate
+ \o DATE
+ \row
+ \o QDateTime
+ \o DATE
+ \row
+ \o QTime
+ \o DATE
+ \row
+ \o QFont
+ \o IFontDisp*
+ \row
+ \o QPixmap
+ \o IPictureDisp*
+ \footnote
+ COM cannot marshal IPictureDisp accross process boundaries,
+ so QPixmap properties cannot be called for out-of-process servers. You
+ can however marshal the image data via e.g. temporary files. See the
+ Microsoft
+ \link http://support.microsoft.com/default.aspx?scid=kb;[LN];Q150034 KB article
+ Q150034 \endlink for more information.
+ \endfootnote
+ \row
+ \o QVariant
+ \o VARIANT
+ \row
+ \o QVariantList (same as QList\<QVariant\>)
+ \o SAFEARRAY(VARIANT)
+ \row
+ \o QStringList
+ \o SAFEARRAY(BSTR)
+ \row
+ \o QByteArray
+ \o SAFEARRAY(BYTE)
+ \row
+ \o QRect
+ \o User defined type
+ \row
+ \o QSize
+ \o User defined type
+ \row
+ \o QPoint
+ \o User defined type
+ \endtable
+
+ The Qt data types that are supported for parameters in signals and
+ slots are:
+ \table
+ \header
+ \o Qt data type
+ \o COM parameter
+ \row
+ \o bool
+ \o [in] VARIANT_BOOL
+ \row
+ \o bool&
+ \o [in, out] VARIANT_BOOL*
+ \row
+ \o QString, const QString&
+ \o [in] BSTR
+ \row
+ \o QString&
+ \o [in, out] BSTR*
+ \row
+ \o QString&
+ \o [in, out] BSTR*
+ \row
+ \o int
+ \o [in] int
+ \row
+ \o int&
+ \o [in,out] int
+ \row
+ \o uint
+ \o [in] unsigned int
+ \row
+ \o uint&
+ \o [in, out] unsigned int*
+ \row
+ \o double
+ \o [in] double
+ \row
+ \o double&
+ \o [in, out] double*
+ \row
+ \o QColor, const QColor&
+ \o [in] OLE_COLOR
+ \row
+ \o QColor&
+ \o [in, out] OLE_COLOR*
+ \row
+ \o QDate, const QDate&
+ \o [in] DATE
+ \row
+ \o QDate&
+ \o [in, out] DATE*
+ \row
+ \o QDateTime, const QDateTime&
+ \o [in] DATE
+ \row
+ \o QDateTime&
+ \o [in, out] DATE*
+ \row
+ \o QFont, const QFont&
+ \o [in] IFontDisp*
+ \row
+ \o QFont&
+ \o [in, out] IFontDisp**
+ \row
+ \o QPixmap, const QPixmap&
+ \o [in] IPictureDisp*
+ \row
+ \o QPixmap&
+ \o [in, out] IPictureDisp**
+ \row
+ \o QList\<QVariant\>, const QList\<QVariant\>&
+ \o [in] SAFEARRAY(VARIANT)
+ \row
+ \o QList\<QVariant\>&
+ \o [in, out] SAFEARRAY(VARIANT)*
+ \row
+ \o QStringList, const QStringList&
+ \o [in] SAFEARRAY(BSTR)
+ \row
+ \o QStringList&
+ \o [in, out] SAFEARRAY(BSTR)*
+ \row
+ \o QByteArray, const QByteArray&
+ \o [in] SAFEARRAY(BYTE)
+ \row
+ \o QByteArray&
+ \o [in, out] SAFEARRAY(BYTE)*
+ \row
+ \o QObject*
+ \o [in] IDispatch*
+ \row
+ \o QRect&
+ \footnote
+ OLE needs to marshal user defined types by reference (ByRef), and cannot
+ marshal them by value (ByVal). This is why const-references and object
+ parameters are not supported for QRect, QSize and QPoint.
+ \endfootnote
+ \o [in, out] struct QRect (user defined)
+ \row
+ \o QSize&
+ \o [in, out] struct QSize (user defined)
+ \row
+ \o QPoint&
+ \o [in, out] struct QPoint (user defined)
+ \endtable
+
+ Also supported are exported enums and flags (see Q_ENUMS() and
+ Q_FLAGS()). The in-parameter types are also supported as
+ return values.
+
+ Properties and signals/slots that have parameters using any other
+ data types are ignored by the ActiveQt framework.
+
+ \section2 Sub-Objects
+
+ COM objects can have multiple sub-objects that can represent a sub element
+ of the COM object. A COM object representing a multi-document spread sheet
+ application can for example provide one sub-object for each spread sheet.
+
+ Any QObject subclass can be used as the type for a sub object in ActiveX, as
+ long as it is known to the QAxFactory. Then the type can be used in properties,
+ or as the return type or paramter of a slot.
+
+ \section2 Property Notification
+
+ To make the properties bindable for the ActiveX client, use multiple
+ inheritance from the QAxBindable class:
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 7
+
+ When implementing the property write functions, use the
+ QAxBindable class's requestPropertyChange() and propertyChanged()
+ functions to allow ActiveX clients to bind to the control
+ properties.
+ \footnote
+ This is not required, but gives the client more control over
+ the ActiveX control.
+ \endfootnote
+
+ \section1 Serving Controls
+
+ To make a COM server available to the COM system it must be registered
+ in the system registry using five unique identifiers.
+ These identifiers are provided by tools like \c guidgen or \c uuidgen.
+ The registration information allows COM to localize the binary providing
+ a requested ActiveX control, marshall remote procedure calls to the
+ control and read type information about the methods and properties exposed
+ by the control.
+
+ To create the COM object when the client asks for it the server must export
+ an implementation of a QAxFactory. The easist way to do this is to use a set
+ of macros:
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 8
+
+ This will export \c MyWidget and \c MyWidget2 as COM objects that can be
+ created by COM clients, and will register \c MySubType as a type that can
+ be used in properties and parameters of \c MyWidget and \c MyWidget2.
+
+ The \link QAxFactory QAxFactory class documentation \endlink explains
+ how to use this macro, and how to implement and use custom factories.
+
+ For out-of-process executable servers you can implement a main()
+ function to instantiate a QApplication object and enter the event
+ loop just like any normal Qt application. By default the
+ application will start as a standard Qt application, but if you
+ pass \c -activex on the command line it will start as an ActiveX
+ server. Use QAxFactory::isServer() to create and run a standard
+ application interface, or to prevent a stand-alone execution:
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 9
+
+ This is however not necessary as ActiveQt provides a default implementation
+ of a main function. The default implemenation calls QAxFactory::startServer(),
+ creates a QApplication instance and calls exec().
+
+ To build the ActiveX server executable run \c qmake
+ to generate the makefile, and use your compiler's
+ make tool as for any other Qt application. The make process will
+ also register the controls in the system registry by calling the
+ resulting executable with the \c -regserver command line option.
+
+ If the ActiveX server is an executable, the following command line
+ options are supported:
+ \table
+ \header \o Option \o Result
+ \row \o \c -regserver \o Registers the server in the system registry
+ \row \o \c -unregserver \o Unregisters the server from the system registry
+ \row \o \c -activex \o Starts the application as an ActiveX server
+ \row \o \c{-dumpidl <file> -version x.y} \o Writes the server's IDL to the
+ specified file. The type library will have version x.y
+ \endtable
+
+ In-process servers can be registered using the \c regsvr32 tool available
+ on all Windows systems.
+
+ \section2 Typical Compile-Time Problems
+
+ The compiler/linker errors listed are based on those issued by the
+ Microsoft Visual C++ 6.0 compiler.
+
+ \section3 "No overloaded function takes 2 parameters"
+
+ When the error occurs in code that uses the QAXFACTORY_DEFAULT()
+ macro, the widget class had no constructor that can be used by the
+ default factory. Either add a standard widget constructor or
+ implement a custom factory that doesn't require one.
+
+ When the error occurs in code that uses the QAXFACTORY_EXPORT()
+ macro, the QAxFactory subclass had no appropriate constructor.
+ Provide a public class constructor like
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 10
+
+ for your factory class.
+
+ \section3 "Syntax error: bad suffix on number"
+
+ The unique identifiers have not been passed as strings into the
+ QAXFACTORY_EXPORT() or QAXFACTORY_DEFAULT() macro.
+
+ \section3 "Unresolved external symbol _ucm_instantiate"
+
+ The server does not export an implementation of a QAxFactory. Use
+ the QAXFACTORY_EXPORT() macro in one of the project's
+ implementation files to instantiate and export a factory, or use
+ the QAXFACTORY_DEFAULT() macro to use the default factory.
+
+ \section3 "_ucm_initialize already defined in ..."
+
+ The server exports more than one implementation of a QAxFactory,
+ or exports the same implementation twice. If you use the default
+ factory, the QAXFACTORY_DEFAULT() macro must only be used once in
+ the project. Use a custom QAxFactory implementation and the
+ QAXFACTORY_EXPORT() macro if the server provides multiple ActiveX
+ controls.
+
+ \section2 Distributing QAxServer Binaries
+
+ ActiveX servers written with Qt can use Qt either as a shared
+ library, or have Qt linked statically into the binary. Both ways
+ will produce rather large packages (either the server binary
+ itself becomes large, or you have to ship the Qt DLL).
+
+ \section3 Installing Stand-Alone Servers
+
+ When your ActiveX server can also run as a stand-alone application,
+ run the server executable with the \c -regserver command line
+ parameter after installing the executable on the target system.
+ After that the controls provided by the server will be available to
+ ActiveX clients.
+
+ \section3 Installing In-Process Servers
+
+ When your ActiveX server is part of an installation package, use the
+ \c regsvr32 tool provided by Microsoft to register the controls on
+ the target system. If this tool is not present, load the DLL into
+ your installer process, resolve the \c DllRegisterServer symbol and
+ call the function:
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 11
+
+ \section3 Distributing Servers over the Internet
+
+ If you want to use controls in your server in web-pages you need to
+ make the server available to the browser used to view your page, and
+ you need to specify the location of the server package in your page.
+
+ To specify the location of a server, use the CODEBASE attribute in
+ the OBJECT tag of your web-site. The value can point to the server
+ file itself, to an INF file listing other files the server requires
+ (e.g. the Qt DLL), or a compressed CAB archive.
+
+ INF and CAB files are documented in almost every book available about
+ ActiveX and COM programming as well as in the MSDN library and various
+ other Online resources. The examples include INF files that can be used
+ to build CAB archives:
+
+ \snippet examples/activeqt/simple/simple.inf 0
+
+ The CABARC tool from Microsoft can easily generate CAB archives:
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 12
+
+ The INF files assume a static build of Qt, so no dependencies to other DLLs
+ are listed in the INF files. To distribute an ActiveX server depending on
+ DLLs you must add the dependencies, and provide the library files
+ with the archive.
+
+ \section1 Using the Controls
+
+ To use the ActiveX controls, e.g. to embed them in a web page, use
+ the \c <object> HTML tag.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 13
+
+ To initialize the control's properties, use
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 14
+
+ If the web browser supports scripting use JavaScript, VBScript
+ and forms to script the control. The
+ \l{ActiveQt Examples} include demonstration HTML pages for the example
+ controls.
+
+ \section2 Supported and Unsupported ActiveX Clients
+
+ The following is largly based on our own experiements with ActiveX
+ controls and client applications, and is by no means complete.
+
+ \section3 Supported Clients
+
+ These standard applications work with ActiveX controls developed with
+ ActiveQt. Note that some clients support only in-process controls.
+
+ \list
+ \o Internet Explorer
+ \o Microsoft ActiveX Control Test Container
+ \o Microsoft Visual Studio 6.0
+ \o Microsoft Visual Studio.NET/2003
+ \o Microsoft Visual Basic 6.0
+ \o MFC- and ATL-based containers
+ \o Sybase PowerBuilder
+ \o ActiveQt based containers
+ \endlist
+
+ Microsoft Office applications are supported, but you need to register
+ the controls as "Insertable" objects. Reimplement QAxFactory::registerClass
+ to add this attribute to the COM class, or set the "Insertable" class info
+ for your class to "yes" using the Q_CLASSINFO macro.
+
+ \section3 Unsupported Clients
+
+ We have not managed to make ActiveQt based COM objects work with the
+ following client applications.
+
+ \list
+ \o Borland C++ Builder (Versions 5 and 6)
+ \o Borland Delphi
+ \endlist
+
+ \section2 Typical Runtime Errors
+
+ \section3 The Server Does Not Respond
+
+ If the system is unable to start the server (check with the task
+ manager whether the server runs a process), make sure that no DLL
+ the server depends on is missing from the system path (e.g. the Qt
+ DLL!). Use a dependency walker to view all dependencies of the server
+ binary.
+
+ If the server runs (e.g. the task manager lists a process), see
+ the following section for information on debugging your server.
+
+ \section3 The Object Cannot Be Created
+
+ If the server could be built and registered correctly during the build
+ process, but the object cannot be initiliazed e.g. by the OLE/COM Object
+ Viewer application, make sure that no DLL the server depends on is
+ missing from the system path (e.g. the Qt DLL). Use a dependency walker
+ to view all dependencies of the server binary.
+
+ If the server runs, see the following section for information on
+ debugging your server.
+
+ \section2 Debugging Runtime Errors
+
+ To debug an in-process server in Visual Studio, set the server project
+ as the active project, and specify a client "executable for debug
+ session" in the project settings (e.g. use the ActiveX Test Container).
+ You can set breakpoints in your code, and also step into ActiveQt and
+ Qt code if you installed the debug version.
+
+ To debug an executable server, run the application in a debugger
+ and start with the command line parameter \c -activex. Then start
+ your client and create an instance of your ActiveX control. COM
+ will use the existing process for the next client trying to create
+ an ActiveX control.
+
+ \section1 Class Information and Tuning
+
+ To provide attributes for each COM class, use the Q_CLASSINFO macro, which is part of
+ Qt's meta object system.
+
+ \table
+ \header
+ \o Key
+ \o Meaning of value
+ \row
+ \o Version
+ \o The version of the class (1.0 is default)
+ \row
+ \o Description
+ \o A string describing the class.
+ \row
+ \o ClassID
+ \o The class ID.
+ You must reimplement QAxFactory::classID if not specified.
+ \row
+ \o InterfaceID
+ \o The interface ID.
+ You must reimplement QAxFactory::interfaceID if not specified.
+ \row
+ \o EventsID
+ \o The event interface ID.
+ No signals are exposed as COM events if not specified.
+ \row
+ \o DefaultProperty
+ \o The property specified represents the default property of this class.
+ Ie. the default property of a push button would be "text".
+ \row
+ \o DefaultSignal
+ \o The signal specified respresents the default signal of this class.
+ Ie. the default signal of a push button would be "clicked".
+ \row
+ \o LicenseKey
+ \o Object creation requires the specified license key. The key can be
+ empty to require a licensed machine. By default classes are not
+ licensed. Also see the following section.
+ \row
+ \o StockEvents
+ \o Objects expose stock events if value is "yes".
+ See \l QAxFactory::hasStockEvents()
+ \row
+ \o ToSuperClass
+ \o Objects expose functionality of all super-classes up to and
+ including the class name in value.
+ See \l QAxFactory::exposeToSuperClass()
+ \row
+ \o Insertable
+ \o If the value is "yes" the class is registered to be "Insertable"
+ and will be listed in OLE 2 containers (ie. Microsoft Office). This
+ attribute is not be set by default.
+ \row
+ \o Aggregatable
+ \o If the value is "no" the class does not support aggregation. By
+ default aggregation is supported.
+ \row
+ \o Creatable
+ \o If the value is "no" the class cannot be created by the client,
+ and is only available through the API of another class (ie. the
+ class is a sub-type).
+ \row
+ \o RegisterObject
+ \o If the value is "yes" objects of this class are registered with
+ OLE and accessible from the running object table (ie. clients
+ can connect to an already running instance of this class). This
+ attribute is only supported in out-of-process servers.
+ \row
+ \o MIME
+ \o The object can handle data and files of the format specified in the
+ value. The value has the format mime:extension:description. Multiple
+ formats are separated by a semicolon.
+ \row
+ \o CoClassAlias
+ \o The classname used in the generated IDL and in the registry. This is
+ esp. useful for C++ classes that live in a namespace - by default,
+ ActiveQt just removes the "::" to make the IDL compile.
+ \endtable
+
+ Note that both keys and values are case sensitive.
+
+ The following declares version 2.0 of a class that exposes only its
+ own API, and is available in the "Insert Objects" dialog of Microsoft
+ Office applications.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 15
+
+ \section2 Developing Licensed Components
+
+ If you develop components you might want to control who is able to instantiate
+ those components. Since the server binary can be shipped to and registered on
+ any client machine it is possible for anybody to use those components in his
+ own software.
+
+ Licensing components can be done using a variety of techniques, e.g. the code
+ creating the control can provide a license key, or the machine on which the
+ control is supposed to run needs to be licensed.
+
+ To mark a Qt class as licensed specify a "LicenseKey" using the
+ Q_CLASSINFO() macro.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 16
+
+ The key is required to be able to create an instance of \c MyLicensedControl
+ on a machine that is not licensed itself. The licensed developer can now
+ redistributes the server binary with his application, which creates the control
+ using the value of "LicenseKey", while users of the application cannot create
+ the control without the license key.
+
+ If a single license key for the control is not sufficient (ie. you want
+ differnet developers to receive different license keys) you can specify an
+ empty key to indicate that the control requires a license, and reimplement
+ \l QAxFactory::validateLicenseKey() to verify that a license exists on the
+ system (ie. through a license file).
+
+ \section2 More Interfaces
+
+ ActiveX controls provided by ActiveQt servers support a minimal set of COM
+ interfaces to implement the OLE specifications. When the ActiveX class inherits
+ from the QAxBindable class it can also implement additional COM interfaces.
+
+ Create a new subclass of QAxAggregated and use multiple inheritance
+ to subclass additional COM interface classes.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 17
+
+ Reimplement the QAxAggregated::queryInterface() function to
+ support the additional COM interfaces.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 18
+
+ Since \c ISomeCOMInterface is a subclass of \c IUnknown you will
+ have to implement the \c QueryInterface(), \c AddRef(), and \c
+ Release() functions. Use the QAXAGG_IUNKNOWN macro in your
+ class definition to do that. If you implement the \c IUnknown
+ functions manually, delegate the calls to the interface pointer
+ returned by the QAxAggregated::controllingUnknown() function,
+ e.g.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 19
+
+ Do not support the \c IUnknown interface itself in your
+ \l{QAxAggregated::queryInterface()}{queryInterface()}
+ implementation.
+
+ Implement the methods of the COM interfaces, and use QAxAggregated::object()
+ if you need to make calls to the QObject subclass implementing the control.
+
+ In your QAxBindable subclass, implement
+ QAxBindable::createAggregate() to return a new object of the
+ QAxAggregated subclass.
+
+ \snippet doc/src/snippets/code/doc_src_qaxserver.cpp 20
+*/
diff --git a/doc/src/activeqt.qdoc b/doc/src/activeqt.qdoc
new file mode 100644
index 0000000..ba4a92f
--- /dev/null
+++ b/doc/src/activeqt.qdoc
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group activeqt-tools
+ \title Tools for ActiveQt
+ \brief Tools to help integrate Qt applications with ActiveX components.
+
+ These tools provide support for integrating Qt with ActiveX components.
+
+ \generatelist{related}
+
+ \sa {ActiveQt Framework}
+*/
+
+/*!
+ \page activeqt.html
+ \title Qt's ActiveX Framework (ActiveQt)
+ \brief An overview of Qt's ActiveX and COM integration on Windows.
+
+ \ingroup qt-activex
+ \keyword ActiveQt
+ \target ActiveQt Framework
+
+ Qt's ActiveX and COM support allows Qt for Windows developers to:
+
+ \list 1
+ \o Access and use ActiveX controls and COM objects provided by any
+ ActiveX server in their Qt applications.
+ \o Make their Qt applications available as COM servers, with
+ any number of Qt objects and widgets as COM objects and ActiveX
+ controls.
+ \endlist
+
+ For more information about using ActiveX with Qt, see
+ \l{Building ActiveX servers in Qt}.
+
+ The ActiveQt framework consists of two modules:
+
+ \list
+ \o The \l{Using ActiveX controls and COM in Qt}{QAxContainer}
+ module is a static library implementing QObject and QWidget subclasses,
+ QAxObject and QAxWidget, that act as containers for COM objects and
+ ActiveX controls.
+ \o The \l{Building ActiveX servers in Qt}{QAxServer}
+ module is a static library that implements
+ functionality for in-process and executable COM servers. This
+ module provides the QAxAggregated, QAxBindable and QAxFactory
+ classes.
+ \endlist
+
+ A set of \l{Tools for ActiveQt}{tools} is provided to simplify the
+ developing and building of Qt projects that use ActiveX.
+
+ To build the static libraries, change into the \c activeqt directory
+ (usually \c QTDIR/src/activeqt), and run \c qmake and your make
+ tool in both the \c container and the \c control subdirectory.
+ The libraries \c qaxcontainer.lib and \c qaxserver.lib will be linked
+ into \c QTDIR/lib.
+
+ If you are using a shared configuration of Qt enter the \c plugin
+ subdirectory and run \c qmake and your make tool to build a
+ plugin that integrates the QAxContainer module into \l{Qt
+ Designer}.
+
+ The ActiveQt modules are part of the \l{Qt Commercial Edition} and
+ the \l{Open Source Versions of Qt}.
+
+ \sa {QAxContainer Module}, {QAxServer Module}
+*/
diff --git a/doc/src/examples/comapp.qdoc b/doc/src/examples/comapp.qdoc
new file mode 100644
index 0000000..4e4b9cb
--- /dev/null
+++ b/doc/src/examples/comapp.qdoc
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example activeqt/comapp
+ \title COM App Example (ActiveQt)
+
+ The COM App example shows how to use ActiveQt to develop a Qt
+ application that can be automated via COM. Different QObject
+ based classes are exposed as COM objects that communicate with the
+ GUI of the running Qt application. The APIs of those COM objects
+ has been designed to resemble the APIs of standard COM
+ applications; i.e. those from Microsoft Office.
+
+ \snippet examples/activeqt/comapp/main.cpp 2
+ The first class \c Application represents the application object. It
+ exposes read-only properties \c documents and \c id to get access to the
+ list of documents, and an identifier. A read/write property \c visible
+ controls whether the QTabWidget-based user interface of the application
+ should be visible, and a slot \c quit() terminates the application.
+
+ The \e RegisterObject attribute is set to make sure that instances of this
+ class are registered in COM's running object table (ROT) - this allows COM
+ clients to connect to an already instantiated COM object.
+
+ \snippet examples/activeqt/comapp/main.cpp 1
+ The \c DocumentList class stores a list of documents. It provides an API
+ to read the number of documents, to access each document by index and to
+ create a new document. The \c application property returns the root object.
+
+ \snippet examples/activeqt/comapp/main.cpp 0
+
+ The \c Document class finally represents a document in the application.
+ Each document is represented by a page in the application's tab widget, and
+ has a title that is readable and writable through the document's API.
+ The \c application property again returns the root object.
+
+ \snippet examples/activeqt/comapp/main.cpp 3
+ The implementation of the \c Document class creates a new page for the tab
+ widget, and uses the title of that page for the title property. The page
+ is deleted when the document is deleted.
+
+ \snippet examples/activeqt/comapp/main.cpp 4
+ The \c DocumentList implementation is straightforward.
+
+ \snippet examples/activeqt/comapp/main.cpp 5
+ The \c Application class initializes the user interface in the constructor,
+ and shows and hides it in the implementation of \c setVisible(). The object
+ name (accessible through the \c id property) is set to \c "From QAxFactory"
+ to indicate that this COM object has been created by COM. Note that there is
+ no destructor that would delete the QTabWidget - this is instead done in the
+ \c quit() slot, before calling QApplication::quit() through a single-shot-timer,
+ which is necessary ensure that the COM call to the slot is complete.
+
+ \snippet examples/activeqt/comapp/main.cpp 6
+ The classes are exported from the server using the QAxFactory macros. Only
+ \c Application objects can be instantiated from outside - the other APIs can
+ only be used after accessing the respective objects throught the \c Application
+ API.
+
+ \snippet examples/activeqt/comapp/main.cpp 7
+ The main() entry point function creates a QApplication, and just enters the
+ event loop if the application has been started by COM. If the application
+ has been started by the user, then the \c Application object is created and
+ the object name is set to "From Application". Then the COM server is started,
+ and the application object is registered with COM. It is now accessible to
+ COM clients through the client-specific APIs.
+
+ Application exiting is controlled explicitly - if COM started the application,
+ then the client code has to call quit(); if the user started the application,
+ then the application terminates when the last window has been closed.
+
+ Finally, the user interface is made visible, and the event loop is started.
+
+ A simple Visual Basic application could now access this Qt application. In VB,
+ start a new "Standard Exe" project and add a project reference to the comappLib
+ type library. Create a form with a listbox "DocumentList", a static label
+ "DocumentsCount" and a command button "NewDocument". Finally, implement the code
+ for the form like this:
+
+ \snippet doc/src/snippets/code/doc_src_examples_activeqt_comapp.qdoc 0
+
+ To build the example you must first build the QAxServer library.
+ Then run \c qmake and your make tool in
+ \c{examples\activeqt\comapp}.
+*/
diff --git a/doc/src/examples/dotnet.qdoc b/doc/src/examples/dotnet.qdoc
new file mode 100644
index 0000000..ec13ce8
--- /dev/null
+++ b/doc/src/examples/dotnet.qdoc
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page activeqt-dotnet.html
+ \title Dot Net Example (ActiveQt)
+
+ The Dot Net example demonstrates how Qt objects can be used in a
+ .NET environment, and how .NET objects can be used in a Qt
+ environment.
+
+ If you need to combine Qt and Win Forms widgets in the same
+ application, you might want to use the higher-level
+ \l{QtWinForms Solution} instead.
+
+ Contents:
+
+ \tableofcontents
+
+ \section1 Qt vs. .NET
+
+ Qt is a C++ library and is compiled into traditional, native
+ binaries that make full use of the performance provided by the
+ runtime environment.
+
+ One of the key concepts of .NET is the idea of "intermediate language
+ code" - the source code is compiled into a bytecode format, and at
+ runtime, that bytecode is executed in a virtual machine - the \e
+ {Common Language Runtime} (CLR).
+
+ Another key concept is that of \e {managed code}. This is essentially
+ intermediate language code written in such a way that the CLR can take
+ care of the memory management, i.e. the CLR will do automatic garbage
+ collection, so the application code does not need to explicitly free
+ the memory for unused objects.
+
+ The MS compilers for C# and VB.NET will only produce managed
+ code. Such programs cannot directly call normal, native functions
+ or classes. \footnote The .NET framework provides Platform Invocation
+ Services - P/Invoke - that enable managed code to call native C (not
+ C++) functions located in DLLs directly. The resulting application
+ then becomes partially unmanaged.\endfootnote
+
+ The MS C++ compiler for .NET on the other hand, can produce both
+ normal and managed code. To write a C++ class that can be compiled
+ into managed code, the developer must flag the class as managed using
+ the \c __gc keyword, and restrict the code to only use the subset of
+ C++ known as "Managed Extensions for C++", or MC++ for short. The
+ advantage is that MC++ code can freely call and use normal C++
+ functions and classes. And it also works the other way around: normal
+ C++ code can call managed functions and use managed classes (e.g. the
+ entire .NET framework class library), including managed functions and
+ classes implemented in C# or VB.NET. This feature of mixing managed
+ and normal C++ code immensely eases the interoperability with .NET,
+ and is by Microsoft referred to as the "It Just Works" (IJW) feature.
+
+ This document demonstrates two different ways of integrating normal
+ C++ code (that uses Qt) with managed .NET code. First, the manual way
+ is presented, which includes using a thin MC++ wrapper class around
+ the normal Qt/C++ class. Then, the automated way is presented, which
+ utilizes the ActiveQt framework as a generic bridge. The advantage of
+ the first method is that it gives the application developer full
+ control, while the second method requires less coding and relieves the
+ developer of dealing with the conversion between managed and normal
+ data objects.
+
+ The impatient reader, who right away wants to see a QPushButton
+ and a custom Qt widget (\l{activeqt/multiple}{QAxWidget2}) run in
+ a .NET GUI application is referred to the example directory of
+ ActiveQt. It contains the result of this walkthrough using both
+ C# and VB.NET, created with Visual Studio .NET (not 2003).
+ Load \c {examples/dotnet/walkthrough/csharp.csproj},
+ \c {examples/dotnet/walkthrough/vb.vbproj}
+ or \c {examples/dotnet/wrapper/wrapper.sln} into the IDE and run
+ the solution.
+
+ \bold{Remark:} You will notice that in the generated code the following line is
+ commented out:
+
+ \snippet doc/src/snippets/code/doc_src_examples_activeqt_dotnet.qdoc 0
+
+ This line is regenerated without comment whenever you change the
+ dialog, in which case you have to comment it out again to be able
+ to run the project. This is a bug in the original version of
+ Visual Studio.NET, and is fixed in the 2003 edition.
+
+ \section1 Walkthrough: .NET interop with MC++ and IJW
+
+ Normal C++ classes and functions can be used from managed .NET code by
+ providing thin wrapper classes written in MC++. The wrapper class will
+ take care of forwarding the calls to the normal C++ functions or
+ methods, and converting parameter data as necessary. Since the wrapper
+ class is a managed class, it can be used without further ado in any
+ managed .NET application, whether written in C#, VB.NET, MC++ or other
+ managed programming language.
+
+ \snippet examples/activeqt/dotnet/wrapper/lib/worker.h 0
+
+ The Qt class has nothing unusual for Qt users, and as even the Qt
+ specialities like \c Q_PROPERTY, \c slots and \c signals are
+ implemented with straight C++ they don't cause any trouble when
+ compiling this class with any C++ compiler.
+
+ \snippet examples/activeqt/dotnet/wrapper/lib/networker.h 0
+
+ The .NET wrapper class uses keywords that are part of MC++ to indicate
+ that the class is managed/garbage collected (\c {__gc}), and that \c
+ StatusString should be accessible as a property in languages that
+ support this concept (\c {__property}). We also declare an event
+ function \c statusStringChanged(String*) (\c {__event}), the
+ equivalent of the respective signal in the Qt class.
+
+ Before we can start implementing the wrapper class we need a way to
+ convert Qt's datatypes (and potentionally your own) into .NET
+ datatypes, e.g. \c QString objects need to be converted into objects
+ of type \c {String*}.
+
+ When operating on managed objects in normal C++ code, a little extra
+ care must be taken because of the CLR's garbage collection. A normal
+ pointer variable should not \footnote Indeed, the compiler will in
+ many cases disallow it. \endfootnote be used to refer to a managed
+ object. The reason is that the garbage collection can kick in at any
+ time and move the object to another place on the heap, leaving you
+ with an invalid pointer.
+
+ However, two methods are provided that solves this problem easily. The
+ first is to use a \e pinned pointer, i.e. declare the pointer variable
+ with the \c __pin keyword. This guarantees that the object pointed to
+ will not be moved by the garbage collector. It is recommended that
+ this method not be used to keep a references to managed objects for a
+ long time, since it will decrease the efficiency of the garbage
+ collector. The second way is to use the \c gcroot smartpointer
+ template type. This lets you create safe pointers to managed
+ objects. E.g. a variable of type \c gcroot<String> will always point
+ to the String object, even if it has been moved by the garbage
+ collector, and it can be used just like a normal pointer.
+
+ \snippet examples/activeqt/dotnet/wrapper/lib/tools.cpp 0
+ \codeline
+ \snippet examples/activeqt/dotnet/wrapper/lib/tools.cpp 1
+
+ The convertor functions can then be used in the wrapper class
+ implementation to call the functions in the native C++ class.
+
+ \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 0
+ \codeline
+ \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 1
+
+ The constructor and destructor simply create and destroy the Qt
+ object wrapped using the C++ operators \c new and \c delete.
+
+ \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 2
+
+ The netWorker class delegates calls from the .NET code to the native
+ code. Although the transition between those two worlds implies a small
+ performance hit for each function call, and for the type conversion,
+ this should be negligible since we are anyway going to run within the
+ CLR.
+
+ \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 3
+
+ The property setter calls the native Qt class before firing the
+ event using the \c __raise keyword.
+
+ This wrapper class can now be used in .NET code, e.g. using C++, C#,
+ Visual Basic or any other programming language available for .NET.
+
+ \snippet examples/activeqt/dotnet/wrapper/main.cs 0
+ \snippet examples/activeqt/dotnet/wrapper/main.cs 1
+ \snippet examples/activeqt/dotnet/wrapper/main.cs 2
+ \snippet examples/activeqt/dotnet/wrapper/main.cs 3
+
+ \section1 Walkthrough: .NET/COM Interop with ActiveQt
+
+ Fortunately .NET provides a generic wrapper for COM objects, the
+ \e {Runtime Callable Wrapper} (RCW). This RCW is a proxy for the
+ COM object and is generated by the CLR when a .NET Framework client
+ activates a COM object. This provides a generic way to reuse COM
+ objects in a .NET Framework project.
+
+ Making a QObject class into a COM object is easily achieved with
+ ActiveQt and demonstrated in the QAxServer examples (e.g., the
+ \l{activeqt/simple}{Simple} example). The walkthrough will use
+ the Qt classes implemented in those examples, so the first thing
+ to do is to make sure that those examples have been built
+ correctly, e.g. by opening the
+ \l{qaxserver-demo-multiple.html}{demonstration pages} in Internet
+ Explorer to verify that the controls are functional.
+
+ \section2 Starting a Project
+
+ Start Visual Studio.NET, and create a new C# project for writing a
+ Windows application. This will present you with an empty form in
+ Visual Studio's dialog editor. You should see the toolbox, which
+ presents you with a number of available controls and objects in
+ different categories. If you right-click on the toolbox it allows
+ you to add new tabs. We will add the tab "Qt".
+
+ \section2 Importing Qt Widgets
+
+ The category only has a pointer tool by default, and we have to add
+ the Qt objects we want to use in our form. Right-click on the empty
+ space, and select "Customize". This opens a dialog that has two
+ tabs, "COM Components" and ".NET Framework Components". We used
+ ActiveQt to wrap QWidgets into COM objects, so we select the "COM
+ Components" page, and look for the classes we want to use, e.g.
+ "QPushButton" and "QAxWidget2".
+
+ When we select those widgets and close the dialog the two widgets
+ will now be available from the toolbox as grey squares with their
+ name next to it \footnote Icons could be added by modifying the
+ way the controls register themselves. \endfootnote.
+
+ \section2 Using Qt Widgets
+
+ We can now add an instance of QAxWidget2 and a QPushButton to
+ the form. Visual Studio will automatically generate the RCW for the
+ object servers. The QAxWidget2 instance takes most of the upper
+ part of the form, with the QPushButton in the lower right corner.
+
+ In the property editor of Visual Studio we can modify the properties
+ of our controls - QPushButton exposes the \c QWidget API and has many
+ properties, while QAxWidget2 has only the Visual Studio standard
+ properties in addition to its own property "lineWidth" in the
+ "Miscellaneous" category. The objects are named "axQPushButton1" and
+ "axQAxWidget21", and since especially the last name is a bit
+ confusing we rename the objects to "resetButton" and "circleWidget".
+
+ We can also change the Qt properties, e.g. set the "text" property
+ of the \c resetButton to "Reset", and the "lineWidth" property of the
+ \c circleWidget to 5. We can also put those objects into the layout
+ system that Visual Studio's dialog editor provides, e.g. by setting
+ the anchors of the \c circleWidget to "Left, Top, Right, Bottom", and
+ the anchors of the \c resetButton to "Bottom, Right".
+
+ Now we can compile and start the project, which will open a user
+ interface with our two Qt widgets. If we can resize the dialog,
+ the widgets will resize appropriately.
+
+ \section2 Handling Qt Signals
+
+ We will now implement event handlers for the widgets. Select the
+ \c circleWidget and select the "Events" page in the property
+ editor. The widget exposes events because the QAxWidget2 class has
+ the "StockEvents" attribute set in its class definition. We implement
+ the event handler \c circleClicked for the \c ClickEvent to increase
+ the line width by one for every click:
+
+ \snippet examples/activeqt/dotnet/walkthrough/Form1.cs 0
+
+ In general we can implement a default event handler by double
+ clicking on the widget in the form, but the default events for
+ our widgets are right now not defined.
+
+ We will also implement an event handler for the \c clicked signal
+ emitted by QPushButton. Add the event handler \c resetLineWidth to
+ the \c clicked event, and implement the generated function:
+
+ \snippet examples/activeqt/dotnet/walkthrough/Form1.cs 1
+
+ We reset the property to 1, and also call the \c setFocus() slot
+ to simulate the user style on Windows, where a button grabs focus
+ when you click it (so that you can click it again with the spacebar).
+
+ If we now compile and run the project we can click on the circle
+ widget to increase its line width, and press the reset button to
+ set the line width back to 1.
+
+ \section1 Summary
+
+ Using ActiveQt as a universal interoperability bridge between the
+ .NET world and the native world of Qt is very easy, and makes it
+ often unnecessary to implement a lot of handwritten wrapper classes.
+ Instead, the QAxFactory implementation in the otherwise completely
+ cross-platform Qt project provides the glue that .NET needs to to
+ generate the RCW.
+
+ If this is not sufficient we can implement our own wrapper classes
+ thanks to the C++ extensions provided by Microsoft.
+
+ \section2 Limitations
+
+ All the limitations when using ActiveQt are implied when using this
+ technique to interoperate with .NET, e.g. the datatypes we can use
+ in the APIs can only be those supported by ActiveQt and COM. However,
+ since this includes subclasses of QObject and QWidget we can wrap
+ any of our datatypes into a QObject subclass to make its API
+ available to .NET. This has the positive side effect that the same
+ API is automatically available in
+ \l{http://qt.nokia.com/products/qsa/}{QSA}, the cross platform
+ scripting solution for Qt applications, and to COM clients in general.
+
+ When using the "IJW" method, in priciple the only limitation is the
+ time required to write the wrapper classes and data type conversion
+ functions.
+
+ \section2 Performance Considerations
+
+ Every call from CLR bytecode to native code implies a small
+ performance hit, and necessary type conversions introduce an
+ additional delay with every layer that exists between the two
+ frameworks. Consequently every approach to mix .NET and native
+ code should try to minimize the communication necessary between
+ the different worlds.
+
+ As ActiveQt introduces three layers at once - the RCW, COM and finally
+ ActiveQt itself - the performance penalty when using the generic
+ Qt/ActiveQt/COM/RCW/.NET bridge is larger than when using a
+ hand-crafted IJW-wrapper class. The execution speed however is still
+ sufficient for connecting to and modifying interactive elements in a
+ user interface, and as soon as the benefit of using Qt and C++ to
+ implement and compile performance critical algorithms into native code
+ kicks in, ActiveQt becomes a valid choice for making even non-visual
+ parts of your application accessible to .NET.
+
+ \sa {QtWinForms Solution}
+*/
diff --git a/doc/src/examples/hierarchy-demo-snippet.qdoc b/doc/src/examples/hierarchy-demo-snippet.qdoc
new file mode 100644
index 0000000..a36ebbb
--- /dev/null
+++ b/doc/src/examples/hierarchy-demo-snippet.qdoc
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [script]
+<script language="javascript">
+function createSubWidget( form )
+{
+ ParentWidget.createSubWidget( form.nameEdit.value );
+}
+
+function renameSubWidget( form )
+{
+ var SubWidget = ParentWidget.subWidget( form.nameEdit.value );
+ if ( !SubWidget ) {
+ alert( "No such widget " + form.nameEdit.value + "!" );
+ return;
+ }
+ SubWidget.label = form.labelEdit.value;
+ form.nameEdit.value = SubWidget.label;
+}
+
+function setFont( form )
+{
+ ParentWidget.font = form.fontEdit.value;
+}
+</script>
+
+<p>
+This widget can have many children!
+</p>
+<object ID="ParentWidget" CLASSID="CLSID:d574a747-8016-46db-a07c-b2b4854ee75c"
+CODEBASE="http://qt.nokia.com/demos/hierarchy.cab">
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+<form>
+<input type="edit" ID="nameEdit" value="&lt;enter object name&gt;" />
+<input type="button" value="Create" onClick="createSubWidget(this.form)" />
+<input type="edit" ID="labelEdit" />
+<input type="button" value="Rename" onClick="renameSubWidget(this.form)" />
+<br />
+<input type="edit" ID="fontEdit" value="MS Sans Serif" />
+<input type="button" value = "Set Font" onClick="setFont(this.form)" />
+</form>
+//! [script]
diff --git a/doc/src/examples/hierarchy-demo.qdocinc b/doc/src/examples/hierarchy-demo.qdocinc
new file mode 100644
index 0000000..86bfd87
--- /dev/null
+++ b/doc/src/examples/hierarchy-demo.qdocinc
@@ -0,0 +1,41 @@
+\raw HTML
+<script language="javascript">
+function createSubWidget( form )
+{
+ ParentWidget.createSubWidget( form.nameEdit.value );
+}
+
+function renameSubWidget( form )
+{
+ var SubWidget = ParentWidget.subWidget( form.nameEdit.value );
+ if ( !SubWidget ) {
+ alert( "No such widget " + form.nameEdit.value + "!" );
+ return;
+ }
+ SubWidget.label = form.labelEdit.value;
+ form.nameEdit.value = SubWidget.label;
+}
+
+function setFont( form )
+{
+ ParentWidget.font = form.fontEdit.value;
+}
+</script>
+
+<p>
+This widget can have many children!
+</p>
+<object ID="ParentWidget" CLASSID="CLSID:d574a747-8016-46db-a07c-b2b4854ee75c"
+CODEBASE="http://qt.nokia.com/demos/hierarchy.cab">
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+<form>
+<input type="edit" ID="nameEdit" value="&lt;enter object name&gt;" />
+<input type="button" value="Create" onClick="createSubWidget(this.form)" />
+<input type="edit" ID="labelEdit" />
+<input type="button" value="Rename" onClick="renameSubWidget(this.form)" />
+<br />
+<input type="edit" ID="fontEdit" value="MS Sans Serif" />
+<input type="button" value = "Set Font" onClick="setFont(this.form)" />
+</form>
+\endraw
diff --git a/doc/src/examples/hierarchy.qdoc b/doc/src/examples/hierarchy.qdoc
new file mode 100644
index 0000000..791af1f
--- /dev/null
+++ b/doc/src/examples/hierarchy.qdoc
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qaxserver-demo-hierarchy.html
+ \title Qt Widget Hierarchy
+
+ \input examples/activeqt/hierarchy-demo.qdocinc
+*/
+
+/*!
+ \example activeqt/hierarchy
+ \title Hierarchy Example (ActiveQt)
+
+ The Hierarchy example is shows how to write an in-process ActiveX
+ control. The control is a QWidget subclass with child widgets
+ that are accessible as sub-types.
+
+ \snippet examples/activeqt/hierarchy/objects.h 0
+ The \c QParentWidget class provides slots to create a widget
+ with a name, and to return a pointer to a named widget. The class
+ declaration uses \c Q_CLASSINFO() to provide the COM identifiers for
+ this class.
+
+ \snippet examples/activeqt/hierarchy/objects.cpp 0
+ The constructor of QParentWidget creates a vertical box layout.
+ New child widgets are automatically added to the layout.
+
+ \snippet examples/activeqt/hierarchy/objects.cpp 1
+ The \c createSubWidget slot creates a new \c QSubWidget with
+ the name provided in the parameter, and sets the label to that
+ name. The widget is also shown explicitly.
+
+ \snippet examples/activeqt/hierarchy/objects.cpp 2
+ The \c subWidget slot uses the \c QObject::child() function and
+ returns the first child of type \c QSubWidget that has the requested
+ name.
+
+ \snippet examples/activeqt/hierarchy/objects.h 1
+ The \c QSubWidget class has a single string-property \c label,
+ and implements the paintEvent to draw the label. The class uses
+ again \c Q_CLASSINFO to provide the COM identifiers, and also sets
+ the \e ToSuperClass attribute to \e QSubWidget, to ensure that only
+ no slots of any superclasses (i.e. QWidget) are exposed.
+
+ \snippet examples/activeqt/hierarchy/objects.cpp 3
+ \snippet examples/activeqt/hierarchy/objects.cpp 4
+ The implementation of the QSubWidget class is self-explanatory.
+
+ \snippet examples/activeqt/hierarchy/main.cpp 0
+ The classes are then exported using a QAxFactory. \c QParentWidget is
+ exported as a full class (which can be created ), while \c QSubWidget is
+ only exported as a type, which can only be created indirectly through
+ APIs of \c QParentWidget.
+
+ To build the example you must first build the QAxServer library.
+ Then run qmake and your make tool in \c examples/activeqt/hierarchy.
+
+ The \l{qaxserver-demo-hierarchy.html}{demonstration} requires
+ your WebBrowser to support ActiveX controls, and scripting to be
+ enabled.
+
+ \snippet examples/activeqt/hierarchy-demo-snippet.qdoc script
+*/
diff --git a/doc/src/examples/menus.qdoc b/doc/src/examples/menus.qdoc
new file mode 100644
index 0000000..5cbf063
--- /dev/null
+++ b/doc/src/examples/menus.qdoc
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qaxserver-demo-menus.html
+ \preliminary
+
+ \title Menubar Merging
+
+ This example is not full functional at the moment.
+
+ \raw HTML
+ <object ID="QMenus" CLASSID="CLSID:4dc3f340-a6f7-44e4-a79b-3e9217695fbd"
+ CODEBASE="http://qt.nokia.com/demos/menusax.cab">
+ [Object not available! Did you forget to build and register the server?]
+ </object>
+ \endraw
+*/
+
+/*!
+ \example activeqt/menus
+ \title Menus Example (ActiveQt)
+
+ The Menus example demonstrates the use of QMenuBar and QStatusBar
+ in a QMainWindow to implement an in-place active control.
+
+ To build the example you must first build the QAxServer library.
+ Then run \c qmake and your make tool in \c
+ examples/activeqt/menus.
+
+ The \l{qaxserver-demo-menus.html}{demonstration} requires your
+ WebBrowser to support ActiveX controls, and scripting to be
+ enabled.
+
+ \snippet doc/src/snippets/code/doc_src_examples_activeqt_menus.qdoc 0
+*/
diff --git a/doc/src/examples/multiple-demo.qdocinc b/doc/src/examples/multiple-demo.qdocinc
new file mode 100644
index 0000000..339fc20
--- /dev/null
+++ b/doc/src/examples/multiple-demo.qdocinc
@@ -0,0 +1,39 @@
+\raw HTML
+//! [0]
+<script language="javascript">
+function setColor( form )
+{
+ Ax1.fillColor = form.colorEdit.value;
+}
+
+function setWidth( form )
+{
+ Ax2.lineWidth = form.widthEdit.value;
+}
+</script>
+
+<p />
+This is one QWidget subclass:<br />
+<object ID="Ax1" CLASSID="CLSID:1D9928BD-4453-4bdd-903D-E525ED17FDE5"
+CODEBASE="http://qt.nokia.com/demos/multipleax.cab">
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+<form>
+Fill Color: <input type="edit" ID="colorEdit" value = "red" />
+<input type="button" value = "Set" onClick="setColor(this.form)" />
+<input type="button" value = "Hide" onClick="Ax1.hide()" />
+<input type="button" value = "Show" onClick="Ax1.show()" />
+</form>
+
+<p />
+This is another QWidget subclass:<br />
+<object ID="Ax2" CLASSID="CLSID:58139D56-6BE9-4b17-937D-1B1EDEDD5B71"
+CODEBASE="http://qt.nokia.com/demos/multipleax.cab">
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+<form>
+Line width: <input type="edit" ID="widthEdit" value = "1" />
+<input type="button" value = "Set" onClick="setWidth(this.form)" />
+</form>
+//! [0]
+\endraw
diff --git a/doc/src/examples/multiple.qdoc b/doc/src/examples/multiple.qdoc
new file mode 100644
index 0000000..1f58dcc
--- /dev/null
+++ b/doc/src/examples/multiple.qdoc
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qaxserver-demo-multiple.html
+ \title Two Simple Qt Widgets
+
+ \input examples/activeqt/multiple-demo.qdocinc
+*/
+
+/*!
+ \example activeqt/multiple
+ \title Multiple Example (ActiveQt)
+
+ The Multiple example demonstrates the implementation of a
+ QAxFactory to provide multiple ActiveX controls in a single in
+ process ActiveX server using the \c QAXFACTORY_EXPORT() macro.
+ The ActiveX controls in this example are simple QWidget
+ subclasses that reimplement QWidget::paintEvent().
+
+ \snippet examples/activeqt/multiple/ax1.h 0
+
+ The first control draws a filled rectangle. The fill color is exposed
+ as a property. \c Q_CLASSINFO() is used to specify the COM identifiers.
+
+ \snippet examples/activeqt/multiple/ax2.h 0
+
+ The second control draws a circle. The linewith is exposed as a property.
+ \c Q_CLASSINFO() is used to specify the COM identifiers, and to set the
+ attributes \e ToSuperClass and \e StockEvents to expose only the API of
+ the class itself, and to add COM stock events to the ActiveX control.
+
+ \snippet examples/activeqt/multiple/main.cpp 0
+
+ The classes are exported from the server using the QAxFactory macros.
+
+ To build the example you must first build the QAxServer library.
+ Then run \c qmake and your make tool in \c
+ examples/activeqt/multiple.
+
+ The \l{qaxserver-demo-multiple.html}{demonstration} requires your
+ WebBrowser to support ActiveX controls, and scripting to be
+ enabled.
+
+ \snippet examples/activeqt/multiple-demo.qdocinc 0
+*/
diff --git a/doc/src/examples/opengl-demo.qdocinc b/doc/src/examples/opengl-demo.qdocinc
new file mode 100644
index 0000000..ccc1452
--- /dev/null
+++ b/doc/src/examples/opengl-demo.qdocinc
@@ -0,0 +1,27 @@
+\raw HTML
+//! [0]
+<SCRIPT LANGUAGE="JavaScript">
+function setRot( form )
+{
+ GLBox.setXRotation( form.XEdit.value );
+ GLBox.setYRotation( form.YEdit.value );
+ GLBox.setZRotation( form.ZEdit.value );
+}
+</SCRIPT>
+
+<p />
+An OpenGL scene:<br />
+<object ID="GLBox" CLASSID="CLSID:5fd9c22e-ed45-43fa-ba13-1530bb6b03e0"
+CODEBASE="http://qt.nokia.com/demos/openglax.cab">
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+
+<form>
+Rotate the scene:<br />
+X:<input type="edit" ID="XEdit" value="0" /><br />
+Y:<input type="edit" name="YEdit" value="0" /><br />
+Z:<input type="edit" name="ZEdit" value="0" /><br />
+<input type="button" value="Set" onClick="setRot(this.form)" />
+</form>
+//! [0]
+\endraw
diff --git a/doc/src/examples/opengl.qdoc b/doc/src/examples/opengl.qdoc
new file mode 100644
index 0000000..4f64eff
--- /dev/null
+++ b/doc/src/examples/opengl.qdoc
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qaxserver-demo-opengl.html
+
+ \title OpenGL in an HTML page
+
+ \raw HTML
+ <SCRIPT LANGUAGE="JavaScript">
+ function setRot( form )
+ {
+ GLBox.setXRotation( form.XEdit.value );
+ GLBox.setYRotation( form.YEdit.value );
+ GLBox.setZRotation( form.ZEdit.value );
+ }
+ </SCRIPT>
+
+ <p />
+ An OpenGL scene:<br />
+ <object ID="GLBox" CLASSID="CLSID:5fd9c22e-ed45-43fa-ba13-1530bb6b03e0"
+ CODEBASE="http://qt.nokia.com/demos/openglax.cab">
+ [Object not available! Did you forget to build and register the server?]
+ </object><br />
+
+ <form>
+ Rotate the scene:<br />
+ X:<input type="edit" ID="XEdit" value="0" /><br />
+ Y:<input type="edit" name="YEdit" value="0" /><br />
+ Z:<input type="edit" name="ZEdit" value="0" /><br />
+ <input type="button" value="Set" onClick="setRot(this.form)" />
+ </form>
+ \endraw
+*/
+
+/*!
+ \example activeqt/opengl
+ \title OpenGL Example (ActiveQt)
+
+ The OpenGL example demonstrates the use of the default factory
+ and QAxFactory::isServer(), and the implementation of an
+ additional COM interface using QAxBindable and QAxAggregated.
+ The server executable can run both as an ActiveX server and as a
+ stand-alone application.
+
+ The ActiveX control in this example uses the QGlWidget class in
+ Qt to render an OpenGL scene in an ActiveX. The control exposes a few
+ methods to change the scene.
+
+ The application uses the default factory as provided by the
+ QAXFACTORY_DEFAULT macro to expose the \c GLBox widget as an ActiveX
+ control.
+ \snippet examples/activeqt/opengl/main.cpp 0
+ The implementation of \c main initializes the QApplication object,
+ and uses \c QAxFactory::isServer() to determine whether or not it is
+ appropriate to create and show the application interface.
+ \snippet examples/activeqt/opengl/main.cpp 1
+ \snippet examples/activeqt/opengl/main.cpp 2
+ \snippet examples/activeqt/opengl/main.cpp 3
+
+ The \c GLBox class inherits from both the \l QGLWidget class to be able
+ to render OpenGL, and from \l QAxBindable.
+ \snippet examples/activeqt/opengl/glbox.h 0
+ The class reimplements the \l QAxBindable::createAggregate() function from QAxBindable
+ to return the pointer to a \l QAxAggregated object.
+ \snippet examples/activeqt/opengl/glbox.h 1
+ The rest of the class declaration and the implementation of the OpenGL
+ rendering is identical to the original "box" example.
+
+ The implementation file of the \c GLBox class includes the \c objsafe.h
+ system header, in which the \c IObjectSafety COM interface is defined.
+ \snippet examples/activeqt/opengl/glbox.cpp 0
+ A class \c ObjectSafetyImpl is declared using multiple inheritance
+ to subclass the QAxAggregated class, and to implement the IObjectSafety
+ interface.
+ \snippet examples/activeqt/opengl/glbox.cpp 1
+ The class declares a default constructor, and implements the queryInterface
+ function to support the IObjectSafety interface.
+ \snippet examples/activeqt/opengl/glbox.cpp 2
+ Since every COM interface inherits \c IUnknown the \c QAXAGG_IUNKNOWN macro
+ is used to provide the default implementation of the \c IUnknown interface.
+ The macro is defined to delegate all calls to \c QueryInterface, \c AddRef
+ and \c Release to the interface returned by the controllingUnknown() function.
+ \snippet examples/activeqt/opengl/glbox.cpp 3
+ The implementation of the \c IObjectSafety interface provides the caller
+ with information about supported and enabled safety options, and returns
+ \c S_OK for all calls to indicate that the ActiveX control is safe.
+ \snippet examples/activeqt/opengl/glbox.cpp 4
+ The implementation of the \c createAggregate() function just returns a new
+ \c ObjectSafetyImpl object.
+ \snippet examples/activeqt/opengl/glbox.cpp 5
+
+ To build the example you must first build the QAxServer library.
+ Then run \c qmake and your make tool in \c
+ examples/activeqt/wrapper.
+
+ The \l{qaxserver-demo-opengl.html}{demonstration} requires your
+ WebBrowser to support ActiveX controls, and scripting to be
+ enabled.
+
+ In contrast to the other QAxServer examples Internet Explorer will not
+ open a dialog box to ask the user whether or not the scripting of the GLBox
+ control should be allowed (the exact browser behaviour depends on the security
+ settings in the Internet Options dialog).
+
+ \snippet doc/src/examples/activeqt/opengl-demo.qdocinc 0
+*/
diff --git a/doc/src/examples/qutlook.qdoc b/doc/src/examples/qutlook.qdoc
new file mode 100644
index 0000000..e701c59
--- /dev/null
+++ b/doc/src/examples/qutlook.qdoc
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example activeqt/qutlook
+ \title Qutlook Example (ActiveQt)
+
+ The Qutlook example demonstrates the use of ActiveQt to automate
+ Outlook. The example makes use of the \l dumpcpp tool to generate
+ a C++ namespace for the type library describing the Outlook
+ Object Model.
+
+ The project file for the example looks like this:
+
+ \snippet examples/activeqt/qutlook/qutlook.pro 1
+ \snippet examples/activeqt/qutlook/qutlook.pro 2
+
+ The project file uses the \c dumpcpp tool to add an MS Outlook type library to the project.
+ If this fails, then the generated makefile will just print an error message, otherwise
+ the build step will now run the \e dumpcpp tool on the type library, and
+ generate a header and a cpp file (in this case, \c msoutl.h and \c msoutl.cpp) that
+ declares and implement an easy to use API to the Outlook objects.
+
+ \snippet examples/activeqt/qutlook/addressview.h 0
+
+ The AddressView class is a QWidget subclass for the user interface. The QTreeView widget
+ will display the contents of Outlook's Contact folder as provided by the \c{model}.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 0
+ The AddressBookModel class is a QAbstractListModel subclass that communicates directly with
+ Outlook, using a QHash for caching.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 1
+ The constructor initializes Outlook. The various signals Outlook provides to notify about
+ contents changes are connected to the \c updateOutlook() slot.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 2
+ The destructor logs off from the session.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 3
+ The \c rowCount() implementation returns the number of entries as reported by Outlook. \c columnCount
+ and \c headerData are implemented to show four columns in the tree view.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 4
+ The \c headerData() implementation returns hardcoded strings.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 5
+ The \c data() implementation is the core of the model. If the requested data is in the cache the
+ cached value is used, otherwise the data is acquired from Outlook.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 6
+ The \c changeItem() slot is called when the user changes the current entry using the user interface.
+ The Outlook item is accessed using the Outlook API, and is modified using the property setters.
+ Finally, the item is saved to Outlook, and removed from the cache. Note that the model does not
+ signal the view of the data change, as Outlook will emit a signal on its own.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 7
+ The \c addItem() slot calls the CreateItem method of Outlook to create a new contact item,
+ sets the properties of the new item to the values entered by the user and saves the item.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 8
+ The \c update() slot clears the cache, and emits the reset() signal to notify the view about the
+ data change requiring a redraw of the contents.
+
+ \snippet examples/activeqt/qutlook/addressview.cpp 9
+ \snippet examples/activeqt/qutlook/addressview.cpp 10
+ The rest of the file implements the user interface using only Qt APIs, i.e. without communicating
+ with Outlook directly.
+
+ \snippet examples/activeqt/qutlook/main.cpp 0
+
+ The \c main() entry point function finally instantiates the user interface and enters the
+ event loop.
+
+ To build the example you must first build the QAxContainer
+ library. Then run your make tool in \c examples/activeqt/qutlook
+ and run the resulting \c qutlook.exe.
+*/
diff --git a/doc/src/examples/simple-demo.qdocinc b/doc/src/examples/simple-demo.qdocinc
new file mode 100644
index 0000000..5eee8bc
--- /dev/null
+++ b/doc/src/examples/simple-demo.qdocinc
@@ -0,0 +1,45 @@
+\raw HTML
+//! [0]
+<object ID="QSimpleAX" CLASSID="CLSID:DF16845C-92CD-4AAB-A982-EB9840E74669"
+CODEBASE="http://qt.nokia.com/demos/simpleax.cab">
+ <PARAM NAME="text" VALUE="A simple control" />
+ <PARAM NAME="value" VALUE="1" />
+[Object not available! Did you forget to build and register the server?]
+</object>
+//! [0] //! [1]
+
+<FORM>
+ <INPUT TYPE="BUTTON" VALUE="About..." onClick="QSimpleAX.about()" />
+</FORM>
+//! [1]
+
+//! [2]
+<object ID="Calendar" CLASSID="CLSID:8E27C92B-1264-101C-8A2F-040224009C02">
+[Standard Calendar control not available!]
+ <PARAM NAME="day" VALUE="1" />
+</object>
+//! [2]
+
+<FORM>
+ <INPUT TYPE="BUTTON" VALUE="Today" onClick="Calendar.Today()" />
+</FORM>
+
+//! [3]
+<SCRIPT LANGUAGE="VBScript">
+Sub Calendar_Click()
+ MsgBox( "Calendar Clicked!" )
+End Sub
+
+Sub QSimpleAX_TextChanged( str )
+ document.title = str
+End Sub
+</SCRIPT>
+
+<SCRIPT LANGUAGE="JavaScript">
+function QSimpleAX::ValueChanged( Newvalue )
+{
+ Calendar.Day = Newvalue;
+}
+</SCRIPT>
+//! [3]
+\endraw
diff --git a/doc/src/examples/simple.qdoc b/doc/src/examples/simple.qdoc
new file mode 100644
index 0000000..b0e942f
--- /dev/null
+++ b/doc/src/examples/simple.qdoc
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qaxserver-demo-simple.html
+
+ \title A standard ActiveX and the "simple" ActiveQt widget
+
+ \raw HTML
+ <object ID="QSimpleAX" CLASSID="CLSID:DF16845C-92CD-4AAB-A982-EB9840E74669"
+ CODEBASE="http://qt.nokia.com/demos/simpleax.cab">
+ <PARAM NAME="text" VALUE="A simple control" />
+ <PARAM NAME="value" VALUE="1" />
+ [Object not available! Did you forget to build and register the server?]
+ </object>
+
+ <FORM>
+ <INPUT TYPE="BUTTON" VALUE="About..." onClick="QSimpleAX.about()" />
+ </FORM>
+
+ <object ID="Calendar" CLASSID="CLSID:8E27C92B-1264-101C-8A2F-040224009C02">
+ [Standard Calendar control not available!]
+ <PARAM NAME="day" VALUE="1" />
+ </object>
+
+ <FORM>
+ <INPUT TYPE="BUTTON" VALUE="Today" onClick="Calendar.Today()" />
+ </FORM>
+
+ <SCRIPT LANGUAGE="VBScript">
+ Sub Calendar_Click()
+ MsgBox( "Calendar Clicked!" )
+ End Sub
+
+ Sub QSimpleAX_TextChanged( str )
+ document.title = str
+ End Sub
+ </SCRIPT>
+
+ <SCRIPT LANGUAGE="JavaScript">
+ function QSimpleAX::ValueChanged( Newvalue )
+ {
+ Calendar.Day = Newvalue;
+ }
+ </SCRIPT>
+ \endraw
+*/
+
+/*!
+ \example activeqt/simple
+ \title Simple Example (ActiveQt)
+
+ The Simple example demonstrates the use of
+ QAxBindable::requestPropertyChange() and
+ QAxBindable::propertyChanged(), and the use of the default
+ QAxFactory through the \c QAXFACTORY_DEFAULT() macro.
+
+ The ActiveX control in this example is a laid out QWidget with a
+ QSlider, a QLCDNumber and a QLineEdit. It provides a
+ signal/slot/property interface to change the values of the slider
+ and the line edit, and to get notified of any property changes.
+
+
+ The Qt implementation of the ActiveX for this example is
+ \snippet examples/activeqt/simple/main.cpp 0
+
+ The control is exported using the default QAxFactory
+ \snippet examples/activeqt/simple/main.cpp 1
+
+ To build the example you must first build the QAxServer library.
+ Then run qmake and your make tool in \c examples/activeqt/simple.
+
+ The \l{qaxserver-demo-simple.html}{demonstration} requires your
+ WebBrowser to support ActiveX controls, and scripting to be enabled.
+
+ The simple ActiveX control is embedded using the \c <object> tag.
+
+ \snippet doc/src/examples/activeqt/simple-demo.qdocinc 0
+
+ A simple HTML button is connected to the ActiveQt's about() slot.
+
+ \snippet doc/src/examples/activeqt/simple-demo.qdocinc 1
+
+ A second ActiveX control - the standard Calendar Control - is instantiated
+
+ \snippet doc/src/examples/activeqt/simple-demo.qdocinc 2
+
+ Events from the ActiveX controls are handled using both Visual Basic Script
+ and JavaScript.
+
+ \snippet doc/src/examples/activeqt/simple-demo.qdocinc 3
+*/
diff --git a/doc/src/examples/webbrowser.qdoc b/doc/src/examples/webbrowser.qdoc
new file mode 100644
index 0000000..ac9cec5
--- /dev/null
+++ b/doc/src/examples/webbrowser.qdoc
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example activeqt/webbrowser
+ \title Web Browser Example (ActiveQt)
+
+ The Web Browser example uses the Microsoft Web Browser
+ ActiveX control to implement a fully functional Web Browser
+ application. The user interface has been developed using the Qt
+ Designer integration of the QAxWidget class.
+
+ The code demonstrates how the Qt application can communicate
+ with the embedded ActiveX controls using signals, slots and the
+ dynamicCall() function.
+
+ \snippet examples/activeqt/webbrowser/main.cpp 0
+
+ The \c MainWindow class declares a \c QMainWindow based user interface,
+ using the \c Ui::MainWindow class generated by Qt Designer. A number
+ of slots are implemented to handle events from the various user
+ interface elements, including the \c WebBrowser object, which is a
+ QAxWidget hosting the Microsoft Web Browser control.
+
+ \snippet examples/activeqt/webbrowser/main.cpp 1
+
+ The constructor initializes the user interface, installs a
+ progress bar on the status bar, and uses QAxBase::dynamicCall()
+ to invoke the \c GoHome() method of Internet Explorer to
+ navigate to the user's home page.
+
+ \snippet examples/activeqt/webbrowser/main.cpp 2
+ Different slots handle the signals emitted by the WebBrowser object.
+
+ Connections that don't require any coding, i.e. connecting the \c back
+ action to the \c GoBack() slot, have already been made in Qt Designer.
+
+ \snippet examples/activeqt/webbrowser/main.cpp 3
+ \snippet examples/activeqt/webbrowser/main.cpp 4
+
+ The rest of the implementation is not related to ActiveQt - the actions
+ are handled by different slots, and the entry point function starts the
+ application using standard Qt APIs.
+
+ To build the example you must first build the QAxContainer
+ library. Then run your make tool in \c
+ examples/activeqt/webbrowser and run the resulting \c
+ webbrowser.exe.
+*/
diff --git a/doc/src/examples/wrapper-demo.qdocinc b/doc/src/examples/wrapper-demo.qdocinc
new file mode 100644
index 0000000..a00c505
--- /dev/null
+++ b/doc/src/examples/wrapper-demo.qdocinc
@@ -0,0 +1,51 @@
+\raw HTML
+//! [0]
+<SCRIPT LANGUAGE="VBScript">
+Sub ToolButton_Clicked()
+ RadioButton.text = InputBox( "Enter something", "Wrapper Demo" )
+End Sub
+
+Sub PushButton_clicked()
+ MsgBox( "Thank you!" )
+End Sub
+
+Sub CheckBox_toggled( state )
+ if state = 0 then
+ CheckBox.text = "Check me!"
+ else
+ CheckBox.text = "Uncheck me!"
+ end if
+End Sub
+</SCRIPT>
+<p />
+A QPushButton:<br />
+<object ID="PushButton" CLASSID="CLSID:2B262458-A4B6-468B-B7D4-CF5FEE0A7092"
+CODEBASE="http://qt.nokia.com/demos/wrapperax.cab">
+ <PARAM NAME="text" VALUE="Click me!" />
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+
+<p />
+A QCheckBox:<br />
+<object ID="CheckBox" CLASSID="CLSID:6E795de9-872d-43cf-a831-496ef9d86c68"
+CODEBASE="http://qt.nokia.com/demos/wrapperax.cab">
+ <PARAM NAME="text" VALUE="Check me!" />
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+
+<p />
+A QToolButton:<br />
+<object ID="ToolButton" CLASSID="CLSID:7c0ffe7a-60c3-4666-bde2-5cf2b54390a1"
+CODEBASE="http://qt.nokia.com/demos/wrapperax.cab">
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+
+<p />
+A QRadioButton:<br />
+<object ID="RadioButton" CLASSID="CLSID:afcf78c8-446c-409a-93b3-ba2959039189"
+CODEBASE="http://qt.nokia.com/demos/wrapperax.cab">
+ <PARAM NAME="text" VALUE="Tune me!" />
+[Object not available! Did you forget to build and register the server?]
+</object><br />
+//! [0]
+\endraw
diff --git a/doc/src/examples/wrapper.qdoc b/doc/src/examples/wrapper.qdoc
new file mode 100644
index 0000000..980757c
--- /dev/null
+++ b/doc/src/examples/wrapper.qdoc
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qaxserver-demo-wrapper.html
+
+ \title Standard Qt widgets in an HTML page
+
+ \input examples/activeqt/wrapper-demo.qdocinc
+*/
+
+/*!
+ \example activeqt/wrapper
+ \title Wrapper Example (ActiveQt)
+
+ The Wrapper example demonstrates how to export existing QWidget
+ classes as ActiveX controls, and the use of QAxFactory together
+ with the \c QAXFACTORY_EXPORT() macro. ActiveX controls in this
+ example are the standard button classes QPushButton, QCheckBox
+ and QRadioButton as provided by Qt.
+
+ \snippet examples/activeqt/wrapper/main.cpp 0
+ The factory implementation returns the list of supported controls,
+ creates controls on request and provides information about the unique
+ IDs of the COM classes and interfaces for each control.
+
+ \snippet examples/activeqt/wrapper/main.cpp 1
+ The factory is exported using the QAXFACTORY_EXPORT macro.
+
+ To build the example you must first build the QAxServer library.
+ Then run \c qmake and your make tool in \c
+ examples/activeqt/wrapper.
+
+ The \l{qaxserver-demo-wrapper.html}{demonstration} requires a
+ web browser that supports ActiveX controls, and scripting to be
+ enabled.
+
+ \snippet examples/activeqt/wrapper-demo.qdocinc 0
+*/
diff --git a/doc/src/snippets/code/doc_src_examples_activeqt_comapp.qdoc b/doc/src/snippets/code/doc_src_examples_activeqt_comapp.qdoc
new file mode 100644
index 0000000..40ee834
--- /dev/null
+++ b/doc/src/snippets/code/doc_src_examples_activeqt_comapp.qdoc
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+Private Application As comappLib.Application
+Private MyApp As Boolean
+
+Private Sub UpdateList()
+ DocumentList.Clear
+ DocumentsCount.Caption = Application.documents.Count
+ For Index = 0 To Application.documents.Count - 1
+ DocumentList.AddItem (Application.documents.Item(Index).Title)
+ Next
+End Sub
+
+Private Sub Form_Load()
+ On Error GoTo CreateNew
+ Set Application = GetObject(, "comapp.Application")
+ MyApp = False
+ GoTo Initialized
+CreateNew:
+ On Error GoTo InitializeFailed
+ Set Application = New Application
+ Application.Visible = True
+ MyApp = True
+Initialized:
+ Caption = Application.id
+ UpdateList
+InitializeFailed:
+End Sub
+
+Private Sub Form_Unload(Cancel As Integer)
+ If MyApp Then
+ Application.quit
+ End If
+End Sub
+
+Private Sub NewDocument_Click()
+ Application.documents.addDocument
+ UpdateList
+End Sub
+//! [0]
diff --git a/doc/src/snippets/code/doc_src_examples_activeqt_dotnet.qdoc b/doc/src/snippets/code/doc_src_examples_activeqt_dotnet.qdoc
new file mode 100644
index 0000000..74c869e
--- /dev/null
+++ b/doc/src/snippets/code/doc_src_examples_activeqt_dotnet.qdoc
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+' VB is case insensitive, but our C++ controls are not.
+' Me.resetButton.enabled = True
+//! [0]
diff --git a/doc/src/snippets/code/doc_src_examples_activeqt_menus.qdoc b/doc/src/snippets/code/doc_src_examples_activeqt_menus.qdoc
new file mode 100644
index 0000000..a6f42aa
--- /dev/null
+++ b/doc/src/snippets/code/doc_src_examples_activeqt_menus.qdoc
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+<object ID="QMenus" CLASSID="CLSID:4dc3f340-a6f7-44e4-a79b-3e9217695fbd"
+CODEBASE="http://qt.nokia.com/demos/menusax.cab">
+[Object not available! Did you forget to build and register the server?]
+</object>
+//! [0]
diff --git a/doc/src/snippets/code/doc_src_qaxcontainer.pro b/doc/src/snippets/code/doc_src_qaxcontainer.pro
new file mode 100644
index 0000000..ff39e67
--- /dev/null
+++ b/doc/src/snippets/code/doc_src_qaxcontainer.pro
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#! [0]
+CONFIG += qaxcontainer
+#! [0]
+
+
+#! [1]
+TYPELIBS = file.tlb
+#! [1]
diff --git a/doc/src/snippets/code/doc_src_qaxserver.cpp b/doc/src/snippets/code/doc_src_qaxserver.cpp
new file mode 100644
index 0000000..dc16776
--- /dev/null
+++ b/doc/src/snippets/code/doc_src_qaxserver.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [3]
+#include <QWidget>
+
+class MyActiveX : public QWidget
+{
+ Q_OBJECT
+//! [3]
+
+
+//! [4]
+Q_CLASSINFO("ClassID", "{1D9928BD-4453-4bdd-903D-E525ED17FDE5}")
+Q_CLASSINFO("InterfaceID", "{99F6860E-2C5A-42ec-87F2-43396F4BE389}")
+Q_CLASSINFO("EventsID", "{0A3E9F27-E4F1-45bb-9E47-63099BCCD0E3}")
+//! [4]
+
+
+//! [5]
+Q_PROPERTY(int value READ value WRITE setValue)
+//! [5]
+
+
+//! [6]
+public:
+ MyActiveX(QWidget *parent = 0)
+ ...
+
+ int value() const;
+
+public slots:
+ void setValue(int v);
+ ...
+
+signals:
+ void valueChange(int v);
+ ...
+
+};
+//! [6]
+
+
+//! [7]
+#include <QAxBindable>
+#include <QWidget>
+
+class MyActiveX : public QWidget, public QAxBindable
+{
+ Q_OBJECT
+//! [7]
+
+
+//! [8]
+QAXFACTORY_BEGIN("{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}",
+ "{a8f21901-7ff7-4f6a-b939-789620c03d83}")
+ QAXCLASS(MyWidget)
+ QAXCLASS(MyWidget2)
+ QAXTYPE(MySubType)
+QAXFACTORY_END()
+//! [8]
+
+
+//! [9]
+#include <QApplication>
+#include <QAxFactory>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ if (!QAxFactory::isServer()) {
+ // create and show main window
+ }
+ return app.exec();
+}
+//! [9]
+
+
+//! [10]
+MyFactory(const QUuid &, const QUuid &);
+//! [10]
+
+
+//! [11]
+HMODULE dll = LoadLibrary("myserver.dll");
+typedef HRESULT(__stdcall *DllRegisterServerProc)();
+DllRegisterServerProc DllRegisterServer =
+ (DllRegisterServerProc)GetProcAddress(dll, "DllRegisterServer");
+
+HRESULT res = E_FAIL;
+if (DllRegisterServer)
+ res = DllRegisterServer();
+if (res != S_OK)
+ // error handling
+//! [11]
+
+
+//! [15]
+class MyActiveX : public QWidget
+{
+ Q_OBJECT
+ Q_CLASSINFO("Version", "2.0")
+ Q_CLASSINFO("ClassID", "{7a4cffd8-cbcd-4ae9-ae7e-343e1e5710df}")
+ Q_CLASSINFO("InterfaceID", "{6fb035bf-8019-48d8-be51-ef05427d8994}")
+ Q_CLASSINFO("EventsID", "{c42fffdf-6557-47c9-817a-2da2228bc29c}")
+ Q_CLASSINFO("Insertable", "yes")
+ Q_CLASSINFO("ToSuperClass", "MyActiveX")
+ Q_PROPERTY(...)
+
+public:
+ MyActiveX(QWidget *parent = 0);
+
+ ...
+};
+//! [15]
+
+
+//! [16]
+class MyLicensedControl : public QWidget
+{
+ Q_OBJECT
+ Q_CLASSINFO("LicenseKey", "<key string>")
+ ...
+};
+//! [16]
+
+
+//! [17]
+class AxImpl : public QAxAggregated, public ISomeCOMInterface
+{
+public:
+ AxImpl() {}
+
+ long queryInterface(const QUuid &iid, void **iface);
+
+ // IUnknown
+ QAXAGG_IUNKNOWN
+
+ // ISomeCOMInterface
+ ...
+}
+//! [17]
+
+
+//! [18]
+long AxImpl::queryInterface(const QUuid &iid, void **iface)
+{
+ *iface = 0;
+ if (iid == IID_ISomeCOMInterface)
+ *iface = (ISomeCOMInterface *)this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+}
+//! [18]
+
+
+//! [19]
+HRESULT AxImpl::QueryInterface(REFIID iid, void **iface)
+{
+ return controllingUnknown()->QueryInterface(iid, iface);
+}
+//! [19]
+
+
+//! [20]
+class MyActiveX : public QWidget, public QAxBindable
+{
+ Q_OBJECT
+
+public:
+ MyActiveX(QWidget *parent);
+
+ QAxAggregated *createAggregate()
+ {
+ return new AxImpl();
+ }
+};
+//! [20]
diff --git a/doc/src/snippets/code/doc_src_qaxserver.pro b/doc/src/snippets/code/doc_src_qaxserver.pro
new file mode 100644
index 0000000..18d66f3
--- /dev/null
+++ b/doc/src/snippets/code/doc_src_qaxserver.pro
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#! [0]
+TEMPLATE = app
+CONFIG += qaxserver
+
+RC_FILE = qaxserver.rc
+...
+#! [0]
+
+
+#! [1]
+TEMPLATE = lib
+CONFIG += qaxserver dll
+
+DEF_FILE = qaxserver.def
+RC_FILE = qaxserver.rc
+...
+#! [1]
+
+
+#! [2]
+TEMPLATE = lib
+VERSION = 2.5
+...
+#! [2]
diff --git a/doc/src/snippets/code/doc_src_qaxserver.qdoc b/doc/src/snippets/code/doc_src_qaxserver.qdoc
new file mode 100644
index 0000000..2fd79e3
--- /dev/null
+++ b/doc/src/snippets/code/doc_src_qaxserver.qdoc
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [12]
+cabarc N simpleax.cab simpleax.exe simple.inf
+//! [12]
+
+
+//! [13]
+<object ID="MyActiveX1" CLASSID="CLSID:ad90301a-849e-4e8b-9a91-0a6dc5f6461f">
+ ...
+<\object>
+//! [13]
+
+
+//! [14]
+<object ID=...>
+ <param name="name" value="value">
+<\object>
+//! [14]
diff --git a/doc/src/snippets/code/src_activeqt_container_qaxbase.cpp b/doc/src/snippets/code/src_activeqt_container_qaxbase.cpp
new file mode 100644
index 0000000..5df221e
--- /dev/null
+++ b/doc/src/snippets/code/src_activeqt_container_qaxbase.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+connect(buttonBack, SIGNAL(clicked()), webBrowser, SLOT(GoBack()));
+//! [0]
+
+
+//! [1]
+activeX->setProperty("text", "some text");
+int value = activeX->property("value");
+//! [1]
+
+
+//! [2]
+webBrowser->dynamicCall("GoHome()");
+//! [2]
+
+
+//! [3]
+connect(webBrowser, SIGNAL(TitleChanged(QString)),
+ this, SLOT(setCaption(QString)));
+//! [3]
+
+
+//! [4]
+dispinterface IControl
+{
+properties:
+ [id(1)] BSTR text;
+ [id(2)] IFontDisp *font;
+
+methods:
+ [id(6)] void showColumn([in] int i);
+ [id(3)] bool addColumn([in] BSTR t);
+ [id(4)] int fillList([in, out] SAFEARRAY(VARIANT) *list);
+ [id(5)] IDispatch *item([in] int i);
+};
+//! [4]
+
+
+//! [5]
+QAxObject object("<CLSID>");
+
+QString text = object.property("text").toString();
+object.setProperty("font", QFont("Times New Roman", 12));
+
+connect(this, SIGNAL(clicked(int)), &object, SLOT(showColumn(int)));
+bool ok = object.dynamicCall("addColumn(const QString&)", "Column 1").toBool();
+
+QList<QVariant> varlist;
+QList<QVariant> parameters;
+parameters << QVariant(varlist);
+int n = object.dynamicCall("fillList(QList<QVariant>&)", parameters).toInt();
+
+QAxObject *item = object.querySubItem("item(int)", 5);
+//! [5]
+
+
+//! [6]
+IUnknown *iface = 0;
+activeX->queryInterface(IID_IUnknown, (void**)&iface);
+if (iface) {
+ // use the interface
+ iface->Release();
+}
+//! [6]
+
+
+//! [7]
+ctrl->setControl("{8E27C92B-1264-101C-8A2F-040224009C02}");
+//! [7]
+
+
+//! [8]
+ctrl->setControl("MSCal.Calendar");
+//! [8]
+
+
+//! [9]
+ctrl->setControl("Calendar Control 9.0");
+//! [9]
+
+
+//! [10]
+ctrl->setControl("c:/files/file.doc");
+//! [10]
+
+
+//! [11]
+<domain/username>:<password>@server/{8E27C92B-1264-101C-8A2F-040224009C02}
+//! [11]
+
+
+//! [12]
+{8E27C92B-1264-101C-8A2F-040224009C02}:<LicenseKey>
+//! [12]
+
+
+//! [13]
+{8E27C92B-1264-101C-8A2F-040224009C02}&
+//! [13]
+
+
+//! [14]
+ctrl->setControl("DOMAIN/user:password@server/{8E27C92B-1264-101C-8A2F-040224009C02}:LicenseKey");
+//! [14]
+
+
+//! [15]
+activeX->dynamicCall("Navigate(const QString&)", "qt.nokia.com");
+//! [15]
+
+
+//! [16]
+activeX->dynamicCall("Navigate(\"qt.nokia.com\")");
+//! [16]
+
+
+//! [17]
+activeX->dynamicCall("Value", 5);
+QString text = activeX->dynamicCall("Text").toString();
+//! [17]
+
+
+//! [18]
+IWebBrowser2 *webBrowser = 0;
+activeX->queryInterface(IID_IWebBrowser2, (void **)&webBrowser);
+if (webBrowser) {
+ webBrowser->Navigate2(pvarURL);
+ webBrowser->Release();
+}
+//! [18]
+
+
+//! [19]
+QAxWidget outlook("Outlook.Application");
+QAxObject *session = outlook.querySubObject("Session");
+if (session) {
+ QAxObject *defFolder = session->querySubObject(
+ "GetDefaultFolder(OlDefaultFolders)",
+ "olFolderContacts");
+ //...
+}
+//! [19]
+
+
+//! [20]
+void Receiver::slot(const QString &name, int argc, void *argv)
+{
+ VARIANTARG *params = (VARIANTARG*)argv;
+ if (name.startsWith("BeforeNavigate2(")) {
+ IDispatch *pDisp = params[argc-1].pdispVal;
+ VARIANTARG URL = *params[argc-2].pvarVal;
+ VARIANTARG Flags = *params[argc-3].pvarVal;
+ VARIANTARG TargetFrameName = *params[argc-4].pvarVal;
+ VARIANTARG PostData = *params[argc-5].pvarVal;
+ VARIANTARG Headers = *params[argc-6].pvarVal;
+ bool *Cancel = params[argc-7].pboolVal;
+ }
+}
+//! [20]
diff --git a/doc/src/snippets/code/src_activeqt_container_qaxscript.cpp b/doc/src/snippets/code/src_activeqt_container_qaxscript.cpp
new file mode 100644
index 0000000..ff911d1
--- /dev/null
+++ b/doc/src/snippets/code/src_activeqt_container_qaxscript.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+function setNumber(number)
+{
+ n = number;
+}
+//! [0]
+
+
+//! [1]
+QValueList args;
+args << 5;
+script->call("setNumber(const QVariant&)", args);
+//! [1]
+
+
+//! [2]
+script->call("setNumber(5)");
+//! [2]
diff --git a/doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp b/doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp
new file mode 100644
index 0000000..d3202ff
--- /dev/null
+++ b/doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+class MyActiveX : public QWidget, public QAxBindable
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+
+public:
+ MyActiveX(QWidget *parent = 0);
+ ...
+
+ int value() const;
+ void setValue(int);
+};
+//! [0]
+
+
+//! [1]
+void MyActiveQt::setText(const QString &text)
+{
+ if (!requestPropertyChange("text"))
+ return;
+
+ // update property
+
+ propertyChanged("text");
+}
+//! [1]
+
+
+//! [2]
+long AxImpl::queryInterface(const QUuid &iid, void **iface)
+{
+ *iface = 0;
+ if (iid == IID_ISomeCOMInterface)
+ *iface = (ISomeCOMInterface*)this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+}
+//! [2]
+
+
+//! [3]
+HRESULT AxImpl::QueryInterface(REFIID iid, void **iface)
+{
+ return controllingUnknown()->QueryInterface(iid, iface);
+}
+
+ulong AxImpl::AddRef()
+{
+ return controllingUnknown()->AddRef();
+}
+
+ulong AxImpl::Release()
+{
+ return controllingUnknown()->Release();
+}
+//! [3]
diff --git a/doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp b/doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp
new file mode 100644
index 0000000..6747f87
--- /dev/null
+++ b/doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+QStringList ActiveQtFactory::featureList() const
+{
+ QStringList list;
+ list << "ActiveX1";
+ list << "ActiveX2";
+ return list;
+}
+
+QObject *ActiveQtFactory::createObject(const QString &key)
+{
+ if (key == "ActiveX1")
+ return new ActiveX1(parent);
+ if (key == "ActiveX2")
+ return new ActiveX2(parent);
+ return 0;
+}
+
+const QMetaObject *ActiveQtFactory::metaObject(const QString &key) const
+{
+ if (key == "ActiveX1")
+ return &ActiveX1::staticMetaObject;
+ if (key == "ActiveX2")
+ return &ActiveX2::staticMetaObject;
+}
+
+QUuid ActiveQtFactory::classID(const QString &key) const
+{
+ if (key == "ActiveX1")
+ return "{01234567-89AB-CDEF-0123-456789ABCDEF}";
+ ...
+ return QUuid();
+}
+
+QUuid ActiveQtFactory::interfaceID(const QString &key) const
+{
+ if (key == "ActiveX1")
+ return "{01234567-89AB-CDEF-0123-456789ABCDEF}";
+ ...
+ return QUuid();
+}
+
+QUuid ActiveQtFactory::eventsID(const QString &key) const
+{
+ if (key == "ActiveX1")
+ return "{01234567-89AB-CDEF-0123-456789ABCDEF}";
+ ...
+ return QUuid();
+}
+
+QAXFACTORY_EXPORT(
+ ActiveQtFactory, // factory class
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // type library ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}" // application ID
+)
+//! [0]
+
+
+//! [1]
+QAXFACTORY_BEGIN(
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // type library ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}" // application ID
+)
+ QAXCLASS(Class1)
+ QAXCLASS(Class2)
+QAXFACTORY_END()
+//! [1]
+
+
+//! [2]
+#include <qapplication.h>
+#include <qaxfactory.h>
+
+#include "theactivex.h"
+
+QAXFACTORY_DEFAULT(
+ TheActiveX, // widget class
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // class ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // interface ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // event interface ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // type library ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}" // application ID
+)
+//! [2]
+
+
+//! [3]
+settings->setValue("/CLSID/" + classID(key)
+ + "/Implemented Categories/"
+ + "/{00000000-0000-0000-000000000000}/.",
+ QString());
+//! [3]
+
+
+//! [4]
+settings->remove("/CLSID/" + classID(key)
+ + "/Implemented Categories"
+ + "/{00000000-0000-0000-000000000000}/.");
+//! [4]
+
+
+//! [5]
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ if (!QAxFactory::isServer()) {
+ // initialize for stand-alone execution
+ }
+ return app.exec();
+}
+//! [5]
+
+
+//! [6]
+if (QAxFactory::isServer()) {
+ QAxFactory::stopServer();
+ QAxFactory::startServer(QAxFactory::SingleInstance);
+}
+//! [6]
+
+
+//! [7]
+#include <qaxfactory.h>
+
+#include "theactivex.h"
+
+QAXFACTORY_DEFAULT(
+ TheActiveX, // widget class
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // class ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // interface ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // event interface ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // type library ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}" // application ID
+)
+//! [7]
+
+
+//! [8]
+QAXFACTORY_EXPORT(
+ MyFactory, // factory class
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // type library ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}" // application ID
+)
+//! [8]
+
+
+//! [9]
+QAXFACTORY_BEGIN(
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}", // type library ID
+ "{01234567-89AB-CDEF-0123-456789ABCDEF}" // application ID
+)
+ QAXCLASS(Class1)
+ QAXCLASS(Class2)
+QAXFACTORY_END()
+//! [9]
diff --git a/examples/activeqt/README b/examples/activeqt/README
new file mode 100644
index 0000000..24be2de
--- /dev/null
+++ b/examples/activeqt/README
@@ -0,0 +1,39 @@
+Qt is supplied with a number of example applications and demonstrations that
+have been written to provide developers with examples of the Qt API in use,
+highlight good programming practice, and showcase features found in each of
+Qt's core technologies.
+
+The example and demo launcher can be used to explore the different categories
+available. It provides an overview of each example, lets you view the
+documentation in Qt Assistant, and is able to launch examples and demos.
+
+Documentation for examples can be found in the Tutorial and Examples section
+of the Qt documentation.
+
+
+Finding the Qt Examples and Demos launcher
+==========================================
+
+On Windows:
+
+The launcher can be accessed via the Windows Start menu. Select the menu
+entry entitled "Qt Examples and Demos" entry in the submenu containing
+the Qt tools.
+
+On Mac OS X:
+
+For the binary distribution, the qtdemo executable is installed in the
+/Developer/Applications/Qt directory. For the source distribution, it is
+installed alongside the other Qt tools on the path specified when Qt is
+configured.
+
+On Unix/Linux:
+
+The qtdemo executable is installed alongside the other Qt tools on the path
+specified when Qt is configured.
+
+On all platforms:
+
+The source code for the launcher can be found in the demos/qtdemo directory
+in the Qt package. This example is built at the same time as the Qt libraries,
+tools, examples, and demonstrations.
diff --git a/examples/activeqt/activeqt.pro b/examples/activeqt/activeqt.pro
new file mode 100644
index 0000000..79d257a
--- /dev/null
+++ b/examples/activeqt/activeqt.pro
@@ -0,0 +1,20 @@
+TEMPLATE = subdirs
+SUBDIRS += comapp \
+ hierarchy \
+ menus \
+ multiple \
+ simple \
+ webbrowser \
+ wrapper
+
+contains(QT_CONFIG, opengl):SUBDIRS += opengl
+
+# For now only the contain examples with mingw, for the others you need
+# an IDL compiler
+win32-g++*|wince*:SUBDIRS = webbrowser
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS activeqt.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt
+INSTALLS += target sources
diff --git a/examples/activeqt/comapp/comapp.pro b/examples/activeqt/comapp/comapp.pro
new file mode 100644
index 0000000..84ce072
--- /dev/null
+++ b/examples/activeqt/comapp/comapp.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+CONFIG += qaxserver
+
+# Input
+SOURCES += main.cpp
+
+RC_FILE = comapp.rc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/comapp
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS comapp.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/comapp
+INSTALLS += target sources
diff --git a/examples/activeqt/comapp/comapp.rc b/examples/activeqt/comapp/comapp.rc
new file mode 100644
index 0000000..24e339a
--- /dev/null
+++ b/examples/activeqt/comapp/comapp.rc
@@ -0,0 +1 @@
+1 TYPELIB "comapp.rc"
diff --git a/examples/activeqt/comapp/main.cpp b/examples/activeqt/comapp/main.cpp
new file mode 100644
index 0000000..66af248
--- /dev/null
+++ b/examples/activeqt/comapp/main.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QAxFactory>
+#include <QTabWidget>
+#include <QTimer>
+
+class Application;
+class DocumentList;
+
+//! [0]
+class Document : public QObject
+{
+ Q_OBJECT
+
+ Q_CLASSINFO("ClassID", "{2b5775cd-72c2-43da-bc3b-b0e8d1e1c4f7}")
+ Q_CLASSINFO("InterfaceID", "{2ce1761e-07a3-415c-bd11-0eab2c7283de}")
+
+ Q_PROPERTY(Application *application READ application)
+ Q_PROPERTY(QString title READ title WRITE setTitle)
+
+public:
+ Document(DocumentList *list);
+ ~Document();
+
+ Application *application() const;
+
+ QString title() const;
+ void setTitle(const QString &title);
+
+private:
+ QWidget *page;
+};
+//! [0]
+
+//! [1]
+class DocumentList : public QObject
+{
+ Q_OBJECT
+
+ Q_CLASSINFO("ClassID", "{496b761d-924b-4554-a18a-8f3704d2a9a6}")
+ Q_CLASSINFO("InterfaceID", "{6c9e30e8-3ff6-4e6a-9edc-d219d074a148}")
+
+ Q_PROPERTY(Application* application READ application)
+ Q_PROPERTY(int count READ count)
+
+public:
+ DocumentList(Application *application);
+
+ int count() const;
+ Application *application() const;
+
+public slots:
+ Document *addDocument();
+ Document *item(int index) const;
+
+private:
+ QList<Document*> list;
+};
+//! [1]
+
+//! [2]
+class Application : public QObject
+{
+ Q_OBJECT
+
+ Q_CLASSINFO("ClassID", "{b50a71db-c4a7-4551-8d14-49983566afee}")
+ Q_CLASSINFO("InterfaceID", "{4a427759-16ef-4ed8-be79-59ffe5789042}")
+ Q_CLASSINFO("RegisterObject", "yes")
+
+ Q_PROPERTY(DocumentList* documents READ documents)
+ Q_PROPERTY(QString id READ id)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
+
+public:
+ Application(QObject *parent = 0);
+ DocumentList *documents() const;
+
+ QString id() const { return objectName(); }
+
+ void setVisible(bool on);
+ bool isVisible() const;
+
+ QTabWidget *window() const { return ui; }
+
+public slots:
+ void quit();
+
+private:
+ DocumentList *docs;
+
+ QTabWidget *ui;
+};
+//! [2]
+
+//! [3]
+Document::Document(DocumentList *list)
+: QObject(list)
+{
+ QTabWidget *tabs = list->application()->window();
+ page = new QWidget(tabs);
+ page->setWindowTitle("Unnamed");
+ tabs->addTab(page, page->windowTitle());
+
+ page->show();
+}
+
+Document::~Document()
+{
+ delete page;
+}
+
+Application *Document::application() const
+{
+ return qobject_cast<DocumentList*>(parent())->application();
+}
+
+QString Document::title() const
+{
+ return page->windowTitle();
+}
+
+void Document::setTitle(const QString &t)
+{
+ page->setWindowTitle(t);
+
+ QTabWidget *tabs = application()->window();
+ int index = tabs->indexOf(page);
+ tabs->setTabText(index, page->windowTitle());
+}
+
+//! [3] //! [4]
+DocumentList::DocumentList(Application *application)
+: QObject(application)
+{
+}
+
+Application *DocumentList::application() const
+{
+ return qobject_cast<Application*>(parent());
+}
+
+int DocumentList::count() const
+{
+ return list.count();
+}
+
+Document *DocumentList::item(int index) const
+{
+ if (index >= list.count())
+ return 0;
+
+ return list.at(index);
+}
+
+Document *DocumentList::addDocument()
+{
+ Document *document = new Document(this);
+ list.append(document);
+
+ return document;
+}
+
+
+//! [4] //! [5]
+Application::Application(QObject *parent)
+: QObject(parent), ui(0)
+{
+ ui = new QTabWidget;
+
+ setObjectName("From QAxFactory");
+ docs = new DocumentList(this);
+}
+
+DocumentList *Application::documents() const
+{
+ return docs;
+}
+
+void Application::setVisible(bool on)
+{
+ ui->setShown(on);
+}
+
+bool Application::isVisible() const
+{
+ return ui->isVisible();
+}
+
+void Application::quit()
+{
+ delete docs;
+ docs = 0;
+
+ delete ui;
+ ui = 0;
+ QTimer::singleShot(0, qApp, SLOT(quit()));
+}
+
+#include "main.moc"
+//! [5] //! [6]
+
+
+QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}")
+ QAXCLASS(Application)
+ QAXTYPE(Document)
+ QAXTYPE(DocumentList)
+QAXFACTORY_END()
+
+//! [6] //! [7]
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ app.setQuitOnLastWindowClosed(false);
+
+ // started by COM - don't do anything
+ if (QAxFactory::isServer())
+ return app.exec();
+
+ // started by user
+ Application appobject(0);
+ appobject.setObjectName("From Application");
+
+ QAxFactory::startServer();
+ QAxFactory::registerActiveObject(&appobject);
+
+ appobject.setVisible(true);
+
+ QObject::connect(qApp, SIGNAL(lastWindowClosed()), &appobject, SLOT(quit()));
+
+ return app.exec();
+}
+//! [7]
diff --git a/examples/activeqt/dotnet/walkthrough/Form1.cs b/examples/activeqt/dotnet/walkthrough/Form1.cs
new file mode 100644
index 0000000..9fb572a
--- /dev/null
+++ b/examples/activeqt/dotnet/walkthrough/Form1.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Data;
+
+namespace csharp
+{
+ /// <summary>
+ /// Summary description for Form1.
+ /// </summary>
+ public class Form1 : System.Windows.Forms.Form
+ {
+ private AxwrapperaxLib.AxQPushButton resetButton;
+ private AxmultipleaxLib.AxQAxWidget2 circleWidget;
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.Container components = null;
+
+ public Form1()
+ {
+ //
+ // Required for Windows Form Designer support
+ //
+ InitializeComponent();
+
+ //
+ // TODO: Add any constructor code after InitializeComponent call
+ //
+ }
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ protected override void Dispose( bool disposing )
+ {
+ if( disposing )
+ {
+ if (components != null)
+ {
+ components.Dispose();
+ }
+ }
+ base.Dispose( disposing );
+ }
+
+ #region Windows Form Designer generated code
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
+ this.resetButton = new AxwrapperaxLib.AxQPushButton();
+ this.circleWidget = new AxmultipleaxLib.AxQAxWidget2();
+ ((System.ComponentModel.ISupportInitialize)(this.resetButton)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.circleWidget)).BeginInit();
+ this.SuspendLayout();
+ //
+ // resetButton
+ //
+ this.resetButton.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right);
+ this.resetButton.Enabled = true;
+ this.resetButton.Location = new System.Drawing.Point(160, 296);
+ this.resetButton.Name = "resetButton";
+ this.resetButton.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("resetButton.OcxState")));
+ this.resetButton.Size = new System.Drawing.Size(168, 32);
+ this.resetButton.TabIndex = 1;
+ this.resetButton.clicked += new System.EventHandler(this.resetLineWidth);
+ //
+ // circleWidget
+ //
+ this.circleWidget.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right);
+ this.circleWidget.Enabled = true;
+ this.circleWidget.Location = new System.Drawing.Point(8, 8);
+ this.circleWidget.Name = "circleWidget";
+ this.circleWidget.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("circleWidget.OcxState")));
+ this.circleWidget.Size = new System.Drawing.Size(320, 264);
+ this.circleWidget.TabIndex = 2;
+ this.circleWidget.ClickEvent += new System.EventHandler(this.circleClicked);
+ //
+ // Form1
+ //
+ this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+ this.ClientSize = new System.Drawing.Size(336, 333);
+ this.Controls.AddRange(new System.Windows.Forms.Control[] {
+ this.circleWidget,
+ this.resetButton});
+ this.Name = "Form1";
+ this.Text = "Form1";
+ ((System.ComponentModel.ISupportInitialize)(this.resetButton)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.circleWidget)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+ #endregion
+
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ Application.Run(new Form1());
+ }
+
+//! [0]
+ private void circleClicked(object sender, System.EventArgs e)
+ {
+ this.circleWidget.lineWidth++;
+ }
+//! [0]
+
+//! [1]
+ private void resetLineWidth(object sender, System.EventArgs e)
+ {
+ this.circleWidget.lineWidth = 1;
+ this.resetButton.setFocus();
+ }
+//! [1]
+ }
+}
diff --git a/examples/activeqt/dotnet/walkthrough/Form1.resx b/examples/activeqt/dotnet/walkthrough/Form1.resx
new file mode 100644
index 0000000..6353f82
--- /dev/null
+++ b/examples/activeqt/dotnet/walkthrough/Form1.resx
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 1.3
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">1.3</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1">this is my long string</data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ [base64 mime encoded serialized .NET Framework object]
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ [base64 mime encoded string representing a byte array form of the .NET Framework object]
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>1.3</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="resetButton.OcxState" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFpTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0xLjAuMzMw
+ MC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACFT
+ eXN0ZW0uV2luZG93cy5Gb3Jtcy5BeEhvc3QrU3RhdGUBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAGwMA
+ AAIBAAAAAQAAAAAAAAAAAAAAAAYDAAAAAAAFAAAACGVuYWJsZWQAAAAAEgEAAAACeAAAAAAQAAAAAAAA
+ AAJ5AAAAABAAAAAAAAAABndpZHRoAAAAABAAAACoAAAAB2hlaWdodAAAAAAQAAAAGgAAAA1taW5pbXVt
+ V2lkdGgAAAAAEAAAAAAAAAAObWluaW11bUhlaWdodAAAAAAQAAAAAAAAAA1tYXhpbXVtV2lkdGgAAAAA
+ EAAAf/8AAAAObWF4aW11bUhlaWdodAAAAAAQAAB//wAAAA9iYWNrZ3JvdW5kTW9kZQAAAAAQAAAABAAA
+ ABdwYWxldHRlRm9yZWdyb3VuZENvbG9yAAAAAAr/AAAAAAAAF3BhbGV0dGVCYWNrZ3JvdW5kQ29sb3IA
+ AAAACv/U0MgAAAARYmFja2dyb3VuZE9yaWdpbgAAAAAQAAAAAAAAAAVmb250AAAAAAUAAAAYAE0AUwAg
+ AFMAaABlAGwAbAAgAEQAbABnAFP//wUBADIAAAAACGNhcHRpb24AAAAAA/////8AAAAJaWNvblRleHQA
+ AAAAA/////8AAAAObW91c2VUcmFja2luZwAAAAASAAAAAAxmb2N1c1BvbGljeQAAAAAQAAAAAQAAAA91
+ cGRhdGVzRW5hYmxlZAAAAAASAQAAAAptYXhpbWl6ZWQAAAAAEgAAAAALZnVsbFNjcmVlbgAAAAASAAAA
+ AAxhY2NlcHREcm9wcwAAAAASAAAAABNpbnB1dE1ldGhvZEVuYWJsZWQAAAAAEgAAAAAFdGV4dAAAAAAD
+ AAAADAAmAFIAZQBzAGUAdAAAAAt0b2dnbGVUeXBlAAAAABAAAAAAAAAABWRvd24AAAAAEgAAAAAMdG9n
+ Z2xlU3RhdGUAAAAAEAAAAAAAAAALYXV0b1Jlc2l6ZQAAAAASAAAAAAthdXRvUmVwZWF0AAAAABIAAAAA
+ EGV4Y2x1c2l2ZVRvZ2dsZQAAAAASAAAAAAxhdXRvRGVmYXVsdAAAAAASAQAAAAttZW51QnV0dG9uAAAA
+ ABIAAAAABWZsYXQAAAAAEgAL
+</value>
+ </data>
+ <data name="circleWidget.OcxState" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFpTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0xLjAuMzMw
+ MC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACFT
+ eXN0ZW0uV2luZG93cy5Gb3Jtcy5BeEhvc3QrU3RhdGUBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAALwAA
+ AAIBAAAAAQAAAAAAAAAAAAAAABoAAAAAAAAFAAAACmxpbmVXaWR0aAAAAAAQAAAAAAs=
+</value>
+ </data>
+ <data name="$this.Name">
+ <value>Form1</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/examples/activeqt/dotnet/walkthrough/Form1.vb b/examples/activeqt/dotnet/walkthrough/Form1.vb
new file mode 100644
index 0000000..f5f241b
--- /dev/null
+++ b/examples/activeqt/dotnet/walkthrough/Form1.vb
@@ -0,0 +1,88 @@
+Public Class Form1
+ Inherits System.Windows.Forms.Form
+
+#Region " Windows Form Designer generated code "
+
+ Public Sub New()
+ MyBase.New()
+
+ 'This call is required by the Windows Form Designer.
+ InitializeComponent()
+
+ 'Add any initialization after the InitializeComponent() call
+
+ End Sub
+
+ 'Form overrides dispose to clean up the component list.
+ Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
+ If disposing Then
+ If Not (components Is Nothing) Then
+ components.Dispose()
+ End If
+ End If
+ MyBase.Dispose(disposing)
+ End Sub
+
+ 'Required by the Windows Form Designer
+ Private components As System.ComponentModel.IContainer
+
+ 'NOTE: The following procedure is required by the Windows Form Designer
+ 'It can be modified using the Windows Form Designer.
+ 'Do not modify it using the code editor.
+ Friend WithEvents circleWidget As AxmultipleaxLib.AxQAxWidget2
+ Friend WithEvents resetButton As AxwrapperaxLib.AxQPushButton
+ <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
+ Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(Form1))
+ Me.circleWidget = New AxmultipleaxLib.AxQAxWidget2()
+ Me.resetButton = New AxwrapperaxLib.AxQPushButton()
+ CType(Me.circleWidget, System.ComponentModel.ISupportInitialize).BeginInit()
+ CType(Me.resetButton, System.ComponentModel.ISupportInitialize).BeginInit()
+ Me.SuspendLayout()
+ '
+ 'circleWidget
+ '
+ Me.circleWidget.Anchor = (((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
+ Or System.Windows.Forms.AnchorStyles.Left) _
+ Or System.Windows.Forms.AnchorStyles.Right)
+ Me.circleWidget.Enabled = True
+ Me.circleWidget.Location = New System.Drawing.Point(8, 8)
+ Me.circleWidget.Name = "circleWidget"
+ Me.circleWidget.OcxState = CType(resources.GetObject("circleWidget.OcxState"), System.Windows.Forms.AxHost.State)
+ Me.circleWidget.Size = New System.Drawing.Size(280, 216)
+ Me.circleWidget.TabIndex = 0
+ '
+ 'resetButton
+ '
+ Me.resetButton.Anchor = (System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right)
+ ' VB is case insensitive, but our C++ controls are not.
+ ' Me.resetButton.enabled = True
+ Me.resetButton.Location = New System.Drawing.Point(184, 240)
+ Me.resetButton.Name = "resetButton"
+ Me.resetButton.OcxState = CType(resources.GetObject("resetButton.OcxState"), System.Windows.Forms.AxHost.State)
+ Me.resetButton.Size = New System.Drawing.Size(104, 24)
+ Me.resetButton.TabIndex = 1
+ '
+ 'Form1
+ '
+ Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
+ Me.ClientSize = New System.Drawing.Size(292, 273)
+ Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.resetButton, Me.circleWidget})
+ Me.Name = "Form1"
+ Me.Text = "Form1"
+ CType(Me.circleWidget, System.ComponentModel.ISupportInitialize).EndInit()
+ CType(Me.resetButton, System.ComponentModel.ISupportInitialize).EndInit()
+ Me.ResumeLayout(False)
+
+ End Sub
+
+#End Region
+
+ Private Sub circleWidget_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles circleWidget.ClickEvent
+ Me.circleWidget.lineWidth = Me.circleWidget.lineWidth + 1
+ End Sub
+
+ Private Sub resetButton_clicked(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles resetButton.clicked
+ Me.circleWidget.lineWidth = 1
+ Me.resetButton.setFocus()
+ End Sub
+End Class
diff --git a/examples/activeqt/dotnet/walkthrough/csharp.csproj b/examples/activeqt/dotnet/walkthrough/csharp.csproj
new file mode 100644
index 0000000..4c5502b
--- /dev/null
+++ b/examples/activeqt/dotnet/walkthrough/csharp.csproj
@@ -0,0 +1,143 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.0.9466"
+ SchemaVersion = "1.0"
+ ProjectGuid = "{F15600FD-7677-4C01-B98A-6776CE500617}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "csharp"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "WinExe"
+ RootNamespace = "csharp"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "true"
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
+ />
+ <Reference
+ Name = "System.Drawing"
+ AssemblyName = "System.Drawing"
+ HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
+ />
+ <Reference
+ Name = "System.Windows.Forms"
+ AssemblyName = "System.Windows.Forms"
+ HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
+ />
+ <Reference
+ Name = "stdole"
+ Guid = "{00020430-0000-0000-C000-000000000046}"
+ VersionMajor = "2"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "primary"
+ />
+ <Reference
+ Name = "wrapperaxLib"
+ Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "tlbimp"
+ />
+ <Reference
+ Name = "AxwrapperaxLib"
+ Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "aximp"
+ />
+ <Reference
+ Name = "multipleaxLib"
+ Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "tlbimp"
+ />
+ <Reference
+ Name = "AxmultipleaxLib"
+ Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "aximp"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "Form1.cs"
+ SubType = "Form"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Form1.resx"
+ DependentUpon = "Form1.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/examples/activeqt/dotnet/walkthrough/vb.vbproj b/examples/activeqt/dotnet/walkthrough/vb.vbproj
new file mode 100644
index 0000000..eb0a9d6
--- /dev/null
+++ b/examples/activeqt/dotnet/walkthrough/vb.vbproj
@@ -0,0 +1,147 @@
+<VisualStudioProject>
+ <VisualBasic
+ ProjectType = "Local"
+ ProductVersion = "7.0.9466"
+ SchemaVersion = "1.0"
+ ProjectGuid = "{BFF242A6-967C-4F73-BEBE-DED2D9C395C6}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "vb"
+ AssemblyOriginatorKeyFile = ""
+ AssemblyOriginatorKeyMode = "None"
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "WinExe"
+ OptionCompare = "Binary"
+ OptionExplicit = "On"
+ OptionStrict = "Off"
+ RootNamespace = "vb"
+ StartupObject = "vb.Form1"
+ >
+ <Config
+ Name = "Debug"
+ BaseAddress = "285212672"
+ ConfigurationOverrideFile = ""
+ DefineConstants = ""
+ DefineDebug = "true"
+ DefineTrace = "true"
+ DebugSymbols = "true"
+ IncrementalBuild = "true"
+ Optimize = "false"
+ OutputPath = "bin\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "1"
+ />
+ <Config
+ Name = "Release"
+ BaseAddress = "285212672"
+ ConfigurationOverrideFile = ""
+ DefineConstants = ""
+ DefineDebug = "false"
+ DefineTrace = "true"
+ DebugSymbols = "false"
+ IncrementalBuild = "false"
+ Optimize = "true"
+ OutputPath = "bin\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "1"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ />
+ <Reference
+ Name = "System.Drawing"
+ AssemblyName = "System.Drawing"
+ />
+ <Reference
+ Name = "System.Windows.Forms"
+ AssemblyName = "System.Windows.Forms"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ />
+ <Reference
+ Name = "stdole"
+ Guid = "{00020430-0000-0000-C000-000000000046}"
+ VersionMajor = "2"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "primary"
+ />
+ <Reference
+ Name = "wrapperaxLib"
+ Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "tlbimp"
+ />
+ <Reference
+ Name = "multipleaxLib"
+ Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "tlbimp"
+ />
+ <Reference
+ Name = "AxwrapperaxLib"
+ Guid = "{3B756301-0075-4E40-8BE8-5A81DE2426B7}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "aximp"
+ />
+ <Reference
+ Name = "AxmultipleaxLib"
+ Guid = "{05828915-AD1C-47AB-AB96-D6AD1E25F0E2}"
+ VersionMajor = "1"
+ VersionMinor = "0"
+ Lcid = "0"
+ WrapperTool = "aximp"
+ />
+ </References>
+ <Imports>
+ <Import Namespace = "Microsoft.VisualBasic" />
+ <Import Namespace = "System" />
+ <Import Namespace = "System.Collections" />
+ <Import Namespace = "System.Data" />
+ <Import Namespace = "System.Drawing" />
+ <Import Namespace = "System.Diagnostics" />
+ <Import Namespace = "System.Windows.Forms" />
+ </Imports>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "Form1.vb"
+ SubType = "Form"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Form1.resx"
+ DependentUpon = "Form1.vb"
+ BuildAction = "EmbeddedResource"
+ />
+ </Include>
+ </Files>
+ </VisualBasic>
+</VisualStudioProject>
+
diff --git a/examples/activeqt/dotnet/wrapper/app.csproj b/examples/activeqt/dotnet/wrapper/app.csproj
new file mode 100644
index 0000000..dce4bf0
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/app.csproj
@@ -0,0 +1,93 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.0.9466"
+ SchemaVersion = "1.0"
+ ProjectGuid = "{334C8F04-E034-4082-9380-43906DDE71AB}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "wrapper"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Exe"
+ RootNamespace = "wrapper"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "true"
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
+ />
+ <Reference
+ Name = "lib"
+ AssemblyName = "lib"
+ HintPath = "lib\lib.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "main.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/examples/activeqt/dotnet/wrapper/lib/lib.vcproj b/examples/activeqt/dotnet/wrapper/lib/lib.vcproj
new file mode 100644
index 0000000..f49c35d
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/lib/lib.vcproj
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.00"
+ Name="lib"
+ ProjectGUID="{2E94A303-45A2-47AC-B87A-7C3519E9D6D8}"
+ Keyword="ManagedCProj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="2"
+ CharacterSet="2"
+ ManagedExtensions="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtCore&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG"
+ IgnoreStandardIncludePath="FALSE"
+ MinimalRebuild="FALSE"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="QtCored4.lib"
+ OutputFile="lib.dll"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="$(QTDIR)/lib"
+ GenerateDebugInformation="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="2"
+ CharacterSet="2"
+ ManagedExtensions="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories="&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtCore&quot;"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG"
+ MinimalRebuild="FALSE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="QtCore4.lib"
+ OutputFile="$(OutDir)/lib.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="$(QTDIR)/lib"
+ GenerateDebugInformation="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ </Configuration>
+ </Configurations>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+ <File
+ RelativePath="networker.cpp">
+ </File>
+ <File
+ RelativePath="tools.cpp">
+ </File>
+ <File
+ RelativePath="worker.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc">
+ <File
+ RelativePath="networker.h">
+ </File>
+ <File
+ RelativePath="tools.h">
+ </File>
+ <File
+ RelativePath="worker.h">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="$(QTDIR)\bin\moc.exe $(InputName).h -o moc_$(InputName).cpp"
+ Outputs="moc_$(InputName).cpp"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="$(QTDIR)\bin\moc.exe $(InputName).h -o moc_$(InputName).cpp"
+ Outputs="moc_$(InputName).cpp"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Generated MOC"
+ Filter="">
+ <File
+ RelativePath="moc_worker.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/examples/activeqt/dotnet/wrapper/lib/networker.cpp b/examples/activeqt/dotnet/wrapper/lib/networker.cpp
new file mode 100644
index 0000000..a40297b
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/lib/networker.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+#include "networker.h"
+#include "worker.h"
+#include "tools.h"
+
+netWorker::netWorker()
+{
+ workerObject = new Worker();
+}
+//! [0] //! [1]
+
+netWorker::~netWorker()
+{
+ delete workerObject;
+}
+//! [1] //! [2]
+
+String *netWorker::get_StatusString()
+{
+ return QStringToString(workerObject->statusString());
+}
+//! [2] //! [3]
+
+void netWorker::set_StatusString(String *string)
+{
+ workerObject->setStatusString(StringToQString(string));
+ __raise statusStringChanged(string);
+}
+//! [3]
diff --git a/examples/activeqt/dotnet/wrapper/lib/networker.h b/examples/activeqt/dotnet/wrapper/lib/networker.h
new file mode 100644
index 0000000..ef61085
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/lib/networker.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+// lib.h
+
+#pragma once
+
+#using <mscorlib.dll>
+using namespace System;
+
+//! [0]
+class Worker;
+
+// .NET class
+public __gc class netWorker
+{
+public:
+ netWorker();
+ ~netWorker();
+
+ __property String *get_StatusString();
+ __property void set_StatusString(String *string);
+
+ __event void statusStringChanged(String *args);
+
+private:
+ Worker *workerObject;
+};
+//! [0]
diff --git a/examples/activeqt/dotnet/wrapper/lib/tools.cpp b/examples/activeqt/dotnet/wrapper/lib/tools.cpp
new file mode 100644
index 0000000..5a0fb20
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/lib/tools.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+#include <QString>
+
+#using <mscorlib.dll>
+#include <vcclr.h>
+
+using namespace System;
+
+String *QStringToString(const QString &qstring)
+{
+ return new String((const wchar_t *)qstring.utf16());
+}
+//! [0] //! [1]
+
+QString StringToQString(String *string)
+{
+ const wchar_t __pin *chars = PtrToStringChars(string);
+ return QString::fromWCharArray(chars);
+}
+//! [1]
diff --git a/examples/activeqt/dotnet/wrapper/lib/tools.h b/examples/activeqt/dotnet/wrapper/lib/tools.h
new file mode 100644
index 0000000..96b9230
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/lib/tools.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 TOOLS_H
+#define TOOLS_H
+
+#using <mscorlib.dll>
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+System::String *QStringToString(const QString &qstring);
+QString StringToQString(System::String *string);
+
+#endif // TOOLS_H
diff --git a/examples/activeqt/dotnet/wrapper/lib/worker.cpp b/examples/activeqt/dotnet/wrapper/lib/worker.cpp
new file mode 100644
index 0000000..c55e85f
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/lib/worker.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "worker.h"
+#include "tools.h"
+
+Worker::Worker()
+{
+ status = "Idle";
+}
+
+void Worker::setStatusString(const QString &string)
+{
+ status = string;
+ emit statusStringChanged(status);
+}
+
+QString Worker::statusString() const
+{
+ return status;
+}
diff --git a/examples/activeqt/dotnet/wrapper/lib/worker.h b/examples/activeqt/dotnet/wrapper/lib/worker.h
new file mode 100644
index 0000000..0b4b0e2
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/lib/worker.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 WORKER_H
+#define WORKER_H
+
+#include <QObject>
+
+// native Qt/C++ class
+//! [0]
+class Worker : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString statusString READ statusString WRITE setStatusString)
+public:
+ Worker();
+
+ QString statusString() const;
+
+public slots:
+ void setStatusString(const QString &string);
+
+signals:
+ void statusStringChanged(const QString &string);
+
+private:
+ QString status;
+};
+//! [0]
+
+#endif // WORKER_H
diff --git a/examples/activeqt/dotnet/wrapper/main.cs b/examples/activeqt/dotnet/wrapper/main.cs
new file mode 100644
index 0000000..1d43029
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/main.cs
@@ -0,0 +1,40 @@
+//! [0]
+using System;
+
+namespace WrapperApp
+{
+ class App
+ {
+ void Run()
+ {
+ netWorker worker = new netWorker();
+
+ worker.statusStringChanged += new netWorker.__Delegate_statusStringChanged(onStatusStringChanged);
+
+ System.Console.Out.WriteLine(worker.StatusString);
+
+ System.Console.Out.WriteLine("Working cycle begins...");
+ worker.StatusString = "Working";
+ worker.StatusString = "Lunch Break";
+ worker.StatusString = "Working";
+ worker.StatusString = "Idle";
+ System.Console.Out.WriteLine("Working cycle ends...");
+ }
+
+ private void onStatusStringChanged(string str)
+ {
+ System.Console.Out.WriteLine(str);
+ }
+
+ [STAThread]
+//! [0] //! [1]
+ static void Main(string[] args)
+ {
+ App app = new App();
+ app.Run();
+ }
+//! [1] //! [2]
+ }
+//! [2] //! [3]
+}
+//! [3]
diff --git a/examples/activeqt/dotnet/wrapper/wrapper.sln b/examples/activeqt/dotnet/wrapper/wrapper.sln
new file mode 100644
index 0000000..e25e6bd
--- /dev/null
+++ b/examples/activeqt/dotnet/wrapper/wrapper.sln
@@ -0,0 +1,28 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "app", "app.csproj", "{334C8F04-E034-4082-9380-43906DDE71AB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib", "lib\lib.vcproj", "{2E94A303-45A2-47AC-B87A-7C3519E9D6D8}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ {334C8F04-E034-4082-9380-43906DDE71AB}.0 = {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {334C8F04-E034-4082-9380-43906DDE71AB}.Debug.ActiveCfg = Debug|.NET
+ {334C8F04-E034-4082-9380-43906DDE71AB}.Debug.Build.0 = Debug|.NET
+ {334C8F04-E034-4082-9380-43906DDE71AB}.Release.ActiveCfg = Release|.NET
+ {334C8F04-E034-4082-9380-43906DDE71AB}.Release.Build.0 = Release|.NET
+ {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Debug.ActiveCfg = Debug|Win32
+ {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Debug.Build.0 = Debug|Win32
+ {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Release.ActiveCfg = Release|Win32
+ {2E94A303-45A2-47AC-B87A-7C3519E9D6D8}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/examples/activeqt/hierarchy/hierarchy.inf b/examples/activeqt/hierarchy/hierarchy.inf
new file mode 100644
index 0000000..cb7e90f
--- /dev/null
+++ b/examples/activeqt/hierarchy/hierarchy.inf
@@ -0,0 +1,9 @@
+[version]
+ signature="$CHICAGO$"
+ AdvancedINF=2.0
+ [Add.Code]
+ hierarchyax.dll=hierarchyax.dll
+ [hierarchyax.dll]
+ file-win32-x86=thiscab
+ clsid={d574a747-8016-46db-a07c-b2b4854ee75c}
+ RegisterServer=yes
diff --git a/examples/activeqt/hierarchy/hierarchy.pro b/examples/activeqt/hierarchy/hierarchy.pro
new file mode 100644
index 0000000..abe5f1b
--- /dev/null
+++ b/examples/activeqt/hierarchy/hierarchy.pro
@@ -0,0 +1,16 @@
+TEMPLATE = lib
+TARGET = hierarchyax
+
+CONFIG += qt warn_off qaxserver dll
+contains(CONFIG, static):DEFINES += QT_NODLL
+
+SOURCES = objects.cpp main.cpp
+HEADERS = objects.h
+RC_FILE = $$QT_SOURCE_TREE/src/activeqt/control/qaxserver.rc
+DEF_FILE = $$QT_SOURCE_TREE/src/activeqt/control/qaxserver.def
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/hierarchy
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS hierarchy.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/hierarchy
+INSTALLS += target sources
diff --git a/examples/activeqt/hierarchy/main.cpp b/examples/activeqt/hierarchy/main.cpp
new file mode 100644
index 0000000..0f23b71
--- /dev/null
+++ b/examples/activeqt/hierarchy/main.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+#include "objects.h"
+#include <QAxFactory>
+
+QAXFACTORY_BEGIN("{9e626211-be62-4d18-9483-9419358fbb03}", "{75c276de-1df5-451f-a004-e4fa1a587df1}")
+ QAXCLASS(QParentWidget)
+ QAXTYPE(QSubWidget)
+QAXFACTORY_END()
+//! [0]
diff --git a/examples/activeqt/hierarchy/objects.cpp b/examples/activeqt/hierarchy/objects.cpp
new file mode 100644
index 0000000..ab2cd61
--- /dev/null
+++ b/examples/activeqt/hierarchy/objects.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "objects.h"
+#include <QLayout>
+#include <QPainter>
+
+/* Implementation of QParentWidget */
+//! [0]
+QParentWidget::QParentWidget(QWidget *parent)
+: QWidget(parent)
+{
+ vbox = new QVBoxLayout(this);
+}
+
+//! [0] //! [1]
+void QParentWidget::createSubWidget(const QString &name)
+{
+ QSubWidget *sw = new QSubWidget(this, name);
+ vbox->addWidget(sw);
+ sw->setLabel(name);
+ sw->show();
+}
+
+//! [1] //! [2]
+QSubWidget *QParentWidget::subWidget(const QString &name)
+{
+ return findChild<QSubWidget*>(name);
+}
+
+//! [2]
+QSize QParentWidget::sizeHint() const
+{
+ return QWidget::sizeHint().expandedTo(QSize(100, 100));
+}
+
+/* Implementation of QSubWidget */
+//! [3]
+QSubWidget::QSubWidget(QWidget *parent, const QString &name)
+: QWidget(parent)
+{
+ setObjectName(name);
+}
+
+void QSubWidget::setLabel(const QString &text)
+{
+ lbl = text;
+ setObjectName(text);
+ update();
+}
+
+QString QSubWidget::label() const
+{
+ return lbl;
+}
+
+QSize QSubWidget::sizeHint() const
+{
+ QFontMetrics fm(font());
+ return QSize(fm.width(lbl), fm.height());
+}
+
+void QSubWidget::paintEvent(QPaintEvent *)
+{
+ QPainter painter(this);
+ painter.setPen(palette().text().color());
+ painter.drawText(rect(), Qt::AlignCenter, lbl);
+//! [3] //! [4]
+}
+//! [4]
diff --git a/examples/activeqt/hierarchy/objects.h b/examples/activeqt/hierarchy/objects.h
new file mode 100644
index 0000000..f840a17
--- /dev/null
+++ b/examples/activeqt/hierarchy/objects.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 OBJECTS_H
+#define OBJECTS_H
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QVBoxLayout;
+QT_END_NAMESPACE
+class QSubWidget;
+
+//! [0]
+class QParentWidget : public QWidget
+{
+ Q_OBJECT
+ Q_CLASSINFO("ClassID", "{d574a747-8016-46db-a07c-b2b4854ee75c}");
+ Q_CLASSINFO("InterfaceID", "{4a30719d-d9c2-4659-9d16-67378209f822}");
+ Q_CLASSINFO("EventsID", "{4a30719d-d9c2-4659-9d16-67378209f823}");
+public:
+ QParentWidget(QWidget *parent = 0);
+
+ QSize sizeHint() const;
+
+public slots:
+ void createSubWidget( const QString &name );
+
+ QSubWidget *subWidget( const QString &name );
+
+private:
+ QVBoxLayout *vbox;
+};
+//! [0]
+
+//! [1]
+class QSubWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( QString label READ label WRITE setLabel )
+
+ Q_CLASSINFO("ClassID", "{850652f4-8f71-4f69-b745-bce241ccdc30}");
+ Q_CLASSINFO("InterfaceID", "{2d76cc2f-3488-417a-83d6-debff88b3c3f}");
+ Q_CLASSINFO("ToSuperClass", "QSubWidget");
+
+public:
+ QSubWidget(QWidget *parent = 0, const QString &name = QString());
+
+ void setLabel( const QString &text );
+ QString label() const;
+
+ QSize sizeHint() const;
+
+protected:
+ void paintEvent( QPaintEvent *e );
+
+private:
+ QString lbl;
+};
+//! [1]
+
+#endif // OBJECTS_H
diff --git a/examples/activeqt/menus/fileopen.xpm b/examples/activeqt/menus/fileopen.xpm
new file mode 100644
index 0000000..880417e
--- /dev/null
+++ b/examples/activeqt/menus/fileopen.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char *fileopen[] = {
+" 16 13 5 1",
+". c #040404",
+"# c #808304",
+"a c None",
+"b c #f3f704",
+"c c #f3f7f3",
+"aaaaaaaaa...aaaa",
+"aaaaaaaa.aaa.a.a",
+"aaaaaaaaaaaaa..a",
+"a...aaaaaaaa...a",
+".bcb.......aaaaa",
+".cbcbcbcbc.aaaaa",
+".bcbcbcbcb.aaaaa",
+".cbcb...........",
+".bcb.#########.a",
+".cb.#########.aa",
+".b.#########.aaa",
+"..#########.aaaa",
+"...........aaaaa"
+};
diff --git a/examples/activeqt/menus/filesave.xpm b/examples/activeqt/menus/filesave.xpm
new file mode 100644
index 0000000..bd6870f
--- /dev/null
+++ b/examples/activeqt/menus/filesave.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char *filesave[] = {
+" 14 14 4 1",
+". c #040404",
+"# c #808304",
+"a c #bfc2bf",
+"b c None",
+"..............",
+".#.aaaaaaaa.a.",
+".#.aaaaaaaa...",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".##........##.",
+".############.",
+".##.........#.",
+".##......aa.#.",
+".##......aa.#.",
+".##......aa.#.",
+"b............."
+};
diff --git a/examples/activeqt/menus/main.cpp b/examples/activeqt/menus/main.cpp
new file mode 100644
index 0000000..7d19e1f
--- /dev/null
+++ b/examples/activeqt/menus/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "menus.h"
+#include <QApplication>
+#include <QAxFactory>
+
+QAXFACTORY_DEFAULT(QMenus,
+ "{4dc3f340-a6f7-44e4-a79b-3e9217695fbd}",
+ "{9ee49617-7d5c-441a-b833-4b068d40d751}",
+ "{13eca64b-ee2a-4f3c-aa04-5d9d975979a7}",
+ "{ce947ee3-0403-4fdc-895a-4fe779394b46}",
+ "{8de435ce-8d2a-46ac-b3b3-cb800d0847c7}");
+
+int main( int argc, char **argv )
+{
+ QApplication a( argc, argv );
+
+ QWidget *window = 0;
+ if ( !QAxFactory::isServer() ) {
+ window = new QMenus();
+ window->show();
+ }
+
+ return a.exec();
+}
diff --git a/examples/activeqt/menus/menus.cpp b/examples/activeqt/menus/menus.cpp
new file mode 100644
index 0000000..f1e8718
--- /dev/null
+++ b/examples/activeqt/menus/menus.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "menus.h"
+#include <QAction>
+#include <QAxFactory>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QTextEdit>
+#include <QPixmap>
+
+#include "fileopen.xpm"
+#include "filesave.xpm"
+
+QMenus::QMenus(QWidget *parent)
+ : QMainWindow(parent, 0) // QMainWindow's default flag is WType_TopLevel
+{
+ QAction *action;
+
+ QMenu *file = new QMenu(this);
+
+ action = new QAction(QPixmap((const char**)fileopen), "&Open", this);
+ action->setShortcut(tr("CTRL+O"));
+ connect(action, SIGNAL(triggered()), this, SLOT(fileOpen()));
+ file->addAction(action);
+
+ action = new QAction(QPixmap((const char**)filesave),"&Save", this);
+ action->setShortcut(tr("CTRL+S"));
+ connect(action, SIGNAL(triggered()), this, SLOT(fileSave()));
+ file->addAction(action);
+
+ QMenu *edit = new QMenu(this);
+
+ action = new QAction("&Normal", this);
+ action->setShortcut(tr("CTRL+N"));
+ action->setToolTip("Normal");
+ action->setStatusTip("Toggles Normal");
+ action->setCheckable(true);
+ connect(action, SIGNAL(triggered()), this, SLOT(editNormal()));
+ edit->addAction(action);
+
+ action = new QAction("&Bold", this);
+ action->setShortcut(tr("CTRL+B"));
+ action->setCheckable(true);
+ connect(action, SIGNAL(triggered()), this, SLOT(editBold()));
+ edit->addAction(action);
+
+ action = new QAction("&Underline", this);
+ action->setShortcut(tr("CTRL+U"));
+ action->setCheckable(true);
+ connect(action, SIGNAL(triggered()), this, SLOT(editUnderline()));
+ edit->addAction(action);
+
+ QMenu *advanced = new QMenu(this);
+ action = new QAction("&Font...", this);
+ connect(action, SIGNAL(triggered()), this, SLOT(editAdvancedFont()));
+ advanced->addAction(action);
+
+ action = new QAction("&Style...", this);
+ connect(action, SIGNAL(triggered()), this, SLOT(editAdvancedStyle()));
+ advanced->addAction(action);
+
+ edit->addMenu(advanced)->setText("&Advanced");
+
+ edit->addSeparator();
+
+ action = new QAction("Una&vailable", this);
+ action->setShortcut(tr("CTRL+V"));
+ action->setCheckable(true);
+ action->setEnabled(false);
+ connect(action, SIGNAL(triggered()), this, SLOT(editUnderline()));
+ edit->addAction(action);
+
+ QMenu *help = new QMenu(this);
+
+ action = new QAction("&About...", this);
+ action->setShortcut(tr("F1"));
+ connect(action, SIGNAL(triggered()), this, SLOT(helpAbout()));
+ help->addAction(action);
+
+ action = new QAction("&About Qt...", this);
+ connect(action, SIGNAL(triggered()), this, SLOT(helpAboutQt()));
+ help->addAction(action);
+
+ if (!QAxFactory::isServer())
+ menuBar()->addMenu(file)->setText("&File");
+ menuBar()->addMenu(edit)->setText("&Edit");
+ menuBar()->addMenu(help)->setText("&Help");
+
+ editor = new QTextEdit(this);
+ setCentralWidget(editor);
+
+ statusBar();
+}
+
+void QMenus::fileOpen()
+{
+ editor->append("File Open selected.");
+}
+
+void QMenus::fileSave()
+{
+ editor->append("File Save selected.");
+}
+
+void QMenus::editNormal()
+{
+ editor->append("Edit Normal selected.");
+}
+
+void QMenus::editBold()
+{
+ editor->append("Edit Bold selected.");
+}
+
+void QMenus::editUnderline()
+{
+ editor->append("Edit Underline selected.");
+}
+
+void QMenus::editAdvancedFont()
+{
+ editor->append("Edit Advanced Font selected.");
+}
+
+void QMenus::editAdvancedStyle()
+{
+ editor->append("Edit Advanced Style selected.");
+}
+
+void QMenus::helpAbout()
+{
+ QMessageBox::about(this, "About QMenus",
+ "This example implements an in-place ActiveX control with menus and status messages.");
+}
+
+void QMenus::helpAboutQt()
+{
+ QMessageBox::aboutQt(this);
+}
diff --git a/examples/activeqt/menus/menus.h b/examples/activeqt/menus/menus.h
new file mode 100644
index 0000000..55aa995
--- /dev/null
+++ b/examples/activeqt/menus/menus.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 MENUS_H
+#define MENUS_H
+
+#include <QMainWindow>
+
+QT_BEGIN_NAMESPACE
+class QTextEdit;
+QT_END_NAMESPACE
+
+class QMenus : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ QMenus(QWidget *parent = 0);
+
+public slots:
+ void fileOpen();
+ void fileSave();
+
+ void editNormal();
+ void editBold();
+ void editUnderline();
+
+ void editAdvancedFont();
+ void editAdvancedStyle();
+
+ void helpAbout();
+ void helpAboutQt();
+
+private:
+ QTextEdit *editor;
+};
+
+#endif // MENUS_H
diff --git a/examples/activeqt/menus/menus.inf b/examples/activeqt/menus/menus.inf
new file mode 100644
index 0000000..f97efe8
--- /dev/null
+++ b/examples/activeqt/menus/menus.inf
@@ -0,0 +1,9 @@
+[version]
+ signature="$CHICAGO$"
+ AdvancedINF=2.0
+ [Add.Code]
+ menusax.exe=menusax.exe
+ [menusax.exe]
+ file-win32-x86=thiscab
+ clsid={4dc3f340-a6f7-44e4-a79b-3e9217695fbd}
+ RegisterServer=yes
diff --git a/examples/activeqt/menus/menus.pro b/examples/activeqt/menus/menus.pro
new file mode 100644
index 0000000..c962b6b
--- /dev/null
+++ b/examples/activeqt/menus/menus.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+TARGET = menusax
+
+CONFIG += qt warn_off qaxserver
+
+SOURCES = main.cpp menus.cpp
+HEADERS = menus.h
+RC_FILE = $$QT_SOURCE_TREE/src/activeqt/control/qaxserver.rc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/menus
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS menus.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/menus
+INSTALLS += target sources
diff --git a/examples/activeqt/multiple/ax1.h b/examples/activeqt/multiple/ax1.h
new file mode 100644
index 0000000..79c5109
--- /dev/null
+++ b/examples/activeqt/multiple/ax1.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 AX1_H
+#define AX1_H
+
+#include <QWidget>
+#include <QPainter>
+
+//! [0]
+class QAxWidget1 : public QWidget
+{
+ Q_OBJECT
+ Q_CLASSINFO("ClassID", "{1D9928BD-4453-4bdd-903D-E525ED17FDE5}")
+ Q_CLASSINFO("InterfaceID", "{99F6860E-2C5A-42ec-87F2-43396F4BE389}")
+ Q_CLASSINFO("EventsID", "{0A3E9F27-E4F1-45bb-9E47-63099BCCD0E3}")
+
+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor)
+public:
+ QAxWidget1(QWidget *parent = 0)
+ : QWidget(parent), fill_color(Qt::red)
+ {
+ }
+
+ QColor fillColor() const
+ {
+ return fill_color;
+ }
+ void setFillColor(const QColor &fc)
+ {
+ fill_color = fc;
+ repaint();
+ }
+
+protected:
+ void paintEvent(QPaintEvent *e)
+ {
+ QPainter paint(this);
+ QRect r = rect();
+ r.adjust(10, 10, -10, -10);
+ paint.fillRect(r, fill_color);
+ }
+
+private:
+ QColor fill_color;
+};
+//! [0]
+
+#endif // AX1_H
diff --git a/examples/activeqt/multiple/ax2.h b/examples/activeqt/multiple/ax2.h
new file mode 100644
index 0000000..3069bcf
--- /dev/null
+++ b/examples/activeqt/multiple/ax2.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 AX2_H
+#define AX2_H
+
+#include <QWidget>
+#include <QPainter>
+
+//! [0]
+class QAxWidget2 : public QWidget
+{
+ Q_OBJECT
+ Q_CLASSINFO("ClassID", "{58139D56-6BE9-4b17-937D-1B1EDEDD5B71}")
+ Q_CLASSINFO("InterfaceID", "{B66280AB-08CC-4dcc-924F-58E6D7975B7D}")
+ Q_CLASSINFO("EventsID", "{D72BACBA-03C4-4480-B4BB-DE4FE3AA14A0}")
+ Q_CLASSINFO("ToSuperClass", "QAxWidget2")
+ Q_CLASSINFO("StockEvents", "yes")
+ Q_CLASSINFO("Insertable", "yes")
+
+ Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth )
+public:
+ QAxWidget2(QWidget *parent = 0)
+ : QWidget(parent), line_width( 1 )
+ {
+ }
+
+ int lineWidth() const
+ {
+ return line_width;
+ }
+ void setLineWidth( int lw )
+ {
+ line_width = lw;
+ repaint();
+ }
+
+protected:
+ void paintEvent( QPaintEvent *e )
+ {
+ QPainter paint( this );
+ QPen pen = paint.pen();
+ pen.setWidth( line_width );
+ paint.setPen( pen );
+
+ QRect r = rect();
+ r.adjust( 10, 10, -10, -10 );
+ paint.drawEllipse( r );
+ }
+
+private:
+ int line_width;
+};
+//! [0]
+
+#endif // AX2_H
diff --git a/examples/activeqt/multiple/main.cpp b/examples/activeqt/multiple/main.cpp
new file mode 100644
index 0000000..d7ecdc6
--- /dev/null
+++ b/examples/activeqt/multiple/main.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+#include "ax1.h"
+#include "ax2.h"
+#include <QAxFactory>
+
+QT_USE_NAMESPACE
+
+QAXFACTORY_BEGIN("{98DE28B6-6CD3-4e08-B9FA-3D1DB43F1D2F}", "{05828915-AD1C-47ab-AB96-D6AD1E25F0E2}")
+ QAXCLASS(QAxWidget1)
+ QAXCLASS(QAxWidget2)
+QAXFACTORY_END()
+//! [0]
diff --git a/examples/activeqt/multiple/multiple.inf b/examples/activeqt/multiple/multiple.inf
new file mode 100644
index 0000000..7f6be76
--- /dev/null
+++ b/examples/activeqt/multiple/multiple.inf
@@ -0,0 +1,9 @@
+[version]
+ signature="$CHICAGO$"
+ AdvancedINF=2.0
+ [Add.Code]
+ multipleax.dll=multipleax.dll
+ [multipleax.dll]
+ file-win32-x86=thiscab
+ clsid={1D9928BD-4453-4bdd-903D-E525ED17FDE5}
+ RegisterServer=yes
diff --git a/examples/activeqt/multiple/multiple.pro b/examples/activeqt/multiple/multiple.pro
new file mode 100644
index 0000000..7b86950
--- /dev/null
+++ b/examples/activeqt/multiple/multiple.pro
@@ -0,0 +1,16 @@
+TEMPLATE = lib
+TARGET = multipleax
+
+CONFIG += qt warn_off qaxserver dll
+contains(CONFIG, static):DEFINES += QT_NODLL
+
+SOURCES = main.cpp
+HEADERS = ax1.h ax2.h
+RC_FILE = multipleax.rc
+DEF_FILE = $$QT_SOURCE_TREE/src/activeqt/control/qaxserver.def
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/multiple
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS multiple.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/multiple
+INSTALLS += target sources
diff --git a/examples/activeqt/multiple/multipleax.rc b/examples/activeqt/multiple/multipleax.rc
new file mode 100644
index 0000000..b16b3a9
--- /dev/null
+++ b/examples/activeqt/multiple/multipleax.rc
@@ -0,0 +1,32 @@
+#include "winver.h"
+
+1 TYPELIB "multipleax.rc"
+1 ICON DISCARDABLE "..\\..\\..\\src\\activeqt\\control\\qaxserver.ico"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,0
+ PRODUCTVERSION 1,0,0,0
+ FILEFLAGSMASK 0x3fL
+ FILEOS 0x00040000L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)"
+ VALUE "FileDescription", "Multiple Example (ActiveQt)"
+ VALUE "FileVersion", "1.0.0.0"
+ VALUE "LegalCopyright", "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)."
+ VALUE "InternalName", "multipleax.dll"
+ VALUE "OriginalFilename", "multipleax.dll"
+ VALUE "ProductName", "Multiple Example (ActiveQt)"
+ VALUE "ProductVersion", "1.0.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/examples/activeqt/opengl/glbox.cpp b/examples/activeqt/opengl/glbox.cpp
new file mode 100644
index 0000000..bf16232
--- /dev/null
+++ b/examples/activeqt/opengl/glbox.cpp
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** This is a simple QGLWidget displaying an openGL wireframe box
+**
+** The OpenGL code is mostly borrowed from Brian Pauls "spin" example
+** in the Mesa distribution
+**
+****************************************************************************/
+
+#include "glbox.h"
+#include <QAxAggregated>
+#include <QUuid>
+//! [0]
+#include <objsafe.h>
+//! [0]
+
+#if defined(Q_CC_MSVC)
+#pragma warning(disable:4305) // init: truncation from const double to float
+#endif
+
+/*!
+ Create a GLBox widget
+*/
+
+GLBox::GLBox( QWidget* parent, const char* name )
+ : QGLWidget( parent )
+{
+ xRot = yRot = zRot = 0.0; // default object rotation
+ scale = 1.25; // default object scale
+ object = 0;
+}
+
+
+/*!
+ Release allocated resources
+*/
+
+GLBox::~GLBox()
+{
+ makeCurrent();
+ glDeleteLists( object, 1 );
+}
+
+
+/*!
+ Paint the box. The actual openGL commands for drawing the box are
+ performed here.
+*/
+
+void GLBox::paintGL()
+{
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, -10.0 );
+ glScalef( scale, scale, scale );
+
+ glRotatef( xRot, 1.0, 0.0, 0.0 );
+ glRotatef( yRot, 0.0, 1.0, 0.0 );
+ glRotatef( zRot, 0.0, 0.0, 1.0 );
+
+ glCallList( object );
+}
+
+
+/*!
+ Set up the OpenGL rendering state, and define display list
+*/
+
+void GLBox::initializeGL()
+{
+ qglClearColor(Qt::black); // Let OpenGL clear to black
+ object = makeObject(); // Generate an OpenGL display list
+ glShadeModel( GL_FLAT );
+}
+
+
+
+/*!
+ Set up the OpenGL view port, matrix mode, etc.
+*/
+
+void GLBox::resizeGL( int w, int h )
+{
+ glViewport( 0, 0, (GLint)w, (GLint)h );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
+ glMatrixMode( GL_MODELVIEW );
+}
+
+
+/*!
+ Generate an OpenGL display list for the object to be shown, i.e. the box
+*/
+
+GLuint GLBox::makeObject()
+{
+ GLuint list;
+
+ list = glGenLists( 1 );
+
+ glNewList( list, GL_COMPILE );
+
+ qglColor(Qt::white); // Shorthand for glColor3f or glIndex
+
+ glLineWidth( 2.0 );
+
+ glBegin( GL_LINE_LOOP );
+ glVertex3f( 1.0, 0.5, -0.4 );
+ glVertex3f( 1.0, -0.5, -0.4 );
+ glVertex3f( -1.0, -0.5, -0.4 );
+ glVertex3f( -1.0, 0.5, -0.4 );
+ glEnd();
+
+ glBegin( GL_LINE_LOOP );
+ glVertex3f( 1.0, 0.5, 0.4 );
+ glVertex3f( 1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, 0.5, 0.4 );
+ glEnd();
+
+ glBegin( GL_LINES );
+ glVertex3f( 1.0, 0.5, -0.4 ); glVertex3f( 1.0, 0.5, 0.4 );
+ glVertex3f( 1.0, -0.5, -0.4 ); glVertex3f( 1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, -0.5, -0.4 ); glVertex3f( -1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, 0.5, -0.4 ); glVertex3f( -1.0, 0.5, 0.4 );
+ glEnd();
+
+ glEndList();
+
+ return list;
+}
+
+
+/*!
+ Set the rotation angle of the object to \e degrees around the X axis.
+*/
+
+void GLBox::setXRotation( int degrees )
+{
+ xRot = (GLfloat)(degrees % 360);
+ updateGL();
+}
+
+
+/*!
+ Set the rotation angle of the object to \e degrees around the Y axis.
+*/
+
+void GLBox::setYRotation( int degrees )
+{
+ yRot = (GLfloat)(degrees % 360);
+ updateGL();
+}
+
+
+/*!
+ Set the rotation angle of the object to \e degrees around the Z axis.
+*/
+
+void GLBox::setZRotation( int degrees )
+{
+ zRot = (GLfloat)(degrees % 360);
+ updateGL();
+}
+
+//! [1]
+class ObjectSafetyImpl : public QAxAggregated,
+ public IObjectSafety
+{
+public:
+//! [1] //! [2]
+ ObjectSafetyImpl() {}
+
+ long queryInterface( const QUuid &iid, void **iface )
+ {
+ *iface = 0;
+ if ( iid == IID_IObjectSafety )
+ *iface = (IObjectSafety*)this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+ }
+
+//! [2] //! [3]
+ QAXAGG_IUNKNOWN;
+
+//! [3] //! [4]
+ HRESULT WINAPI GetInterfaceSafetyOptions( REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions )
+ {
+ *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER;
+ *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER;
+ return S_OK;
+ }
+ HRESULT WINAPI SetInterfaceSafetyOptions( REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions )
+ {
+ return S_OK;
+ }
+};
+//! [4] //! [5]
+
+QAxAggregated *GLBox::createAggregate()
+{
+ return new ObjectSafetyImpl();
+}
+//! [5]
diff --git a/examples/activeqt/opengl/glbox.h b/examples/activeqt/opengl/glbox.h
new file mode 100644
index 0000000..e4740fc
--- /dev/null
+++ b/examples/activeqt/opengl/glbox.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** This is a simple QGLWidget displaying an openGL wireframe box
+**
+****************************************************************************/
+
+#ifndef GLBOX_H
+#define GLBOX_H
+
+#include <QtOpenGL>
+//! [0]
+#include <QAxBindable>
+
+class GLBox : public QGLWidget,
+ public QAxBindable
+{
+ Q_OBJECT
+//! [0] //! [1]
+
+public:
+
+ GLBox( QWidget* parent, const char* name = 0 );
+ ~GLBox();
+
+ QAxAggregated *createAggregate();
+
+public slots:
+
+ void setXRotation( int degrees );
+//! [1]
+ void setYRotation( int degrees );
+ void setZRotation( int degrees );
+
+protected:
+
+ void initializeGL();
+ void paintGL();
+ void resizeGL( int w, int h );
+
+ virtual GLuint makeObject();
+
+private:
+
+ GLuint object;
+ GLfloat xRot, yRot, zRot, scale;
+
+};
+
+#endif // GLBOX_H
diff --git a/examples/activeqt/opengl/globjwin.cpp b/examples/activeqt/opengl/globjwin.cpp
new file mode 100644
index 0000000..2626125
--- /dev/null
+++ b/examples/activeqt/opengl/globjwin.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "globjwin.h"
+#include "glbox.h"
+#include <QPushButton>
+#include <QSlider>
+#include <QLayout>
+#include <QFrame>
+#include <QMenuBar>
+#include <QMenu>
+#include <QApplication>
+
+
+GLObjectWindow::GLObjectWindow(QWidget* parent)
+ : QWidget(parent)
+{
+
+ // Create a menu
+ QMenu *file = new QMenu( this );
+ file->addAction( "Exit", qApp, SLOT(quit())/*, CTRL+Key_Q*/);
+
+ // Create a menu bar
+ QMenuBar *m = new QMenuBar( this );
+ m->addMenu(file)->setText("&File");
+
+ // Create a nice frame to put around the OpenGL widget
+ QFrame* f = new QFrame(this);
+ f->setFrameStyle( QFrame::Sunken | QFrame::Panel );
+ f->setLineWidth( 2 );
+
+ // Create our OpenGL widget
+ GLBox* c = new GLBox( f, "glbox");
+
+ // Create the three sliders; one for each rotation axis
+ QSlider* x = new QSlider(Qt::Vertical, this);
+ x->setMaximum(360);
+ x->setPageStep(60);
+ x->setTickPosition( QSlider::TicksLeft );
+ QObject::connect( x, SIGNAL(valueChanged(int)),c,SLOT(setXRotation(int)) );
+
+ QSlider* y = new QSlider(Qt::Vertical, this);
+ y->setMaximum(360);
+ y->setPageStep(60);
+ y->setTickPosition( QSlider::TicksLeft );
+ QObject::connect( y, SIGNAL(valueChanged(int)),c,SLOT(setYRotation(int)) );
+
+ QSlider* z = new QSlider(Qt::Vertical, this);
+ z->setMaximum(360);
+ z->setPageStep(60);
+ z->setTickPosition( QSlider::TicksLeft );
+ QObject::connect( z, SIGNAL(valueChanged(int)),c,SLOT(setZRotation(int)) );
+
+ // Now that we have all the widgets, put them into a nice layout
+
+ // Top level layout, puts the sliders to the left of the frame/GL widget
+ QHBoxLayout* hlayout = new QHBoxLayout(this);
+
+ // Put the sliders on top of each other
+ QVBoxLayout* vlayout = new QVBoxLayout();
+ vlayout->addWidget( x );
+ vlayout->addWidget( y );
+ vlayout->addWidget( z );
+
+ // Put the GL widget inside the frame
+ QHBoxLayout* flayout = new QHBoxLayout(f);
+ flayout->setMargin(0);
+ flayout->addWidget( c, 1 );
+
+ hlayout->setMenuBar( m );
+ hlayout->addLayout( vlayout );
+ hlayout->addWidget( f, 1 );
+}
diff --git a/examples/activeqt/opengl/globjwin.h b/examples/activeqt/opengl/globjwin.h
new file mode 100644
index 0000000..5f660af
--- /dev/null
+++ b/examples/activeqt/opengl/globjwin.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** The GLObjectWindow contains a GLBox and three sliders connected to
+** the GLBox's rotation slots.
+**
+****************************************************************************/
+
+#ifndef GLOBJWIN_H
+#define GLOBJWIN_H
+
+#include <qwidget.h>
+
+class GLObjectWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ GLObjectWindow(QWidget *parent = 0);
+};
+
+#endif
diff --git a/examples/activeqt/opengl/main.cpp b/examples/activeqt/opengl/main.cpp
new file mode 100644
index 0000000..4a16bac
--- /dev/null
+++ b/examples/activeqt/opengl/main.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+//
+// Qt OpenGL example: Box
+//
+// A small example showing how a GLWidget can be used just as any Qt widget
+//
+// File: main.cpp
+//
+// The main() function
+//
+
+#include "globjwin.h"
+#include "glbox.h"
+#include <QApplication>
+#include <QtOpenGL>
+//! [0]
+#include <QAxFactory>
+
+QAXFACTORY_DEFAULT( GLBox,
+ "{5fd9c22e-ed45-43fa-ba13-1530bb6b03e0}",
+ "{33b051af-bb25-47cf-a390-5cfd2987d26a}",
+ "{8c996c29-eafa-46ac-a6f9-901951e765b5}",
+ "{2c3c183a-eeda-41a4-896e-3d9c12c3577d}",
+ "{83e16271-6480-45d5-aaf1-3f40b7661ae4}"
+ )
+
+//! [0] //! [1]
+/*
+ The main program is here.
+*/
+
+int main( int argc, char **argv )
+{
+ QApplication::setColorSpec( QApplication::CustomColor );
+ QApplication a(argc,argv);
+
+ if ( !QGLFormat::hasOpenGL() ) {
+ qWarning( "This system has no OpenGL support. Exiting." );
+ return -1;
+ }
+
+ if ( !QAxFactory::isServer() ) {
+ GLObjectWindow w;
+ w.resize( 400, 350 );
+ w.show();
+ return a.exec();
+//! [1] //! [2]
+ }
+ return a.exec();
+//! [2] //! [3]
+}
+//! [3]
diff --git a/examples/activeqt/opengl/opengl.inf b/examples/activeqt/opengl/opengl.inf
new file mode 100644
index 0000000..4a79e67
--- /dev/null
+++ b/examples/activeqt/opengl/opengl.inf
@@ -0,0 +1,9 @@
+[version]
+ signature="$CHICAGO$"
+ AdvancedINF=2.0
+ [Add.Code]
+ openglax.exe=openglax.exe
+ [openglax.exe]
+ file-win32-x86=thiscab
+ clsid={5fd9c22e-ed45-43fa-ba13-1530bb6b03e0}
+ RegisterServer=yes
diff --git a/examples/activeqt/opengl/opengl.pro b/examples/activeqt/opengl/opengl.pro
new file mode 100644
index 0000000..8eb81be
--- /dev/null
+++ b/examples/activeqt/opengl/opengl.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+TARGET = openglax
+
+CONFIG += qt warn_off qaxserver
+
+QT += opengl
+
+HEADERS = glbox.h \
+ globjwin.h
+SOURCES = glbox.cpp \
+ globjwin.cpp \
+ main.cpp
+RC_FILE = $$QT_SOURCE_TREE/src/activeqt/control/qaxserver.rc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/opengl
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS opengl.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/opengl
+INSTALLS += target sources
diff --git a/examples/activeqt/qutlook/addressview.cpp b/examples/activeqt/qutlook/addressview.cpp
new file mode 100644
index 0000000..45ce662
--- /dev/null
+++ b/examples/activeqt/qutlook/addressview.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+#include "addressview.h"
+#include "msoutl.h"
+#include <QtGui>
+
+class AddressBookModel : public QAbstractListModel
+{
+public:
+ AddressBookModel(AddressView *parent);
+ ~AddressBookModel();
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+ void changeItem(const QModelIndex &index, const QString &firstName, const QString &lastName, const QString &address, const QString &email);
+ void addItem(const QString &firstName, const QString &lastName, const QString &address, const QString &email);
+ void update();
+
+private:
+ Outlook::Application outlook;
+ Outlook::Items * contactItems;
+
+ mutable QHash<QModelIndex, QStringList> cache;
+};
+//! [0] //! [1]
+
+AddressBookModel::AddressBookModel(AddressView *parent)
+: QAbstractListModel(parent)
+{
+ if (!outlook.isNull()) {
+ Outlook::NameSpace session(outlook.Session());
+ session.Logon();
+ Outlook::MAPIFolder *folder = session.GetDefaultFolder(Outlook::olFolderContacts);
+ contactItems = new Outlook::Items(folder->Items());
+ connect(contactItems, SIGNAL(ItemAdd(IDispatch*)), parent, SLOT(updateOutlook()));
+ connect(contactItems, SIGNAL(ItemChange(IDispatch*)), parent, SLOT(updateOutlook()));
+ connect(contactItems, SIGNAL(ItemRemove()), parent, SLOT(updateOutlook()));
+
+ delete folder;
+ }
+}
+
+//! [1] //! [2]
+AddressBookModel::~AddressBookModel()
+{
+ delete contactItems;
+
+ if (!outlook.isNull())
+ Outlook::NameSpace(outlook.Session()).Logoff();
+}
+
+//! [2] //! [3]
+int AddressBookModel::rowCount(const QModelIndex &) const
+{
+ return contactItems ? contactItems->Count() : 0;
+}
+
+int AddressBookModel::columnCount(const QModelIndex &parent) const
+{
+ return 4;
+}
+
+//! [3] //! [4]
+QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ switch (section) {
+ case 0:
+ return tr("First Name");
+ case 1:
+ return tr("Last Name");
+ case 2:
+ return tr("Address");
+ case 3:
+ return tr("Email");
+ default:
+ break;
+ }
+
+ return QVariant();
+}
+
+//! [4] //! [5]
+QVariant AddressBookModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+
+ QStringList data;
+ if (cache.contains(index)) {
+ data = cache.value(index);
+ } else {
+ Outlook::ContactItem contact(contactItems->Item(index.row() + 1));
+ data << contact.FirstName() << contact.LastName() << contact.HomeAddress() << contact.Email1Address();
+ cache.insert(index, data);
+ }
+
+ if (index.column() < data.count())
+ return data.at(index.column());
+
+ return QVariant();
+}
+
+//! [5] //! [6]
+void AddressBookModel::changeItem(const QModelIndex &index, const QString &firstName, const QString &lastName, const QString &address, const QString &email)
+{
+ Outlook::ContactItem item(contactItems->Item(index.row() + 1));
+
+ item.SetFirstName(firstName);
+ item.SetLastName(lastName);
+ item.SetHomeAddress(address);
+ item.SetEmail1Address(email);
+
+ item.Save();
+
+ cache.take(index);
+}
+
+//! [6] //! [7]
+void AddressBookModel::addItem(const QString &firstName, const QString &lastName, const QString &address, const QString &email)
+{
+ Outlook::ContactItem item(outlook.CreateItem(Outlook::olContactItem));
+ if (!item.isNull()) {
+ item.SetFirstName(firstName);
+ item.SetLastName(lastName);
+ item.SetHomeAddress(address);
+ item.SetEmail1Address(email);
+
+ item.Save();
+ }
+}
+
+//! [7] //! [8]
+void AddressBookModel::update()
+{
+ cache.clear();
+
+ emit reset();
+}
+
+
+//! [8] //! [9]
+AddressView::AddressView(QWidget *parent)
+: QWidget(parent)
+{
+ QGridLayout *mainGrid = new QGridLayout(this);
+
+ QLabel *liFirstName = new QLabel("First &Name", this);
+ liFirstName->resize(liFirstName->sizeHint());
+ mainGrid->addWidget(liFirstName, 0, 0);
+
+ QLabel *liLastName = new QLabel("&Last Name", this);
+ liLastName->resize(liLastName->sizeHint());
+ mainGrid->addWidget(liLastName, 0, 1);
+
+ QLabel *liAddress = new QLabel("Add&ress", this);
+ liAddress->resize(liAddress->sizeHint());
+ mainGrid->addWidget(liAddress, 0, 2);
+
+ QLabel *liEMail = new QLabel("&E-Mail", this);
+ liEMail->resize(liEMail->sizeHint());
+ mainGrid->addWidget(liEMail, 0, 3);
+
+ add = new QPushButton("A&dd", this);
+ add->resize(add->sizeHint());
+ mainGrid->addWidget(add, 0, 4);
+ connect(add, SIGNAL(clicked()), this, SLOT(addEntry()));
+
+ iFirstName = new QLineEdit(this);
+ iFirstName->resize(iFirstName->sizeHint());
+ mainGrid->addWidget(iFirstName, 1, 0);
+ liFirstName->setBuddy(iFirstName);
+
+ iLastName = new QLineEdit(this);
+ iLastName->resize(iLastName->sizeHint());
+ mainGrid->addWidget(iLastName, 1, 1);
+ liLastName->setBuddy(iLastName);
+
+ iAddress = new QLineEdit(this);
+ iAddress->resize(iAddress->sizeHint());
+ mainGrid->addWidget(iAddress, 1, 2);
+ liAddress->setBuddy(iAddress);
+
+ iEMail = new QLineEdit(this);
+ iEMail->resize(iEMail->sizeHint());
+ mainGrid->addWidget(iEMail, 1, 3);
+ liEMail->setBuddy(iEMail);
+
+ change = new QPushButton("&Change", this);
+ change->resize(change->sizeHint());
+ mainGrid->addWidget(change, 1, 4);
+ connect(change, SIGNAL(clicked()), this, SLOT(changeEntry()));
+
+ treeView = new QTreeView(this);
+ treeView->setSelectionMode(QTreeView::SingleSelection);
+ treeView->setRootIsDecorated(false);
+
+ model = new AddressBookModel(this);
+ treeView->setModel(model);
+
+ connect(treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(itemSelected(QModelIndex)));
+
+ mainGrid->addWidget(treeView, 2, 0, 1, 5);
+}
+
+void AddressView::updateOutlook()
+{
+ model->update();
+}
+
+void AddressView::addEntry()
+{
+ if (!iFirstName->text().isEmpty() || !iLastName->text().isEmpty() ||
+ !iAddress->text().isEmpty() || !iEMail->text().isEmpty()) {
+ model->addItem(iFirstName->text(), iFirstName->text(), iAddress->text(), iEMail->text());
+ }
+
+ iFirstName->setText("");
+ iLastName->setText("");
+ iAddress->setText("");
+ iEMail->setText("");
+}
+
+void AddressView::changeEntry()
+{
+ QModelIndex current = treeView->currentIndex();
+
+ if (current.isValid())
+ model->changeItem(current, iFirstName->text(), iLastName->text(), iAddress->text(), iEMail->text());
+}
+
+//! [9] //! [10]
+void AddressView::itemSelected(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return;
+
+ QAbstractItemModel *model = treeView->model();
+ iFirstName->setText(model->data(model->index(index.row(), 0)).toString());
+ iLastName->setText(model->data(model->index(index.row(), 1)).toString());
+ iAddress->setText(model->data(model->index(index.row(), 2)).toString());
+ iEMail->setText(model->data(model->index(index.row(), 3)).toString());
+}
+//! [10]
diff --git a/examples/activeqt/qutlook/addressview.h b/examples/activeqt/qutlook/addressview.h
new file mode 100644
index 0000000..e1a0b85
--- /dev/null
+++ b/examples/activeqt/qutlook/addressview.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 ADDRESSVIEW_H
+#define ADDRESSVIEW_H
+
+#include <QWidget>
+
+class AddressBookModel;
+QT_BEGIN_NAMESPACE
+class QLineEdit;
+class QModelIndex;
+class QPushButton;
+class QTreeView;
+QT_END_NAMESPACE
+
+//! [0]
+class AddressView : public QWidget
+{
+ Q_OBJECT
+
+public:
+ AddressView(QWidget *parent = 0);
+
+protected slots:
+ void addEntry();
+ void changeEntry();
+ void itemSelected(const QModelIndex &index);
+
+ void updateOutlook();
+
+protected:
+ AddressBookModel *model;
+
+ QTreeView *treeView;
+ QPushButton *add, *change;
+ QLineEdit *iFirstName, *iLastName, *iAddress, *iEMail;
+};
+//! [0]
+
+#endif // ADDRESSVIEW_H
diff --git a/examples/activeqt/qutlook/fileopen.xpm b/examples/activeqt/qutlook/fileopen.xpm
new file mode 100644
index 0000000..880417e
--- /dev/null
+++ b/examples/activeqt/qutlook/fileopen.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char *fileopen[] = {
+" 16 13 5 1",
+". c #040404",
+"# c #808304",
+"a c None",
+"b c #f3f704",
+"c c #f3f7f3",
+"aaaaaaaaa...aaaa",
+"aaaaaaaa.aaa.a.a",
+"aaaaaaaaaaaaa..a",
+"a...aaaaaaaa...a",
+".bcb.......aaaaa",
+".cbcbcbcbc.aaaaa",
+".bcbcbcbcb.aaaaa",
+".cbcb...........",
+".bcb.#########.a",
+".cb.#########.aa",
+".b.#########.aaa",
+"..#########.aaaa",
+"...........aaaaa"
+};
diff --git a/examples/activeqt/qutlook/fileprint.xpm b/examples/activeqt/qutlook/fileprint.xpm
new file mode 100644
index 0000000..6ada912
--- /dev/null
+++ b/examples/activeqt/qutlook/fileprint.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char *fileprint[] = {
+" 16 14 6 1",
+". c #000000",
+"# c #848284",
+"a c #c6c3c6",
+"b c #ffff00",
+"c c #ffffff",
+"d c None",
+"ddddd.........dd",
+"dddd.cccccccc.dd",
+"dddd.c.....c.ddd",
+"ddd.cccccccc.ddd",
+"ddd.c.....c....d",
+"dd.cccccccc.a.a.",
+"d..........a.a..",
+".aaaaaaaaaa.a.a.",
+".............aa.",
+".aaaaaa###aa.a.d",
+".aaaaaabbbaa...d",
+".............a.d",
+"d.aaaaaaaaa.a.dd",
+"dd...........ddd"
+};
diff --git a/examples/activeqt/qutlook/filesave.xpm b/examples/activeqt/qutlook/filesave.xpm
new file mode 100644
index 0000000..bd6870f
--- /dev/null
+++ b/examples/activeqt/qutlook/filesave.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char *filesave[] = {
+" 14 14 4 1",
+". c #040404",
+"# c #808304",
+"a c #bfc2bf",
+"b c None",
+"..............",
+".#.aaaaaaaa.a.",
+".#.aaaaaaaa...",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".##........##.",
+".############.",
+".##.........#.",
+".##......aa.#.",
+".##......aa.#.",
+".##......aa.#.",
+"b............."
+};
diff --git a/examples/activeqt/qutlook/main.cpp b/examples/activeqt/qutlook/main.cpp
new file mode 100644
index 0000000..da5b656
--- /dev/null
+++ b/examples/activeqt/qutlook/main.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//! [0]
+#include "addressview.h"
+#include <QApplication>
+
+int main(int argc, char ** argv)
+{
+ QApplication a(argc, argv);
+
+ AddressView view;
+ view.setWindowTitle("Qt Example - Looking at Outlook");
+ view.show();
+
+ return a.exec();
+}
+//! [0]
diff --git a/examples/activeqt/qutlook/qutlook.pro b/examples/activeqt/qutlook/qutlook.pro
new file mode 100644
index 0000000..c1154e0
--- /dev/null
+++ b/examples/activeqt/qutlook/qutlook.pro
@@ -0,0 +1,23 @@
+#! [0] #! [1]
+TEMPLATE = app
+TARGET = qutlook
+CONFIG += qaxcontainer
+
+TYPELIBS = $$system(dumpcpp -getfile {00062FFF-0000-0000-C000-000000000046})
+#! [0]
+
+isEmpty(TYPELIBS) {
+ message("Microsoft Outlook type library not found!")
+ REQUIRES += Outlook
+} else {
+#! [1] #! [2]
+ HEADERS = addressview.h
+ SOURCES = addressview.cpp main.cpp
+}
+#! [2]
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/qutlook
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS qutlook.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/qutlook
+INSTALLS += target sources
diff --git a/examples/activeqt/simple/main.cpp b/examples/activeqt/simple/main.cpp
new file mode 100644
index 0000000..7d6d340
--- /dev/null
+++ b/examples/activeqt/simple/main.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include <QAxBindable>
+#include <QAxFactory>
+#include <QApplication>
+#include <QLayout>
+#include <QSlider>
+#include <QLCDNumber>
+#include <QLineEdit>
+#include <QMessageBox>
+
+//! [0]
+class QSimpleAX : public QWidget, public QAxBindable
+{
+ Q_OBJECT
+ Q_PROPERTY( QString text READ text WRITE setText )
+ Q_PROPERTY( int value READ value WRITE setValue )
+public:
+ QSimpleAX(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ QVBoxLayout *vbox = new QVBoxLayout( this );
+
+ slider = new QSlider( Qt::Horizontal, this );
+ LCD = new QLCDNumber( 3, this );
+ edit = new QLineEdit( this );
+
+ connect( slider, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)) );
+ connect( edit, SIGNAL(textChanged(QString)), this, SLOT(setText(QString)) );
+
+ vbox->addWidget( slider );
+ vbox->addWidget( LCD );
+ vbox->addWidget( edit );
+ }
+
+ QString text() const
+ {
+ return edit->text();
+ }
+ int value() const
+ {
+ return slider->value();
+ }
+
+signals:
+ void someSignal();
+ void valueChanged(int);
+ void textChanged(const QString&);
+
+public slots:
+ void setText( const QString &string )
+ {
+ if ( !requestPropertyChange( "text" ) )
+ return;
+
+ edit->blockSignals( true );
+ edit->setText( string );
+ edit->blockSignals( false );
+ emit someSignal();
+ emit textChanged( string );
+
+ propertyChanged( "text" );
+ }
+ void about()
+ {
+ QMessageBox::information( this, "About QSimpleAX", "This is a Qt widget, and this slot has been\n"
+ "called through ActiveX/OLE automation!" );
+ }
+ void setValue( int i )
+ {
+ if ( !requestPropertyChange( "value" ) )
+ return;
+ slider->blockSignals( true );
+ slider->setValue( i );
+ slider->blockSignals( false );
+ LCD->display( i );
+ emit valueChanged( i );
+
+ propertyChanged( "value" );
+ }
+
+private:
+ QSlider *slider;
+ QLCDNumber *LCD;
+ QLineEdit *edit;
+};
+
+//! [0]
+#include "main.moc"
+
+//! [1]
+QAXFACTORY_DEFAULT(QSimpleAX,
+ "{DF16845C-92CD-4AAB-A982-EB9840E74669}",
+ "{616F620B-91C5-4410-A74E-6B81C76FFFE0}",
+ "{E1816BBA-BF5D-4A31-9855-D6BA432055FF}",
+ "{EC08F8FC-2754-47AB-8EFE-56A54057F34E}",
+ "{A095BA0C-224F-4933-A458-2DD7F6B85D8F}")
+//! [1]
diff --git a/examples/activeqt/simple/simple.inf b/examples/activeqt/simple/simple.inf
new file mode 100644
index 0000000..3657e9f
--- /dev/null
+++ b/examples/activeqt/simple/simple.inf
@@ -0,0 +1,11 @@
+//! [0]
+[version]
+ signature="$CHICAGO$"
+ AdvancedINF=2.0
+ [Add.Code]
+ simpleax.exe=simpleax.exe
+ [simpleax.exe]
+ file-win32-x86=thiscab
+ clsid={DF16845C-92CD-4AAB-A982-EB9840E74669}
+ RegisterServer=yes
+//! [0]
diff --git a/examples/activeqt/simple/simple.pro b/examples/activeqt/simple/simple.pro
new file mode 100644
index 0000000..d0f2019
--- /dev/null
+++ b/examples/activeqt/simple/simple.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = simpleax
+
+CONFIG += qt warn_off qaxserver
+
+SOURCES = main.cpp
+RC_FILE = $$QT_SOURCE_TREE/src/activeqt/control/qaxserver.rc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/simple
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS simple.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/simple
+INSTALLS += target sources
diff --git a/examples/activeqt/webbrowser/main.cpp b/examples/activeqt/webbrowser/main.cpp
new file mode 100644
index 0000000..4928380
--- /dev/null
+++ b/examples/activeqt/webbrowser/main.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QMessageBox>
+#include <QProgressBar>
+#include <QStatusBar>
+#include <QMainWindow>
+#include <QAbstractEventDispatcher>
+
+#if defined(Q_WS_WINCE_WM)
+#include "ui_mainwindow_windowsmobile.h"
+#include <windows.h>
+#else
+#include "ui_mainwindow.h"
+#endif
+
+//! [0]
+class MainWindow : public QMainWindow, public Ui::MainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow();
+
+public slots:
+ void on_WebBrowser_TitleChange(const QString &title);
+ void on_WebBrowser_ProgressChange(int a, int b);
+ void on_WebBrowser_CommandStateChange(int cmd, bool on);
+ void on_WebBrowser_BeforeNavigate();
+ void on_WebBrowser_NavigateComplete(QString);
+
+ void on_actionGo_triggered();
+ void on_actionNewWindow_triggered();
+ void on_actionAbout_triggered();
+ void on_actionAboutQt_triggered();
+ void on_actionFileClose_triggered();
+
+private:
+ QProgressBar *pb;
+};
+//! [0] //! [1]
+
+MainWindow::MainWindow()
+{
+ setupUi(this);
+
+ connect(addressEdit, SIGNAL(returnPressed()), actionGo, SLOT(trigger()));
+ connect(actionBack, SIGNAL(triggered()), WebBrowser, SLOT(GoBack()));
+ connect(actionForward, SIGNAL(triggered()), WebBrowser, SLOT(GoForward()));
+ connect(actionStop, SIGNAL(triggered()), WebBrowser, SLOT(Stop()));
+ connect(actionRefresh, SIGNAL(triggered()), WebBrowser, SLOT(Refresh()));
+ connect(actionHome, SIGNAL(triggered()), WebBrowser, SLOT(GoHome()));
+ connect(actionSearch, SIGNAL(triggered()), WebBrowser, SLOT(GoSearch()));
+
+ pb = new QProgressBar(statusBar());
+ pb->setTextVisible(false);
+ pb->hide();
+ statusBar()->addPermanentWidget(pb);
+
+ WebBrowser->dynamicCall("GoHome()");
+}
+
+//! [1] //! [2]
+void MainWindow::on_WebBrowser_TitleChange(const QString &title)
+{
+ setWindowTitle("Qt WebBrowser - " + title);
+}
+
+void MainWindow::on_WebBrowser_ProgressChange(int a, int b)
+{
+ if (a <= 0 || b <= 0) {
+ pb->hide();
+ return;
+ }
+ pb->show();
+ pb->setRange(0, b);
+ pb->setValue(a);
+}
+
+void MainWindow::on_WebBrowser_CommandStateChange(int cmd, bool on)
+{
+ switch (cmd) {
+ case 1:
+ actionForward->setEnabled(on);
+ break;
+ case 2:
+ actionBack->setEnabled(on);
+ break;
+ }
+}
+
+void MainWindow::on_WebBrowser_BeforeNavigate()
+{
+ actionStop->setEnabled(true);
+}
+
+void MainWindow::on_WebBrowser_NavigateComplete(QString)
+{
+ actionStop->setEnabled(false);
+}
+
+//! [2] //! [3]
+void MainWindow::on_actionGo_triggered()
+{
+ WebBrowser->dynamicCall("Navigate(const QString&)", addressEdit->text());
+}
+
+void MainWindow::on_actionNewWindow_triggered()
+{
+ MainWindow *window = new MainWindow;
+ window->show();
+ if (addressEdit->text().isEmpty())
+ return;
+ window->addressEdit->setText(addressEdit->text());
+ window->actionStop->setEnabled(true);
+ window->on_actionGo_triggered();
+}
+
+void MainWindow::on_actionAbout_triggered()
+{
+ QMessageBox::about(this, tr("About WebBrowser"),
+ tr("This Example has been created using the ActiveQt integration into Qt Designer.\n"
+ "It demonstrates the use of QAxWidget to embed the Internet Explorer ActiveX\n"
+ "control into a Qt application."));
+}
+
+void MainWindow::on_actionAboutQt_triggered()
+{
+ QMessageBox::aboutQt(this, tr("About Qt"));
+}
+
+void MainWindow::on_actionFileClose_triggered()
+{
+ close();
+}
+
+#include "main.moc"
+
+//! [3] //! [4]
+int main(int argc, char ** argv)
+{
+ QApplication a(argc, argv);
+ MainWindow w;
+#if defined(Q_OS_WINCE)
+ w.showMaximized();
+#else
+ w.show();
+#endif
+ return a.exec();
+}
+//! [4]
diff --git a/examples/activeqt/webbrowser/mainwindow.ui b/examples/activeqt/webbrowser/mainwindow.ui
new file mode 100644
index 0000000..12a0a32
--- /dev/null
+++ b/examples/activeqt/webbrowser/mainwindow.ui
@@ -0,0 +1,306 @@
+<ui version="4.0" stdsetdef="1" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="objectName" >
+ <string notr="true" >MainWindow</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>812</width>
+ <height>605</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Qt WebBrowser</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="Frame3" >
+ <property name="objectName" >
+ <string notr="true" >Frame3</string>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>1</number>
+ </property>
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="WebAxWidget" name="WebBrowser" >
+ <property name="objectName" >
+ <string notr="true" >WebBrowser</string>
+ </property>
+ <property name="focusPolicy" >
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="control" >
+ <string>{8856F961-340A-11D0-A96B-00C04FD705A2}</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolBar" name="tbNavigate" >
+ <property name="objectName" >
+ <string notr="true" >tbNavigate</string>
+ </property>
+ <property name="windowTitle" >
+ <string>Navigation</string>
+ </property>
+ <addaction name="actionBack" />
+ <addaction name="actionForward" />
+ <addaction name="actionStop" />
+ <addaction name="actionRefresh" />
+ <addaction name="actionHome" />
+ <addaction name="separator" />
+ <addaction name="actionSearch" />
+ </widget>
+ <widget class="QToolBar" name="tbAddress" >
+ <property name="objectName" >
+ <string notr="true" >tbAddress</string>
+ </property>
+ <property name="windowTitle" >
+ <string>Address</string>
+ </property>
+ <widget class="QLabel" name="lblAddress" >
+ <property name="objectName" >
+ <string notr="true" >lblAddress</string>
+ </property>
+ <property name="text" >
+ <string>Address</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" name="addressEdit" >
+ <property name="objectName" >
+ <string notr="true" >addressEdit</string>
+ </property>
+ </widget>
+ <addaction name="actionGo" />
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="objectName" >
+ <string notr="true" >menubar</string>
+ </property>
+ <widget class="QMenu" name="PopupMenu" >
+ <property name="objectName" >
+ <string notr="true" >PopupMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;File</string>
+ </property>
+ <widget class="QMenu" name="FileNewGroup_2" >
+ <property name="objectName" >
+ <string notr="true" >FileNewGroup_2</string>
+ </property>
+ <property name="title" >
+ <string>New</string>
+ </property>
+ <addaction name="actionNewWindow" />
+ </widget>
+ <addaction name="FileNewGroup" />
+ <addaction name="FileNewGroup_2" />
+ <addaction name="separator" />
+ <addaction name="actionFileClose" />
+ </widget>
+ <widget class="QMenu" name="unnamed" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="actionAbout" />
+ <addaction name="actionAboutQt" />
+ </widget>
+ <addaction name="PopupMenu" />
+ <addaction name="unnamed" />
+ </widget>
+ <action name="actionGo" >
+ <property name="objectName" >
+ <string>actionGo</string>
+ </property>
+ <property name="icon" >
+ <iconset>image0</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Go</string>
+ </property>
+ </action>
+ <action name="actionBack" >
+ <property name="objectName" >
+ <string>actionBack</string>
+ </property>
+ <property name="icon" >
+ <iconset>image1</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Back</string>
+ </property>
+ <property name="shortcut" >
+ <string>Backspace</string>
+ </property>
+ </action>
+ <action name="actionForward" >
+ <property name="objectName" >
+ <string>actionForward</string>
+ </property>
+ <property name="icon" >
+ <iconset>image2</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Forward</string>
+ </property>
+ </action>
+ <action name="actionStop" >
+ <property name="objectName" >
+ <string>actionStop</string>
+ </property>
+ <property name="icon" >
+ <iconset>image3</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Stop</string>
+ </property>
+ </action>
+ <action name="actionRefresh" >
+ <property name="objectName" >
+ <string>actionRefresh</string>
+ </property>
+ <property name="icon" >
+ <iconset>image4</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Refresh</string>
+ </property>
+ </action>
+ <action name="actionHome" >
+ <property name="objectName" >
+ <string>actionHome</string>
+ </property>
+ <property name="icon" >
+ <iconset>image5</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Home</string>
+ </property>
+ </action>
+ <action name="actionFileClose" >
+ <property name="objectName" >
+ <string>actionFileClose</string>
+ </property>
+ <property name="iconText" >
+ <string>Close</string>
+ </property>
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </action>
+ <action name="actionSearch" >
+ <property name="objectName" >
+ <string>actionSearch</string>
+ </property>
+ <property name="icon" >
+ <iconset>image6</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Search</string>
+ </property>
+ </action>
+ <action name="actionAbout" >
+ <property name="objectName" >
+ <string>actionAbout</string>
+ </property>
+ <property name="iconText" >
+ <string>About</string>
+ </property>
+ </action>
+ <action name="actionAboutQt" >
+ <property name="objectName" >
+ <string>actionAboutQt</string>
+ </property>
+ <property name="iconText" >
+ <string>About Qt</string>
+ </property>
+ </action>
+ <actiongroup name="FileNewGroup" >
+ <action name="actionNewWindow" >
+ <property name="objectName" >
+ <string>actionNewWindow</string>
+ </property>
+ <property name="iconText" >
+ <string>Window</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <property name="objectName" >
+ <string>FileNewGroup</string>
+ </property>
+ </actiongroup>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>WebAxWidget</class>
+ <extends>QAxWidget</extends>
+ <header>webaxwidget.h</header>
+ </customwidget>
+ </customwidgets>
+ <connections>
+ <connection>
+ <sender>addressEdit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>actionGo</receiver>
+ <slot>trigger()</slot>
+ </connection>
+ </connections>
+ <layoutdefault spacing="6" margin="11" />
+ <images>
+ <image name="image0" >
+ <data format="XPM.GZ" length="1241" >789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade65232365200210543251d2e253d856405bffcbc54103b11c8563600020b03105719c4b530b08072f50880513560a09c080338d5209420294a4451a38c90426621ab5146d10de524a2aa417505445122861a547722bb0c971a3d2aa921c2ae446c6a9431fc85a9064551220e354009653dec00294e712a1ac4e97078a9a9b5e6020013b3f563</data>
+ </image>
+ <image name="image1" >
+ <data format="XPM.GZ" length="4494" >789ce596497332470c86effe15947573a5f4c1cc30cc542a07ef60bc808dd7540e3d9b6df006186c93ca7f8fba2535ce57be98dc9292313c487a2575f7ccf063a376d53baa6dfc589bbe9ad7fbbc96df99496da3983d3e7efcfec76f7faead87418dfe1a51500bd67f595befbfd6f2daf1f35369014e08a05e6fd4ab96e31e73d0282bc7a7cae23ff3ccfe8170ca6cee9843f51f3b4ec8cff9efccdebf2d2cf9b06bb9417a25c74f98bdff99390a84fb8e49af70f39891b2e40bfbf8b6b0917e87968346a8f5a6cc51c07ab02f2cf1983237552f709c86691e3bbd5be5821998a32067bd1765d13f67563d530a4b3df8b01c523d8ec74059faed086bfc82390e851b8ed3c86485e34365a9bfc5ece3df8433e10bcb5140f5dd3cf0e099f32f99e350cecb5858f2b1c1dc52fda663d334a277c0ecfd5d61c9373973120967969b548fd71b079e797d8e985b21eb63aecceb85e7c299f4ffaa2ce7739359ebc195631387c6ad1f5e302791ccbba72cf173e15cfa2d2cc7619cf1fa63c9dccaa4ff4bcfdc7fa82cfdf7999348f6bf299c4bfd4c59ea0f99535dafca71d60a65ffebca52ff8c3989e47cce98351fb785759e7bcbad65bf0be624ca9a8e87caac0fb1702ef191b2cc9731a7b9ec4f87d934659e27e142f8c671e6eb9d0ae7b2be07cc6924ccf999698a7e4f58f572e64cebb9f393444994e68e4365d9ff7be15caef70766ad678cb0f8f18359ebe109b3af27f199fadd794cf254eb196599774758e77d5496f5dd64a67959af122ef87c639b59eb81d34ba97fe3f4215196f3922acbbc28acf527cc792c7a857029ecf63bcded05efb8a52cf3cc9833ed2f66563dac0b8b1ebe3317ea77f73352173db8f6ccf54a66df0f30fb7c777d9bc214d2cf88d9cf73cfece3ddf3296b66da7fe199d7a32b5cc8feef31fbfe8f99bdde96b0faddf3272bac390665b99e90d9e7ef33972de9d73d7ff3d873255c49fc1b73257ee4f8d2eb5d336b3e8e8535ff86d9e7bbf35f2cf51366ef77cfeb6299df62563f3c0a8b1fdcf3d3569778773f756e66f7fcac967e175f797ffff5dfd9ff4103010d6698a35955030b2cb1c25bbcc3fbd5344861882352b8c5077c5c45836678c267ca7fc1314ebeaf81537cc599eb608e6ff88e1f2b682c705314b6486182dbb8f31d0ddca529f644619ff2db641d3cf82a8bfa9d62d7da670d3cc4233c760a63eaa08d2734478fac8f87ffc833788a6738c073bc20ebe3255eb1069d863e5e3b851bacfb7c6b0d0c30c488f24a3a2d4ddaf1986a3d600b13179be280ef597809e876e206000c69d8ec0e590f32c8a18012b7a0825b9799e018eee0de4e0b4318c103ff2ea2985b78c47d28a487ce276b634cca40356d1655801c3bf044af2136e0195ef8b711be4045ab50ff42e16bdbb6463d8e610253fe3d4855ec3ed80abd9f62397ef9c9e6cee835249bc31bbc731ff0010beacbcdbfaca29f2836a3e839fd1f3acb5cb6fd6e13b6605b34766097d6664cdf0d7faad9813dd827df08daf4de812ddaa7061c4017baf43ea6daef70c8fb0247704c932dc897b94e67da09553a811ef4a94a0f4ee10c069435216b630ae7a43b800b7fc6164ea543ea73ea75663b22a50e5cc215ec50956beaf606ead08080147b64c76403d20ebdc6142268528d3655ee3a1db6f88b535ee015b42081d4205ee1f4f335878501ea7644331dc81acecdb7ef63b86b32eae59956cff63237f92af7319c9a82669c989256bd0b6fa6fabe86bbfe0ecdadb9a399ce61b49a86355adfbedd45736756bc27b30afd161a9a9179585de33bf69fd2f8ebd7b5bf014644b906</data>
+ </image>
+ <image name="image2" >
+ <data format="XPM.GZ" length="4494" >789ce5965b4f23471085dff915d6d6db2aaac5e3b92aca037703cbc55c8c21ca43cf8c8d0dd85c6c307694ff9eeaaed3bd68771f968d14298a0a109fabebd4e99a9ef17cfad8e81d1f343e7e5a99cecc6c5435aaa1796a7cac9fc7e3c5ef7ffcf6e7ca8756d4909f661c35a20fbfac7ce8cc1a55e3f07ed2b7409702b4badaccfb996563020f5c7ecbf340b9a31c3591dff7ac7943e002cc8e73cf74acdcc27a8a2d37a5be4e1d9f04567f9fc105f25dcfea9726caad62a07c1158f58f94e3087e868ea57fa5fa0be590bfb11c3525affd4e03ebfa25b8507fbcaa1c47ca66e459fdf10c6c30af4dcfda8f5f9513dfffce71e1f5a956967adddfaeb25f4f7b60e8d199e596f42f6bc787ca213f554e5be06dc7a28ffdee282791cedb5c83d19fd795a55ecf4b3fb0ee07ebd312fae796e3283665e238524e2265de031bcc774d396d61be25b8c4fe1f02abfeab67f49f2867decfbd6393b6a03f03438f3bca19fa51cb33fc6f80fd7eae2c27e257e7cb4de5b4045f78d679f24960ddcfb172e6f73357ce63e88fc115ce43e558fcabbeb905fb7e47cae24ff5daca41af007bbd81e5b425f53aff6160d52f95f318f37d01a39ee7ca05f4790a469e0e1c97590bfa1b81f53c3e2bfbf5ecf697b532efe754398f31af437085eb65948b18e723f70cbf9e2bcc633db0f65b533609fcbafb372bf318fdcfc015e65b281731ee0ff6acf70767ca5e8f7be01abcab5cfa7e89e53cce2ba3fd1681b5df8172013f44e00acfbf4a39e8ef287b7dbe02234feefce795d727a36c12ccf75239d4b7c1bede9def42fcc0ef7960d5cbc05ebf543635aed752b94aa1ff02ee83ddf3b6a87c3d3f2b9b047a4fcaa17e0cf6f5eef928ab13f5476960d5eb7ac6f5dd07d7e04839e83d29d7be9ffbfe31b50dc723cfa87f08acf947e51a7ad457ee6760773ecaa4f47e36036bfd96673c3fb6c13578a01cf41f9505d5af3b2f655dc28fa93da33e550ef523e5e06f08861eb9e7b94cdfe7ddf753d50feb6f94437e00f67edcf3aa4e831ed8afe73bb05fefe655f7c37edcfd62bb81ddfb82935776cfeb41c87766ff2cfe7f1a4c6cb8e48ae91f68d4dce7015ff390473fad71c3b77cc7639ef03d3ffcb48f013ff293a84c79c6d54f693c8bc28b28589539bff2e2ed647e586389184bacf13a6ff0e6d71a32f92dde96bfdf9dbccc6387dba2d086caae4c668ff7bf68f0673ee0433ee263eef0099ff2199f8b62d0e32e5f704fea2fe5b70d3f57729556b91b349a1c718b634e64faa9fc7fc919e772220a91213254ca273b884bf72b4a54f1846ad925e93b1af56940d734a4110fe4efb5c40dddda907311734c7752d10b3a1ae289c634a17b7dafe331e995b3b124fbdfd25d85471763596fab7aa2a4f53d444653ded3773bb96e8faeae1de2ea8dff9da0b0ebfcd858e3357aa667bb1f68b4a5e7d256853559e8f56d64aefe85e6f44a0b5aea3bac5c2bebf74b8775fb6bfbb858771e7a6f1df09c36f89a36698bb6f53d5c4ef08ee4e6a2dd269b9d488729ed4a171b7bd40ece3228cce5d305edd3673ed7773139bd133a14d5233a96cff7a9237142a77446e7125dba900e70681564f5a6acdc1285ae9e0feaf150d675e8d2d59dd315ad52931fec2973d1a5489c6698e29c5a508829797bd629a52665bcf9fdd32ed95c1d50217b5c18b67390f34befb8e78873a9b6b39ad285216328a2de3bef5b32a59db5ccec42a6b565aaf7dffba6e663d3972b211ea86b065f3cbccbc7b53890399a21a55f677f5863e4f670c337df667f58e3d6dc99dbef3dd5ff6bdf73ff82c65fbfaefc0d4fb5b868</data>
+ </image>
+ <image name="image3" >
+ <data format="XPM.GZ" length="802" >789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade65232325500210543251d2e25658564056503300071f540dc3430007371012a492a830156496538c094848922c9c2259134c099304914e3604c8424aa5e6449b0044216ca824ba2da8b4512218b4d122e8b55520fee5974072164511da487ea490c7f22cba249e20d3efc018f3fcae0d2702eb5d2106992b5d65c00b9a48974</data>
+ </image>
+ <image name="image4" >
+ <data format="XPM.GZ" length="1241" >789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade65232365200210543251d2e253d856405bffcbc54105b19c8563600020b03103711c4b530b08072f50880513524ab518681443435ca984ae08ae06a94114a10ac443435ca3043904d4c4453a38ca604ae11590d9a0ab80bd0d46078914c35c4d885a608871a547f61f81d5d117a1862018930e5b8d5c0950c741a1b1e6a6aadb90086a9d853</data>
+ </image>
+ <image name="image5" >
+ <data format="XPM.GZ" length="5598" >789ca5985973db480ec7dff3295cc15b6a0b2351a428d6d63ef83e255bbe647b6a1fd02465dd872d9f53f3dd076c005dc926ce6a32eed8553f37fadf7fa0c1a69cdfbe6cdc9cb537befcf6e97145ab61be910fe861e34bf1349dbefdfedffffcf1e97323dae07f51bdbe117dfed7a7cfddd546bed199cfca0ae888016afeab62e8796ef110ee545caf05be16ae5bfc6ee096e7b6e756983f51b6f53b81257ecfb8eee7e9b162f66af1c78125fe48987f23f3fb81657e691cd5bddecc7316d555efd058f7eb2867aa771058f4de8c55cffb6dd4a34cf5b68d357e681c6515634db81a7e3ef59c35cccf5560bf9ef6953389c77660af074f15c751e05c38a6d81f2ef9f3a848f4e9d658f2c36b635dbfa54cc2383556bd33e12492fc70df38f1f3f8ae4cc2745a711285fda7caa4f95e06967a2d8c63f27a8fc2a60fa4acfa980a371b898f0767dc6cf8fdbc9f84c27e4de124d2fabe186b3dee8c75ff1365dbef2db0ccef0987fd2f2a6632fd576552fd2b63d57b08ecd7d39d70b321fd0560acfb6d1a4b7e3050764de7d79f08a70de937ea7b7689e68f4de1e0776e2c7ab8abecb47eb170aa7ee822b0e89f1b4b7fd24dc529abe9794f02cbf99e2b3badc7a5b1ee97089b3e0e8d253f3c364e253e5576120ff7c63a9f7966d2e771d358e75bca4ef3bb0e2cf9758db5fe47c6b21eeb81bd3f07c2ad58ebd130d67e6a194b3cf97e62b2fa24c67a1f5d2aab3f8781a53e17c6eaa7082cfa3de156acf9d5034b7e3563f1eb96c6eaf7c0b815fbf8d2739e3aedefb1b1de9723618b77a49cebf946c6e20f5f8d251e753e8b5bb9e74c980a4afc7a7fbf66b1ed8fb7c67a9ec7c2ad5cfd74038bdfa6b1f6cbd458fd2e84b358efbb0363f5b71358fccd8c33596f9c4bfddcc458fac78d8cf5797b3296f5f82c4c49e6f5c9bf9fb23ce41307967e3935d6f36c0b67b1ce3f188b5f3757367f5363b98fdc38b0cc0f8cf5f90bf3ea97028bfe50981289777d63edcf81b1c4439897f3c52d615738cfe0df371c1deb7db265acf98d8d253f7a50d67a60c758cfcbf4cc7f2fb0f8bf1736bfae30d6f35f1a4b3ce6c6e2df95ca85f6f7dc58f3db0e5c783e14e6ebc533e87e963fbe0873f9fd3cc97c91693fd028b0d4e3c558f3eb0b9b5f972bab3fe78c353f3056bfabc0e2371636bfe4cf9b29d1e76b69acfdb863accfd33cb0dc2fa7c6e2179e03cb79ae940b7dffbf1b6bfd1363f53b12367f581a6b3d1bca56df6e60a9bfc6e765def4ecef6bc7eafaf9e8d558fbb7a15ce87d7263acf7ffbdb1e40f33e1e0cf29ebfea8eb6d7ff29f17f8f4137dfe51d8fa0117ca65ee3fbfe3bd705116b2de9f775e3af50313e1a229f1f0682cf1b052e6e1d9dfbf1cddd4fd2363cdcfef5fb05b7d1f0c944bed4f67ac9f5f27c265bf4c3d9f07eefb787f1f96695eaa1e0a174d7d7f81b1ee4f81a5fe75e552d9bf1fca7e617e9e8d556f33b0c4fbcf5ffdb44c956bc6a2d75dfd6c2020fd3ce2ff69a0c31c0b2cff91461fef71804374bfaa81231ce3044b9ce2ecd734380fc2392e70890ff888bfa6f184cff8c24e5ef10ddf71f3a37c3ed6c015afdec26dfeb983bbb887fb78f0f734380fe031c7437f3247788c27d8fe713e1f6a1076f014cfb08be7ac7481977885d75c951fe4f3630dcea3c3eb7b9cc70d6b9ce12d9fee26de610debeb69b0fb578cb89a0d8c399711e794609373d9c39455f2b53466d8c20c17809c45cc7a3c00f011081cffccff379fef35388f1d0428a0c401f459e58c3d45700f0003cee71d8678fc730d7430e2557d3c8331f7568c37308129cc7006733e9d262c6008cb6ff3f94ea3c72bc678ca3f1fb80a637884154c71c974c55d72c91a4feca4fdf553f8ad46554d8e9ee30a9eb1efab31611f2ff0ca346427bb9c11e114debe7e7ebed328318702e7f0ce9dbee47a1c724655b745b0c94ea6b0c55519f059b98f73d19a6cc30eecc21eecfb7100877004c770026de8e070bdfe805338832e9cc3055cc2955f7b0d3de8f0cfebb5356ee016eea0c6a30e11342086049a907aadcd35355a90111250f5e5288706bfdb4bea572a78b49e06ddd3a0d2807a2502110d6944639ad09466ebf9e8ae684e0bf5b1a4075ab28f11ffa1df678dc7f57cb0c68a9ee899355e7c2ddbf40a31bdb1c63bcdfe86c6803669cb9f4555c76b38a76dcee57d5d1f5c8f1d5af0b9745581bb029a5c8f3eedd21eed73b70ebe56fa91061dd061f05139e9d1116b1cfb9aee55c4fcf6330d5cd289d778a6b65fdd831dea702e256b9cf2b974a84367d4fd580347744e17744957acc13e7cfc095d538f356ed8cd2ddd518dea147da4c1956890ffcf295ed5e4c83b4a59f182b9455935e3b801ab791c7fa4e188d7a4bcbee66353feaef9df8852ca2f3e9ee3ef73840f359cabfec22979f4ddbd1bf018ba118f318f899bf298b9b95bb8e537cffe9ffffef4171c39a0bf</data>
+ </image>
+ <image name="image6" >
+ <data format="XPM.GZ" length="3742" >789c8d96c9521c490c86ef3c458775734cc8ddd5b5c6c41c303b180cc60b66620eaacc2c9aa5599b7562de7da45fc5180c8e98fa39f091522e4a49c9bbb783bdedcdc1db77735733991d864198c8e5e06dbc9e4eeffffceb8fbfe7de64d9407f466531c8defc36f76667360883adb3d364c013051ae2039f8147266359068f4dc6740a2e4db05f05d726f0253898c017c6a3cc04ffafce79aa3af0143c36c17e055caa0aacbf06aeb2203e5f09ae4d185f75ce472de6e7737063c2fcb57356b702fed673e32c473d4bcf3760198f02e69325706b022f3a676df0f567e05035d1ed273dc79883e7c1d1045e70ae2456d84fd9738a589f0b703261bc72ae25e17ee4b0e7d8f3b5733374e603e32c37c11ff36970db12f193f7e07c1c6bec87c6e0c604ff0e1c4db03f36cec7e3a6f4fd2e38e779eee7bd05e7e350fa7e4fc0455ee6b84fb9eab913bfdf1c5ce5758efba54fffb1e75302d726f8af3817a5f8f922584cf06fc0211f951ebfd0b30afe07ce4510dfdf1e38e665e9f9f1e01c32cf1fda06a73c2f7c7eac5f8c8b61eef582f315b909dc82f1c17e07dc1459e5f1c77d953abb787e0ab832611cf957366dd9c707f556762a3fcf8673ddd6d8afdc1957b909fe98af2a65d4c787c08d09e3c8bfaad504f378de83a309e35fc049d9d747bda19c7dbe8f602d88d6fd11af3a33c1ffde398e02ec69178c0b04bb7fa12be03e08e7ab4b895e2f74ec1ca2e73f6d811b2d37df1feaa9969082f71ff4a73a98c01f9cdb3678fde27eea58f7f9cdc8bfba33c11efda2199ac01bcead048fd72678a4e9e3f6a86f6d172acc87fc69f290f9386f3d72f478a1bf348509fea8b7a66c9b80fec1a8b7a66a53f47cc2fe9b5ae77346fe35ad09e761703081d12f9b68c2fc57ce6d0c1e6fe463934ce0efc63234c11ffd5b4a13c66f9cb53d79fded832bcd27f47f5aeb59055e744eb1df3fe2251aeee4e7453f9264c27aa847b44f7f4f909fda3efb7ae30c5c84b65f1fef435b9a608ff7a4ad4c981ffb6b6b13d8fda5edfb37eff4dcb65e2f787f5a7cb0f7fd0413ecf13eb49d09f6783ff07cf97d8ec0a3f8d8df516f483faf07c45b1f27e9f30ff989e9fdbe11ff1034fd3c9eebe068c238fa9f6677f2fb27ac1f475dd3f97da25fc6c204be755673ef3f8db3360c1f1f824b13c651df2877c44fd0df511efe5ea39f44318151cf9a4e2ab0af870d63fee4dc55fdfe109f880ff3fb788a8ff98df733762630fa471aa6febda2839e5b3f0fe1bef4f18bc9fb01fa7dca4ce0bb9e5b671ef69c3cff18f99cc626d853cf551f3fe453ca531bbdde979cbb2c793e207f536102a39fa5ca0446bf4279f97b89feaabb5181511f38bedf2ffa47373461bdcfe0dc8471d46387860fc6fbaad155c11ef7a5d953747ede69cf2a30fe3fd06c5121fe88572726f8a37f68720ffbfdadf7ac02fb7e82098c7e85ebf2fde37dea92098cf7acc367bc33fbff7a6ecfc4c22d078eaac41d1ff0e4d7f66a7df84293e71ecfec858f9ee8d1fef8a9c733fb139ef2299ff1395ff0255fc167c233befee1f1cc3ef10ddff21ddff303cfabe77bd584177891971e3d7ed8db4e7b2df30aaff29a7aac3ff9ebe4a9bdf2067fe04ddee28ffafb36eff027de558fcfbaab2ffc95bf3db5578b3dfecefb3ce411673c56ceb9e0b23f47a5fbac7fb26f889988742f2a129e504b81a246e0c8ec293cb7a7441d0b1dd0840ee9883486744253bea4533a7bd5fe9c2ed4feb29fff4aff32a36b8dd5e92fe6bfa15bddcf1dddd303cd93c6911668aa2b5cbc363f3c16799f9630fbb2d20aadd21aadeb3d547a8617f6f0d8a00fb4495bfadb47daa61dfa84f977e933c597f64f6e6c9fbed057fa467bf49df669c8bb34a2eca53d8d35576ef88e722aa8a48a6a6a448320a20fd36bf3eb7f407c2c89efb5500f6422877224c77222533915e6b397fbd117f54ccee54275295732936bb9915bb9937b797869ff34e7649ecfe4bd2ce81a8bbc2a4bb2fc5a3dfe2c59915559fb75fdfe8f7affe7f7b97f011cdd9635</data>
+ </image>
+ </images>
+</ui>
diff --git a/examples/activeqt/webbrowser/mainwindow_windowsmobile.ui b/examples/activeqt/webbrowser/mainwindow_windowsmobile.ui
new file mode 100644
index 0000000..98a9ddb
--- /dev/null
+++ b/examples/activeqt/webbrowser/mainwindow_windowsmobile.ui
@@ -0,0 +1,299 @@
+<ui version="4.0" stdsetdef="1" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="objectName" >
+ <string notr="true" >MainWindow</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>812</width>
+ <height>605</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Qt WebBrowser</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="Frame3" >
+ <property name="objectName" >
+ <string notr="true" >Frame3</string>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>1</number>
+ </property>
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QAxWidget" name="WebBrowser" >
+ <property name="objectName" >
+ <string notr="true" >WebBrowser</string>
+ </property>
+ <property name="focusPolicy" >
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="control" >
+ <string>{F5AFC7EF-1571-48B6-A69C-F1833F4C3A44}</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolBar" name="tbNavigate" >
+ <property name="objectName" >
+ <string notr="true" >tbNavigate</string>
+ </property>
+ <property name="windowTitle" >
+ <string>Navigation</string>
+ </property>
+ <addaction name="actionBack" />
+ <addaction name="actionForward" />
+ <addaction name="actionStop" />
+ <addaction name="actionRefresh" />
+ <addaction name="actionHome" />
+ <addaction name="separator" />
+ <addaction name="actionSearch" />
+ </widget>
+ <widget class="QToolBar" name="tbAddress" >
+ <property name="objectName" >
+ <string notr="true" >tbAddress</string>
+ </property>
+ <property name="windowTitle" >
+ <string>Address</string>
+ </property>
+ <widget class="QLabel" name="lblAddress" >
+ <property name="objectName" >
+ <string notr="true" >lblAddress</string>
+ </property>
+ <property name="text" >
+ <string>Address</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" name="addressEdit" >
+ <property name="objectName" >
+ <string notr="true" >addressEdit</string>
+ </property>
+ </widget>
+ <addaction name="actionGo" />
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="objectName" >
+ <string notr="true" >menubar</string>
+ </property>
+ <widget class="QMenu" name="PopupMenu" >
+ <property name="objectName" >
+ <string notr="true" >PopupMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;File</string>
+ </property>
+ <widget class="QMenu" name="FileNewGroup_2" >
+ <property name="objectName" >
+ <string notr="true" >FileNewGroup_2</string>
+ </property>
+ <property name="title" >
+ <string>New</string>
+ </property>
+ <addaction name="actionNewWindow" />
+ </widget>
+ <addaction name="FileNewGroup" />
+ <addaction name="FileNewGroup_2" />
+ <addaction name="separator" />
+ <addaction name="actionFileClose" />
+ </widget>
+ <widget class="QMenu" name="unnamed" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="actionAbout" />
+ <addaction name="actionAboutQt" />
+ </widget>
+ <addaction name="PopupMenu" />
+ <addaction name="unnamed" />
+ </widget>
+ <action name="actionGo" >
+ <property name="objectName" >
+ <string>actionGo</string>
+ </property>
+ <property name="icon" >
+ <iconset>image0</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Go</string>
+ </property>
+ </action>
+ <action name="actionBack" >
+ <property name="objectName" >
+ <string>actionBack</string>
+ </property>
+ <property name="icon" >
+ <iconset>image1</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Back</string>
+ </property>
+ <property name="shortcut" >
+ <string>Backspace</string>
+ </property>
+ </action>
+ <action name="actionForward" >
+ <property name="objectName" >
+ <string>actionForward</string>
+ </property>
+ <property name="icon" >
+ <iconset>image2</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Forward</string>
+ </property>
+ </action>
+ <action name="actionStop" >
+ <property name="objectName" >
+ <string>actionStop</string>
+ </property>
+ <property name="icon" >
+ <iconset>image3</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Stop</string>
+ </property>
+ </action>
+ <action name="actionRefresh" >
+ <property name="objectName" >
+ <string>actionRefresh</string>
+ </property>
+ <property name="icon" >
+ <iconset>image4</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Refresh</string>
+ </property>
+ </action>
+ <action name="actionHome" >
+ <property name="objectName" >
+ <string>actionHome</string>
+ </property>
+ <property name="icon" >
+ <iconset>image5</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Home</string>
+ </property>
+ </action>
+ <action name="actionFileClose" >
+ <property name="objectName" >
+ <string>actionFileClose</string>
+ </property>
+ <property name="iconText" >
+ <string>Close</string>
+ </property>
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </action>
+ <action name="actionSearch" >
+ <property name="objectName" >
+ <string>actionSearch</string>
+ </property>
+ <property name="icon" >
+ <iconset>image6</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Search</string>
+ </property>
+ </action>
+ <action name="actionAbout" >
+ <property name="objectName" >
+ <string>actionAbout</string>
+ </property>
+ <property name="iconText" >
+ <string>About</string>
+ </property>
+ </action>
+ <action name="actionAboutQt" >
+ <property name="objectName" >
+ <string>actionAboutQt</string>
+ </property>
+ <property name="iconText" >
+ <string>About Qt</string>
+ </property>
+ </action>
+ <actiongroup name="FileNewGroup" >
+ <action name="actionNewWindow" >
+ <property name="objectName" >
+ <string>actionNewWindow</string>
+ </property>
+ <property name="iconText" >
+ <string>Window</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <property name="objectName" >
+ <string>FileNewGroup</string>
+ </property>
+ </actiongroup>
+ </widget>
+ <connections>
+ <connection>
+ <sender>addressEdit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>actionGo</receiver>
+ <slot>trigger()</slot>
+ </connection>
+ </connections>
+ <layoutdefault spacing="6" margin="11" />
+ <images>
+ <image name="image0" >
+ <data format="XPM.GZ" length="1241" >789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade65232365200210543251d2e253d856405bffcbc54103b11c8563600020b03105719c4b530b08072f50880513560a09c080338d5209420294a4451a38c90426621ab5146d10de524a2aa417505445122861a547722bb0c971a3d2aa921c2ae446c6a9431fc85a9064551220e354009653dec00294e712a1ac4e97078a9a9b5e6020013b3f563</data>
+ </image>
+ <image name="image1" >
+ <data format="XPM.GZ" length="4494" >789ce596497332470c86effe15947573a5f4c1cc30cc542a07ef60bc808dd7540e3d9b6df006186c93ca7f8fba2535ce57be98dc9292313c487a2575f7ccf063a376d53baa6dfc589bbe9ad7fbbc96df99496da3983d3e7efcfec76f7faead87418dfe1a51500bd67f595befbfd6f2daf1f35369014e08a05e6fd4ab96e31e73d0282bc7a7cae23ff3ccfe8170ca6cee9843f51f3b4ec8cff9efccdebf2d2cf9b06bb9417a25c74f98bdff99390a84fb8e49af70f39891b2e40bfbf8b6b0917e87968346a8f5a6cc51c07ab02f2cf1983237552f709c86691e3bbd5be5821998a32067bd1765d13f67563d530a4b3df8b01c523d8ec74059faed086bfc82390e851b8ed3c86485e34365a9bfc5ece3df8433e10bcb5140f5dd3cf0e099f32f99e350cecb5858f2b1c1dc52fda663d334a277c0ecfd5d61c9373973120967969b548fd71b079e797d8e985b21eb63aecceb85e7c299f4ffaa2ce7739359ebc195631387c6ad1f5e302791ccbba72cf173e15cfa2d2cc7619cf1fa63c9dccaa4ff4bcfdc7fa82cfdf7999348f6bf299c4bfd4c59ea0f99535dafca71d60a65ffebca52ff8c3989e47cce98351fb785759e7bcbad65bf0be624ca9a8e87caac0fb1702ef191b2cc9731a7b9ec4f87d934659e27e142f8c671e6eb9d0ae7b2be07cc6924ccf999698a7e4f58f572e64cebb9f393444994e68e4365d9ff7be15caef70766ad678cb0f8f18359ebe109b3af27f199fadd794cf254eb196599774758e77d5496f5dd64a67959af122ef87c639b59eb81d34ba97fe3f4215196f3922acbbc28acf527cc792c7a857029ecf63bcded05efb8a52cf3cc9833ed2f66563dac0b8b1ebe3317ea77f73352173db8f6ccf54a66df0f30fb7c777d9bc214d2cf88d9cf73cfece3ddf3296b66da7fe199d7a32b5cc8feef31fbfe8f99bdde96b0faddf3272bac390665b99e90d9e7ef33972de9d73d7ff3d873255c49fc1b73257ee4f8d2eb5d336b3e8e8535ff86d9e7bbf35f2cf51366ef77cfeb6299df62563f3c0a8b1fdcf3d3569778773f756e66f7fcac967e175f797ffff5dfd9ff4103010d6698a35955030b2cb1c25bbcc3fbd5344861882352b8c5077c5c45836678c267ca7fc1314ebeaf81537cc599eb608e6ff88e1f2b682c705314b6486182dbb8f31d0ddca529f644619ff2db641d3cf82a8bfa9d62d7da670d3cc4233c760a63eaa08d2734478fac8f87ffc833788a6738c073bc20ebe3255eb1069d863e5e3b851bacfb7c6b0d0c30c488f24a3a2d4ddaf1986a3d600b13179be280ef597809e876e206000c69d8ec0e590f32c8a18012b7a0825b9799e018eee0de4e0b4318c103ff2ea2985b78c47d28a487ce276b634cca40356d1655801c3bf044af2136e0195ef8b711be4045ab50ff42e16bdbb6463d8e610253fe3d4855ec3ed80abd9f62397ef9c9e6cee835249bc31bbc731ff0010beacbcdbfaca29f2836a3e839fd1f3acb5cb6fd6e13b6605b34766097d6664cdf0d7faad9813dd827df08daf4de812ddaa7061c4017baf43ea6daef70c8fb0247704c932dc897b94e67da09553a811ef4a94a0f4ee10c069435216b630ae7a43b800b7fc6164ea543ea73ea75663b22a50e5cc215ec50956beaf606ead08080147b64c76403d20ebdc6142268528d3655ee3a1db6f88b535ee015b42081d4205ee1f4f335878501ea7644331dc81acecdb7ef63b86b32eae59956cff63237f92af7319c9a82669c989256bd0b6fa6fabe86bbfe0ecdadb9a399ce61b49a86355adfbedd45736756bc27b30afd161a9a9179585de33bf69fd2f8ebd7b5bf014644b906</data>
+ </image>
+ <image name="image2" >
+ <data format="XPM.GZ" length="4494" >789ce5965b4f23471085dff915d6d6db2aaac5e3b92aca037703cbc55c8c21ca43cf8c8d0dd85c6c307694ff9eeaaed3bd68771f968d14298a0a109fabebd4e99a9ef17cfad8e81d1f343e7e5a99cecc6c5435aaa1796a7cac9fc7e3c5ef7ffcf6e7ca8756d4909f661c35a20fbfac7ce8cc1a55e3f07ed2b7409702b4badaccfb996563020f5c7ecbf340b9a31c3591dff7ac7943e002cc8e73cf74acdcc27a8a2d37a5be4e1d9f04567f9fc105f25dcfea9726caad62a07c1158f58f94e3087e868ea57fa5fa0be590bfb11c3525affd4e03ebfa25b8507fbcaa1c47ca66e459fdf10c6c30af4dcfda8f5f9513dfffce71e1f5a956967adddfaeb25f4f7b60e8d199e596f42f6bc787ca213f554e5be06dc7a28ffdee282791cedb5c83d19fd795a55ecf4b3fb0ee07ebd312fae796e3283665e238524e2265de031bcc774d396d61be25b8c4fe1f02abfeab67f49f2867decfbd6393b6a03f03438f3bca19fa51cb33fc6f80fd7eae2c27e257e7cb4de5b4045f78d679f24960ddcfb172e6f73357ce63e88fc115ce43e558fcabbeb905fb7e47cae24ff5daca41af007bbd81e5b425f53aff6160d52f95f318f37d01a39ee7ca05f4790a469e0e1c97590bfa1b81f53c3e2bfbf5ecf697b532efe754398f31af437085eb65948b18e723f70cbf9e2bcc633db0f65b533609fcbafb372bf318fdcfc015e65b281731ee0ff6acf70767ca5e8f7be01abcab5cfa7e89e53cce2ba3fd1681b5df8172013f44e00acfbf4a39e8ef287b7dbe02234feefce795d727a36c12ccf75239d4b7c1bede9def42fcc0ef7960d5cbc05ebf543635aed752b94aa1ff02ee83ddf3b6a87c3d3f2b9b047a4fcaa17e0cf6f5eef928ab13f5476960d5eb7ac6f5dd07d7e04839e83d29d7be9ffbfe31b50dc723cfa87f08acf947e51a7ad457ee6760773ecaa4f47e36036bfd96673c3fb6c13578a01cf41f9505d5af3b2f655dc28fa93da33e550ef523e5e06f08861eb9e7b94cdfe7ddf753d50feb6f94437e00f67edcf3aa4e831ed8afe73bb05fefe655f7c37edcfd62bb81ddfb82935776cfeb41c87766ff2cfe7f1a4c6cb8e48ae91f68d4dce7015ff390473fad71c3b77cc7639ef03d3ffcb48f013ff293a84c79c6d54f693c8bc28b28589539bff2e2ed647e586389184bacf13a6ff0e6d71a32f92dde96bfdf9dbccc6387dba2d086caae4c668ff7bf68f0673ee0433ee263eef0099ff2199f8b62d0e32e5f704fea2fe5b70d3f57729556b91b349a1c718b634e64faa9fc7fc919e772220a91213254ca273b884bf72b4a54f1846ad925e93b1af56940d734a4110fe4efb5c40dddda907311734c7752d10b3a1ae289c634a17b7dafe331e995b3b124fbdfd25d85471763596fab7aa2a4f53d444653ded3773bb96e8faeae1de2ea8dff9da0b0ebfcd858e3357aa667bb1f68b4a5e7d256853559e8f56d64aefe85e6f44a0b5aea3bac5c2bebf74b8775fb6bfbb858771e7a6f1df09c36f89a36698bb6f53d5c4ef08ee4e6a2dd269b9d488729ed4a171b7bd40ece3228cce5d305edd3673ed7773139bd133a14d5233a96cff7a9237142a77446e7125dba900e70681564f5a6acdc1285ae9e0feaf150d675e8d2d59dd315ad52931fec2973d1a5489c6698e29c5a508829797bd629a52665bcf9fdd32ed95c1d50217b5c18b67390f34befb8e78873a9b6b39ad285216328a2de3bef5b32a59db5ccec42a6b565aaf7dffba6e663d3972b211ea86b065f3cbccbc7b53890399a21a55f677f5863e4f670c337df667f58e3d6dc99dbef3dd5ff6bdf73ff82c65fbfaefc0d4fb5b868</data>
+ </image>
+ <image name="image3" >
+ <data format="XPM.GZ" length="802" >789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade65232325500210543251d2e25658564056503300071f540dc3430007371012a492a830156496538c094848922c9c2259134c099304914e3604c8424aa5e6449b0044216ca824ba2da8b4512218b4d122e8b55520fee5974072164511da487ea490c7f22cba249e20d3efc018f3fcae0d2702eb5d2106992b5d65c00b9a48974</data>
+ </image>
+ <image name="image4" >
+ <data format="XPM.GZ" length="1241" >789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade65232365200210543251d2e253d856405bffcbc54105b19c8563600020b03103711c4b530b08072f50880513524ab518681443435ca984ae08ae06a94114a10ac443435ca3043904d4c4453a38ca604ae11590d9a0ab80bd0d46078914c35c4d885a608871a547f61f81d5d117a1862018930e5b8d5c0950c741a1b1e6a6aadb90086a9d853</data>
+ </image>
+ <image name="image5" >
+ <data format="XPM.GZ" length="5598" >789ca5985973db480ec7dff3295cc15b6a0b2351a428d6d63ef83e255bbe647b6a1fd02465dd872d9f53f3dd076c005dc926ce6a32eed8553f37fadf7fa0c1a69cdfbe6cdc9cb537befcf6e97145ab61be910fe861e34bf1349dbefdfedffffcf1e97323dae07f51bdbe117dfed7a7cfddd546bed199cfca0ae888016afeab62e8796ef110ee545caf05be16ae5bfc6ee096e7b6e756983f51b6f53b81257ecfb8eee7e9b162f66af1c78125fe48987f23f3fb81657e691cd5bddecc7316d555efd058f7eb2867aa771058f4de8c55cffb6dd4a34cf5b68d357e681c6515634db81a7e3ef59c35cccf5560bf9ef6953389c77660af074f15c751e05c38a6d81f2ef9f3a848f4e9d658f2c36b635dbfa54cc2383556bd33e12492fc70df38f1f3f8ae4cc2745a711285fda7caa4f95e06967a2d8c63f27a8fc2a60fa4acfa980a371b898f0767dc6cf8fdbc9f84c27e4de124d2fabe186b3dee8c75ff1365dbef2db0ccef0987fd2f2a6632fd576552fd2b63d57b08ecd7d39d70b321fd0560acfb6d1a4b7e3050764de7d79f08a70de937ea7b7689e68f4de1e0776e2c7ab8abecb47eb170aa7ee822b0e89f1b4b7fd24dc529abe9794f02cbf99e2b3badc7a5b1ee97089b3e0e8d253f3c364e253e5576120ff7c63a9f7966d2e771d358e75bca4ef3bb0e2cf9758db5fe47c6b21eeb81bd3f07c2ad58ebd130d67e6a194b3cf97e62b2fa24c67a1f5d2aab3f8781a53e17c6eaa7082cfa3de156acf9d5034b7e3563f1eb96c6eaf7c0b815fbf8d2739e3aedefb1b1de9723618b77a49cebf946c6e20f5f8d251e753e8b5bb9e74c980a4afc7a7fbf66b1ed8fb7c67a9ec7c2ad5cfd74038bdfa6b1f6cbd458fd2e84b358efbb0363f5b71358fccd8c33596f9c4bfddcc458fac78d8cf5797b3296f5f82c4c49e6f5c9bf9fb23ce41307967e3935d6f36c0b67b1ce3f188b5f3757367f5363b98fdc38b0cc0f8cf5f90bf3ea97028bfe50981289777d63edcf81b1c4439897f3c52d615738cfe0df371c1deb7db265acf98d8d253f7a50d67a60c758cfcbf4cc7f2fb0f8bf1736bfae30d6f35f1a4b3ce6c6e2df95ca85f6f7dc58f3db0e5c783e14e6ebc533e87e963fbe0873f9fd3cc97c91693fd028b0d4e3c558f3eb0b9b5f972bab3fe78c353f3056bfabc0e2371636bfe4cf9b29d1e76b69acfdb863accfd33cb0dc2fa7c6e2179e03cb79ae940b7dffbf1b6bfd1363f53b12367f581a6b3d1bca56df6e60a9bfc6e765def4ecef6bc7eafaf9e8d558fbb7a15ce87d7263acf7ffbdb1e40f33e1e0cf29ebfea8eb6d7ff29f17f8f4137dfe51d8fa0117ca65ee3fbfe3bd705116b2de9f775e3af50313e1a229f1f0682cf1b052e6e1d9dfbf1cddd4fd2363cdcfef5fb05b7d1f0c944bed4f67ac9f5f27c265bf4c3d9f07eefb787f1f96695eaa1e0a174d7d7f81b1ee4f81a5fe75e552d9bf1fca7e617e9e8d556f33b0c4fbcf5ffdb44c956bc6a2d75dfd6c2020fd3ce2ff69a0c31c0b2cff91461fef71804374bfaa81231ce3044b9ce2ecd734380fc2392e70890ff888bfa6f184cff8c24e5ef10ddf71f3a37c3ed6c015afdec26dfeb983bbb887fb78f0f734380fe031c7437f3247788c27d8fe713e1f6a1076f014cfb08be7ac7481977885d75c951fe4f3630dcea3c3eb7b9cc70d6b9ce12d9fee26de610debeb69b0fb578cb89a0d8c399711e794609373d9c39455f2b53466d8c20c17809c45cc7a3c00f011081cffccff379fef35388f1d0428a0c401f459e58c3d45700f0003cee71d8678fc730d7430e2557d3c8331f7568c37308129cc7006733e9d262c6008cb6ff3f94ea3c72bc678ca3f1fb80a637884154c71c974c55d72c91a4feca4fdf553f8ad46554d8e9ee30a9eb1efab31611f2ff0ca346427bb9c11e114debe7e7ebed328318702e7f0ce9dbee47a1c724655b745b0c94ea6b0c55519f059b98f73d19a6cc30eecc21eecfb7100877004c770026de8e070bdfe805338832e9cc3055cc2955f7b0d3de8f0cfebb5356ee016eea0c6a30e11342086049a907aadcd35355a90111250f5e5288706bfdb4bea572a78b49e06ddd3a0d2807a2502110d6944639ad09466ebf9e8ae684e0bf5b1a4075ab28f11ffa1df678dc7f57cb0c68a9ee899355e7c2ddbf40a31bdb1c63bcdfe86c6803669cb9f4555c76b38a76dcee57d5d1f5c8f1d5af0b9745581bb029a5c8f3eedd21eed73b70ebe56fa91061dd061f05139e9d1116b1cfb9aee55c4fcf6330d5cd289d778a6b65fdd831dea702e256b9cf2b974a84367d4fd580347744e17744957acc13e7cfc095d538f356ed8cd2ddd518dea147da4c1956890ffcf295ed5e4c83b4a59f182b9455935e3b801ab791c7fa4e188d7a4bcbee66353feaef9df8852ca2f3e9ee3ef73840f359cabfec22979f4ddbd1bf018ba118f318f899bf298b9b95bb8e537cffe9ffffef4171c39a0bf</data>
+ </image>
+ <image name="image6" >
+ <data format="XPM.GZ" length="3742" >789c8d96c9521c490c86ef3c458775734cc8ddd5b5c6c41c303b180cc60b66620eaacc2c9aa5599b7562de7da45fc5180c8e98fa39f091522e4a49c9bbb783bdedcdc1db77735733991d864198c8e5e06dbc9e4eeffffceb8fbfe7de64d9407f466531c8defc36f76667360883adb3d364c013051ae2039f8147266359068f4dc6740a2e4db05f05d726f0253898c017c6a3cc04ffafce79aa3af0143c36c17e055caa0aacbf06aeb2203e5f09ae4d185f75ce472de6e7737063c2fcb57356b702fed673e32c473d4bcf3760198f02e69325706b022f3a676df0f567e05035d1ed273dc79883e7c1d1045e70ae2456d84fd9738a589f0b703261bc72ae25e17ee4b0e7d8f3b5733374e603e32c37c11ff36970db12f193f7e07c1c6bec87c6e0c604ff0e1c4db03f36cec7e3a6f4fd2e38e779eee7bd05e7e350fa7e4fc0455ee6b84fb9eab913bfdf1c5ce5758efba54fffb1e75302d726f8af3817a5f8f922584cf06fc0211f951ebfd0b30afe07ce4510dfdf1e38e665e9f9f1e01c32cf1fda06a73c2f7c7eac5f8c8b61eef582f315b909dc82f1c17e07dc1459e5f1c77d953abb787e0ab832611cf957366dd9c707f556762a3fcf8673ddd6d8afdc1957b909fe98af2a65d4c787c08d09e3c8bfaad504f378de83a309e35fc049d9d747bda19c7dbe8f602d88d6fd11af3a33c1ffde398e02ec69178c0b04bb7fa12be03e08e7ab4b895e2f74ec1ca2e73f6d811b2d37df1feaa9969082f71ff4a73a98c01f9cdb3678fde27eea58f7f9cdc8bfba33c11efda2199ac01bcead048fd72678a4e9e3f6a86f6d172acc87fc69f290f9386f3d72f478a1bf348509fea8b7a66c9b80fec1a8b7a66a53f47cc2fe9b5ae77346fe35ad09e761703081d12f9b68c2fc57ce6d0c1e6fe463934ce0efc63234c11ffd5b4a13c66f9cb53d79fded832bcd27f47f5aeb59055e744eb1df3fe2251aeee4e7453f9264c27aa847b44f7f4f909fda3efb7ae30c5c84b65f1fef435b9a608ff7a4ad4c981ffb6b6b13d8fda5edfb37eff4dcb65e2f787f5a7cb0f7fd0413ecf13eb49d09f6783ff07cf97d8ec0a3f8d8df516f483faf07c45b1f27e9f30ff989e9fdbe11ff1034fd3c9eebe068c238fa9f6677f2fb27ac1f475dd3f97da25fc6c204be755673ef3f8db3360c1f1f824b13c651df2877c44fd0df511efe5ea39f44318151cf9a4e2ab0af870d63fee4dc55fdfe109f880ff3fb788a8ff98df733762630fa471aa6febda2839e5b3f0fe1bef4f18bc9fb01fa7dca4ce0bb9e5b671ef69c3cff18f99cc626d853cf551f3fe453ca531bbdde979cbb2c793e207f536102a39fa5ca0446bf4279f97b89feaabb5181511f38bedf2ffa47373461bdcfe0dc8471d46387860fc6fbaad155c11ef7a5d953747ede69cf2a30fe3fd06c5121fe88572726f8a37f68720ffbfdadf7ac02fb7e82098c7e85ebf2fde37dea92098cf7acc367bc33fbff7a6ecfc4c22d078eaac41d1ff0e4d7f66a7df84293e71ecfec858f9ee8d1fef8a9c733fb139ef2299ff1395ff0255fc167c233befee1f1cc3ef10ddff21ddff303cfabe77bd584177891971e3d7ed8db4e7b2df30aaff29a7aac3ff9ebe4a9bdf2067fe04ddee28ffafb36eff027de558fcfbaab2ffc95bf3db5578b3dfecefb3ce411673c56ceb9e0b23f47a5fbac7fb26f889988742f2a129e504b81a246e0c8ec293cb7a7441d0b1dd0840ee9883486744253bea4533a7bd5fe9c2ed4feb29fff4aff32a36b8dd5e92fe6bfa15bddcf1dddd303cd93c6911668aa2b5cbc363f3c16799f9630fbb2d20aadd21aadeb3d547a8617f6f0d8a00fb4495bfadb47daa61dfa84f977e933c597f64f6e6c9fbed057fa467bf49df669c8bb34a2eca53d8d35576ef88e722aa8a48a6a6a448320a20fd36bf3eb7f407c2c89efb5500f6422877224c77222533915e6b397fbd117f54ccee54275295732936bb9915bb9937b797869ff34e7649ecfe4bd2ce81a8bbc2a4bb2fc5a3dfe2c59915559fb75fdfe8f7affe7f7b97f011cdd9635</data>
+ </image>
+ </images>
+</ui>
diff --git a/examples/activeqt/webbrowser/webaxwidget.h b/examples/activeqt/webbrowser/webaxwidget.h
new file mode 100644
index 0000000..b03ce12
--- /dev/null
+++ b/examples/activeqt/webbrowser/webaxwidget.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 WEBAXWIDGET_H
+#define WEBAXWIDGET_H
+
+#include <ActiveQt/QAxWidget>
+#include "windows.h"
+
+class WebAxWidget : public QAxWidget
+{
+public:
+
+ WebAxWidget(QWidget* parent = 0, Qt::WindowFlags f = 0)
+ : QAxWidget(parent, f)
+ {
+ }
+protected:
+ virtual bool translateKeyEvent(int message, int keycode) const
+ {
+ if (message >= WM_KEYFIRST && message <= WM_KEYLAST)
+ return true;
+ else
+ return QAxWidget::translateKeyEvent(message, keycode);
+ }
+
+};
+
+#endif // WEBAXWIDGET_H
diff --git a/examples/activeqt/webbrowser/webbrowser.pro b/examples/activeqt/webbrowser/webbrowser.pro
new file mode 100644
index 0000000..32eac71
--- /dev/null
+++ b/examples/activeqt/webbrowser/webbrowser.pro
@@ -0,0 +1,17 @@
+TEMPLATE = app
+
+CONFIG += qaxcontainer
+
+QTDIR_build:REQUIRES = shared
+
+HEADERS = webaxwidget.h
+SOURCES = main.cpp
+FORMS = mainwindow.ui
+wincewm*: FORMS = mainwindow_windowsmobile.ui
+
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/webbrowser
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS webbrowser.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/webbrowser
+INSTALLS += target sources
diff --git a/examples/activeqt/wrapper/main.cpp b/examples/activeqt/wrapper/main.cpp
new file mode 100644
index 0000000..49756d7
--- /dev/null
+++ b/examples/activeqt/wrapper/main.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include <QAxFactory>
+#include <QCheckBox>
+#include <QRadioButton>
+#include <QPushButton>
+#include <QToolButton>
+#include <QPixmap>
+
+/* XPM */
+static const char *fileopen[] = {
+" 16 13 5 1",
+". c #040404",
+"# c #808304",
+"a c None",
+"b c #f3f704",
+"c c #f3f7f3",
+"aaaaaaaaa...aaaa",
+"aaaaaaaa.aaa.a.a",
+"aaaaaaaaaaaaa..a",
+"a...aaaaaaaa...a",
+".bcb.......aaaaa",
+".cbcbcbcbc.aaaaa",
+".bcbcbcbcb.aaaaa",
+".cbcb...........",
+".bcb.#########.a",
+".cb.#########.aa",
+".b.#########.aaa",
+"..#########.aaaa",
+"...........aaaaa"
+};
+
+
+//! [0]
+class ActiveQtFactory : public QAxFactory
+{
+public:
+ ActiveQtFactory( const QUuid &lib, const QUuid &app )
+ : QAxFactory( lib, app )
+ {}
+ QStringList featureList() const
+ {
+ QStringList list;
+ list << "QCheckBox";
+ list << "QRadioButton";
+ list << "QPushButton";
+ list << "QToolButton";
+ return list;
+ }
+ QObject *createObject(const QString &key)
+ {
+ if ( key == "QCheckBox" )
+ return new QCheckBox(0);
+ if ( key == "QRadioButton" )
+ return new QRadioButton(0);
+ if ( key == "QPushButton" )
+ return new QPushButton(0 );
+ if ( key == "QToolButton" ) {
+ QToolButton *tb = new QToolButton(0);
+// tb->setIcon( QPixmap(fileopen) );
+ return tb;
+ }
+
+ return 0;
+ }
+ const QMetaObject *metaObject( const QString &key ) const
+ {
+ if ( key == "QCheckBox" )
+ return &QCheckBox::staticMetaObject;
+ if ( key == "QRadioButton" )
+ return &QRadioButton::staticMetaObject;
+ if ( key == "QPushButton" )
+ return &QPushButton::staticMetaObject;
+ if ( key == "QToolButton" )
+ return &QToolButton::staticMetaObject;
+
+ return 0;
+ }
+ QUuid classID( const QString &key ) const
+ {
+ if ( key == "QCheckBox" )
+ return "{6E795DE9-872D-43CF-A831-496EF9D86C68}";
+ if ( key == "QRadioButton" )
+ return "{AFCF78C8-446C-409A-93B3-BA2959039189}";
+ if ( key == "QPushButton" )
+ return "{2B262458-A4B6-468B-B7D4-CF5FEE0A7092}";
+ if ( key == "QToolButton" )
+ return "{7c0ffe7a-60c3-4666-bde2-5cf2b54390a1}";
+
+ return QUuid();
+ }
+ QUuid interfaceID( const QString &key ) const
+ {
+ if ( key == "QCheckBox" )
+ return "{4FD39DD7-2DE0-43C1-A8C2-27C51A052810}";
+ if ( key == "QRadioButton" )
+ return "{7CC8AE30-206C-48A3-A009-B0A088026C2F}";
+ if ( key == "QPushButton" )
+ return "{06831CC9-59B6-436A-9578-6D53E5AD03D3}";
+ if ( key == "QToolButton" )
+ return "{6726080f-d63d-4950-a366-9bf33e5cdf84}";
+
+ return QUuid();
+ }
+ QUuid eventsID( const QString &key ) const
+ {
+ if ( key == "QCheckBox" )
+ return "{FDB6FFBE-56A3-4E90-8F4D-198488418B3A}";
+ if ( key == "QRadioButton" )
+ return "{73EE4860-684C-4A66-BF63-9B9EFFA0CBE5}";
+ if ( key == "QPushButton" )
+ return "{3CC3F17F-EA59-4B58-BBD3-842D467131DD}";
+ if ( key == "QToolButton" )
+ return "{f4d421fd-4ead-4fd9-8a25-440766939639}";
+
+ return QUuid();
+ }
+};
+//! [0] //! [1]
+
+QAXFACTORY_EXPORT( ActiveQtFactory, "{3B756301-0075-4E40-8BE8-5A81DE2426B7}", "{AB068077-4924-406a-BBAF-42D91C8727DD}" )
+//! [1]
diff --git a/examples/activeqt/wrapper/wrapper.inf b/examples/activeqt/wrapper/wrapper.inf
new file mode 100644
index 0000000..fc17a3d
--- /dev/null
+++ b/examples/activeqt/wrapper/wrapper.inf
@@ -0,0 +1,9 @@
+[version]
+ signature="$CHICAGO$"
+ AdvancedINF=2.0
+ [Add.Code]
+ wrapperax.dll=wrapperax.dll
+ [wrapperax.dll]
+ file-win32-x86=thiscab
+ clsid={23F5012A-7333-43D3-BCA8-836AABC61B4A}
+ RegisterServer=yes
diff --git a/examples/activeqt/wrapper/wrapper.pro b/examples/activeqt/wrapper/wrapper.pro
new file mode 100644
index 0000000..4eb6baf
--- /dev/null
+++ b/examples/activeqt/wrapper/wrapper.pro
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+TARGET = wrapperax
+
+CONFIG += qt warn_off qaxserver dll
+contains(CONFIG, static):DEFINES += QT_NODLL
+
+SOURCES = main.cpp
+RC_FILE = wrapperax.rc
+DEF_FILE = $$QT_SOURCE_TREE/src/activeqt/control/qaxserver.def
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/wrapper
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS wrapper.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/activeqt/wrapper
+INSTALLS += target sources
diff --git a/examples/activeqt/wrapper/wrapperax.rc b/examples/activeqt/wrapper/wrapperax.rc
new file mode 100644
index 0000000..0ccf606
--- /dev/null
+++ b/examples/activeqt/wrapper/wrapperax.rc
@@ -0,0 +1,32 @@
+#include "winver.h"
+
+1 TYPELIB "wrapperax.rc"
+1 ICON DISCARDABLE "..\\..\\..\\src\\activeqt\\control\\qaxserver.ico"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,0
+ PRODUCTVERSION 1,0,0,0
+ FILEFLAGSMASK 0x3fL
+ FILEOS 0x00040000L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)"
+ VALUE "FileDescription", "Wrapper Example (ActiveQt)"
+ VALUE "FileVersion", "1.0.0.0"
+ VALUE "LegalCopyright", "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)."
+ VALUE "InternalName", "wrapperax.dll"
+ VALUE "OriginalFilename", "wrapperax.dll"
+ VALUE "ProductName", "Wrapper Example (ActiveQt)"
+ VALUE "ProductVersion", "1.0.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/examples/examples.pro b/examples/examples.pro
new file mode 100644
index 0000000..4f16fa0
--- /dev/null
+++ b/examples/examples.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += activeqt
diff --git a/src/activeqt/activeqt.pro b/src/activeqt/activeqt.pro
new file mode 100644
index 0000000..0948ea0
--- /dev/null
+++ b/src/activeqt/activeqt.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+CONFIG += ordered
+SUBDIRS = container
+!wince*: SUBDIRS += control
diff --git a/src/activeqt/container/container.pro b/src/activeqt/container/container.pro
new file mode 100644
index 0000000..4c9b3a8
--- /dev/null
+++ b/src/activeqt/container/container.pro
@@ -0,0 +1,41 @@
+TEMPLATE = lib
+
+TARGET = ActiveQt
+CONFIG += qt_install_headers
+SYNCQT.HEADER_FILES = qaxbase.h qaxobject.h qaxscript.h qaxselect.h qaxwidget.h
+SYNCQT.HEADER_CLASSES = ../../../include/ActiveQt/QAxBase ../../../include/ActiveQt/QAxObject ../../../include/ActiveQt/QAxScriptEngine ../../../include/ActiveQt/QAxScript ../../../include/ActiveQt/QAxScriptManager ../../../include/ActiveQt/QAxSelect ../../../include/ActiveQt/QAxWidget
+include(../../qt_install.pri)
+
+TARGET = QAxContainer
+
+!debug_and_release|build_pass {
+ CONFIG(debug, debug|release) {
+ TARGET = $$member(TARGET, 0)d
+ }
+}
+
+CONFIG += qt warn_on staticlib
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/lib
+
+LIBS += -lole32 -loleaut32
+!wince*:LIBS += -luser32 -lgdi32 -ladvapi32
+win32-g++*:LIBS += -luuid
+
+HEADERS = ../control/qaxaggregated.h \
+ qaxbase.h \
+ qaxwidget.h \
+ qaxobject.h \
+ qaxscript.h \
+ qaxselect.h \
+ ../shared/qaxtypes.h
+
+SOURCES = qaxbase.cpp \
+ qaxdump.cpp \
+ qaxwidget.cpp \
+ qaxobject.cpp \
+ qaxscript.cpp \
+ qaxscriptwrapper.cpp \
+ qaxselect.cpp \
+ ../shared/qaxtypes.cpp
+
+FORMS = qaxselect.ui
diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp
new file mode 100644
index 0000000..aa51925
--- /dev/null
+++ b/src/activeqt/container/qaxbase.cpp
@@ -0,0 +1,4472 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+//#define QAX_NO_CLASSINFO
+
+#define QT_CHECK_STATE
+
+#include "qaxobject.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qfile.h>
+#include <qwidget.h>
+
+#include <quuid.h>
+#include <qhash.h>
+#include <qset.h>
+#include <qpair.h>
+#include <qmetaobject.h>
+#include <qsettings.h>
+
+#ifndef QT_NO_THREAD
+# include <qmutex.h>
+#endif
+
+#include <qt_windows.h>
+#include <ocidl.h>
+#include <ctype.h>
+
+#include "../shared/qaxtypes.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ \internal
+ \class QAxMetaObject
+
+ \brief The QAxMetaObject class stores extended information
+*/
+struct QAxMetaObject : public QMetaObject
+{
+ QAxMetaObject()
+ {
+ d.data = 0;
+ d.stringdata = 0;
+ }
+ ~QAxMetaObject()
+ {
+ delete [] (int*)d.data;
+ delete [] (char*)d.stringdata;
+ }
+
+ int numParameter(const QByteArray &prototype);
+ QByteArray paramType(const QByteArray &signature, int index, bool *out = 0);
+ QByteArray propertyType(const QByteArray &propertyName);
+ void parsePrototype(const QByteArray &prototype);
+ DISPID dispIDofName(const QByteArray &name, IDispatch *disp);
+
+private:
+ friend class MetaObjectGenerator;
+ // save information about QAxEventSink connections, and connect when found in cache
+ QList<QUuid> connectionInterfaces;
+ // DISPID -> signal name
+ QMap< QUuid, QMap<DISPID, QByteArray> > sigs;
+ // DISPID -> property changed signal name
+ QMap< QUuid, QMap<DISPID, QByteArray> > propsigs;
+ // DISPID -> property name
+ QMap< QUuid, QMap<DISPID, QByteArray> > props;
+
+ // Prototype -> member info
+ QHash<QByteArray, QList<QByteArray> > memberInfo;
+ QMap<QByteArray, QByteArray> realPrototype;
+
+ // DISPID cache
+ QHash<QByteArray, DISPID> dispIDs;
+};
+
+void QAxMetaObject::parsePrototype(const QByteArray &prototype)
+{
+ QByteArray realProto = realPrototype.value(prototype, prototype);
+ QByteArray parameters = realProto.mid(realProto.indexOf('(') + 1);
+ parameters.truncate(parameters.length() - 1);
+
+ if (parameters.isEmpty()) {
+ memberInfo.insert(prototype, QList<QByteArray>());
+ } else {
+ QList<QByteArray> plist = parameters.split(',');
+ memberInfo.insert(prototype, plist);
+ }
+}
+
+inline QByteArray QAxMetaObject::propertyType(const QByteArray &propertyName)
+{
+ return realPrototype.value(propertyName);
+}
+
+int QAxMetaObject::numParameter(const QByteArray &prototype)
+{
+ if (!memberInfo.contains(prototype))
+ parsePrototype(prototype);
+
+ return memberInfo.value(prototype).count();
+}
+
+QByteArray QAxMetaObject::paramType(const QByteArray &prototype, int index, bool *out)
+{
+ if (!memberInfo.contains(prototype))
+ parsePrototype(prototype);
+
+ if (out)
+ *out = false;
+
+ QList<QByteArray> plist = memberInfo.value(prototype);
+ if (index > plist.count() - 1)
+ return QByteArray();
+
+ QByteArray param(plist.at(index));
+ if (param.isEmpty())
+ return QByteArray();
+
+ bool byRef = param.endsWith('&') || param.endsWith("**");
+ if (byRef) {
+ param.truncate(param.length() - 1);
+ if (out)
+ *out = true;
+ }
+
+ return param;
+}
+
+inline DISPID QAxMetaObject::dispIDofName(const QByteArray &name, IDispatch *disp)
+{
+ DISPID dispid = dispIDs.value(name, DISPID_UNKNOWN);
+ if (dispid == DISPID_UNKNOWN) {
+ // get the Dispatch ID from the object
+ QString unicodeName = QLatin1String(name);
+ OLECHAR *names = (wchar_t*)unicodeName.utf16();
+ disp->GetIDsOfNames(IID_NULL, &names, 1, LOCALE_USER_DEFAULT, &dispid);
+ if (dispid != DISPID_UNKNOWN)
+ dispIDs.insert(name, dispid);
+ }
+ return dispid;
+}
+
+
+static QHash<QString, QAxMetaObject*> mo_cache;
+static QHash<QUuid, QMap<QByteArray, QList<QPair<QByteArray, int> > > > enum_cache;
+static int mo_cache_ref = 0;
+static QMutex cache_mutex;
+
+
+static const char *const type_conversion[][2] =
+{
+ { "float", "double"},
+ { "short", "int"},
+ { "char", "int"},
+ { "QList<int>", "QVariantList" },
+ { "QList<uint>", "QVariantList" },
+ { "QList<double>", "QVariantList" },
+ { "QList<bool>", "QVariantList" },
+ { "QList<QDateTime>", "QVariantList" },
+ { "QList<qlonglong>", "QVariantList" },
+ { 0, 0 }
+};
+
+/*
+ \internal
+ \class QAxEventSink
+
+ \brief The QAxEventSink class implements the event sink for all
+ IConnectionPoints implemented in the COM object.
+*/
+
+class QAxEventSink : public IDispatch, public IPropertyNotifySink
+{
+public:
+ QAxEventSink(QAxBase *com)
+ : cpoint(0), ciid(IID_NULL), combase(com), ref(1)
+ {}
+ virtual ~QAxEventSink()
+ {
+ Q_ASSERT(!cpoint);
+ }
+
+ QUuid connectionInterface() const
+ {
+ return ciid;
+ }
+ QMap<DISPID, QByteArray> signalMap() const
+ {
+ return sigs;
+ }
+ QMap<DISPID, QByteArray> propertyMap() const
+ {
+ return props;
+ }
+ QMap<DISPID, QByteArray> propSignalMap() const
+ {
+ return propsigs;
+ }
+
+ // add a connection
+ void advise(IConnectionPoint *cp, IID iid)
+ {
+ cpoint = cp;
+ cpoint->AddRef();
+ ciid = iid;
+ cpoint->Advise((IUnknown*)(IDispatch*)this, &cookie);
+ }
+
+ // disconnect from all connection points
+ void unadvise()
+ {
+ combase = 0;
+ if (cpoint) {
+ cpoint->Unadvise(cookie);
+ cpoint->Release();
+ cpoint = 0;
+ }
+ }
+
+ void addSignal(DISPID memid, const char *name)
+ {
+ QByteArray signalname = name;
+ int pi = signalname.indexOf('(');
+ int i = 0;
+ while (type_conversion[i][0]) {
+ int ti = pi;
+ int len = int(strlen(type_conversion[i][0]));
+ while ((ti = signalname.indexOf(type_conversion[i][0], ti)) != -1)
+ signalname.replace(ti, len, type_conversion[i][1]);
+ ++i;
+ }
+
+ sigs.insert(memid, signalname);
+ QMap<DISPID,QByteArray>::ConstIterator it;
+ DISPID id = -1;
+ for (it = propsigs.constBegin(); it!= propsigs.constEnd(); ++it) {
+ if (it.value() == signalname) {
+ id = it.key();
+ break;
+ }
+ }
+ if (id != -1)
+ propsigs.remove(id);
+ }
+ void addProperty(DISPID propid, const char *name, const char *signal)
+ {
+ props.insert(propid, name);
+ propsigs.insert(propid, signal);
+ }
+
+ // IUnknown
+ unsigned long __stdcall AddRef()
+ {
+ return ref++;
+ }
+ unsigned long __stdcall Release()
+ {
+ if (!--ref) {
+ delete this;
+ return 0;
+ }
+ return ref;
+ }
+ HRESULT __stdcall QueryInterface(REFIID riid, void **ppvObject)
+ {
+ *ppvObject = 0;
+ if (riid == IID_IUnknown)
+ *ppvObject = (IUnknown*)(IDispatch*)this;
+ else if (riid == IID_IDispatch)
+ *ppvObject = (IDispatch*)this;
+ else if (riid == IID_IPropertyNotifySink)
+ *ppvObject = (IPropertyNotifySink*)this;
+ else if (ciid == riid)
+ *ppvObject = (IDispatch*)this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+ }
+
+ // IDispatch
+ HRESULT __stdcall GetTypeInfoCount(unsigned int *) { return E_NOTIMPL; }
+ HRESULT __stdcall GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_NOTIMPL; }
+ HRESULT __stdcall GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *) { return E_NOTIMPL; }
+
+ HRESULT __stdcall Invoke(DISPID dispIdMember,
+ REFIID riid,
+ LCID,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT*,
+ EXCEPINFO*,
+ UINT*)
+ {
+ // verify input
+ if (riid != IID_NULL)
+ return DISP_E_UNKNOWNINTERFACE;
+ if (!(wFlags & DISPATCH_METHOD))
+ return DISP_E_MEMBERNOTFOUND;
+ if (!combase)
+ return E_UNEXPECTED;
+
+ QByteArray signame = sigs.value(dispIdMember);
+ if (signame.isEmpty())
+ return DISP_E_MEMBERNOTFOUND;
+
+ QObject *qobject = combase->qObject();
+ if (qobject->signalsBlocked())
+ return S_OK;
+
+ QAxMetaObject *axmeta = combase->internalMetaObject();
+ const QMetaObject *meta = combase->metaObject();
+
+ 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[] = {0, &nameString, &pDispParams->cArgs, &pDispParams->rgvarg};
+ combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
+ }
+
+ HRESULT hres = S_OK;
+
+ // get the signal information from the metaobject
+ index = -1;
+ if (signalHasReceivers(qobject, signame)) {
+ index = meta->indexOfSignal(signame);
+ Q_ASSERT(index != -1);
+ const QMetaMethod signal = meta->method(index);
+ Q_ASSERT(signal.methodType() == QMetaMethod::Signal);
+ Q_ASSERT(signame == signal.signature());
+ // verify parameter count
+ int pcount = axmeta->numParameter(signame);
+ int argcount = pDispParams->cArgs;
+ if (pcount > argcount)
+ return DISP_E_PARAMNOTOPTIONAL;
+ else if (pcount < argcount)
+ return DISP_E_BADPARAMCOUNT;
+
+ // setup parameters (no return values in signals)
+ bool ok = true;
+ void *static_argv[QAX_NUM_PARAMS + 1];
+ void *static_argv_pointer[QAX_NUM_PARAMS + 1];
+ QVariant static_varp[QAX_NUM_PARAMS + 1];
+
+ void **argv = 0;
+ void **argv_pointer = 0; // in case we need an additional level of indirection
+ QVariant *varp = 0;
+
+ if (pcount) {
+ if (pcount <= QAX_NUM_PARAMS) {
+ argv = static_argv;
+ argv_pointer = static_argv_pointer;
+ varp = static_varp;
+ } else {
+ argv = new void*[pcount + 1];
+ argv_pointer = new void*[pcount + 1];
+ varp = new QVariant[pcount + 1];
+ }
+
+ argv[0] = 0;
+ argv_pointer[0] = 0;
+ }
+
+ int p;
+ for (p = 0; p < pcount && ok; ++p) {
+ // map the VARIANT to the void*
+ QByteArray ptype = axmeta->paramType(signame, p);
+ varp[p + 1] = VARIANTToQVariant(pDispParams->rgvarg[pcount - p - 1], ptype);
+ argv_pointer[p + 1] = 0;
+ if (varp[p + 1].isValid()) {
+ if (varp[p + 1].type() == QVariant::UserType) {
+ argv[p + 1] = varp[p + 1].data();
+ } else if (ptype == "QVariant") {
+ argv[p + 1] = varp + p + 1;
+ } else {
+ argv[p + 1] = const_cast<void*>(varp[p + 1].constData());
+ if (ptype.endsWith('*')) {
+ argv_pointer[p + 1] = argv[p + 1];
+ argv[p + 1] = argv_pointer + p + 1;
+ }
+ }
+ } else if (ptype == "QVariant") {
+ argv[p + 1] = varp + p + 1;
+ } else {
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ // emit the generated signal if everything went well
+ combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
+ // update the VARIANT for references and free memory
+ for (p = 0; p < pcount; ++p) {
+ bool out;
+ QByteArray ptype = axmeta->paramType(signame, p, &out);
+ if (out) {
+ if (!QVariantToVARIANT(varp[p + 1], pDispParams->rgvarg[pcount - p - 1], ptype, out))
+ ok = false;
+ }
+ }
+ }
+
+ if (argv != static_argv) {
+ delete [] argv;
+ delete [] argv_pointer;
+ delete [] varp;
+ }
+ hres = ok ? S_OK : (ok ? DISP_E_MEMBERNOTFOUND : DISP_E_TYPEMISMATCH);
+ }
+
+ return hres;
+ }
+
+ QByteArray findProperty(DISPID dispID);
+
+ // IPropertyNotifySink
+ HRESULT __stdcall OnChanged(DISPID dispID)
+ {
+ // verify input
+ if (dispID == DISPID_UNKNOWN || !combase)
+ return S_OK;
+
+ const QMetaObject *meta = combase->metaObject();
+ if (!meta)
+ return S_OK;
+
+ QByteArray propname(findProperty(dispID));
+ if (propname.isEmpty())
+ return S_OK;
+
+ QObject *qobject = combase->qObject();
+ if (qobject->signalsBlocked())
+ return S_OK;
+
+ // emit the generic signal
+ int index = meta->indexOfSignal("propertyChanged(QString)");
+ if (index != -1) {
+ QString propnameString = QString::fromLatin1(propname);
+ void *argv[] = {0, &propnameString};
+ combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
+ }
+
+ QByteArray signame = propsigs.value(dispID);
+ if (signame.isEmpty())
+ return S_OK;
+
+ index = meta->indexOfSignal(signame);
+ if (index == -1) // bindable but not marked as bindable in typelib
+ return S_OK;
+
+ // get the signal information from the metaobject
+ if (signalHasReceivers(qobject, signame)) {
+ index = meta->indexOfSignal(signame);
+ Q_ASSERT(index != -1);
+ // setup parameters
+ QVariant var = qobject->property(propname);
+ if (!var.isValid())
+ return S_OK;
+
+ const QMetaProperty metaProp = meta->property(meta->indexOfProperty(propname));
+ void *argv[] = {0, var.data()};
+ if (metaProp.type() == QVariant::LastType)
+ argv[1] = &var;
+
+ // emit the "changed" signal
+ combase->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
+ }
+ return S_OK;
+ }
+ HRESULT __stdcall OnRequestEdit(DISPID dispID)
+ {
+ if (dispID == DISPID_UNKNOWN || !combase)
+ return S_OK;
+
+ QByteArray propname(findProperty(dispID));
+ if (propname.isEmpty())
+ return S_OK;
+
+ return combase->propertyWritable(propname) ? S_OK : S_FALSE;
+ }
+
+ static bool signalHasReceivers(QObject *qobject, const char *signalName)
+ {
+ Q_ASSERT(qobject);
+ return ((QAxObject*)qobject)->receivers(QByteArray::number(QSIGNAL_CODE) + signalName);
+ }
+
+ IConnectionPoint *cpoint;
+ IID ciid;
+ ULONG cookie;
+
+ QMap<DISPID, QByteArray> sigs;
+ QMap<DISPID, QByteArray> propsigs;
+ QMap<DISPID, QByteArray> props;
+
+ QAxBase *combase;
+ long ref;
+};
+
+/*
+ \internal
+ \class QAxBasePrivate
+*/
+
+class QAxBasePrivate
+{
+public:
+ QAxBasePrivate()
+ : useEventSink(true), useMetaObject(true), useClassInfo(true),
+ cachedMetaObject(false), initialized(false), tryCache(false),
+ ptr(0), disp(0), metaobj(0)
+ {
+ // protect initialization
+ QMutexLocker locker(&cache_mutex);
+ mo_cache_ref++;
+
+ qRegisterMetaType<IUnknown*>("IUnknown*", &ptr);
+ qRegisterMetaType<IDispatch*>("IDispatch*", &disp);
+ }
+
+ ~QAxBasePrivate()
+ {
+ Q_ASSERT(!ptr);
+ Q_ASSERT(!disp);
+
+ // protect cleanup
+ QMutexLocker locker(&cache_mutex);
+ if (!--mo_cache_ref) {
+ qDeleteAll(mo_cache);
+ mo_cache.clear();
+ }
+
+ CoFreeUnusedLibraries();
+ }
+
+ inline IDispatch *dispatch() const
+ {
+ if (disp)
+ return disp;
+
+ if (ptr)
+ ptr->QueryInterface(IID_IDispatch, (void**)&disp);
+ return disp;
+ }
+
+ QString ctrl;
+
+ QHash<QUuid, QAxEventSink*> eventSink;
+ uint useEventSink :1;
+ uint useMetaObject :1;
+ uint useClassInfo :1;
+ uint cachedMetaObject :1;
+ uint initialized :1;
+ uint tryCache :1;
+
+ IUnknown *ptr;
+ mutable IDispatch *disp;
+
+ QMap<QByteArray, bool> propWritable;
+
+ inline QAxMetaObject *metaObject()
+ {
+ if (!metaobj)
+ metaobj = new QAxMetaObject;
+ return metaobj;
+ }
+
+ mutable QMap<QString, LONG> verbs;
+
+ QAxMetaObject *metaobj;
+};
+
+
+QByteArray QAxEventSink::findProperty(DISPID dispID)
+{
+ // look up in cache, and fall back to
+ // type info for precompiled metaobjects
+ QByteArray propname(props.value(dispID));
+
+ if (!propname.isEmpty())
+ return propname;
+
+ IDispatch *dispatch = combase->d->dispatch();
+ ITypeInfo *typeinfo = 0;
+ if (dispatch)
+ dispatch->GetTypeInfo(0, LOCALE_USER_DEFAULT, &typeinfo);
+ if (!typeinfo)
+ return propname;
+
+ BSTR names;
+ UINT cNames;
+ typeinfo->GetNames(dispID, &names, 1, &cNames);
+ if (cNames) {
+ propname = QString::fromWCharArray(names).toLatin1();
+ SysFreeString(names);
+ }
+ typeinfo->Release();
+
+ QByteArray propsignal(propname + "Changed(");
+ const QMetaObject *mo = combase->metaObject();
+ int index = mo->indexOfProperty(propname);
+ const QMetaProperty prop = mo->property(index);
+ propsignal += prop.typeName();
+ propsignal += ')';
+ addProperty(dispID, propname, propsignal);
+
+ return propname;
+}
+
+/*!
+ \class QAxBase
+ \brief The QAxBase class is an abstract class that provides an API
+ to initialize and access a COM object.
+
+ \inmodule QAxContainer
+
+ QAxBase is an abstract class that cannot be used directly, and is
+ instantiated through the subclasses QAxObject and QAxWidget. This
+ class provides the API to access the COM object directly
+ through its IUnknown implementation. If the COM object implements
+ the IDispatch interface, the properties and methods of that object
+ become available as Qt properties and slots.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 0
+
+ Properties exposed by the object's IDispatch implementation can
+ be read and written through the property system provided by the
+ Qt Object Model (both subclasses are QObjects, so you can use
+ QObject::setProperty() and QObject::property()). Properties with
+ multiple parameters are not supported.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 1
+
+ Write-functions for properties and other methods exposed by the
+ object's IDispatch implementation can be called directly using
+ dynamicCall(), or indirectly as slots connected to a signal.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 2
+
+ Outgoing events supported by the COM object are emitted as
+ standard Qt signals.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 3
+
+ QAxBase transparently converts between COM data types and the
+ equivalent Qt data types. Some COM types have no equivalent Qt data structure.
+
+ Supported COM datatypes are listed in the first column of following table.
+ The second column is the Qt type that can be used with the QObject property
+ functions. The third column is the Qt type that is used in the prototype of
+ generated signals and slots for in-parameters, and the last column is the Qt
+ type that is used in the prototype of signals and slots for out-parameters.
+ \table
+ \header
+ \i COM type
+ \i Qt property
+ \i in-parameter
+ \i out-parameter
+ \row
+ \i VARIANT_BOOL
+ \i bool
+ \i bool
+ \i bool&
+ \row
+ \i BSTR
+ \i QString
+ \i const QString&
+ \i QString&
+ \row
+ \i char, short, int, long
+ \i int
+ \i int
+ \i int&
+ \row
+ \i uchar, ushort, uint, ulong
+ \i uint
+ \i uint
+ \i uint&
+ \row
+ \i float, double
+ \i double
+ \i double
+ \i double&
+ \row
+ \i DATE
+ \i QDateTime
+ \i const QDateTime&
+ \i QDateTime&
+ \row
+ \i CY
+ \i qlonglong
+ \i qlonglong
+ \i qlonglong&
+ \row
+ \i OLE_COLOR
+ \i QColor
+ \i const QColor&
+ \i QColor&
+ \row
+ \i SAFEARRAY(VARIANT)
+ \i QList\<QVariant\>
+ \i const QList\<QVariant\>&
+ \i QList\<QVariant\>&
+ \row
+ \i SAFEARRAY(int), SAFEARRAY(double), SAFEARRAY(Date)
+ \i QList\<QVariant\>
+ \i const QList\<QVariant\>&
+ \i QList\<QVariant\>&
+ \row
+ \i SAFEARRAY(BYTE)
+ \i QByteArray
+ \i const QByteArray&
+ \i QByteArray&
+ \row
+ \i SAFEARRAY(BSTR)
+ \i QStringList
+ \i const QStringList&
+ \i QStringList&
+ \row
+ \i VARIANT
+ \i type-dependent
+ \i const QVariant&
+ \i QVariant&
+ \row
+ \i IFontDisp*
+ \i QFont
+ \i const QFont&
+ \i QFont&
+ \row
+ \i IPictureDisp*
+ \i QPixmap
+ \i const QPixmap&
+ \i QPixmap&
+ \row
+ \i IDispatch*
+ \i QAxObject*
+ \i \c QAxBase::asVariant()
+ \i QAxObject* (return value)
+ \row
+ \i IUnknown*
+ \i QAxObject*
+ \i \c QAxBase::asVariant()
+ \i QAxObject* (return value)
+ \row
+ \i SCODE, DECIMAL
+ \i \e unsupported
+ \i \e unsupported
+ \i \e unsupported
+ \row
+ \i VARIANT* (Since Qt 4.5)
+ \i \e unsupported
+ \i \e QVariant&
+ \i \e QVariant&
+ \endtable
+
+ Supported are also enumerations, and typedefs to supported types.
+
+ To call the methods of a COM interface described by the following IDL
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 4
+
+ use the QAxBase API like this:
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 5
+
+ Note that the QList the object should fill has to be provided as an
+ element in the parameter list of \l{QVariant}s.
+
+ If you need to access properties or pass parameters of
+ unsupported datatypes you must access the COM object directly
+ through its \c IDispatch implementation or other interfaces.
+ Those interfaces can be retrieved through queryInterface().
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 6
+
+ To get the definition of the COM interfaces you will have to use the header
+ files provided with the component you want to use. Some compilers can also
+ import type libraries using the #import compiler directive. See the component
+ documentation to find out which type libraries you have to import, and how to use
+ them.
+
+ If you need to react to events that pass parameters of unsupported
+ datatypes you can use the generic signal that delivers the event
+ data as provided by the COM event.
+
+ \sa QAxObject, QAxWidget, QAxScript, {ActiveQt Framework}
+*/
+
+/*!
+ \typedef QAxBase::PropertyBag
+
+ A QMap<QString,QVariant> that can store properties as name:value pairs.
+*/
+
+/*!
+ Creates a QAxBase object that wraps the COM object \a iface. If \a
+ iface is 0 (the default), use setControl() to instantiate a COM
+ object.
+*/
+QAxBase::QAxBase(IUnknown *iface)
+{
+ d = new QAxBasePrivate();
+ d->ptr = iface;
+ if (d->ptr) {
+ d->ptr->AddRef();
+ d->initialized = true;
+ }
+#if defined(Q_OS_WINCE)
+ CoInitializeEx(0, COINIT_MULTITHREADED);
+#endif
+}
+
+/*!
+ Shuts down the COM object and destroys the QAxBase object.
+
+ \sa clear()
+*/
+QAxBase::~QAxBase()
+{
+#if defined(Q_OS_WINCE)
+ CoUninitialize();
+#endif
+
+ clear();
+
+ delete d;
+ d = 0;
+}
+
+/*!
+ \internal
+
+ Used by subclasses generated with dumpcpp to balance reference count.
+*/
+void QAxBase::internalRelease()
+{
+ if (d->ptr)
+ d->ptr->Release();
+}
+
+/*!
+ \internal
+
+ Used by subclasses generated with dumpcpp to implement cast-operators.
+*/
+void QAxBase::initializeFrom(QAxBase *that)
+{
+ if (d->ptr)
+ return;
+
+ d->ptr = that->d->ptr;
+ if (d->ptr) {
+ d->ptr->AddRef();
+ d->initialized = true;
+ }
+}
+
+
+QAxMetaObject *QAxBase::internalMetaObject() const
+{
+ return d->metaObject();
+}
+
+/*!
+ \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 doc/src/snippets/code/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 doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 8
+
+ The slowest, but easiest way to use is to use the control's full
+ name, e.g.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 9
+
+ It is also possible to initialize the object from a file, e.g.
+
+ \snippet doc/src/snippets/code/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
+ \i To initialize the control on a different machine use the following
+ pattern:
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 11
+
+ \i To initialize a licensed control use the following pattern:
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 12
+
+ \i To connect to an already running object use the following pattern:
+
+ \snippet doc/src/snippets/code/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 doc/src/snippets/code/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.
+*/
+bool QAxBase::setControl(const QString &c)
+{
+ if (c.toLower() == d->ctrl.toLower())
+ return !d->ctrl.isEmpty();
+
+ QString search = c;
+ // don't waste time for DCOM requests
+ int dcomIDIndex = search.indexOf(QLatin1String("/{"));
+ if ((dcomIDIndex == -1 || dcomIDIndex != search.length()-39) && !search.endsWith(QLatin1String("}&"))) {
+ QUuid uuid(search);
+ if (uuid.isNull()) {
+ CLSID clsid;
+ HRESULT res = CLSIDFromProgID((wchar_t*)c.utf16(), &clsid);
+ if (res == S_OK)
+ search = QUuid(clsid).toString();
+ else {
+ QSettings controls(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes\\"), QSettings::NativeFormat);
+ search = controls.value(c + QLatin1String("/CLSID/Default")).toString();
+ if (search.isEmpty()) {
+ controls.beginGroup(QLatin1String("/CLSID"));
+ QStringList clsids = controls.childGroups();
+ for (QStringList::Iterator it = clsids.begin(); it != clsids.end(); ++it) {
+ QString clsid = *it;
+ QString name = controls.value(clsid + QLatin1String("/Default")).toString();
+ if (name == c) {
+ search = clsid;
+ break;
+ }
+ }
+ controls.endGroup();
+ }
+ }
+ }
+ if (search.isEmpty())
+ search = c;
+ }
+
+ if (search.toLower() == d->ctrl.toLower())
+ return !d->ctrl.isEmpty();
+
+ clear();
+ d->ctrl = search;
+
+ d->tryCache = true;
+ if (!initialize(&d->ptr))
+ d->initialized = true;
+ if (isNull()) {
+ qWarning("QAxBase::setControl: requested control %s could not be instantiated", c.toLatin1().data());
+ clear();
+ return false;
+ }
+ return true;
+}
+
+QString QAxBase::control() const
+{
+ return d->ctrl;
+}
+
+/*!
+ Disables the event sink implementation for this ActiveX container.
+ If you don't intend to listen to the ActiveX control's events use
+ this function to speed up the meta object generation.
+
+ Some ActiveX controls might be unstable when connected to an event
+ sink. To get OLE events you must use standard COM methods to
+ register your own event sink. Use queryInterface() to get access
+ to the raw COM object.
+
+ Note that this function should be called immediately after
+ construction of the object.
+*/
+void QAxBase::disableEventSink()
+{
+ d->useEventSink = false;
+}
+
+/*!
+ Disables the meta object generation for this ActiveX container.
+ This also disables the event sink and class info generation. If
+ you don't intend to use the Qt meta object implementation call
+ this function to speed up instantiation of the control. You will
+ still be able to call the object through \l dynamicCall(), but
+ signals, slots and properties will not be available with QObject
+ APIs.
+
+ Some ActiveX controls might be unstable when used with OLE
+ automation. Use standard COM methods to use those controls through
+ the COM interfaces provided by queryInterface().
+
+ Note that this function must be called immediately after
+ construction of the object.
+*/
+void QAxBase::disableMetaObject()
+{
+ d->useMetaObject = false;
+ d->useEventSink = false;
+ d->useClassInfo = false;
+}
+
+/*!
+ Disables the class info generation for this ActiveX container. If
+ you don't require any class information about the ActiveX control
+ use this function to speed up the meta object generation.
+
+ Note that this function must be called immediately after
+ construction of the object
+*/
+void QAxBase::disableClassInfo()
+{
+ d->useClassInfo = false;
+}
+
+/*!
+ Disconnects and destroys the COM object.
+
+ If you reimplement this function you must also reimplement the
+ destructor to call clear(), and call this implementation at the
+ end of your clear() function.
+*/
+void QAxBase::clear()
+{
+ QHash<QUuid, QAxEventSink*>::Iterator it = d->eventSink.begin();
+ while (it != d->eventSink.end()) {
+ QAxEventSink *eventSink = it.value();
+ ++it;
+ if (eventSink) {
+ eventSink->unadvise();
+ eventSink->Release();
+ }
+ }
+ d->eventSink.clear();
+ if (d->disp) {
+ d->disp->Release();
+ d->disp = 0;
+ }
+ if (d->ptr) {
+ d->ptr->Release();
+ d->ptr = 0;
+ d->initialized = false;
+ }
+
+ d->ctrl.clear();
+
+ if (!d->cachedMetaObject)
+ delete d->metaobj;
+ d->metaobj = 0;
+}
+
+/*!
+ \since 4.1
+
+ Returns the list of verbs that the COM object can execute. If
+ the object does not implement IOleObject, or does not support
+ any verbs, then this function returns an empty stringlist.
+
+ Note that the OLE default verbs (OLEIVERB_SHOW etc) are not
+ included in the list.
+*/
+QStringList QAxBase::verbs() const
+{
+ if (!d->ptr)
+ return QStringList();
+
+ if (d->verbs.isEmpty()) {
+ IOleObject *ole = 0;
+ d->ptr->QueryInterface(IID_IOleObject, (void**)&ole);
+ if (ole) {
+ IEnumOLEVERB *enumVerbs = 0;
+ ole->EnumVerbs(&enumVerbs);
+ if (enumVerbs) {
+ enumVerbs->Reset();
+ ULONG c;
+ OLEVERB verb;
+ while (enumVerbs->Next(1, &verb, &c) == S_OK) {
+ if (!verb.lpszVerbName)
+ continue;
+ QString verbName = QString::fromWCharArray(verb.lpszVerbName);
+ if (!verbName.isEmpty())
+ d->verbs.insert(verbName, verb.lVerb);
+ }
+ enumVerbs->Release();
+ }
+ ole->Release();
+ }
+ }
+
+ return d->verbs.keys();
+}
+
+/*!
+ \internal
+*/
+
+long QAxBase::indexOfVerb(const QString &verb) const
+{
+ return d->verbs.value(verb);
+}
+
+/*!
+ This virtual function is called by setControl() and creates the
+ requested COM object. \a ptr is set to the object's IUnknown
+ implementation. The function returns true if the object
+ initialization succeeded; otherwise the function returns false.
+
+ The default implementation interprets the string returned by
+ control(), and calls initializeRemote(), initializeLicensed()
+ or initializeActive() if the string matches the respective
+ patterns. If control() is the name of an existing file,
+ initializeFromFile() is called. If no pattern is matched, or
+ if remote or licensed initialization fails, CoCreateInstance
+ is used directly to create the object.
+
+ See the \l control property documentation for details about
+ supported patterns.
+
+ The interface returned in \a ptr must be referenced exactly once
+ when this function returns. The interface provided by e.g.
+ CoCreateInstance is already referenced, and there is no need to
+ reference it again.
+*/
+bool QAxBase::initialize(IUnknown **ptr)
+{
+ if (*ptr || control().isEmpty())
+ return false;
+
+ *ptr = 0;
+
+ bool res = false;
+
+ const QString ctrl(d->ctrl);
+ if (ctrl.contains(QLatin1String("/{"))) // DCOM request
+ res = initializeRemote(ptr);
+ else if (ctrl.contains(QLatin1String("}:"))) // licensed control
+ res = initializeLicensed(ptr);
+ else if (ctrl.contains(QLatin1String("}&"))) // running object
+ res = initializeActive(ptr);
+ else if (QFile::exists(ctrl)) // existing file
+ res = initializeFromFile(ptr);
+
+ if (!res) { // standard
+ HRESULT hres = CoCreateInstance(QUuid(ctrl), 0, CLSCTX_SERVER, IID_IUnknown, (void**)ptr);
+ res = S_OK == hres;
+#ifndef QT_NO_DEBUG
+ if (!res)
+ qErrnoWarning(hres, "CoCreateInstance failure");
+#endif
+ }
+
+ return *ptr != 0;
+}
+
+/*!
+ 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.
+
+ This function is called by initialize() if the control string contains the
+ substring "}:". The license key needs to follow this substring.
+
+ \sa initialize()
+*/
+bool QAxBase::initializeLicensed(IUnknown** ptr)
+{
+ int at = control().lastIndexOf(QLatin1String("}:"));
+
+ QString clsid(control().left(at));
+ QString key(control().mid(at+2));
+
+ IClassFactory *factory = 0;
+ CoGetClassObject(QUuid(clsid), CLSCTX_SERVER, 0, IID_IClassFactory, (void**)&factory);
+ if (!factory)
+ return false;
+ initializeLicensedHelper(factory, key, ptr);
+ factory->Release();
+
+ return *ptr != 0;
+}
+
+/* \internal
+ Called by initializeLicensed and initializedRemote to create an object
+ via IClassFactory2.
+*/
+bool QAxBase::initializeLicensedHelper(void *f, const QString &key, IUnknown **ptr)
+{
+ IClassFactory *factory = (IClassFactory*)f;
+ IClassFactory2 *factory2 = 0;
+ factory->QueryInterface(IID_IClassFactory2, (void**)&factory2);
+ if (factory2) {
+ BSTR bkey = QStringToBSTR(key);
+ HRESULT hres = factory2->CreateInstanceLic(0, 0, IID_IUnknown, bkey, (void**)ptr);
+ SysFreeString(bkey);
+#ifdef QT_DEBUG
+ LICINFO licinfo;
+ licinfo.cbLicInfo = sizeof(LICINFO);
+ factory2->GetLicInfo(&licinfo);
+
+ if (hres != S_OK) {
+ SetLastError(hres);
+ qErrnoWarning("CreateInstanceLic failed");
+ if (!licinfo.fLicVerified) {
+ qWarning("Wrong license key specified, and machine is not fully licensed.");
+ } else if (licinfo.fRuntimeKeyAvail) {
+ BSTR licenseKey;
+ factory2->RequestLicKey(0, &licenseKey);
+ QString qlicenseKey = QString::fromWCharArray(licenseKey);
+ SysFreeString(licenseKey);
+ qWarning("Use license key is '%s' to create object on unlicensed machine.",
+ qlicenseKey.toLatin1().constData());
+ }
+ } else if (licinfo.fLicVerified) {
+ qWarning("Machine is fully licensed for '%s'", control().toLatin1().constData());
+ if (licinfo.fRuntimeKeyAvail) {
+ BSTR licenseKey;
+ factory2->RequestLicKey(0, &licenseKey);
+ QString qlicenseKey = QString::fromWCharArray(licenseKey);
+ SysFreeString(licenseKey);
+
+ if (qlicenseKey != key)
+ qWarning("Runtime license key is '%s'", qlicenseKey.toLatin1().constData());
+ }
+ }
+#else
+ Q_UNUSED(hres);
+#endif
+ factory2->Release();
+ } else { // give it a shot without license
+ factory->CreateInstance(0, IID_IUnknown, (void**)ptr);
+ }
+ return *ptr != 0;
+}
+
+
+/*!
+ Connects to an active instance running on the current machine, and returns the
+ IUnknown interface to the running object in \a ptr. This function returns true
+ if successful, otherwise returns false.
+
+ This function is called by initialize() if the control string contains the
+ substring "}&".
+
+ \sa initialize()
+*/
+bool QAxBase::initializeActive(IUnknown** ptr)
+{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(ptr);
+ return false;
+#else
+ int at = control().lastIndexOf(QLatin1String("}&"));
+ QString clsid(control().left(at));
+
+ GetActiveObject(QUuid(clsid), 0, ptr);
+
+ return *ptr != 0;
+#endif
+}
+
+#ifdef Q_CC_GNU
+# ifndef OLEPENDER_NONE
+# define OLERENDER_NONE 0
+# endif
+#endif
+
+/*!
+ Creates the COM object handling the filename in the control property, and
+ returns the IUnknown interface to the object in \a ptr. This function returns
+ true if successful, otherwise returns false.
+
+ This function is called by initialize() if the control string is the name of
+ an existing file.
+
+ \sa initialize()
+*/
+bool QAxBase::initializeFromFile(IUnknown** ptr)
+{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(ptr);
+ return false;
+#else
+ IStorage *storage = 0;
+ ILockBytes * bytes = 0;
+ HRESULT hres = ::CreateILockBytesOnHGlobal(0, TRUE, &bytes);
+ hres = ::StgCreateDocfileOnILockBytes(bytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &storage);
+
+ hres = OleCreateFromFile(CLSID_NULL, reinterpret_cast<const wchar_t*>(control().utf16()), IID_IUnknown, OLERENDER_NONE, 0, 0, storage, (void**)ptr);
+
+ storage->Release();
+ bytes->Release();
+
+ return hres == S_OK;
+#endif
+}
+
+
+// There seams to be a naming problem in mingw headers
+#if defined(Q_CC_GNU) && !defined(COAUTHIDENTITY) && !defined(__MINGW64_VERSION_MAJOR)
+#define COAUTHIDENTITY AUTH_IDENTITY
+#endif
+
+
+/*!
+ Creates the instance on a remote server, and returns the IUnknown interface
+ to the object in \a ptr. This function returns true if successful, otherwise
+ returns false.
+
+ This function is called by initialize() if the control string contains the
+ substring "/{". The information about the remote machine needs to be provided
+ in front of the substring.
+
+ \sa initialize()
+*/
+bool QAxBase::initializeRemote(IUnknown** ptr)
+{
+ int at = control().lastIndexOf(QLatin1String("/{"));
+
+ QString server(control().left(at));
+ QString clsid(control().mid(at+1));
+
+ QString user;
+ QString domain;
+ QString passwd;
+ QString key;
+
+ at = server.indexOf(QChar::fromLatin1('@'));
+ if (at != -1) {
+ user = server.left(at);
+ server = server.mid(at+1);
+
+ at = user.indexOf(QChar::fromLatin1(':'));
+ if (at != -1) {
+ passwd = user.mid(at+1);
+ user = user.left(at);
+ }
+ at = user.indexOf(QChar::fromLatin1('/'));
+ if (at != -1) {
+ domain = user.left(at);
+ user = user.mid(at+1);
+ }
+ }
+
+ at = clsid.lastIndexOf(QLatin1String("}:"));
+ if (at != -1) {
+ key = clsid.mid(at+2);
+ clsid = clsid.left(at);
+ }
+
+ d->ctrl = server + QChar::fromLatin1('/') + clsid;
+ if (!key.isEmpty())
+ d->ctrl = d->ctrl + QChar::fromLatin1(':') + key;
+
+ COAUTHIDENTITY authIdentity;
+ authIdentity.UserLength = user.length();
+ authIdentity.User = authIdentity.UserLength ? (ushort*)user.utf16() : 0;
+ authIdentity.DomainLength = domain.length();
+ authIdentity.Domain = authIdentity.DomainLength ? (ushort*)domain.utf16() : 0;
+ authIdentity.PasswordLength = passwd.length();
+ authIdentity.Password = authIdentity.PasswordLength ? (ushort*)passwd.utf16() : 0;
+ authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+
+ COAUTHINFO authInfo;
+ authInfo.dwAuthnSvc = RPC_C_AUTHN_WINNT;
+ authInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;
+ authInfo.pwszServerPrincName = 0;
+ authInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
+ authInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
+ authInfo.pAuthIdentityData = &authIdentity;
+ authInfo.dwCapabilities = 0;
+
+ COSERVERINFO serverInfo;
+ serverInfo.dwReserved1 = 0;
+ serverInfo.dwReserved2 = 0;
+ serverInfo.pAuthInfo = &authInfo;
+ serverInfo.pwszName = (wchar_t*)server.utf16();
+
+ IClassFactory *factory = 0;
+ HRESULT res = CoGetClassObject(QUuid(clsid), CLSCTX_REMOTE_SERVER, &serverInfo, IID_IClassFactory, (void**)&factory);
+ if (factory) {
+ if (!key.isEmpty())
+ initializeLicensedHelper(factory, key, ptr);
+ else
+ res = factory->CreateInstance(0, IID_IUnknown, (void**)ptr);
+ factory->Release();
+ }
+#ifndef QT_NO_DEBUG
+ if (res != S_OK)
+ qErrnoWarning(res, "initializeRemote Failed");
+#endif
+
+ return res == S_OK;
+}
+
+/*!
+ Requests the interface \a uuid from the COM object and sets the
+ value of \a iface to the provided interface, or to 0 if the
+ requested interface could not be provided.
+
+ Returns the result of the QueryInterface implementation of the COM object.
+
+ \sa control
+*/
+long QAxBase::queryInterface(const QUuid &uuid, void **iface) const
+{
+ *iface = 0;
+ if (!d->ptr) {
+ ((QAxBase*)this)->initialize(&d->ptr);
+ d->initialized = true;
+ }
+
+ if (d->ptr && !uuid.isNull())
+ return d->ptr->QueryInterface(uuid, iface);
+
+ return E_NOTIMPL;
+}
+
+class MetaObjectGenerator
+{
+public:
+ MetaObjectGenerator(QAxBase *ax, QAxBasePrivate *dptr);
+ MetaObjectGenerator(ITypeLib *typelib, ITypeInfo *typeinfo);
+ ~MetaObjectGenerator();
+
+ QMetaObject *metaObject(const QMetaObject *parentObject, const QByteArray &className = QByteArray());
+
+ void readClassInfo();
+ void readEnumInfo();
+ void readInterfaceInfo();
+ void readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs);
+ void readVarsInfo(ITypeInfo *typeinfo, ushort nVars);
+ void readEventInfo();
+ void readEventInterface(ITypeInfo *eventinfo, IConnectionPoint *cpoint);
+
+ inline void addClassInfo(const char *key, const char *value)
+ {
+ classinfo_list.insert(key, value);
+ }
+
+private:
+ void init();
+
+
+ QMetaObject *tryCache();
+
+ QByteArray createPrototype(FUNCDESC *funcdesc, ITypeInfo *typeinfo, const QList<QByteArray> &names,
+ QByteArray &type, QList<QByteArray> &parameters);
+
+ QByteArray usertypeToString(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function);
+ QByteArray guessTypes(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function);
+
+ // ### from qmetaobject.cpp
+ enum ProperyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ // And our own - don't use the upper byte, as it's used for the property type
+ RequestingEdit = 0x00400000,
+ Bindable = 0x00800000
+ };
+ enum MemberFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ MemberMethod = 0x00,
+ MemberSignal = 0x04,
+ MemberSlot = 0x08,
+ MemberCompatibility = 0x10,
+ MemberCloned = 0x20,
+ MemberScriptable = 0x40,
+ };
+
+ inline QList<QByteArray> paramList(const QByteArray &proto)
+ {
+ QByteArray prototype(proto);
+ QByteArray parameters = prototype.mid(prototype.indexOf('(') + 1);
+ parameters.truncate(parameters.length() - 1);
+
+ QList<QByteArray> plist = parameters.split(',');
+ return plist;
+ }
+
+ inline QByteArray replaceType(const QByteArray &type)
+ {
+ int i = 0;
+ while (type_conversion[i][0]) {
+ int len = int(strlen(type_conversion[i][0]));
+ int ti;
+ if ((ti = type.indexOf(type_conversion[i][0])) != -1) {
+ QByteArray rtype(type);
+ rtype.replace(ti, len, type_conversion[i][1]);
+ return rtype;
+ }
+ ++i;
+ }
+ return type;
+ }
+
+ QByteArray replacePrototype(const QByteArray &prototype)
+ {
+ QByteArray proto(prototype);
+
+ QList<QByteArray> plist = paramList(prototype);
+ for (int p = 0; p < plist.count(); ++p) {
+ QByteArray param(plist.at(p));
+ if (param != replaceType(param)) {
+ int type = 0;
+ while (type_conversion[type][0]) {
+ int paren = proto.indexOf('(');
+ while ((paren = proto.indexOf(type_conversion[type][0])) != -1) {
+ proto.replace(paren, qstrlen(type_conversion[type][0]), type_conversion[type][1]);
+ }
+ ++type;
+ }
+ break;
+ }
+ }
+
+ return proto;
+ }
+
+ QMap<QByteArray, QByteArray> classinfo_list;
+
+ inline bool hasClassInfo(const char *key)
+ {
+ return classinfo_list.contains(key);
+ }
+
+ struct Method {
+ Method() : flags(0)
+ {}
+ QByteArray type;
+ QByteArray parameters;
+ int flags;
+ QByteArray realPrototype;
+ };
+ QMap<QByteArray, Method> signal_list;
+ inline void addSignal(const QByteArray &prototype, const QByteArray &parameters)
+ {
+ QByteArray proto(replacePrototype(prototype));
+
+ Method &signal = signal_list[proto];
+ signal.type = 0;
+ signal.parameters = parameters;
+ signal.flags = QMetaMethod::Public | MemberSignal;
+ if (proto != prototype)
+ signal.realPrototype = prototype;
+ }
+
+ void addChangedSignal(const QByteArray &function, const QByteArray &type, int memid);
+
+ inline bool hasSignal(const QByteArray &prototype)
+ {
+ return signal_list.contains(prototype);
+ }
+
+ QMap<QByteArray, Method> slot_list;
+ inline void addSlot(const QByteArray &type, const QByteArray &prototype, const QByteArray &parameters, int flags = QMetaMethod::Public)
+ {
+ QByteArray proto = replacePrototype(prototype);
+
+ Method &slot = slot_list[proto];
+ slot.type = replaceType(type);
+ slot.parameters = parameters;
+ slot.flags = flags | MemberSlot;
+ if (proto != prototype)
+ slot.realPrototype = prototype;
+ }
+
+ void addSetterSlot(const QByteArray &property);
+
+ inline bool hasSlot(const QByteArray &prototype)
+ {
+ return slot_list.contains(prototype);
+ }
+
+ struct Property {
+ Property() : typeId(0)
+ {}
+ QByteArray type;
+ uint typeId;
+ QByteArray realType;
+ };
+ QMap<QByteArray, Property> property_list;
+ void addProperty(const QByteArray &type, const QByteArray &name, uint flags)
+ {
+ QByteArray propertyType(type);
+ if (propertyType.endsWith('&'))
+ propertyType.chop(1);
+
+ Property &prop = property_list[name];
+ if (!propertyType.isEmpty() && propertyType != "HRESULT") {
+ prop.type = replaceType(propertyType);
+ if (prop.type != propertyType)
+ prop.realType = propertyType;
+ }
+ if (flags & Writable)
+ flags |= Stored;
+ prop.typeId |= flags;
+ QVariant::Type vartype = QVariant::nameToType(prop.type);
+ switch(vartype) {
+ case QVariant::Invalid:
+ case QVariant::UserType:
+ if (prop.type == "QVariant") {
+ prop.typeId |= 0xff << 24;
+ break;
+ }
+ if (QMetaType::type(prop.type) == -1)
+ qWarning("QAxBase: Unsupported property type: %s", prop.type.data());
+ break;
+ default:
+ prop.typeId |= vartype << 24;
+ break;
+ }
+ }
+
+ inline bool hasProperty(const QByteArray &name)
+ {
+ return property_list.contains(name);
+ }
+
+ inline QByteArray propertyType(const QByteArray &name)
+ {
+ return property_list.value(name).type;
+ }
+
+ QMap<QByteArray, QList<QPair<QByteArray, int> > > enum_list;
+ inline void addEnumValue(const QByteArray &enumname, const QByteArray &key, int value)
+ {
+ enum_list[enumname].append(QPair<QByteArray, int>(key, value));
+ }
+
+ inline bool hasEnum(const QByteArray &enumname)
+ {
+ return enum_list.contains(enumname);
+ }
+
+ QAxBase *that;
+ QAxBasePrivate *d;
+
+ IDispatch *disp;
+ ITypeInfo *dispInfo;
+ ITypeInfo *classInfo;
+ ITypeLib *typelib;
+ QByteArray current_typelib;
+
+ QSettings iidnames;
+ QString cacheKey;
+ QByteArray debugInfo;
+
+ QUuid iid_propNotifySink;
+
+ friend QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *classInfo, const QMetaObject *parentObject);
+};
+
+QMetaObject *qax_readEnumInfo(ITypeLib *typeLib, const QMetaObject *parentObject)
+{
+ MetaObjectGenerator generator(typeLib, 0);
+
+ generator.readEnumInfo();
+ return generator.metaObject(parentObject, "EnumInfo");
+}
+
+QMetaObject *qax_readInterfaceInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject)
+{
+ MetaObjectGenerator generator(typeLib, typeInfo);
+
+ QString className;
+ BSTR bstr;
+ if (S_OK != typeInfo->GetDocumentation(-1, &bstr, 0, 0, 0))
+ return 0;
+
+ className = QString::fromWCharArray(bstr);
+ SysFreeString(bstr);
+
+ generator.readEnumInfo();
+ generator.readFuncsInfo(typeInfo, 0);
+ generator.readVarsInfo(typeInfo, 0);
+
+ return generator.metaObject(parentObject, className.toLatin1());
+}
+
+QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *classInfo, const QMetaObject *parentObject)
+{
+ MetaObjectGenerator generator(typeLib, 0);
+ generator.addSignal("exception(int,QString,QString,QString)", "code,source,disc,help");
+ generator.addSignal("propertyChanged(QString)", "name");
+
+ QString className;
+ BSTR bstr;
+ if (S_OK != classInfo->GetDocumentation(-1, &bstr, 0, 0, 0))
+ return 0;
+
+ className = QString::fromWCharArray(bstr);
+ SysFreeString(bstr);
+
+ generator.readEnumInfo();
+
+ TYPEATTR *typeattr;
+ classInfo->GetTypeAttr(&typeattr);
+ if (typeattr) {
+ int nInterfaces = typeattr->cImplTypes;
+ classInfo->ReleaseTypeAttr(typeattr);
+
+ for (int index = 0; index < nInterfaces; ++index) {
+ HREFTYPE refType;
+ if (S_OK != classInfo->GetRefTypeOfImplType(index, &refType))
+ continue;
+
+ int flags = 0;
+ classInfo->GetImplTypeFlags(index, &flags);
+ if (flags & IMPLTYPEFLAG_FRESTRICTED)
+ continue;
+
+ ITypeInfo *interfaceInfo = 0;
+ classInfo->GetRefTypeInfo(refType, &interfaceInfo);
+ if (!interfaceInfo)
+ continue;
+
+ interfaceInfo->GetDocumentation(-1, &bstr, 0, 0, 0);
+ QString interfaceName = QString::fromWCharArray(bstr);
+ SysFreeString(bstr);
+ QByteArray key;
+
+ TYPEATTR *typeattr = 0;
+ interfaceInfo->GetTypeAttr(&typeattr);
+
+ if (flags & IMPLTYPEFLAG_FSOURCE) {
+ if (typeattr && !(typeattr->wTypeFlags & TYPEFLAG_FHIDDEN))
+ key = "Event Interface " + QByteArray::number(index);
+ generator.readEventInterface(interfaceInfo, 0);
+ } else {
+ if (typeattr && !(typeattr->wTypeFlags & TYPEFLAG_FHIDDEN))
+ key = "Interface " + QByteArray::number(index);
+ generator.readFuncsInfo(interfaceInfo, 0);
+ generator.readVarsInfo(interfaceInfo, 0);
+ }
+ if (!key.isEmpty())
+ generator.addClassInfo(key.data(), interfaceName.toLatin1());
+
+ if (typeattr)
+ interfaceInfo->ReleaseTypeAttr(typeattr);
+ interfaceInfo->Release();
+ }
+ }
+
+ return generator.metaObject(parentObject, className.toLatin1());
+}
+
+MetaObjectGenerator::MetaObjectGenerator(QAxBase *ax, QAxBasePrivate *dptr)
+: that(ax), d(dptr), disp(0), dispInfo(0), classInfo(0), typelib(0),
+ iidnames(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"), QSettings::NativeFormat)
+{
+ init();
+}
+
+MetaObjectGenerator::MetaObjectGenerator(ITypeLib *tlib, ITypeInfo *tinfo)
+: that(0), d(0), disp(0), dispInfo(tinfo), classInfo(0), typelib(tlib),
+ iidnames(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"), QSettings::NativeFormat)
+{
+ init();
+
+ if (dispInfo)
+ dispInfo->AddRef();
+ if (typelib) {
+ typelib->AddRef();
+ BSTR bstr;
+ typelib->GetDocumentation(-1, &bstr, 0, 0, 0);
+ current_typelib = QString::fromWCharArray(bstr).toLatin1();
+ SysFreeString(bstr);
+ }
+ readClassInfo();
+}
+
+void MetaObjectGenerator::init()
+{
+ if (d)
+ disp = d->dispatch();
+
+ iid_propNotifySink = IID_IPropertyNotifySink;
+
+ addSignal("signal(QString,int,void*)", "name,argc,argv");
+ addSignal("exception(int,QString,QString,QString)", "code,source,disc,help");
+ addSignal("propertyChanged(QString)", "name");
+ if (d || dispInfo) {
+ addProperty("QString", "control", Readable|Writable|Designable|Scriptable|Stored|Editable|StdCppSet);
+ }
+}
+
+MetaObjectGenerator::~MetaObjectGenerator()
+{
+ if (dispInfo) dispInfo->Release();
+ if (classInfo) classInfo->Release();
+ if (typelib) typelib->Release();
+}
+
+bool qax_dispatchEqualsIDispatch = true;
+QList<QByteArray> qax_qualified_usertypes;
+
+QByteArray MetaObjectGenerator::usertypeToString(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function)
+{
+ HREFTYPE usertype = tdesc.hreftype;
+ if (tdesc.vt != VT_USERDEFINED)
+ return 0;
+
+ QByteArray typeName;
+ ITypeInfo *usertypeinfo = 0;
+ info->GetRefTypeInfo(usertype, &usertypeinfo);
+ if (usertypeinfo) {
+ ITypeLib *usertypelib = 0;
+ UINT index;
+ usertypeinfo->GetContainingTypeLib(&usertypelib, &index);
+ if (usertypelib) {
+ // get type library name
+ BSTR typelibname = 0;
+ usertypelib->GetDocumentation(-1, &typelibname, 0, 0, 0);
+ QByteArray typeLibName = QString::fromWCharArray(typelibname).toLatin1();
+ SysFreeString(typelibname);
+
+ // get type name
+ BSTR usertypename = 0;
+ usertypelib->GetDocumentation(index, &usertypename, 0, 0, 0);
+ QByteArray userTypeName = QString::fromWCharArray(usertypename).toLatin1();
+ SysFreeString(usertypename);
+
+ if (hasEnum(userTypeName)) // known enum?
+ typeName = userTypeName;
+ else if (userTypeName == "OLE_COLOR" || userTypeName == "VB_OLE_COLOR")
+ typeName = "QColor";
+ else if (userTypeName == "IFontDisp" || userTypeName == "IFontDisp*" || userTypeName == "IFont" || userTypeName == "IFont*")
+ typeName = "QFont";
+ else if (userTypeName == "Picture" || userTypeName == "Picture*")
+ typeName = "QPixmap";
+
+ if (typeName.isEmpty()) {
+ TYPEATTR *typeattr = 0;
+ usertypeinfo->GetTypeAttr(&typeattr);
+ if (typeattr) {
+ switch(typeattr->typekind) {
+ case TKIND_ALIAS:
+ userTypeName = guessTypes(typeattr->tdescAlias, usertypeinfo, function);
+ break;
+ case TKIND_DISPATCH:
+ case TKIND_COCLASS:
+ if (qax_dispatchEqualsIDispatch) {
+ userTypeName = "IDispatch";
+ } else {
+ if (typeLibName != current_typelib)
+ userTypeName = typeLibName + "::" + userTypeName;
+ if (!qax_qualified_usertypes.contains(userTypeName))
+ qax_qualified_usertypes << userTypeName;
+ }
+ break;
+ case TKIND_ENUM:
+ if (typeLibName != current_typelib)
+ userTypeName = typeLibName + "::" + userTypeName;
+ if (!qax_qualified_usertypes.contains("enum " + userTypeName))
+ qax_qualified_usertypes << "enum " + userTypeName;
+ break;
+ case TKIND_INTERFACE:
+ if (typeLibName != current_typelib)
+ userTypeName = typeLibName + "::" + userTypeName;
+ if (!qax_qualified_usertypes.contains(userTypeName))
+ qax_qualified_usertypes << userTypeName;
+ break;
+ case TKIND_RECORD:
+ if (!qax_qualified_usertypes.contains("struct " + userTypeName))
+ qax_qualified_usertypes << "struct "+ userTypeName;
+ break;
+ default:
+ break;
+ }
+ }
+
+ usertypeinfo->ReleaseTypeAttr(typeattr);
+ typeName = userTypeName;
+ }
+ usertypelib->Release();
+ }
+ usertypeinfo->Release();
+ }
+
+ return typeName;
+}
+
+#define VT_UNHANDLED(x) case VT_##x: qWarning("QAxBase: Unhandled type %s", #x); str = #x; break;
+
+QByteArray MetaObjectGenerator::guessTypes(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function)
+{
+ QByteArray str;
+ switch (tdesc.vt) {
+ case VT_EMPTY:
+ case VT_VOID:
+ break;
+ case VT_LPWSTR:
+ str = "wchar_t *";
+ break;
+ case VT_BSTR:
+ str = "QString";
+ break;
+ case VT_BOOL:
+ str = "bool";
+ break;
+ case VT_I1:
+ str = "char";
+ break;
+ case VT_I2:
+ str = "short";
+ break;
+ case VT_I4:
+ case VT_INT:
+ str = "int";
+ break;
+ case VT_I8:
+ str = "qlonglong";
+ break;
+ case VT_UI1:
+ case VT_UI2:
+ case VT_UI4:
+ case VT_UINT:
+ str = "uint";
+ break;
+ case VT_UI8:
+ str = "qulonglong";
+ break;
+ case VT_CY:
+ str = "qlonglong";
+ break;
+ case VT_R4:
+ str = "float";
+ break;
+ case VT_R8:
+ str = "double";
+ break;
+ case VT_DATE:
+ str = "QDateTime";
+ break;
+ case VT_DISPATCH:
+ str = "IDispatch*";
+ break;
+ case VT_VARIANT:
+ str = "QVariant";
+ break;
+ case VT_UNKNOWN:
+ str = "IUnknown*";
+ break;
+ case VT_HRESULT:
+ str = "HRESULT";
+ break;
+ case VT_PTR:
+ str = guessTypes(*tdesc.lptdesc, info, function);
+ switch(tdesc.lptdesc->vt) {
+ case VT_VOID:
+ str = "void*";
+ break;
+ case VT_VARIANT:
+ case VT_BSTR:
+ case VT_I1:
+ case VT_I2:
+ case VT_I4:
+ case VT_I8:
+ case VT_UI1:
+ case VT_UI2:
+ case VT_UI4:
+ case VT_UI8:
+ case VT_BOOL:
+ case VT_R4:
+ case VT_R8:
+ case VT_INT:
+ case VT_UINT:
+ case VT_CY:
+ str += '&';
+ break;
+ case VT_PTR:
+ if (str == "QFont" || str == "QPixmap") {
+ str += '&';
+ break;
+ } else if (str == "void*") {
+ str = "void **";
+ break;
+ }
+ // FALLTHROUGH
+ default:
+ if (str == "QColor")
+ str += '&';
+ else if (str == "QDateTime")
+ str += '&';
+ else if (str == "QVariantList")
+ str += '&';
+ else if (str == "QByteArray")
+ str += '&';
+ else if (str == "QStringList")
+ str += '&';
+ else if (!str.isEmpty() && hasEnum(str))
+ str += '&';
+ else if (!str.isEmpty() && str != "QFont" && str != "QPixmap" && str != "QVariant")
+ str += '*';
+ }
+ break;
+ case VT_SAFEARRAY:
+ switch(tdesc.lpadesc->tdescElem.vt) {
+ // some shortcuts, and generic support for lists of QVariant-supported types
+ case VT_UI1:
+ str = "QByteArray";
+ break;
+ case VT_BSTR:
+ str = "QStringList";
+ break;
+ case VT_VARIANT:
+ str = "QVariantList";
+ break;
+ default:
+ str = guessTypes(tdesc.lpadesc->tdescElem, info, function);
+ if (!str.isEmpty())
+ str = "QList<" + str + '>';
+ break;
+ }
+ break;
+ case VT_CARRAY:
+ str = guessTypes(tdesc.lpadesc->tdescElem, info, function);
+ if (!str.isEmpty()) {
+ for (int index = 0; index < tdesc.lpadesc->cDims; ++index)
+ str += '[' + QByteArray::number((int)tdesc.lpadesc->rgbounds[index].cElements) + ']';
+ }
+ break;
+ case VT_USERDEFINED:
+ str = usertypeToString(tdesc, info, function);
+ break;
+
+ VT_UNHANDLED(FILETIME);
+ VT_UNHANDLED(BLOB);
+ VT_UNHANDLED(ERROR);
+ VT_UNHANDLED(DECIMAL);
+ VT_UNHANDLED(LPSTR);
+ default:
+ break;
+ }
+
+ if (tdesc.vt & VT_BYREF)
+ str += '&';
+
+ str.replace("&*", "**");
+ return str;
+}
+
+void MetaObjectGenerator::readClassInfo()
+{
+ // Read class information
+ IProvideClassInfo *provideClassInfo = 0;
+ if (d)
+ d->ptr->QueryInterface(IID_IProvideClassInfo, (void**)&provideClassInfo);
+ if (provideClassInfo) {
+ provideClassInfo->GetClassInfo(&classInfo);
+ TYPEATTR *typeattr = 0;
+ if (classInfo)
+ classInfo->GetTypeAttr(&typeattr);
+
+ QString coClassID;
+ if (typeattr) {
+ QUuid clsid(typeattr->guid);
+ coClassID = clsid.toString().toUpper();
+#ifndef QAX_NO_CLASSINFO
+ // UUID
+ if (d->useClassInfo && !hasClassInfo("CoClass")) {
+ QString coClassIDstr = iidnames.value(QLatin1String("/CLSID/") + coClassID + QLatin1String("/Default"), coClassID).toString();
+ addClassInfo("CoClass", coClassIDstr.isEmpty() ? coClassID.toLatin1() : coClassIDstr.toLatin1());
+ QByteArray version = QByteArray::number(typeattr->wMajorVerNum) + '.' + QByteArray::number(typeattr->wMinorVerNum);
+ if (version != "0.0")
+ addClassInfo("Version", version);
+ }
+#endif
+ classInfo->ReleaseTypeAttr(typeattr);
+ }
+ provideClassInfo->Release();
+ provideClassInfo = 0;
+
+ if (d->tryCache && !coClassID.isEmpty())
+ cacheKey = QString::fromLatin1("%1$%2$%3$%4").arg(coClassID)
+ .arg((int)d->useEventSink).arg((int)d->useClassInfo).arg((int)qax_dispatchEqualsIDispatch);
+ }
+
+ UINT index = 0;
+ if (disp && !dispInfo)
+ disp->GetTypeInfo(index, LOCALE_USER_DEFAULT, &dispInfo);
+
+ if (dispInfo && !typelib)
+ dispInfo->GetContainingTypeLib(&typelib, &index);
+
+ if (!typelib) {
+ QSettings controls(QLatin1String("HKEY_LOCAL_MACHINE\\Software"), QSettings::NativeFormat);
+ QString tlid = controls.value(QLatin1String("/Classes/CLSID/") + that->control() + QLatin1String("/TypeLib/.")).toString();
+ QString tlfile;
+ if (!tlid.isEmpty()) {
+ controls.beginGroup(QLatin1String("/Classes/TypeLib/") + tlid);
+ QStringList versions = controls.childGroups();
+ QStringList::Iterator vit = versions.begin();
+ while (tlfile.isEmpty() && vit != versions.end()) {
+ QString version = *vit;
+ ++vit;
+ tlfile = controls.value(QLatin1Char('/') + version + QLatin1String("/0/win32/.")).toString();
+ }
+ controls.endGroup();
+ } else {
+ tlfile = controls.value(QLatin1String("/Classes/CLSID/") + that->control() + QLatin1String("/InprocServer32/.")).toString();
+ if (tlfile.isEmpty())
+ tlfile = controls.value(QLatin1String("/Classes/CLSID/") + that->control() + QLatin1String("/LocalServer32/.")).toString();
+ }
+ if (!tlfile.isEmpty()) {
+ LoadTypeLib((OLECHAR*)tlfile.utf16(), &typelib);
+ if (!typelib) {
+ tlfile = tlfile.left(tlfile.lastIndexOf(QLatin1Char('.'))) + QLatin1String(".tlb");
+ LoadTypeLib((OLECHAR*)tlfile.utf16(), &typelib);
+ }
+ if (!typelib) {
+ tlfile = tlfile.left(tlfile.lastIndexOf(QLatin1Char('.'))) + QLatin1String(".olb");
+ LoadTypeLib((OLECHAR*)tlfile.utf16(), &typelib);
+ }
+ }
+ }
+
+ if (!classInfo && typelib && that)
+ typelib->GetTypeInfoOfGuid(QUuid(that->control()), &classInfo);
+
+ if (classInfo && !dispInfo) {
+ TYPEATTR *classAttr;
+ classInfo->GetTypeAttr(&classAttr);
+ if (classAttr) {
+ for (int i = 0; i < classAttr->cImplTypes; ++i) {
+ int typeFlags = 0;
+ classInfo->GetImplTypeFlags(i, &typeFlags);
+ if (typeFlags & IMPLTYPEFLAG_FSOURCE)
+ continue;
+
+ HREFTYPE hrefType;
+ if (S_OK == classInfo->GetRefTypeOfImplType(i, &hrefType))
+ classInfo->GetRefTypeInfo(hrefType, &dispInfo);
+ if (dispInfo) {
+ TYPEATTR *ifaceAttr;
+ dispInfo->GetTypeAttr(&ifaceAttr);
+ WORD typekind = ifaceAttr->typekind;
+ dispInfo->ReleaseTypeAttr(ifaceAttr);
+
+ if (typekind & TKIND_DISPATCH) {
+ break;
+ } else {
+ dispInfo->Release();
+ dispInfo = 0;
+ }
+ }
+ }
+ classInfo->ReleaseTypeAttr(classAttr);
+ }
+ }
+
+ if (!d || !dispInfo || !cacheKey.isEmpty() || !d->tryCache)
+ return;
+
+ TYPEATTR *typeattr = 0;
+ dispInfo->GetTypeAttr(&typeattr);
+
+ QString interfaceID;
+ if (typeattr) {
+ QUuid iid(typeattr->guid);
+ interfaceID = iid.toString().toUpper();
+
+ dispInfo->ReleaseTypeAttr(typeattr);
+ // ### event interfaces!!
+ if (!interfaceID.isEmpty())
+ cacheKey = QString::fromLatin1("%1$%2$%3$%4").arg(interfaceID)
+ .arg((int)d->useEventSink).arg((int)d->useClassInfo).arg((int)qax_dispatchEqualsIDispatch);
+ }
+}
+
+void MetaObjectGenerator::readEnumInfo()
+{
+ if (!typelib)
+ return;
+
+ QUuid libUuid;
+
+ if (d && d->tryCache) {
+ TLIBATTR *libAttr = 0;
+ typelib->GetLibAttr(&libAttr);
+ if (libAttr) {
+ libUuid = QUuid(libAttr->guid);
+ typelib->ReleaseTLibAttr(libAttr);
+ enum_list = enum_cache.value(libUuid);
+ if (!enum_list.isEmpty())
+ return;
+ }
+ }
+
+ int valueindex = 0;
+ QSet<QString> clashCheck;
+ int clashIndex = 0;
+
+ int enum_serial = 0;
+ UINT index = typelib->GetTypeInfoCount();
+ for (UINT i = 0; i < index; ++i) {
+ TYPEKIND typekind;
+ typelib->GetTypeInfoType(i, &typekind);
+ if (typekind == TKIND_ENUM) {
+ // Get the type information for the enum
+ ITypeInfo *enuminfo = 0;
+ typelib->GetTypeInfo(i, &enuminfo);
+ if (!enuminfo)
+ continue;
+
+ // Get the name of the enumeration
+ BSTR enumname;
+ QByteArray enumName;
+ if (typelib->GetDocumentation(i, &enumname, 0, 0, 0) == S_OK) {
+ enumName = QString::fromWCharArray(enumname).toLatin1();
+ SysFreeString(enumname);
+ } else {
+ enumName = "enum" + QByteArray::number(++enum_serial);
+ }
+
+ // Get the attributes of the enum type
+ TYPEATTR *typeattr = 0;
+ enuminfo->GetTypeAttr(&typeattr);
+ if (typeattr) {
+ // Get all values of the enumeration
+ for (UINT vd = 0; vd < (UINT)typeattr->cVars; ++vd) {
+ VARDESC *vardesc = 0;
+ enuminfo->GetVarDesc(vd, &vardesc);
+ if (vardesc && vardesc->varkind == VAR_CONST) {
+ int value = vardesc->lpvarValue->lVal;
+ int memid = vardesc->memid;
+ // Get the name of the value
+ BSTR valuename;
+ QByteArray valueName;
+ UINT maxNamesOut;
+ enuminfo->GetNames(memid, &valuename, 1, &maxNamesOut);
+ if (maxNamesOut) {
+ valueName = QString::fromWCharArray(valuename).toLatin1();
+ SysFreeString(valuename);
+ } else {
+ valueName = "value" + QByteArray::number(valueindex++);
+ }
+
+ if (clashCheck.contains(QString::fromLatin1(valueName)))
+ valueName += QByteArray::number(++clashIndex);
+
+ clashCheck.insert(QString::fromLatin1(valueName));
+ addEnumValue(enumName, valueName, value);
+ }
+ enuminfo->ReleaseVarDesc(vardesc);
+ }
+ }
+ enuminfo->ReleaseTypeAttr(typeattr);
+ enuminfo->Release();
+ }
+ }
+
+ if (!libUuid.isNull())
+ enum_cache.insert(libUuid, enum_list);
+}
+
+void MetaObjectGenerator::addChangedSignal(const QByteArray &function, const QByteArray &type, int memid)
+{
+ QAxEventSink *eventSink = 0;
+ if (d) {
+ eventSink = d->eventSink.value(iid_propNotifySink);
+ if (!eventSink && d->useEventSink) {
+ eventSink = new QAxEventSink(that);
+ d->eventSink.insert(iid_propNotifySink, eventSink);
+ }
+ }
+ // generate changed signal
+ QByteArray signalName(function);
+ signalName += "Changed";
+ QByteArray signalProto = signalName + '(' + replaceType(type) + ')';
+ if (!hasSignal(signalProto))
+ addSignal(signalProto, function);
+ if (eventSink)
+ eventSink->addProperty(memid, function, signalProto);
+}
+
+void MetaObjectGenerator::addSetterSlot(const QByteArray &property)
+{
+ QByteArray set;
+ QByteArray prototype(property);
+ if (isupper(prototype.at(0))) {
+ set = "Set";
+ } else {
+ set = "set";
+ prototype[0] = toupper(prototype[0]);
+ }
+ prototype = set + prototype + '(' + propertyType(property) + ')';
+ if (!hasSlot(prototype))
+ addSlot(0, prototype, property);
+}
+
+QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *typeinfo, const QList<QByteArray> &names,
+ QByteArray &type, QList<QByteArray> &parameters)
+{
+ QByteArray prototype;
+ QByteArray function(names.at(0));
+ 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) {
+ type = guessTypes(funcdesc->lprgelemdescParam->tdesc, typeinfo, function);
+ }
+
+ prototype = function + '(';
+ if (funcdesc->invkind == INVOKE_FUNC && type == hresult)
+ type = 0;
+
+ int p;
+ for (p = 1; p < names.count(); ++p) {
+ // parameter
+ QByteArray paramName = names.at(p);
+ bool optional = p > (funcdesc->cParams - funcdesc->cParamsOpt);
+ TYPEDESC tdesc = funcdesc->lprgelemdescParam[p-1].tdesc;
+ PARAMDESC pdesc = funcdesc->lprgelemdescParam[p-1].paramdesc;
+
+ QByteArray ptype = guessTypes(tdesc, typeinfo, function);
+ if (pdesc.wParamFlags & PARAMFLAG_FRETVAL) {
+ if (ptype.endsWith('&')) {
+ ptype.truncate(ptype.length() - 1);
+ } else if (ptype.endsWith("**")) {
+ ptype.truncate(ptype.length() - 1);
+ }
+ type = ptype;
+ } else {
+ prototype += ptype;
+ if (pdesc.wParamFlags & PARAMFLAG_FOUT && !ptype.endsWith('&') && !ptype.endsWith("**"))
+ prototype += '&';
+ if (optional || pdesc.wParamFlags & PARAMFLAG_FOPT)
+ paramName += "=0";
+ else if (pdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
+ // ### get the value from pdesc.pparamdescex
+ paramName += "=0";
+ }
+ parameters << paramName;
+ }
+ if (p < funcdesc->cParams && !(pdesc.wParamFlags & PARAMFLAG_FRETVAL))
+ prototype += ',';
+ }
+
+ if (!prototype.isEmpty()) {
+ if (prototype.endsWith(',')) {
+ if (funcdesc->invkind == INVOKE_PROPERTYPUT && p == funcdesc->cParams) {
+ TYPEDESC tdesc = funcdesc->lprgelemdescParam[p-1].tdesc;
+ QByteArray ptype = guessTypes(tdesc, typeinfo, function);
+ prototype += ptype;
+ prototype += ')';
+ parameters << "rhs";
+ } else {
+ prototype[prototype.length()-1] = ')';
+ }
+ } else {
+ prototype += ')';
+ }
+ }
+
+ return prototype;
+}
+
+void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
+{
+ if (!nFuncs) {
+ TYPEATTR *typeattr = 0;
+ typeinfo->GetTypeAttr(&typeattr);
+ if (typeattr) {
+ nFuncs = typeattr->cFuncs;
+ typeinfo->ReleaseTypeAttr(typeattr);
+ }
+ }
+
+ // get information about all functions
+ for (ushort fd = 0; fd < nFuncs ; ++fd) {
+ FUNCDESC *funcdesc = 0;
+ typeinfo->GetFuncDesc(fd, &funcdesc);
+ if (!funcdesc)
+ break;
+
+ QByteArray function;
+ QByteArray type;
+ QByteArray prototype;
+ QList<QByteArray> parameters;
+
+ // parse function description
+ BSTR bstrNames[256];
+ UINT maxNames = 255;
+ UINT maxNamesOut;
+ typeinfo->GetNames(funcdesc->memid, (BSTR*)&bstrNames, maxNames, &maxNamesOut);
+ QList<QByteArray> names;
+ int p;
+ for (p = 0; p < (int)maxNamesOut; ++p) {
+ names << QString::fromWCharArray(bstrNames[p]).toLatin1();
+ SysFreeString(bstrNames[p]);
+ }
+
+ // function name
+ function = names.at(0);
+ if ((maxNamesOut == 3 && function == "QueryInterface") ||
+ (maxNamesOut == 1 && function == "AddRef") ||
+ (maxNamesOut == 1 && function == "Release") ||
+ (maxNamesOut == 9 && function == "Invoke") ||
+ (maxNamesOut == 6 && function == "GetIDsOfNames") ||
+ (maxNamesOut == 2 && function == "GetTypeInfoCount") ||
+ (maxNamesOut == 4 && function == "GetTypeInfo")) {
+ typeinfo->ReleaseFuncDesc(funcdesc);
+ continue;
+ }
+
+ prototype = createPrototype(/*in*/ funcdesc, typeinfo, names, /*out*/type, parameters);
+
+ // get type of function
+ switch(funcdesc->invkind) {
+ case INVOKE_PROPERTYGET: // property
+ case INVOKE_PROPERTYPUT:
+ if (funcdesc->cParams - funcdesc->cParamsOpt <= 1) {
+ bool dontBreak = false;
+ // getter with non-default-parameters -> fall through to function handling
+ if (funcdesc->invkind == INVOKE_PROPERTYGET && parameters.count() && funcdesc->cParams - funcdesc->cParamsOpt) {
+ dontBreak = true;
+ } else {
+ uint flags = Readable;
+ if (funcdesc->invkind != INVOKE_PROPERTYGET)
+ flags |= Writable;
+ if (!(funcdesc->wFuncFlags & (FUNCFLAG_FNONBROWSABLE | FUNCFLAG_FHIDDEN)))
+ flags |= Designable;
+ if (!(funcdesc->wFuncFlags & FUNCFLAG_FRESTRICTED))
+ flags |= Scriptable;
+ if (funcdesc->wFuncFlags & FUNCFLAG_FREQUESTEDIT)
+ flags |= RequestingEdit;
+ if (hasEnum(type))
+ flags |= EnumOrFlag;
+
+ if (funcdesc->wFuncFlags & FUNCFLAG_FBINDABLE && funcdesc->invkind == INVOKE_PROPERTYGET) {
+ addChangedSignal(function, type, funcdesc->memid);
+ flags |= Bindable;
+ }
+ // Don't generate code for properties without type
+ if (type.isEmpty())
+ break;
+ addProperty(type, function, flags);
+
+ // more parameters -> function handling
+ if (funcdesc->invkind == INVOKE_PROPERTYGET && funcdesc->cParams)
+ dontBreak = true;
+ }
+
+ if (!funcdesc->cParams) {
+ // don't generate slots for incomplete properties
+ if (type.isEmpty())
+ break;
+
+ // Done for getters
+ if (funcdesc->invkind == INVOKE_PROPERTYGET)
+ break;
+
+ // generate setter slot
+ if (funcdesc->invkind == INVOKE_PROPERTYPUT && hasProperty(function)) {
+ addSetterSlot(function);
+ break;
+ }
+ } else if (funcdesc->invkind == INVOKE_PROPERTYPUT && hasProperty(function)) {
+ addSetterSlot(function);
+ // more parameters -> function handling
+ if (funcdesc->cParams > 1)
+ dontBreak = true;
+ }
+ if (!dontBreak)
+ break;
+ }
+ if (funcdesc->invkind == INVOKE_PROPERTYPUT) {
+ // remove the typename guessed for property setters
+ // its done only for setter's with more than one parameter.
+ if (funcdesc->cParams - funcdesc->cParamsOpt > 1) {
+ type.clear();
+ }
+ QByteArray set;
+ if (isupper(prototype.at(0))) {
+ set = "Set";
+ } else {
+ set = "set";
+ prototype[0] = toupper(prototype[0]);
+ }
+
+ prototype = set + prototype;
+ }
+ // FALL THROUGH to support multi-variat properties
+ case INVOKE_FUNC: // method
+ {
+ bool cloned = false;
+ bool defargs;
+ do {
+ QByteArray pnames;
+ for (p = 0; p < parameters.count(); ++p) {
+ pnames += parameters.at(p);
+ if (p < parameters.count() - 1)
+ pnames += ',';
+ }
+ defargs = pnames.contains("=0");
+ int flags = QMetaMethod::Public;
+ if (cloned)
+ flags |= QMetaMethod::Cloned << 4;
+ cloned |= defargs;
+ addSlot(type, prototype, pnames.replace("=0", ""), flags);
+
+ if (defargs) {
+ parameters.takeLast();
+ int lastParam = prototype.lastIndexOf(',');
+ if (lastParam == -1)
+ lastParam = prototype.indexOf('(') + 1;
+ prototype.truncate(lastParam);
+ prototype += ')';
+ }
+ } while (defargs);
+ }
+ break;
+
+ default:
+ break;
+ }
+#if 0 // documentation in metaobject would be cool?
+ // get function documentation
+ BSTR bstrDocu;
+ info->GetDocumentation(funcdesc->memid, 0, &bstrDocu, 0, 0);
+ QString strDocu = QString::fromWCharArray(bstrDocu);
+ SysFreeString(bstrDocu);
+ if (!!strDocu)
+ desc += '[' + strDocu + ']';
+ desc += '\n';
+#endif
+ typeinfo->ReleaseFuncDesc(funcdesc);
+ }
+}
+
+void MetaObjectGenerator::readVarsInfo(ITypeInfo *typeinfo, ushort nVars)
+{
+ if (!nVars) {
+ TYPEATTR *typeattr = 0;
+ typeinfo->GetTypeAttr(&typeattr);
+ if (typeattr) {
+ nVars = typeattr->cVars;
+ typeinfo->ReleaseTypeAttr(typeattr);
+ }
+ }
+
+ // get information about all variables
+ for (ushort vd = 0; vd < nVars; ++vd) {
+ VARDESC *vardesc;
+ typeinfo->GetVarDesc(vd, &vardesc);
+ if (!vardesc)
+ break;
+
+ // no use if it's not a dispatched variable
+ if (vardesc->varkind != VAR_DISPATCH) {
+ typeinfo->ReleaseVarDesc(vardesc);
+ continue;
+ }
+
+ // get variable name
+ BSTR bstrName;
+ UINT maxNames = 1;
+ UINT maxNamesOut;
+ typeinfo->GetNames(vardesc->memid, &bstrName, maxNames, &maxNamesOut);
+ if (maxNamesOut != 1 || !bstrName) {
+ typeinfo->ReleaseVarDesc(vardesc);
+ continue;
+ }
+ QByteArray variableType;
+ QByteArray variableName;
+ uint flags = 0;
+
+ variableName = QString::fromWCharArray(bstrName).toLatin1();
+ SysFreeString(bstrName);
+
+ // get variable type
+ TYPEDESC typedesc = vardesc->elemdescVar.tdesc;
+ variableType = guessTypes(typedesc, typeinfo, variableName);
+
+ // generate meta property
+ if (!hasProperty(variableName)) {
+ flags = Readable;
+ if (!(vardesc->wVarFlags & VARFLAG_FREADONLY))
+ flags |= Writable;
+ if (!(vardesc->wVarFlags & (VARFLAG_FNONBROWSABLE | VARFLAG_FHIDDEN)))
+ flags |= Designable;
+ if (!(vardesc->wVarFlags & VARFLAG_FRESTRICTED))
+ flags |= Scriptable;
+ if (vardesc->wVarFlags & VARFLAG_FREQUESTEDIT)
+ flags |= RequestingEdit;
+ if (hasEnum(variableType))
+ flags |= EnumOrFlag;
+
+ if (vardesc->wVarFlags & VARFLAG_FBINDABLE) {
+ addChangedSignal(variableName, variableType, vardesc->memid);
+ flags |= Bindable;
+ }
+ addProperty(variableType, variableName, flags);
+ }
+
+ // generate a set slot
+ if (!(vardesc->wVarFlags & VARFLAG_FREADONLY))
+ addSetterSlot(variableName);
+
+#if 0 // documentation in metaobject would be cool?
+ // get function documentation
+ BSTR bstrDocu;
+ info->GetDocumentation(vardesc->memid, 0, &bstrDocu, 0, 0);
+ QString strDocu = QString::fromWCharArray(bstrDocu);
+ SysFreeString(bstrDocu);
+ if (!!strDocu)
+ desc += '[' + strDocu + ']';
+ desc += '\n';
+#endif
+ typeinfo->ReleaseVarDesc(vardesc);
+ }
+}
+
+void MetaObjectGenerator::readInterfaceInfo()
+{
+ ITypeInfo *typeinfo = dispInfo;
+ if (!typeinfo)
+ return;
+ typeinfo->AddRef();
+ int interface_serial = 0;
+ while (typeinfo) {
+ ushort nFuncs = 0;
+ ushort nVars = 0;
+ ushort nImpl = 0;
+ // get information about type
+ TYPEATTR *typeattr;
+ typeinfo->GetTypeAttr(&typeattr);
+ bool interesting = true;
+ if (typeattr) {
+ // get number of functions, variables, and implemented interfaces
+ nFuncs = typeattr->cFuncs;
+ nVars = typeattr->cVars;
+ nImpl = typeattr->cImplTypes;
+
+ if ((typeattr->typekind == TKIND_DISPATCH || typeattr->typekind == TKIND_INTERFACE) &&
+ (typeattr->guid != IID_IDispatch && typeattr->guid != IID_IUnknown)) {
+#ifndef QAX_NO_CLASSINFO
+ if (d && d->useClassInfo) {
+ // UUID
+ QUuid uuid(typeattr->guid);
+ QString uuidstr = uuid.toString().toUpper();
+ uuidstr = iidnames.value(QLatin1String("/Interface/") + uuidstr + QLatin1String("/Default"), uuidstr).toString();
+ addClassInfo("Interface " + QByteArray::number(++interface_serial), uuidstr.toLatin1());
+ }
+#endif
+ typeinfo->ReleaseTypeAttr(typeattr);
+ } else {
+ interesting = false;
+ typeinfo->ReleaseTypeAttr(typeattr);
+ }
+ }
+
+ if (interesting) {
+ readFuncsInfo(typeinfo, nFuncs);
+ readVarsInfo(typeinfo, nVars);
+ }
+
+ if (!nImpl) {
+ typeinfo->Release();
+ typeinfo = 0;
+ break;
+ }
+
+ // go up one base class
+ HREFTYPE pRefType;
+ typeinfo->GetRefTypeOfImplType(0, &pRefType);
+ ITypeInfo *baseInfo = 0;
+ typeinfo->GetRefTypeInfo(pRefType, &baseInfo);
+ typeinfo->Release();
+ if (typeinfo == baseInfo) { // IUnknown inherits IUnknown ???
+ baseInfo->Release();
+ typeinfo = 0;
+ break;
+ }
+ typeinfo = baseInfo;
+ }
+}
+
+void MetaObjectGenerator::readEventInterface(ITypeInfo *eventinfo, IConnectionPoint *cpoint)
+{
+ TYPEATTR *eventattr;
+ eventinfo->GetTypeAttr(&eventattr);
+ if (!eventattr)
+ return;
+ if (eventattr->typekind != TKIND_DISPATCH) {
+ eventinfo->ReleaseTypeAttr(eventattr);
+ return;
+ }
+
+ QAxEventSink *eventSink = 0;
+ if (d) {
+ IID conniid;
+ cpoint->GetConnectionInterface(&conniid);
+ eventSink = d->eventSink.value(QUuid(conniid));
+ if (!eventSink) {
+ eventSink = new QAxEventSink(that);
+ d->eventSink.insert(QUuid(conniid), eventSink);
+ eventSink->advise(cpoint, conniid);
+ }
+ }
+
+ // get information about all event functions
+ for (UINT fd = 0; fd < (UINT)eventattr->cFuncs; ++fd) {
+ FUNCDESC *funcdesc;
+ eventinfo->GetFuncDesc(fd, &funcdesc);
+ if (!funcdesc)
+ break;
+ if (funcdesc->invkind != INVOKE_FUNC ||
+ funcdesc->funckind != FUNC_DISPATCH) {
+ eventinfo->ReleaseTypeAttr(eventattr);
+ eventinfo->ReleaseFuncDesc(funcdesc);
+ continue;
+ }
+
+ QByteArray function;
+ QByteArray prototype;
+ QList<QByteArray> parameters;
+
+ // parse event function description
+ BSTR bstrNames[256];
+ UINT maxNames = 255;
+ UINT maxNamesOut;
+ eventinfo->GetNames(funcdesc->memid, (BSTR*)&bstrNames, maxNames, &maxNamesOut);
+ QList<QByteArray> names;
+ int p;
+ for (p = 0; p < (int)maxNamesOut; ++p) {
+ names << QString::fromWCharArray(bstrNames[p]).toLatin1();
+ SysFreeString(bstrNames[p]);
+ }
+
+ // get event function prototype
+ function = names.at(0);
+ QByteArray type; // dummy - we don't care about return values for signals
+ prototype = createPrototype(/*in*/ funcdesc, eventinfo, names, /*out*/type, parameters);
+ if (!hasSignal(prototype)) {
+ QByteArray pnames;
+ for (p = 0; p < parameters.count(); ++p) {
+ pnames += parameters.at(p);
+ if (p < parameters.count() - 1)
+ pnames += ',';
+ }
+ addSignal(prototype, pnames);
+ }
+ if (eventSink)
+ eventSink->addSignal(funcdesc->memid, prototype);
+
+#if 0 // documentation in metaobject would be cool?
+ // get function documentation
+ BSTR bstrDocu;
+ eventinfo->GetDocumentation(funcdesc->memid, 0, &bstrDocu, 0, 0);
+ QString strDocu = QString::fromWCharArray(bstrDocu);
+ SysFreeString(bstrDocu);
+ if (!!strDocu)
+ desc += '[' + strDocu + ']';
+ desc += '\n';
+#endif
+ eventinfo->ReleaseFuncDesc(funcdesc);
+ }
+ eventinfo->ReleaseTypeAttr(eventattr);
+}
+
+void MetaObjectGenerator::readEventInfo()
+{
+ int event_serial = 0;
+ IConnectionPointContainer *cpoints = 0;
+ if (d && d->useEventSink)
+ d->ptr->QueryInterface(IID_IConnectionPointContainer, (void**)&cpoints);
+ if (cpoints) {
+ // Get connection point enumerator
+ IEnumConnectionPoints *epoints = 0;
+ cpoints->EnumConnectionPoints(&epoints);
+ if (epoints) {
+ ULONG c = 1;
+ IConnectionPoint *cpoint = 0;
+ epoints->Reset();
+ QList<QUuid> cpointlist;
+ do {
+ if (cpoint) cpoint->Release();
+ cpoint = 0;
+ HRESULT hr = epoints->Next(c, &cpoint, &c);
+ if (!c || hr != S_OK)
+ break;
+
+ IID conniid;
+ cpoint->GetConnectionInterface(&conniid);
+ // workaround for typelibrary bug of Word.Application
+ QUuid connuuid(conniid);
+ if (cpointlist.contains(connuuid))
+ break;
+
+#ifndef QAX_NO_CLASSINFO
+ if (d->useClassInfo) {
+ QString uuidstr = connuuid.toString().toUpper();
+ uuidstr = iidnames.value(QLatin1String("/Interface/") + uuidstr + QLatin1String("/Default"), uuidstr).toString();
+ addClassInfo("Event Interface " + QByteArray::number(++event_serial), uuidstr.toLatin1());
+ }
+#endif
+
+ // get information about type
+ if (conniid == IID_IPropertyNotifySink) {
+ // test whether property notify sink has been created already, and advise on it
+ QAxEventSink *eventSink = d->eventSink.value(iid_propNotifySink);
+ if (eventSink)
+ eventSink->advise(cpoint, conniid);
+ continue;
+ }
+
+ ITypeInfo *eventinfo = 0;
+ if (typelib)
+ typelib->GetTypeInfoOfGuid(conniid, &eventinfo);
+
+ if (eventinfo) {
+ // avoid recursion (see workaround above)
+ cpointlist.append(connuuid);
+
+ readEventInterface(eventinfo, cpoint);
+ eventinfo->Release();
+ }
+ } while (c);
+ if (cpoint) cpoint->Release();
+ epoints->Release();
+ } else if (classInfo) { // no enumeration - search source interfaces and ask for those
+ TYPEATTR *typeattr = 0;
+ classInfo->GetTypeAttr(&typeattr);
+ if (typeattr) {
+ for (int i = 0; i < typeattr->cImplTypes; ++i) {
+ int flags = 0;
+ classInfo->GetImplTypeFlags(i, &flags);
+ if (!(flags & IMPLTYPEFLAG_FSOURCE))
+ continue;
+ HREFTYPE reference;
+ if (S_OK != classInfo->GetRefTypeOfImplType(i, &reference))
+ continue;
+ ITypeInfo *eventInfo = 0;
+ classInfo->GetRefTypeInfo(reference, &eventInfo);
+ if (!eventInfo)
+ continue;
+ TYPEATTR *eventattr = 0;
+ eventInfo->GetTypeAttr(&eventattr);
+ if (eventattr) {
+ IConnectionPoint *cpoint = 0;
+ cpoints->FindConnectionPoint(eventattr->guid, &cpoint);
+ if (cpoint) {
+ if (eventattr->guid == IID_IPropertyNotifySink) {
+ // test whether property notify sink has been created already, and advise on it
+ QAxEventSink *eventSink = d->eventSink.value(iid_propNotifySink);
+ if (eventSink)
+ eventSink->advise(cpoint, eventattr->guid);
+ continue;
+ }
+
+ readEventInterface(eventInfo, cpoint);
+ cpoint->Release();
+ }
+ eventInfo->ReleaseTypeAttr(eventattr);
+ }
+ eventInfo->Release();
+ }
+ classInfo->ReleaseTypeAttr(typeattr);
+ }
+ }
+ cpoints->Release();
+ }
+}
+
+QMetaObject *MetaObjectGenerator::tryCache()
+{
+ if (!cacheKey.isEmpty()) {
+ d->metaobj = mo_cache.value(cacheKey);
+ if (d->metaobj) {
+ d->cachedMetaObject = true;
+
+ IConnectionPointContainer *cpoints = 0;
+ d->ptr->QueryInterface(IID_IConnectionPointContainer, (void**)&cpoints);
+ if (cpoints) {
+ QList<QUuid>::ConstIterator it = d->metaobj->connectionInterfaces.begin();
+ while (it != d->metaobj->connectionInterfaces.end()) {
+ QUuid iid = *it;
+ ++it;
+
+ IConnectionPoint *cpoint = 0;
+ cpoints->FindConnectionPoint(iid, &cpoint);
+ if (cpoint) {
+ QAxEventSink *sink = new QAxEventSink(that);
+ sink->advise(cpoint, iid);
+ d->eventSink.insert(iid, sink);
+ sink->sigs = d->metaobj->sigs.value(iid);
+ sink->props = d->metaobj->props.value(iid);
+ sink->propsigs = d->metaobj->propsigs.value(iid);
+ cpoint->Release();
+ }
+ }
+ cpoints->Release();
+ }
+
+ return d->metaobj;
+ }
+ }
+ return 0;
+}
+
+QMetaObject *MetaObjectGenerator::metaObject(const QMetaObject *parentObject, const QByteArray &className)
+{
+ if (that) {
+ readClassInfo();
+ if (typelib) {
+ BSTR bstr;
+ typelib->GetDocumentation(-1, &bstr, 0, 0, 0);
+ current_typelib = QString::fromWCharArray(bstr).toLatin1();
+ SysFreeString(bstr);
+ }
+ if (d->tryCache && tryCache())
+ return d->metaobj;
+ readEnumInfo();
+ readInterfaceInfo();
+ readEventInfo();
+ }
+
+ current_typelib = QByteArray();
+
+#ifndef QAX_NO_CLASSINFO
+ if (!debugInfo.isEmpty() && d->useClassInfo)
+ addClassInfo("debugInfo", debugInfo);
+#endif
+
+ QAxMetaObject *metaobj = new QAxMetaObject;
+
+ // revision + classname + table + zero terminator
+ uint int_data_size = 1+1+2+2+2+2+1;
+
+ int_data_size += classinfo_list.count() * 2;
+ int_data_size += signal_list.count() * 5;
+ int_data_size += slot_list.count() * 5;
+ int_data_size += property_list.count() * 3;
+ int_data_size += enum_list.count() * 4;
+ for (QMap<QByteArray, QList<QPair<QByteArray, int> > >::ConstIterator it = enum_list.begin();
+ it != enum_list.end(); ++it) {
+ int_data_size += (*it).count() * 2;
+ }
+
+ uint *int_data = new uint[int_data_size];
+ int_data[0] = 1; // revision number
+ int_data[1] = 0; // classname index
+ int_data[2] = classinfo_list.count(); // num_classinfo
+ int_data[3] = 10; // idx_classinfo
+ int_data[4] = signal_list.count() + slot_list.count(); // num_methods
+ int_data[5] = int_data[3] + int_data[2] * 2; // idx_signals
+ int_data[6] = property_list.count(); // num_properties
+ int_data[7] = int_data[5] + int_data[4] * 5; // idx_properties
+ int_data[8] = enum_list.count(); // num_enums
+ int_data[9] = int_data[7] + int_data[6] * 3; // idx_enums
+ int_data[int_data_size - 1] = 0; // eod;
+
+ char null('\0');
+ // data + zero-terminator
+ QByteArray stringdata = that ? QByteArray(that->className()) : className;
+ stringdata += null;
+ stringdata.reserve(8192);
+
+ uint offset = int_data[3]; //idx_classinfo
+
+ // each class info in form key\0value\0
+ for (QMap<QByteArray, QByteArray>::ConstIterator it = classinfo_list.begin(); it != classinfo_list.end(); ++it) {
+ QByteArray key(it.key());
+ QByteArray value(it.value());
+ int_data[offset++] = stringdata.length();
+ stringdata += key;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += value;
+ stringdata += null;
+ }
+ Q_ASSERT(offset == int_data[5]);
+
+ // each signal in form prototype\0parameters\0type\0tag\0
+ for (QMap<QByteArray, Method>::ConstIterator it = signal_list.begin(); it != signal_list.end(); ++it) {
+ QByteArray prototype(QMetaObject::normalizedSignature(it.key()));
+ QByteArray type(it.value().type);
+ QByteArray parameters(it.value().parameters);
+ if (!it.value().realPrototype.isEmpty())
+ metaobj->realPrototype.insert(prototype, it.value().realPrototype);
+ QByteArray tag;
+ int flags = it.value().flags;
+
+ int_data[offset++] = stringdata.length();
+ stringdata += prototype;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += parameters;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += type;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += tag;
+ stringdata += null;
+ int_data[offset++] = flags;
+ }
+
+ // each slot in form prototype\0parameters\0type\0tag\0
+ for (QMap<QByteArray, Method>::ConstIterator it = slot_list.begin(); it != slot_list.end(); ++it) {
+ QByteArray prototype(QMetaObject::normalizedSignature(it.key()));
+ QByteArray type(it.value().type);
+ QByteArray parameters(it.value().parameters);
+ if (!it.value().realPrototype.isEmpty())
+ metaobj->realPrototype.insert(prototype, it.value().realPrototype);
+ QByteArray tag;
+ int flags = it.value().flags;
+
+ int_data[offset++] = stringdata.length();
+ stringdata += prototype;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += parameters;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += type;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += tag;
+ stringdata += null;
+ int_data[offset++] = flags;
+ }
+ Q_ASSERT(offset == int_data[7]);
+
+ // each property in form name\0type\0
+ for (QMap<QByteArray, Property>::ConstIterator it = property_list.begin(); it != property_list.end(); ++it) {
+ QByteArray name(it.key());
+ QByteArray type(it.value().type);
+ QByteArray realType(it.value().realType);
+ if (!realType.isEmpty() && realType != type)
+ metaobj->realPrototype.insert(name, realType);
+ uint flags = it.value().typeId;
+
+ int_data[offset++] = stringdata.length();
+ stringdata += name;
+ stringdata += null;
+ int_data[offset++] = stringdata.length();
+ stringdata += type;
+ stringdata += null;
+ int_data[offset++] = flags;
+ }
+ Q_ASSERT(offset == int_data[9]);
+
+ int value_offset = offset + enum_list.count() * 4;
+ // each enum in form name\0
+ for (QMap<QByteArray, QList<QPair<QByteArray, int> > >::ConstIterator it = enum_list.begin(); it != enum_list.end(); ++it) {
+ QByteArray name(it.key());
+ int flags = 0x0; // 0x1 for flag?
+ int count = it.value().count();
+
+ int_data[offset++] = stringdata.length();
+ stringdata += name;
+ stringdata += null;
+ int_data[offset++] = flags;
+ int_data[offset++] = count;
+ int_data[offset++] = value_offset;
+ value_offset += count * 2;
+ }
+ Q_ASSERT(offset == int_data[9] + enum_list.count() * 4);
+
+ // each enum value in form key\0
+ for (QMap<QByteArray, QList<QPair<QByteArray, int> > >::ConstIterator it = enum_list.begin(); it != enum_list.end(); ++it) {
+ for (QList<QPair<QByteArray,int> >::ConstIterator it2 = it.value().begin(); it2 != it.value().end(); ++it2) {
+ QByteArray key((*it2).first);
+ int value = (*it2).second;
+ int_data[offset++] = stringdata.length();
+ stringdata += key;
+ stringdata += null;
+ int_data[offset++] = value;
+ }
+ }
+ Q_ASSERT(offset == int_data_size-1);
+
+ char *string_data = new char[stringdata.length()];
+ memset(string_data, 0, sizeof(string_data));
+ memcpy(string_data, stringdata, stringdata.length());
+
+ // put the metaobject together
+ metaobj->d.data = int_data;
+ metaobj->d.extradata = 0;
+ metaobj->d.stringdata = string_data;
+ metaobj->d.superdata = parentObject;
+
+ if (d)
+ d->metaobj = metaobj;
+
+ if (!cacheKey.isEmpty()) {
+ mo_cache.insert(cacheKey, d->metaobj);
+ d->cachedMetaObject = true;
+ for (QHash<QUuid, QAxEventSink*>::Iterator it = d->eventSink.begin(); it != d->eventSink.end(); ++it) {
+ QAxEventSink *sink = it.value();
+ if (sink) {
+ QUuid ciid = sink->connectionInterface();
+
+ d->metaobj->connectionInterfaces.append(ciid);
+ d->metaobj->sigs.insert(ciid, sink->signalMap());
+ d->metaobj->props.insert(ciid, sink->propertyMap());
+ d->metaobj->propsigs.insert(ciid, sink->propSignalMap());
+ }
+ }
+ }
+
+ return metaobj;
+}
+
+static const uint qt_meta_data_QAxBase[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 3, 10, // methods
+ 1, 25, // properties
+ 0, 0, // enums/sets
+
+ // signals: signature, parameters, type, tag, flags
+ 24, 9, 8, 8, 0x05,
+ 55, 50, 8, 8, 0x05,
+ 102, 80, 8, 8, 0x05,
+
+ // properties: name, type, flags
+ 149, 141, 0x0a095103,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_QAxBase[] = {
+ "QAxBase\0\0name,argc,argv\0signal(QString,int,void*)\0name\0"
+ "propertyChanged(QString)\0code,source,desc,help\0"
+ "exception(int,QString,QString,QString)\0QString\0control\0"
+};
+
+static QMetaObject qaxobject_staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_QAxBase,
+ qt_meta_data_QAxBase, 0 }
+};
+static QMetaObject qaxwidget_staticMetaObject = {
+ { &QWidget::staticMetaObject, qt_meta_stringdata_QAxBase,
+ qt_meta_data_QAxBase, 0 }
+};
+
+/*!
+ \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
+{
+ if (d->metaobj)
+ return d->metaobj;
+ const QMetaObject* parentObject = parentMetaObject();
+
+ if (!d->ptr && !d->initialized) {
+ ((QAxBase*)this)->initialize(&d->ptr);
+ d->initialized = true;
+ }
+
+#ifndef QT_NO_THREAD
+ // only one thread at a time can generate meta objects
+ QMutexLocker locker(&cache_mutex);
+#endif
+
+ // return the default meta object if not yet initialized
+ if (!d->ptr || !d->useMetaObject) {
+ if (qObject()->isWidgetType())
+ return &qaxwidget_staticMetaObject;
+ return &qaxobject_staticMetaObject;
+ }
+ MetaObjectGenerator generator((QAxBase*)this, d);
+ return generator.metaObject(parentObject);
+}
+
+/*!
+ \internal
+
+ Connects to all event interfaces of the object.
+
+ Called by the subclasses' connectNotify() reimplementations, so
+ at this point the connection as actually been created already.
+*/
+void QAxBase::connectNotify()
+{
+ if (d->eventSink.count()) // already listening
+ return;
+
+ IEnumConnectionPoints *epoints = 0;
+ if (d->ptr && d->useEventSink) {
+ IConnectionPointContainer *cpoints = 0;
+ d->ptr->QueryInterface(IID_IConnectionPointContainer, (void**)&cpoints);
+ if (!cpoints)
+ return;
+
+ cpoints->EnumConnectionPoints(&epoints);
+ cpoints->Release();
+ }
+
+ if (!epoints)
+ return;
+
+ UINT index;
+ IDispatch *disp = d->dispatch();
+ ITypeInfo *typeinfo = 0;
+ ITypeLib *typelib = 0;
+ if (disp)
+ disp->GetTypeInfo(0, LOCALE_USER_DEFAULT, &typeinfo);
+ if (typeinfo)
+ typeinfo->GetContainingTypeLib(&typelib, &index);
+
+ if (!typelib) {
+ epoints->Release();
+ return;
+ }
+
+ MetaObjectGenerator generator(this, d);
+ bool haveEnumInfo = false;
+
+ ULONG c = 1;
+ IConnectionPoint *cpoint = 0;
+ epoints->Reset();
+ do {
+ if (cpoint) cpoint->Release();
+ cpoint = 0;
+ epoints->Next(c, &cpoint, &c);
+ if (!c || !cpoint)
+ break;
+
+ IID conniid;
+ cpoint->GetConnectionInterface(&conniid);
+ // workaround for typelibrary bug of Word.Application
+ QString connuuid(QUuid(conniid).toString());
+ if (d->eventSink.contains(connuuid))
+ break;
+
+ // Get ITypeInfo for source-interface, and skip if not supporting IDispatch
+ ITypeInfo *eventinfo = 0;
+ typelib->GetTypeInfoOfGuid(conniid, &eventinfo);
+ if (eventinfo) {
+ TYPEATTR *eventAttr;
+ eventinfo->GetTypeAttr(&eventAttr);
+ if (!eventAttr) {
+ eventinfo->Release();
+ break;
+ }
+
+ TYPEKIND eventKind = eventAttr->typekind;
+ eventinfo->ReleaseTypeAttr(eventAttr);
+ if (eventKind != TKIND_DISPATCH) {
+ eventinfo->Release();
+ break;
+ }
+ }
+
+ // always into the cache to avoid recoursion
+ QAxEventSink *eventSink = eventinfo ? new QAxEventSink(this) : 0;
+ d->eventSink.insert(connuuid, eventSink);
+
+ if (!eventinfo)
+ continue;
+
+ // have to get type info to support signals with enum parameters
+ if (!haveEnumInfo) {
+ bool wasTryCache = d->tryCache;
+ d->tryCache = true;
+ generator.readClassInfo();
+ generator.readEnumInfo();
+ d->tryCache = wasTryCache;
+ haveEnumInfo = true;
+ }
+ generator.readEventInterface(eventinfo, cpoint);
+ eventSink->advise(cpoint, conniid);
+
+ eventinfo->Release();
+ } while (c);
+ if (cpoint) cpoint->Release();
+ epoints->Release();
+
+ typelib->Release();
+
+ // make sure we don't try again
+ if (!d->eventSink.count())
+ d->eventSink.insert(QString(), 0);
+}
+
+/*!
+ \fn QString QAxBase::generateDocumentation()
+
+ Returns a rich text string with documentation for the
+ wrapped COM object. Dump the string to an HTML-file,
+ or use it in e.g. a QTextBrowser widget.
+*/
+
+static bool checkHRESULT(HRESULT hres, EXCEPINFO *exc, QAxBase *that, const QString &name, uint argerr)
+{
+ switch(hres) {
+ case S_OK:
+ return true;
+ case DISP_E_BADPARAMCOUNT:
+ qWarning("QAxBase: Error calling IDispatch member %s: Bad parameter count", name.toLatin1().data());
+ return false;
+ case DISP_E_BADVARTYPE:
+ qWarning("QAxBase: Error calling IDispatch member %s: Bad variant type", name.toLatin1().data());
+ return false;
+ case DISP_E_EXCEPTION:
+ {
+ bool printWarning = true;
+ unsigned short code = -1;
+ QString source, desc, help;
+ const QMetaObject *mo = that->metaObject();
+ int exceptionSignal = mo->indexOfSignal("exception(int,QString,QString,QString)");
+ if (exceptionSignal >= 0) {
+ if (exc->pfnDeferredFillIn)
+ exc->pfnDeferredFillIn(exc);
+
+ code = exc->wCode ? exc->wCode : exc->scode;
+ source = QString::fromWCharArray(exc->bstrSource);
+ desc = QString::fromWCharArray(exc->bstrDescription);
+ help = QString::fromWCharArray(exc->bstrHelpFile);
+ uint helpContext = exc->dwHelpContext;
+
+ if (helpContext && !help.isEmpty())
+ help += QString::fromLatin1(" [%1]").arg(helpContext);
+
+ if (QAxEventSink::signalHasReceivers(that->qObject(), "exception(int,QString,QString,QString)")) {
+ void *argv[] = {0, &code, &source, &desc, &help};
+ that->qt_metacall(QMetaObject::InvokeMetaMethod, exceptionSignal, argv);
+ printWarning = false;
+ }
+ }
+ if (printWarning) {
+ qWarning("QAxBase: Error calling IDispatch member %s: Exception thrown by server", name.toLatin1().data());
+ qWarning(" Code : %d", code);
+ qWarning(" Source : %s", source.toLatin1().data());
+ qWarning(" Description: %s", desc.toLatin1().data());
+ qWarning(" Help : %s", help.toLatin1().data());
+ qWarning(" Connect to the exception(int,QString,QString,QString) signal to catch this exception");
+ }
+ }
+ return false;
+ case DISP_E_MEMBERNOTFOUND:
+ qWarning("QAxBase: Error calling IDispatch member %s: Member not found", name.toLatin1().data());
+ return false;
+ case DISP_E_NONAMEDARGS:
+ qWarning("QAxBase: Error calling IDispatch member %s: No named arguments", name.toLatin1().data());
+ return false;
+ case DISP_E_OVERFLOW:
+ qWarning("QAxBase: Error calling IDispatch member %s: Overflow", name.toLatin1().data());
+ return false;
+ case DISP_E_PARAMNOTFOUND:
+ qWarning("QAxBase: Error calling IDispatch member %s: Parameter %d not found", name.toLatin1().data(), argerr);
+ return false;
+ case DISP_E_TYPEMISMATCH:
+ qWarning("QAxBase: Error calling IDispatch member %s: Type mismatch in parameter %d", name.toLatin1().data(), argerr);
+ return false;
+ case DISP_E_UNKNOWNINTERFACE:
+ qWarning("QAxBase: Error calling IDispatch member %s: Unknown interface", name.toLatin1().data());
+ return false;
+ case DISP_E_UNKNOWNLCID:
+ qWarning("QAxBase: Error calling IDispatch member %s: Unknown locale ID", name.toLatin1().data());
+ return false;
+ case DISP_E_PARAMNOTOPTIONAL:
+ qWarning("QAxBase: Error calling IDispatch member %s: Non-optional parameter missing", name.toLatin1().data());
+ return false;
+ default:
+ qWarning("QAxBase: Error calling IDispatch member %s: Unknown error", name.toLatin1().data());
+ return false;
+ }
+}
+
+/*!
+ \internal
+*/
+int QAxBase::internalProperty(QMetaObject::Call call, int index, void **v)
+{
+ const QMetaObject *mo = metaObject();
+ const QMetaProperty prop = mo->property(index + mo->propertyOffset());
+ QByteArray propname = prop.name();
+
+ // hardcoded control property
+ if (propname == "control") {
+ switch(call) {
+ case QMetaObject::ReadProperty:
+ *(QString*)*v = control();
+ break;
+ case QMetaObject::WriteProperty:
+ setControl(*(QString*)*v);
+ break;
+ case QMetaObject::ResetProperty:
+ clear();
+ break;
+ default:
+ break;
+ }
+ return index - mo->propertyCount();
+ }
+
+ // get the IDispatch
+ if (!d->ptr || !prop.isValid())
+ return index;
+ IDispatch *disp = d->dispatch();
+ if (!disp)
+ return index;
+
+ DISPID dispid = d->metaObject()->dispIDofName(propname, disp);
+ if (dispid == DISPID_UNKNOWN)
+ return index;
+
+ Q_ASSERT(d->metaobj);
+ // property found, so everthing that goes wrong now should not bother the caller
+ index -= mo->propertyCount();
+
+ VARIANTARG arg;
+ VariantInit(&arg);
+ DISPPARAMS params;
+ EXCEPINFO excepinfo;
+ memset(&excepinfo, 0, sizeof(excepinfo));
+ UINT argerr = 0;
+ HRESULT hres = E_FAIL;
+
+ QByteArray proptype(prop.typeName());
+ switch (call) {
+ case QMetaObject::ReadProperty:
+ {
+ params.cArgs = 0;
+ params.cNamedArgs = 0;
+ params.rgdispidNamedArgs = 0;
+ params.rgvarg = 0;
+
+ hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params, &arg, &excepinfo, 0);
+
+ // map result VARIANTARG to void*
+ uint type = QVariant::Int;
+ if (!prop.isEnumType())
+ type = prop.type();
+ QVariantToVoidStar(VARIANTToQVariant(arg, proptype, type), *v, proptype, type);
+ if ((arg.vt != VT_DISPATCH && arg.vt != VT_UNKNOWN) || type == QVariant::Pixmap || type == QVariant::Font)
+ clearVARIANT(&arg);
+ }
+ break;
+
+ case QMetaObject::WriteProperty:
+ {
+ QVariant::Type t = (QVariant::Type)prop.type();
+
+ DISPID dispidNamed = DISPID_PROPERTYPUT;
+ params.cArgs = 1;
+ params.cNamedArgs = 1;
+ params.rgdispidNamedArgs = &dispidNamed;
+ params.rgvarg = &arg;
+
+ arg.vt = VT_ERROR;
+ arg.scode = DISP_E_TYPEMISMATCH;
+
+ // map void* to VARIANTARG via QVariant
+ QVariant qvar;
+ if (prop.isEnumType()) {
+ qvar = *(int*)v[0];
+ proptype = 0;
+ } else {
+ if (t == QVariant::LastType) {
+ qvar = *(QVariant*)v[0];
+ proptype = 0;
+ } else if (t == QVariant::UserType) {
+ qvar = QVariant(qRegisterMetaType<void*>(prop.typeName()), (void**)v[0]);
+// qvar.setValue(*(void**)v[0], prop.typeName());
+ } else {
+ proptype = d->metaObject()->propertyType(propname);
+ qvar = QVariant(t, v[0]);
+ }
+ }
+
+ QVariantToVARIANT(qvar, arg, proptype);
+ if (arg.vt == VT_EMPTY || arg.vt == VT_ERROR) {
+ qWarning("QAxBase::setProperty: Unhandled property type %s", prop.typeName());
+ break;
+ }
+ }
+ hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, 0, &excepinfo, &argerr);
+ clearVARIANT(&arg);
+ break;
+
+ default:
+ break;
+ }
+
+ checkHRESULT(hres, &excepinfo, this, QLatin1String(propname), argerr);
+ return index;
+}
+
+int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v)
+{
+ Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
+ Q_UNUSED(call);
+
+ // get the IDispatch
+ IDispatch *disp = d->dispatch();
+ if (!disp)
+ return index;
+
+ const QMetaObject *mo = metaObject();
+ // get the slot information
+ const QMetaMethod slot = mo->method(index + mo->methodOffset());
+ Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
+
+ QByteArray signature(slot.signature());
+ QByteArray slotname(signature);
+ slotname.truncate(slotname.indexOf('('));
+
+ // Get the Dispatch ID of the method to be called
+ bool isProperty = false;
+ DISPID dispid = d->metaObject()->dispIDofName(slotname, disp);
+
+ Q_ASSERT(d->metaobj);
+
+ if (dispid == DISPID_UNKNOWN && slotname.toLower().startsWith("set")) {
+ // see if we are calling a property set function as a slot
+ slotname = slotname.right(slotname.length() - 3);
+ dispid = d->metaobj->dispIDofName(slotname, disp);
+ isProperty = true;
+ }
+ if (dispid == DISPID_UNKNOWN)
+ return index;
+
+ // slot found, so everthing that goes wrong now should not bother the caller
+ index -= mo->methodCount();
+
+ // setup the parameters
+ DISPPARAMS params;
+ DISPID dispidNamed = DISPID_PROPERTYPUT;
+ params.cArgs = d->metaobj->numParameter(signature);
+ params.cNamedArgs = isProperty ? 1 : 0;
+ params.rgdispidNamedArgs = isProperty ? &dispidNamed : 0;
+ params.rgvarg = 0;
+ VARIANTARG static_rgvarg[QAX_NUM_PARAMS];
+ if (params.cArgs) {
+ if (params.cArgs <= QAX_NUM_PARAMS)
+ params.rgvarg = static_rgvarg;
+ else
+ params.rgvarg = new VARIANTARG[params.cArgs];
+ }
+
+ int p;
+ for (p = 0; p < (int)params.cArgs; ++p) {
+ bool out;
+ QByteArray type = d->metaobj->paramType(signature, p, &out);
+ QVariant::Type vt = QVariant::nameToType(type);
+ QVariant qvar;
+ if (vt != QVariant::UserType)
+ qvar = QVariant(vt, v[p + 1]);
+
+ if (!qvar.isValid()) {
+ if (type == "IDispatch*")
+ qvar.setValue(*(IDispatch**)v[p+1]);
+ else if (type == "IUnknown*")
+ qvar.setValue(*(IUnknown**)v[p+1]);
+ else if (type == "QVariant")
+ qvar = *(QVariant*)v[p + 1];
+ else if (mo->indexOfEnumerator(type) != -1)
+ qvar = *(int*)v[p + 1];
+ else
+ qvar = QVariant(QMetaType::type(type), v[p + 1]);
+ }
+
+ QVariantToVARIANT(qvar, params.rgvarg[params.cArgs - p - 1], type, out);
+ }
+
+ // call the method
+ VARIANT ret;
+ VariantInit(&ret);
+ UINT argerr = 0;
+ HRESULT hres = E_FAIL;
+ EXCEPINFO excepinfo;
+ 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);
+
+ // get return value
+ if (hres == S_OK && ret.vt != VT_EMPTY)
+ QVariantToVoidStar(VARIANTToQVariant(ret, slot.typeName()), v[0], slot.typeName());
+
+ // update out parameters
+ for (p = 0; p < (int)params.cArgs; ++p) {
+ bool out;
+ QByteArray ptype = d->metaobj->paramType(signature, p, &out);
+ if (out)
+ QVariantToVoidStar(VARIANTToQVariant(params.rgvarg[params.cArgs - p - 1], ptype), v[p+1], ptype);
+ }
+ // clean up
+ for (p = 0; p < (int)params.cArgs; ++p)
+ clearVARIANT(params.rgvarg+p);
+ if (params.rgvarg != static_rgvarg)
+ delete [] params.rgvarg;
+
+ checkHRESULT(hres, &excepinfo, this, QString::fromLatin1(slotname), params.cArgs-argerr-1);
+ return index;
+}
+
+/*!
+ \internal
+*/
+int QAxBase::qt_metacall(QMetaObject::Call call, int id, void **v)
+{
+ const QMetaObject *mo = metaObject();
+ if (isNull() && mo->property(id + mo->propertyOffset()).name() != QByteArray("control")) {
+ qWarning("QAxBase::qt_metacall: Object is not initialized, or initialization failed");
+ return id;
+ }
+
+ switch(call) {
+ case QMetaObject::InvokeMetaMethod:
+ switch (mo->method(id + mo->methodOffset()).methodType()) {
+ case QMetaMethod::Signal:
+ QMetaObject::activate(qObject(), mo, id, v);
+ id -= mo->methodCount();
+ break;
+ case QMetaMethod::Method:
+ case QMetaMethod::Slot:
+ id = internalInvoke(call, id, v);
+ break;
+ default:
+ break;
+ }
+ break;
+ case QMetaObject::ReadProperty:
+ case QMetaObject::WriteProperty:
+ case QMetaObject::ResetProperty:
+ id = internalProperty(call, id, v);
+ break;
+ case QMetaObject::QueryPropertyScriptable:
+ case QMetaObject::QueryPropertyDesignable:
+ case QMetaObject::QueryPropertyStored:
+ case QMetaObject::QueryPropertyEditable:
+ case QMetaObject::QueryPropertyUser:
+ id -= mo->propertyCount();
+ break;
+ default:
+ break;
+ }
+ Q_ASSERT(id < 0);
+ return id;
+}
+
+#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 char *coclass = metaObject->classInfo(metaObject->indexOfClassInfo("CoClass")).value();
+
+ if (disptype == DISPATCH_METHOD) {
+ qWarning("QAxBase::dynamicCallHelper: %s: No such method in %s [%s]", name.data(), that->control().toLatin1().data(), coclass ? coclass: "unknown");
+ qWarning("\tCandidates are:");
+ for (int i = 0; i < metaObject->methodCount(); ++i) {
+ const QMetaMethod slot(metaObject->method(i));
+ if (slot.methodType() != QMetaMethod::Slot)
+ continue;
+ QByteArray signature = slot.signature();
+ if (signature.toLower().startsWith(function.toLower()))
+ qWarning("\t\t%s", signature.data());
+ }
+ } else {
+ qWarning("QAxBase::dynamicCallHelper: %s: No such property in %s [%s]", name.data(), that->control().toLatin1().data(), coclass ? coclass: "unknown");
+ if (!function.isEmpty()) {
+ qWarning("\tCandidates are:");
+ char f0 = function.toLower().at(0);
+ for (int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i) {
+ QByteArray signature(metaObject->property(i).name());
+ if (!signature.isEmpty() && signature.toLower().at(0) == f0)
+ qWarning("\t\t%s", signature.data());
+ }
+ }
+ }
+}
+#endif
+
+/*!
+ \internal
+
+ \a name is already normalized?
+*/
+bool QAxBase::dynamicCallHelper(const char *name, void *inout, QList<QVariant> &vars, QByteArray &type)
+{
+ if (isNull()) {
+ qWarning("QAxBase::dynamicCallHelper: Object is not initialized, or initialization failed");
+ return false;
+ }
+
+ IDispatch *disp = d->dispatch();
+ if (!disp) {
+ qWarning("QAxBase::dynamicCallHelper: Object does not support automation");
+ return false;
+ }
+
+ const QMetaObject *mo = metaObject();
+ d->metaObject();
+ Q_ASSERT(d->metaobj);
+
+ int varc = vars.count();
+
+ QByteArray normFunction = QMetaObject::normalizedSignature(name);
+ QByteArray function(normFunction);
+ VARIANT staticarg[QAX_NUM_PARAMS];
+ VARIANT *arg = 0;
+ VARIANTARG *res = (VARIANTARG*)inout;
+
+ unsigned short disptype;
+
+ int id = -1;
+ bool parse = false;
+
+ if (function.contains('(')) {
+ disptype = DISPATCH_METHOD | DISPATCH_PROPERTYGET;
+ if (d->useMetaObject)
+ id = mo->indexOfSlot(function);
+ if (id >= 0) {
+ const QMetaMethod slot = mo->method(id);
+ Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
+ function = slot.signature();
+ type = slot.typeName();
+ }
+ function.truncate(function.indexOf('('));
+ parse = !varc && normFunction.length() > function.length() + 2;
+ if (parse) {
+ QString args = QLatin1String(normFunction);
+ args = args.mid(function.length() + 1);
+ // parse argument string int list of arguments
+ QString curArg;
+ const QChar *c = args.unicode();
+ int index = 0;
+ bool inString = false;
+ bool inEscape = false;
+ while (index < (int)args.length()) {
+ QChar cc = *c;
+ ++c;
+ ++index;
+ switch(cc.toLatin1()) {
+ case 'n':
+ if (inEscape)
+ cc = QLatin1Char('\n');
+ break;
+ case 'r':
+ if (inEscape)
+ cc = QLatin1Char('\r');
+ break;
+ case 't':
+ if (inEscape)
+ cc = QLatin1Char('\t');
+ break;
+ case '\\':
+ if (!inEscape && inString) {
+ inEscape = true;
+ continue;
+ }
+ break;
+ case '"':
+ if (!inEscape) {
+ inString = !inString;
+ curArg += cc;
+ continue;
+ }
+ break;
+ case ' ':
+ if (!inString && curArg.isEmpty())
+ continue;
+ break;
+ case ',':
+ case ')':
+ if (inString)
+ break;
+ curArg = curArg.trimmed();
+ if (curArg.at(0) == QLatin1Char('\"') && curArg.at(curArg.length()-1) == QLatin1Char('\"')) {
+ vars << curArg.mid(1, curArg.length() - 2);
+ } else {
+ bool isNumber = false;
+ bool isDouble = false;
+ int number = curArg.toInt(&isNumber);
+ double dbl = curArg.toDouble(&isDouble);
+ if (isNumber) {
+ vars << number;
+ } else if (isDouble) {
+ vars << dbl;
+ } else {
+ bool isEnum = false;
+ for (int enumIndex = 0; enumIndex < mo->enumeratorCount(); ++enumIndex) {
+ QMetaEnum metaEnum =mo->enumerator(enumIndex);
+ int value = metaEnum.keyToValue(curArg.toLatin1());
+ if (value != -1 && !QByteArray(metaEnum.valueToKey(value)).isEmpty()) {
+ vars << value;
+ isEnum = true;
+ break;
+ }
+ }
+ if (!isEnum)
+ vars << curArg;
+ }
+ }
+ curArg.clear();
+ continue;
+ default:
+ break;
+ }
+ inEscape = false;
+ curArg += cc;
+ }
+
+ varc = vars.count();
+ }
+ } else {
+ if (d->useMetaObject)
+ id = mo->indexOfProperty(normFunction);
+
+ if (id >= 0) {
+ const QMetaProperty prop =mo->property(id);
+ type = prop.typeName();
+ }
+ if (varc == 1) {
+ res = 0;
+ disptype = DISPATCH_PROPERTYPUT;
+ } else {
+ disptype = DISPATCH_PROPERTYGET;
+ }
+ }
+ if (varc) {
+ varc = qMin(varc, d->metaobj->numParameter(normFunction));
+ arg = varc <= QAX_NUM_PARAMS ? staticarg : new VARIANT[varc];
+ for (int i = 0; i < varc; ++i) {
+ QVariant var(vars.at(i));
+ VariantInit(arg + (varc - i - 1));
+ bool out = false;
+ QByteArray paramType;
+ if (disptype == DISPATCH_PROPERTYPUT)
+ paramType = type;
+ else if (parse || disptype == DISPATCH_PROPERTYGET)
+ paramType = 0;
+ else
+ paramType = d->metaobj->paramType(normFunction, i, &out);
+
+ if ((!parse && d->useMetaObject && var.type() == QVariant::String) || var.type() == QVariant::ByteArray) {
+ int enumIndex =mo->indexOfEnumerator(paramType);
+ if (enumIndex != -1) {
+ QMetaEnum metaEnum =mo->enumerator(enumIndex);
+ QVariantToVARIANT(metaEnum.keyToValue(var.toByteArray()), arg[varc - i - 1], "int", out);
+ }
+ }
+
+ if (arg[varc - i - 1].vt == VT_EMPTY)
+ QVariantToVARIANT(var, arg[varc - i - 1], paramType, out);
+ }
+ }
+
+ DISPID dispid = d->metaobj->dispIDofName(function, disp);
+ if (dispid == DISPID_UNKNOWN && function.toLower().startsWith("set")) {
+ function = function.mid(3);
+ dispid = d->metaobj->dispIDofName(function, disp);
+ disptype = DISPATCH_PROPERTYPUT;
+ }
+
+ if (dispid == DISPID_UNKNOWN) {
+#ifdef QT_CHECK_STATE
+ qax_noSuchFunction(disptype, normFunction, function, this);
+#endif
+ return false;
+ }
+
+ DISPPARAMS params;
+ DISPID dispidNamed = DISPID_PROPERTYPUT;
+
+ params.cArgs = varc;
+ params.cNamedArgs = (disptype == DISPATCH_PROPERTYPUT) ? 1 : 0;
+ params.rgdispidNamedArgs = (disptype == DISPATCH_PROPERTYPUT) ? &dispidNamed : 0;
+ params.rgvarg = arg;
+ EXCEPINFO excepinfo;
+ memset(&excepinfo, 0, sizeof(excepinfo));
+ UINT argerr = 0;
+
+ HRESULT hres = disp->Invoke(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)
+ if (arg[varc-i-1].vt & VT_BYREF) // update out-parameters
+ vars[i] = VARIANTToQVariant(arg[varc-i-1], vars.at(i).typeName());
+ }
+
+ // clean up
+ for (int i = 0; i < varc; ++i)
+ clearVARIANT(params.rgvarg+i);
+ if (arg && arg != staticarg)
+ delete[] arg;
+
+ return checkHRESULT(hres, &excepinfo, this, QLatin1String(function), varc-argerr-1);
+}
+
+
+/*!
+ Calls the COM object's method \a function, passing the
+ parameters \a var1, \a var1, \a var2, \a var3, \a var4, \a var5,
+ \a var6, \a var7 and \a var8, and returns the value returned by
+ the method, or an invalid QVariant if the method does not return
+ a value or when the function call failed.
+
+ If \a function is a method of the object the string must be provided
+ as the full prototype, for example as it would be written in a
+ QObject::connect() call.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 15
+
+ Alternatively a function can be called passing the parameters embedded
+ in the string, e.g. above function can also be invoked using
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 16
+
+ All parameters are passed as strings; it depends on the control whether
+ they are interpreted correctly, and is slower than using the prototype
+ with correctly typed parameters.
+
+ If \a function is a property the string has to be the name of the
+ property. The property setter is called when \a var1 is a valid QVariant,
+ otherwise the getter is called.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 17
+
+ Note that it is faster to get and set properties using
+ QObject::property() and QObject::setProperty().
+
+ dynamicCall() can also be used to call objects with a
+ \l{QAxBase::disableMetaObject()}{disabled metaobject} wrapper,
+ which can improve performance significantely, esp. when calling many
+ different objects of different types during an automation process.
+ ActiveQt will then however not validate parameters.
+
+ It is only possible to call functions through dynamicCall() that
+ have parameters or return values of datatypes supported by
+ QVariant. See the QAxBase class documentation for a list of
+ supported and unsupported datatypes. If you want to call functions
+ that have unsupported datatypes in the parameter list, use
+ queryInterface() to retrieve the appropriate COM interface, and
+ use the function directly.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 18
+
+ This is also more efficient.
+*/
+QVariant QAxBase::dynamicCall(const char *function,
+ const QVariant &var1,
+ const QVariant &var2,
+ const QVariant &var3,
+ const QVariant &var4,
+ const QVariant &var5,
+ const QVariant &var6,
+ const QVariant &var7,
+ const QVariant &var8)
+{
+ QList<QVariant> vars;
+ QVariant var = var1;
+ int argc = 1;
+ while(var.isValid()) {
+ vars << var;
+ switch(++argc) {
+ case 2: var = var2; break;
+ case 3: var = var3; break;
+ case 4: var = var4; break;
+ case 5: var = var5; break;
+ case 6: var = var6; break;
+ case 7: var = var7; break;
+ case 8: var = var8; break;
+ default:var = QVariant(); break;
+ }
+ }
+
+ return dynamicCall(function, vars);
+}
+
+/*!
+ \overload
+
+ Calls the COM object's method \a function, passing the
+ parameters in \a vars, and returns the value returned by
+ the method. If the method does not return a value or when
+ the function call failed this function returns an invalid
+ QVariant object.
+
+ The QVariant objects in \a vars are updated when the method has
+ out-parameters.
+*/
+QVariant QAxBase::dynamicCall(const char *function, QList<QVariant> &vars)
+{
+ VARIANTARG res;
+ VariantInit(&res);
+
+ QByteArray rettype;
+ if (!dynamicCallHelper(function, &res, vars, rettype))
+ return QVariant();
+
+ QVariant qvar = VARIANTToQVariant(res, rettype);
+ if ((res.vt != VT_DISPATCH && res.vt != VT_UNKNOWN) || qvar.type() == QVariant::Pixmap || qvar.type() == QVariant::Font)
+ clearVARIANT(&res);
+
+ return qvar;
+}
+
+/*!
+ Returns a pointer to a QAxObject wrapping the COM object provided
+ by the method or property \a name, passing passing the parameters
+ \a var1, \a var1, \a var2, \a var3, \a var4, \a var5, \a var6,
+ \a var7 and \a var8.
+
+ If \a name is provided by a method the string must include the
+ full function prototype.
+
+ If \a name is a property the string must be the name of the property,
+ and \a var1, ... \a var8 are ignored.
+
+ The returned QAxObject is a child of this object (which is either of
+ type QAxObject or QAxWidget), and is deleted when this object is
+ deleted. It is however safe to delete the returned object yourself,
+ and you should do so when you iterate over lists of subobjects.
+
+ COM enabled applications usually have an object model publishing
+ certain elements of the application as dispatch interfaces. Use
+ this method to navigate the hierarchy of the object model, e.g.
+
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxbase.cpp 19
+*/
+QAxObject *QAxBase::querySubObject(const char *name,
+ const QVariant &var1,
+ const QVariant &var2,
+ const QVariant &var3,
+ const QVariant &var4,
+ const QVariant &var5,
+ const QVariant &var6,
+ const QVariant &var7,
+ const QVariant &var8)
+{
+ QList<QVariant> vars;
+ QVariant var = var1;
+ int argc = 1;
+ while(var.isValid()) {
+ vars << var;
+ switch(++argc) {
+ case 2: var = var2; break;
+ case 3: var = var3; break;
+ case 4: var = var4; break;
+ case 5: var = var5; break;
+ case 6: var = var6; break;
+ case 7: var = var7; break;
+ case 8: var = var8; break;
+ default:var = QVariant(); break;
+ }
+ }
+
+ return querySubObject(name, vars);
+}
+
+/*!
+ \overload
+
+ The QVariant objects in \a vars are updated when the method has
+ out-parameters.
+*/
+QAxObject *QAxBase::querySubObject(const char *name, QList<QVariant> &vars)
+{
+ QAxObject *object = 0;
+ VARIANTARG res;
+ VariantInit(&res);
+
+ QByteArray rettype;
+ if (!dynamicCallHelper(name, &res, vars, rettype))
+ return 0;
+
+ switch (res.vt) {
+ case VT_DISPATCH:
+ if (res.pdispVal) {
+ if (rettype.isEmpty() || rettype == "IDispatch*" || rettype == "QVariant") {
+ object = new QAxObject(res.pdispVal, qObject());
+ } else if (QMetaType::type(rettype)) {
+ QVariant qvar = VARIANTToQVariant(res, rettype, 0);
+ object = *(QAxObject**)qvar.constData();
+// qVariantGet(qvar, object, rettype);
+ res.pdispVal->AddRef();
+ }
+ if (object)
+ ((QAxBase*)object)->d->tryCache = true;
+ }
+ break;
+ case VT_UNKNOWN:
+ if (res.punkVal) {
+ if (rettype.isEmpty() || rettype == "IUnknown*") {
+ object = new QAxObject(res.punkVal, qObject());
+ } else if (QMetaType::type(rettype)) {
+ QVariant qvar = VARIANTToQVariant(res, rettype, 0);
+ object = *(QAxObject**)qvar.constData();
+// qVariantGet(qvar, object, rettype);
+ res.punkVal->AddRef();
+ }
+ if (object)
+ ((QAxBase*)object)->d->tryCache = true;
+ }
+ break;
+ case VT_EMPTY:
+#ifdef QT_CHECK_STATE
+ {
+ const char *coclass = metaObject()->classInfo(metaObject()->indexOfClassInfo("CoClass")).value();
+ qWarning("QAxBase::querySubObject: %s: Error calling function or property in %s (%s)"
+ , name, control().toLatin1().data(), coclass ? coclass: "unknown");
+ }
+#endif
+ break;
+ default:
+#ifdef QT_CHECK_STATE
+ {
+ const char *coclass = metaObject()->classInfo(metaObject()->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");
+ }
+#endif
+ break;
+ }
+
+ clearVARIANT(&res);
+ return object;
+}
+
+class QtPropertyBag : public IPropertyBag
+{
+public:
+ QtPropertyBag() :ref(0) {}
+ virtual ~QtPropertyBag() {}
+
+ HRESULT __stdcall QueryInterface(REFIID iid, LPVOID *iface)
+ {
+ *iface = 0;
+ if (iid == IID_IUnknown)
+ *iface = this;
+ else if (iid == IID_IPropertyBag)
+ *iface = this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+ }
+ unsigned long __stdcall AddRef() { return ++ref; }
+ unsigned long __stdcall Release()
+ {
+ if (!--ref) {
+ delete this;
+ return 0;
+ }
+ return ref;
+ }
+
+ HRESULT __stdcall Read(LPCOLESTR name, VARIANT *var, IErrorLog *)
+ {
+ if (!var)
+ return E_POINTER;
+
+ QString property = QString::fromWCharArray(name);
+ QVariant qvar = map.value(property);
+ QVariantToVARIANT(qvar, *var);
+ return S_OK;
+ }
+ HRESULT __stdcall Write(LPCOLESTR name, VARIANT *var)
+ {
+ if (!var)
+ return E_POINTER;
+ QString property = QString::fromWCharArray(name);
+ QVariant qvar = VARIANTToQVariant(*var, 0);
+ map[property] = qvar;
+
+ return S_OK;
+ }
+
+ QAxBase::PropertyBag map;
+
+private:
+ unsigned long ref;
+};
+
+/*!
+ Returns a name:value map of all the properties exposed by the COM
+ object.
+
+ This is more efficient than getting multiple properties
+ individually if the COM object supports property bags.
+
+ \warning It is not guaranteed that the property bag implementation
+ of the COM object returns all properties, or that the properties
+ returned are the same as those available through the IDispatch
+ interface.
+*/
+QAxBase::PropertyBag QAxBase::propertyBag() const
+{
+ PropertyBag result;
+
+ if (!d->ptr && !d->initialized) {
+ ((QAxBase*)this)->initialize(&d->ptr);
+ d->initialized = true;
+ }
+
+ if (isNull())
+ return result;
+ IPersistPropertyBag *persist = 0;
+ d->ptr->QueryInterface(IID_IPersistPropertyBag, (void**)&persist);
+ if (persist) {
+ QtPropertyBag *pbag = new QtPropertyBag();
+ pbag->AddRef();
+ persist->Save(pbag, false, true);
+ result = pbag->map;
+ pbag->Release();
+ persist->Release();
+ return result;
+ } else {
+ const QMetaObject *mo = metaObject();
+ for (int p = mo->propertyOffset(); p < mo->propertyCount(); ++p) {
+ const QMetaProperty property = mo->property(p);
+ QVariant var = qObject()->property(property.name());
+ result.insert(QLatin1String(property.name()), var);
+ }
+ }
+ return result;
+}
+
+/*!
+ Sets the properties of the COM object to the corresponding values
+ in \a bag.
+
+ \warning
+ You should only set property bags that have been returned by the
+ propertyBag function, as it cannot be guaranteed that the property
+ bag implementation of the COM object supports the same properties
+ that are available through the IDispatch interface.
+
+ \sa propertyBag()
+*/
+void QAxBase::setPropertyBag(const PropertyBag &bag)
+{
+ if (!d->ptr && !d->initialized) {
+ initialize(&d->ptr);
+ d->initialized = true;
+ }
+
+ if (isNull())
+ return;
+ IPersistPropertyBag *persist = 0;
+ d->ptr->QueryInterface(IID_IPersistPropertyBag, (void**)&persist);
+ if (persist) {
+ QtPropertyBag *pbag = new QtPropertyBag();
+ pbag->map = bag;
+ pbag->AddRef();
+ persist->Load(pbag, 0);
+ pbag->Release();
+ persist->Release();
+ } else {
+ const QMetaObject *mo = metaObject();
+ for (int p = mo->propertyOffset(); p < mo->propertyCount(); ++p) {
+ const QMetaProperty property = mo->property(p);
+ QVariant var = bag.value(QLatin1String(property.name()));
+ qObject()->setProperty(property.name(), var);
+ }
+ }
+}
+
+/*!
+ Returns true if the property \a prop is writable; otherwise
+ returns false. By default, all properties are writable.
+
+ \warning
+ Depending on the control implementation this setting might be
+ ignored for some properties.
+
+ \sa setPropertyWritable(), propertyChanged()
+*/
+bool QAxBase::propertyWritable(const char *prop) const
+{
+ return d->propWritable.value(prop, true);
+}
+
+/*!
+ Sets the property \a prop to writable if \a ok is true, otherwise
+ sets \a prop to be read-only. By default, all properties are
+ writable.
+
+ \warning
+ Depending on the control implementation this setting might be
+ ignored for some properties.
+
+ \sa propertyWritable(), propertyChanged()
+*/
+void QAxBase::setPropertyWritable(const char *prop, bool ok)
+{
+ d->propWritable[prop] = ok;
+}
+
+/*!
+ Returns true if there is no COM object loaded by this wrapper;
+ otherwise return false.
+
+ \sa control
+*/
+bool QAxBase::isNull() const
+{
+ return !d->ptr;
+}
+
+/*!
+ Returns a QVariant that wraps the COM object. The variant can
+ then be used as a parameter in e.g. dynamicCall().
+*/
+QVariant QAxBase::asVariant() const
+{
+ if (!d->ptr && !d->initialized) {
+ ((QAxBase*)this)->initialize(&d->ptr);
+ d->initialized = true;
+ }
+
+ QVariant qvar;
+ QByteArray cn(className());
+ if (cn == "QAxObject" || cn == "QAxWidget" || cn == "QAxBase") {
+ if (d->dispatch())
+ qvar.setValue(d->dispatch());
+ else if (d->ptr)
+ qvar.setValue(d->ptr);
+ } else {
+ cn = cn.mid(cn.lastIndexOf(':') + 1);
+ QObject *object = qObject();
+ if (QMetaType::type(cn))
+ qvar = QVariant(qRegisterMetaType<QObject*>(cn + '*'), &object);
+// qvar.setValue(qObject(), cn + '*');
+ }
+
+ return qvar;
+}
+
+// internal function that creates a QAxObject from an iface
+// used by type-conversion code (types.cpp)
+void *qax_createObjectWrapper(int metaType, IUnknown *iface)
+{
+ if (!iface)
+ return 0;
+
+ QAxObject *object = (QAxObject*)QMetaType::construct(metaType, 0);
+ QAxBasePrivate *d = object->d;
+
+ d->ptr = iface;
+ d->initialized = true;
+
+ // no release, since no addref
+
+ return object;
+}
+
+/*!
+ \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 doc/src/snippets/code/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
+*/
+
+/*!
+ \fn const char *QAxBase::className() const
+ \internal
+*/
+
+QT_END_NAMESPACE
+#endif //QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/container/qaxbase.h b/src/activeqt/container/qaxbase.h
new file mode 100644
index 0000000..ab1bc7f
--- /dev/null
+++ b/src/activeqt/container/qaxbase.h
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXBASE_H
+#define QAXBASE_H
+
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+
+struct IUnknown;
+struct IDispatch;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+struct QUuid;
+class QAxEventSink;
+class QAxObject;
+class QAxBasePrivate;
+struct QAxMetaObject;
+
+class QAxBase
+{
+ QDOC_PROPERTY(QString control READ control WRITE setControl)
+
+public:
+ typedef QMap<QString, QVariant> PropertyBag;
+
+ QAxBase(IUnknown *iface = 0);
+ virtual ~QAxBase();
+
+ QString control() const;
+
+ long queryInterface(const QUuid &, void**) const;
+
+ QVariant dynamicCall(const char *name, const QVariant &v1 = QVariant(),
+ const QVariant &v2 = QVariant(),
+ const QVariant &v3 = QVariant(),
+ const QVariant &v4 = QVariant(),
+ const QVariant &v5 = QVariant(),
+ const QVariant &v6 = QVariant(),
+ const QVariant &v7 = QVariant(),
+ const QVariant &v8 = QVariant());
+ QVariant dynamicCall(const char *name, QList<QVariant> &vars);
+ QAxObject *querySubObject(const char *name, const QVariant &v1 = QVariant(),
+ const QVariant &v2 = QVariant(),
+ const QVariant &v3 = QVariant(),
+ const QVariant &v4 = QVariant(),
+ const QVariant &v5 = QVariant(),
+ const QVariant &v6 = QVariant(),
+ const QVariant &v7 = QVariant(),
+ 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 **);
+
+ virtual QObject *qObject() const = 0;
+ virtual const char *className() const = 0;
+
+ PropertyBag propertyBag() const;
+ void setPropertyBag(const PropertyBag&);
+
+ QString generateDocumentation();
+
+ virtual bool propertyWritable(const char*) const;
+ virtual void setPropertyWritable(const char*, bool);
+
+ bool isNull() const;
+
+ QStringList verbs() const;
+
+ QVariant asVariant() const;
+
+#ifdef 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();
+ bool setControl(const QString&);
+
+ void disableMetaObject();
+ void disableClassInfo();
+ void disableEventSink();
+
+protected:
+ virtual bool initialize(IUnknown** ptr);
+ bool initializeRemote(IUnknown** ptr);
+ bool initializeLicensed(IUnknown** ptr);
+ bool initializeActive(IUnknown** ptr);
+ bool initializeFromFile(IUnknown** ptr);
+
+ void internalRelease();
+ void initializeFrom(QAxBase *that);
+ void connectNotify();
+ long indexOfVerb(const QString &verb) const;
+
+private:
+ friend class QAxEventSink;
+ friend void *qax_createObjectWrapper(int, IUnknown*);
+ bool initializeLicensedHelper(void *factory, const QString &key, IUnknown **ptr);
+ QAxBasePrivate *d;
+ QAxMetaObject *internalMetaObject() const;
+
+ virtual const QMetaObject *parentMetaObject() const = 0;
+ int internalProperty(QMetaObject::Call, int index, void **v);
+ int internalInvoke(QMetaObject::Call, int index, void **v);
+ bool dynamicCallHelper(const char *name, void *out, QList<QVariant> &var, QByteArray &type);
+
+ static QMetaObject staticMetaObject;
+};
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QAxBase *qobject_cast_helper<QAxBase*>(const QObject *o, QAxBase *)
+#else
+template <> inline QAxBase *qobject_cast<QAxBase*>(const QObject *o)
+#endif
+{
+ void *result = o ? const_cast<QObject *>(o)->qt_metacast("QAxBase") : 0;
+ return (QAxBase*)(result);
+}
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QAxBase *qobject_cast_helper<QAxBase*>(QObject *o, QAxBase *)
+#else
+template <> inline QAxBase *qobject_cast<QAxBase*>(QObject *o)
+#endif
+{
+ void *result = o ? o->qt_metacast("QAxBase") : 0;
+ return (QAxBase*)(result);
+}
+
+extern QString qax_generateDocumentation(QAxBase *);
+
+inline QString QAxBase::generateDocumentation()
+{
+ return qax_generateDocumentation(this);
+}
+
+#ifndef QT_NO_DATASTREAM
+inline QDataStream &operator >>(QDataStream &s, QAxBase &c)
+{
+ QAxBase::PropertyBag bag;
+ c.qObject()->blockSignals(true);
+ QString control;
+ s >> control;
+ c.setControl(control);
+ s >> bag;
+ c.setPropertyBag(bag);
+ c.qObject()->blockSignals(false);
+
+ return s;
+}
+
+inline QDataStream &operator <<(QDataStream &s, const QAxBase &c)
+{
+ QAxBase::PropertyBag bag = c.propertyBag();
+ s << c.control();
+ s << bag;
+
+ return s;
+}
+#endif // QT_NO_DATASTREAM
+
+QT_END_NAMESPACE
+
+#ifndef Q_COM_METATYPE_DECLARED
+#define Q_COM_METATYPE_DECLARED
+
+Q_DECLARE_METATYPE(IUnknown*)
+Q_DECLARE_METATYPE(IDispatch*)
+
+#endif
+
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXBASE_H
diff --git a/src/activeqt/container/qaxdump.cpp b/src/activeqt/container/qaxdump.cpp
new file mode 100644
index 0000000..e6de9de
--- /dev/null
+++ b/src/activeqt/container/qaxdump.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxbase.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qmetaobject.h>
+#include <quuid.h>
+#include <qt_windows.h>
+#include <qtextstream.h>
+
+#include <ctype.h>
+
+#include "../shared/qaxtypes.h"
+
+QT_BEGIN_NAMESPACE
+
+QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name)
+{
+ QString docu;
+ if (!typeInfo)
+ return docu;
+
+ MEMBERID memId;
+ BSTR names = QStringToBSTR(name);
+ typeInfo->GetIDsOfNames((BSTR*)&names, 1, &memId);
+ SysFreeString(names);
+ if (memId != DISPID_UNKNOWN) {
+ BSTR docStringBstr, helpFileBstr;
+ ulong helpContext;
+ HRESULT hres = typeInfo->GetDocumentation(memId, 0, &docStringBstr, &helpContext, &helpFileBstr);
+ QString docString = QString::fromWCharArray(docStringBstr);
+ QString helpFile = QString::fromWCharArray(helpFileBstr);
+ SysFreeString(docStringBstr);
+ SysFreeString(helpFileBstr);
+ if (hres == S_OK) {
+ if (!docString.isEmpty())
+ docu += docString + QLatin1String("\n");
+ if (!helpFile.isEmpty())
+ docu += QString::fromLatin1("For more information, see help context %1 in %2.").arg((uint)helpContext).arg(helpFile);
+ }
+ }
+
+ return docu;
+}
+
+static inline QString docuFromName(ITypeInfo *typeInfo, const QString &name)
+{
+ return QLatin1String("<p>") + qax_docuFromName(typeInfo, name) + QLatin1String("\n");
+}
+
+static QByteArray namedPrototype(const QList<QByteArray> &parameterTypes, const QList<QByteArray> &parameterNames, int numDefArgs = 0)
+{
+ QByteArray prototype("(");
+ for (int p = 0; p < parameterTypes.count(); ++p) {
+ QByteArray type(parameterTypes.at(p));
+ prototype += type;
+
+ if (p < parameterNames.count())
+ prototype += ' ' + parameterNames.at(p);
+
+ if (numDefArgs >= parameterTypes.count() - p)
+ prototype += " = 0";
+ if (p < parameterTypes.count() - 1)
+ prototype += ", ";
+ }
+ prototype += ')';
+
+ return prototype;
+}
+
+static QByteArray toType(const QByteArray &t)
+{
+ QByteArray type = t;
+ int vartype = QVariant::nameToType(type);
+ if (vartype == QVariant::Invalid)
+ type = "int";
+
+ if (type.at(0) == 'Q')
+ type = type.mid(1);
+ type[0] = toupper(type.at(0));
+ if (type == "VariantList")
+ type = "List";
+ else if (type == "Map<QVariant,QVariant>")
+ type = "Map";
+ else if (type == "Uint")
+ type = "UInt";
+
+ return "to" + type + "()";
+}
+
+QString qax_generateDocumentation(QAxBase *that)
+{
+ that->metaObject();
+
+ if (that->isNull())
+ return QString();
+
+ ITypeInfo *typeInfo = 0;
+ IDispatch *dispatch = 0;
+ that->queryInterface(IID_IDispatch, (void**)&dispatch);
+ if (dispatch)
+ dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);
+
+ QString docu;
+ QTextStream stream(&docu, QIODevice::WriteOnly);
+
+ const QMetaObject *mo = that->metaObject();
+ QString coClass = QLatin1String(mo->classInfo(mo->indexOfClassInfo("CoClass")).value());
+
+ stream << "<h1 align=center>" << coClass << " Reference</h1>" << endl;
+ stream << "<p>The " << coClass << " COM object is a " << that->qObject()->metaObject()->className();
+ stream << " with the CLSID " << that->control() << ".</p>" << endl;
+
+ stream << "<h3>Interfaces</h3>" << endl;
+ stream << "<ul>" << endl;
+ const char *inter = 0;
+ int interCount = 1;
+ while ((inter = mo->classInfo(mo->indexOfClassInfo("Interface " + QByteArray::number(interCount))).value())) {
+ stream << "<li>" << inter << endl;
+ interCount++;
+ }
+ stream << "</ul>" << endl;
+
+ stream << "<h3>Event Interfaces</h3>" << endl;
+ stream << "<ul>" << endl;
+ interCount = 1;
+ while ((inter = mo->classInfo(mo->indexOfClassInfo("Event Interface " + QByteArray::number(interCount))).value())) {
+ stream << "<li>" << inter << endl;
+ interCount++;
+ }
+ stream << "</ul>" << endl;
+
+ QList<QString> methodDetails, propDetails;
+
+ const int slotCount = mo->methodCount();
+ if (slotCount) {
+ stream << "<h2>Public Slots:</h2>" << endl;
+ stream << "<ul>" << endl;
+
+ int defArgCount = 0;
+ for (int islot = mo->methodOffset(); islot < slotCount; ++islot) {
+ const QMetaMethod slot = mo->method(islot);
+ if (slot.methodType() != QMetaMethod::Slot)
+ continue;
+
+ if (slot.attributes() & QMetaMethod::Cloned) {
+ ++defArgCount;
+ continue;
+ }
+
+ QByteArray returntype(slot.typeName());
+ if (returntype.isEmpty())
+ returntype = "void";
+ QByteArray prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames(), defArgCount);
+ QByteArray signature = slot.signature();
+ QByteArray name = signature.left(signature.indexOf('('));
+ stream << "<li>" << returntype << " <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl;
+
+ prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames());
+ QString detail = QString::fromLatin1("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
+ QLatin1String(returntype.constData()) + QLatin1Char(' ') +
+ QLatin1String(name.constData()) + QLatin1Char(' ') +
+ QString::fromLatin1(prototype.constData()) + QLatin1String("<tt> [slot]</tt></h3>\n");
+ prototype = namedPrototype(slot.parameterTypes(), QList<QByteArray>());
+ detail += docuFromName(typeInfo, QString::fromLatin1(name.constData()));
+ detail += QLatin1String("<p>Connect a signal to this slot:<pre>\n");
+ detail += QString::fromLatin1("\tQObject::connect(sender, SIGNAL(someSignal") + QString::fromLatin1(prototype.constData()) +
+ QLatin1String("), object, SLOT(") + QString::fromLatin1(name.constData()) +
+ QString::fromLatin1(prototype.constData()) + QLatin1String("));");
+ detail += QLatin1String("</pre>\n");
+
+ if (1) {
+ detail += QLatin1String("<p>Or call the function directly:<pre>\n");
+
+ bool hasParams = slot.parameterTypes().count() != 0;
+ if (hasParams)
+ detail += QLatin1String("\tQVariantList params = ...\n");
+ detail += QLatin1String("\t");
+ QByteArray functionToCall = "dynamicCall";
+ if (returntype == "IDispatch*" || returntype == "IUnknown*") {
+ functionToCall = "querySubObject";
+ returntype = "QAxObject *";
+ }
+ if (returntype != "void")
+ detail += QLatin1String(returntype.constData()) + QLatin1String(" result = ");
+ detail += QLatin1String("object->") + QLatin1String(functionToCall.constData()) +
+ QLatin1String("(\"" + name + prototype + '\"');
+ if (hasParams)
+ detail += QLatin1String(", params");
+ detail += QLatin1Char(')');
+ if (returntype != "void" && returntype != "QAxObject *" && returntype != "QVariant")
+ detail += QLatin1Char('.') + QLatin1String(toType(returntype));
+ detail += QLatin1String(";</pre>\n");
+ } else {
+ detail += QLatin1String("<p>This function has parameters of unsupported types and cannot be called directly.");
+ }
+
+ methodDetails << detail;
+ defArgCount = 0;
+ }
+
+ stream << "</ul>" << endl;
+ }
+ int signalCount = mo->methodCount();
+ if (signalCount) {
+ ITypeLib *typeLib = 0;
+ if (typeInfo) {
+ UINT index = 0;
+ typeInfo->GetContainingTypeLib(&typeLib, &index);
+ typeInfo->Release();
+ }
+ typeInfo = 0;
+
+ stream << "<h2>Signals:</h2>" << endl;
+ stream << "<ul>" << endl;
+
+ for (int isignal = mo->methodOffset(); isignal < signalCount; ++isignal) {
+ const QMetaMethod signal(mo->method(isignal));
+ if (signal.methodType() != QMetaMethod::Signal)
+ continue;
+
+ QByteArray prototype = namedPrototype(signal.parameterTypes(), signal.parameterNames());
+ QByteArray signature = signal.signature();
+ QByteArray name = signature.left(signature.indexOf('('));
+ stream << "<li>void <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl;
+
+ QString detail = QLatin1String("<h3><a name=") + QLatin1String(name.constData()) + QLatin1String("></a>void ") +
+ QLatin1String(name.constData()) + QLatin1Char(' ') +
+ QLatin1String(prototype.constData()) + QLatin1String("<tt> [signal]</tt></h3>\n");
+ if (typeLib) {
+ interCount = 0;
+ do {
+ if (typeInfo)
+ typeInfo->Release();
+ typeInfo = 0;
+ typeLib->GetTypeInfo(++interCount, &typeInfo);
+ QString typeLibDocu = docuFromName(typeInfo, QString::fromLatin1(name.constData()));
+ if (!typeLibDocu.isEmpty()) {
+ detail += typeLibDocu;
+ break;
+ }
+ } while (typeInfo);
+ }
+ prototype = namedPrototype(signal.parameterTypes(), QList<QByteArray>());
+ detail += QLatin1String("<p>Connect a slot to this signal:<pre>\n");
+ detail += QLatin1String("\tQObject::connect(object, SIGNAL(") + QString::fromLatin1(name.constData()) +
+ QString::fromLatin1(prototype.constData()) +
+ QLatin1String("), receiver, SLOT(someSlot") + QString::fromLatin1(prototype.constData()) + QLatin1String("));");
+ detail += QLatin1String("</pre>\n");
+
+ methodDetails << detail;
+ if (typeInfo)
+ typeInfo->Release();
+ typeInfo = 0;
+ }
+ stream << "</ul>" << endl;
+
+ if (typeLib)
+ typeLib->Release();
+ }
+
+ const int propCount = mo->propertyCount();
+ if (propCount) {
+ if (dispatch)
+ dispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &typeInfo);
+ stream << "<h2>Properties:</h2>" << endl;
+ stream << "<ul>" << endl;
+
+ for (int iprop = 0; iprop < propCount; ++iprop) {
+ const QMetaProperty prop = mo->property(iprop);
+ QByteArray name(prop.name());
+ QByteArray type(prop.typeName());
+
+ stream << "<li>" << type << " <a href=\"#" << name << "\"><b>" << name << "</b></a>;</li>" << endl;
+ QString detail = QLatin1String("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
+ QLatin1String(type.constData()) +
+ QLatin1Char(' ') + QLatin1String(name.constData()) + QLatin1String("</h3>\n");
+ detail += docuFromName(typeInfo, QString::fromLatin1(name));
+ QVariant::Type vartype = QVariant::nameToType(type);
+ if (!prop.isReadable())
+ continue;
+
+ if (prop.isEnumType())
+ vartype = QVariant::Int;
+
+ if (vartype != QVariant::Invalid) {
+ detail += QLatin1String("<p>Read this property's value using QObject::property:<pre>\n");
+ if (prop.isEnumType())
+ detail += QLatin1String("\tint val = ");
+ else
+ detail += QLatin1Char('\t') + QLatin1String(type.constData()) + QLatin1String(" val = ");
+ detail += QLatin1String("object->property(\"") + QLatin1String(name.constData()) +
+ QLatin1String("\").") + QLatin1String(toType(type).constData()) + QLatin1String(";\n");
+ detail += QLatin1String("</pre>\n");
+ } else if (type == "IDispatch*" || type == "IUnknown*") {
+ detail += QLatin1String("<p>Get the subobject using querySubObject:<pre>\n");
+ detail += QLatin1String("\tQAxObject *") + QLatin1String(name.constData()) +
+ QLatin1String(" = object->querySubObject(\"") + QLatin1String(name.constData()) + QLatin1String("\");\n");
+ detail += QLatin1String("</pre>\n");
+ } else {
+ detail += QLatin1String("<p>This property is of an unsupported type.\n");
+ }
+ if (prop.isWritable()) {
+ detail += QLatin1String("Set this property' value using QObject::setProperty:<pre>\n");
+ if (prop.isEnumType()) {
+ detail += QLatin1String("\tint newValue = ... // string representation of values also supported\n");
+ } else {
+ detail += QLatin1String("\t") + QString::fromLatin1(type.constData()) + QLatin1String(" newValue = ...\n");
+ }
+ detail += QLatin1String("\tobject->setProperty(\"") + QString::fromLatin1(name) + QLatin1String("\", newValue);\n");
+ detail += QLatin1String("</pre>\n");
+ detail += QLatin1String("Or using the ");
+ QByteArray setterSlot;
+ if (isupper(name.at(0))) {
+ setterSlot = "Set" + name;
+ } else {
+ QByteArray nameUp = name;
+ nameUp[0] = toupper(nameUp.at(0));
+ setterSlot = "set" + nameUp;
+ }
+ detail += QLatin1String("<a href=\"#") + QString::fromLatin1(setterSlot) + QLatin1String("\">") +
+ QString::fromLatin1(setterSlot.constData()) + QLatin1String("</a> slot.\n");
+ }
+ if (prop.isEnumType()) {
+ detail += QLatin1String("<p>See also <a href=\"#") + QString::fromLatin1(type) +
+ QLatin1String("\">") + QString::fromLatin1(type) + QLatin1String("</a>.\n");
+ }
+
+ propDetails << detail;
+ }
+ stream << "</ul>" << endl;
+ }
+
+ const int enumCount = mo->enumeratorCount();
+ if (enumCount) {
+ stream << "<hr><h2>Member Type Documentation</h2>" << endl;
+ for (int i = 0; i < enumCount; ++i) {
+ const QMetaEnum enumdata = mo->enumerator(i);
+ stream << "<h3><a name=" << enumdata.name() << "></a>" << enumdata.name() << "</h3>" << endl;
+ stream << "<ul>" << endl;
+ for (int e = 0; e < enumdata.keyCount(); ++e) {
+ stream << "<li>" << enumdata.key(e) << "\t=" << enumdata.value(e) << "</li>" << endl;
+ }
+ stream << "</ul>" << endl;
+ }
+ }
+ if (methodDetails.count()) {
+ stream << "<hr><h2>Member Function Documentation</h2>" << endl;
+ for (int i = 0; i < methodDetails.count(); ++i)
+ stream << methodDetails.at(i) << endl;
+ }
+ if (propDetails.count()) {
+ stream << "<hr><h2>Property Documentation</h2>" << endl;
+ for (int i = 0; i < propDetails.count(); ++i)
+ stream << propDetails.at(i) << endl;
+ }
+
+ if (typeInfo)
+ typeInfo->Release();
+ if (dispatch)
+ dispatch->Release();
+ return docu;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/container/qaxobject.cpp b/src/activeqt/container/qaxobject.cpp
new file mode 100644
index 0000000..26cd26a
--- /dev/null
+++ b/src/activeqt/container/qaxobject.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxobject.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <quuid.h>
+#include <qmetaobject.h>
+#include <qstringlist.h>
+
+#include <windows.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAxObject
+ \brief The QAxObject class provides a QObject that wraps a COM object.
+
+ \inmodule QAxContainer
+
+ A QAxObject can be instantiated as an empty object, with the name
+ of the COM object it should wrap, or with a pointer to the
+ IUnknown that represents an existing COM object. If the COM object
+ implements the \c IDispatch interface, the properties, methods and
+ events of that object become available as Qt properties, slots and
+ signals. The base class, QAxBase, provides an API to access the
+ COM object directly through the IUnknown pointer.
+
+ QAxObject is a QObject and can be used as such, e.g. it can be
+ organized in an object hierarchy, receive events and connect to
+ signals and slots.
+
+ QAxObject also inherits most of its ActiveX-related functionality
+ from QAxBase, notably dynamicCall() and querySubObject().
+
+ \warning
+ You can subclass QAxObject, but you cannot use the Q_OBJECT macro
+ in the subclass (the generated moc-file will not compile), so you
+ cannot add further signals, slots or properties. This limitation is
+ due to the metaobject information generated in runtime.
+ To work around this problem, aggregate the QAxObject as a member of
+ the QObject subclass.
+
+ \sa QAxBase, QAxWidget, QAxScript, {ActiveQt Framework}
+*/
+
+/*!
+ Creates an empty COM object and propagates \a parent to the
+ QObject constructor. To initialize the object, call \link
+ QAxBase::setControl() setControl \endlink.
+*/
+QAxObject::QAxObject(QObject *parent)
+: QObject(parent)
+{
+}
+
+/*!
+ Creates a QAxObject that wraps the COM object \a c. \a parent is
+ propagated to the QObject constructor.
+
+ \sa setControl()
+*/
+QAxObject::QAxObject(const QString &c, QObject *parent)
+: QObject(parent)
+{
+ setControl(c);
+}
+
+/*!
+ Creates a QAxObject that wraps the COM object referenced by \a
+ iface. \a parent is propagated to the QObject constructor.
+*/
+QAxObject::QAxObject(IUnknown *iface, QObject *parent)
+: QObject(parent), QAxBase(iface)
+{
+}
+
+/*!
+ Releases the COM object and destroys the QAxObject,
+ cleaning up all allocated resources.
+*/
+QAxObject::~QAxObject()
+{
+ clear();
+}
+
+/*!
+ \internal
+*/
+const QMetaObject *QAxObject::metaObject() const
+{
+ return QAxBase::metaObject();
+}
+
+/*!
+ \internal
+*/
+const QMetaObject *QAxObject::parentMetaObject() const
+{
+ return &QObject::staticMetaObject;
+}
+
+/*!
+ \internal
+*/
+void *QAxObject::qt_metacast(const char *cname)
+{
+ if (!qstrcmp(cname, "QAxObject")) return (void*)this;
+ if (!qstrcmp(cname, "QAxBase")) return (QAxBase*)this;
+ return QObject::qt_metacast(cname);
+}
+
+/*!
+ \internal
+*/
+const char *QAxObject::className() const
+{
+ return "QAxObject";
+}
+
+/*!
+ \internal
+*/
+int QAxObject::qt_metacall(QMetaObject::Call call, int id, void **v)
+{
+ id = QObject::qt_metacall(call, id, v);
+ if (id < 0)
+ return id;
+ return QAxBase::qt_metacall(call, id, v);
+}
+
+/*!
+ \fn QObject *QAxObject::qObject() const
+ \internal
+*/
+
+/*!
+ \reimp
+*/
+void QAxObject::connectNotify(const char *)
+{
+ QAxBase::connectNotify();
+}
+
+/*!
+ \since 4.1
+
+ Requests the COM object to perform the action \a verb. The
+ possible verbs are returned by verbs().
+
+ The function returns true if the object could perform the action, otherwise returns false.
+*/
+bool QAxObject::doVerb(const QString &verb)
+{
+ if (!verbs().contains(verb))
+ return false;
+ IOleObject *ole = 0;
+ queryInterface(IID_IOleObject, (void**)&ole);
+ if (!ole)
+ return false;
+
+ LONG index = indexOfVerb(verb);
+
+ HRESULT hres = ole->DoVerb(index, 0, 0, 0, 0, 0);
+
+ ole->Release();
+
+ return hres == S_OK;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/container/qaxobject.h b/src/activeqt/container/qaxobject.h
new file mode 100644
index 0000000..130814e
--- /dev/null
+++ b/src/activeqt/container/qaxobject.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXOBJECT_H
+#define QAXOBJECT_H
+
+#include <ActiveQt/qaxbase.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+class QAxObject : public QObject, public QAxBase
+{
+ friend class QAxEventSink;
+public:
+ const QMetaObject *metaObject() const;
+ void* qt_metacast(const char*);
+ int qt_metacall(QMetaObject::Call, int, void **);
+ QObject* qObject() const { return (QObject*)this; }
+ const char *className() const;
+
+ QAxObject(QObject *parent = 0);
+ QAxObject(const QString &c, QObject *parent = 0);
+ QAxObject(IUnknown *iface, QObject *parent = 0);
+ ~QAxObject();
+
+ bool doVerb(const QString &verb);
+
+protected:
+ void connectNotify(const char *signal);
+
+private:
+ const QMetaObject *parentMetaObject() const;
+ static QMetaObject staticMetaObject;
+};
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QAxObject *qobject_cast_helper<QAxObject*>(const QObject *o, QAxObject *)
+#else
+template <> inline QAxObject *qobject_cast<QAxObject*>(const QObject *o)
+#endif
+{
+ void *result = o ? const_cast<QObject *>(o)->qt_metacast("QAxObject") : 0;
+ return (QAxObject*)(result);
+}
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QAxObject *qobject_cast_helper<QAxObject*>(QObject *o, QAxObject *)
+#else
+template <> inline QAxObject *qobject_cast<QAxObject*>(QObject *o)
+#endif
+{
+ void *result = o ? o->qt_metacast("QAxObject") : 0;
+ return (QAxObject*)(result);
+}
+
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QAxObject*)
+
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXOBJECT_H
diff --git a/src/activeqt/container/qaxscript.cpp b/src/activeqt/container/qaxscript.cpp
new file mode 100644
index 0000000..7e038a5
--- /dev/null
+++ b/src/activeqt/container/qaxscript.cpp
@@ -0,0 +1,1290 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxscript.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#if defined(Q_CC_GNU)
+# define QT_NO_QAXSCRIPT
+#elif defined(Q_CC_BOR) && __BORLANDC__ < 0x560
+# define QT_NO_QAXSCRIPT
+#endif
+
+#include <qapplication.h>
+#include <qfile.h>
+#include <qhash.h>
+#include <qmetaobject.h>
+#include <quuid.h>
+#include <qwidget.h>
+
+#include <qt_windows.h>
+#ifndef QT_NO_QAXSCRIPT
+#include <initguid.h>
+#include <activscp.h>
+#endif
+
+#include "../shared/qaxtypes.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QAxEngineDescriptor { QString name, extension, code; };
+static QList<QAxEngineDescriptor> engines;
+
+class QAxScriptManagerPrivate
+{
+public:
+ QHash<QString, QAxScript*> scriptDict;
+ QHash<QString, QAxBase*> objectDict;
+};
+
+/*
+ \class QAxScriptSite
+ \brief The QAxScriptSite class implements a Windows Scripting Host
+ \internal
+
+ The QAxScriptSite is used internally to communicate callbacks from the script
+ engine to the script manager.
+*/
+
+#ifndef QT_NO_QAXSCRIPT
+
+class QAxScriptSite : public IActiveScriptSite, public IActiveScriptSiteWindow
+{
+public:
+ QAxScriptSite(QAxScript *script);
+
+ ULONG WINAPI AddRef();
+ ULONG WINAPI Release();
+ HRESULT WINAPI QueryInterface(REFIID iid, void **ppvObject);
+
+ HRESULT WINAPI GetLCID(LCID *plcid);
+ HRESULT WINAPI GetItemInfo(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti);
+ HRESULT WINAPI GetDocVersionString(BSTR *pbstrVersion);
+
+ HRESULT WINAPI OnScriptTerminate(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo);
+ HRESULT WINAPI OnStateChange(SCRIPTSTATE ssScriptState);
+ HRESULT WINAPI OnScriptError(IActiveScriptError *pscripterror);
+ HRESULT WINAPI OnEnterScript();
+ HRESULT WINAPI OnLeaveScript();
+
+ HRESULT WINAPI GetWindow(HWND *phwnd);
+ HRESULT WINAPI EnableModeless(BOOL fEnable);
+
+protected:
+ QWidget *window() const;
+
+private:
+ QAxScript *script;
+ unsigned long ref;
+};
+
+/*
+ Constructs the site for the \a s.
+*/
+QAxScriptSite::QAxScriptSite(QAxScript *s)
+: script(s), ref(1)
+{
+}
+
+/*
+ Implements IUnknown::AddRef
+*/
+ULONG WINAPI QAxScriptSite::AddRef()
+{
+ return ++ref;
+}
+
+/*
+ Implements IUnknown::Release
+*/
+ULONG WINAPI QAxScriptSite::Release()
+{
+ if (!--ref) {
+ delete this;
+ return 0;
+ }
+ return ref;
+}
+
+/*
+ Implements IUnknown::QueryInterface
+*/
+HRESULT WINAPI QAxScriptSite::QueryInterface(REFIID iid, void **ppvObject)
+{
+ *ppvObject = 0;
+ if (iid == IID_IUnknown)
+ *ppvObject = (IUnknown*)(IActiveScriptSite*)this;
+ else if (iid == IID_IActiveScriptSite)
+ *ppvObject = (IActiveScriptSite*)this;
+ else if (iid == IID_IActiveScriptSiteWindow)
+ *ppvObject = (IActiveScriptSiteWindow*)this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+}
+
+/*
+ Implements IActiveScriptSite::GetLCID
+
+ This method is not implemented. Use the system-defined locale.
+*/
+HRESULT WINAPI QAxScriptSite::GetLCID(LCID * /*plcid*/)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Implements IActiveScriptSite::GetItemInfo
+
+ Tries to find the QAxBase for \a pstrName and returns the
+ relevant interfaces in \a item and \a type as requested through \a mask.
+*/
+HRESULT WINAPI QAxScriptSite::GetItemInfo(LPCOLESTR pstrName, DWORD mask, IUnknown **item, ITypeInfo **type)
+{
+ if (item)
+ *item = 0;
+ else if (mask & SCRIPTINFO_IUNKNOWN)
+ return E_POINTER;
+
+ if (type)
+ *type = 0;
+ else if (mask & SCRIPTINFO_ITYPEINFO)
+ return E_POINTER;
+
+ QAxBase *object = script->findObject(QString::fromWCharArray(pstrName));
+ if (!object)
+ return TYPE_E_ELEMENTNOTFOUND;
+
+ if (mask & SCRIPTINFO_IUNKNOWN)
+ object->queryInterface(IID_IUnknown, (void**)item);
+ if (mask & SCRIPTINFO_ITYPEINFO) {
+ IProvideClassInfo *classInfo = 0;
+ object->queryInterface(IID_IProvideClassInfo, (void**)&classInfo);
+ if (classInfo) {
+ classInfo->GetClassInfo(type);
+ classInfo->Release();
+ }
+ }
+ return S_OK;
+}
+
+/*
+ Implements IActiveScriptSite::GetDocVersionString
+
+ This method is not implemented. The scripting engine should assume
+ that the script is in sync with the document.
+*/
+HRESULT WINAPI QAxScriptSite::GetDocVersionString(BSTR * /*version*/)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Implements IActiveScriptSite::OnScriptTerminate
+
+ This method is usually not called, but if it is it fires
+ QAxScript::finished().
+*/
+HRESULT WINAPI QAxScriptSite::OnScriptTerminate(const VARIANT *result, const EXCEPINFO *exception)
+{
+ emit script->finished();
+
+ if (result && result->vt != VT_EMPTY)
+ emit script->finished(VARIANTToQVariant(*result, 0));
+ if (exception)
+ emit script->finished(exception->wCode,
+ QString::fromWCharArray(exception->bstrSource),
+ QString::fromWCharArray(exception->bstrDescription),
+ QString::fromWCharArray(exception->bstrHelpFile)
+ );
+ return S_OK;
+}
+
+/*
+ Implements IActiveScriptSite::OnEnterScript
+
+ Fires QAxScript::entered() to inform the host that the
+ scripting engine has begun executing the script code.
+*/
+HRESULT WINAPI QAxScriptSite::OnEnterScript()
+{
+ emit script->entered();
+ return S_OK;
+}
+
+/*
+ Implements IActiveScriptSite::OnLeaveScript
+
+ Fires QAxScript::finished() to inform the host that the
+ scripting engine has returned from executing the script code.
+*/
+HRESULT WINAPI QAxScriptSite::OnLeaveScript()
+{
+ emit script->finished();
+ return S_OK;
+}
+
+/*
+ Implements IActiveScriptSite::OnScriptError
+
+ Fires QAxScript::error() to inform the host that an
+ that an execution error occurred while the engine was running the script.
+*/
+HRESULT WINAPI QAxScriptSite::OnScriptError(IActiveScriptError *error)
+{
+ EXCEPINFO exception;
+ memset(&exception, 0, sizeof(exception));
+ DWORD context;
+ ULONG lineNumber;
+ LONG charPos;
+ BSTR bstrLineText;
+ QString lineText;
+
+ error->GetExceptionInfo(&exception);
+ error->GetSourcePosition(&context, &lineNumber, &charPos);
+ HRESULT hres = error->GetSourceLineText(&bstrLineText);
+ if (hres == S_OK) {
+ lineText = QString::fromWCharArray(bstrLineText);
+ SysFreeString(bstrLineText);
+ }
+ SysFreeString(exception.bstrSource);
+ SysFreeString(exception.bstrDescription);
+ SysFreeString(exception.bstrHelpFile);
+
+ emit script->error(exception.wCode, QString::fromWCharArray(exception.bstrDescription), lineNumber, lineText);
+
+ return S_OK;
+}
+
+/*
+ Implements IActiveScriptSite::OnStateChange
+
+ Fires QAxScript::stateChanged() to inform the
+ the host that the scripting engine has changed states.
+*/
+HRESULT WINAPI QAxScriptSite::OnStateChange(SCRIPTSTATE ssScriptState)
+{
+ emit script->stateChanged(ssScriptState);
+ return S_OK;
+}
+
+/*
+ \internal
+ Returns the toplevel widget parent of this script, or
+ the application' active window if there is no widget parent.
+*/
+QWidget *QAxScriptSite::window() const
+{
+ QWidget *w = 0;
+ QObject *p = script->parent();
+ while (!w && p) {
+ w = qobject_cast<QWidget*>(p);
+ p = p->parent();
+ }
+
+ if (w)
+ w = w->window();
+ if (!w && qApp)
+ w = qApp->activeWindow();
+
+ return w;
+}
+
+/*
+ Implements IActiveScriptSiteWindow::GetWindow
+
+ Retrieves the handle to a window that can act as the owner of a
+ pop-up window that the scripting engine must display.
+*/
+HRESULT WINAPI QAxScriptSite::GetWindow(HWND *phwnd)
+{
+ if (!phwnd)
+ return E_POINTER;
+
+ *phwnd = 0;
+ QWidget *w = window();
+ if (!w)
+ return E_FAIL;
+
+ *phwnd = w->winId();
+ return S_OK;
+}
+
+/*
+ Implements IActiveScriptSiteWindow::EnableModeless
+
+ Causes the host to enable or disable its main window
+ as well as any modeless dialog boxes.
+*/
+HRESULT WINAPI QAxScriptSite::EnableModeless(BOOL fEnable)
+{
+ QWidget *w = window();
+ if (!w)
+ return E_FAIL;
+
+ EnableWindow(w->winId(), fEnable);
+ return S_OK;
+}
+
+#endif //QT_NO_QAXSCRIPT
+
+
+/*!
+ \class QAxScriptEngine
+ \brief The QAxScriptEngine class provides a wrapper around a script engine.
+ \inmodule QAxContainer
+
+ Every instance of the QAxScriptEngine class represents an interpreter
+ for script code in a particular scripting language. The class is usually
+ not used directly. The QAxScript and QAxScriptManager classes provide
+ convenient functions to handle and call script code.
+
+ Direct access to the script engine is provided through
+ queryInterface().
+
+ \warning This class is not available with the bcc5.5 and MingW
+ compilers.
+
+ \sa QAxScript, QAxScriptManager, QAxBase, {ActiveQt Framework}
+*/
+
+/*!
+ \enum QAxScriptEngine::State
+
+ The State enumeration defines the different states a script
+ engine can be in.
+
+ \value Uninitialized The script has been created, but not yet initialized
+ \value Initialized The script has been initialized, but is not running
+ \value Started The script can execute code, but does not yet handle events
+ \value Connected The script can execute code and is connected so
+ that it can handle events
+ \value Disconnected The script is loaded, but is not connected to
+ event sources
+ \value Closed The script has been closed.
+*/
+
+/*!
+ Constructs a QAxScriptEngine object interpreting script code in \a language
+ provided by the code in \a script. This is usually done by the QAxScript
+ class when \link QAxScript::load() loading a script\endlink.
+
+ Instances of QAxScriptEngine should always have both a language and a
+ script.
+*/
+QAxScriptEngine::QAxScriptEngine(const QString &language, QAxScript *script)
+: QAxObject(script), script_code(script), engine(0), script_language(language)
+{
+#ifdef QT_CHECK_STATE
+ if (language.isEmpty())
+ qWarning("QAxScriptEngine: created without language");
+
+ if (!script_code)
+ qWarning("QAxScriptEngine: created without script");
+#endif
+ setObjectName(QLatin1String("QAxScriptEngine_") + language);
+ disableClassInfo();
+ disableEventSink();
+}
+
+/*!
+ Destroys the QAxScriptEngine object, releasing all allocated
+ resources.
+*/
+QAxScriptEngine::~QAxScriptEngine()
+{
+#ifndef QT_NO_QAXSCRIPT
+ if (engine) {
+ engine->SetScriptState(SCRIPTSTATE_DISCONNECTED);
+ engine->Close();
+ engine->Release();
+ }
+#endif
+}
+
+/*!
+ \fn QString QAxScriptEngine::scriptLanguage() const
+ Returns the scripting language, for example "VBScript",
+ or "JScript".
+*/
+
+/*!
+ \reimp
+*/
+bool QAxScriptEngine::initialize(IUnknown **ptr)
+{
+ *ptr = 0;
+
+#ifndef QT_NO_QAXSCRIPT
+ if (!script_code || script_language.isEmpty())
+ return false;
+
+ CLSID clsid;
+ HRESULT hres = CLSIDFromProgID((wchar_t*)script_language.utf16(), &clsid);
+ if(FAILED(hres))
+ return false;
+
+ CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void**)&engine);
+ if (!engine)
+ return false;
+
+ IActiveScriptParse *parser = 0;
+ engine->QueryInterface(IID_IActiveScriptParse, (void**)&parser);
+ if (!parser) {
+ engine->Release();
+ engine = 0;
+ return false;
+ }
+
+ if (engine->SetScriptSite(script_code->script_site) != S_OK) {
+ engine->Release();
+ engine = 0;
+ return false;
+ }
+ if (parser->InitNew() != S_OK) {
+ parser->Release();
+ engine->Release();
+ engine = 0;
+ return false;
+ }
+
+ BSTR bstrCode = QStringToBSTR(script_code->scriptCode());
+#ifdef Q_OS_WIN64
+ hres = parser->ParseScriptText(bstrCode, 0, 0, 0, DWORDLONG(this), 0, SCRIPTTEXT_ISVISIBLE, 0, 0);
+#else
+ hres = parser->ParseScriptText(bstrCode, 0, 0, 0, DWORD(this), 0, SCRIPTTEXT_ISVISIBLE, 0, 0);
+#endif
+ SysFreeString(bstrCode);
+
+ parser->Release();
+ parser = 0;
+
+ script_code->updateObjects();
+
+ if (engine->SetScriptState(SCRIPTSTATE_CONNECTED) != S_OK) {
+ engine = 0;
+ return false;
+ }
+
+ IDispatch *scriptDispatch = 0;
+ engine->GetScriptDispatch(0, &scriptDispatch);
+ if (scriptDispatch) {
+ scriptDispatch->QueryInterface(IID_IUnknown, (void**)ptr);
+ scriptDispatch->Release();
+ }
+#endif
+
+ return *ptr != 0;
+}
+
+/*!
+ \fn bool QAxScriptEngine::isValid() const
+
+ Returns true if the script engine has been initialized
+ correctly; otherwise returns false.
+*/
+
+/*!
+ Returns true if the script engine supports introspection;
+ otherwise returns false.
+*/
+bool QAxScriptEngine::hasIntrospection() const
+{
+ if (!isValid())
+ return false;
+
+ IDispatch *scriptDispatch = 0;
+ QAxBase::queryInterface(IID_IDispatch, (void**)&scriptDispatch);
+ if (!scriptDispatch)
+ return false;
+
+ UINT tic = 0;
+ HRESULT hres = scriptDispatch->GetTypeInfoCount(&tic);
+ scriptDispatch->Release();
+ return hres == S_OK && tic > 0;
+}
+
+/*!
+ Requests the interface \a uuid from the script engine object and
+ sets the value of \a iface to the provided interface, or to 0 if
+ the requested interface could not be provided.
+
+ Returns the result of the QueryInterface implementation of the COM
+ object.
+*/
+long QAxScriptEngine::queryInterface(const QUuid &uuid, void **iface) const
+{
+ *iface = 0;
+ if (!engine)
+ return E_NOTIMPL;
+
+#ifndef QT_NO_QAXSCRIPT
+ return engine->QueryInterface(uuid, iface);
+#else
+ return E_NOTIMPL;
+#endif
+}
+
+/*!
+ Returns the state of the script engine.
+*/
+QAxScriptEngine::State QAxScriptEngine::state() const
+{
+ if (!engine)
+ return Uninitialized;
+
+#ifndef QT_NO_QAXSCRIPT
+ SCRIPTSTATE state;
+ engine->GetScriptState(&state);
+ return (State)state;
+#else
+ return Uninitialized;
+#endif
+}
+
+/*!
+ Sets the state of the script engine to \a st.
+ Calling this function is usually not necessary.
+*/
+void QAxScriptEngine::setState(State st)
+{
+#ifndef QT_NO_QAXSCRIPT
+ if (!engine)
+ return;
+
+ engine->SetScriptState((SCRIPTSTATE)st);
+#endif
+}
+
+/*!
+ Registers an item with the script engine. Script code can
+ refer to this item using \a name.
+*/
+void QAxScriptEngine::addItem(const QString &name)
+{
+#ifndef QT_NO_QAXSCRIPT
+ if (!engine)
+ return;
+
+ engine->AddNamedItem((wchar_t*)name.utf16(), SCRIPTITEM_ISSOURCE|SCRIPTITEM_ISVISIBLE);
+#endif
+}
+
+/*!
+ \class QAxScript
+ \brief The QAxScript class provides a wrapper around script code.
+ \inmodule QAxContainer
+
+ Every instance of the QAxScript class represents a piece of
+ scripting code in a particular scripting language. The code is
+ loaded into the script engine using load(). Functions declared
+ in the code can be called using call().
+
+ The script provides scriptEngine() provides feedback to the
+ application through signals. The most important signal is the
+ error() signal. Direct access to the QAxScriptEngine is provided
+ through the scriptEngine() function.
+
+ \warning This class is not available with the bcc5.5 and MingW
+ compilers.
+
+ \sa QAxScriptEngine, QAxScriptManager, QAxBase, {ActiveQt Framework}
+*/
+
+/*!
+ \enum QAxScript::FunctionFlags
+
+ This FunctionFlags enum describes formatting for function introspection.
+
+ \value FunctionNames Only function names are returned.
+ \value FunctionSignatures Returns the functions with signatures.
+*/
+
+/*!
+ Constructs a QAxScript object called \a name and registers
+ it with the QAxScriptManager \a manager. This is usually done by the
+ QAxScriptManager class when \link QAxScriptManager::load() loading a
+ script\endlink.
+
+ A script should always have a name. A manager is necessary to allow
+ the script code to reference objects in the application. The \a manager
+ takes ownership of the object.
+*/
+QAxScript::QAxScript(const QString &name, QAxScriptManager *manager)
+: QObject(manager), script_name(name), script_manager(manager),
+script_engine(0)
+{
+ if (manager) {
+ manager->d->scriptDict.insert(name, this);
+ connect(this, SIGNAL(error(int,QString,int,QString)),
+ manager, SLOT(scriptError(int,QString,int,QString)));
+ }
+
+#ifndef QT_NO_QAXSCRIPT
+ script_site = new QAxScriptSite(this);
+#else
+ script_site = 0;
+#endif
+}
+
+/*!
+ Destroys the object, releasing all allocated resources.
+*/
+QAxScript::~QAxScript()
+{
+ delete script_engine;
+ script_engine = 0;
+
+#ifndef QT_NO_QAXSCRIPT
+ script_site->Release();
+#endif
+}
+
+/*!
+ Loads the script source \a code written in language \a language
+ into the script engine. Returns true if \a code was successfully
+ entered into the script engine; otherwise returns false.
+
+ If \a language is empty (the default) it will be determined
+ heuristically. If \a code contains the string \c {End Sub} it will
+ be interpreted as VBScript, otherwise as JScript. Additional
+ scripting languages can be registered using
+ QAxScript::registerEngine().
+
+ This function can only be called once for each QAxScript object,
+ which is done automatically when using QAxScriptManager::load().
+*/
+bool QAxScript::load(const QString &code, const QString &language)
+{
+ if (script_engine || code.isEmpty())
+ return false;
+
+ script_code = code;
+ QString lang = language;
+ if (lang.isEmpty()) {
+ if (code.contains(QLatin1String("End Sub"), Qt::CaseInsensitive))
+ lang = QLatin1String("VBScript");
+
+ QList<QAxEngineDescriptor>::ConstIterator it;
+ for (it = engines.begin(); it != engines.end(); ++it) {
+ QAxEngineDescriptor engine = *it;
+ if (engine.code.isEmpty())
+ continue;
+
+ if (code.contains(engine.code)) {
+ lang = engine.name;
+ break;
+ }
+ }
+ }
+ if (lang.isEmpty())
+ lang = QLatin1String("JScript");
+
+ script_engine = new QAxScriptEngine(lang, this);
+ // trigger call to initialize
+ script_engine->metaObject();
+
+ return script_engine->isValid();
+}
+
+/*!
+ Returns a list of all the functions in this script if the respective
+ script engine supports introspection; otherwise returns an empty list.
+ The functions are either provided with full prototypes or only as
+ names, depending on the value of \a flags.
+
+ \sa QAxScriptEngine::hasIntrospection()
+*/
+QStringList QAxScript::functions(FunctionFlags flags) const
+{
+ QStringList functions;
+
+ const QMetaObject *mo = script_engine->metaObject();
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod slot(mo->method(i));
+ if (slot.methodType() != QMetaMethod::Slot || slot.access() != QMetaMethod::Public)
+ continue;
+ QString slotname = QString::fromLatin1(slot.signature());
+ if (slotname.contains(QLatin1Char('_')))
+ continue;
+
+ if (flags == FunctionSignatures)
+ functions << slotname;
+ else
+ functions << slotname.left(slotname.indexOf(QLatin1Char('(')));
+ }
+
+ return functions;
+}
+
+/*!
+ Calls \a function, passing the parameters \a var1, \a var1,
+ \a var2, \a var3, \a var4, \a var5, \a var6, \a var7 and \a var8
+ as arguments and returns the value returned by the function, or an
+ invalid QVariant if the function does not return a value or when
+ the function call failed.
+
+ See QAxScriptManager::call() for more information about how to call
+ script functions.
+*/
+QVariant QAxScript::call(const QString &function, const QVariant &var1,
+ const QVariant &var2,
+ const QVariant &var3,
+ const QVariant &var4,
+ const QVariant &var5,
+ const QVariant &var6,
+ const QVariant &var7,
+ const QVariant &var8)
+{
+ if (!script_engine)
+ return QVariant();
+
+ return script_engine->dynamicCall(function.toLatin1(), var1, var2, var3, var4, var5, var6, var7, var8);
+}
+
+/*!
+ \overload
+
+ Calls \a function passing \a arguments as parameters, and returns
+ the result. Returns when the script's execution has finished.
+
+ See QAxScriptManager::call() for more information about how to call
+ script functions.
+*/
+QVariant QAxScript::call(const QString &function, QList<QVariant> &arguments)
+{
+ if (!script_engine)
+ return QVariant();
+
+ return script_engine->dynamicCall(function.toLatin1(), arguments);
+}
+
+/*! \internal
+ Registers all objects in the manager with the script engine.
+*/
+void QAxScript::updateObjects()
+{
+ if (!script_manager)
+ return;
+
+ script_manager->updateScript(this);
+}
+
+/*! \internal
+ Returns the object \a name registered with the manager.
+*/
+QAxBase *QAxScript::findObject(const QString &name)
+{
+ if (!script_manager)
+ return 0;
+
+ return script_manager->d->objectDict.value(name);
+}
+
+/*! \fn QString QAxScript::scriptName() const
+ Returns the name of the script.
+*/
+
+/*! \fn QString QAxScript::scriptCode() const
+ Returns the script's code, or the null-string if no
+ code has been loaded yet.
+
+ \sa load()
+*/
+
+/*! \fn QAxScriptEngine* QAxScript::scriptEngine() const
+ Returns a pointer to the script engine.
+
+ You can use the object returned to connect signals to the
+ script functions, or to access the script engine directly.
+*/
+
+/*! \fn void QAxScript::entered()
+
+ This signal is emitted when a script engine has started executing code.
+*/
+
+/*! \fn void QAxScript::finished()
+
+ This signal is emitted when a script engine has finished executing code.
+*/
+
+/*!
+ \fn void QAxScript::finished(const QVariant &result)
+ \overload
+
+ \a result contains the script's result. This will be an invalid
+ QVariant if the script has no return value.
+*/
+
+/*! \fn void QAxScript::finished(int code, const QString &source,
+ const QString &description, const QString &help)
+ \overload
+
+ \a code, \a source, \a description and \a help contain exception information
+ when the script terminated.
+*/
+
+/*! \fn void QAxScript::stateChanged(int state);
+
+ This signal is emitted when a script engine changes state.
+ \a state can be any value in the QAxScriptEngineState enumeration.
+*/
+
+/*!
+ \fn void QAxScript::error(int code, const QString &description,
+ int sourcePosition, const QString &sourceText)
+
+ This signal is emitted when an execution error occurred while
+ running a script.
+
+ \a code, \a description, \a sourcePosition and \a sourceText
+ contain information about the execution error.
+*/
+
+
+
+/*!
+ \class QAxScriptManager
+ \brief The QAxScriptManager class provides a bridge between application objects
+ and script code.
+ \inmodule QAxContainer
+
+ The QAxScriptManager acts as a bridge between the COM objects embedded
+ in the Qt application through QAxObject or QAxWidget, and the scripting
+ languages available through the Windows Script technologies, usually JScript
+ and VBScript.
+
+ Create one QAxScriptManager for each separate document in your
+ application, and add the COM objects the scripts need to access
+ using addObject(). Then load() the script sources and invoke the
+ functions using call().
+
+ \warning This class is not available with the bcc5.5 and MingW
+ compilers.
+
+ \sa QAxScript, QAxScriptEngine, QAxBase, {ActiveQt Framework}
+*/
+
+/*!
+ Creates a QAxScriptManager object. \a parent is passed on to the
+ QObject constructor.
+
+ It is usual to create one QAxScriptManager for each document in an
+ application.
+*/
+QAxScriptManager::QAxScriptManager(QObject *parent)
+: QObject(parent)
+{
+ d = new QAxScriptManagerPrivate;
+}
+
+/*!
+ Destroys the objects, releasing all allocated resources.
+*/
+QAxScriptManager::~QAxScriptManager()
+{
+ delete d;
+}
+
+/*!
+ Returns a list with all the functions that are available.
+ Functions provided by script engines that don't support
+ introspection are not included in the list.
+ The functions are either provided with full prototypes or
+ only as names, depending on the value of \a flags.
+*/
+QStringList QAxScriptManager::functions(QAxScript::FunctionFlags flags) const
+{
+ QStringList functions;
+
+ QHash<QString, QAxScript*>::ConstIterator scriptIt;
+ for (scriptIt = d->scriptDict.begin(); scriptIt != d->scriptDict.end(); ++scriptIt) {
+ QAxScript *script = scriptIt.value();
+ functions += script->functions(flags);
+ }
+
+ return functions;
+}
+
+/*!
+ Returns a list with the names of all the scripts.
+*/
+QStringList QAxScriptManager::scriptNames() const
+{
+ QStringList scripts;
+
+ QHash<QString, QAxScript*>::ConstIterator scriptIt;
+ for (scriptIt = d->scriptDict.begin(); scriptIt != d->scriptDict.end(); ++scriptIt) {
+ scripts << scriptIt.key();
+ }
+
+ return scripts;
+}
+
+/*!
+ Returns the script called \a name.
+
+ You can use the returned pointer to call functions directly
+ through QAxScript::call(), to access the script engine directly, or
+ to delete and thus unload the script.
+*/
+QAxScript *QAxScriptManager::script(const QString &name) const
+{
+ return d->scriptDict.value(name);
+}
+
+/*!
+ Adds \a object to the manager. Scripts handled by this manager
+ can access the object in the code using the object's
+ \l{QObject::objectName}{objectName} property.
+
+ You must add all the necessary objects before loading any scripts.
+*/
+void QAxScriptManager::addObject(QAxBase *object)
+{
+ QObject *obj = object->qObject();
+ QString name = obj->objectName();
+ if (d->objectDict.contains(name))
+ return;
+
+ d->objectDict.insert(name, object);
+ connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+}
+
+/*! \fn void QAxScriptManager::addObject(QObject *object)
+ \overload
+
+ Adds a generic COM wrapper for \a object to the manager. \a object
+ must be exposed as a COM object using the functionality provided
+ by the QAxServer module. Applications
+ using this function you must link against the qaxserver library.
+*/
+
+/*!
+ Loads the script source \a code using the script engine for \a
+ language. The script can later be referred to using its \a name
+ which should not be empty.
+
+ The function returns a pointer to the script for the given
+ \a code if the \a code was loaded successfully; otherwise it
+ returns 0.
+
+ If \a language is empty it will be determined heuristically. If \a
+ code contains the string "End Sub" it will be interpreted as
+ VBScript, otherwise as JScript. Additional script engines can be
+ registered using registerEngine().
+
+ You must add all the objects necessary (using addObject()) \e
+ before loading any scripts. If \a code declares a function that is
+ already available (no matter in which language) the first function
+ is overloaded and can no longer be called via call(); but it will
+ still be available by calling its \link script() script \endlink
+ directly.
+
+ \sa addObject(), scriptNames(), functions()
+*/
+QAxScript *QAxScriptManager::load(const QString &code, const QString &name, const QString &language)
+{
+ QAxScript *script = new QAxScript(name, this);
+ if (script->load(code, language))
+ return script;
+
+ delete script;
+ return 0;
+}
+
+/*!
+ \overload
+
+ Loads the source code from the \a file. The script can later be
+ referred to using its \a name which should not be empty.
+
+ The function returns a pointer to the script engine for the code
+ in \a file if \a file was loaded successfully; otherwise it
+ returns 0.
+
+ The script engine used is determined from the file's extension. By
+ default ".js" files are interpreted as JScript files, and ".vbs"
+ and ".dsm" files are interpreted as VBScript. Additional script
+ engines can be registered using registerEngine().
+*/
+QAxScript *QAxScriptManager::load(const QString &file, const QString &name)
+{
+ QFile f(file);
+ if (!f.open(QIODevice::ReadOnly))
+ return 0;
+ QByteArray data = f.readAll();
+ QString contents = QString::fromLocal8Bit(data, data.size());
+ f.close();
+
+ if (contents.isEmpty())
+ return 0;
+
+ QString language;
+ if (file.endsWith(QLatin1String(".js"))) {
+ language = QLatin1String("JScript");
+ } else {
+ QList<QAxEngineDescriptor>::ConstIterator it;
+ for (it = engines.begin(); it != engines.end(); ++it) {
+ QAxEngineDescriptor engine = *it;
+ if (engine.extension.isEmpty())
+ continue;
+
+ if (file.endsWith(engine.extension)) {
+ language = engine.name;
+ break;
+ }
+ }
+ }
+
+ if (language.isEmpty())
+ language = QLatin1String("VBScript");
+
+ QAxScript *script = new QAxScript(name, this);
+ if (script->load(contents, language))
+ return script;
+
+ delete script;
+ return 0;
+}
+
+/*!
+ Calls \a function, passing the parameters \a var1, \a var1,
+ \a var2, \a var3, \a var4, \a var5, \a var6, \a var7 and \a var8
+ as arguments and returns the value returned by the function, or an
+ invalid QVariant if the function does not return a value or when
+ the function call failed. The call returns when the script's
+ execution has finished.
+
+ In most script engines the only supported parameter type is "const
+ QVariant&", for example, to call a JavaScript function
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxscript.cpp 0
+ use
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxscript.cpp 1
+ As with \link QAxBase::dynamicCall() dynamicCall \endlink the
+ parameters can directly be embedded in the function string.
+ \snippet doc/src/snippets/code/src_activeqt_container_qaxscript.cpp 2
+ However, this is slower.
+
+ Functions provided by script engines that don't support
+ introspection are not available and must be called directly
+ using QAxScript::call() on the respective \link script()
+ script \endlink object.
+
+ Note that calling this function can be significantely slower than
+ using call() on the respective QAxScript directly.
+*/
+QVariant QAxScriptManager::call(const QString &function, const QVariant &var1,
+ const QVariant &var2,
+ const QVariant &var3,
+ const QVariant &var4,
+ const QVariant &var5,
+ const QVariant &var6,
+ const QVariant &var7,
+ const QVariant &var8)
+{
+ QAxScript *s = script(function);
+ if (!s) {
+#ifdef QT_CHECK_STATE
+ qWarning("QAxScriptManager::call: No script provides function %s, or this function\n"
+ "\tis provided through an engine that does not support introspection", function.latin1());
+#endif
+ return QVariant();
+ }
+
+ return s->call(function, var1, var2, var3, var4, var5, var6, var7, var8);
+}
+
+/*! \overload
+
+ Calls \a function passing \a arguments as parameters, and returns
+ the result. Returns when the script's execution has finished.
+*/
+QVariant QAxScriptManager::call(const QString &function, QList<QVariant> &arguments)
+{
+ QAxScript *s = script(function);
+ if (!s) {
+#ifdef QT_CHECK_STATE
+ qWarning("QAxScriptManager::call: No script provides function %s, or this function\n"
+ "\tis provided through an engine that does not support introspection", function.latin1());
+#endif
+ return QVariant();
+ }
+
+ QList<QVariant> args(arguments);
+ return s->call(function, args);
+}
+
+/*!
+ Registers the script engine called \a name and returns true if the
+ engine was found; otherwise does nothing and returns false.
+
+ The script engine will be used when loading files with the given
+ \a extension, or when loading source code that contains the string
+ \a code.
+*/
+bool QAxScriptManager::registerEngine(const QString &name, const QString &extension, const QString &code)
+{
+ if (name.isEmpty())
+ return false;
+
+ CLSID clsid;
+ HRESULT hres = CLSIDFromProgID((wchar_t*)name.utf16(), &clsid);
+ if (hres != S_OK)
+ return false;
+
+ QAxEngineDescriptor engine;
+ engine.name = name;
+ engine.extension = extension;
+ engine.code = code;
+
+ engines.prepend(engine);
+ return true;
+}
+
+/*!
+ Returns a file filter listing all the supported script languages.
+ This filter string is convenient for use with QFileDialog.
+*/
+QString QAxScriptManager::scriptFileFilter()
+{
+ QString allFiles = QLatin1String("Script Files (*.js *.vbs *.dsm");
+ QString specialFiles = QLatin1String(";;VBScript Files (*.vbs *.dsm)"
+ ";;JavaScript Files (*.js)");
+
+ QList<QAxEngineDescriptor>::ConstIterator it;
+ for (it = engines.begin(); it != engines.end(); ++it) {
+ QAxEngineDescriptor engine = *it;
+ if (engine.extension.isEmpty())
+ continue;
+
+ allFiles += QLatin1String(" *") + engine.extension;
+ specialFiles += QLatin1String(";;") + engine.name + QLatin1String(" Files (*") + engine.extension + QLatin1Char(')');
+ }
+ allFiles += QLatin1Char(')');
+
+ return allFiles + specialFiles + QLatin1String(";;All Files (*.*)");
+}
+
+/*!
+ \fn void QAxScriptManager::error(QAxScript *script, int code, const QString &description,
+ int sourcePosition, const QString &sourceText)
+
+ This signal is emitted when an execution error occurred while
+ running \a script.
+
+ \a code, \a description, \a sourcePosition and \a sourceText
+ contain information about the execution error.
+
+ \warning Do not delete \a script in a slot connected to this signal. Use deleteLater()
+ instead.
+*/
+
+/*!
+ \internal
+
+ Returns a pointer to the first QAxScript that knows
+ about \a function, or 0 if this function is unknown.
+*/
+QAxScript *QAxScriptManager::scriptForFunction(const QString &function) const
+{
+ // check full prototypes if included
+ if (function.contains(QLatin1Char('('))) {
+ QHash<QString, QAxScript*>::ConstIterator scriptIt;
+ for (scriptIt = d->scriptDict.begin(); scriptIt != d->scriptDict.end(); ++scriptIt) {
+ QAxScript *script = scriptIt.value();
+
+ if (script->functions(QAxScript::FunctionSignatures).contains(function))
+ return script;
+ }
+ }
+
+ QString funcName = function;
+ funcName = funcName.left(funcName.indexOf(QLatin1Char('(')));
+ // second try, checking only names, not prototypes
+ QHash<QString, QAxScript*>::ConstIterator scriptIt;
+ for (scriptIt = d->scriptDict.begin(); scriptIt != d->scriptDict.end(); ++scriptIt) {
+ QAxScript *script = scriptIt.value();
+
+ if (script->functions(QAxScript::FunctionNames).contains(funcName))
+ return script;
+ }
+
+ return 0;
+}
+
+/*!
+ \internal
+*/
+void QAxScriptManager::updateScript(QAxScript *script)
+{
+ QHash<QString, QAxBase*>::ConstIterator objectIt;
+ for (objectIt = d->objectDict.constBegin(); objectIt != d->objectDict.constEnd(); ++objectIt) {
+ QString name = objectIt.key();
+
+ QAxScriptEngine *engine = script->scriptEngine();
+ if (engine)
+ engine->addItem(name);
+ }
+}
+
+/*!
+ \internal
+*/
+void QAxScriptManager::objectDestroyed(QObject *o)
+{
+ d->objectDict.take(o->objectName());
+}
+
+/*!
+ \internal
+*/
+void QAxScriptManager::scriptError(int code, const QString &desc, int spos, const QString &stext)
+{
+ QAxScript *source = qobject_cast<QAxScript*>(sender());
+ emit error(source, code, desc, spos, stext);
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/container/qaxscript.h b/src/activeqt/container/qaxscript.h
new file mode 100644
index 0000000..b423376
--- /dev/null
+++ b/src/activeqt/container/qaxscript.h
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXSCRIPT_H
+#define QAXSCRIPT_H
+
+#include <ActiveQt/qaxobject.h>
+
+struct IActiveScript;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+class QAxBase;
+class QAxScript;
+class QAxScriptSite;
+class QAxScriptEngine;
+class QAxScriptManager;
+class QAxScriptManagerPrivate;
+
+class QAxScriptEngine : public QAxObject
+{
+public:
+ enum State {
+ Uninitialized = 0,
+ Initialized = 5,
+ Started = 1,
+ Connected = 2,
+ Disconnected = 3,
+ Closed = 4
+ };
+
+ QAxScriptEngine(const QString &language, QAxScript *script);
+ ~QAxScriptEngine();
+
+ bool isValid() const;
+ bool hasIntrospection() const;
+
+ QString scriptLanguage() const;
+
+ State state() const;
+ void setState(State st);
+
+ void addItem(const QString &name);
+
+ long queryInterface(const QUuid &, void**) const;
+
+protected:
+ bool initialize(IUnknown** ptr);
+
+private:
+ QAxScript *script_code;
+ IActiveScript *engine;
+
+ QString script_language;
+};
+
+class QAxScript : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum FunctionFlags {
+ FunctionNames = 0,
+ FunctionSignatures
+ };
+
+ QAxScript(const QString &name, QAxScriptManager *manager);
+ ~QAxScript();
+
+ bool load(const QString &code, const QString &language = QString());
+
+ QStringList functions(FunctionFlags = FunctionNames) const;
+
+ QString scriptCode() const;
+ QString scriptName() const;
+ QAxScriptEngine *scriptEngine() const;
+
+ QVariant call(const QString &function, const QVariant &v1 = QVariant(),
+ const QVariant &v2 = QVariant(),
+ const QVariant &v3 = QVariant(),
+ const QVariant &v4 = QVariant(),
+ const QVariant &v5 = QVariant(),
+ const QVariant &v6 = QVariant(),
+ const QVariant &v7 = QVariant(),
+ const QVariant &v8 = QVariant());
+ QVariant call(const QString &function, QList<QVariant> &arguments);
+
+Q_SIGNALS:
+ void entered();
+ void finished();
+ void finished(const QVariant &result);
+ void finished(int code, const QString &source,const QString &description, const QString &help);
+ void stateChanged(int state);
+ void error(int code, const QString &description, int sourcePosition, const QString &sourceText);
+
+private:
+ friend class QAxScriptSite;
+ friend class QAxScriptEngine;
+
+ void updateObjects();
+ QAxBase *findObject(const QString &name);
+
+ QString script_name;
+ QString script_code;
+ QAxScriptManager *script_manager;
+ QAxScriptEngine *script_engine;
+ QAxScriptSite *script_site;
+};
+
+class QAxScriptManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ QAxScriptManager(QObject *parent = 0);
+ ~QAxScriptManager();
+
+ void addObject(QAxBase *object);
+ void addObject(QObject *object);
+
+ QStringList functions(QAxScript::FunctionFlags = QAxScript::FunctionNames) const;
+ QStringList scriptNames() const;
+ QAxScript *script(const QString &name) const;
+
+ QAxScript* load(const QString &code, const QString &name, const QString &language);
+ QAxScript* load(const QString &file, const QString &name);
+
+ QVariant call(const QString &function, const QVariant &v1 = QVariant(),
+ const QVariant &v2 = QVariant(),
+ const QVariant &v3 = QVariant(),
+ const QVariant &v4 = QVariant(),
+ const QVariant &v5 = QVariant(),
+ const QVariant &v6 = QVariant(),
+ const QVariant &v7 = QVariant(),
+ const QVariant &v8 = QVariant());
+ QVariant call(const QString &function, QList<QVariant> &arguments);
+
+ static bool registerEngine(const QString &name, const QString &extension, const QString &code = QString());
+ static QString scriptFileFilter();
+
+Q_SIGNALS:
+ void error(QAxScript *script, int code, const QString &description, int sourcePosition, const QString &sourceText);
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *o);
+ void scriptError(int code, const QString &description, int sourcePosition, const QString &sourceText);
+
+private:
+ friend class QAxScript;
+ QAxScriptManagerPrivate *d;
+
+ void updateScript(QAxScript*);
+ QAxScript *scriptForFunction(const QString &function) const;
+};
+
+
+// QAxScript inlines
+
+inline QString QAxScript::scriptCode() const
+{
+ return script_code;
+}
+
+inline QString QAxScript::scriptName() const
+{
+ return script_name;
+}
+
+inline QAxScriptEngine *QAxScript::scriptEngine() const
+{
+ return script_engine;
+}
+
+// QAxScriptEngine inlines
+
+inline bool QAxScriptEngine::isValid() const
+{
+ return engine != 0;
+}
+
+inline QString QAxScriptEngine::scriptLanguage() const
+{
+ return script_language;
+}
+
+// QAxScriptManager inlines
+
+extern QAxBase *qax_create_object_wrapper(QObject*);
+
+inline void QAxScriptManager::addObject(QObject *object)
+{
+ QAxBase *wrapper = qax_create_object_wrapper(object);
+ if (!wrapper) {
+ qWarning("QAxScriptMananger::addObject: Class %s not exposed through the QAxFactory",
+ object->metaObject()->className());
+ Q_ASSERT(wrapper);
+ }
+ addObject(wrapper);
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXSCRIPT_H
diff --git a/src/activeqt/container/qaxscriptwrapper.cpp b/src/activeqt/container/qaxscriptwrapper.cpp
new file mode 100644
index 0000000..e2f3109
--- /dev/null
+++ b/src/activeqt/container/qaxscriptwrapper.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxobject.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <ActiveQt/qaxfactory.h>
+
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+QAxBase *qax_create_object_wrapper(QObject *object)
+{
+ IDispatch *dispatch = 0;
+ QAxObject *wrapper = 0;
+ qAxFactory()->createObjectWrapper(object, &dispatch);
+ if (dispatch) {
+ wrapper = new QAxObject(dispatch, object);
+ wrapper->setObjectName(object->objectName());
+ dispatch->Release();
+ }
+ return wrapper;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/container/qaxselect.cpp b/src/activeqt/container/qaxselect.cpp
new file mode 100644
index 0000000..335b73f
--- /dev/null
+++ b/src/activeqt/container/qaxselect.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxselect.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class ControlList : public QAbstractListModel
+{
+public:
+ ControlList(QObject *parent=0)
+ : QAbstractListModel(parent)
+ {
+ HKEY classes_key;
+ RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &classes_key);
+ if (!classes_key)
+ return;
+
+ DWORD index = 0;
+ LONG result = 0;
+ wchar_t buffer[256];
+ DWORD szBuffer = sizeof(buffer) / sizeof(wchar_t);
+ FILETIME ft;
+ do {
+ result = RegEnumKeyEx(classes_key, index, buffer, &szBuffer, 0, 0, 0, &ft);
+ szBuffer = sizeof(buffer) / sizeof(wchar_t);
+ if (result == ERROR_SUCCESS) {
+ HKEY sub_key;
+ QString clsid = QString::fromWCharArray(buffer);
+ result = RegOpenKeyEx(classes_key, reinterpret_cast<const wchar_t *>(QString(clsid + "\\Control").utf16()), 0, KEY_READ, &sub_key);
+ if (result == ERROR_SUCCESS) {
+ RegCloseKey(sub_key);
+ RegistryQueryValue(classes_key, buffer, (LPBYTE)buffer, &szBuffer);
+ QString name = QString::fromWCharArray(buffer);
+
+ controls << name;
+ clsids.insert(name, clsid);
+ }
+ result = ERROR_SUCCESS;
+ }
+ szBuffer = sizeof(buffer) / sizeof(wchar_t);
+ ++index;
+ } while (result == ERROR_SUCCESS);
+ RegCloseKey(classes_key);
+ controls.sort();
+ }
+
+ LONG RegistryQueryValue(HKEY hKey, LPCWSTR lpSubKey, LPBYTE lpData, LPDWORD lpcbData)
+ {
+ LONG ret = ERROR_FILE_NOT_FOUND;
+ HKEY hSubKey = NULL;
+ RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &hSubKey);
+ if (hSubKey) {
+ ret = RegQueryValueEx(hSubKey, 0, 0, 0, lpData, lpcbData);
+ RegCloseKey(hSubKey);
+ }
+ return ret;
+ }
+
+ int rowCount(const QModelIndex & = QModelIndex()) const { return controls.count(); }
+ QVariant data(const QModelIndex &index, int role) const;
+
+private:
+ QStringList controls;
+ QMap<QString, QString> clsids;
+};
+
+QVariant ControlList::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole)
+ return controls.at(index.row());
+ if (role == Qt::UserRole)
+ return clsids.value(controls.at(index.row()));
+
+ return QVariant();
+}
+
+QAxSelect::QAxSelect(QWidget *parent, Qt::WindowFlags f)
+: QDialog(parent, f)
+{
+#ifndef QT_NO_CURSOR
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+#endif
+
+ setupUi(this);
+ ActiveXList->setModel(new ControlList(this));
+ connect(ActiveXList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ this, SLOT(on_ActiveXList_clicked(QModelIndex)));
+#ifndef QT_NO_CURSOR
+ QApplication::restoreOverrideCursor();
+#endif
+ ActiveXList->setFocus();
+
+ connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+}
+
+void QAxSelect::on_ActiveXList_clicked(const QModelIndex &index)
+{
+ QVariant clsid = ActiveXList->model()->data(index, Qt::UserRole);
+ ActiveX->setText(clsid.toString());
+}
+
+void QAxSelect::on_ActiveXList_doubleClicked(const QModelIndex &index)
+{
+ QVariant clsid = ActiveXList->model()->data(index, Qt::UserRole);
+ ActiveX->setText(clsid.toString());
+
+ accept();
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/container/qaxselect.h b/src/activeqt/container/qaxselect.h
new file mode 100644
index 0000000..063d87e
--- /dev/null
+++ b/src/activeqt/container/qaxselect.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXSELECT_H
+#define QAXSELECT_H
+
+#include <QtGui/qdialog.h>
+
+#ifndef QT_NO_WIN_ACTIVEQT
+#include "ui_qaxselect.h"
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+class QAxSelect : public QDialog, private Ui::QAxSelect
+{
+ Q_OBJECT
+public:
+ QAxSelect(QWidget *parent = 0, Qt::WindowFlags f = 0);
+
+ QString clsid() const { return ActiveX->text(); }
+
+private Q_SLOTS:
+ void on_ActiveXList_clicked(const QModelIndex &index);
+ void on_ActiveXList_doubleClicked(const QModelIndex &index);
+};
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXSELECT_H
diff --git a/src/activeqt/container/qaxselect.ui b/src/activeqt/container/qaxselect.ui
new file mode 100644
index 0000000..b82a543
--- /dev/null
+++ b/src/activeqt/container/qaxselect.ui
@@ -0,0 +1,174 @@
+<ui version="4.0" stdsetdef="1" >
+ <class>QAxSelect</class>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+*********************************************************************</comment>
+ <widget class="QDialog" name="QAxSelect" >
+ <property name="objectName" >
+ <string notr="true" >QAxSelect</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>439</width>
+ <height>326</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Select ActiveX Control</string>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="2" row="0" column="1" colspan="1" >
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonOk" >
+ <property name="objectName" >
+ <string notr="true" >buttonOk</string>
+ </property>
+ <property name="text" >
+ <string>OK</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonCancel" >
+ <property name="objectName" >
+ <string notr="true" >buttonCancel</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="Spacer2" >
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="sizeType" >
+ <enum>Expanding</enum>
+ </property>
+ <property name="orientation" >
+ <enum>Vertical</enum>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QListView" name="ActiveXList" >
+ <property name="objectName" >
+ <string notr="true" >ActiveXList</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="objectName" >
+ <string notr="true" >TextLabel1</string>
+ </property>
+ <property name="text" >
+ <string>COM &amp;Object:</string>
+ </property>
+ <property name="buddy" stdset="0" >
+ <cstring>ActiveX</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="ActiveX" >
+ <property name="objectName" >
+ <string notr="true" >ActiveX</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <includes>
+ <include location="local" >qaxwidget.h</include>
+ </includes>
+</ui>
diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp
new file mode 100644
index 0000000..f69ef95
--- /dev/null
+++ b/src/activeqt/container/qaxwidget.cpp
@@ -0,0 +1,2257 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxwidget.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <ActiveQt/qaxaggregated.h>
+
+#include <qabstracteventdispatcher.h>
+#include <qapplication.h>
+#include <private/qapplication_p.h>
+#include <qdockwidget.h>
+#include <qevent.h>
+#include <qlayout.h>
+#include <qmainwindow.h>
+#include <qmenu.h>
+#include <qmenubar.h>
+#include <qmetaobject.h>
+#include <qpainter.h>
+#include <qpointer.h>
+#include <qregexp.h>
+#include <quuid.h>
+#include <qwhatsthis.h>
+
+#include <windowsx.h>
+#include <ocidl.h>
+#include <olectl.h>
+#include <docobj.h>
+
+// #define QAX_DEBUG
+
+#ifdef QAX_DEBUG
+#define AX_DEBUG(x) qDebug(#x);
+#else
+#define AX_DEBUG(x);
+#endif
+
+// #define QAX_SUPPORT_WINDOWLESS
+// #define QAX_SUPPORT_BORDERSPACE
+
+// missing interface from win32api
+#if defined(Q_CC_GNU) && !defined(__MINGW64_VERSION_MAJOR)
+ DECLARE_INTERFACE_(IOleInPlaceObjectWindowless,IOleInPlaceObject)
+ {
+ STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD(GetWindow)(THIS_ HWND*) PURE;
+ STDMETHOD(ContextSensitiveHelp)(THIS_ BOOL) PURE;
+ STDMETHOD(InPlaceDeactivate)(THIS) PURE;
+ STDMETHOD(UIDeactivate)(THIS) PURE;
+ STDMETHOD(SetObjectRects)(THIS_ LPCRECT,LPCRECT) PURE;
+ STDMETHOD(ReactivateAndUndo)(THIS) PURE;
+ STDMETHOD(OnWindowMessage)(THIS_ UINT, WPARAM, LPARAM, LRESULT*) PURE;
+ STDMETHOD(GetDropTarget)(THIS_ IDropTarget**) PURE;
+ };
+#endif
+
+#include "../shared/qaxtypes.h"
+
+QT_BEGIN_NAMESPACE
+
+/* \class QAxHostWidget
+ \brief The QAxHostWidget class is the actual container widget.
+
+ \internal
+*/
+class QAxHostWidget : public QWidget
+{
+ friend class QAxClientSite;
+public:
+ Q_OBJECT_CHECK
+ QAxHostWidget(QWidget *parent, QAxClientSite *ax);
+ ~QAxHostWidget();
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ int qt_metacall(QMetaObject::Call, int isignal, void **argv);
+ void* qt_metacast(const char *clname);
+
+ inline QAxClientSite *clientSite() const
+ {
+ return axhost;
+ }
+
+protected:
+ bool winEvent(MSG *msg, long *result);
+ bool event(QEvent *e);
+ bool eventFilter(QObject *o, QEvent *e);
+ void resizeEvent(QResizeEvent *e);
+ void focusInEvent(QFocusEvent *e);
+ void focusOutEvent(QFocusEvent *e);
+ void paintEvent(QPaintEvent *e);
+ void showEvent(QShowEvent *e);
+ QPaintEngine* paintEngine() const
+ {
+ return 0;
+ }
+
+private:
+ void resizeObject();
+
+ int setFocusTimer;
+ bool hasFocus;
+ QAxClientSite *axhost;
+};
+
+/* \class QAxClientSite
+ \brief The QAxClientSite class implements the client site interfaces.
+
+ \internal
+*/
+class QAxClientSite : public IDispatch,
+ public IOleClientSite,
+ public IOleControlSite,
+#ifdef QAX_SUPPORT_WINDOWLESS
+ public IOleInPlaceSiteWindowless,
+#else
+ public IOleInPlaceSite,
+#endif
+ public IOleInPlaceFrame,
+ public IOleDocumentSite,
+ public IAdviseSink
+{
+ friend class QAxHostWidget;
+public:
+ QAxClientSite(QAxWidget *c);
+ virtual ~QAxClientSite();
+
+ bool activateObject(bool initialized, const QByteArray &data);
+
+ void releaseAll();
+ void deactivate();
+ inline void reset(QWidget *p)
+ {
+ if (widget == p)
+ widget = 0;
+ else if (host == p)
+ host = 0;
+ }
+
+ inline IOleInPlaceActiveObject *inPlaceObject() const
+ {
+ return m_spInPlaceActiveObject;
+ }
+
+ inline HRESULT doVerb(LONG index)
+ {
+ if (!m_spOleObject)
+ return E_NOTIMPL;
+ if (!host)
+ return OLE_E_NOT_INPLACEACTIVE;
+
+ RECT rcPos = { host->x(), host->y(), host->x()+host->width(), host->y()+host->height() };
+ return m_spOleObject->DoVerb(index, 0, this, 0, host->winId(), &rcPos);
+ }
+
+ // IUnknown
+ unsigned long WINAPI AddRef();
+ unsigned long WINAPI Release();
+ STDMETHOD(QueryInterface)(REFIID iid, void **iface);
+
+ // IDispatch
+ HRESULT __stdcall GetTypeInfoCount(unsigned int *) { return E_NOTIMPL; }
+ HRESULT __stdcall GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_NOTIMPL; }
+ HRESULT __stdcall GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *) { return E_NOTIMPL; }
+ HRESULT __stdcall Invoke(DISPID dispIdMember,
+ REFIID riid,
+ LCID lcid,
+ WORD wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *puArgErr);
+ void emitAmbientPropertyChange(DISPID dispid);
+
+ // IOleClientSite
+ STDMETHOD(SaveObject)();
+ STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
+ STDMETHOD(GetContainer)(LPOLECONTAINER FAR* ppContainer);
+ STDMETHOD(ShowObject)();
+ STDMETHOD(OnShowWindow)(BOOL fShow);
+ STDMETHOD(RequestNewObjectLayout)();
+
+ // IOleControlSite
+ STDMETHOD(OnControlInfoChanged)();
+ STDMETHOD(LockInPlaceActive)(BOOL fLock);
+ STDMETHOD(GetExtendedControl)(IDispatch** ppDisp);
+ STDMETHOD(TransformCoords)(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags);
+ STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, DWORD grfModifiers);
+ STDMETHOD(OnFocus)(BOOL fGotFocus);
+ STDMETHOD(ShowPropertyFrame)();
+
+ // IOleWindow
+ STDMETHOD(GetWindow)(HWND *phwnd);
+ STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
+
+ // IOleInPlaceSite
+ STDMETHOD(CanInPlaceActivate)();
+ STDMETHOD(OnInPlaceActivate)();
+ STDMETHOD(OnUIActivate)();
+ STDMETHOD(GetWindowContext)(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
+ STDMETHOD(Scroll)(SIZE scrollExtant);
+ STDMETHOD(OnUIDeactivate)(BOOL fUndoable);
+ STDMETHOD(OnInPlaceDeactivate)();
+ STDMETHOD(DiscardUndoState)();
+ STDMETHOD(DeactivateAndUndo)();
+ STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect);
+
+#ifdef QAX_SUPPORT_WINDOWLESS
+// IOleInPlaceSiteEx ###
+ STDMETHOD(OnInPlaceActivateEx)(BOOL* /*pfNoRedraw*/, DWORD /*dwFlags*/)
+ {
+ return S_OK;
+ }
+ STDMETHOD(OnInPlaceDeactivateEx)(BOOL /*fNoRedraw*/)
+ {
+ return S_OK;
+ }
+ STDMETHOD(RequestUIActivate)()
+ {
+ return S_OK;
+ }
+
+// IOleInPlaceSiteWindowless ###
+ STDMETHOD(CanWindowlessActivate)()
+ {
+ return S_OK;
+ }
+ STDMETHOD(GetCapture)()
+ {
+ return S_FALSE;
+ }
+ STDMETHOD(SetCapture)(BOOL /*fCapture*/)
+ {
+ return S_FALSE;
+ }
+ STDMETHOD(GetFocus)()
+ {
+ return S_FALSE;
+ }
+ STDMETHOD(SetFocus)(BOOL /*fCapture*/)
+ {
+ return S_FALSE;
+ }
+ STDMETHOD(GetDC)(LPCRECT /*pRect*/, DWORD /*grfFlags*/, HDC *phDC)
+ {
+ *phDC = 0;
+ return S_OK;
+ }
+ STDMETHOD(ReleaseDC)(HDC hDC)
+ {
+ ::ReleaseDC(widget->winId(), hDC);
+ return S_OK;
+ }
+ STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase)
+ {
+ ::InvalidateRect(host->winId(), pRect, fErase);
+ return S_OK;
+ }
+ STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase)
+ {
+ ::InvalidateRgn(host->winId(), hRGN, fErase);
+ return S_OK;
+ }
+ STDMETHOD(ScrollRect)(int /*dx*/, int /*dy*/, LPCRECT /*pRectScroll*/, LPCRECT /*pRectClip*/)
+ {
+ return S_OK;
+ }
+ STDMETHOD(AdjustRect)(LPRECT /*prc*/)
+ {
+ return S_OK;
+ }
+#ifdef Q_CC_GNU // signature incorrect in win32api
+ STDMETHOD(AdjustRect)(LPCRECT /*prc*/)
+ {
+ RECT rect;
+ return AdjustRect(&rect);
+ }
+#endif
+
+ STDMETHOD(OnDefWindowMessage)(UINT /*msg*/, WPARAM /*wPara*/, LPARAM /*lParam*/, LRESULT* /*plResult*/)
+ {
+ return S_FALSE;
+ }
+#endif
+
+ // IOleInPlaceFrame
+ STDMETHOD(InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths));
+ STDMETHOD(SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject));
+ STDMETHOD(RemoveMenus(HMENU hmenuShared));
+ STDMETHOD(SetStatusText(LPCOLESTR pszStatusText));
+ STDMETHOD(EnableModeless(BOOL fEnable));
+ STDMETHOD(TranslateAccelerator(LPMSG lpMsg, WORD grfModifiers));
+
+ // IOleInPlaceUIWindow
+ STDMETHOD(GetBorder(LPRECT lprectBorder));
+ STDMETHOD(RequestBorderSpace(LPCBORDERWIDTHS pborderwidths));
+ STDMETHOD(SetBorderSpace(LPCBORDERWIDTHS pborderwidths));
+ STDMETHOD(SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName));
+
+ // IOleDocumentSite
+ STDMETHOD(ActivateMe(IOleDocumentView *pViewToActivate));
+
+ // IAdviseSink
+ STDMETHOD_(void, OnDataChange)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pStgmed*/)
+ {
+ AX_DEBUG(QAxClientSite::OnDataChange);
+ }
+ STDMETHOD_(void, OnViewChange)(DWORD /*dwAspect*/, LONG /*lindex*/)
+ {
+ AX_DEBUG(QAxClientSite::OnViewChange);
+ }
+ STDMETHOD_(void, OnRename)(IMoniker* /*pmk*/)
+ {
+ }
+ STDMETHOD_(void, OnSave)()
+ {
+ }
+ STDMETHOD_(void, OnClose)()
+ {
+ }
+
+ QSize sizeHint() const { return sizehint; }
+ QSize minimumSizeHint() const;
+ inline void resize(QSize sz) { if (host) host->resize(sz); }
+
+ bool translateKeyEvent(int message, int keycode) const
+ {
+ if (!widget)
+ return false;
+ return widget->translateKeyEvent(message, keycode);
+ }
+
+ int qt_metacall(QMetaObject::Call, int isignal, void **argv);
+ void windowActivationChange();
+
+ bool eventTranslated : 1;
+
+private:
+#if !defined(Q_WS_WINCE)
+ struct OleMenuItem {
+ OleMenuItem(HMENU hm = 0, int ID = 0, QMenu *menu = 0)
+ : hMenu(hm), id(ID), subMenu(menu)
+ {}
+ HMENU hMenu;
+ int id;
+ QMenu *subMenu;
+ };
+ QMenu *generatePopup(HMENU subMenu, QWidget *parent);
+#endif
+
+ IOleObject *m_spOleObject;
+ IOleControl *m_spOleControl;
+ IOleInPlaceObjectWindowless *m_spInPlaceObject;
+ IOleInPlaceActiveObject *m_spInPlaceActiveObject;
+ IOleDocumentView *m_spActiveView;
+
+ QAxAggregated *aggregatedObject;
+
+ bool inPlaceObjectWindowless :1;
+ bool inPlaceModelessEnabled :1;
+ bool canHostDocument : 1;
+
+ DWORD m_dwOleObject;
+#if !defined(Q_WS_WINCE)
+ HWND m_menuOwner;
+#endif
+ CONTROLINFO control_info;
+
+ QSize sizehint;
+ unsigned long ref;
+ QAxWidget *widget;
+ QAxHostWidget *host;
+#if !defined(Q_WS_WINCE)
+ QPointer<QMenuBar> menuBar;
+ QMap<QAction*,OleMenuItem> menuItemMap;
+#endif
+};
+
+static const ushort mouseTbl[] = {
+ WM_MOUSEMOVE, QEvent::MouseMove, 0,
+ WM_LBUTTONDOWN, QEvent::MouseButtonPress, Qt::LeftButton,
+ WM_LBUTTONUP, QEvent::MouseButtonRelease, Qt::LeftButton,
+ WM_LBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::LeftButton,
+ WM_RBUTTONDOWN, QEvent::MouseButtonPress, Qt::RightButton,
+ WM_RBUTTONUP, QEvent::MouseButtonRelease, Qt::RightButton,
+ WM_RBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::RightButton,
+ WM_MBUTTONDOWN, QEvent::MouseButtonPress, Qt::MidButton,
+ WM_MBUTTONUP, QEvent::MouseButtonRelease, Qt::MidButton,
+ WM_MBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::MidButton,
+ 0, 0, 0
+};
+
+static Qt::MouseButtons translateMouseButtonState(int s)
+{
+ Qt::MouseButtons bst = 0;
+ if (s & MK_LBUTTON)
+ bst |= Qt::LeftButton;
+ if (s & MK_MBUTTON)
+ bst |= Qt::MidButton;
+ if (s & MK_RBUTTON)
+ bst |= Qt::RightButton;
+
+ return bst;
+}
+
+static Qt::KeyboardModifiers translateModifierState(int s)
+{
+ Qt::KeyboardModifiers bst = 0;
+ if (s & MK_SHIFT)
+ bst |= Qt::ShiftModifier;
+ if (s & MK_CONTROL)
+ bst |= Qt::ControlModifier;
+ if (GetKeyState(VK_MENU) < 0)
+ bst |= Qt::AltModifier;
+
+ return bst;
+}
+
+static QAbstractEventDispatcher::EventFilter previous_filter = 0;
+#if QT_VERSION >= 0x050000
+#error "Fix QAbstractEventDispatcher::setEventFilter"
+#endif
+#if defined(Q_WS_WINCE)
+static int filter_ref = 0;
+#else
+static const wchar_t *qaxatom = L"QAxContainer4_Atom";
+#endif
+
+// The filter procedure listening to user interaction on the control
+bool axc_FilterProc(void *m)
+{
+ MSG *msg = (MSG*)m;
+ const uint message = msg->message;
+ if ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) || (message >= WM_KEYFIRST && message <= WM_KEYLAST)) {
+ HWND hwnd = msg->hwnd;
+ QAxWidget *ax = 0;
+ QAxHostWidget *host = 0;
+ while (!host && hwnd) {
+ QWidget *widget = QWidget::find(hwnd);
+ if (widget && widget->inherits("QAxHostWidget"))
+ host = qobject_cast<QAxHostWidget*>(widget);
+ hwnd = ::GetParent(hwnd);
+ }
+ if (host)
+ ax = qobject_cast<QAxWidget*>(host->parentWidget());
+ if (ax && msg->hwnd != host->winId()) {
+ if (message >= WM_KEYFIRST && message <= WM_KEYLAST) {
+ QAxClientSite *site = host->clientSite();
+ site->eventTranslated = true; // reset in QAxClientSite::TranslateAccelerator
+ HRESULT hres = S_FALSE;
+ if (site && site->inPlaceObject() && site->translateKeyEvent(msg->message, msg->wParam))
+ hres = site->inPlaceObject()->TranslateAccelerator(msg);
+ // if the object calls our TranslateAccelerator implementation, then continue with normal event processing
+ // otherwise the object has translated the accelerator, and the event should be stopped
+ if (site->eventTranslated && hres == S_OK)
+ return true;
+ } else {
+ int i;
+ for (i = 0; (UINT)mouseTbl[i] != message && mouseTbl[i]; i += 3)
+ ;
+
+ if (mouseTbl[i]) {
+ QEvent::Type type = (QEvent::Type)mouseTbl[++i];
+ int button = mouseTbl[++i];
+ if (type != QEvent::MouseMove || ax->hasMouseTracking() || button) {
+ if (type == QEvent::MouseMove)
+ button = 0;
+
+ DWORD ol_pos = GetMessagePos();
+ QPoint gpos(GET_X_LPARAM(ol_pos), GET_Y_LPARAM(ol_pos));
+ QPoint pos = ax->mapFromGlobal(gpos);
+
+ QMouseEvent e(type, pos, gpos, (Qt::MouseButton)button,
+ translateMouseButtonState(msg->wParam),
+ translateModifierState(msg->wParam));
+ QApplication::sendEvent(ax, &e);
+ }
+ }
+ }
+ }
+ }
+
+ if (previous_filter)
+ return previous_filter(m);
+
+ return false;
+}
+
+QAxClientSite::QAxClientSite(QAxWidget *c)
+: eventTranslated(true), ref(1), widget(c), host(0)
+{
+ aggregatedObject = widget->createAggregate();
+ if (aggregatedObject) {
+ aggregatedObject->controlling_unknown = (IUnknown*)(IDispatch*)this;
+ aggregatedObject->the_object = c;
+ }
+
+ m_spOleObject = 0;
+ m_spOleControl = 0;
+ m_spInPlaceObject = 0;
+ m_spInPlaceActiveObject = 0;
+ m_spActiveView = 0;
+
+ inPlaceObjectWindowless = false;
+ inPlaceModelessEnabled = true;
+ canHostDocument = false;
+
+ m_dwOleObject = 0;
+#if !defined(Q_WS_WINCE)
+ m_menuOwner = 0;
+ menuBar = 0;
+#endif
+ memset(&control_info, 0, sizeof(control_info));
+}
+
+bool QAxClientSite::activateObject(bool initialized, const QByteArray &data)
+{
+ if (!host)
+ host = new QAxHostWidget(widget, this);
+
+ bool showHost = false;
+ HRESULT hr = S_OK;
+ if (!m_spOleObject)
+ widget->queryInterface(IID_IOleObject, (void**)&m_spOleObject);
+ if (m_spOleObject) {
+ DWORD dwMiscStatus = 0;
+ m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
+
+#if !defined(Q_OS_WINCE)
+ IOleDocument *document = 0;
+ m_spOleObject->QueryInterface(IID_IOleDocument, (void**)&document);
+ if (document) {
+ IPersistStorage *persistStorage = 0;
+ document->QueryInterface(IID_IPersistStorage, (void**)&persistStorage);
+ if (persistStorage) {
+ // try to activate as document server
+ IStorage *storage = 0;
+ ILockBytes * bytes = 0;
+ HRESULT hres = ::CreateILockBytesOnHGlobal(0, TRUE, &bytes);
+ hres = ::StgCreateDocfileOnILockBytes(bytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &storage);
+
+ persistStorage->InitNew(storage);
+ persistStorage->Release();
+ canHostDocument = true;
+ storage->Release();
+ bytes->Release();
+
+ m_spOleObject->SetClientSite(this);
+ OleRun(m_spOleObject);
+ }
+ document->Release();
+ }
+#endif
+
+ if (!canHostDocument) {
+ // activate as control
+ if(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
+ m_spOleObject->SetClientSite(this);
+
+ if (!initialized) {
+ IPersistStreamInit *spPSI = 0;
+ m_spOleObject->QueryInterface(IID_IPersistStreamInit, (void**)&spPSI);
+ if (spPSI) {
+ if (data.length()) {
+ IStream *pStream = 0;
+ HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, data.length());
+ if (hGlobal) {
+ BYTE *pStByte = (BYTE *)GlobalLock(hGlobal);
+ if (pStByte)
+ memcpy(pStByte, data.data(), data.length());
+ GlobalUnlock(hGlobal);
+ if (SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream))) {
+ spPSI->Load(pStream);
+ pStream->Release();
+ }
+ GlobalFree(hGlobal);
+ }
+ } else {
+ spPSI->InitNew();
+ }
+ spPSI->Release();
+ } else if (data.length()) { //try initializing using a IPersistStorage
+ IPersistStorage *spPS = 0;
+ m_spOleObject->QueryInterface( IID_IPersistStorage, (void**)&spPS );
+ if (spPS) {
+ HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, data.length());
+ if (hGlobal) {
+#if !defined(Q_OS_WINCE)
+ BYTE* pbData = (BYTE*)GlobalLock(hGlobal);
+ if (pbData)
+ memcpy(pbData, data.data(), data.length());
+ GlobalUnlock(hGlobal);
+ // open an IStorage on the data and pass it to Load
+ LPLOCKBYTES pLockBytes = 0;
+ if (SUCCEEDED(CreateILockBytesOnHGlobal(hGlobal, TRUE, &pLockBytes))) {
+ LPSTORAGE pStorage = 0;
+ if (SUCCEEDED(StgOpenStorageOnILockBytes(pLockBytes, 0,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStorage))) {
+ spPS->Load(pStorage);
+ pStorage->Release();
+ }
+ pLockBytes->Release();
+ }
+ GlobalFree(hGlobal);
+#endif
+ }
+ spPS->Release();
+ }
+ }
+ }
+
+ if(!(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
+ m_spOleObject->SetClientSite(this);
+ }
+
+ IViewObject *spViewObject = 0;
+ m_spOleObject->QueryInterface(IID_IViewObject, (void**) &spViewObject);
+
+ m_spOleObject->Advise(this, &m_dwOleObject);
+ IAdviseSink *spAdviseSink = 0;
+ QueryInterface(IID_IAdviseSink, (void**)&spAdviseSink);
+ if (spAdviseSink && spViewObject) {
+ if (spViewObject)
+ spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);
+ spAdviseSink->Release();
+ }
+ if (spViewObject)
+ spViewObject->Release();
+
+ m_spOleObject->SetHostNames(OLESTR("AXWIN"), 0);
+
+ if (!(dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)) {
+ SIZEL hmSize;
+ hmSize.cx = MAP_PIX_TO_LOGHIM(250, widget->logicalDpiX());
+ hmSize.cy = MAP_PIX_TO_LOGHIM(250, widget->logicalDpiY());
+
+ m_spOleObject->SetExtent(DVASPECT_CONTENT, &hmSize);
+ m_spOleObject->GetExtent(DVASPECT_CONTENT, &hmSize);
+
+ sizehint.setWidth(MAP_LOGHIM_TO_PIX(hmSize.cx, widget->logicalDpiX()));
+ sizehint.setHeight(MAP_LOGHIM_TO_PIX(hmSize.cy, widget->logicalDpiY()));
+ showHost = true;
+ } else {
+ sizehint = QSize(0, 0);
+ host->hide();
+ }
+ if (!(dwMiscStatus & OLEMISC_NOUIACTIVATE)) {
+ host->setFocusPolicy(Qt::StrongFocus);
+ } else {
+ host->setFocusPolicy(Qt::NoFocus);
+ }
+
+ RECT rcPos = { host->x(), host->y(), host->x()+sizehint.width(), host->y()+sizehint.height() };
+
+ hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, (IOleClientSite*)this, 0, host->winId(), &rcPos);
+
+ if (!m_spOleControl)
+ m_spOleObject->QueryInterface(IID_IOleControl, (void**)&m_spOleControl);
+ if (m_spOleControl) {
+ m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR);
+ m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR);
+ m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_FONT);
+ m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
+
+ control_info.cb = sizeof(control_info);
+ m_spOleControl->GetControlInfo(&control_info);
+ }
+
+ BSTR userType;
+ HRESULT result = m_spOleObject->GetUserType(USERCLASSTYPE_SHORT, &userType);
+ if (result == S_OK) {
+ widget->setWindowTitle(QString::fromWCharArray(userType));
+ CoTaskMemFree(userType);
+ }
+ } else {
+ IObjectWithSite *spSite = 0;
+ widget->queryInterface(IID_IObjectWithSite, (void**)&spSite);
+ if (spSite) {
+ spSite->SetSite((IUnknown*)(IDispatch*)this);
+ spSite->Release();
+ }
+ }
+
+ host->resize(widget->size());
+ if (showHost)
+ host->show();
+
+ if (host->focusPolicy() != Qt::NoFocus) {
+ widget->setFocusProxy(host);
+ widget->setFocusPolicy(host->focusPolicy());
+ }
+
+ return true;
+}
+
+QAxClientSite::~QAxClientSite()
+{
+ if (host) {
+ host->axhost = 0;
+ }
+
+ if (aggregatedObject)
+ aggregatedObject->the_object = 0;
+ delete aggregatedObject;
+ delete host;
+}
+
+void QAxClientSite::releaseAll()
+{
+ if (m_spOleObject) {
+ m_spOleObject->SetClientSite(0);
+ m_spOleObject->Unadvise(m_dwOleObject);
+ m_spOleObject->Release();
+ }
+ m_spOleObject = 0;
+ if (m_spOleControl) m_spOleControl->Release();
+ m_spOleControl = 0;
+ if (m_spInPlaceObject) m_spInPlaceObject->Release();
+ m_spInPlaceObject = 0;
+ if (m_spInPlaceActiveObject) m_spInPlaceActiveObject->Release();
+ m_spInPlaceActiveObject = 0;
+
+ inPlaceObjectWindowless = false;
+}
+
+void QAxClientSite::deactivate()
+{
+ if (m_spInPlaceObject) m_spInPlaceObject->InPlaceDeactivate();
+ // if this assertion fails the control didn't call OnInPlaceDeactivate
+ Q_ASSERT(m_spInPlaceObject == 0);
+}
+
+//**** IUnknown
+unsigned long WINAPI QAxClientSite::AddRef()
+{
+ return ++ref;
+}
+
+unsigned long WINAPI QAxClientSite::Release()
+{
+ if (!--ref) {
+ delete this;
+ return 0;
+ }
+ return ref;
+}
+
+HRESULT WINAPI QAxClientSite::QueryInterface(REFIID iid, void **iface)
+{
+ *iface = 0;
+
+ if (iid == IID_IUnknown) {
+ *iface = (IUnknown*)(IDispatch*)this;
+ } else {
+ HRESULT res = S_OK;
+ if (aggregatedObject)
+ res = aggregatedObject->queryInterface(iid, iface);
+ if (*iface)
+ return res;
+ }
+
+ if (!(*iface)) {
+ if (iid == IID_IDispatch)
+ *iface = (IDispatch*)this;
+ else if (iid == IID_IOleClientSite)
+ *iface = (IOleClientSite*)this;
+ else if (iid == IID_IOleControlSite)
+ *iface = (IOleControlSite*)this;
+ else if (iid == IID_IOleWindow)
+ *iface = (IOleWindow*)(IOleInPlaceSite*)this;
+ else if (iid == IID_IOleInPlaceSite)
+ *iface = (IOleInPlaceSite*)this;
+#ifdef QAX_SUPPORT_WINDOWLESS
+ else if (iid == IID_IOleInPlaceSiteEx)
+ *iface = (IOleInPlaceSiteEx*)this;
+ else if (iid == IID_IOleInPlaceSiteWindowless)
+ *iface = (IOleInPlaceSiteWindowless*)this;
+#endif
+ else if (iid == IID_IOleInPlaceFrame)
+ *iface = (IOleInPlaceFrame*)this;
+ else if (iid == IID_IOleInPlaceUIWindow)
+ *iface = (IOleInPlaceUIWindow*)this;
+ else if (iid == IID_IOleDocumentSite && canHostDocument)
+ *iface = (IOleDocumentSite*)this;
+ else if (iid == IID_IAdviseSink)
+ *iface = (IAdviseSink*)this;
+ }
+ if (!*iface)
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+}
+
+bool qax_runsInDesignMode = false;
+
+//**** IDispatch
+HRESULT WINAPI QAxClientSite::Invoke(DISPID dispIdMember,
+ REFIID /*riid*/,
+ LCID /*lcid*/,
+ WORD /*wFlags*/,
+ DISPPARAMS * /*pDispParams*/,
+ VARIANT *pVarResult,
+ EXCEPINFO * /*pExcepInfo*/,
+ UINT * /*puArgErr*/)
+{
+ if (!pVarResult)
+ return E_POINTER;
+ if (!widget || !host)
+ return E_UNEXPECTED;
+
+ switch(dispIdMember) {
+ case DISPID_AMBIENT_USERMODE:
+ pVarResult->vt = VT_BOOL;
+ pVarResult->boolVal = !qax_runsInDesignMode;
+ return S_OK;
+
+ case DISPID_AMBIENT_AUTOCLIP:
+ case DISPID_AMBIENT_SUPPORTSMNEMONICS:
+ pVarResult->vt = VT_BOOL;
+ pVarResult->boolVal = true;
+ return S_OK;
+
+ case DISPID_AMBIENT_SHOWHATCHING:
+ case DISPID_AMBIENT_SHOWGRABHANDLES:
+ case DISPID_AMBIENT_DISPLAYASDEFAULT:
+ case DISPID_AMBIENT_MESSAGEREFLECT:
+ pVarResult->vt = VT_BOOL;
+ pVarResult->boolVal = false;
+ return S_OK;
+
+ case DISPID_AMBIENT_DISPLAYNAME:
+ pVarResult->vt = VT_BSTR;
+ pVarResult->bstrVal = QStringToBSTR(widget->windowTitle());
+ return S_OK;
+
+ case DISPID_AMBIENT_FONT:
+ QVariantToVARIANT(widget->font(), *pVarResult);
+ return S_OK;
+
+ case DISPID_AMBIENT_BACKCOLOR:
+ pVarResult->vt = VT_UI4;
+ pVarResult->lVal = QColorToOLEColor(widget->palette().color(widget->backgroundRole()));
+ return S_OK;
+
+ case DISPID_AMBIENT_FORECOLOR:
+ pVarResult->vt = VT_UI4;
+ pVarResult->lVal = QColorToOLEColor(widget->palette().color(widget->foregroundRole()));
+ return S_OK;
+
+ case DISPID_AMBIENT_UIDEAD:
+ pVarResult->vt = VT_BOOL;
+ pVarResult->boolVal = !widget->isEnabled();
+ return S_OK;
+
+ default:
+ break;
+ }
+
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+void QAxClientSite::emitAmbientPropertyChange(DISPID dispid)
+{
+ if (m_spOleControl)
+ m_spOleControl->OnAmbientPropertyChange(dispid);
+}
+
+//**** IOleClientSite
+HRESULT WINAPI QAxClientSite::SaveObject()
+{
+ return E_NOTIMPL;
+}
+
+HRESULT WINAPI QAxClientSite::GetMoniker(DWORD, DWORD, IMoniker **ppmk)
+{
+ if (!ppmk)
+ return E_POINTER;
+
+ *ppmk = 0;
+ return E_NOTIMPL;
+}
+
+HRESULT WINAPI QAxClientSite::GetContainer(LPOLECONTAINER *ppContainer)
+{
+ if (!ppContainer)
+ return E_POINTER;
+
+ *ppContainer = 0;
+ return E_NOINTERFACE;
+}
+
+HRESULT WINAPI QAxClientSite::ShowObject()
+{
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::OnShowWindow(BOOL /*fShow*/)
+{
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::RequestNewObjectLayout()
+{
+ return E_NOTIMPL;
+}
+
+//**** IOleControlSite
+HRESULT WINAPI QAxClientSite::OnControlInfoChanged()
+{
+ if (m_spOleControl)
+ m_spOleControl->GetControlInfo(&control_info);
+
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::LockInPlaceActive(BOOL /*fLock*/)
+{
+ AX_DEBUG(QAxClientSite::LockInPlaceActive);
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::GetExtendedControl(IDispatch** ppDisp)
+{
+ if (!ppDisp)
+ return E_POINTER;
+
+ *ppDisp = 0;
+ return E_NOTIMPL;
+}
+
+HRESULT WINAPI QAxClientSite::TransformCoords(POINTL* /*pPtlHimetric*/, POINTF* /*pPtfContainer*/, DWORD /*dwFlags*/)
+{
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, DWORD /*grfModifiers*/)
+{
+ if (lpMsg->message == WM_KEYDOWN && !lpMsg->wParam)
+ return S_OK;
+
+ bool ActiveQtDetected = false;
+ bool fromInProcServer = false;
+#ifdef GWLP_USERDATA
+ LONG_PTR serverType = GetWindowLongPtr(lpMsg->hwnd, GWLP_USERDATA);
+#else
+ LONG serverType = GetWindowLong(lpMsg->hwnd, GWL_USERDATA);
+#endif
+ if (serverType == QAX_INPROC_SERVER) {
+ ActiveQtDetected = true;
+ fromInProcServer = true;
+ } else if (serverType == QAX_OUTPROC_SERVER) {
+ ActiveQtDetected = true;
+ fromInProcServer = false;
+ }
+
+ eventTranslated = false;
+ if (!ActiveQtDetected || !fromInProcServer) {
+ // if the request is coming from an out-of-proc server or a non ActiveQt server,
+ // we send the message to the host window. This will make sure this key event
+ // comes to Qt for processing.
+ SendMessage(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam);
+ if (ActiveQtDetected && !fromInProcServer) {
+ // ActiveQt based servers will need further processing of the event
+ // (eg. <SPACE> key for a checkbox), so we return false.
+ return S_FALSE;
+ }
+ }
+ // ActiveQt based in-processes-servers will handle the event properly, so
+ // we don't need to send this key event to the host.
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::OnFocus(BOOL bGotFocus)
+{
+ AX_DEBUG(QAxClientSite::OnFocus);
+ if (host) {
+ host->hasFocus = bGotFocus;
+ qApp->removeEventFilter(host);
+ if (bGotFocus)
+ qApp->installEventFilter(host);
+ }
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::ShowPropertyFrame()
+{
+ return E_NOTIMPL;
+}
+
+//**** IOleWindow
+HRESULT WINAPI QAxClientSite::GetWindow(HWND *phwnd)
+{
+ if (!phwnd)
+ return E_POINTER;
+
+ *phwnd = host->winId();
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::ContextSensitiveHelp(BOOL fEnterMode)
+{
+ if (fEnterMode)
+ QWhatsThis::enterWhatsThisMode();
+ else
+ QWhatsThis::leaveWhatsThisMode();
+
+ return S_OK;
+}
+
+//**** IOleInPlaceSite
+HRESULT WINAPI QAxClientSite::CanInPlaceActivate()
+{
+ AX_DEBUG(QAxClientSite::CanInPlaceActivate);
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::OnInPlaceActivate()
+{
+ AX_DEBUG(QAxClientSite::OnInPlaceActivate);
+#if !defined(Q_OS_WINCE)
+ OleLockRunning(m_spOleObject, true, false);
+#endif
+ if (!m_spInPlaceObject) {
+/* ### disabled for now
+ m_spOleObject->QueryInterface(IID_IOleInPlaceObjectWindowless, (void**) &m_spInPlaceObject);
+*/
+ if (m_spInPlaceObject) {
+ inPlaceObjectWindowless = true;
+ } else {
+ inPlaceObjectWindowless = false;
+ m_spOleObject->QueryInterface(IID_IOleInPlaceObject, (void**) &m_spInPlaceObject);
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::OnUIActivate()
+{
+ AX_DEBUG(QAxClientSite::OnUIActivate);
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::GetWindowContext(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ if (!ppFrame || !ppDoc || !lprcPosRect || !lprcClipRect || !lpFrameInfo)
+ return E_POINTER;
+
+ QueryInterface(IID_IOleInPlaceFrame, (void**)ppFrame);
+ QueryInterface(IID_IOleInPlaceUIWindow, (void**)ppDoc);
+
+ ::GetClientRect(host->winId(), lprcPosRect);
+ ::GetClientRect(host->winId(), lprcClipRect);
+
+ lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
+ lpFrameInfo->fMDIApp = false;
+ lpFrameInfo->haccel = 0;
+ lpFrameInfo->cAccelEntries = 0;
+ lpFrameInfo->hwndFrame = widget ? widget->window()->winId() : 0;
+
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::Scroll(SIZE /*scrollExtant*/)
+{
+ return S_FALSE;
+}
+
+HRESULT WINAPI QAxClientSite::OnUIDeactivate(BOOL)
+{
+ AX_DEBUG(QAxClientSite::OnUIDeactivate);
+ if (host && host->hasFocus) {
+ qApp->removeEventFilter(host);
+ host->hasFocus = false;
+ }
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::OnInPlaceDeactivate()
+{
+ AX_DEBUG(QAxClientSite::OnInPlaceDeactivate);
+ if (m_spInPlaceObject)
+ m_spInPlaceObject->Release();
+ m_spInPlaceObject = 0;
+ inPlaceObjectWindowless = false;
+#if !defined(Q_OS_WINCE)
+ OleLockRunning(m_spOleObject, false, false);
+#endif
+
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::DiscardUndoState()
+{
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::DeactivateAndUndo()
+{
+ if (m_spInPlaceObject)
+ m_spInPlaceObject->UIDeactivate();
+
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::OnPosRectChange(LPCRECT /*lprcPosRect*/)
+{
+ AX_DEBUG(QAxClientSite::OnPosRectChange);
+ // ###
+ return S_OK;
+}
+
+//**** IOleInPlaceFrame
+#if defined(Q_WS_WINCE)
+HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
+{
+ return E_NOTIMPL;
+#else
+HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS lpMenuWidths)
+{
+ AX_DEBUG(QAxClientSite::InsertMenus);
+ QMenuBar *mb = menuBar;
+ if (!mb)
+ mb = widget->window()->findChild<QMenuBar*>();
+ if (!mb)
+ return E_NOTIMPL;
+ menuBar = mb;
+
+ QMenu *fileMenu = 0;
+ QMenu *viewMenu = 0;
+ QMenu *windowMenu = 0;
+ QList<QAction*> actions = menuBar->actions();
+ for (int i = 0; i < actions.count(); ++i) {
+ QAction *action = actions.at(i);
+ QString text = action->text().remove(QLatin1Char('&'));
+ if (text == QLatin1String("File")) {
+ fileMenu = action->menu();
+ } else if (text == QLatin1String("View")) {
+ viewMenu = action->menu();
+ } else if (text == QLatin1String("Window")) {
+ windowMenu = action->menu();
+ }
+ }
+ if (fileMenu)
+ lpMenuWidths->width[0] = fileMenu->actions().count();
+ if (viewMenu)
+ lpMenuWidths->width[2] = viewMenu->actions().count();
+ if (windowMenu)
+ lpMenuWidths->width[4] = windowMenu->actions().count();
+
+ return S_OK;
+#endif
+}
+
+static int menuItemEntry(HMENU menu, int index, MENUITEMINFO item, QString &text, QPixmap &/*icon*/)
+{
+ if (item.fType == MFT_STRING && item.cch) {
+ wchar_t *titlebuf = new wchar_t[item.cch + 1];
+ item.dwTypeData = titlebuf;
+ item.cch++;
+ ::GetMenuItemInfo(menu, index, true, &item);
+ text = QString::fromWCharArray(titlebuf);
+ delete [] titlebuf;
+ return MFT_STRING;
+ }
+#if 0
+ else if (item.fType == MFT_BITMAP) {
+ HBITMAP hbm = (HBITMAP)LOWORD(item.hbmpItem);
+ SIZE bmsize;
+ GetBitmapDimensionEx(hbm, &bmsize);
+ QPixmap pixmap(1,1);
+ QSize sz(MAP_LOGHIM_TO_PIX(bmsize.cx, pixmap.logicalDpiX()),
+ MAP_LOGHIM_TO_PIX(bmsize.cy, pixmap.logicalDpiY()));
+
+ pixmap.resize(bmsize.cx, bmsize.cy);
+ if (!pixmap.isNull()) {
+ HDC hdc = ::CreateCompatibleDC(pixmap.handle());
+ ::SelectObject(hdc, hbm);
+ BOOL res = ::BitBlt(pixmap.handle(), 0, 0, pixmap.width(), pixmap.height(), hdc, 0, 0, SRCCOPY);
+ ::DeleteObject(hdc);
+ }
+
+ icon = pixmap;
+ }
+#endif
+ return -1;
+}
+
+#if !defined(Q_OS_WINCE)
+QMenu *QAxClientSite::generatePopup(HMENU subMenu, QWidget *parent)
+{
+ QMenu *popup = 0;
+ int count = GetMenuItemCount(subMenu);
+ if (count)
+ popup = new QMenu(parent);
+ for (int i = 0; i < count; ++i) {
+ MENUITEMINFO item;
+ memset(&item, 0, sizeof(MENUITEMINFO));
+ item.cbSize = sizeof(MENUITEMINFO);
+ item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
+ ::GetMenuItemInfo(subMenu, i, true, &item);
+
+ QAction *action = 0;
+ QMenu *popupMenu = 0;
+ if (item.fType == MFT_SEPARATOR) {
+ action = popup->addSeparator();
+ } else {
+ QString text;
+ QPixmap icon;
+ QKeySequence accel;
+ popupMenu = item.hSubMenu ? generatePopup(item.hSubMenu, popup) : 0;
+ int res = menuItemEntry(subMenu, i, item, text, icon);
+
+ int lastSep = text.lastIndexOf(QRegExp(QLatin1String("[\\s]")));
+ if (lastSep != -1) {
+ QString keyString = text.right(text.length() - lastSep);
+ accel = keyString;
+ if ((int)accel)
+ text = text.left(lastSep);
+ }
+
+ if (popupMenu)
+ popupMenu->setTitle(text);
+
+ switch (res) {
+ case MFT_STRING:
+ if (popupMenu)
+ action = popup->addMenu(popupMenu);
+ else
+ action = popup->addAction(text);
+ break;
+ case MFT_BITMAP:
+ if (popupMenu)
+ action = popup->addMenu(popupMenu);
+ else
+ action = popup->addAction(icon, text);
+ break;
+ }
+
+ if (action) {
+ if (int(accel))
+ action->setShortcut(accel);
+ if (!icon.isNull())
+ action->setIcon(icon);
+ }
+ }
+
+ if (action) {
+ OleMenuItem oleItem(subMenu, item.wID, popupMenu);
+ menuItemMap.insert(action, oleItem);
+ }
+ }
+ return popup;
+}
+#endif
+
+#if defined(Q_OS_WINCE)
+HRESULT WINAPI QAxClientSite::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
+{
+ return E_NOTIMPL;
+#else
+HRESULT WINAPI QAxClientSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
+{
+ AX_DEBUG(QAxClientSite::SetMenu);
+
+ if (hmenuShared) {
+ m_menuOwner = hwndActiveObject;
+ QMenuBar *mb = menuBar;
+ if (!mb)
+ mb = widget->window()->findChild<QMenuBar*>();
+ if (!mb)
+ return E_NOTIMPL;
+ menuBar = mb;
+
+ int count = GetMenuItemCount(hmenuShared);
+ for (int i = 0; i < count; ++i) {
+ MENUITEMINFO item;
+ memset(&item, 0, sizeof(MENUITEMINFO));
+ item.cbSize = sizeof(MENUITEMINFO);
+ item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
+ ::GetMenuItemInfo(hmenuShared, i, true, &item);
+
+ QAction *action = 0;
+ QMenu *popupMenu = 0;
+ if (item.fType == MFT_SEPARATOR) {
+ action = menuBar->addSeparator();
+ } else {
+ QString text;
+ QPixmap icon;
+ popupMenu = item.hSubMenu ? generatePopup(item.hSubMenu, menuBar) : 0;
+ int res = menuItemEntry(hmenuShared, i, item, text, icon);
+
+ if (popupMenu)
+ popupMenu->setTitle(text);
+
+ switch(res) {
+ case MFT_STRING:
+ if (popupMenu)
+ action = menuBar->addMenu(popupMenu);
+ else
+ action = menuBar->addAction(text);
+ break;
+ case MFT_BITMAP:
+ if (popupMenu)
+ action = menuBar->addMenu(popupMenu);
+ else
+ action = menuBar->addAction(text);
+ break;
+ default:
+ break;
+ }
+ if (action && !icon.isNull())
+ action->setIcon(icon);
+ }
+
+ if (action) {
+ OleMenuItem oleItem(hmenuShared, item.wID, popupMenu);
+ menuItemMap.insert(action, oleItem);
+ }
+ }
+ if (count) {
+ const QMetaObject *mbmo = menuBar->metaObject();
+ int index = mbmo->indexOfSignal("triggered(QAction*)");
+ Q_ASSERT(index != -1);
+ menuBar->disconnect(SIGNAL(triggered(QAction*)), host);
+ QMetaObject::connect(menuBar, index, host, index);
+ }
+ } else if (menuBar) {
+ m_menuOwner = 0;
+ QMap<QAction*, OleMenuItem>::Iterator it;
+ for (it = menuItemMap.begin(); it != menuItemMap.end(); ++it) {
+ QAction *action = it.key();
+ delete action;
+ }
+ menuItemMap.clear();
+ }
+
+ OleSetMenuDescriptor(holemenu, widget ? widget->window()->winId() : 0, m_menuOwner, this, m_spInPlaceActiveObject);
+ return S_OK;
+#endif
+}
+
+#if defined(Q_OS_WINCE)
+int QAxClientSite::qt_metacall(QMetaObject::Call /*call*/, int isignal, void ** /*argv*/)
+{
+ return isignal;
+#else
+int QAxClientSite::qt_metacall(QMetaObject::Call call, int isignal, void **argv)
+{
+ if (!m_spOleObject || call != QMetaObject::InvokeMetaMethod || !menuBar)
+ return isignal;
+
+ if (isignal != menuBar->metaObject()->indexOfSignal("triggered(QAction*)"))
+ return isignal;
+
+ QAction *action = *(QAction**)argv[1];
+ // ###
+
+ OleMenuItem oleItem = menuItemMap.value(action);
+ if (oleItem.hMenu)
+ ::PostMessage(m_menuOwner, WM_COMMAND, oleItem.id, 0);
+ return -1;
+#endif
+}
+
+
+HRESULT WINAPI QAxClientSite::RemoveMenus(HMENU /*hmenuShared*/)
+{
+#if defined(Q_OS_WINCE)
+ return E_NOTIMPL;
+#else
+ AX_DEBUG(QAxClientSite::RemoveMenus);
+ QMap<QAction*, OleMenuItem>::Iterator it;
+ for (it = menuItemMap.begin(); it != menuItemMap.end(); ++it) {
+ QAction *action = it.key();
+ action->setVisible(false);
+ delete action;
+ }
+ menuItemMap.clear();
+ return S_OK;
+#endif
+}
+
+HRESULT WINAPI QAxClientSite::SetStatusText(LPCOLESTR pszStatusText)
+{
+ QStatusTipEvent tip(QString::fromWCharArray(pszStatusText));
+ QApplication::sendEvent(widget, &tip);
+ return S_OK;
+}
+
+extern Q_GUI_EXPORT bool qt_win_ignoreNextMouseReleaseEvent;
+
+HRESULT WINAPI QAxClientSite::EnableModeless(BOOL fEnable)
+{
+ EnableWindow(host->window()->winId(), fEnable);
+
+ if (!fEnable) {
+ if (!QApplicationPrivate::isBlockedByModal(host))
+ QApplicationPrivate::enterModal(host);
+ } else {
+ if (QApplicationPrivate::isBlockedByModal(host))
+ QApplicationPrivate::leaveModal(host);
+ }
+ qt_win_ignoreNextMouseReleaseEvent = false;
+ return S_OK;
+}
+
+HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, WORD grfModifiers)
+{
+ return TranslateAccelerator(lpMsg, (DWORD)grfModifiers);
+}
+
+//**** IOleInPlaceUIWindow
+HRESULT WINAPI QAxClientSite::GetBorder(LPRECT lprectBorder)
+{
+#ifndef QAX_SUPPORT_BORDERSPACE
+ Q_UNUSED(lprectBorder);
+ return INPLACE_E_NOTOOLSPACE;
+#else
+ AX_DEBUG(QAxClientSite::GetBorder);
+
+ QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window());
+ if (!mw)
+ return INPLACE_E_NOTOOLSPACE;
+
+ RECT border = { 0,0, 300, 200 };
+ *lprectBorder = border;
+ return S_OK;
+#endif
+}
+
+HRESULT WINAPI QAxClientSite::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
+{
+#ifndef QAX_SUPPORT_BORDERSPACE
+ return INPLACE_E_NOTOOLSPACE;
+#else
+ AX_DEBUG(QAxClientSite::RequestBorderSpace);
+
+ QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window());
+ if (!mw)
+ return INPLACE_E_NOTOOLSPACE;
+
+ return S_OK;
+#endif
+}
+
+HRESULT WINAPI QAxClientSite::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
+{
+#ifndef QAX_SUPPORT_BORDERSPACE
+ Q_UNUSED(pborderwidths);
+ return OLE_E_INVALIDRECT;
+#else
+ AX_DEBUG(QAxClientSite::SetBorderSpace);
+
+ // object has no toolbars and wants container toolbars to remain
+ if (!pborderwidths)
+ return S_OK;
+
+ QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window());
+ if (!mw)
+ return OLE_E_INVALIDRECT;
+
+ bool removeToolBars = !(pborderwidths->left || pborderwidths->top || pborderwidths->right || pborderwidths->bottom);
+
+ // object has toolbars, and wants container to remove toolbars
+ if (removeToolBars) {
+ if (mw) {
+ //### remove our toolbars
+ }
+ }
+
+ if (pborderwidths->left) {
+ QDockWidget *left = new QDockWidget(mw);
+ left->setFixedWidth(pborderwidths->left);
+ mw->addDockWidget(Qt::LeftDockWidgetArea, left);
+ left->show();
+ }
+ if (pborderwidths->top) {
+ QDockWidget *top = new QDockWidget(mw);
+ top->setFixedHeight(pborderwidths->top);
+ mw->addDockWidget(Qt::TopDockWidgetArea, top);
+ top->show();
+ }
+
+ return S_OK;
+#endif
+}
+
+HRESULT WINAPI QAxClientSite::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
+{
+ AX_DEBUG(QAxClientSite::SetActiveObject);
+
+ Q_UNUSED(pszObjName);
+ // we are ignoring the name of the object, as suggested by MSDN documentation
+ // for IOleInPlaceUIWindow::SetActiveObject().
+
+ if (m_spInPlaceActiveObject) {
+ if (!inPlaceModelessEnabled)
+ m_spInPlaceActiveObject->EnableModeless(true);
+ inPlaceModelessEnabled = true;
+ m_spInPlaceActiveObject->Release();
+ }
+
+ m_spInPlaceActiveObject = pActiveObject;
+ if (m_spInPlaceActiveObject)
+ m_spInPlaceActiveObject->AddRef();
+
+ return S_OK;
+}
+
+//**** IOleDocumentSite
+HRESULT WINAPI QAxClientSite::ActivateMe(IOleDocumentView *pViewToActivate)
+{
+ AX_DEBUG(QAxClientSite::ActivateMe);
+
+ if (m_spActiveView)
+ m_spActiveView->Release();
+ m_spActiveView = 0;
+
+ if (!pViewToActivate) {
+ IOleDocument *document = 0;
+ m_spOleObject->QueryInterface(IID_IOleDocument, (void**)&document);
+ if (!document)
+ return E_FAIL;
+
+ document->CreateView(this, 0, 0, &pViewToActivate);
+
+ document->Release();
+ if (!pViewToActivate)
+ return E_OUTOFMEMORY;
+ } else {
+ pViewToActivate->SetInPlaceSite(this);
+ }
+
+ m_spActiveView = pViewToActivate;
+ m_spActiveView->AddRef();
+
+ m_spActiveView->UIActivate(TRUE);
+
+ RECT rect;
+ GetClientRect(widget->winId(), &rect);
+ m_spActiveView->SetRect(&rect);
+ m_spActiveView->Show(TRUE);
+
+ return S_OK;
+}
+
+QSize QAxClientSite::minimumSizeHint() const
+{
+ if (!m_spOleObject)
+ return QSize();
+
+ SIZE sz = { 0, 0 };
+ m_spOleObject->SetExtent(DVASPECT_CONTENT, &sz);
+ HRESULT res = m_spOleObject->GetExtent(DVASPECT_CONTENT, &sz);
+ if (SUCCEEDED(res)) {
+ return QSize(MAP_LOGHIM_TO_PIX(sz.cx, widget->logicalDpiX()),
+ MAP_LOGHIM_TO_PIX(sz.cy, widget->logicalDpiY()));
+ }
+ return QSize();
+}
+
+void QAxClientSite::windowActivationChange()
+{
+ AX_DEBUG(QAxClientSite::windowActivationChange);
+
+ if (m_spInPlaceActiveObject && widget) {
+ QWidget *modal = QApplication::activeModalWidget();
+ if (modal && inPlaceModelessEnabled) {
+ m_spInPlaceActiveObject->EnableModeless(false);
+ inPlaceModelessEnabled = false;
+ } else if (!inPlaceModelessEnabled) {
+ m_spInPlaceActiveObject->EnableModeless(true);
+ inPlaceModelessEnabled = true;
+ }
+ m_spInPlaceActiveObject->OnFrameWindowActivate(widget->isActiveWindow());
+ }
+}
+
+
+//**** QWidget
+
+QAxHostWidget::QAxHostWidget(QWidget *parent, QAxClientSite *ax)
+: QWidget(parent), setFocusTimer(0), hasFocus(false), axhost(ax)
+{
+ setAttribute(Qt::WA_NoBackground);
+ setAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ setAttribute(Qt::WA_PaintOnScreen);
+
+ setObjectName(parent->objectName() + QLatin1String(" - QAxHostWidget"));
+}
+
+QAxHostWidget::~QAxHostWidget()
+{
+ if (axhost)
+ axhost->reset(this);
+}
+
+int QAxHostWidget::qt_metacall(QMetaObject::Call call, int isignal, void **argv)
+{
+ if (axhost)
+ return axhost->qt_metacall(call, isignal, argv);
+ return -1;
+}
+
+void* QAxHostWidget::qt_metacast(const char *clname)
+{
+ if (!clname) return 0;
+ if (!qstrcmp(clname,"QAxHostWidget"))
+ return static_cast<void*>(const_cast< QAxHostWidget*>(this));
+ return QWidget::qt_metacast(clname);
+}
+
+QSize QAxHostWidget::sizeHint() const
+{
+ return axhost ? axhost->sizeHint() : QWidget::sizeHint();
+}
+
+QSize QAxHostWidget::minimumSizeHint() const
+{
+ QSize size;
+ if (axhost)
+ size = axhost->minimumSizeHint();
+ if (size.isValid())
+ return size;
+ return QWidget::minimumSizeHint();
+}
+
+void QAxHostWidget::resizeObject()
+{
+ if (!axhost)
+ return;
+
+ // document server - talk to view?
+ if (axhost->m_spActiveView) {
+ RECT rect;
+ GetClientRect(winId(), &rect);
+ axhost->m_spActiveView->SetRect(&rect);
+
+ return;
+ }
+
+ SIZEL hmSize;
+ hmSize.cx = MAP_PIX_TO_LOGHIM(width(), logicalDpiX());
+ hmSize.cy = MAP_PIX_TO_LOGHIM(height(), logicalDpiY());
+
+ if (axhost->m_spOleObject)
+ axhost->m_spOleObject->SetExtent(DVASPECT_CONTENT, &hmSize);
+ if (axhost->m_spInPlaceObject) {
+ RECT rcPos = { x(), y(), x()+width(), y()+height() };
+ axhost->m_spInPlaceObject->SetObjectRects(&rcPos, &rcPos);
+ }
+}
+
+void QAxHostWidget::resizeEvent(QResizeEvent *)
+{
+ resizeObject();
+}
+
+void QAxHostWidget::showEvent(QShowEvent *)
+{
+ resizeObject();
+}
+
+bool QAxHostWidget::winEvent(MSG *msg, long *result)
+{
+ if (axhost && axhost->inPlaceObjectWindowless) {
+ Q_ASSERT(axhost->m_spInPlaceObject);
+ IOleInPlaceObjectWindowless *windowless = (IOleInPlaceObjectWindowless*)axhost->m_spInPlaceObject;
+ Q_ASSERT(windowless);
+ LRESULT lres;
+ HRESULT hres = windowless->OnWindowMessage(msg->message, msg->wParam, msg->lParam, &lres);
+ if (hres == S_OK)
+ return true;
+ }
+ return QWidget::winEvent(msg, result);
+}
+
+bool QAxHostWidget::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::Timer:
+ if (axhost && ((QTimerEvent*)e)->timerId() == setFocusTimer) {
+ killTimer(setFocusTimer);
+ setFocusTimer = 0;
+ RECT rcPos = { x(), y(), x()+size().width(), y()+size().height() };
+ axhost->m_spOleObject->DoVerb(OLEIVERB_UIACTIVATE, 0, (IOleClientSite*)axhost, 0, winId(), &rcPos);
+ if (axhost->m_spActiveView)
+ axhost->m_spActiveView->UIActivate(TRUE);
+ }
+ break;
+ case QEvent::WindowBlocked:
+ if (IsWindowEnabled(winId())) {
+ EnableWindow(winId(), false);
+ if (axhost && axhost->m_spInPlaceActiveObject) {
+ axhost->inPlaceModelessEnabled = false;
+ axhost->m_spInPlaceActiveObject->EnableModeless(false);
+ }
+ }
+ break;
+ case QEvent::WindowUnblocked:
+ if (!IsWindowEnabled(winId())) {
+ EnableWindow(winId(), true);
+ if (axhost && axhost->m_spInPlaceActiveObject) {
+ axhost->inPlaceModelessEnabled = true;
+ axhost->m_spInPlaceActiveObject->EnableModeless(true);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return QWidget::event(e);
+}
+
+bool QAxHostWidget::eventFilter(QObject *o, QEvent *e)
+{
+ // focus goes to Qt while ActiveX still has it - deactivate
+ QWidget *newFocus = qobject_cast<QWidget*>(o);
+ if (e->type() == QEvent::FocusIn && hasFocus
+ && newFocus && newFocus->window() == window()) {
+ if (axhost && axhost->m_spInPlaceActiveObject && axhost->m_spInPlaceObject)
+ axhost->m_spInPlaceObject->UIDeactivate();
+ qApp->removeEventFilter(this);
+ }
+
+ return QWidget::eventFilter(o, e);
+}
+
+void QAxHostWidget::focusInEvent(QFocusEvent *e)
+{
+ QWidget::focusInEvent(e);
+
+ if (!axhost || !axhost->m_spOleObject)
+ return;
+
+ // this is called by QWidget::setFocus which calls ::SetFocus on "this",
+ // so we have to UIActivate the control after all that had happend.
+ AX_DEBUG(Setting focus on in-place object);
+ setFocusTimer = startTimer(0);
+}
+
+void QAxHostWidget::focusOutEvent(QFocusEvent *e)
+{
+ QWidget::focusOutEvent(e);
+ if (setFocusTimer) {
+ killTimer(setFocusTimer);
+ setFocusTimer = 0;
+ }
+ if (e->reason() == Qt::PopupFocusReason || e->reason() == Qt::MenuBarFocusReason)
+ return;
+
+ if (!axhost || !axhost->m_spInPlaceActiveObject || !axhost->m_spInPlaceObject)
+ return;
+
+ AX_DEBUG(Deactivating in-place object);
+ axhost->m_spInPlaceObject->UIDeactivate();
+}
+
+
+void QAxHostWidget::paintEvent(QPaintEvent*)
+{
+ if (!QPainter::redirected(this))
+ return;
+
+ IViewObject *view = 0;
+ if (axhost)
+ axhost->widget->queryInterface(IID_IViewObject, (void**)&view);
+ if (!view)
+ return;
+
+ // somebody tries to grab us!
+ QPixmap pm(size());
+ pm.fill();
+
+ HBITMAP hBmp = pm.toWinHBITMAP();
+ HDC hBmp_hdc = CreateCompatibleDC(qt_win_display_dc());
+ HGDIOBJ old_hBmp = SelectObject(hBmp_hdc, hBmp);
+
+ RECTL bounds;
+ bounds.left = 0;
+ bounds.right = pm.width();
+ bounds.top = 0;
+ bounds.bottom = pm.height();
+
+ view->Draw(DVASPECT_CONTENT, -1, 0, 0, 0, hBmp_hdc, &bounds, 0, 0 /*fptr*/, 0);
+ view->Release();
+
+ QPainter painter(this);
+ painter.drawPixmap(0, 0, QPixmap::fromWinHBITMAP(hBmp));
+
+ SelectObject(hBmp_hdc, old_hBmp);
+ DeleteObject(hBmp);
+ DeleteDC(hBmp_hdc);
+}
+
+/*!
+ \class QAxWidget
+ \brief The QAxWidget class is a QWidget that wraps an ActiveX control.
+
+ \inmodule QAxContainer
+
+ A QAxWidget can be instantiated as an empty object, with the name
+ of the ActiveX control it should wrap, or with an existing
+ interface pointer to the ActiveX control. The ActiveX control's
+ properties, methods and events which only use QAxBase
+ supported data types, become available as Qt properties,
+ slots and signals. The base class QAxBase provides an API to
+ access the ActiveX directly through the \c IUnknown pointer.
+
+ QAxWidget is a QWidget and can mostly be used as such, e.g. it can be
+ organized in a widget hierarchy and layouts or act as an event filter.
+ Standard widget properties, e.g. \link QWidget::enabled
+ enabled \endlink are supported, but it depends on the ActiveX
+ control to implement support for ambient properties like e.g.
+ palette or font. QAxWidget tries to provide the necessary hints.
+
+ However, you cannot reimplement Qt-specific event handlers like
+ mousePressEvent or keyPressEvent and expect them to be called reliably.
+ The embedded control covers the QAxWidget completely, and usually
+ handles the user interface itself. Use control-specific APIs (i.e. listen
+ to the signals of the control), or use standard COM techniques like
+ window procedure subclassing.
+
+ QAxWidget also inherits most of its ActiveX-related functionality
+ from QAxBase, notably dynamicCall() and querySubObject().
+
+ \warning
+ You can subclass QAxWidget, but you cannot use the \c Q_OBJECT macro
+ in the subclass (the generated moc-file will not compile), so you
+ cannot add further signals, slots or properties. This limitation
+ is due to the metaobject information generated in runtime. To work
+ around this problem, aggregate the QAxWidget as a member of the
+ QObject subclass.
+
+ \sa QAxBase, QAxObject, QAxScript, {ActiveQt Framework}
+*/
+
+/*!
+ 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), container(0)
+{
+}
+
+/*!
+ Creates an QAxWidget widget and initializes the ActiveX control \a c.
+ \a parent and \a f are propagated to the QWidget contructor.
+
+ \sa setControl()
+*/
+QAxWidget::QAxWidget(const QString &c, QWidget *parent, Qt::WindowFlags f)
+: QWidget(parent, f), container(0)
+{
+ setControl(c);
+}
+
+/*!
+ Creates a QAxWidget that wraps the COM object referenced by \a iface.
+ \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), container(0)
+{
+}
+
+/*!
+ Shuts down the ActiveX control and destroys the QAxWidget widget,
+ cleaning up all allocated resources.
+
+ \sa clear()
+*/
+QAxWidget::~QAxWidget()
+{
+ if (container)
+ container->reset(this);
+ clear();
+}
+
+/*!
+ \since 4.2
+
+ Calls QAxBase::initialize(\a ptr), and embeds the control in this
+ widget by calling createHostWindow(false) if successful.
+
+ To initialize the control before it is activated, reimplement this
+ function and add your initialization code before you call
+ createHostWindow(true).
+*/
+bool QAxWidget::initialize(IUnknown **ptr)
+{
+ if (!QAxBase::initialize(ptr))
+ return false;
+
+ return createHostWindow(false); // assume that control is not initialized
+}
+
+/*!
+ Creates the client site for the ActiveX control, and returns true if
+ the control could be embedded successfully, otherwise returns false.
+ If \a initialized is true the control has already been initialized.
+
+ This function is called by initialize(). If you reimplement initialize
+ to customize the actual control instantiation, call this function in your
+ reimplementation to have the control embedded by the default client side.
+ Creates the client site for the ActiveX control, and returns true if
+ the control could be embedded successfully, otherwise returns false.
+*/
+bool QAxWidget::createHostWindow(bool initialized)
+{
+ return createHostWindow(initialized, QByteArray());
+}
+
+/*!
+ \since 4.4
+
+ Creates the client site for the ActiveX control, and returns true if
+ the control could be embedded successfully, otherwise returns false.
+ If \a initialized is false the control will be initialized using the
+ \a data. The control will be initialized through either IPersistStreamInit
+ or IPersistStorage interface.
+
+ If the control needs to be initialized using custom data, call this function
+ in your reimplementation of initialize(). This function is not called by
+ the default implementation of initialize().
+*/
+bool QAxWidget::createHostWindow(bool initialized, const QByteArray &data)
+{
+#ifdef QT3_SUPPORT
+ QApplication::sendPostedEvents(0, QEvent::ChildInserted);
+#endif
+
+ container = new QAxClientSite(this);
+ container->activateObject(initialized, data);
+
+#if !defined(Q_OS_WINCE)
+ ATOM filter_ref = FindAtom(qaxatom);
+#endif
+ if (!filter_ref)
+ previous_filter = QAbstractEventDispatcher::instance()->setEventFilter(axc_FilterProc);
+#if !defined(Q_OS_WINCE)
+ AddAtom(qaxatom);
+#else
+ ++filter_ref;
+#endif
+
+ if (parentWidget())
+ QApplication::postEvent(parentWidget(), new QEvent(QEvent::LayoutRequest));
+
+ return true;
+}
+
+/*!
+ Reimplement this function when you want to implement additional
+ COM interfaces for the client site of the ActiveX control, or when
+ you want to provide alternative implementations of COM interfaces.
+ Return a new object of a QAxAggregated subclass.
+
+ The default implementation returns the null pointer.
+*/
+QAxAggregated *QAxWidget::createAggregate()
+{
+ return 0;
+}
+
+/*!
+ \reimp
+
+ Shuts down the ActiveX control.
+*/
+void QAxWidget::clear()
+{
+ if (isNull())
+ return;
+ if (!control().isEmpty()) {
+#if !defined(Q_OS_WINCE)
+ ATOM filter_ref = FindAtom(qaxatom);
+ if (filter_ref)
+ DeleteAtom(filter_ref);
+ filter_ref = FindAtom(qaxatom);
+ if (!filter_ref) {
+#else
+ if (!filter_ref && !--filter_ref) {
+#endif
+ QAbstractEventDispatcher::instance()->setEventFilter(previous_filter);
+ previous_filter = 0;
+ }
+ }
+
+ if (container)
+ container->deactivate();
+
+ QAxBase::clear();
+ setFocusPolicy(Qt::NoFocus);
+
+ if (container) {
+ container->releaseAll();
+ container->Release();
+ }
+ container = 0;
+}
+
+/*!
+ \since 4.1
+
+ Requests the ActiveX control to perform the action \a verb. The
+ possible verbs are returned by verbs().
+
+ The function returns true if the object could perform the action, otherwise returns false.
+*/
+bool QAxWidget::doVerb(const QString &verb)
+{
+ if (!verbs().contains(verb))
+ return false;
+
+ HRESULT hres = container->doVerb(indexOfVerb(verb));
+
+ return hres == S_OK;
+}
+
+ /*!
+ \fn QObject *QAxWidget::qObject() const
+ \internal
+*/
+
+/*!
+ \internal
+*/
+const QMetaObject *QAxWidget::metaObject() const
+{
+ return QAxBase::metaObject();
+}
+
+/*!
+ \internal
+*/
+const QMetaObject *QAxWidget::parentMetaObject() const
+{
+ return &QWidget::staticMetaObject;
+}
+
+/*!
+ \internal
+*/
+void *QAxWidget::qt_metacast(const char *cname)
+{
+ if (!qstrcmp(cname, "QAxWidget")) return (void*)this;
+ if (!qstrcmp(cname, "QAxBase")) return (QAxBase*)this;
+ return QWidget::qt_metacast(cname);
+}
+
+/*!
+ \internal
+*/
+const char *QAxWidget::className() const
+{
+ return "QAxWidget";
+}
+
+/*!
+ \internal
+*/
+int QAxWidget::qt_metacall(QMetaObject::Call call, int id, void **v)
+{
+ id = QWidget::qt_metacall(call, id, v);
+ if (id < 0)
+ return id;
+ return QAxBase::qt_metacall(call, id, v);
+}
+
+/*!
+ \reimp
+*/
+QSize QAxWidget::sizeHint() const
+{
+ if (container) {
+ QSize sh = container->sizeHint();
+ if (sh.isValid())
+ return sh;
+ }
+
+ return QWidget::sizeHint();
+}
+
+/*!
+ \reimp
+*/
+QSize QAxWidget::minimumSizeHint() const
+{
+ if (container) {
+ QSize sh = container->minimumSizeHint();
+ if (sh.isValid())
+ return sh;
+ }
+
+ return QWidget::minimumSizeHint();
+}
+
+/*!
+ \reimp
+*/
+void QAxWidget::changeEvent(QEvent *e)
+{
+ if (isNull())
+ return;
+
+ switch (e->type()) {
+ case QEvent::EnabledChange:
+ container->emitAmbientPropertyChange(DISPID_AMBIENT_UIDEAD);
+ break;
+ case QEvent::FontChange:
+ container->emitAmbientPropertyChange(DISPID_AMBIENT_FONT);
+ break;
+ case QEvent::PaletteChange:
+ container->emitAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR);
+ container->emitAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR);
+ break;
+ case QEvent::ActivationChange:
+ container->windowActivationChange();
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QAxWidget::resizeEvent(QResizeEvent *)
+{
+ if (container)
+ container->resize(size());
+}
+
+/*!
+ \reimp
+*/
+void QAxWidget::connectNotify(const char *)
+{
+ QAxBase::connectNotify();
+}
+
+
+/*!
+ Reimplement this function to pass certain key events to the
+ ActiveX control. \a message is the Window message identifier
+ specifying the message type (ie. WM_KEYDOWN), and \a keycode is
+ the virtual keycode (ie. VK_TAB).
+
+ If the function returns true the key event is passed on to the
+ ActiveX control, which then either processes the event or passes
+ the event on to Qt.
+
+ If the function returns false the processing of the key event is
+ ignored by ActiveQt, ie. the ActiveX control might handle it or
+ not.
+
+ The default implementation returns true for the following cases:
+
+ \table
+ \header
+ \i WM_SYSKEYDOWN
+ \i WM_SYSKEYUP
+ \i WM_KEYDOWN
+ \row
+ \i All keycodes
+ \i VK_MENU
+ \i VK_TAB, VK_DELETE and all non-arrow-keys in combination with VK_SHIFT,
+ VK_CONTROL or VK_MENU
+ \endtable
+
+ This table is the result of experimenting with popular ActiveX controls,
+ ie. Internet Explorer and Microsoft Office applications, but for some
+ controls it might require modification.
+*/
+bool QAxWidget::translateKeyEvent(int message, int keycode) const
+{
+ bool translate = false;
+
+ switch (message) {
+ case WM_SYSKEYDOWN:
+ translate = true;
+ break;
+ case WM_KEYDOWN:
+ translate = keycode == VK_TAB
+ || keycode == VK_DELETE;
+ if (!translate) {
+ int state = 0;
+ if (GetKeyState(VK_SHIFT) < 0)
+ state |= 0x01;
+ if (GetKeyState(VK_CONTROL) < 0)
+ state |= 0x02;
+ if (GetKeyState(VK_MENU) < 0)
+ state |= 0x04;
+ if (state) {
+ state = keycode < VK_LEFT || keycode > VK_DOWN;
+ }
+ translate = state;
+ }
+ break;
+ case WM_SYSKEYUP:
+ translate = keycode == VK_MENU;
+ break;
+ }
+
+ return translate;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/container/qaxwidget.h b/src/activeqt/container/qaxwidget.h
new file mode 100644
index 0000000..58069a1
--- /dev/null
+++ b/src/activeqt/container/qaxwidget.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXWIDGET_H
+#define QAXWIDGET_H
+
+#include <ActiveQt/qaxbase.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+class QAxHostWindow;
+class QAxAggregated;
+
+class QAxClientSite;
+
+class QAxWidget : public QWidget, public QAxBase
+{
+public:
+ const QMetaObject *metaObject() const;
+ void* qt_metacast(const char*);
+ int qt_metacall(QMetaObject::Call, int, void **);
+ QObject* qObject() const { return (QWidget*)this; }
+ const char *className() const;
+
+ QAxWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
+ QAxWidget(const QString &c, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ QAxWidget(IUnknown *iface, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ ~QAxWidget();
+
+ void clear();
+ bool doVerb(const QString &verb);
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ virtual QAxAggregated *createAggregate();
+
+protected:
+ bool initialize(IUnknown**);
+ virtual bool createHostWindow(bool);
+ bool createHostWindow(bool, const QByteArray&);
+
+ void changeEvent(QEvent *e);
+ void resizeEvent(QResizeEvent *);
+
+ virtual bool translateKeyEvent(int message, int keycode) const;
+
+ void connectNotify(const char *signal);
+private:
+ friend class QAxClientSite;
+ QAxClientSite *container;
+
+ const QMetaObject *parentMetaObject() const;
+ static QMetaObject staticMetaObject;
+};
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QAxWidget *qobject_cast_helper<QAxWidget*>(const QObject *o, QAxWidget *)
+#else
+template <> inline QAxWidget *qobject_cast<QAxWidget*>(const QObject *o)
+#endif
+{
+ void *result = o ? const_cast<QObject *>(o)->qt_metacast("QAxWidget") : 0;
+ return (QAxWidget*)(result);
+}
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QAxWidget *qobject_cast_helper<QAxWidget*>(QObject *o, QAxWidget *)
+#else
+template <> inline QAxWidget *qobject_cast<QAxWidget*>(QObject *o)
+#endif
+{
+ void *result = o ? o->qt_metacast("QAxWidget") : 0;
+ return (QAxWidget*)(result);
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXWIDGET_H
diff --git a/src/activeqt/control/control.pro b/src/activeqt/control/control.pro
new file mode 100644
index 0000000..361ca29
--- /dev/null
+++ b/src/activeqt/control/control.pro
@@ -0,0 +1,39 @@
+TEMPLATE = lib
+
+TARGET = ActiveQt
+CONFIG += qt_install_headers
+SYNCQT.HEADER_FILES = qaxaggregated.h qaxbindable.h qaxfactory.h
+SYNCQT.HEADER_CLASSES = ../../../include/ActiveQt/QAxAggregated ../../../include/ActiveQt/QAxBindable ../../../include/ActiveQt/QAxFactory ../../../include/ActiveQt/QAxClass
+include(../../qt_install.pri)
+
+TARGET = QAxServer
+
+!debug_and_release|build_pass {
+ CONFIG(debug, debug|release) {
+ TARGET = $$member(TARGET, 0)d
+ }
+}
+
+CONFIG += qt warn_off staticlib
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE\\lib
+
+DEFINES += QAX_SERVER
+win32-g++*:DEFINES += QT_NEEDS_QMAIN
+win32-borland:DEFINES += QT_NEEDS_QMAIN
+
+LIBS += -luser32 -lole32 -loleaut32 -lgdi32
+win32-g++*:LIBS += -luuid
+
+HEADERS = qaxaggregated.h \
+ qaxbindable.h \
+ qaxfactory.h \
+ ../shared/qaxtypes.h
+
+SOURCES = qaxserver.cpp \
+ qaxserverbase.cpp \
+ qaxbindable.cpp \
+ qaxfactory.cpp \
+ qaxservermain.cpp \
+ qaxserverdll.cpp \
+ qaxmain.cpp \
+ ../shared/qaxtypes.cpp
diff --git a/src/activeqt/control/qaxaggregated.h b/src/activeqt/control/qaxaggregated.h
new file mode 100644
index 0000000..f8537c8
--- /dev/null
+++ b/src/activeqt/control/qaxaggregated.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXAGGREGATED_H
+#define QAXAGGREGATED_H
+
+#include <QtCore/qobject.h>
+
+struct IUnknown;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+struct QUuid;
+
+class QAxAggregated
+{
+ friend class QAxServerBase;
+ friend class QAxClientSite;
+public:
+ virtual long queryInterface(const QUuid &iid, void **iface) = 0;
+
+protected:
+ virtual ~QAxAggregated()
+ {}
+
+ inline IUnknown *controllingUnknown() const
+ { return controlling_unknown; }
+ inline QWidget *widget() const
+ {
+ return qobject_cast<QWidget*>(the_object);
+ }
+ inline QObject *object() const { return the_object; }
+
+private:
+ IUnknown *controlling_unknown;
+ QObject *the_object;
+};
+
+#define QAXAGG_IUNKNOWN \
+ HRESULT WINAPI QueryInterface(REFIID iid, LPVOID *iface) { \
+ return controllingUnknown()->QueryInterface(iid, iface); } \
+ ULONG WINAPI AddRef() {return controllingUnknown()->AddRef(); } \
+ ULONG WINAPI Release() {return controllingUnknown()->Release(); } \
+
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QAXAGGREGATED_H
diff --git a/src/activeqt/control/qaxbindable.cpp b/src/activeqt/control/qaxbindable.cpp
new file mode 100644
index 0000000..f023a19
--- /dev/null
+++ b/src/activeqt/control/qaxbindable.cpp
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxbindable.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qmetaobject.h>
+
+#include <qt_windows.h> // for IUnknown
+#include "../shared/qaxtypes.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAxBindable
+ \brief The QAxBindable class provides an interface between a
+ QWidget and an ActiveX client.
+
+ \inmodule QAxServer
+
+ The functions provided by this class allow an ActiveX control to
+ communicate property changes to a client application. Inherit
+ your control class from both QWidget (directly or indirectly) and
+ this class to get access to this class's functions. The
+ \l{moc}{meta-object compiler} requires you to inherit from
+ QWidget first.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp 0
+
+ When implementing the property write function, use
+ requestPropertyChange() to get permission from the ActiveX client
+ application to change this property. When the property changes,
+ call propertyChanged() to notify the ActiveX client application
+ about the change. If a fatal error occurs in the control, use the
+ static reportError() function to notify the client.
+
+ Use the interface returned by clientSite() to call the ActiveX
+ client. To implement additional COM interfaces in your ActiveX
+ control, reimplement createAggregate() to return a new object of a
+ QAxAggregated subclass.
+
+ The ActiveQt \l{activeqt/opengl}{OpenGL} example shows how to use
+ QAxBindable to implement additional COM interfaces.
+
+ \sa QAxAggregated, QAxFactory, {ActiveQt Framework}
+*/
+
+/*!
+ Constructs an empty QAxBindable object.
+*/
+QAxBindable::QAxBindable()
+:activex(0)
+{
+}
+
+/*!
+ Destroys the QAxBindable object.
+*/
+QAxBindable::~QAxBindable()
+{
+}
+
+/*!
+ Call this function to request permission to change the property
+ \a property from the client that is hosting this ActiveX control.
+ Returns true if the client allows the change; otherwise returns
+ false.
+
+ This function is usually called first in the write function for \a
+ property, and writing is abandoned if the function returns false.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp 1
+
+ \sa propertyChanged()
+*/
+bool QAxBindable::requestPropertyChange(const char *property)
+{
+ if (!activex)
+ return true;
+
+ return activex->emitRequestPropertyChange(property);
+}
+
+/*!
+ Call this function to notify the client that is hosting this
+ ActiveX control that the property \a property has been changed.
+
+ This function is usually called at the end of the property's write
+ function.
+
+ \sa requestPropertyChange()
+*/
+void QAxBindable::propertyChanged(const char *property)
+{
+ if (!activex)
+ return;
+
+ activex->emitPropertyChanged(property);
+}
+
+/*!
+ Returns a pointer to the client site interface for this ActiveX object,
+ or null if no client site has been set.
+
+ Call \c QueryInterface() on the returned interface to get the
+ interface you want to call.
+*/
+IUnknown *QAxBindable::clientSite() const
+{
+ if (!activex)
+ return 0;
+
+ return activex->clientSite();
+}
+
+/*!
+ Reimplement this function when you want to implement additional
+ COM interfaces in the ActiveX control, or when you want to provide
+ alternative implementations of COM interfaces. Return a new object
+ of a QAxAggregated subclass.
+
+ The default implementation returns the null pointer.
+*/
+QAxAggregated *QAxBindable::createAggregate()
+{
+ return 0;
+}
+
+/*!
+ Reports an error to the client application. \a code is a
+ control-defined error code. \a desc is a human-readable description
+ of the error intended for the application user. \a src is the name
+ of the source for the error, typically the ActiveX server name. \a
+ context can be the location of a help file with more information
+ about the error. If \a context ends with a number in brackets,
+ e.g. [12], this number will be interpreted as the context ID in
+ the help file.
+*/
+void QAxBindable::reportError(int code, const QString &src, const QString &desc, const QString &context)
+{
+ if (!activex)
+ return;
+
+ activex->reportError(code, src, desc, context);
+}
+
+/*!
+ \since 4.1
+
+ If the COM object supports a MIME type then this function is called
+ to initialize the COM object from the data \a source in \a format.
+ You have to open \a source for reading before you can read from it.
+
+ Returns true to indicate success. If the function returns false,
+ then ActiveQt will process the data by setting the properties
+ through the meta object system.
+
+ If you reimplement this function you also have to implement
+ writeData(). The default implementation does nothing and returns
+ false.
+
+ \warning ActiveX controls embedded in HTML can use either the
+ \c type and \c data attribute of the \c object tag to read data,
+ or use a list of \c param tags to initialize properties. If
+ \c param tags are used, then Internet Explorer will ignore the
+ \c data attribute, and readData will not be called.
+
+ \sa writeData()
+*/
+bool QAxBindable::readData(QIODevice *source, const QString &format)
+{
+ Q_UNUSED(source);
+ Q_UNUSED(format);
+ return false;
+}
+
+/*!
+ \since 4.1
+
+ If the COM object supports a MIME type then this function is called
+ to store the COM object into \a sink.
+ You have to open \a sink for writing before you can write to it.
+
+ Returns true to indicate success. If the function returns false,
+ then ActiveQt will serialize the object by storing the property
+ values.
+
+ If you reimplement this function you also have to implement
+ readData(). The default implementation does nothing and returns
+ false.
+
+ \sa readData()
+*/
+bool QAxBindable::writeData(QIODevice *sink)
+{
+ Q_UNUSED(sink);
+ return false;
+}
+
+/*!
+ \class QAxAggregated
+ \brief The QAxAggregated class is an abstract base class for implementations of
+ additional COM interfaces.
+
+ \inmodule QAxServer
+
+ Create a subclass of QAxAggregated and reimplement
+ queryInterface() to support additional COM interfaces. Use
+ multiple inheritance from those COM interfaces. Implement the
+ IUnknown interface of those COM interfaces by delegating the
+ calls to \c QueryInterface(), \c AddRef() and \c Release() to the
+ interface provided by controllingUnknown().
+
+ Use the widget() method if you need to make calls to the QWidget
+ implementing the ActiveX control. You must not store that pointer
+ in your subclass (unless you use QPointer), as the QWidget can
+ be destroyed by the ActiveQt framework at any time.
+
+ \sa QAxBindable, QAxFactory, {Qt's ActiveX Framework (ActiveQt)}
+*/
+
+/*!
+ \fn QAxAggregated::~QAxAggregated()
+
+ The destructor is called internally by Qt.
+*/
+
+/*!
+ \fn long QAxAggregated::queryInterface(const QUuid &iid, void **iface)
+
+ Reimplement this pure virtual function to support additional COM
+ interfaces. Set the value of \a iface to point to this object to
+ support the interface \a iid. Note that you must cast the \c
+ this pointer to the appropriate superclass.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp 2
+
+ Return the standard COM results \c S_OK (interface is supported)
+ or \c E_NOINTERFACE (requested interface is not supported).
+
+ \warning
+ Even though you must implement the \c IUnknown interface if you
+ implement any COM interface you must not support the \c IUnknown
+ interface in your queryInterface() implementation.
+*/
+
+/*!
+ \fn IUnknown *QAxAggregated::controllingUnknown() const
+
+ Returns the \c IUnknown interface of the ActiveX control. Implement
+ the \c IUnknown interface in your QAxAggregated subclass to
+ delegate calls to \c QueryInterface(), \c AddRef(), and \c
+ Release() to the interface provided by this function.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxbindable.cpp 3
+
+ Instead of declaring and implementing these three functions
+ manually, you can use the \c QAXAGG_IUNKNOWN macro in the class
+ declaration of your subclass.
+*/
+
+/*!
+ \fn QObject *QAxAggregated::object() const
+
+ Returns a pointer to the QObject subclass implementing the COM object.
+ This function might return 0.
+
+ \warning
+ You must not store the returned pointer, unless you use a
+ QPointer, since the QObject can be destroyed by ActiveQt at any
+ time.
+*/
+
+/*!
+ \fn QWidget *QAxAggregated::widget() const
+
+ Returns a pointer to the QWidget subclass implementing the ActiveX control.
+ This function might return 0.
+
+ \warning
+ You must not store the returned pointer, unless you use a
+ QPointer, since the QWidget can be destroyed by ActiveQt at any
+ time.
+*/
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/control/qaxbindable.h b/src/activeqt/control/qaxbindable.h
new file mode 100644
index 0000000..1e1a6dd
--- /dev/null
+++ b/src/activeqt/control/qaxbindable.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXBINDABLE_H
+#define QAXBINDABLE_H
+
+#include <QtGui/qwidget.h>
+
+struct IUnknown;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+class QAxAggregated;
+class QIODevice;
+struct IAxServerBase;
+
+class QAxBindable
+{
+ friend class QAxServerBase;
+public:
+ QAxBindable();
+ virtual ~QAxBindable();
+
+ virtual QAxAggregated *createAggregate();
+ void reportError(int code, const QString &src, const QString &desc, const QString &help = QString());
+
+ virtual bool readData(QIODevice *source, const QString &format);
+ virtual bool writeData(QIODevice *sink);
+
+protected:
+ bool requestPropertyChange(const char *property);
+ void propertyChanged(const char *property);
+
+ IUnknown *clientSite() const;
+
+private:
+ IAxServerBase *activex;
+};
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXBINDABLE_H
diff --git a/src/activeqt/control/qaxfactory.cpp b/src/activeqt/control/qaxfactory.cpp
new file mode 100644
index 0000000..7a7a285
--- /dev/null
+++ b/src/activeqt/control/qaxfactory.cpp
@@ -0,0 +1,592 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxfactory.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qmetaobject.h>
+#include <qsettings.h>
+#include <qwidget.h>
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+extern wchar_t qAxModuleFilename[MAX_PATH];
+
+/*!
+ \class QAxFactory
+ \brief The QAxFactory class defines a factory for the creation of COM components.
+
+ \inmodule QAxServer
+
+ Implement this factory once in your COM server to provide information
+ about the components the server can create. Subclass QAxFactory and implement
+ the pure virtual functions in any implementation file (e.g. main.cpp), and export
+ the factory using the \c QAXFACTORY_EXPORT() macro.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 0
+
+ If you use the \c Q_CLASSINFO() macro to provide the unique
+ identifiers or other attributes for your class you can use the \c
+ QAXFACTORY_BEGIN(), \c QAXCLASS() and \c QAXFACTORY_END() macros to
+ expose one or more classes as COM objects.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 1
+
+
+ If your server supports just a single COM object, you can use
+ a default factory implementation through the \c QAXFACTORY_DEFAULT() macro.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 2
+
+ Only one QAxFactory implementation may be instantiated and
+ exported by an ActiveX server application. This instance is accessible
+ through the global qAxFactory() function.
+
+ A factory can also reimplement the registerClass() and
+ unregisterClass() functions to set additional flags for an ActiveX
+ control in the registry. To limit the number of methods or
+ properties a widget class exposes from its parent classes
+ reimplement exposeToSuperClass().
+
+ \sa QAxAggregated, QAxBindable, {ActiveQt Framework}
+*/
+
+/*!
+ Constructs a QAxFactory object that returns \a libid and \a appid
+ in the implementation of the respective interface functions.
+*/
+
+QAxFactory::QAxFactory(const QUuid &libid, const QUuid &appid)
+: typelib(libid), app(appid)
+{
+}
+
+/*!
+ Destroys the QAxFactory object.
+*/
+QAxFactory::~QAxFactory()
+{
+}
+
+/*!
+ \fn QUuid QAxFactory::typeLibID() const
+
+ Reimplement this function to return the ActiveX server's type
+ library identifier.
+*/
+QUuid QAxFactory::typeLibID() const
+{
+ return typelib;
+}
+
+/*!
+ \fn QUuid QAxFactory::appID() const
+
+ Reimplement this function to return the ActiveX server's
+ application identifier.
+*/
+QUuid QAxFactory::appID() const
+{
+ return app;
+}
+
+/*!
+ \fn QStringList QAxFactory::featureList() const
+
+ Reimplement this function to return a list of the widgets (class
+ names) supported by this factory.
+*/
+
+/*!
+ \fn QObject *QAxFactory::createObject(const QString &key)
+
+ Reimplement this function to return a new object for \a key, or 0 if
+ this factory doesn't support the value of \a key.
+
+ If the object returned is a QWidget it will be exposed as an ActiveX
+ control, otherwise the returned object will be exposed as a simple COM
+ object.
+*/
+
+/*!
+ \fn const QMetaObject *QAxFactory::metaObject(const QString &key) const
+
+ Reimplement this function to return the QMetaObject corresponding to
+ \a key, or 0 if this factory doesn't support the value of \a key.
+*/
+
+/*!
+ \fn bool QAxFactory::createObjectWrapper(QObject *object, IDispatch **wrapper)
+
+ Reimplement this function to provide the COM object for \a object
+ in \a wrapper. Return true if the function was successful; otherwise
+ return false.
+
+ The default implementation creates a generic automation wrapper based
+ on the meta object information of \a object.
+*/
+// implementation in qaxserverbase.cpp
+
+/*!
+ Reimplement this function to return the class identifier for each
+ \a key returned by the featureList() implementation, or an empty
+ QUuid if this factory doesn't support the value of \a key.
+
+ The default implementation interprets \a key as the class name,
+ and returns the value of the Q_CLASSINFO() entry "ClassID".
+*/
+QUuid QAxFactory::classID(const QString &key) const
+{
+ const QMetaObject *mo = metaObject(key);
+ if (!mo)
+ return QUuid();
+ QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("ClassID")).value());
+
+ return QUuid(id);
+}
+
+/*!
+ Reimplement this function to return the interface identifier for
+ each \a key returned by the featureList() implementation, or an
+ empty QUuid if this factory doesn't support the value of \a key.
+
+ The default implementation interprets \a key as the class name,
+ and returns the value of the Q_CLASSINFO() entry "InterfaceID".
+*/
+QUuid QAxFactory::interfaceID(const QString &key) const
+{
+ const QMetaObject *mo = metaObject(key);
+ if (!mo)
+ return QUuid();
+ QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("InterfaceID")).value());
+
+ return QUuid(id);
+}
+
+/*!
+ Reimplement this function to return the identifier of the event
+ interface for each \a key returned by the featureList()
+ implementation, or an empty QUuid if this factory doesn't support
+ the value of \a key.
+
+ The default implementation interprets \a key as the class name,
+ and returns the value of the Q_CLASSINFO() entry "EventsID".
+*/
+QUuid QAxFactory::eventsID(const QString &key) const
+{
+ const QMetaObject *mo = metaObject(key);
+ if (!mo)
+ return QUuid();
+ QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("EventsID")).value());
+
+ return QUuid(id);
+}
+
+/*!
+ Registers additional values for the class \a key in the system
+ registry using the \a settings object. The standard values have
+ already been registered by the framework, but additional values,
+ e.g. implemented categories, can be added in an implementation of
+ this function.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 3
+
+ If you reimplement this function you must also reimplement
+ unregisterClass() to remove the additional registry values.
+
+ \sa QSettings
+*/
+void QAxFactory::registerClass(const QString &key, QSettings *settings) const
+{
+ Q_UNUSED(key);
+ Q_UNUSED(settings)
+}
+
+/*!
+ Unregisters any additional values for the class \a key from the
+ system registry using the \a settings object.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 4
+
+ \sa registerClass(), QSettings
+*/
+void QAxFactory::unregisterClass(const QString &key, QSettings *settings) const
+{
+ Q_UNUSED(key);
+ Q_UNUSED(settings)
+}
+
+/*!
+ Reimplement this function to return true if \a licenseKey is a valid
+ license for the class \a key, or if the current machine is licensed.
+
+ The default implementation returns true if the class \a key is
+ not licensed (ie. no \c Q_CLASSINFO() attribute "LicenseKey"), or
+ if \a licenseKey matches the value of the "LicenseKey"
+ attribute, or if the machine is licensed through a .LIC file with
+ the same filename as this COM server.
+*/
+bool QAxFactory::validateLicenseKey(const QString &key, const QString &licenseKey) const
+{
+ const QMetaObject *mo = metaObject(key);
+ if (!mo)
+ return true;
+
+ QString classKey = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value());
+ if (classKey.isEmpty())
+ return true;
+
+ if (licenseKey.isEmpty()) {
+ QString licFile(QString::fromWCharArray(qAxModuleFilename));
+ int lastDot = licFile.lastIndexOf(QLatin1Char('.'));
+ licFile = licFile.left(lastDot) + QLatin1String(".lic");
+ if (QFile::exists(licFile))
+ return true;
+ return false;
+ }
+ return licenseKey == classKey;
+}
+
+/*!
+ Reimplement this function to return the name of the super class of
+ \a key up to which methods and properties should be exposed by the
+ ActiveX control.
+
+ The default implementation interprets \a key as the class name,
+ and returns the value of the \c Q_CLASSINFO() entry
+ "ToSuperClass". If no such value is set the null-string is
+ returned, and the functions and properties of all the super
+ classes including QWidget will be exposed.
+
+ To only expose the functions and properties of the class itself,
+ reimplement this function to return \a key.
+*/
+QString QAxFactory::exposeToSuperClass(const QString &key) const
+{
+ const QMetaObject *mo = metaObject(key);
+ if (!mo)
+ return QString();
+ return QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("ToSuperClass")).value());
+}
+
+/*!
+ Reimplement this function to return true if the ActiveX control \a key
+ should be a top level window, e.g. a dialog. The default implementation
+ returns false.
+*/
+bool QAxFactory::stayTopLevel(const QString &key) const
+{
+ return false;
+}
+
+/*!
+ Reimplement this function to return true if the ActiveX control
+ \a key should support the standard ActiveX events
+ \list
+ \i Click
+ \i DblClick
+ \i KeyDown
+ \i KeyPress
+ \i KeyUp
+ \i MouseDown
+ \i MouseUp
+ \i MouseMove
+ \endlist
+
+ The default implementation interprets \a key as the class name,
+ and returns true if the value of the \c Q_CLASSINFO() entry
+ "StockEvents" is "yes". Otherwise this function returns false.
+*/
+bool QAxFactory::hasStockEvents(const QString &key) const
+{
+ const QMetaObject *mo = metaObject(key);
+ if (!mo)
+ return false;
+ return QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("StockEvents")).value()) == QLatin1String("yes");
+}
+
+
+extern bool qAxIsServer;
+
+/*!
+ Returns true if the application has been started (by COM) as an ActiveX
+ server, otherwise returns false.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 5
+*/
+
+bool QAxFactory::isServer()
+{
+ return qAxIsServer;
+}
+
+extern wchar_t qAxModuleFilename[MAX_PATH];
+
+/*!
+ Returns the directory that contains the server binary.
+
+ For out-of-process servers this is the same as
+ QApplication::applicationDirPath(). For in-process servers
+ that function returns the directory that contains the hosting
+ application.
+*/
+QString QAxFactory::serverDirPath()
+{
+ return QFileInfo(QString::fromWCharArray(qAxModuleFilename)).absolutePath();
+}
+
+/*!
+ Returns the file path of the server binary.
+
+ For out-of-process servers this is the same as
+ QApplication::applicationFilePath(). For in-process servers
+ that function returns the file path of the hosting application.
+*/
+QString QAxFactory::serverFilePath()
+{
+ return QString::fromWCharArray(qAxModuleFilename);
+}
+
+/*!
+ Reimplement this function to return true if the server is
+ running as a persistent service (e.g. an NT service) and should
+ not terminate even when all objects provided have been released.
+
+ The default implementation returns false.
+*/
+bool QAxFactory::isService() const
+{
+ return false;
+}
+
+/*!
+ \enum QAxFactory::ServerType
+
+ This enum specifies the different types of servers that can be
+ started with startServer.
+
+ \value SingleInstance The server process can create only one instance of each
+ exported class. COM starts a new process for each request. This is typically
+ used in servers that export only one creatable class.
+ \value MultipleInstances The server can create multiple instances of
+ each exported class. This is the default. All instances will live in the same
+ thread, and will share static resources.
+*/
+
+/*!
+ \fn bool QAxFactory::startServer(ServerType type);
+
+ Starts the COM server with \a type and returns true if successful,
+ otherwise returns false.
+
+ Calling this function if the server is already running (or for an
+ in-process server) does nothing and returns true.
+
+ The server is started automatically with \a type set to \c MultipleInstances
+ if the server executable has been started with the \c -activex
+ command line parameter. To switch to SingleInstance, call
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 6
+
+ in your own main() entry point function.
+*/
+
+/*!
+ \fn bool QAxFactory::stopServer();
+
+ Stops the COM server and returns true if successful, otherwise
+ returns false.
+
+ Calling this function if the server is not running (or for an
+ in-process server) does nothing and returns true.
+
+ Stopping the server will not invalidate existing objects, but no
+ new objects can be created from the existing server process. Usually
+ COM will start a new server process if additional objects are requested.
+
+ The server is stopped automatically when the main() function returns.
+*/
+
+class ActiveObject : public QObject
+{
+public:
+ ActiveObject(QObject *parent, QAxFactory *factory);
+ ~ActiveObject();
+
+ IDispatch *wrapper;
+ DWORD cookie;
+};
+
+ActiveObject::ActiveObject(QObject *parent, QAxFactory *factory)
+: QObject(parent), wrapper(0), cookie(0)
+{
+ QLatin1String key(parent->metaObject()->className());
+
+ factory->createObjectWrapper(parent, &wrapper);
+ if (wrapper)
+ RegisterActiveObject(wrapper, QUuid(factory->classID(key)), ACTIVEOBJECT_STRONG, &cookie);
+}
+
+ActiveObject::~ActiveObject()
+{
+ if (cookie)
+ RevokeActiveObject(cookie, 0);
+ if (wrapper)
+ wrapper->Release();
+}
+
+/*!
+ Registers the QObject \a object with COM as a running object, and returns true if
+ the registration succeeded, otherwise returns false. The object is unregistered
+ automatically when it is destroyed.
+
+ This function should only be called if the application has been started by the user
+ (i.e. not by COM to respond to a request), and only for one object, usually the
+ toplevel object of the application's object hierarchy.
+
+ This function does nothing and returns false if the object's class info for
+ "RegisterObject" is not set to "yes", or if the server is an in-process server.
+*/
+bool QAxFactory::registerActiveObject(QObject *object)
+{
+ if (qstricmp(object->metaObject()->classInfo(object->metaObject()->indexOfClassInfo("RegisterObject")).value(), "yes"))
+ return false;
+
+ if (!QString::fromWCharArray(qAxModuleFilename).toLower().endsWith(QLatin1String(".exe")))
+ return false;
+
+ ActiveObject *active = new ActiveObject(object, qAxFactory());
+ if (!active->wrapper || !active->cookie) {
+ delete active;
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \macro QAXFACTORY_DEFAULT(Class, ClassID, InterfaceID, EventID, LibID, AppID)
+ \relates QAxFactory
+
+ This macro can be used to export a single QObject subclass \a Class a this
+ COM server through an implicitly declared QAxFactory implementation.
+
+ This macro exports the class \a Class as a COM coclass with the CLSID \a ClassID.
+ The properties and slots will be declared through a COM interface with the IID
+ \a InterfaceID, and signals will be declared through a COM event interface with
+ the IID \a EventID. All declarations will be in a type library with the id \a LibID,
+ and if the server is an executable server then it will have the application id
+ \a AppID.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 7
+
+ \sa QAXFACTORY_EXPORT(), QAXFACTORY_BEGIN()
+*/
+
+/*!
+ \macro QAXFACTORY_EXPORT(Class, LibID, AppID)
+ \relates QAxFactory
+
+ This macro can be used to export a QAxFactory implementation \a Class from
+ a COM server. All declarations will be in a type library with the id \a LibID,
+ and if the server is an executable server then it will have the application id
+ \a AppID.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 8
+
+ \sa QAXFACTORY_BEGIN()
+*/
+
+/*!
+ \macro QAXFACTORY_BEGIN(IDTypeLib, IDApp)
+ \relates QAxFactory
+
+ This macro can be used to export multiple QObject classes through an
+ implicitly declared QAxFactory implementation. All QObject classes have to
+ declare the ClassID, InterfaceID and EventsID (if applicable) through the
+ Q_CLASSINFO() macro. All declarations will be in a type library with the id
+ \a IDTypeLib, and if the server is an executable server then it will have the
+ application id \a IDApp.
+
+ This macro needs to be used together with the QAXCLASS(), QAXTYPE()
+ and QAXFACTORY_END() macros.
+
+ \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 9
+*/
+
+/*!
+ \macro QAXCLASS(Class)
+ \relates QAxFactory
+
+ This macro adds a creatable COM class \a Class to the QAxFactory declared
+ with the QAXFACTORY_BEGIN() macro.
+
+ \sa QAXFACTORY_BEGIN(), QAXTYPE(), QAXFACTORY_END(), Q_CLASSINFO()
+*/
+
+/*!
+ \macro QAXTYPE(Class)
+ \relates QAxFactory
+
+ This macro adds a non-creatable COM class \a Class to the QAxFactory
+ declared with the QAXFACTORY_BEGIN(). The class \a Class can be used
+ in APIs of other COM classes exported through QAXTYPE() or QAXCLASS().
+
+ Instances of type \a Class can only be retrieved using APIs of already
+ instantiated objects.
+
+ \sa QAXFACTORY_BEGIN(), QAXCLASS(), QAXFACTORY_END(), Q_CLASSINFO()
+*/
+
+/*!
+ \macro QAXFACTORY_END()
+ \relates QAxFactory
+
+ Completes the QAxFactory declaration started with the QAXFACTORY_BEGIN()
+ macro.
+
+ \sa QAXFACTORY_BEGIN(), QAXCLASS(), QAXTYPE()
+*/
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/control/qaxfactory.h b/src/activeqt/control/qaxfactory.h
new file mode 100644
index 0000000..25650ad
--- /dev/null
+++ b/src/activeqt/control/qaxfactory.h
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXFACTORY_H
+#define QAXFACTORY_H
+
+#include <QtCore/qhash.h>
+#include <QtCore/quuid.h>
+#include <QtCore/qfactoryinterface.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qstringlist.h>
+
+struct IUnknown;
+struct IDispatch;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+class QWidget;
+class QSettings;
+
+class QAxFactory : public QObject
+{
+public:
+ QAxFactory(const QUuid &libId, const QUuid &appId);
+ virtual ~QAxFactory();
+
+ virtual QStringList featureList() const = 0;
+
+ virtual QObject *createObject(const QString &key) = 0;
+ virtual const QMetaObject *metaObject(const QString &key) const = 0;
+ virtual bool createObjectWrapper(QObject *object, IDispatch **wrapper);
+
+ virtual QUuid classID(const QString &key) const;
+ virtual QUuid interfaceID(const QString &key) const;
+ virtual QUuid eventsID(const QString &key) const;
+
+ virtual QUuid typeLibID() const;
+ virtual QUuid appID() const;
+
+ virtual void registerClass(const QString &key, QSettings *) const;
+ virtual void unregisterClass(const QString &key, QSettings *) const;
+
+ virtual bool validateLicenseKey(const QString &key, const QString &licenseKey) const;
+
+ virtual QString exposeToSuperClass(const QString &key) const;
+ virtual bool stayTopLevel(const QString &key) const;
+ virtual bool hasStockEvents(const QString &key) const;
+ virtual bool isService() const;
+
+ enum ServerType {
+ SingleInstance,
+ MultipleInstances
+ };
+
+ static bool isServer();
+ static QString serverDirPath();
+ static QString serverFilePath();
+ static bool startServer(ServerType type = MultipleInstances);
+ static bool stopServer();
+
+ static bool registerActiveObject(QObject *object);
+
+private:
+ QUuid typelib;
+ QUuid app;
+};
+
+extern QAxFactory *qAxFactory();
+
+extern bool qax_startServer(QAxFactory::ServerType);
+
+inline bool QAxFactory::startServer(ServerType type)
+{
+ // implementation in qaxservermain.cpp
+ return qax_startServer(type);
+}
+
+extern bool qax_stopServer();
+
+inline bool QAxFactory::stopServer()
+{
+ // implementation in qaxservermain.cpp
+ return qax_stopServer();
+}
+
+#define QAXFACTORY_EXPORT(IMPL, TYPELIB, APPID) \
+ QT_BEGIN_NAMESPACE \
+ QAxFactory *qax_instantiate() \
+ { \
+ IMPL *impl = new IMPL(QUuid(TYPELIB), QUuid(APPID)); \
+ return impl; \
+ } \
+ QT_END_NAMESPACE
+
+#define QAXFACTORY_DEFAULT(Class, IIDClass, IIDInterface, IIDEvents, IIDTypeLib, IIDApp) \
+ QT_BEGIN_NAMESPACE \
+ class QAxDefaultFactory : public QAxFactory \
+ { \
+ public: \
+ QAxDefaultFactory(const QUuid &app, const QUuid &lib) \
+ : QAxFactory(app, lib), className(QLatin1String(#Class)) {} \
+ QStringList featureList() const \
+ { \
+ QStringList list; \
+ list << className; \
+ return list; \
+ } \
+ const QMetaObject *metaObject(const QString &key) const \
+ { \
+ if (key == className) \
+ return &Class::staticMetaObject; \
+ return 0; \
+ } \
+ QObject *createObject(const QString &key) \
+ { \
+ if (key == className) \
+ return new Class(0); \
+ return 0; \
+ } \
+ QUuid classID(const QString &key) const \
+ { \
+ if (key == className) \
+ return QUuid(IIDClass); \
+ return QUuid(); \
+ } \
+ QUuid interfaceID(const QString &key) const \
+ { \
+ if (key == className) \
+ return QUuid(IIDInterface); \
+ return QUuid(); \
+ } \
+ QUuid eventsID(const QString &key) const \
+ { \
+ if (key == className) \
+ return QUuid(IIDEvents); \
+ return QUuid(); \
+ } \
+ private: \
+ QString className; \
+ }; \
+ QT_END_NAMESPACE \
+ QAXFACTORY_EXPORT(QAxDefaultFactory, IIDTypeLib, IIDApp) \
+
+template<class T>
+class QAxClass : public QAxFactory
+{
+public:
+ QAxClass(const QString &libId, const QString &appId)
+ : QAxFactory(libId, appId)
+ {}
+
+ const QMetaObject *metaObject(const QString &) const { return &T::staticMetaObject; }
+ QStringList featureList() const { return QStringList(QString(T::staticMetaObject.className())); }
+ QObject *createObject(const QString &key)
+ {
+ const QMetaObject &mo = T::staticMetaObject;
+ if (key != QLatin1String(mo.className()))
+ return 0;
+ if (!qstrcmp(mo.classInfo(mo.indexOfClassInfo("Creatable")).value(), "no"))
+ return 0;
+ return new T(0);
+ }
+};
+
+#define QAXFACTORY_BEGIN(IDTypeLib, IDApp) \
+ QT_BEGIN_NAMESPACE \
+ class QAxFactoryList : public QAxFactory \
+ { \
+ QStringList factoryKeys; \
+ QHash<QString, QAxFactory*> factories; \
+ QHash<QString, bool> creatable; \
+ public: \
+ QAxFactoryList() \
+ : QAxFactory(IDTypeLib, IDApp) \
+ { \
+ QAxFactory *factory = 0; \
+ QStringList keys; \
+ QStringList::Iterator it; \
+
+#define QAXCLASS(Class) \
+ factory = new QAxClass<Class>(typeLibID(), appID()); \
+ qRegisterMetaType<Class*>(#Class"*"); \
+ keys = factory->featureList(); \
+ for (it = keys.begin(); it != keys.end(); ++it) { \
+ factoryKeys += *it; \
+ factories.insert(*it, factory); \
+ creatable.insert(*it, true); \
+ }\
+
+#define QAXTYPE(Class) \
+ factory = new QAxClass<Class>(typeLibID(), appID()); \
+ qRegisterMetaType<Class*>(#Class"*"); \
+ keys = factory->featureList(); \
+ for (it = keys.begin(); it != keys.end(); ++it) { \
+ factoryKeys += *it; \
+ factories.insert(*it, factory); \
+ creatable.insert(*it, false); \
+ }\
+
+#define QAXFACTORY_END() \
+ } \
+ ~QAxFactoryList() { qDeleteAll(factories); } \
+ QStringList featureList() const { return factoryKeys; } \
+ const QMetaObject *metaObject(const QString&key) const { \
+ QAxFactory *f = factories[key]; \
+ return f ? f->metaObject(key) : 0; \
+ } \
+ QObject *createObject(const QString &key) { \
+ if (!creatable.value(key)) \
+ return 0; \
+ QAxFactory *f = factories[key]; \
+ return f ? f->createObject(key) : 0; \
+ } \
+ QUuid classID(const QString &key) { \
+ QAxFactory *f = factories.value(key); \
+ return f ? f->classID(key) : QUuid(); \
+ } \
+ QUuid interfaceID(const QString &key) { \
+ QAxFactory *f = factories.value(key); \
+ return f ? f->interfaceID(key) : QUuid(); \
+ } \
+ QUuid eventsID(const QString &key) { \
+ QAxFactory *f = factories.value(key); \
+ return f ? f->eventsID(key) : QUuid(); \
+ } \
+ void registerClass(const QString &key, QSettings *s) const { \
+ QAxFactory *f = factories.value(key); \
+ if (f) f->registerClass(key, s); \
+ } \
+ void unregisterClass(const QString &key, QSettings *s) const { \
+ QAxFactory *f = factories.value(key); \
+ if (f) f->unregisterClass(key, s); \
+ } \
+ QString exposeToSuperClass(const QString &key) const { \
+ QAxFactory *f = factories.value(key); \
+ return f ? f->exposeToSuperClass(key) : QString(); \
+ } \
+ bool stayTopLevel(const QString &key) const { \
+ QAxFactory *f = factories.value(key); \
+ return f ? f->stayTopLevel(key) : false; \
+ } \
+ bool hasStockEvents(const QString &key) const { \
+ QAxFactory *f = factories.value(key); \
+ return f ? f->hasStockEvents(key) : false; \
+ } \
+ }; \
+ QAxFactory *qax_instantiate() \
+ { \
+ QAxFactoryList *impl = new QAxFactoryList(); \
+ return impl; \
+ } \
+ QT_END_NAMESPACE
+
+QT_END_NAMESPACE
+
+#ifndef Q_COM_METATYPE_DECLARED
+#define Q_COM_METATYPE_DECLARED
+
+Q_DECLARE_METATYPE(IUnknown*)
+Q_DECLARE_METATYPE(IDispatch*)
+
+#endif
+
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXFACTORY_H
diff --git a/src/activeqt/control/qaxmain.cpp b/src/activeqt/control/qaxmain.cpp
new file mode 100644
index 0000000..3d1e6c8
--- /dev/null
+++ b/src/activeqt/control/qaxmain.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include <qapplication.h>
+#include <qaxfactory.h>
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+int main(int argc, char **argv)
+{
+ QT_USE_NAMESPACE
+ QAxFactory::startServer();
+ QApplication app(argc, argv);
+ app.setQuitOnLastWindowClosed(false);
+
+ return app.exec();
+}
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp
new file mode 100644
index 0000000..1726f92
--- /dev/null
+++ b/src/activeqt/control/qaxserver.cpp
@@ -0,0 +1,1257 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include "qaxbindable.h"
+#include "qaxfactory.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qapplication.h>
+#include <qdatetime.h>
+#include <qdir.h>
+#include <qmap.h>
+#include <qmenubar.h>
+#include <qmetaobject.h>
+#include <qsettings.h>
+#include <qvariant.h>
+#include <qtextstream.h>
+
+#include <qt_windows.h>
+#include <olectl.h>
+
+QT_BEGIN_NAMESPACE
+
+#define Q_REQUIRED_RPCNDR_H_VERSION 475
+
+// Some global variables to store module information
+bool qAxIsServer = false;
+HANDLE qAxInstance = 0;
+ITypeLib *qAxTypeLibrary = 0;
+wchar_t qAxModuleFilename[MAX_PATH];
+bool qAxOutProcServer = false;
+
+// The QAxFactory instance
+static QAxFactory* qax_factory = 0;
+extern CLSID CLSID_QRect;
+extern CLSID CLSID_QSize;
+extern CLSID CLSID_QPoint;
+extern void qax_shutDown();
+extern bool qax_ownQApp;
+
+
+extern QAxFactory *qax_instantiate();
+
+QAxFactory *qAxFactory()
+{
+ if (!qax_factory) {
+ bool hadQApp = qApp != 0;
+ qax_factory = qax_instantiate();
+ // QAxFactory created a QApplication
+ if (!hadQApp && qApp)
+ qax_ownQApp = true;
+
+ // register all types with metatype system as pointers
+ QStringList keys(qax_factory->featureList());
+ for (int i = 0; i < keys.count(); ++i) {
+ QString key(keys.at(i));
+ qRegisterMetaType((key + QLatin1Char('*')).toLatin1(), (void**)0);
+ }
+ }
+ return qax_factory;
+}
+
+// Some local variables to handle module lifetime
+static unsigned long qAxModuleRef = 0;
+static CRITICAL_SECTION qAxModuleSection;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Server control
+/////////////////////////////////////////////////////////////////////////////
+
+static int initCount = 0;
+
+QString qAxInit()
+{
+ static QString libFile;
+
+ if (initCount++)
+ return libFile;
+
+ InitializeCriticalSection(&qAxModuleSection);
+
+ libFile = QString::fromWCharArray(qAxModuleFilename);
+ libFile = libFile.toLower();
+ if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
+ return libFile;
+
+ int lastDot = libFile.lastIndexOf(QLatin1Char('.'));
+ libFile = libFile.left(lastDot) + QLatin1String(".tlb");
+ if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
+ return libFile;
+
+ lastDot = libFile.lastIndexOf(QLatin1Char('.'));
+ libFile = libFile.left(lastDot) + QLatin1String(".olb");
+ if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK)
+ return libFile;
+
+ libFile = QString();
+ return libFile;
+}
+
+void qAxCleanup()
+{
+ if (!initCount)
+ qWarning("qAxInit/qAxCleanup mismatch");
+
+ if (--initCount)
+ return;
+
+ delete qax_factory;
+ qax_factory = 0;
+
+ if (qAxTypeLibrary) {
+ qAxTypeLibrary->Release();
+ qAxTypeLibrary = 0;
+ }
+
+ DeleteCriticalSection(&qAxModuleSection);
+}
+
+unsigned long qAxLock()
+{
+ EnterCriticalSection(&qAxModuleSection);
+ unsigned long ref = ++qAxModuleRef;
+ LeaveCriticalSection(&qAxModuleSection);
+ return ref;
+}
+
+unsigned long qAxUnlock()
+{
+ if (!initCount) // cleaned up already
+ return 0;
+
+ EnterCriticalSection(&qAxModuleSection);
+ unsigned long ref = --qAxModuleRef;
+ LeaveCriticalSection(&qAxModuleSection);
+
+ if (!ref)
+ qax_shutDown();
+ return ref;
+}
+
+unsigned long qAxLockCount()
+{
+ return qAxModuleRef;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Registry
+/////////////////////////////////////////////////////////////////////////////
+
+extern bool qax_disable_inplaceframe;
+
+QString qax_clean_type(const QString &type, const QMetaObject *mo)
+{
+ if (mo) {
+ int classInfoIdx = mo->indexOfClassInfo("CoClassAlias");
+ if (classInfoIdx != -1) {
+ const QMetaClassInfo classInfo = mo->classInfo(classInfoIdx);
+ return QLatin1String(classInfo.value());
+ }
+ }
+
+ QString alias(type);
+ alias.remove(QLatin1String("::"));
+ return alias;
+}
+
+// (Un)Register the ActiveX server in the registry.
+// The QAxFactory implementation provides the information.
+HRESULT UpdateRegistry(BOOL bRegister)
+{
+ qAxIsServer = false;
+ QString file = QString::fromWCharArray(qAxModuleFilename);
+ QString path = file.left(file.lastIndexOf(QLatin1Char('\\'))+1);
+ QString module = file.right(file.length() - path.length());
+ module = module.left(module.lastIndexOf(QLatin1Char('.')));
+
+ const QString appId = qAxFactory()->appID().toString().toUpper();
+ const QString libId = qAxFactory()->typeLibID().toString().toUpper();
+
+ QString libFile = qAxInit();
+ QString typeLibVersion;
+
+ TLIBATTR *libAttr = 0;
+ if (qAxTypeLibrary)
+ qAxTypeLibrary->GetLibAttr(&libAttr);
+ if (!libAttr)
+ return SELFREG_E_TYPELIB;
+
+ DWORD major = libAttr->wMajorVerNum;
+ DWORD minor = libAttr->wMinorVerNum;
+ typeLibVersion = QString::number((uint)major) + QLatin1Char('.') + QString::number((uint)minor);
+
+ if (bRegister)
+ RegisterTypeLib(qAxTypeLibrary, (wchar_t*)libFile.utf16(), 0);
+ else
+ UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind);
+
+ qAxTypeLibrary->ReleaseTLibAttr(libAttr);
+
+ if (typeLibVersion.isEmpty())
+ typeLibVersion = QLatin1String("1.0");
+
+ // check whether the user has permission to write to HKLM\Software\Classes
+ // if not, use HKCU\Software\Classes
+ QString keyPath(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"));
+ QSettings test(keyPath, QSettings::NativeFormat);
+ if (!test.isWritable())
+ keyPath = QLatin1String("HKEY_CURRENT_USER\\Software\\Classes");
+
+ QSettings settings(keyPath, QSettings::NativeFormat);
+
+ // we try to create the ActiveX widgets later on...
+ bool delete_qApp = false;
+ if (!qApp) {
+ int argc = 0;
+ (void)new QApplication(argc, 0);
+ delete_qApp = true;
+ }
+
+ if (bRegister) {
+ if (qAxOutProcServer) {
+ settings.setValue(QLatin1String("/AppID/") + appId + QLatin1String("/."), module);
+ settings.setValue(QLatin1String("/AppID/") + module + QLatin1String(".EXE/AppID"), appId);
+ }
+
+ QStringList keys = qAxFactory()->featureList();
+ for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
+ QString className = *key;
+ QObject *object = qAxFactory()->createObject(className);
+ const QMetaObject *mo = qAxFactory()->metaObject(className);
+ const QString classId = qAxFactory()->classID(className).toString().toUpper();
+
+ className = qax_clean_type(className, mo);
+
+ if (object) { // don't register subobject classes
+ QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
+ if (classVersion.isNull())
+ classVersion = QLatin1String("1.0");
+ bool insertable = mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Insertable")).value(), "yes");
+ bool control = object->isWidgetType();
+ const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
+ uint olemisc = OLEMISC_SETCLIENTSITEFIRST
+ |OLEMISC_ACTIVATEWHENVISIBLE
+ |OLEMISC_INSIDEOUT
+ |OLEMISC_CANTLINKINSIDE
+ |OLEMISC_RECOMPOSEONRESIZE;
+ if (!control)
+ olemisc |= OLEMISC_INVISIBLEATRUNTIME;
+ else if (object->findChild<QMenuBar*>() && !qax_disable_inplaceframe)
+ olemisc |= OLEMISC_WANTSTOMENUMERGE;
+
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class"));
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."), classId);
+ if (insertable)
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
+
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."), className + QLatin1String(" Class"));
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."), classId);
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
+
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/."), className + QLatin1String(" Class"));
+ if (file.endsWith(QLatin1String("exe"), Qt::CaseInsensitive))
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"), appId);
+ if (control)
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."), QVariant(QLatin1String("")));
+ if (insertable)
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
+ if (file.right(3).toLower() == QLatin1String("dll"))
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."), file);
+ else
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."),
+ QLatin1Char('\"') + file + QLatin1String("\" -activex"));
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."), control ? QLatin1String("1") : QLatin1String("0"));
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."), QString::number(olemisc));
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."), QVariant(QLatin1String("")));
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."), QLatin1Char('\"') +
+ file + QLatin1String("\", 101"));
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."), libId); settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."), classVersion);
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."), module + QLatin1Char('.') + className);
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classVersion.left(classVersion.indexOf(QLatin1Char('.'))));
+
+ QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
+ if (!mime.isEmpty()) {
+ QStringList mimeTypes = mime.split(QLatin1Char(';'));
+ for (int m = 0; m < mimeTypes.count(); ++m) {
+ mime = mimeTypes.at(m);
+ if (mime.isEmpty())
+ continue;
+ QString extension;
+ while (mime.contains(QLatin1Char(':'))) {
+ extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
+ mime = mime.left(mime.length() - extension.length() - 1);
+ // Prepend '.' before extension, if required.
+ extension = extension.trimmed();
+ if (extension[0] != QLatin1Char('.'))
+ extension = QLatin1Char('.') + extension;
+ }
+
+ if (!extension.isEmpty()) {
+ settings.setValue(QLatin1Char('/') + extension + QLatin1String("/."), module + QLatin1Char('.') + className);
+ settings.setValue(QLatin1Char('/') + extension + QLatin1String("/Content Type"), mime);
+
+ mime = mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"), classId);
+ settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"), extension);
+ }
+ }
+ }
+
+ delete object;
+ }
+
+ qAxFactory()->registerClass(*key, &settings);
+ }
+ } else {
+ if (qAxOutProcServer) {
+ settings.remove(QLatin1String("/AppID/") + appId + QLatin1String("/."));
+ settings.remove(QLatin1String("/AppID/") + module + QLatin1String(".EXE"));
+ }
+ QStringList keys = qAxFactory()->featureList();
+ for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
+ QString className = *key;
+ const QMetaObject *mo = qAxFactory()->metaObject(className);
+ const QString classId = qAxFactory()->classID(className).toString().toUpper();
+ className = qax_clean_type(className, mo);
+
+ QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
+ if (classVersion.isNull())
+ classVersion = QLatin1String("1.0");
+ const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
+
+ qAxFactory()->unregisterClass(*key, &settings);
+
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
+
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className);
+
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Insertable/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."));
+ settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/."));
+ settings.remove(QLatin1String("/CLSID/") + classId);
+
+ QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
+ if (!mime.isEmpty()) {
+ QStringList mimeTypes = mime.split(QLatin1Char(';'));
+ for (int m = 0; m < mimeTypes.count(); ++m) {
+ mime = mimeTypes.at(m);
+ if (mime.isEmpty())
+ continue;
+ QString extension;
+ while (mime.contains(QLatin1Char(':'))) {
+ extension = mime.mid(mime.lastIndexOf(QLatin1Char(':')) + 1);
+ mime = mime.left(mime.length() - extension.length() - 1);
+ // Prepend '.' before extension, if required.
+ extension = extension.trimmed();
+ if (extension[0] != QLatin1Char('.'))
+ extension.prepend(QLatin1Char('.'));
+ }
+ if (!extension.isEmpty()) {
+ settings.remove(QLatin1Char('/') + extension + QLatin1String("/Content Type"));
+ settings.remove(QLatin1Char('/') + extension + QLatin1String("/."));
+ settings.remove(QLatin1Char('/') + extension);
+ mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"));
+ settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"));
+ settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/."));
+ settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime);
+ }
+ }
+ }
+ }
+ }
+
+ if (delete_qApp)
+ delete qApp;
+
+ qAxCleanup();
+ if (settings.status() == QSettings::NoError)
+ return S_OK;
+ return SELFREG_E_CLASS;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// IDL generator
+/////////////////////////////////////////////////////////////////////////////
+
+static QList<QByteArray> enums;
+static QList<QByteArray> enumValues;
+static QList<QByteArray> subtypes;
+
+static const char* const type_map[][2] =
+{
+ // QVariant/Qt Value data types
+ { "QString", "BSTR" },
+ { "QCString", "BSTR" },
+ { "bool", "VARIANT_BOOL" },
+ { "int", "int" },
+ { "uint", "unsigned int" },
+ { "double", "double" },
+ { "QColor", "OLE_COLOR" },
+ { "QDate", "DATE" },
+ { "QTime", "DATE" },
+ { "QDateTime", "DATE" },
+ { "QFont", "IFontDisp*" },
+ { "QPixmap", "IPictureDisp*" },
+ { "QVariant", "VARIANT" },
+ { "QVariantList", "SAFEARRAY(VARIANT)" },
+ { "QList<QVariant>", "SAFEARRAY(VARIANT)" },
+ { "quint64", "CY" },
+ { "qint64", "CY" },
+ { "qulonglong", "CY" },
+ { "qlonglong", "CY" },
+ { "QByteArray", "SAFEARRAY(BYTE)" },
+ { "QStringList", "SAFEARRAY(BSTR)" },
+ // Userdefined Qt datatypes - some not on Borland though
+ { "QCursor", "enum MousePointer" },
+ { "Qt::FocusPolicy", "enum FocusPolicy" },
+#ifndef Q_CC_BOR
+# if __REQUIRED_RPCNDR_H_VERSION__ >= Q_REQUIRED_RPCNDR_H_VERSION
+ { "QRect", "struct QRect" },
+ { "QSize", "struct QSize" },
+ { "QPoint", "struct QPoint" },
+# endif
+#endif
+ // And we support COM data types
+ { "BOOL", "BOOL" },
+ { "BSTR", "BSTR" },
+ { "OLE_COLOR", "OLE_COLOR" },
+ { "DATE", "DATE" },
+ { "VARIANT", "VARIANT" },
+ { "IDispatch", "IDispatch*" },
+ { "IUnknown", "IUnknown*" },
+ { "IDispatch*", "IDispatch*" },
+ { "IUnknown*", "IUnknown*" },
+ { 0, 0 }
+};
+
+static QByteArray convertTypes(const QByteArray &qtype, bool *ok)
+{
+ qRegisterMetaType("IDispatch*", (void**)0);
+ qRegisterMetaType("IUnknown*", (void**)0);
+
+ *ok = false;
+
+ int i = 0;
+ while (type_map[i][0]) {
+ if (qtype == type_map[i][0] && type_map[i][1]) {
+ *ok = true;
+ return type_map[i][1];
+ }
+ ++i;
+ }
+ if (enums.contains(qtype)) {
+ *ok = true;
+ return "enum " + qtype;
+ }
+ if (subtypes.contains(qtype)) {
+ *ok = true;
+ } else if (qtype.endsWith('*')) {
+ QByteArray cleanType = qtype.left(qtype.length() - 1);
+ const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(cleanType.constData()));
+ if (mo) {
+ cleanType = qax_clean_type(QString::fromLatin1(cleanType), mo).toLatin1();
+ if (subtypes.contains(cleanType)) {
+ *ok = true;
+ return cleanType + '*';
+ }
+ }
+ }
+ return qtype;
+}
+
+static const char* const keyword_map[][2] =
+{
+ { "aggregatable", "aggregating" },
+ { "allocate", "alloc" },
+ { "appobject", "appObject" },
+ { "arrays", "array" },
+ { "async", "asynchronous" },
+ { "bindable", "binding" },
+ { "Boolean", "boolval" },
+ { "boolean", "boolval" },
+ { "broadcast", "broadCast" },
+ { "callback", "callBack" },
+ { "decode", "deCode" },
+ { "default", "defaulted" },
+ { "defaultbind", "defaultBind" },
+ { "defaultvalue", "defaultValue" },
+ { "encode" "enCode" },
+ { "endpoint", "endPoint" },
+ { "hidden", "isHidden" },
+ { "ignore", "ignore_" },
+ { "local", "local_" },
+ { "notify", "notify_" },
+ { "object", "object_" },
+ { "optimize", "optimize_" },
+ { "optional", "optional_" },
+ { "out", "out_" },
+ { "pipe", "pipe_" },
+ { "proxy", "proxy_" },
+ { "ptr", "pointer" },
+ { "readonly", "readOnly" },
+ { "small", "small_" },
+ { "source", "source_" },
+ { "string", "string_" },
+ { "uuid", "uuid_" },
+ { 0, 0 }
+};
+
+static QByteArray replaceKeyword(const QByteArray &name)
+{
+ int i = 0;
+ while (keyword_map[i][0]) {
+ if (name == keyword_map[i][0] && keyword_map[i][1])
+ return keyword_map[i][1];
+ ++i;
+ }
+ return name;
+}
+
+static QMap<QByteArray, int> mapping;
+
+static QByteArray renameOverloads(const QByteArray &name)
+{
+ QByteArray newName = name;
+
+ int n = mapping.value(name);
+ if (mapping.contains(name)) {
+ int n = mapping.value(name);
+ newName = name + '_' + QByteArray::number(n);
+ mapping.insert(name, n+1);
+ } else {
+ mapping.insert(name, 1);
+ }
+
+ return newName;
+}
+
+// filter out some properties
+static const char* const ignore_props[] =
+{
+ "name",
+ "objectName",
+ "isTopLevel",
+ "isDialog",
+ "isModal",
+ "isPopup",
+ "isDesktop",
+ "geometry",
+ "pos",
+ "frameSize",
+ "frameGeometry",
+ "size",
+ "sizeHint",
+ "minimumSizeHint",
+ "microFocusHint",
+ "rect",
+ "childrenRect",
+ "childrenRegion",
+ "minimumSize",
+ "maximumSize",
+ "sizeIncrement",
+ "baseSize",
+ "ownPalette",
+ "ownFont",
+ "ownCursor",
+ "visibleRect",
+ "isActiveWindow",
+ "underMouse",
+ "visible",
+ "hidden",
+ "minimized",
+ "focus",
+ "focusEnabled",
+ "customWhatsThis",
+ "shown",
+ "windowOpacity",
+ 0
+};
+
+// filter out some slots
+static const char* const ignore_slots[] =
+{
+ "deleteLater",
+ "setMouseTracking",
+ "update",
+ "repaint",
+ "iconify",
+ "showMinimized",
+ "showMaximized",
+ "showFullScreen",
+ "showNormal",
+ "polish",
+ "constPolish",
+ "stackUnder",
+ "setShown",
+ "setHidden",
+ "move_1",
+ "resize_1",
+ "setGeometry_1",
+ 0
+};
+
+static bool ignore(const char *test, const char *const *table)
+{
+ if (!test)
+ return true;
+ int i = 0;
+ while (table[i]) {
+ if (!strcmp(test, table[i]))
+ return true;
+ ++i;
+ }
+ return false;
+}
+
+bool ignoreSlots(const char *test)
+{
+ return ignore(test, ignore_slots);
+}
+
+bool ignoreProps(const char *test)
+{
+ return ignore(test, ignore_props);
+}
+
+#define STRIPCB(x) x = x.mid(1, x.length()-2)
+
+static QByteArray prototype(const QList<QByteArray> &parameterTypes, const QList<QByteArray> &parameterNames, bool *ok)
+{
+ QByteArray prototype;
+
+ for (int p = 0; p < parameterTypes.count() && *ok; ++p) {
+ bool out = false;
+ QByteArray type(parameterTypes.at(p));
+ QByteArray name(parameterNames.at(p));
+
+ if (type.endsWith('&')) {
+ out = true;
+ type.truncate(type.length() - 1);
+ } else if (type.endsWith("**")) {
+ out = true;
+ type.truncate(type.length() - 1);
+ } else if (type.endsWith('*') && !subtypes.contains(type)) {
+ type.truncate(type.length() - 1);
+ }
+ if (type.isEmpty()) {
+ *ok = false;
+ break;
+ }
+ type = convertTypes(type, ok);
+ if (!out)
+ prototype += "[in] " + type + ' ';
+ else
+ prototype += "[in,out] " + type + ' ';
+
+ if (out)
+ prototype += '*';
+ if (name.isEmpty())
+ prototype += 'p' + QByteArray::number(p);
+ else
+ prototype += "p_" + replaceKeyword(name);
+
+ if (p < parameterTypes.count() - 1)
+ prototype += ", ";
+ }
+
+ return prototype;
+}
+
+static QByteArray addDefaultArguments(const QByteArray &prototype, int numDefArgs)
+{
+ // nothing to do, or unsupported anyway
+ if (!numDefArgs || prototype.contains("/**"))
+ return prototype;
+
+ QByteArray ptype(prototype);
+ int in = -1;
+ while (numDefArgs) {
+ in = ptype.lastIndexOf(']', in);
+ ptype.replace(in, 1, ",optional]");
+ in = ptype.indexOf(' ', in) + 1;
+ QByteArray type = ptype.mid(in, ptype.indexOf(' ', in) - in);
+ if (type == "enum")
+ type += ' ' + ptype.mid(in + 5, ptype.indexOf(' ', in + 5) - in - 5);
+ ptype.replace(in, type.length(), QByteArray("VARIANT /*was: ") + type + "*/");
+ --numDefArgs;
+ }
+
+ return ptype;
+}
+
+static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &className, bool isBindable, QTextStream &out)
+{
+ int id = 1;
+ int i = 0;
+ if (!mo)
+ return 3;
+
+ QString topclass = qAxFactory()->exposeToSuperClass(className);
+ if (topclass.isEmpty())
+ topclass = QLatin1String("QObject");
+ bool hasStockEvents = qAxFactory()->hasStockEvents(className);
+
+ const QMetaObject *pmo = mo;
+ do {
+ pmo = pmo->superClass();
+ } while (pmo && topclass != QString::fromLatin1(pmo->className()));
+
+ int enumoff = pmo ? pmo->enumeratorOffset() : mo->enumeratorOffset();
+ int methodoff = pmo ? pmo->methodOffset() : mo->methodOffset();
+ int propoff = pmo ? pmo->propertyOffset() : mo->propertyOffset();
+
+ int qtProps = 0;
+ int qtSlots = 0;
+
+ bool control = false;
+
+ if (o && o->isWidgetType()) {
+ qtProps = QWidget::staticMetaObject.propertyCount();
+ qtSlots = QWidget::staticMetaObject.methodCount();
+ control = true;
+ }
+
+ QString classID = qAxFactory()->classID(className).toString().toUpper();
+ if (QUuid(classID).isNull())
+ return 4;
+ STRIPCB(classID);
+ QString interfaceID = qAxFactory()->interfaceID(className).toString().toUpper();
+ if (QUuid(interfaceID).isNull())
+ return 5;
+ STRIPCB(interfaceID);
+ QString eventsID = qAxFactory()->eventsID(className).toString().toUpper();
+ bool hasEvents = !QUuid(eventsID).isNull();
+ STRIPCB(eventsID);
+
+ QString cleanClassName = qax_clean_type(className, mo);
+ QString defProp(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultProperty")).value()));
+ QString defSignal(QLatin1String(mo->classInfo(mo->indexOfClassInfo("DefaultSignal")).value()));
+
+ for (i = enumoff; i < mo->enumeratorCount(); ++i) {
+ const QMetaEnum enumerator = mo->enumerator(i);
+ if (enums.contains(enumerator.name()))
+ continue;
+
+ enums.append(enumerator.name());
+
+ out << "\tenum " << enumerator.name() << " {" << endl;
+
+ for (int j = 0; j < enumerator.keyCount(); ++j) {
+ QByteArray key(enumerator.key(j));
+ while (enumValues.contains(key)) {
+ key += '_';
+ }
+ enumValues.append(key);
+ uint value = (uint)enumerator.value(j);
+ key = key.leftJustified(20);
+ out << "\t\t" << key << "\t= ";
+ if (enumerator.isFlag())
+ out << "0x" << QByteArray::number(value, 16).rightJustified(8, '0');
+ else
+ out << value;
+ if (j < enumerator.keyCount()-1)
+ out << ", ";
+ out << endl;
+ }
+ out << "\t};" << endl << endl;
+ }
+
+ // mouse cursor enum for QCursor support
+ if (!enums.contains("MousePointer")) {
+ enums.append("MousePointer");
+ out << "\tenum MousePointer {" << endl;
+ out << "\t\tArrowCursor = " << Qt::ArrowCursor << ',' << endl;
+ out << "\t\tUpArrowCursor = " << Qt::UpArrowCursor << ',' << endl;
+ out << "\t\tCrossCursor = " << Qt::CrossCursor << ',' << endl;
+ out << "\t\tWaitCursor = " << Qt::WaitCursor << ',' << endl;
+ out << "\t\tIBeamCursor = " << Qt::IBeamCursor << ',' << endl;
+ out << "\t\tSizeVerCursor = " << Qt::SizeVerCursor << ',' << endl;
+ out << "\t\tSizeHorCursor = " << Qt::SizeHorCursor << ',' << endl;
+ out << "\t\tSizeBDiagCursor = " << Qt::SizeBDiagCursor << ',' << endl;
+ out << "\t\tSizeFDiagCursor = " << Qt::SizeFDiagCursor << ',' << endl;
+ out << "\t\tSizeAllCursor = " << Qt::SizeAllCursor << ',' << endl;
+ out << "\t\tBlankCursor = " << Qt::BlankCursor << ',' << endl;
+ out << "\t\tSplitVCursor = " << Qt::SplitVCursor << ',' << endl;
+ out << "\t\tSplitHCursor = " << Qt::SplitHCursor << ',' << endl;
+ out << "\t\tPointingHandCursor = " << Qt::PointingHandCursor << ',' << endl;
+ out << "\t\tForbiddenCursor = " << Qt::ForbiddenCursor << ',' << endl;
+ out << "\t\tWhatsThisCursor = " << Qt::WhatsThisCursor << ',' << endl;
+ out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl;
+ out << "\t};" << endl << endl;
+ }
+ if (!enums.contains("FocusPolicy")) {
+ enums.append("FocusPolicy");
+ out << "\tenum FocusPolicy {" << endl;
+ out << "\t\tNoFocus = " << Qt::NoFocus << ',' << endl;
+ out << "\t\tTabFocus = " << Qt::TabFocus << ',' << endl;
+ out << "\t\tClickFocus = " << Qt::ClickFocus << ',' << endl;
+ out << "\t\tStrongFocus = " << Qt::StrongFocus << ',' << endl;
+ out << "\t\tWheelFocus = " << Qt::WheelFocus << endl;
+ out << "\t};" << endl << endl;
+ }
+
+ out << endl;
+ out << "\t[" << endl;
+ out << "\t\tuuid(" << interfaceID << ")," << endl;
+ out << "\t\thelpstring(\"" << cleanClassName << " Interface\")" << endl;
+ out << "\t]" << endl;
+ out << "\tdispinterface I" << cleanClassName << endl;
+ out << "\t{" << endl;
+
+ out << "\tproperties:" << endl;
+ for (i = propoff; i < mo->propertyCount(); ++i) {
+ const QMetaProperty property = mo->property(i);
+ /* if (property.testFlags(QMetaProperty::Override))
+ continue;*/
+ if (i <= qtProps && ignoreProps(property.name()))
+ continue;
+ if (!property.name() || mo->indexOfProperty(property.name()) > i)
+ continue;
+
+ bool ok = true;
+ QByteArray type(convertTypes(property.typeName(), &ok));
+ QByteArray name(replaceKeyword(property.name()));
+
+ if (!ok)
+ out << "\t/****** Property is of unsupported datatype" << endl;
+
+ out << "\t\t[id(" << id << ')';
+ if (!property.isWritable())
+ out << ", readonly";
+ if (isBindable && property.isScriptable(o))
+ out << ", bindable";
+ if (!property.isDesignable(o))
+ out << ", nonbrowsable";
+ if (isBindable)
+ out << ", requestedit";
+ if (defProp == QLatin1String(name))
+ out << ", uidefault";
+ out << "] " << type << ' ' << name << ';' << endl;
+
+ if (!ok)
+ out << "\t******/" << endl;
+ ++id;
+ }
+ out << endl;
+ out << "\tmethods:" << endl;
+ int numDefArgs = 0;
+ QByteArray outBuffer;
+ for (i = methodoff; i < mo->methodCount(); ++i) {
+ const QMetaMethod slot = mo->method(i);
+ if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal)
+ continue;
+
+ if (slot.attributes() & QMetaMethod::Cloned) {
+ ++numDefArgs;
+ continue;
+ }
+ if (!outBuffer.isEmpty()) {
+ outBuffer = addDefaultArguments(outBuffer, numDefArgs);
+ numDefArgs = 0;
+ out << outBuffer;
+ outBuffer = QByteArray();
+ }
+
+ QByteArray signature(slot.signature());
+ QByteArray name(signature.left(signature.indexOf('(')));
+ if (i <= qtSlots && ignoreSlots(name))
+ continue;
+
+ signature = signature.mid(name.length() + 1);
+ signature.truncate(signature.length() - 1);
+ name = renameOverloads(replaceKeyword(name));
+ if (ignoreSlots(name))
+ continue;
+
+ QList<QByteArray> parameterTypes(slot.parameterTypes());
+ QList<QByteArray> parameterNames(slot.parameterNames());
+
+ bool ok = true;
+ QByteArray type = slot.typeName();
+ if (type.isEmpty())
+ type = "void";
+ else
+ type = convertTypes(type, &ok);
+
+ QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
+ if (!ok)
+ outBuffer += "\t/****** Slot parameter uses unsupported datatype\n";
+
+ outBuffer += "\t\t[id(" + QString::number(id).toLatin1() + ")] " + type + ' ' + name + '(' + ptype + ");\n";
+
+ if (!ok)
+ outBuffer += "\t******/\n";
+ ++id;
+ }
+ if (!outBuffer.isEmpty()) {
+ outBuffer = addDefaultArguments(outBuffer, numDefArgs);
+ numDefArgs = 0;
+ out << outBuffer;
+ outBuffer = QByteArray();
+ }
+ out << "\t};" << endl << endl;
+
+ mapping.clear();
+ id = 1;
+
+ if (hasEvents) {
+ out << "\t[" << endl;
+ out << "\t\tuuid(" << eventsID << ")," << endl;
+ out << "\t\thelpstring(\"" << cleanClassName << " Events Interface\")" << endl;
+ out << "\t]" << endl;
+ out << "\tdispinterface I" << cleanClassName << "Events" << endl;
+ out << "\t{" << endl;
+ out << "\tproperties:" << endl;
+ out << "\tmethods:" << endl;
+
+ if (hasStockEvents) {
+ out << "\t/****** Stock events ******/" << endl;
+ out << "\t\t[id(DISPID_CLICK)] void Click();" << endl;
+ out << "\t\t[id(DISPID_DBLCLICK)] void DblClick();" << endl;
+ out << "\t\t[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);" << endl;
+ out << "\t\t[id(DISPID_KEYPRESS)] void KeyPress(short* KeyAscii);" << endl;
+ out << "\t\t[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);" << endl;
+ out << "\t\t[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
+ out << "\t\t[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl;
+ out << "\t\t[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);" << endl << endl;
+ }
+
+ for (i = methodoff; i < mo->methodCount(); ++i) {
+ const QMetaMethod signal = mo->method(i);
+ if (signal.methodType() != QMetaMethod::Signal)
+ continue;
+
+ QByteArray signature(signal.signature());
+ QByteArray name(signature.left(signature.indexOf('(')));
+ signature = signature.mid(name.length() + 1);
+ signature.truncate(signature.length() - 1);
+
+ QList<QByteArray> parameterTypes(signal.parameterTypes());
+ QList<QByteArray> parameterNames(signal.parameterNames());
+
+ bool isDefault = defSignal == QLatin1String(name);
+ name = renameOverloads(replaceKeyword(name));
+ bool ok = true;
+
+ QByteArray type = signal.typeName();
+ if (!type.isEmpty()) // signals with return value not supported
+ continue;
+
+ QByteArray ptype(prototype(parameterTypes, parameterNames, &ok));
+ if (!ok)
+ out << "\t/****** Signal parameter uses unsupported datatype" << endl;
+
+ out << "\t\t[id(" << id << ')';
+ if (isDefault)
+ out << ", uidefault";
+ out << "] void " << name << '(' << ptype << ");" << endl;
+
+ if (!ok)
+ out << "\t******/" << endl;
+ ++id;
+ }
+ out << "\t};" << endl << endl;
+ }
+
+ out << "\t[" << endl;
+
+ if (qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no"))
+ out << "\t\taggregatable," << endl;
+ if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes"))
+ out << "\t\tappobject," << endl;
+ if (mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value())
+ out << "\t\tlicensed," << endl;
+ const char *helpString = mo->classInfo(mo->indexOfClassInfo("Description")).value();
+ if (helpString)
+ out << "\t\thelpstring(\"" << helpString << "\")," << endl;
+ else
+ out << "\t\thelpstring(\"" << cleanClassName << " Class\")," << endl;
+ const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value();
+ if (classVersion)
+ out << "\t\tversion(" << classVersion << ")," << endl;
+ out << "\t\tuuid(" << classID << ')';
+ if (control) {
+ out << ", " << endl;
+ out << "\t\tcontrol";
+ } else if (!o) {
+ out << ", " << endl;
+ out << "\t\tnoncreatable";
+ }
+ out << endl;
+ out << "\t]" << endl;
+ out << "\tcoclass " << cleanClassName << endl;
+ out << "\t{" << endl;
+ out << "\t\t[default] dispinterface I" << cleanClassName << ';' << endl;
+ if (hasEvents)
+ out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl;
+ out << "\t};" << endl;
+
+ return S_OK;
+}
+
+#if defined(Q_CC_BOR)
+extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver)
+#else
+extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
+#endif
+{
+ qAxIsServer = false;
+ QTextStream out;
+ if (outfile.contains(QLatin1String("\\"))) {
+ QString outpath = outfile.left(outfile.lastIndexOf(QLatin1String("\\")));
+ QDir dir;
+ dir.mkpath(outpath);
+ }
+ QFile file(outfile);
+ file.remove();
+
+ QString filebase = QString::fromWCharArray(qAxModuleFilename);
+ filebase = filebase.left(filebase.lastIndexOf(QLatin1Char('.')));
+
+ QString appID = qAxFactory()->appID().toString().toUpper();
+ if (QUuid(appID).isNull())
+ return 1;
+ STRIPCB(appID);
+ QString typeLibID = qAxFactory()->typeLibID().toString().toUpper();
+ if (QUuid(typeLibID).isNull())
+ return 2;
+ STRIPCB(typeLibID);
+ QString typelib = filebase.right(filebase.length() - filebase.lastIndexOf(QLatin1String("\\"))-1);
+
+ if (!file.open(QIODevice::WriteOnly))
+ return -1;
+
+ out.setDevice(&file);
+
+ QString version(ver.unicode(), ver.length());
+ while (version.count(QLatin1Char('.')) > 1) {
+ int lastdot = version.lastIndexOf(QLatin1Char('.'));
+ version = version.left(lastdot) + version.right(version.length() - lastdot - 1);
+ }
+ if (version.isEmpty())
+ version = QLatin1String("1.0");
+
+ QString idQRect(QUuid(CLSID_QRect).toString());
+ STRIPCB(idQRect);
+ QString idQSize(QUuid(CLSID_QSize).toString());
+ STRIPCB(idQSize);
+ QString idQPoint(QUuid(CLSID_QPoint).toString());
+ STRIPCB(idQPoint);
+
+ out << "/****************************************************************************" << endl;
+ out << "** Interface definition generated for ActiveQt project" << endl;
+ out << "**" << endl;
+ out << "** '" << QString::fromWCharArray(qAxModuleFilename) << '\'' << endl;
+ out << "**" << endl;
+ out << "** Created: " << QDateTime::currentDateTime().toString() << endl;
+ out << "**" << endl;
+ out << "** WARNING! All changes made in this file will be lost!" << endl;
+ out << "****************************************************************************/" << endl << endl;
+
+ out << "import \"ocidl.idl\";" << endl;
+ out << "#include <olectl.h>" << endl << endl;
+
+ // dummy application to create widgets
+ bool delete_qApp = false;
+ if (!qApp) {
+ int argc;
+ (void)new QApplication(argc, 0);
+ delete_qApp = true;
+ }
+
+ out << '[' << endl;
+ out << "\tuuid(" << typeLibID << ")," << endl;
+ out << "\tversion(" << version << ")," << endl;
+ out << "\thelpstring(\"" << typelib << ' ' << version << " Type Library\")" << endl;
+ out << ']' << endl;
+ out << "library " << typelib << "Lib" << endl;
+ out << '{' << endl;
+ out << "\timportlib(\"stdole32.tlb\");" << endl;
+ out << "\timportlib(\"stdole2.tlb\");" << endl << endl;
+
+ QStringList keys = qAxFactory()->featureList();
+ QStringList::ConstIterator key;
+
+ out << "\t/************************************************************************" << endl;
+ out << "\t** If this causes a compile error in MIDL you need to upgrade the" << endl;
+ out << "\t** Platform SDK you are using. Download the SDK from msdn.microsoft.com" << endl;
+ out << "\t** and make sure that both the system and the Visual Studio environment" << endl;
+ out << "\t** use the correct files." << endl;
+ out << "\t**" << endl;
+
+#ifndef Q_CC_BOR
+#if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
+ out << "\t** Required version of MIDL could not be verified. QRect, QSize and QPoint" << endl;
+ out << "\t** support needs an updated Platform SDK to be installed." << endl;
+ out << "\t*************************************************************************" << endl;
+#else
+ out << "\t************************************************************************/" << endl;
+#endif
+
+ out << endl;
+ out << "\t[uuid(" << idQRect << ")]" << endl;
+ out << "\tstruct QRect {" << endl;
+ out << "\t\tint left;" << endl;
+ out << "\t\tint top;" << endl;
+ out << "\t\tint right;" << endl;
+ out << "\t\tint bottom;" << endl;
+ out << "\t};" << endl << endl;
+
+ out << "\t[uuid(" << idQSize << ")]" << endl;
+ out << "\tstruct QSize {" << endl;
+ out << "\t\tint width;" << endl;
+ out << "\t\tint height;" << endl;
+ out << "\t};" << endl << endl;
+
+ out << "\t[uuid(" << idQPoint << ")]" << endl;
+ out << "\tstruct QPoint {" << endl;
+ out << "\t\tint x;" << endl;
+ out << "\t\tint y;" << endl;
+ out << "\t};" << endl;
+#if __REQUIRED_RPCNDR_H_VERSION__ < Q_REQUIRED_RPCNDR_H_VERSION
+ out << "\t*/" << endl;
+#endif
+#else
+ out << "\t** Custom data types not supported with Borland." << endl;
+ out << "\t*************************************************************************" << endl;
+#endif
+ out << endl;
+
+ out << "\t/* Forward declaration of classes that might be used as parameters */" << endl << endl;
+
+ int res = S_OK;
+ for (key = keys.begin(); key != keys.end(); ++key) {
+ QByteArray className = (*key).toLatin1();
+ const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
+ // We have meta object information for this type. Forward declare it.
+ if (mo) {
+ QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
+ out << "\tcoclass " << cleanType << ';' << endl;
+ subtypes.append(cleanType);
+ qRegisterMetaType(cleanType, (void**)0);
+ cleanType += '*';
+ subtypes.append(cleanType);
+ qRegisterMetaType(cleanType, (void**)0);
+ }
+ }
+ out << endl;
+
+ for (key = keys.begin(); key != keys.end(); ++key) {
+ QByteArray className = (*key).toLatin1();
+ const QMetaObject *mo = qAxFactory()->metaObject(QString::fromLatin1(className.constData()));
+ // We have meta object information for this type. Define it.
+ if (mo) {
+ QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
+ // It's not a control class, so it is actually a subtype. Define it.
+ if (!o)
+ res = classIDL(0, mo, QString::fromLatin1(className), false, out);
+ delete o;
+ }
+ }
+
+ out << endl;
+ if (res != S_OK)
+ goto ErrorInClass;
+
+ for (key = keys.begin(); key != keys.end(); ++key) {
+ QByteArray className = (*key).toLatin1();
+ QObject *o = qAxFactory()->createObject(QString::fromLatin1(className.constData()));
+ if (!o)
+ continue;
+ const QMetaObject *mo = o->metaObject();
+ QAxBindable *bind = (QAxBindable*)o->qt_metacast("QAxBindable");
+ bool isBindable = bind != 0;
+
+ QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
+ subtypes.append(cleanType);
+ subtypes.append(cleanType + '*');
+ res = classIDL(o, mo, QString::fromLatin1(className.constData()), isBindable, out);
+ delete o;
+ if (res != S_OK)
+ break;
+ }
+
+ out << "};" << endl;
+ out.flush();
+
+ErrorInClass:
+ if (delete_qApp)
+ delete qApp;
+
+ if (res != S_OK) {
+ file.close();
+ file.remove();
+ }
+
+ return res;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/control/qaxserver.def b/src/activeqt/control/qaxserver.def
new file mode 100644
index 0000000..a00638d
--- /dev/null
+++ b/src/activeqt/control/qaxserver.def
@@ -0,0 +1,8 @@
+; mfc_test.def : Declares the module parameters.
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
+ DumpIDL PRIVATE
diff --git a/src/activeqt/control/qaxserver.ico b/src/activeqt/control/qaxserver.ico
new file mode 100644
index 0000000..c80d36a
--- /dev/null
+++ b/src/activeqt/control/qaxserver.ico
Binary files differ
diff --git a/src/activeqt/control/qaxserver.rc b/src/activeqt/control/qaxserver.rc
new file mode 100644
index 0000000..390e481
--- /dev/null
+++ b/src/activeqt/control/qaxserver.rc
@@ -0,0 +1,2 @@
+1 TYPELIB "qaxserver.rc"
+1 ICON DISCARDABLE "qaxserver.ico"
diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp
new file mode 100644
index 0000000..a2f9579
--- /dev/null
+++ b/src/activeqt/control/qaxserverbase.cpp
@@ -0,0 +1,4444 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#define QT_NO_CAST_TO_ASCII
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qabstracteventdispatcher.h>
+#include <qapplication.h>
+#include <qbuffer.h>
+#include <qdatastream.h>
+#include <qdebug.h>
+#include <qevent.h>
+#include <qeventloop.h>
+#include <qfile.h>
+#include <qpointer.h>
+#include <qhash.h>
+#include <qmap.h>
+#include <qmenubar.h>
+#include <qmenu.h>
+#include <qmetaobject.h>
+#include <qpixmap.h>
+#include <qstatusbar.h>
+#include <qwhatsthis.h>
+#include <ocidl.h>
+#include <olectl.h>
+#include <private/qcoreapplication_p.h>
+
+#include "qaxfactory.h"
+#include "qaxbindable.h"
+#include "qaxaggregated.h"
+
+#include "../shared/qaxtypes.h"
+
+#if defined Q_CC_GNU
+# include <w32api.h>
+#endif
+
+#ifndef Q_OS_WIN64
+#define ULONG_PTR DWORD
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern HHOOK qax_hhook;
+
+// in qaxserver.cpp
+extern ITypeLib *qAxTypeLibrary;
+extern QAxFactory *qAxFactory();
+extern unsigned long qAxLock();
+extern unsigned long qAxUnlock();
+extern HANDLE qAxInstance;
+extern bool qAxOutProcServer;
+
+static int invokeCount = 0;
+
+#ifdef QT_DEBUG
+unsigned long qaxserverbase_instance_count = 0;
+#endif
+
+// in qaxserverdll.cpp
+extern bool qax_ownQApp;
+
+struct QAxExceptInfo
+{
+ QAxExceptInfo(int c, const QString &s, const QString &d, const QString &x)
+ : code(c), src(s), desc(d), context(x)
+ {
+ }
+ int code;
+ QString src;
+ QString desc;
+ QString context;
+};
+
+
+bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+
+/*
+ \class QAxServerBase
+ \brief The QAxServerBase class is an ActiveX control hosting a QWidget.
+
+ \internal
+*/
+class QAxServerBase :
+ public QObject,
+ public IAxServerBase,
+ public IDispatch,
+ public IOleObject,
+ public IOleControl,
+#if defined Q_CC_GNU
+# if (__W32API_MAJOR_VERSION < 2 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION < 5))
+ public IViewObject, // this should not be needed as IViewObject2 is meant to inherit from this,
+ // untill the mingw headers are fixed this will need to stay.
+# endif
+#endif
+ public IViewObject2,
+ public IOleInPlaceObject,
+ public IOleInPlaceActiveObject,
+ public IProvideClassInfo2,
+ public IConnectionPointContainer,
+ public IPersistStream,
+ public IPersistStreamInit,
+ public IPersistStorage,
+ public IPersistPropertyBag,
+ public IPersistFile,
+ public IDataObject
+{
+public:
+ typedef QMap<QUuid,IConnectionPoint*> ConnectionPoints;
+ typedef QMap<QUuid,IConnectionPoint*>::Iterator ConnectionPointsIterator;
+
+ QAxServerBase(const QString &classname, IUnknown *outerUnknown);
+ QAxServerBase(QObject *o);
+
+ void init();
+
+ ~QAxServerBase();
+
+// Window creation
+ HWND create(HWND hWndParent, RECT& rcPos);
+ HMENU createPopup(QMenu *popup, HMENU oldMenu = 0);
+ void createMenu(QMenuBar *menuBar);
+ void removeMenu();
+
+ static LRESULT QT_WIN_CALLBACK ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+// Object registration with OLE
+ void registerActiveObject(IUnknown *object);
+ void revokeActiveObject();
+
+// IUnknown
+ unsigned long WINAPI AddRef()
+ {
+ if (m_outerUnknown)
+ return m_outerUnknown->AddRef();
+
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = ++ref;
+ LeaveCriticalSection(&refCountSection);
+
+ return r;
+ }
+ unsigned long WINAPI Release()
+ {
+ if (m_outerUnknown)
+ return m_outerUnknown->Release();
+
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = --ref;
+ LeaveCriticalSection(&refCountSection);
+
+ if (!r) {
+ delete this;
+ return 0;
+ }
+ return r;
+ }
+ HRESULT WINAPI QueryInterface(REFIID iid, void **iface);
+ HRESULT InternalQueryInterface(REFIID iid, void **iface);
+
+// IAxServerBase
+ IUnknown *clientSite() const
+ {
+ return m_spClientSite;
+ }
+
+ void emitPropertyChanged(const char*);
+ bool emitRequestPropertyChange(const char*);
+ QObject *qObject() const
+ {
+ return theObject;
+ }
+ void ensureMetaData();
+ bool isPropertyExposed(int index);
+
+ void reportError(int code, const QString &src, const QString &desc, const QString &context)
+ {
+ if (exception)
+ delete exception;
+ exception = new QAxExceptInfo(code, src, desc, context);
+ }
+
+// IDispatch
+ STDMETHOD(GetTypeInfoCount)(UINT* pctinfo);
+ STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo);
+ STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid);
+ STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
+ LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
+ EXCEPINFO* pexcepinfo, UINT* puArgErr);
+
+// IProvideClassInfo
+ STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo);
+
+// IProvideClassInfo2
+ STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID* pGUID);
+
+// IOleObject
+ STDMETHOD(Advise)(IAdviseSink* pAdvSink, DWORD* pdwConnection);
+ STDMETHOD(Close)(DWORD dwSaveOption);
+ STDMETHOD(DoVerb)(LONG iVerb, LPMSG lpmsg, IOleClientSite* pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect);
+ STDMETHOD(EnumAdvise)(IEnumSTATDATA** ppenumAdvise);
+ STDMETHOD(EnumVerbs)(IEnumOLEVERB** ppEnumOleVerb);
+ STDMETHOD(GetClientSite)(IOleClientSite** ppClientSite);
+ STDMETHOD(GetClipboardData)(DWORD dwReserved, IDataObject** ppDataObject);
+ STDMETHOD(GetExtent)(DWORD dwDrawAspect, SIZEL* psizel);
+ STDMETHOD(GetMiscStatus)(DWORD dwAspect, DWORD *pdwStatus);
+ STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk);
+ STDMETHOD(GetUserClassID)(CLSID* pClsid);
+ STDMETHOD(GetUserType)(DWORD dwFormOfType, LPOLESTR *pszUserType);
+ STDMETHOD(InitFromData)(IDataObject* pDataObject, BOOL fCreation, DWORD dwReserved);
+ STDMETHOD(IsUpToDate)();
+ STDMETHOD(SetClientSite)(IOleClientSite* pClientSite);
+ STDMETHOD(SetColorScheme)(LOGPALETTE* pLogPal);
+ STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL* psizel);
+ STDMETHOD(SetHostNames)(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj);
+ STDMETHOD(SetMoniker)(DWORD dwWhichMoniker, IMoniker* ppmk);
+ STDMETHOD(Unadvise)(DWORD dwConnection);
+ STDMETHOD(Update)();
+
+// IViewObject
+ STDMETHOD(Draw)(DWORD dwAspect, LONG lIndex, void *pvAspect, DVTARGETDEVICE *ptd,
+ HDC hicTargetDevice, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds,
+ BOOL(__stdcall*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue);
+ STDMETHOD(GetColorSet)(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
+ HDC hicTargetDev, LOGPALETTE **ppColorSet);
+ STDMETHOD(Freeze)(DWORD dwAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze);
+ STDMETHOD(Unfreeze)(DWORD dwFreeze);
+ STDMETHOD(SetAdvise)(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink);
+ STDMETHOD(GetAdvise)(DWORD *aspects, DWORD *advf, IAdviseSink **pAdvSink);
+
+// IViewObject2
+ STDMETHOD(GetExtent)(DWORD dwAspect, LONG lindex, DVTARGETDEVICE *ptd, LPSIZEL lpsizel);
+
+// IOleControl
+ STDMETHOD(FreezeEvents)(BOOL);
+ STDMETHOD(GetControlInfo)(LPCONTROLINFO);
+ STDMETHOD(OnAmbientPropertyChange)(DISPID);
+ STDMETHOD(OnMnemonic)(LPMSG);
+
+// IOleWindow
+ STDMETHOD(GetWindow)(HWND *pHwnd);
+ STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
+
+// IOleInPlaceObject
+ STDMETHOD(InPlaceDeactivate)();
+ STDMETHOD(UIDeactivate)();
+ STDMETHOD(SetObjectRects)(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
+ STDMETHOD(ReactivateAndUndo)();
+
+// IOleInPlaceActiveObject
+ STDMETHOD(TranslateAcceleratorW)(MSG *pMsg);
+ STDMETHOD(TranslateAcceleratorA)(MSG *pMsg);
+ STDMETHOD(OnFrameWindowActivate)(BOOL);
+ STDMETHOD(OnDocWindowActivate)(BOOL fActivate);
+ STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow);
+ STDMETHOD(EnableModeless)(BOOL);
+
+// IConnectionPointContainer
+ STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints**);
+ STDMETHOD(FindConnectionPoint)(REFIID, IConnectionPoint**);
+
+// IPersist
+ STDMETHOD(GetClassID)(GUID*clsid)
+ {
+ *clsid = qAxFactory()->classID(class_name);
+ return S_OK;
+ }
+
+// IPersistStreamInit
+ STDMETHOD(InitNew)(VOID);
+ STDMETHOD(IsDirty)();
+ STDMETHOD(Load)(IStream *pStm);
+ STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
+ STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);
+
+// IPersistPropertyBag
+ STDMETHOD(Load)(IPropertyBag *, IErrorLog *);
+ STDMETHOD(Save)(IPropertyBag *, BOOL, BOOL);
+
+// IPersistStorage
+ STDMETHOD(InitNew)(IStorage *pStg);
+ STDMETHOD(Load)(IStorage *pStg);
+ STDMETHOD(Save)(IStorage *pStg, BOOL fSameAsLoad);
+ STDMETHOD(SaveCompleted)(IStorage *pStgNew);
+ STDMETHOD(HandsOffStorage)();
+
+// IPersistFile
+ STDMETHOD(SaveCompleted)(LPCOLESTR fileName);
+ STDMETHOD(GetCurFile)(LPOLESTR *currentFile);
+ STDMETHOD(Load)(LPCOLESTR fileName, DWORD mode);
+ STDMETHOD(Save)(LPCOLESTR fileName, BOOL fRemember);
+
+// IDataObject
+ STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
+ STDMETHOD(GetDataHere)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */);
+ STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */);
+ STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */);
+ STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */);
+ STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */);
+ STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
+ STDMETHOD(DUnadvise)(DWORD dwConnection);
+ STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise);
+
+// QObject
+ int qt_metacall(QMetaObject::Call, int index, void **argv);
+
+ bool eventFilter(QObject *o, QEvent *e);
+private:
+ void update();
+ void resize(const QSize &newSize);
+ void updateGeometry();
+ void updateMask();
+ bool internalCreate();
+ void internalBind();
+ void internalConnect();
+ HRESULT internalActivate();
+
+ friend class QAxBindable;
+ friend class QAxPropertyPage;
+
+ QAxAggregated *aggregatedObject;
+ ConnectionPoints points;
+
+ union {
+ QWidget *widget;
+ QObject *object;
+ } qt;
+ QPointer<QObject> theObject;
+ unsigned isWidget :1;
+ unsigned ownObject :1;
+ unsigned initNewCalled :1;
+ unsigned dirtyflag :1;
+ unsigned hasStockEvents :1;
+ unsigned stayTopLevel :1;
+ unsigned isInPlaceActive :1;
+ unsigned isUIActive :1;
+ unsigned wasUIActive :1;
+ unsigned inDesignMode :1;
+ unsigned canTakeFocus :1;
+ short freezeEvents;
+
+ HWND m_hWnd;
+
+ HMENU hmenuShared;
+ HOLEMENU holemenu;
+ HWND hwndMenuOwner;
+ QMap<HMENU, QMenu*> menuMap;
+ QMap<UINT, QAction*> actionMap;
+ QPointer<QMenuBar> menuBar;
+ QPointer<QStatusBar> statusBar;
+ QPointer<QMenu> currentPopup;
+ QAxExceptInfo *exception;
+
+ CRITICAL_SECTION refCountSection;
+ CRITICAL_SECTION createWindowSection;
+
+ unsigned long ref;
+ unsigned long ole_ref;
+
+ QString class_name;
+ QString currentFileName;
+
+ QHash<long, int> indexCache;
+ QHash<int,DISPID> signalCache;
+
+ IUnknown *m_outerUnknown;
+ IAdviseSink *m_spAdviseSink;
+ QList<STATDATA> adviseSinks;
+ IOleClientSite *m_spClientSite;
+ IOleInPlaceSiteWindowless *m_spInPlaceSite;
+ IOleInPlaceFrame *m_spInPlaceFrame;
+ ITypeInfo *m_spTypeInfo;
+ IStorage *m_spStorage;
+ QSize m_currentExtent;
+};
+
+class QAxServerAggregate : public IUnknown
+{
+public:
+ QAxServerAggregate(const QString &className, IUnknown *outerUnknown)
+ : m_outerUnknown(outerUnknown), ref(0)
+ {
+ object = new QAxServerBase(className, outerUnknown);
+ object->registerActiveObject(this);
+
+ InitializeCriticalSection(&refCountSection);
+ InitializeCriticalSection(&createWindowSection);
+ }
+ ~QAxServerAggregate()
+ {
+ DeleteCriticalSection(&refCountSection);
+ DeleteCriticalSection(&createWindowSection);
+
+ delete object;
+ }
+
+// IUnknown
+ unsigned long WINAPI AddRef()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = ++ref;
+ LeaveCriticalSection(&refCountSection);
+
+ return r;
+ }
+ unsigned long WINAPI Release()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = --ref;
+ LeaveCriticalSection(&refCountSection);
+
+ if (!r) {
+ delete this;
+ return 0;
+ }
+ return r;
+ }
+ HRESULT WINAPI QueryInterface(REFIID iid, void **iface)
+ {
+ *iface = 0;
+
+ HRESULT res = E_NOINTERFACE;
+ if (iid == IID_IUnknown) {
+ *iface = (IUnknown*)this;
+ AddRef();
+ return S_OK;
+ }
+ return object->InternalQueryInterface(iid, iface);
+ }
+
+private:
+ QAxServerBase *object;
+ IUnknown *m_outerUnknown;
+ unsigned long ref;
+
+ CRITICAL_SECTION refCountSection;
+ CRITICAL_SECTION createWindowSection;
+};
+
+bool QAxFactory::createObjectWrapper(QObject *object, IDispatch **wrapper)
+{
+ *wrapper = 0;
+ QAxServerBase *obj = new QAxServerBase(object);
+ obj->QueryInterface(IID_IDispatch, (void**)wrapper);
+ if (*wrapper)
+ return true;
+
+ delete obj;
+ return false;
+}
+
+
+/*
+ Helper class to enumerate all supported event interfaces.
+*/
+class QAxSignalVec : public IEnumConnectionPoints
+{
+public:
+ QAxSignalVec(const QAxServerBase::ConnectionPoints &points)
+ : cpoints(points), ref(0)
+ {
+ InitializeCriticalSection(&refCountSection);
+ for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i)
+ (*i)->AddRef();
+ }
+ QAxSignalVec(const QAxSignalVec &old)
+ {
+ InitializeCriticalSection(&refCountSection);
+ ref = 0;
+ cpoints = old.cpoints;
+ for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i)
+ (*i)->AddRef();
+ it = old.it;
+ }
+ ~QAxSignalVec()
+ {
+ for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i)
+ (*i)->Release();
+
+ DeleteCriticalSection(&refCountSection);
+ }
+
+ unsigned long __stdcall AddRef()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = ++ref;
+ LeaveCriticalSection(&refCountSection);
+ return ++r;
+ }
+ unsigned long __stdcall Release()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = --ref;
+ LeaveCriticalSection(&refCountSection);
+
+ if (!r) {
+ delete this;
+ return 0;
+ }
+ return r;
+ }
+ STDMETHOD(QueryInterface)(REFIID iid, void **iface)
+ {
+ *iface = 0;
+ if (iid == IID_IUnknown)
+ *iface = this;
+ else if (iid == IID_IEnumConnectionPoints)
+ *iface = this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+ }
+ STDMETHOD(Next)(ULONG cConnections, IConnectionPoint **cpoint, ULONG *pcFetched)
+ {
+ unsigned long i;
+ for (i = 0; i < cConnections; i++) {
+ if (it == cpoints.end())
+ break;
+ IConnectionPoint *cp = *it;
+ cp->AddRef();
+ cpoint[i] = cp;
+ ++it;
+ }
+ *pcFetched = i;
+ return i == cConnections ? S_OK : S_FALSE;
+ }
+ STDMETHOD(Skip)(ULONG cConnections)
+ {
+ while (cConnections) {
+ ++it;
+ --cConnections;
+ if (it == cpoints.end())
+ return S_FALSE;
+ }
+ return S_OK;
+ }
+ STDMETHOD(Reset)()
+ {
+ it = cpoints.begin();
+
+ return S_OK;
+ }
+ STDMETHOD(Clone)(IEnumConnectionPoints **ppEnum)
+ {
+ *ppEnum = new QAxSignalVec(*this);
+ (*ppEnum)->AddRef();
+
+ return S_OK;
+ }
+
+ QAxServerBase::ConnectionPoints cpoints;
+ QAxServerBase::ConnectionPointsIterator it;
+
+private:
+ CRITICAL_SECTION refCountSection;
+
+ unsigned long ref;
+};
+
+/*
+ Helper class to store and enumerate all connected event listeners.
+*/
+class QAxConnection : public IConnectionPoint,
+ public IEnumConnections
+{
+public:
+ typedef QList<CONNECTDATA> Connections;
+ typedef QList<CONNECTDATA>::Iterator Iterator;
+
+ QAxConnection(QAxServerBase *parent, const QUuid &uuid)
+ : that(parent), iid(uuid), ref(1)
+ {
+ InitializeCriticalSection(&refCountSection);
+ }
+ QAxConnection(const QAxConnection &old)
+ {
+ InitializeCriticalSection(&refCountSection);
+ ref = 0;
+ connections = old.connections;
+ it = old.it;
+ that = old.that;
+ iid = old.iid;
+ QList<CONNECTDATA>::Iterator it = connections.begin();
+ while (it != connections.end()) {
+ CONNECTDATA connection = *it;
+ ++it;
+ connection.pUnk->AddRef();
+ }
+ }
+ ~QAxConnection()
+ {
+ DeleteCriticalSection(&refCountSection);
+ }
+
+ unsigned long __stdcall AddRef()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = ++ref;
+ LeaveCriticalSection(&refCountSection);
+ return r;
+ }
+ unsigned long __stdcall Release()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = --ref;
+ LeaveCriticalSection(&refCountSection);
+
+ if (!r) {
+ delete this;
+ return 0;
+ }
+ return r;
+ }
+ STDMETHOD(QueryInterface)(REFIID iid, void **iface)
+ {
+ *iface = 0;
+ if (iid == IID_IUnknown)
+ *iface = (IConnectionPoint*)this;
+ else if (iid == IID_IConnectionPoint)
+ *iface = this;
+ else if (iid == IID_IEnumConnections)
+ *iface = this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+ }
+ STDMETHOD(GetConnectionInterface)(IID *pIID)
+ {
+ *pIID = iid;
+ return S_OK;
+ }
+ STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC)
+ {
+ return that->QueryInterface(IID_IConnectionPointContainer, (void**)ppCPC);
+ }
+ STDMETHOD(Advise)(IUnknown*pUnk, DWORD *pdwCookie)
+ {
+ {
+ IDispatch *checkImpl = 0;
+ pUnk->QueryInterface(iid, (void**)&checkImpl);
+ if (!checkImpl)
+ return CONNECT_E_CANNOTCONNECT;
+ checkImpl->Release();
+ }
+
+ CONNECTDATA cd;
+ cd.dwCookie = connections.count()+1;
+ cd.pUnk = pUnk;
+ cd.pUnk->AddRef();
+ connections.append(cd);
+
+ *pdwCookie = cd.dwCookie;
+ return S_OK;
+ }
+ STDMETHOD(Unadvise)(DWORD dwCookie)
+ {
+ QList<CONNECTDATA>::Iterator it = connections.begin();
+ while (it != connections.end()) {
+ CONNECTDATA cd = *it;
+ if (cd.dwCookie == dwCookie) {
+ cd.pUnk->Release();
+ connections.erase(it);
+ return S_OK;
+ }
+ ++it;
+ }
+ return CONNECT_E_NOCONNECTION;
+ }
+ STDMETHOD(EnumConnections)(IEnumConnections **ppEnum)
+ {
+ *ppEnum = this;
+ AddRef();
+
+ return S_OK;
+ }
+ STDMETHOD(Next)(ULONG cConnections, CONNECTDATA *cd, ULONG *pcFetched)
+ {
+ unsigned long i;
+ for (i = 0; i < cConnections; i++) {
+ if (it == connections.end())
+ break;
+ cd[i] = *it;
+ cd[i].pUnk->AddRef();
+ ++it;
+ }
+ if (pcFetched)
+ *pcFetched = i;
+ return i == cConnections ? S_OK : S_FALSE;
+ }
+ STDMETHOD(Skip)(ULONG cConnections)
+ {
+ while (cConnections) {
+ ++it;
+ --cConnections;
+ if (it == connections.end())
+ return S_FALSE;
+ }
+ return S_OK;
+ }
+ STDMETHOD(Reset)()
+ {
+ it = connections.begin();
+
+ return S_OK;
+ }
+ STDMETHOD(Clone)(IEnumConnections **ppEnum)
+ {
+ *ppEnum = new QAxConnection(*this);
+ (*ppEnum)->AddRef();
+
+ return S_OK;
+ }
+
+private:
+ QAxServerBase *that;
+ QUuid iid;
+ Connections connections;
+ Iterator it;
+
+ CRITICAL_SECTION refCountSection;
+ unsigned long ref;
+};
+
+// callback for DLL server to hook into non-Qt eventloop
+LRESULT QT_WIN_CALLBACK axs_FilterProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ if (qApp && !invokeCount)
+ qApp->sendPostedEvents();
+
+ return CallNextHookEx(qax_hhook, nCode, wParam, lParam);
+}
+
+// filter for executable case to hook into Qt eventloop
+// for DLLs the client calls TranslateAccelerator
+bool qax_winEventFilter(void *message)
+{
+ MSG *pMsg = (MSG*)message;
+ if (pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST)
+ return false;
+
+ bool ret = false;
+ QWidget *aqt = QWidget::find(pMsg->hwnd);
+ if (!aqt)
+ return ret;
+
+ HWND baseHwnd = ::GetParent(aqt->winId());
+ QAxServerBase *axbase = 0;
+ while (!axbase && baseHwnd) {
+#ifdef GWLP_USERDATA
+ axbase = (QAxServerBase*)GetWindowLongPtr(baseHwnd, GWLP_USERDATA);
+#else
+ axbase = (QAxServerBase*)GetWindowLong(baseHwnd, GWL_USERDATA);
+#endif
+
+ baseHwnd = ::GetParent(baseHwnd);
+ }
+ if (!axbase)
+ return ret;
+
+ HRESULT hres = axbase->TranslateAcceleratorW(pMsg);
+ return hres == S_OK;
+}
+
+extern void qWinMsgHandler(QtMsgType t, const char* str);
+
+// COM Factory class, mapping COM requests to ActiveQt requests.
+// One instance of this class for each ActiveX the server can provide.
+class QClassFactory : public IClassFactory2
+{
+public:
+ QClassFactory(CLSID clsid)
+ : ref(0), licensed(false)
+ {
+ InitializeCriticalSection(&refCountSection);
+
+ // COM only knows the CLSID, but QAxFactory is class name based...
+ QStringList keys = qAxFactory()->featureList();
+ for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) {
+ if (qAxFactory()->classID(*key) == clsid) {
+ className = *key;
+ break;
+ }
+ }
+
+ const QMetaObject *mo = qAxFactory()->metaObject(className);
+ if (mo) {
+ classKey = QLatin1String(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value());
+ licensed = !classKey.isEmpty();
+ }
+ }
+
+ ~QClassFactory()
+ {
+ DeleteCriticalSection(&refCountSection);
+ }
+
+ // IUnknown
+ unsigned long WINAPI AddRef()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = ++ref;
+ LeaveCriticalSection(&refCountSection);
+ return ++r;
+ }
+ unsigned long WINAPI Release()
+ {
+ EnterCriticalSection(&refCountSection);
+ unsigned long r = --ref;
+ LeaveCriticalSection(&refCountSection);
+
+ if (!r) {
+ delete this;
+ return 0;
+ }
+ return r;
+ }
+ HRESULT WINAPI QueryInterface(REFIID iid, LPVOID *iface)
+ {
+ *iface = 0;
+ if (iid == IID_IUnknown)
+ *iface = (IUnknown*)this;
+ else if (iid == IID_IClassFactory)
+ *iface = (IClassFactory*)this;
+ else if (iid == IID_IClassFactory2 && licensed)
+ *iface = (IClassFactory2*)this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+ }
+
+ HRESULT WINAPI CreateInstanceHelper(IUnknown *pUnkOuter, REFIID iid, void **ppObject)
+ {
+ if (pUnkOuter) {
+ if (iid != IID_IUnknown)
+ return CLASS_E_NOAGGREGATION;
+ const QMetaObject *mo = qAxFactory()->metaObject(className);
+ if (mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no"))
+ return CLASS_E_NOAGGREGATION;
+ }
+
+ // Make sure a QApplication instance is present (inprocess case)
+ if (!qApp) {
+ qInstallMsgHandler(qWinMsgHandler);
+ qax_ownQApp = true;
+ int argc = 0;
+ QApplication *app = new QApplication(argc, 0);
+ }
+ qApp->setQuitOnLastWindowClosed(false);
+
+ if (qAxOutProcServer)
+ QAbstractEventDispatcher::instance()->setEventFilter(qax_winEventFilter);
+ else
+ QApplication::instance()->d_func()->in_exec = true;
+
+ // hook into eventloop; this allows a server to create his own QApplication object
+ if (!qax_hhook && qax_ownQApp) {
+ qax_hhook = SetWindowsHookEx(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId());
+ }
+
+ HRESULT res;
+ // Create the ActiveX wrapper - aggregate if requested
+ if (pUnkOuter) {
+ QAxServerAggregate *aggregate = new QAxServerAggregate(className, pUnkOuter);
+ res = aggregate->QueryInterface(iid, ppObject);
+ if (FAILED(res))
+ delete aggregate;
+ } else {
+ QAxServerBase *activeqt = new QAxServerBase(className, pUnkOuter);
+ res = activeqt->QueryInterface(iid, ppObject);
+ if (FAILED(res))
+ delete activeqt;
+ else
+ activeqt->registerActiveObject((IUnknown*)(IDispatch*)activeqt);
+ }
+ return res;
+ }
+
+ // IClassFactory
+ HRESULT WINAPI CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppObject)
+ {
+ // class is licensed
+ if (licensed && !qAxFactory()->validateLicenseKey(className, QString()))
+ return CLASS_E_NOTLICENSED;
+
+ return CreateInstanceHelper(pUnkOuter, iid, ppObject);
+ }
+ HRESULT WINAPI LockServer(BOOL fLock)
+ {
+ if (fLock)
+ qAxLock();
+ else
+ qAxUnlock();
+
+ return S_OK;
+ }
+
+ // IClassFactory2
+ HRESULT WINAPI RequestLicKey(DWORD, BSTR *pKey)
+ {
+ if (!pKey)
+ return E_POINTER;
+ *pKey = 0;
+
+ // This of course works only on fully licensed machines
+ if (!qAxFactory()->validateLicenseKey(className, QString()))
+ return CLASS_E_NOTLICENSED;
+
+ *pKey = QStringToBSTR(classKey);
+ return S_OK;
+ }
+
+ HRESULT WINAPI GetLicInfo(LICINFO *pLicInfo)
+ {
+ if (!pLicInfo)
+ return E_POINTER;
+ pLicInfo->cbLicInfo = sizeof(LICINFO);
+
+ // class specific license key?
+ const QMetaObject *mo = qAxFactory()->metaObject(className);
+ const char *key = mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value();
+ pLicInfo->fRuntimeKeyAvail = key && key[0];
+
+ // machine fully licensed?
+ pLicInfo->fLicVerified = qAxFactory()->validateLicenseKey(className, QString());
+
+ return S_OK;
+ }
+
+ HRESULT WINAPI CreateInstanceLic(IUnknown *pUnkOuter, IUnknown *pUnkReserved, REFIID iid, BSTR bKey, PVOID *ppObject)
+ {
+ QString licenseKey = QString::fromWCharArray(bKey);
+ if (!qAxFactory()->validateLicenseKey(className, licenseKey))
+ return CLASS_E_NOTLICENSED;
+ return CreateInstanceHelper(pUnkOuter, iid, ppObject);
+ }
+
+ QString className;
+
+protected:
+ CRITICAL_SECTION refCountSection;
+ unsigned long ref;
+ bool licensed;
+ QString classKey;
+};
+
+// Create a QClassFactory object for class \a iid
+HRESULT GetClassObject(REFIID clsid, REFIID iid, void **ppUnk)
+{
+ QClassFactory *factory = new QClassFactory(clsid);
+ if (!factory)
+ return E_OUTOFMEMORY;
+ if (factory->className.isEmpty()) {
+ delete factory;
+ return E_NOINTERFACE;
+ }
+ HRESULT res = factory->QueryInterface(iid, ppUnk);
+ if (res != S_OK)
+ delete factory;
+ return res;
+}
+
+
+/*!
+ Constructs a QAxServerBase object wrapping the QWidget \a
+ classname into an ActiveX control.
+
+ The constructor is called by the QClassFactory object provided by
+ the COM server for the respective CLSID.
+*/
+QAxServerBase::QAxServerBase(const QString &classname, IUnknown *outerUnknown)
+: aggregatedObject(0), ref(0), ole_ref(0), class_name(classname),
+ m_hWnd(0), hmenuShared(0), hwndMenuOwner(0),
+ m_outerUnknown(outerUnknown)
+{
+ init();
+
+ internalCreate();
+}
+
+/*!
+ Constructs a QAxServerBase object wrapping \a o.
+*/
+QAxServerBase::QAxServerBase(QObject *o)
+: aggregatedObject(0), ref(0), ole_ref(0),
+ m_hWnd(0), hmenuShared(0), hwndMenuOwner(0),
+ m_outerUnknown(0)
+{
+ init();
+
+ qt.object = o;
+ if (o) {
+ theObject = o;
+ isWidget = false;
+ class_name = QLatin1String(o->metaObject()->className());
+ }
+ internalBind();
+ internalConnect();
+}
+
+/*!
+ Initializes data members.
+*/
+void QAxServerBase::init()
+{
+ qt.object = 0;
+ isWidget = false;
+ ownObject = false;
+ initNewCalled = false;
+ dirtyflag = false;
+ hasStockEvents = false;
+ stayTopLevel = false;
+ isInPlaceActive = false;
+ isUIActive = false;
+ wasUIActive = false;
+ inDesignMode = false;
+ canTakeFocus = false;
+ freezeEvents = 0;
+ exception = 0;
+
+ m_spAdviseSink = 0;
+ m_spClientSite = 0;
+ m_spInPlaceSite = 0;
+ m_spInPlaceFrame = 0;
+ m_spTypeInfo = 0;
+ m_spStorage = 0;
+
+ InitializeCriticalSection(&refCountSection);
+ InitializeCriticalSection(&createWindowSection);
+
+#ifdef QT_DEBUG
+ EnterCriticalSection(&refCountSection);
+ ++qaxserverbase_instance_count;
+ LeaveCriticalSection(&refCountSection);
+#endif
+
+ qAxLock();
+
+ points[IID_IPropertyNotifySink] = new QAxConnection(this, IID_IPropertyNotifySink);
+}
+
+/*!
+ Destroys the QAxServerBase object, releasing all allocated
+ resources and interfaces.
+*/
+QAxServerBase::~QAxServerBase()
+{
+#ifdef QT_DEBUG
+ EnterCriticalSection(&refCountSection);
+ --qaxserverbase_instance_count;
+ LeaveCriticalSection(&refCountSection);
+#endif
+
+ revokeActiveObject();
+
+ for (QAxServerBase::ConnectionPointsIterator it = points.begin(); it != points.end(); ++it) {
+ if (it.value())
+ (*it)->Release();
+ }
+ delete aggregatedObject;
+ aggregatedObject = 0;
+ if (theObject) {
+ qt.object->disconnect(this);
+ QObject *aqt = qt.object;
+ qt.object = 0;
+ if (ownObject)
+ delete aqt;
+ }
+
+ if (m_spAdviseSink) m_spAdviseSink->Release();
+ m_spAdviseSink = 0;
+ for (int i = 0; i < adviseSinks.count(); ++i) {
+ adviseSinks.at(i).pAdvSink->Release();
+ }
+ if (m_spClientSite) m_spClientSite->Release();
+ m_spClientSite = 0;
+ if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
+ m_spInPlaceFrame = 0;
+ if (m_spInPlaceSite) m_spInPlaceSite->Release();
+ m_spInPlaceSite = 0;
+ if (m_spTypeInfo) m_spTypeInfo->Release();
+ m_spTypeInfo = 0;
+ if (m_spStorage) m_spStorage->Release();
+ m_spStorage = 0;
+
+ DeleteCriticalSection(&refCountSection);
+ DeleteCriticalSection(&createWindowSection);
+
+ qAxUnlock();
+}
+
+/*
+ Registering with OLE
+*/
+void QAxServerBase::registerActiveObject(IUnknown *object)
+{
+ if (ole_ref || !qt.object || !qAxOutProcServer)
+ return;
+
+ const QMetaObject *mo = qt.object->metaObject();
+ if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes"))
+ RegisterActiveObject(object, qAxFactory()->classID(class_name), ACTIVEOBJECT_WEAK, &ole_ref);
+}
+
+void QAxServerBase::revokeActiveObject()
+{
+ if (!ole_ref)
+ return;
+
+ RevokeActiveObject(ole_ref, 0);
+ ole_ref = 0;
+}
+
+/*
+ QueryInterface implementation.
+*/
+HRESULT WINAPI QAxServerBase::QueryInterface(REFIID iid, void **iface)
+{
+ if (m_outerUnknown)
+ return m_outerUnknown->QueryInterface(iid, iface);
+
+ return InternalQueryInterface(iid, iface);
+}
+
+HRESULT QAxServerBase::InternalQueryInterface(REFIID iid, void **iface)
+{
+ *iface = 0;
+
+ if (iid == IID_IUnknown) {
+ *iface = (IUnknown*)(IDispatch*)this;
+ } else {
+ HRESULT res = S_OK;
+ if (aggregatedObject)
+ res = aggregatedObject->queryInterface(iid, iface);
+ if (*iface)
+ return res;
+ }
+
+ if (!(*iface)) {
+ if (iid == qAxFactory()->interfaceID(class_name))
+ *iface = (IDispatch*)this;
+ if (iid == IID_IDispatch)
+ *iface = (IDispatch*)this;
+ else if (iid == IID_IAxServerBase)
+ *iface = (IAxServerBase*)this;
+ else if (iid == IID_IOleObject)
+ *iface = (IOleObject*)this;
+ else if (iid == IID_IConnectionPointContainer)
+ *iface = (IConnectionPointContainer*)this;
+ else if (iid == IID_IProvideClassInfo)
+ *iface = (IProvideClassInfo*)this;
+ else if (iid == IID_IProvideClassInfo2)
+ *iface = (IProvideClassInfo2*)this;
+ else if (iid == IID_IPersist)
+ *iface = (IPersist*)(IPersistStream*)this;
+ else if (iid == IID_IPersistStream)
+ *iface = (IPersistStream*)this;
+ else if (iid == IID_IPersistStreamInit)
+ *iface = (IPersistStreamInit*)this;
+ else if (iid == IID_IPersistStorage)
+ *iface = (IPersistStorage*)this;
+ else if (iid == IID_IPersistPropertyBag)
+ *iface = (IPersistPropertyBag*)this;
+ else if (iid == IID_IPersistFile &&
+ qAxFactory()->metaObject(class_name)->indexOfClassInfo("MIME") != -1)
+ *iface = (IPersistFile*)this;
+ else if (iid == IID_IViewObject)
+ *iface = (IViewObject*)this;
+ else if (iid == IID_IViewObject2)
+ *iface = (IViewObject2*)this;
+ else if (isWidget) {
+ if (iid == IID_IOleControl)
+ *iface = (IOleControl*)this;
+ else if (iid == IID_IOleWindow)
+ *iface = (IOleWindow*)(IOleInPlaceObject*)this;
+ else if (iid == IID_IOleInPlaceObject)
+ *iface = (IOleInPlaceObject*)this;
+ else if (iid == IID_IOleInPlaceActiveObject)
+ *iface = (IOleInPlaceActiveObject*)this;
+ else if (iid == IID_IDataObject)
+ *iface = (IDataObject*)this;
+ }
+ }
+ if (!*iface)
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+}
+
+/*!
+ Detects and initilaizes implementation of QAxBindable in objects.
+*/
+void QAxServerBase::internalBind()
+{
+ QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
+ if (axb) {
+ // no addref; this is aggregated
+ axb->activex = this;
+ if (!aggregatedObject)
+ aggregatedObject = axb->createAggregate();
+ if (aggregatedObject) {
+ aggregatedObject->controlling_unknown = (IUnknown*)(IDispatch*)this;
+ aggregatedObject->the_object = qt.object;
+ }
+ }
+}
+
+/*!
+ Connects object signals to event dispatcher.
+*/
+void QAxServerBase::internalConnect()
+{
+ QUuid eventsID = qAxFactory()->eventsID(class_name);
+ if (!eventsID.isNull()) {
+ if (!points[eventsID])
+ points[eventsID] = new QAxConnection(this, eventsID);
+
+ // connect the generic slot to all signals of qt.object
+ const QMetaObject *mo = qt.object->metaObject();
+ for (int isignal = mo->methodCount()-1; isignal >= 0; --isignal) {
+ if (mo->method(isignal).methodType() == QMetaMethod::Signal)
+ QMetaObject::connect(qt.object, isignal, this, isignal);
+ }
+ }
+}
+
+/*!
+ Creates the QWidget for the classname passed to the c'tor.
+
+ All signals of the widget class are connected to the internal event mapper.
+ If the widget implements QAxBindable, stock events are also connected.
+*/
+bool QAxServerBase::internalCreate()
+{
+ if (qt.object)
+ return true;
+
+ qt.object = qAxFactory()->createObject(class_name);
+ Q_ASSERT(qt.object);
+ if (!qt.object)
+ return false;
+
+ theObject = qt.object;
+ ownObject = true;
+ isWidget = qt.object->isWidgetType();
+ hasStockEvents = qAxFactory()->hasStockEvents(class_name);
+ stayTopLevel = qAxFactory()->stayTopLevel(class_name);
+
+ internalBind();
+ if (isWidget) {
+ if (!stayTopLevel) {
+ QEvent e(QEvent::EmbeddingControl);
+ QApplication::sendEvent(qt.widget, &e);
+ ::SetWindowLong(qt.widget->winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+ }
+ qt.widget->setAttribute(Qt::WA_QuitOnClose, false);
+ qt.widget->move(0, 0);
+
+ // initialize to sizeHint, but don't set resized flag so that container has a chance to override
+ bool wasResized = qt.widget->testAttribute(Qt::WA_Resized);
+ updateGeometry();
+ if (!wasResized && qt.widget->testAttribute(Qt::WA_Resized)
+ && qt.widget->sizePolicy() != QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)) {
+ qt.widget->setAttribute(Qt::WA_Resized, false);
+ }
+ }
+
+ internalConnect();
+ // install an event filter for stock events
+ if (isWidget) {
+ qt.object->installEventFilter(this);
+ const QList<QWidget*> children = qt.object->findChildren<QWidget*>();
+ QList<QWidget*>::ConstIterator it = children.constBegin();
+ while (it != children.constEnd()) {
+ (*it)->installEventFilter(this);
+ ++it;
+ }
+ }
+ return true;
+}
+
+/*
+class HackMenuData : public QMenuData
+{
+ friend class QAxServerBase;
+};
+*/
+
+class HackWidget : public QWidget
+{
+ friend class QAxServerBase;
+};
+/*
+ Message handler. \a hWnd is always the ActiveX widget hosting the Qt widget.
+ \a uMsg is handled as follows
+ \list
+ \i WM_CREATE The ActiveX control is created
+ \i WM_DESTROY The QWidget is destroyed
+ \i WM_SHOWWINDOW The QWidget is parented into the ActiveX window
+ \i WM_PAINT The QWidget is updated
+ \i WM_SIZE The QWidget is resized to the new size
+ \i WM_SETFOCUS and
+ \i WM_KILLFOCUS The client site is notified about the focus transfer
+ \i WM_MOUSEACTIVATE The ActiveX is activated
+ \endlist
+
+ The semantics of \a wParam and \a lParam depend on the value of \a uMsg.
+*/
+LRESULT QT_WIN_CALLBACK QAxServerBase::ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == WM_CREATE) {
+ CREATESTRUCT *cs = (CREATESTRUCT*)lParam;
+ QAxServerBase *that = (QAxServerBase*)cs->lpCreateParams;
+
+#ifdef GWLP_USERDATA
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)that);
+#else
+ SetWindowLong(hWnd, GWL_USERDATA, (LONG)that);
+#endif
+
+ that->m_hWnd = hWnd;
+
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+
+ QAxServerBase *that = 0;
+
+#ifdef GWLP_USERDATA
+ that = (QAxServerBase*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+#else
+ that = (QAxServerBase*)GetWindowLong(hWnd, GWL_USERDATA);
+#endif
+
+ if (that) {
+ int width = that->qt.widget ? that->qt.widget->width() : 0;
+ int height = that->qt.widget ? that->qt.widget->height() : 0;
+ RECT rcPos = {0, 0, width + 1, height + 1};
+
+ switch (uMsg) {
+ case WM_NCDESTROY:
+ that->m_hWnd = 0;
+ break;
+
+ case WM_QUERYENDSESSION:
+ case WM_DESTROY:
+ // save the window handle
+ if (that->qt.widget) {
+ that->qt.widget->hide();
+ ::SetParent(that->qt.widget->winId(), 0);
+ }
+ break;
+
+ case WM_SHOWWINDOW:
+ if(wParam) {
+ that->internalCreate();
+ if (!that->stayTopLevel) {
+ ::SetParent(that->qt.widget->winId(), that->m_hWnd);
+ that->qt.widget->raise();
+ that->qt.widget->move(0, 0);
+ }
+ that->qt.widget->show();
+ } else if (that->qt.widget) {
+ that->qt.widget->hide();
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ that->updateMask();
+ break;
+
+ case WM_SIZE:
+ that->resize(QSize(LOWORD(lParam), HIWORD(lParam)));
+ break;
+
+ case WM_SETFOCUS:
+ if (that->isInPlaceActive && that->m_spClientSite && !that->inDesignMode && that->canTakeFocus) {
+ that->DoVerb(OLEIVERB_UIACTIVATE, NULL, that->m_spClientSite, 0, that->m_hWnd, &rcPos);
+ if (that->isUIActive) {
+ IOleControlSite *spSite = 0;
+ that->m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&spSite);
+ if (spSite) {
+ spSite->OnFocus(true);
+ spSite->Release();
+ }
+ QWidget *candidate = that->qt.widget;
+ while (!(candidate->focusPolicy() & Qt::TabFocus)) {
+ candidate = candidate->nextInFocusChain();
+ if (candidate == that->qt.widget) {
+ candidate = 0;
+ break;
+ }
+ }
+ if (candidate) {
+ candidate->setFocus();
+ HackWidget *widget = (HackWidget*)that->qt.widget;
+ if (::GetKeyState(VK_SHIFT) < 0)
+ widget->focusNextPrevChild(false);
+ }
+ }
+ }
+ break;
+
+ case WM_KILLFOCUS:
+ if (that->isInPlaceActive && that->isUIActive && that->m_spClientSite) {
+ IOleControlSite *spSite = 0;
+ that->m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&spSite);
+ if (spSite) {
+ if (!::IsChild(that->m_hWnd, ::GetFocus()))
+ spSite->OnFocus(false);
+ spSite->Release();
+ }
+ }
+ break;
+
+ case WM_MOUSEACTIVATE:
+ that->DoVerb(OLEIVERB_UIACTIVATE, NULL, that->m_spClientSite, 0, that->m_hWnd, &rcPos);
+ break;
+
+ case WM_INITMENUPOPUP:
+ if (that->qt.widget) {
+ that->currentPopup = that->menuMap[(HMENU)wParam];
+ if (!that->currentPopup)
+ break;
+ const QMetaObject *mo = that->currentPopup->metaObject();
+ int index = mo->indexOfSignal("aboutToShow()");
+ if (index < 0)
+ break;
+
+ that->currentPopup->qt_metacall(QMetaObject::InvokeMetaMethod, index, 0);
+ that->createPopup(that->currentPopup, (HMENU)wParam);
+ return 0;
+ }
+ break;
+
+ case WM_MENUSELECT:
+ case WM_COMMAND:
+ if (that->qt.widget) {
+ QMenuBar *menuBar = that->menuBar;
+ if (!menuBar)
+ break;
+
+ QObject *menuObject = 0;
+ bool menuClosed = false;
+
+ if (uMsg == WM_COMMAND) {
+ menuObject = that->actionMap.value(wParam);
+ } else if (!lParam) {
+ menuClosed = true;
+ menuObject = that->currentPopup;
+ } else {
+ menuObject = that->actionMap.value(LOWORD(wParam));
+ }
+
+ if (menuObject) {
+ const QMetaObject *mo = menuObject->metaObject();
+ int index = -1;
+
+ if (uMsg == WM_COMMAND)
+ index = mo->indexOfSignal("activated()");
+ else if (menuClosed)
+ index = mo->indexOfSignal("aboutToHide()");
+ else
+ index = mo->indexOfSignal("hovered()");
+
+ if (index < 0)
+ break;
+
+ menuObject->qt_metacall(QMetaObject::InvokeMetaMethod, index, 0);
+ if (menuClosed || uMsg == WM_COMMAND)
+ that->currentPopup = 0;
+ return 0;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+/*!
+ Creates the window hosting the QWidget.
+*/
+HWND QAxServerBase::create(HWND hWndParent, RECT& rcPos)
+{
+ Q_ASSERT(isWidget && qt.widget);
+
+ static ATOM atom = 0;
+ HINSTANCE hInst = (HINSTANCE)qAxInstance;
+ EnterCriticalSection(&createWindowSection);
+ QString cn(QLatin1String("QAxControl"));
+ cn += QString::number((quintptr)ActiveXProc);
+ if (!atom) {
+ WNDCLASS wcTemp;
+ wcTemp.style = CS_DBLCLKS;
+ wcTemp.cbClsExtra = 0;
+ wcTemp.cbWndExtra = 0;
+ wcTemp.hbrBackground = 0;
+ wcTemp.hCursor = 0;
+ wcTemp.hIcon = 0;
+ wcTemp.hInstance = hInst;
+ wcTemp.lpszClassName = (wchar_t*)cn.utf16();
+ wcTemp.lpszMenuName = 0;
+ wcTemp.lpfnWndProc = ActiveXProc;
+
+ atom = RegisterClass(&wcTemp);
+ }
+ LeaveCriticalSection(&createWindowSection);
+ if (!atom && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
+ return 0;
+
+ Q_ASSERT(!m_hWnd);
+ HWND hWnd = ::CreateWindow((wchar_t*)cn.utf16(), 0,
+ WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ rcPos.left, rcPos.top, rcPos.right - rcPos.left,
+ rcPos.bottom - rcPos.top, hWndParent, 0, hInst, this);
+
+ Q_ASSERT(m_hWnd == hWnd);
+
+ updateMask();
+ EnableWindow(m_hWnd, qt.widget->isEnabled());
+
+ return hWnd;
+}
+
+/*
+ Recoursively creates Win32 submenus.
+*/
+HMENU QAxServerBase::createPopup(QMenu *popup, HMENU oldMenu)
+{
+ HMENU popupMenu = oldMenu ? oldMenu : CreatePopupMenu();
+ menuMap.insert(popupMenu, popup);
+
+ if (oldMenu) while (GetMenuItemCount(oldMenu)) {
+ DeleteMenu(oldMenu, 0, MF_BYPOSITION);
+ }
+
+ const QList<QAction*> actions = popup->actions();
+ for (int i = 0; i < actions.count(); ++i) {
+ QAction *action = actions.at(i);
+
+ uint flags = action->isEnabled() ? MF_ENABLED : MF_GRAYED;
+ if (action->isSeparator())
+ flags |= MF_SEPARATOR;
+ else if (action->menu())
+ flags |= MF_POPUP;
+ else
+ flags |= MF_STRING;
+ if (action->isChecked())
+ flags |= MF_CHECKED;
+
+ ushort itemId;
+ if (flags & MF_POPUP) {
+ itemId = static_cast<ushort>(
+ reinterpret_cast<quintptr>(createPopup(action->menu()))
+ );
+ } else {
+ itemId = static_cast<ushort>(reinterpret_cast<quintptr>(action));
+ actionMap.remove(itemId);
+ actionMap.insert(itemId, action);
+ }
+ AppendMenu(popupMenu, flags, itemId, (const wchar_t *)action->text().utf16());
+ }
+ if (oldMenu)
+ DrawMenuBar(hwndMenuOwner);
+ return popupMenu;
+}
+
+/*!
+ Creates a Win32 menubar.
+*/
+void QAxServerBase::createMenu(QMenuBar *menuBar)
+{
+ hmenuShared = ::CreateMenu();
+
+ int edit = 0;
+ int object = 0;
+ int help = 0;
+
+ const QList<QAction*> actions = menuBar->actions();
+ for (int i = 0; i < actions.count(); ++i) {
+ QAction *action = actions.at(i);
+
+ uint flags = action->isEnabled() ? MF_ENABLED : MF_GRAYED;
+ if (action->isSeparator())
+ flags |= MF_SEPARATOR;
+ else if (action->menu())
+ flags |= MF_POPUP;
+ else
+ flags |= MF_STRING;
+
+ if (action->text() == QCoreApplication::translate(qt.widget->metaObject()->className(), "&Edit"))
+ edit++;
+ else if (action->text() == QCoreApplication::translate(qt.widget->metaObject()->className(), "&Help"))
+ help++;
+ else
+ object++;
+
+ ushort itemId;
+ if (flags & MF_POPUP) {
+ itemId = static_cast<ushort>(
+ reinterpret_cast<quintptr>(createPopup(action->menu()))
+ );
+ } else {
+ itemId = static_cast<ushort>(reinterpret_cast<quintptr>(action));
+ actionMap.insert(itemId, action);
+ }
+ AppendMenu(hmenuShared, flags, itemId, (const wchar_t *)action->text().utf16());
+ }
+
+ OLEMENUGROUPWIDTHS menuWidths = {0,edit,0,object,0,help};
+ HRESULT hres = m_spInPlaceFrame->InsertMenus(hmenuShared, &menuWidths);
+ if (FAILED(hres)) {
+ ::DestroyMenu(hmenuShared);
+ hmenuShared = 0;
+ return;
+ }
+
+ m_spInPlaceFrame->GetWindow(&hwndMenuOwner);
+
+ holemenu = OleCreateMenuDescriptor(hmenuShared, &menuWidths);
+ hres = m_spInPlaceFrame->SetMenu(hmenuShared, holemenu, m_hWnd);
+ if (FAILED(hres)) {
+ ::DestroyMenu(hmenuShared);
+ hmenuShared = 0;
+ OleDestroyMenuDescriptor(holemenu);
+ }
+}
+
+/*!
+ Remove the Win32 menubar.
+*/
+void QAxServerBase::removeMenu()
+{
+ if (hmenuShared)
+ m_spInPlaceFrame->RemoveMenus(hmenuShared);
+ holemenu = 0;
+ m_spInPlaceFrame->SetMenu(0, 0, m_hWnd);
+ if (hmenuShared) {
+ DestroyMenu(hmenuShared);
+ hmenuShared = 0;
+ menuMap.clear();
+ }
+ hwndMenuOwner = 0;
+}
+
+extern bool ignoreSlots(const char *test);
+extern bool ignoreProps(const char *test);
+
+/*!
+ Makes sure the type info is loaded
+*/
+void QAxServerBase::ensureMetaData()
+{
+ if (!m_spTypeInfo) {
+ qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->interfaceID(class_name), &m_spTypeInfo);
+ m_spTypeInfo->AddRef();
+ }
+}
+
+/*!
+ \internal
+ Returns true if the property \a index is exposed to COM and should
+ be saved/loaded.
+*/
+bool QAxServerBase::isPropertyExposed(int index)
+{
+ if (!theObject)
+ return false;
+
+ bool result = false;
+ const QMetaObject *mo = theObject->metaObject();
+
+ int qtProps = 0;
+ if (theObject->isWidgetType())
+ qtProps = QWidget::staticMetaObject.propertyCount();
+ QMetaProperty property = mo->property(index);
+ if (index <= qtProps && ignoreProps(property.name()))
+ return result;
+
+ BSTR bstrNames = QStringToBSTR(QLatin1String(property.name()));
+ DISPID dispId;
+ GetIDsOfNames(IID_NULL, (BSTR*)&bstrNames, 1, LOCALE_USER_DEFAULT, &dispId);
+ result = dispId != DISPID_UNKNOWN;
+ SysFreeString(bstrNames);
+
+ return result;
+}
+
+
+/*!
+ \internal
+ Updates the view, or asks the client site to do so.
+*/
+void QAxServerBase::update()
+{
+ if (isInPlaceActive) {
+ if (m_hWnd)
+ ::InvalidateRect(m_hWnd, 0, true);
+ else if (m_spInPlaceSite)
+ m_spInPlaceSite->InvalidateRect(NULL, true);
+ } else if (m_spAdviseSink) {
+ m_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1);
+ for (int i = 0; i < adviseSinks.count(); ++i) {
+ adviseSinks.at(i).pAdvSink->OnViewChange(DVASPECT_CONTENT, -1);
+ }
+ }
+}
+
+/*!
+ Resizes the control, faking a QResizeEvent if required
+*/
+void QAxServerBase::resize(const QSize &size)
+{
+ if (!isWidget || !qt.widget || !size.isValid() || size == QSize(0, 0))
+ return;
+
+ QSize oldSize = qt.widget->size();
+ qt.widget->resize(size);
+ QSize newSize = qt.widget->size();
+ // make sure we get a resize event even if not embedded as a control
+ if (!m_hWnd && !qt.widget->isVisible() && newSize != oldSize) {
+ QResizeEvent resizeEvent(newSize, oldSize);
+#ifndef QT_DLL // import from static library
+ extern bool qt_sendSpontaneousEvent(QObject*,QEvent*);
+#endif
+ qt_sendSpontaneousEvent(qt.widget, &resizeEvent);
+ }
+ m_currentExtent = qt.widget->size();
+}
+
+/*!
+ \internal
+
+ Updates the internal size values.
+*/
+void QAxServerBase::updateGeometry()
+{
+ if (!isWidget || !qt.widget)
+ return;
+
+ const QSize sizeHint = qt.widget->sizeHint();
+ const QSize size = qt.widget->size();
+ if (sizeHint.isValid()) { // if provided, adjust to sizeHint
+ QSize newSize = size;
+ if (!qt.widget->testAttribute(Qt::WA_Resized)) {
+ newSize = sizeHint;
+ } else { // according to sizePolicy rules if already resized
+ QSizePolicy sizePolicy = qt.widget->sizePolicy();
+ if (sizeHint.width() > size.width() && !(sizePolicy.horizontalPolicy() & QSizePolicy::ShrinkFlag))
+ newSize.setWidth(sizeHint.width());
+ if (sizeHint.width() < size.width() && !(sizePolicy.horizontalPolicy() & QSizePolicy::GrowFlag))
+ newSize.setWidth(sizeHint.width());
+ if (sizeHint.height() > size.height() && !(sizePolicy.verticalPolicy() & QSizePolicy::ShrinkFlag))
+ newSize.setHeight(sizeHint.height());
+ if (sizeHint.height() < size.height() && !(sizePolicy.verticalPolicy() & QSizePolicy::GrowFlag))
+ newSize.setHeight(sizeHint.height());
+ }
+ resize(newSize);
+
+ // set an initial size suitable for embedded controls
+ } else if (!qt.widget->testAttribute(Qt::WA_Resized)) {
+ resize(QSize(100, 100));
+ qt.widget->setAttribute(Qt::WA_Resized, false);
+ }
+}
+
+/*!
+ \internal
+
+ Updates the mask of the widget parent.
+*/
+void QAxServerBase::updateMask()
+{
+ if (!isWidget || !qt.widget || qt.widget->mask().isEmpty())
+ return;
+
+ QRegion rgn = qt.widget->mask();
+ HRGN hrgn = rgn.handle();
+
+ // Since SetWindowRegion takes ownership
+ HRGN wr = CreateRectRgn(0,0,0,0);
+ CombineRgn(wr, hrgn, 0, RGN_COPY);
+ SetWindowRgn(m_hWnd, wr, true);
+}
+
+static bool checkHRESULT(HRESULT hres)
+{
+ const char *name = 0;
+ switch(hres) {
+ case S_OK:
+ return true;
+ case DISP_E_BADPARAMCOUNT:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Bad parameter count", name);
+#endif
+ return false;
+ case DISP_E_BADVARTYPE:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Bad variant type", name);
+#endif
+ return false;
+ case DISP_E_EXCEPTION:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Exception thrown by server", name);
+#endif
+ return false;
+ case DISP_E_MEMBERNOTFOUND:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Member not found", name);
+#endif
+ return false;
+ case DISP_E_NONAMEDARGS:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: No named arguments", name);
+#endif
+ return false;
+ case DISP_E_OVERFLOW:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Overflow", name);
+#endif
+ return false;
+ case DISP_E_PARAMNOTFOUND:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Parameter not found", name);
+#endif
+ return false;
+ case DISP_E_TYPEMISMATCH:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Type mismatch", name);
+#endif
+ return false;
+ case DISP_E_UNKNOWNINTERFACE:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Unknown interface", name);
+#endif
+ return false;
+ case DISP_E_UNKNOWNLCID:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Unknown locale ID", name);
+#endif
+ return false;
+ case DISP_E_PARAMNOTOPTIONAL:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Non-optional parameter missing", name);
+#endif
+ return false;
+ default:
+#if defined(QT_CHECK_STATE)
+ qWarning("QAxBase: Error calling IDispatch member %s: Unknown error", name);
+#endif
+ return false;
+ }
+}
+
+static inline QByteArray paramType(const QByteArray &ptype, bool *out)
+{
+ *out = ptype.endsWith('&') || ptype.endsWith("**");
+ if (*out) {
+ QByteArray res(ptype);
+ res.truncate(res.length() - 1);
+ return res;
+ }
+
+ return ptype;
+}
+
+/*!
+ Catches all signals emitted by the Qt widget and fires the respective COM event.
+
+ \a isignal is the Qt Meta Object index of the received signal, and \a _o the
+ signal parameters.
+*/
+int QAxServerBase::qt_metacall(QMetaObject::Call call, int index, void **argv)
+{
+ Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
+
+ if (index == -1) {
+ if (sender() && m_spInPlaceFrame) {
+ if (qobject_cast<QStatusBar*>(sender()) != statusBar)
+ return true;
+
+ if (statusBar->isHidden()) {
+ QString message = *(QString*)argv[1];
+ m_spInPlaceFrame->SetStatusText(QStringToBSTR(message));
+ }
+ }
+ return true;
+ }
+
+ if (freezeEvents || inDesignMode)
+ return true;
+
+ ensureMetaData();
+
+ // get the signal information.
+ const QMetaObject *mo = qt.object->metaObject();
+ QMetaMethod signal;
+ DISPID eventId = index;
+ int pcount = 0;
+ QByteArray type;
+ QList<QByteArray> ptypes;
+
+ switch(index) {
+ case DISPID_KEYDOWN:
+ case DISPID_KEYUP:
+ pcount = 2;
+ ptypes << "int&" << "int";
+ break;
+ case DISPID_KEYPRESS:
+ pcount = 1;
+ ptypes << "int&";
+ break;
+ case DISPID_MOUSEDOWN:
+ case DISPID_MOUSEMOVE:
+ case DISPID_MOUSEUP:
+ pcount = 4;
+ ptypes << "int" << "int" << "int" << "int";
+ break;
+ case DISPID_CLICK:
+ pcount = 0;
+ break;
+ case DISPID_DBLCLICK:
+ pcount = 0;
+ break;
+ default:
+ {
+ signal = mo->method(index);
+ Q_ASSERT(signal.methodType() == QMetaMethod::Signal);
+ type = signal.typeName();
+ QByteArray signature(signal.signature());
+ QByteArray name(signature);
+ name.truncate(name.indexOf('('));
+
+ eventId = signalCache.value(index, -1);
+ if (eventId == -1) {
+ ITypeInfo *eventInfo = 0;
+ qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->eventsID(class_name), &eventInfo);
+ if (eventInfo) {
+ QString uni_name = QLatin1String(name);
+ const OLECHAR *olename = reinterpret_cast<const OLECHAR *>(uni_name.utf16());
+ eventInfo->GetIDsOfNames((OLECHAR**)&olename, 1, &eventId);
+ eventInfo->Release();
+ }
+ }
+
+ signature = signature.mid(name.length() + 1);
+ signature.truncate(signature.length() - 1);
+
+ if (!signature.isEmpty())
+ ptypes = signature.split(',');
+
+ pcount = ptypes.count();
+ }
+ break;
+ }
+ if (pcount && !argv) {
+ qWarning("QAxServerBase::qt_metacall: Missing %d arguments", pcount);
+ return false;
+ }
+ if (eventId == -1)
+ return false;
+
+ // For all connected event sinks...
+ IConnectionPoint *cpoint = 0;
+ GUID IID_QAxEvents = qAxFactory()->eventsID(class_name);
+ FindConnectionPoint(IID_QAxEvents, &cpoint);
+ if (cpoint) {
+ IEnumConnections *clist = 0;
+ cpoint->EnumConnections(&clist);
+ if (clist) {
+ clist->Reset();
+ ULONG cc = 1;
+ CONNECTDATA c[1];
+ clist->Next(cc, (CONNECTDATA*)&c, &cc);
+ if (cc) {
+ // setup parameters
+ unsigned int argErr = 0;
+ DISPPARAMS dispParams;
+ dispParams.cArgs = pcount;
+ dispParams.cNamedArgs = 0;
+ dispParams.rgdispidNamedArgs = 0;
+ dispParams.rgvarg = 0;
+
+ if (pcount) // Use malloc/free for eval package compatibility
+ dispParams.rgvarg = (VARIANTARG*)malloc(pcount * sizeof(VARIANTARG));
+ int p = 0;
+ for (p = 0; p < pcount; ++p) {
+ VARIANT *arg = dispParams.rgvarg + (pcount - p - 1);
+ VariantInit(arg);
+
+ bool out;
+ QByteArray ptype = paramType(ptypes.at(p), &out);
+ QVariant variant;
+ if (mo->indexOfEnumerator(ptype) != -1) {
+ // convert enum values to int
+ variant = QVariant(*reinterpret_cast<int *>(argv[p+1]));
+ } else {
+ QVariant::Type vt = QVariant::nameToType(ptype);
+ if (vt == QVariant::UserType) {
+ if (ptype.endsWith('*')) {
+ variant = QVariant(QMetaType::type(ptype), (void**)argv[p+1]);
+ // variant.setValue(*(void**)(argv[p + 1]), ptype);
+ } else {
+ variant = QVariant(QMetaType::type(ptype), argv[p+1]);
+ // variant.setValue(argv[p + 1], ptype);
+ }
+ } else {
+ variant = QVariant(vt, argv[p + 1]);
+ }
+ }
+
+ QVariantToVARIANT(variant, *arg, type, out);
+ }
+
+ VARIANT retval;
+ VariantInit(&retval);
+ VARIANT *pretval = 0;
+ if (!type.isEmpty())
+ pretval = &retval;
+
+ // call listeners (through IDispatch)
+ while (cc) {
+ if (c->pUnk) {
+ IDispatch *disp = 0;
+ c->pUnk->QueryInterface(IID_QAxEvents, (void**)&disp);
+ if (disp) {
+ disp->Invoke(eventId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispParams, pretval, 0, &argErr);
+
+ // update out-parameters and return value
+ if (index > 0) {
+ for (p = 0; p < pcount; ++p) {
+ bool out;
+ QByteArray ptype = paramType(ptypes.at(p), &out);
+ if (out)
+ QVariantToVoidStar(VARIANTToQVariant(dispParams.rgvarg[pcount - p - 1], ptype), argv[p+1], ptype);
+ }
+ if (pretval)
+ QVariantToVoidStar(VARIANTToQVariant(retval, type), argv[0], type);
+ }
+ disp->Release();
+ }
+ c->pUnk->Release(); // AddRef'ed by clist->Next implementation
+ }
+ clist->Next(cc, (CONNECTDATA*)&c, &cc);
+ }
+
+ // clean up
+ for (p = 0; p < pcount; ++p)
+ clearVARIANT(dispParams.rgvarg+p);
+ free(dispParams.rgvarg);
+ }
+ clist->Release();
+ }
+ cpoint->Release();
+ }
+
+ return true;
+}
+
+/*!
+ Call IPropertyNotifySink of connected clients.
+ \a dispId specifies the ID of the property that changed.
+*/
+bool QAxServerBase::emitRequestPropertyChange(const char *property)
+{
+ long dispId = -1;
+
+ IConnectionPoint *cpoint = 0;
+ FindConnectionPoint(IID_IPropertyNotifySink, &cpoint);
+ if (cpoint) {
+ IEnumConnections *clist = 0;
+ cpoint->EnumConnections(&clist);
+ if (clist) {
+ clist->Reset();
+ ULONG cc = 1;
+ CONNECTDATA c[1];
+ clist->Next(cc, (CONNECTDATA*)&c, &cc);
+ if (cc) {
+ if (dispId == -1) {
+ BSTR bstr = QStringToBSTR(QLatin1String(property));
+ GetIDsOfNames(IID_NULL, &bstr, 1, LOCALE_USER_DEFAULT, &dispId);
+ SysFreeString(bstr);
+ }
+ if (dispId != -1) while (cc) {
+ if (c->pUnk) {
+ IPropertyNotifySink *sink = 0;
+ c->pUnk->QueryInterface(IID_IPropertyNotifySink, (void**)&sink);
+ bool disallows = sink && sink->OnRequestEdit(dispId) == S_FALSE;
+ sink->Release();
+ c->pUnk->Release();
+ if (disallows) { // a client disallows the property to change
+ clist->Release();
+ cpoint->Release();
+ return false;
+ }
+ }
+ clist->Next(cc, (CONNECTDATA*)&c, &cc);
+ }
+ }
+ clist->Release();
+ }
+ cpoint->Release();
+ }
+ dirtyflag = true;
+ return true;
+}
+
+/*!
+ Call IPropertyNotifySink of connected clients.
+ \a dispId specifies the ID of the property that changed.
+*/
+void QAxServerBase::emitPropertyChanged(const char *property)
+{
+ long dispId = -1;
+
+ IConnectionPoint *cpoint = 0;
+ FindConnectionPoint(IID_IPropertyNotifySink, &cpoint);
+ if (cpoint) {
+ IEnumConnections *clist = 0;
+ cpoint->EnumConnections(&clist);
+ if (clist) {
+ clist->Reset();
+ ULONG cc = 1;
+ CONNECTDATA c[1];
+ clist->Next(cc, (CONNECTDATA*)&c, &cc);
+ if (cc) {
+ if (dispId == -1) {
+ BSTR bstr = QStringToBSTR(QLatin1String(property));
+ GetIDsOfNames(IID_NULL, &bstr, 1, LOCALE_USER_DEFAULT, &dispId);
+ SysFreeString(bstr);
+ }
+ if (dispId != -1) while (cc) {
+ if (c->pUnk) {
+ IPropertyNotifySink *sink = 0;
+ c->pUnk->QueryInterface(IID_IPropertyNotifySink, (void**)&sink);
+ if (sink) {
+ sink->OnChanged(dispId);
+ sink->Release();
+ }
+ c->pUnk->Release();
+ }
+ clist->Next(cc, (CONNECTDATA*)&c, &cc);
+ }
+ }
+ clist->Release();
+ }
+ cpoint->Release();
+ }
+ dirtyflag = true;
+}
+
+//**** IProvideClassInfo
+/*
+ Provide the ITypeInfo implementation for the COM class.
+*/
+HRESULT WINAPI QAxServerBase::GetClassInfo(ITypeInfo** pptinfo)
+{
+ if (!pptinfo)
+ return E_POINTER;
+
+ *pptinfo = 0;
+ if (!qAxTypeLibrary)
+ return DISP_E_BADINDEX;
+
+ return qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->classID(class_name), pptinfo);
+}
+
+//**** IProvideClassInfo2
+/*
+ Provide the ID of the event interface.
+*/
+HRESULT WINAPI QAxServerBase::GetGUID(DWORD dwGuidKind, GUID* pGUID)
+{
+ if (!pGUID)
+ return E_POINTER;
+
+ if (dwGuidKind == GUIDKIND_DEFAULT_SOURCE_DISP_IID) {
+ *pGUID = qAxFactory()->eventsID(class_name);
+ return S_OK;
+ }
+ *pGUID = GUID_NULL;
+ return E_FAIL;
+}
+
+//**** IDispatch
+/*
+ Returns the number of class infos for this IDispatch.
+*/
+HRESULT WINAPI QAxServerBase::GetTypeInfoCount(UINT* pctinfo)
+{
+ if (!pctinfo)
+ return E_POINTER;
+
+ *pctinfo = qAxTypeLibrary ? 1 : 0;
+ return S_OK;
+}
+
+/*
+ Provides the ITypeInfo for this IDispatch implementation.
+*/
+HRESULT WINAPI QAxServerBase::GetTypeInfo(UINT itinfo, LCID /*lcid*/, ITypeInfo** pptinfo)
+{
+ if (!pptinfo)
+ return E_POINTER;
+
+ if (!qAxTypeLibrary)
+ return DISP_E_BADINDEX;
+
+ ensureMetaData();
+
+ *pptinfo = m_spTypeInfo;
+ (*pptinfo)->AddRef();
+
+ return S_OK;
+}
+
+/*
+ Provides the names of the methods implemented in this IDispatch implementation.
+*/
+HRESULT WINAPI QAxServerBase::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
+ LCID /*lcid*/, DISPID* rgdispid)
+{
+ if (!rgszNames || !rgdispid)
+ return E_POINTER;
+
+ if (!qAxTypeLibrary)
+ return DISP_E_UNKNOWNNAME;
+
+ ensureMetaData();
+ if (!m_spTypeInfo)
+ return DISP_E_UNKNOWNNAME;
+
+ return m_spTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
+}
+
+/*
+ Map the COM call to the Qt slot/property for \a dispidMember.
+*/
+HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid,
+ LCID /*lcid*/, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult,
+ EXCEPINFO* pexcepinfo, UINT* puArgErr)
+{
+ if (riid != IID_NULL)
+ return DISP_E_UNKNOWNINTERFACE;
+ if (!theObject)
+ return E_UNEXPECTED;
+
+ HRESULT res = DISP_E_MEMBERNOTFOUND;
+
+ bool uniqueIndex = wFlags == DISPATCH_PROPERTYGET || wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_METHOD;
+
+ int index = uniqueIndex ? indexCache.value(dispidMember, -1) : -1;
+ QByteArray name;
+ if (index == -1) {
+ ensureMetaData();
+
+ // This property or method is invoked when an ActiveX client specifies
+ // the object name without a property or method. We only support property.
+ if (dispidMember == DISPID_VALUE && (wFlags == DISPATCH_PROPERTYGET || wFlags == DISPATCH_PROPERTYPUT)) {
+ const QMetaObject *mo = qt.object->metaObject();
+ index = mo->indexOfClassInfo("DefaultProperty");
+ if (index != -1) {
+ name = mo->classInfo(index).value();
+ index = mo->indexOfProperty(name);
+ }
+ } else {
+ BSTR bname;
+ UINT cname = 0;
+ if (m_spTypeInfo)
+ m_spTypeInfo->GetNames(dispidMember, &bname, 1, &cname);
+ if (!cname)
+ return res;
+
+ name = QString::fromWCharArray(bname).toLatin1();
+ SysFreeString(bname);
+ }
+ }
+
+ const QMetaObject *mo = qt.object->metaObject();
+ QSize oldSizeHint;
+ if (isWidget)
+ oldSizeHint = qt.widget->sizeHint();
+
+ switch (wFlags) {
+ case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+ case DISPATCH_PROPERTYGET:
+ {
+ if (index == -1) {
+ index = mo->indexOfProperty(name);
+ if (index == -1 && wFlags == DISPATCH_PROPERTYGET)
+ return res;
+ }
+
+ QMetaProperty property;
+ if (index < mo->propertyCount())
+ property = mo->property(index);
+
+ if (property.isReadable()) {
+ if (!pvarResult)
+ return DISP_E_PARAMNOTOPTIONAL;
+ if (pDispParams->cArgs ||
+ pDispParams->cNamedArgs)
+ return DISP_E_BADPARAMCOUNT;
+
+ QVariant var = qt.object->property(property.name());
+ if (!var.isValid())
+ res = DISP_E_MEMBERNOTFOUND;
+ else if (!QVariantToVARIANT(var, *pvarResult))
+ res = DISP_E_TYPEMISMATCH;
+ else
+ res = S_OK;
+ break;
+ } else if (wFlags == DISPATCH_PROPERTYGET) {
+ break;
+ }
+ }
+ // FALLTHROUGH if wFlags == DISPATCH_PROPERTYGET|DISPATCH_METHOD AND not a property.
+ case DISPATCH_METHOD:
+ {
+ int nameLength = 0;
+ if (index == -1) {
+ nameLength = name.length();
+ name += '(';
+ // no parameter - shortcut
+ if (!pDispParams->cArgs)
+ index = mo->indexOfSlot((name + ')'));
+ // search
+ if (index == -1) {
+ for (int i = 0; i < mo->methodCount(); ++i) {
+ const QMetaMethod slot(mo->method(i));
+ if (slot.methodType() == QMetaMethod::Slot && QByteArray(slot.signature()).startsWith(name)) {
+ index = i;
+ break;
+ }
+ }
+ // resolve overloads
+ if (index == -1) {
+ QRegExp regexp(QLatin1String("_([0-9])\\("));
+ if (regexp.lastIndexIn(QString::fromLatin1(name.constData())) != -1) {
+ name = name.left(name.length() - regexp.cap(0).length()) + '(';
+ int overload = regexp.cap(1).toInt() + 1;
+
+ for (int s = 0; s < qt.object->metaObject()->methodCount(); ++s) {
+ QMetaMethod slot = qt.object->metaObject()->method(s);
+ if (slot.methodType() == QMetaMethod::Slot && QByteArray(slot.signature()).startsWith(name)) {
+ if (!--overload) {
+ index = s;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (index == -1)
+ return res;
+ }
+ }
+
+ int lookupIndex = index;
+
+ // get slot info
+ QMetaMethod slot(mo->method(index));
+ Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
+ QByteArray type = slot.typeName();
+ name = slot.signature();
+ nameLength = name.indexOf('(');
+ QByteArray prototype = name.mid(nameLength + 1);
+ prototype.truncate(prototype.length() - 1);
+ QList<QByteArray> ptypes;
+ if (!prototype.isEmpty())
+ ptypes = prototype.split(',');
+ int pcount = ptypes.count();
+
+ // verify parameter count
+ if (pcount > pDispParams->cArgs) {
+ // count cloned slots immediately following the real thing
+ int defArgs = 0;
+ while (index < mo->methodCount()) {
+ ++index;
+ slot = mo->method(index);
+ if (!(slot.attributes() & QMetaMethod::Cloned))
+ break;
+ --pcount;
+ // found a matching overload. ptypes still valid
+ if (pcount <= pDispParams->cArgs)
+ break;
+ }
+ // still wrong :(
+ if (pcount > pDispParams->cArgs)
+ return DISP_E_PARAMNOTOPTIONAL;
+ } else if (pcount < pDispParams->cArgs) {
+ return DISP_E_BADPARAMCOUNT;
+ }
+
+ // setup parameters (pcount + return)
+ bool ok = true;
+ void *static_argv[QAX_NUM_PARAMS + 1];
+ QVariant static_varp[QAX_NUM_PARAMS + 1];
+ void *static_argv_pointer[QAX_NUM_PARAMS + 1];
+
+ int totalParam = pcount;
+ if (!type.isEmpty())
+ ++totalParam;
+
+ void **argv = 0; // the actual array passed into qt_metacall
+ void **argv_pointer = 0; // in case we need an additional level of indirection
+ QVariant *varp = 0; // QVariants to hold the temporary Qt data object for us
+
+ if (totalParam) {
+ if (totalParam <= QAX_NUM_PARAMS) {
+ argv = static_argv;
+ argv_pointer = static_argv_pointer;
+ varp = static_varp;
+ } else {
+ argv = new void*[pcount + 1];
+ argv_pointer = new void*[pcount + 1];
+ varp = new QVariant[pcount + 1];
+ }
+
+ argv_pointer[0] = 0;
+ }
+
+ for (int p = 0; p < pcount; ++p) {
+ // map the VARIANT to the void*
+ bool out;
+ QByteArray ptype = paramType(ptypes.at(p), &out);
+ varp[p + 1] = VARIANTToQVariant(pDispParams->rgvarg[pcount - p - 1], ptype);
+ argv_pointer[p + 1] = 0;
+ if (varp[p + 1].isValid()) {
+ if (varp[p + 1].type() == QVariant::UserType) {
+ argv[p + 1] = varp[p + 1].data();
+ } else if (ptype == "QVariant") {
+ argv[p + 1] = varp + p + 1;
+ } else {
+ argv[p + 1] = const_cast<void*>(varp[p + 1].constData());
+ if (ptype.endsWith('*')) {
+ argv_pointer[p + 1] = argv[p + 1];
+ argv[p + 1] = argv_pointer + p + 1;
+ }
+ }
+ } else if (ptype == "QVariant") {
+ argv[p + 1] = varp + p + 1;
+ } else {
+ if (puArgErr)
+ *puArgErr = pcount-p-1;
+ ok = false;
+ }
+ }
+
+ // return value
+ if (!type.isEmpty()) {
+ QVariant::Type vt = QVariant::nameToType(type);
+ if (vt == QVariant::UserType)
+ vt = QVariant::Invalid;
+ varp[0] = QVariant(vt);
+ if (varp[0].type() == QVariant::Invalid && mo->indexOfEnumerator(slot.typeName()) != -1)
+ varp[0] = QVariant(QVariant::Int);
+
+ if (varp[0].type() == QVariant::Invalid) {
+ if (type == "QVariant")
+ argv[0] = varp;
+ else
+ argv[0] = 0;
+ } else {
+ argv[0] = const_cast<void*>(varp[0].constData());
+ }
+ if (type.endsWith('*')) {
+ argv_pointer[0] = argv[0];
+ argv[0] = argv_pointer;
+ }
+ }
+
+ // call the slot if everthing went fine.
+ if (ok) {
+ ++invokeCount;
+ qt.object->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
+ if (--invokeCount < 0)
+ invokeCount = 0;
+
+ // update reference parameters and return value
+ for (int p = 0; p < pcount; ++p) {
+ bool out;
+ QByteArray ptype = paramType(ptypes.at(p), &out);
+ if (out) {
+ if (!QVariantToVARIANT(varp[p + 1], pDispParams->rgvarg[pcount - p - 1], ptype, out))
+ ok = false;
+ }
+ }
+ if (!type.isEmpty() && pvarResult) {
+ if (!varp[0].isValid() && type != "QVariant")
+ varp[0] = QVariant(QMetaType::type(type), argv_pointer);
+// varp[0].setValue(argv_pointer[0], type);
+ ok = QVariantToVARIANT(varp[0], *pvarResult, type);
+ }
+ }
+ if (argv && argv != static_argv) {
+ delete []argv;
+ delete []argv_pointer;
+ delete []varp;
+ }
+
+ res = ok ? S_OK : DISP_E_TYPEMISMATCH;
+
+ // reset in case index changed for default-arg handling
+ index = lookupIndex;
+ }
+ break;
+ case DISPATCH_PROPERTYPUT:
+ case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF:
+ {
+ if (index == -1) {
+ index = mo->indexOfProperty(name);
+ if (index == -1)
+ return res;
+ }
+
+ QMetaProperty property;
+ if (index < mo->propertyCount())
+ property = mo->property(index);
+ if (!property.isWritable())
+ return DISP_E_MEMBERNOTFOUND;
+ if (!pDispParams->cArgs)
+ return DISP_E_PARAMNOTOPTIONAL;
+ if (pDispParams->cArgs != 1 ||
+ pDispParams->cNamedArgs != 1 ||
+ *pDispParams->rgdispidNamedArgs != DISPID_PROPERTYPUT)
+ return DISP_E_BADPARAMCOUNT;
+
+ QVariant var = VARIANTToQVariant(*pDispParams->rgvarg, property.typeName(), property.type());
+ if (!var.isValid()) {
+ if (puArgErr)
+ *puArgErr = 0;
+ return DISP_E_BADVARTYPE;
+ }
+ if (!qt.object->setProperty(property.name(), var)) {
+ if (puArgErr)
+ *puArgErr = 0;
+ return DISP_E_TYPEMISMATCH;
+ }
+
+ res = S_OK;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // maybe calling a setter? Notify client about changes
+ switch(wFlags) {
+ case DISPATCH_METHOD:
+ case DISPATCH_PROPERTYPUT:
+ case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF:
+ if (m_spAdviseSink || adviseSinks.count()) {
+ FORMATETC fmt;
+ fmt.cfFormat = 0;
+ fmt.ptd = 0;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ fmt.tymed = TYMED_NULL;
+
+ STGMEDIUM stg;
+ stg.tymed = TYMED_NULL;
+ stg.pUnkForRelease = 0;
+ stg.hBitmap = 0; // initializes the whole union
+
+ if (m_spAdviseSink) {
+ m_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1);
+ m_spAdviseSink->OnDataChange(&fmt, &stg);
+ }
+ for (int i = 0; i < adviseSinks.count(); ++i) {
+ adviseSinks.at(i).pAdvSink->OnDataChange(&fmt, &stg);
+ }
+ }
+
+ dirtyflag = true;
+ break;
+ default:
+ break;
+ }
+
+ if (index != -1 && uniqueIndex)
+ indexCache.insert(dispidMember, index);
+
+ if (exception) {
+ if (pexcepinfo) {
+ memset(pexcepinfo, 0, sizeof(EXCEPINFO));
+
+ pexcepinfo->wCode = exception->code;
+ if (!exception->src.isNull())
+ pexcepinfo->bstrSource = QStringToBSTR(exception->src);
+ if (!exception->desc.isNull())
+ pexcepinfo->bstrDescription = QStringToBSTR(exception->desc);
+ if (!exception->context.isNull()) {
+ QString context = exception->context;
+ int contextID = 0;
+ int br = context.indexOf(QLatin1Char('['));
+ if (br != -1) {
+ context = context.mid(br+1);
+ context = context.left(context.length() - 1);
+ contextID = context.toInt();
+
+ context = exception->context;
+ context = context.left(br-1);
+ }
+ pexcepinfo->bstrHelpFile = QStringToBSTR(context);
+ pexcepinfo->dwHelpContext = contextID;
+ }
+ }
+ delete exception;
+ exception = 0;
+ return DISP_E_EXCEPTION;
+ } else if (isWidget) {
+ QSize sizeHint = qt.widget->sizeHint();
+ if (oldSizeHint != sizeHint) {
+ updateGeometry();
+ if (m_spInPlaceSite) {
+ RECT rect = {0, 0, sizeHint.width(), sizeHint.height()};
+ m_spInPlaceSite->OnPosRectChange(&rect);
+ }
+ }
+ updateMask();
+ }
+
+ return res;
+}
+
+//**** IConnectionPointContainer
+/*
+ Provide the IEnumConnectionPoints implemented in the QAxSignalVec class.
+*/
+HRESULT WINAPI QAxServerBase::EnumConnectionPoints(IEnumConnectionPoints **epoints)
+{
+ if (!epoints)
+ return E_POINTER;
+ *epoints = new QAxSignalVec(points);
+ (*epoints)->AddRef();
+ return S_OK;
+}
+
+/*
+ Provide the IConnectionPoint implemented in the QAxConnection for \a iid.
+*/
+HRESULT WINAPI QAxServerBase::FindConnectionPoint(REFIID iid, IConnectionPoint **cpoint)
+{
+ if (!cpoint)
+ return E_POINTER;
+
+ IConnectionPoint *cp = points[iid];
+ *cpoint = cp;
+ if (cp) {
+ cp->AddRef();
+ return S_OK;
+ }
+ return CONNECT_E_NOCONNECTION;
+}
+
+//**** IPersistStream
+/*
+ \reimp
+
+ See documentation of IPersistStorage::IsDirty.
+*/
+HRESULT WINAPI QAxServerBase::IsDirty()
+{
+ return dirtyflag ? S_OK : S_FALSE;
+}
+
+HRESULT WINAPI QAxServerBase::Load(IStream *pStm)
+{
+ STATSTG stat;
+ HRESULT hres = pStm->Stat(&stat, STATFLAG_DEFAULT);
+ bool openAsText = false;
+ QByteArray qtarray;
+ if (hres == S_OK) {
+ QString streamName = QString::fromWCharArray(stat.pwcsName);
+ CoTaskMemFree(stat.pwcsName);
+ openAsText = streamName == QLatin1String("SomeStreamName");
+ if (stat.cbSize.HighPart) // more than 4GB - too large!
+ return S_FALSE;
+
+ qtarray.resize(stat.cbSize.LowPart);
+ ULONG read;
+ pStm->Read(qtarray.data(), stat.cbSize.LowPart, &read);
+ } else if (hres == E_NOTIMPL) {
+ ULONG read = 0;
+ while (hres != S_FALSE) {
+ QByteArray arrayRead;
+ arrayRead.resize(4098);
+ hres = pStm->Read(arrayRead.data(), arrayRead.size(), &read);
+ if (hres != S_OK && hres != S_FALSE) {
+ qtarray.resize(0);
+ break;
+ } else if (read == 0)
+ break;
+ qtarray.append(arrayRead);
+ }
+ }
+ const QMetaObject *mo = qt.object->metaObject();
+
+ QBuffer qtbuffer(&qtarray);
+ QByteArray mimeType = mo->classInfo(mo->indexOfClassInfo("MIME")).value();
+ if (!mimeType.isEmpty()) {
+ mimeType = mimeType.left(mimeType.indexOf(':')); // first type
+ QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
+ if (axb && axb->readData(&qtbuffer, QString::fromLatin1(mimeType)))
+ return S_OK;
+ }
+
+ qtbuffer.close(); // resets
+ qtbuffer.open(openAsText ? (QIODevice::ReadOnly | QIODevice::Text) : QIODevice::ReadOnly);
+
+ QDataStream qtstream(&qtbuffer);
+ int version;
+ qtstream >> version;
+ qtstream.setVersion(version);
+ int more = 0;
+ qtstream >> more;
+
+ while (!qtbuffer.atEnd() && more) {
+ QString propname;
+ QVariant value;
+ qtstream >> propname;
+ if (propname.isEmpty())
+ break;
+ qtstream >> value;
+ qtstream >> more;
+
+ int idx = mo->indexOfProperty(propname.toLatin1());
+ QMetaProperty property = mo->property(idx);
+ if (property.isWritable())
+ qt.object->setProperty(propname.toLatin1(), value);
+ }
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::Save(IStream *pStm, BOOL clearDirty)
+{
+ const QMetaObject *mo = qt.object->metaObject();
+
+ QBuffer qtbuffer;
+ bool saved = false;
+ QByteArray mimeType = mo->classInfo(mo->indexOfClassInfo("MIME")).value();
+ if (!mimeType.isEmpty()) {
+ QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
+ saved = axb && axb->writeData(&qtbuffer);
+ qtbuffer.close();
+ }
+
+ if (!saved) {
+ qtbuffer.open(QIODevice::WriteOnly);
+ QDataStream qtstream(&qtbuffer);
+ qtstream << qtstream.version();
+
+ for (int prop = 0; prop < mo->propertyCount(); ++prop) {
+ if (!isPropertyExposed(prop))
+ continue;
+ QMetaProperty metaprop = mo->property(prop);
+ if (QByteArray(metaprop.typeName()).endsWith('*'))
+ continue;
+ QString property = QLatin1String(metaprop.name());
+ QVariant qvar = qt.object->property(metaprop.name());
+ if (qvar.isValid()) {
+ qtstream << int(1);
+ qtstream << property;
+ qtstream << qvar;
+ }
+ }
+
+ qtstream << int(0);
+ qtbuffer.close();
+ }
+
+ QByteArray qtarray = qtbuffer.buffer();
+ ULONG written = 0;
+ const char *data = qtarray.constData();
+ ULARGE_INTEGER newsize;
+ newsize.HighPart = 0;
+ newsize.LowPart = qtarray.size();
+ pStm->SetSize(newsize);
+ pStm->Write(data, qtarray.size(), &written);
+ pStm->Commit(STGC_ONLYIFCURRENT);
+
+ if (clearDirty)
+ dirtyflag = false;
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::GetSizeMax(ULARGE_INTEGER *pcbSize)
+{
+ const QMetaObject *mo = qt.object->metaObject();
+
+ int np = mo->propertyCount();
+ pcbSize->HighPart = 0;
+ pcbSize->LowPart = np * 50;
+
+ return S_OK;
+}
+
+//**** IPersistStorage
+
+HRESULT WINAPI QAxServerBase::InitNew(IStorage *pStg)
+{
+ if (initNewCalled)
+ return CO_E_ALREADYINITIALIZED;
+
+ dirtyflag = false;
+ initNewCalled = true;
+
+ m_spStorage = pStg;
+ if (m_spStorage)
+ m_spStorage->AddRef();
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::Load(IStorage *pStg)
+{
+ if (InitNew(pStg) != S_OK)
+ return CO_E_ALREADYINITIALIZED;
+
+ IStream *spStream = 0;
+ QString streamName = QLatin1String(qt.object->metaObject()->className());
+ streamName.replace(QLatin1Char(':'), QLatin1Char('.'));
+ /* Also invalid, but not relevant
+ streamName.replace(QLatin1Char('/'), QLatin1Char('_'));
+ streamName.replace(QLatin1Char('\\'), QLatin1Char('_'));
+ */
+ streamName += QLatin1String("_Stream4.2");
+
+ pStg->OpenStream((const wchar_t *)streamName.utf16(), 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream);
+ if (!spStream) // support for streams saved with 4.1 and earlier
+ pStg->OpenStream(L"SomeStreamName", 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream);
+ if (!spStream)
+ return E_FAIL;
+
+ Load(spStream);
+ spStream->Release();
+
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::Save(IStorage *pStg, BOOL fSameAsLoad)
+{
+ IStream *spStream = 0;
+ QString streamName = QLatin1String(qt.object->metaObject()->className());
+ streamName.replace(QLatin1Char(':'), QLatin1Char('.'));
+ /* Also invalid, but not relevant
+ streamName.replace(QLatin1Char('/'), QLatin1Char('_'));
+ streamName.replace(QLatin1Char('\\'), QLatin1Char('_'));
+ */
+ streamName += QLatin1String("_Stream4.2");
+
+ pStg->CreateStream((const wchar_t *)streamName.utf16(), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStream);
+ if (!spStream)
+ return E_FAIL;
+
+ Save(spStream, true);
+
+ spStream->Release();
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::SaveCompleted(IStorage *pStgNew)
+{
+ if (pStgNew) {
+ if (m_spStorage)
+ m_spStorage->Release();
+ m_spStorage = pStgNew;
+ m_spStorage->AddRef();
+ }
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::HandsOffStorage()
+{
+ if (m_spStorage) m_spStorage->Release();
+ m_spStorage = 0;
+
+ return S_OK;
+}
+
+//**** IPersistPropertyBag
+/*
+ Initialize the properties of the Qt widget.
+*/
+HRESULT WINAPI QAxServerBase::InitNew()
+{
+ if (initNewCalled)
+ return CO_E_ALREADYINITIALIZED;
+
+ dirtyflag = false;
+ initNewCalled = true;
+ return S_OK;
+}
+
+/*
+ Set the properties of the Qt widget to the values provided in the \a bag.
+*/
+HRESULT WINAPI QAxServerBase::Load(IPropertyBag *bag, IErrorLog * /*log*/)
+{
+ if (!bag)
+ return E_POINTER;
+
+ if (InitNew() != S_OK)
+ return E_UNEXPECTED;
+
+ bool error = false;
+ const QMetaObject *mo = qt.object->metaObject();
+ for (int prop = 0; prop < mo->propertyCount(); ++prop) {
+ if (!isPropertyExposed(prop))
+ continue;
+ QMetaProperty property = mo->property(prop);
+ const char* pname = property.name();
+ BSTR bstr = QStringToBSTR(QLatin1String(pname));
+ VARIANT var;
+ var.vt = VT_EMPTY;
+ HRESULT res = bag->Read(bstr, &var, 0);
+ if (property.isWritable() && var.vt != VT_EMPTY) {
+ if (res != S_OK || !qt.object->setProperty(pname, VARIANTToQVariant(var, property.typeName(), property.type())))
+ error = true;
+ }
+ SysFreeString(bstr);
+ }
+
+ updateGeometry();
+
+ return /*error ? E_FAIL :*/ S_OK;
+}
+
+/*
+ Save the properties of the Qt widget into the \a bag.
+*/
+HRESULT WINAPI QAxServerBase::Save(IPropertyBag *bag, BOOL clearDirty, BOOL /*saveAll*/)
+{
+ if (!bag)
+ return E_POINTER;
+
+ if (clearDirty)
+ dirtyflag = false;
+ bool error = false;
+ const QMetaObject *mo = qt.object->metaObject();
+ for (int prop = 0; prop < mo->propertyCount(); ++prop) {
+ if (!isPropertyExposed(prop))
+ continue;
+ QMetaProperty property = mo->property(prop);
+ if (QByteArray(property.typeName()).endsWith('*'))
+ continue;
+
+ BSTR bstr = QStringToBSTR(QLatin1String(property.name()));
+ QVariant qvar = qt.object->property(property.name());
+ if (!qvar.isValid())
+ error = true;
+ VARIANT var;
+ QVariantToVARIANT(qvar, var);
+ bag->Write(bstr, &var);
+ SysFreeString(bstr);
+ }
+ return /*error ? E_FAIL :*/ S_OK;
+}
+
+//**** IPersistFile
+/*
+*/
+HRESULT WINAPI QAxServerBase::SaveCompleted(LPCOLESTR fileName)
+{
+ if (qt.object->metaObject()->indexOfClassInfo("MIME") == -1)
+ return E_NOTIMPL;
+
+ currentFileName = QString::fromWCharArray(fileName);
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::GetCurFile(LPOLESTR *currentFile)
+{
+ if (qt.object->metaObject()->indexOfClassInfo("MIME") == -1)
+ return E_NOTIMPL;
+
+ if (currentFileName.isEmpty()) {
+ *currentFile = 0;
+ return S_FALSE;
+ }
+ IMalloc *malloc = 0;
+ CoGetMalloc(1, &malloc);
+ if (!malloc)
+ return E_OUTOFMEMORY;
+
+ *currentFile = static_cast<wchar_t *>(malloc->Alloc(currentFileName.length() * 2));
+ malloc->Release();
+ memcpy(*currentFile, currentFileName.unicode(), currentFileName.length() * 2);
+
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::Load(LPCOLESTR fileName, DWORD mode)
+{
+ const QMetaObject *mo = qt.object->metaObject();
+ int mimeIndex = mo->indexOfClassInfo("MIME");
+ if (mimeIndex == -1)
+ return E_NOTIMPL;
+
+ QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
+ if (!axb) {
+ qWarning() << class_name << ": No QAxBindable implementation for mime-type handling";
+ return E_NOTIMPL;
+ }
+
+ QString loadFileName = QString::fromWCharArray(fileName);
+ QString fileExtension = loadFileName.mid(loadFileName.lastIndexOf(QLatin1Char('.')) + 1);
+ QFile file(loadFileName);
+
+ QString mimeType = QLatin1String(mo->classInfo(mimeIndex).value());
+ QStringList mimeTypes = mimeType.split(QLatin1Char(';'));
+ for (int m = 0; m < mimeTypes.count(); ++m) {
+ QString mime = mimeTypes.at(m);
+ if (mime.count(QLatin1Char(':')) != 2) {
+ qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
+ continue;
+ }
+
+ mimeType = mime.left(mimeType.indexOf(QLatin1Char(':'))); // first type
+ if (mimeType.isEmpty()) {
+ qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
+ continue;
+ }
+ QString mimeExtension = mime.mid(mimeType.length() + 1);
+ mimeExtension = mimeExtension.left(mimeExtension.indexOf(QLatin1Char(':')));
+ if (mimeExtension != fileExtension)
+ continue;
+
+ if (axb->readData(&file, mimeType)) {
+ currentFileName = loadFileName;
+ return S_OK;
+ }
+ }
+
+ return E_FAIL;
+}
+
+HRESULT WINAPI QAxServerBase::Save(LPCOLESTR fileName, BOOL fRemember)
+{
+ const QMetaObject *mo = qt.object->metaObject();
+ int mimeIndex = mo->indexOfClassInfo("MIME");
+ if (mimeIndex == -1)
+ return E_NOTIMPL;
+
+ QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
+ if (!axb) {
+ qWarning() << class_name << ": No QAxBindable implementation for mime-type handling";
+ return E_NOTIMPL;
+ }
+
+ QString saveFileName = QString::fromWCharArray(fileName);
+ QString fileExtension = saveFileName.mid(saveFileName.lastIndexOf(QLatin1Char('.')) + 1);
+ QFile file(saveFileName);
+
+ QString mimeType = QLatin1String(mo->classInfo(mimeIndex).value());
+ QStringList mimeTypes = mimeType.split(QLatin1Char(';'));
+ for (int m = 0; m < mimeTypes.count(); ++m) {
+ QString mime = mimeTypes.at(m);
+ if (mime.count(QLatin1Char(':')) != 2) {
+ qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
+ continue;
+ }
+ mimeType = mime.left(mimeType.indexOf(QLatin1Char(':'))); // first type
+ if (mimeType.isEmpty()) {
+ qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
+ continue;
+ }
+ QString mimeExtension = mime.mid(mimeType.length() + 1);
+ mimeExtension = mimeExtension.left(mimeExtension.indexOf(QLatin1Char(':')));
+ if (mimeExtension != fileExtension)
+ continue;
+ if (axb->writeData(&file)) {
+ if (fRemember)
+ currentFileName = saveFileName;
+ return S_OK;
+ }
+ }
+ return E_FAIL;
+}
+
+//**** IViewObject
+/*
+ Draws the widget into the provided device context.
+*/
+HRESULT WINAPI QAxServerBase::Draw(DWORD dwAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
+ HDC hicTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL /*lprcWBounds*/,
+ BOOL(__stdcall* /*pfnContinue*/)(ULONG_PTR), ULONG_PTR /*dwContinue*/)
+{
+ if (!lprcBounds)
+ return E_INVALIDARG;
+
+ internalCreate();
+ if (!isWidget || !qt.widget)
+ return OLE_E_BLANK;
+
+ switch (dwAspect) {
+ case DVASPECT_CONTENT:
+ case DVASPECT_OPAQUE:
+ case DVASPECT_TRANSPARENT:
+ break;
+ default:
+ return DV_E_DVASPECT;
+ }
+ if (!ptd)
+ hicTargetDev = 0;
+
+ bool bDeleteDC = false;
+ if (!hicTargetDev) {
+ hicTargetDev = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
+ bDeleteDC = (hicTargetDev != hdcDraw);
+ }
+
+ RECTL rc = *lprcBounds;
+ bool bMetaFile = GetDeviceCaps(hdcDraw, TECHNOLOGY) == DT_METAFILE;
+ if (!bMetaFile)
+ ::LPtoDP(hicTargetDev, (LPPOINT)&rc, 2);
+
+ QPixmap pm = QPixmap::grabWidget(qt.widget);
+ HBITMAP hbm = pm.toWinHBITMAP();
+ HDC hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, hbm);
+ ::StretchBlt(hdcDraw, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0,pm.width(), pm.height(), SRCCOPY);
+ DeleteDC(hdc);
+ DeleteObject(hbm);
+
+ if (bDeleteDC)
+ DeleteDC(hicTargetDev);
+
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
+ HDC hicTargetDev, LOGPALETTE **ppColorSet)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::Freeze(DWORD dwAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::Unfreeze(DWORD dwFreeze)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Stores the provided advise sink.
+*/
+HRESULT WINAPI QAxServerBase::SetAdvise(DWORD /*aspects*/, DWORD /*advf*/, IAdviseSink *pAdvSink)
+{
+ if (m_spAdviseSink) m_spAdviseSink->Release();
+
+ m_spAdviseSink = pAdvSink;
+ if (m_spAdviseSink) m_spAdviseSink->AddRef();
+ return S_OK;
+}
+
+/*
+ Returns the advise sink.
+*/
+HRESULT WINAPI QAxServerBase::GetAdvise(DWORD* /*aspects*/, DWORD* /*advf*/, IAdviseSink **ppAdvSink)
+{
+ if (!ppAdvSink)
+ return E_POINTER;
+
+ *ppAdvSink = m_spAdviseSink;
+ if (*ppAdvSink)
+ (*ppAdvSink)->AddRef();
+ return S_OK;
+}
+
+//**** IViewObject2
+/*
+ Returns the current size ONLY if the widget has already been sized.
+*/
+HRESULT WINAPI QAxServerBase::GetExtent(DWORD dwAspect, LONG /*lindex*/, DVTARGETDEVICE* /*ptd*/, LPSIZEL lpsizel)
+{
+ if (!isWidget || !qt.widget || !qt.widget->testAttribute(Qt::WA_Resized))
+ return OLE_E_BLANK;
+
+ return GetExtent(dwAspect, lpsizel);
+}
+
+//**** IOleControl
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::GetControlInfo(LPCONTROLINFO)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Turns event firing on and off.
+*/
+HRESULT WINAPI QAxServerBase::FreezeEvents(BOOL bFreeze)
+{
+ // member of CComControl
+ if (bFreeze)
+ freezeEvents++;
+ else
+ freezeEvents--;
+
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::OnMnemonic(LPMSG)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Update the ambient properties of the Qt widget.
+*/
+HRESULT WINAPI QAxServerBase::OnAmbientPropertyChange(DISPID dispID)
+{
+ if (!m_spClientSite || !theObject)
+ return S_OK;
+
+ IDispatch *disp = 0;
+ m_spClientSite->QueryInterface(IID_IDispatch, (void**)&disp);
+ if (!disp)
+ return S_OK;
+
+ VARIANT var;
+ VariantInit(&var);
+ DISPPARAMS params = { 0, 0, 0, 0 };
+ disp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params, &var, 0, 0);
+ disp->Release();
+ disp = 0;
+
+ switch(dispID) {
+ case DISPID_AMBIENT_APPEARANCE:
+ break;
+ case DISPID_AMBIENT_AUTOCLIP:
+ break;
+ case DISPID_AMBIENT_BACKCOLOR:
+ case DISPID_AMBIENT_FORECOLOR:
+ if (isWidget) {
+ long rgb;
+ if (var.vt == VT_UI4)
+ rgb = var.ulVal;
+ else if (var.vt == VT_I4)
+ rgb = var.lVal;
+ else
+ break;
+ QPalette pal = qt.widget->palette();
+ pal.setColor(dispID == DISPID_AMBIENT_BACKCOLOR ? QPalette::Window : QPalette::WindowText,
+ OLEColorToQColor(rgb));
+ qt.widget->setPalette(pal);
+ }
+ break;
+ case DISPID_AMBIENT_DISPLAYASDEFAULT:
+ break;
+ case DISPID_AMBIENT_DISPLAYNAME:
+ if (var.vt != VT_BSTR || !isWidget)
+ break;
+ qt.widget->setWindowTitle(QString::fromWCharArray(var.bstrVal));
+ break;
+ case DISPID_AMBIENT_FONT:
+ if (var.vt != VT_DISPATCH || !isWidget)
+ break;
+ {
+ QVariant qvar = VARIANTToQVariant(var, "QFont", QVariant::Font);
+ QFont qfont = qvariant_cast<QFont>(qvar);
+ qt.widget->setFont(qfont);
+ }
+ break;
+ case DISPID_AMBIENT_LOCALEID:
+ break;
+ case DISPID_AMBIENT_MESSAGEREFLECT:
+ if (var.vt != VT_BOOL)
+ break;
+ if (var.boolVal)
+ qt.widget->installEventFilter(this);
+ else
+ qt.widget->removeEventFilter(this);
+ break;
+ case DISPID_AMBIENT_PALETTE:
+ break;
+ case DISPID_AMBIENT_SCALEUNITS:
+ break;
+ case DISPID_AMBIENT_SHOWGRABHANDLES:
+ break;
+ case DISPID_AMBIENT_SHOWHATCHING:
+ break;
+ case DISPID_AMBIENT_SUPPORTSMNEMONICS:
+ break;
+ case DISPID_AMBIENT_TEXTALIGN:
+ break;
+ case DISPID_AMBIENT_UIDEAD:
+ if (var.vt != VT_BOOL || !isWidget)
+ break;
+ qt.widget->setEnabled(!var.boolVal);
+ break;
+ case DISPID_AMBIENT_USERMODE:
+ if (var.vt != VT_BOOL)
+ break;
+ inDesignMode = !var.boolVal;
+ break;
+ case DISPID_AMBIENT_RIGHTTOLEFT:
+ if (var.vt != VT_BOOL)
+ break;
+ qApp->setLayoutDirection(var.boolVal?Qt::RightToLeft:Qt::LeftToRight);
+ break;
+ }
+
+ return S_OK;
+}
+
+//**** IOleWindow
+/*
+ Returns the HWND of the control.
+*/
+HRESULT WINAPI QAxServerBase::GetWindow(HWND *pHwnd)
+{
+ if (!pHwnd)
+ return E_POINTER;
+ *pHwnd = m_hWnd;
+ return S_OK;
+}
+
+/*
+ Enters What's This mode.
+*/
+HRESULT WINAPI QAxServerBase::ContextSensitiveHelp(BOOL fEnterMode)
+{
+ if (fEnterMode)
+ QWhatsThis::enterWhatsThisMode();
+ else
+ QWhatsThis::leaveWhatsThisMode();
+ return S_OK;
+}
+
+//**** IOleInPlaceObject
+/*
+ Deactivates the control in place.
+*/
+HRESULT WINAPI QAxServerBase::InPlaceDeactivate()
+{
+ if (!isInPlaceActive)
+ return S_OK;
+ UIDeactivate();
+
+ isInPlaceActive = false;
+
+ // if we have a window, tell it to go away.
+ if (m_hWnd) {
+ if (::IsWindow(m_hWnd))
+ ::DestroyWindow(m_hWnd);
+ m_hWnd = 0;
+ }
+
+ if (m_spInPlaceSite)
+ m_spInPlaceSite->OnInPlaceDeactivate();
+
+ return S_OK;
+}
+
+/*
+ Deactivates the control's user interface.
+*/
+HRESULT WINAPI QAxServerBase::UIDeactivate()
+{
+ // if we're not UIActive, not much to do.
+ if (!isUIActive || !m_spInPlaceSite)
+ return S_OK;
+
+ isUIActive = false;
+
+ // notify frame windows, if appropriate, that we're no longer ui-active.
+ HWND hwndParent;
+ if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK) {
+ if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
+ m_spInPlaceFrame = 0;
+ IOleInPlaceUIWindow *spInPlaceUIWindow = 0;
+ RECT rcPos, rcClip;
+ OLEINPLACEFRAMEINFO frameInfo;
+ frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
+
+ m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
+ if (spInPlaceUIWindow) {
+ spInPlaceUIWindow->SetActiveObject(0, 0);
+ spInPlaceUIWindow->Release();
+ }
+ if (m_spInPlaceFrame) {
+ removeMenu();
+ if (menuBar) {
+ menuBar->removeEventFilter(this);
+ menuBar = 0;
+ }
+ if (statusBar) {
+ statusBar->removeEventFilter(this);
+ const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)");
+ QMetaObject::disconnect(statusBar, index, this, -1);
+ statusBar = 0;
+ }
+ m_spInPlaceFrame->SetActiveObject(0, 0);
+ m_spInPlaceFrame->Release();
+ m_spInPlaceFrame = 0;
+ }
+ }
+ // we don't need to explicitly release the focus here since somebody
+ // else grabbing the focus is usually why we are getting called at all
+ m_spInPlaceSite->OnUIDeactivate(false);
+
+ return S_OK;
+}
+
+/*
+ Positions the control, and applies requested clipping.
+*/
+HRESULT WINAPI QAxServerBase::SetObjectRects(LPCRECT prcPos, LPCRECT prcClip)
+{
+ if (prcPos == 0 || prcClip == 0)
+ return E_POINTER;
+
+ if (m_hWnd) {
+ // the container wants us to clip, so figure out if we really need to
+ RECT rcIXect;
+ BOOL b = IntersectRect(&rcIXect, prcPos, prcClip);
+ HRGN tempRgn = 0;
+ if (b && !EqualRect(&rcIXect, prcPos)) {
+ OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
+ tempRgn = CreateRectRgnIndirect(&rcIXect);
+ }
+
+ ::SetWindowRgn(m_hWnd, tempRgn, true);
+ ::SetWindowPos(m_hWnd, 0, prcPos->left, prcPos->top,
+ prcPos->right - prcPos->left, prcPos->bottom - prcPos->top,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+
+ //Save the new extent.
+ m_currentExtent.rwidth() = qBound(qt.widget->minimumWidth(), int(prcPos->right - prcPos->left), qt.widget->maximumWidth());
+ m_currentExtent.rheight() = qBound(qt.widget->minimumHeight(), int(prcPos->bottom - prcPos->top), qt.widget->maximumHeight());
+
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::ReactivateAndUndo()
+{
+ return E_NOTIMPL;
+}
+
+//**** IOleInPlaceActiveObject
+
+Q_GUI_EXPORT int qt_translateKeyCode(int);
+
+HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg)
+{
+ if (pMsg->message != WM_KEYDOWN || !isWidget)
+ return S_FALSE;
+
+ DWORD dwKeyMod = 0;
+ if (::GetKeyState(VK_SHIFT) < 0)
+ dwKeyMod |= 1; // KEYMOD_SHIFT
+ if (::GetKeyState(VK_CONTROL) < 0)
+ dwKeyMod |= 2; // KEYMOD_CONTROL
+ if (::GetKeyState(VK_MENU) < 0)
+ dwKeyMod |= 4; // KEYMOD_ALT
+
+ switch (LOWORD(pMsg->wParam)) {
+ case VK_TAB:
+ if (isUIActive) {
+ bool shift = ::GetKeyState(VK_SHIFT) < 0;
+ bool giveUp = true;
+ QWidget *curFocus = qt.widget->focusWidget();
+ if (curFocus) {
+ if (shift) {
+ if (!curFocus->isWindow()) {
+ QWidget *nextFocus = curFocus->nextInFocusChain();
+ QWidget *prevFocus = 0;
+ QWidget *topLevel = 0;
+ while (nextFocus != curFocus) {
+ if (nextFocus->focusPolicy() & Qt::TabFocus) {
+ prevFocus = nextFocus;
+ topLevel = 0;
+ } else if (nextFocus->isWindow()) {
+ topLevel = nextFocus;
+ }
+ nextFocus = nextFocus->nextInFocusChain();
+ }
+
+ if (!topLevel) {
+ giveUp = false;
+ ((HackWidget*)curFocus)->focusNextPrevChild(false);
+ curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ }
+ }
+ } else {
+ QWidget *nextFocus = curFocus;
+ while (1) {
+ nextFocus = nextFocus->nextInFocusChain();
+ if (nextFocus->isWindow())
+ break;
+ if (nextFocus->focusPolicy() & Qt::TabFocus) {
+ giveUp = false;
+ ((HackWidget*)curFocus)->focusNextPrevChild(true);
+ curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
+ break;
+ }
+ }
+ }
+ }
+ if (giveUp) {
+ HWND hwnd = ::GetParent(m_hWnd);
+ ::SetFocus(hwnd);
+ } else {
+ return S_OK;
+ }
+
+ }
+ break;
+
+ case VK_LEFT:
+ case VK_RIGHT:
+ case VK_UP:
+ case VK_DOWN:
+ if (isUIActive)
+ return S_FALSE;
+ break;
+
+ default:
+ if (isUIActive && qt.widget->focusWidget()) {
+ int state = Qt::NoButton;
+ if (dwKeyMod & 1)
+ state |= Qt::ShiftModifier;
+ if (dwKeyMod & 2)
+ state |= Qt::ControlModifier;
+ if (dwKeyMod & 4)
+ state |= Qt::AltModifier;
+
+ int key = pMsg->wParam;
+ if (!(key >= 'A' && key <= 'Z') && !(key >= '0' && key <= '9'))
+ key = qt_translateKeyCode(pMsg->wParam);
+
+ QKeyEvent override(QEvent::ShortcutOverride, key, (Qt::KeyboardModifiers)state);
+ override.ignore();
+ QApplication::sendEvent(qt.widget->focusWidget(), &override);
+ if (override.isAccepted())
+ return S_FALSE;
+ }
+ break;
+ }
+
+ if (!m_spClientSite)
+ return S_FALSE;
+
+ IOleControlSite *controlSite = 0;
+ m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&controlSite);
+ if (!controlSite)
+ return S_FALSE;
+ bool resetUserData = false;
+ // set server type in the user-data of the window.
+#ifdef GWLP_USERDATA
+ LONG_PTR serverType = QAX_INPROC_SERVER;
+#else
+ LONG serverType = QAX_INPROC_SERVER;
+#endif
+ if (qAxOutProcServer)
+ serverType = QAX_OUTPROC_SERVER;
+#ifdef GWLP_USERDATA
+ LONG_PTR oldData = SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, serverType);
+#else
+ LONG oldData = SetWindowLong(pMsg->hwnd, GWL_USERDATA, serverType);
+#endif
+ HRESULT hres = controlSite->TranslateAcceleratorW(pMsg, dwKeyMod);
+ controlSite->Release();
+ // reset the user-data for the window.
+#ifdef GWLP_USERDATA
+ SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, oldData);
+#else
+ SetWindowLong(pMsg->hwnd, GWL_USERDATA, oldData);
+#endif
+ return hres;
+}
+
+HRESULT WINAPI QAxServerBase::TranslateAcceleratorA(MSG *pMsg)
+{
+ return TranslateAcceleratorW(pMsg);
+}
+
+HRESULT WINAPI QAxServerBase::OnFrameWindowActivate(BOOL fActivate)
+{
+ if (fActivate) {
+ if (wasUIActive)
+ ::SetFocus(m_hWnd);
+ } else {
+ wasUIActive = isUIActive;
+ }
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::OnDocWindowActivate(BOOL fActivate)
+{
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow)
+{
+ return S_OK;
+}
+
+HRESULT WINAPI QAxServerBase::EnableModeless(BOOL fEnable)
+{
+ if (!isWidget)
+ return S_OK;
+
+ EnableWindow(qt.widget->winId(), fEnable);
+ return S_OK;
+}
+
+//**** IOleObject
+
+static inline LPOLESTR QStringToOLESTR(const QString &qstring)
+{
+ LPOLESTR olestr = (wchar_t*)CoTaskMemAlloc(qstring.length()*2+2);
+ memcpy(olestr, (ushort*)qstring.unicode(), qstring.length()*2);
+ olestr[qstring.length()] = 0;
+ return olestr;
+}
+
+/*
+ \reimp
+
+ See documentation of IOleObject::GetUserType.
+*/
+HRESULT WINAPI QAxServerBase::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
+{
+ if (!pszUserType)
+ return E_POINTER;
+
+ switch (dwFormOfType) {
+ case USERCLASSTYPE_FULL:
+ *pszUserType = QStringToOLESTR(class_name);
+ break;
+ case USERCLASSTYPE_SHORT:
+ if (!qt.widget || !isWidget || qt.widget->windowTitle().isEmpty())
+ *pszUserType = QStringToOLESTR(class_name);
+ else
+ *pszUserType = QStringToOLESTR(qt.widget->windowTitle());
+ break;
+ case USERCLASSTYPE_APPNAME:
+ *pszUserType = QStringToOLESTR(qApp->objectName());
+ break;
+ }
+
+ return S_OK;
+}
+
+/*
+ Returns the status flags registered for this control.
+*/
+HRESULT WINAPI QAxServerBase::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
+{
+ return OleRegGetMiscStatus(qAxFactory()->classID(class_name), dwAspect, pdwStatus);
+}
+
+/*
+ Stores the provided advise sink.
+*/
+HRESULT WINAPI QAxServerBase::Advise(IAdviseSink* pAdvSink, DWORD* pdwConnection)
+{
+ *pdwConnection = adviseSinks.count() + 1;
+ STATDATA data = { {0, 0, DVASPECT_CONTENT, -1, TYMED_NULL} , 0, pAdvSink, *pdwConnection };
+ adviseSinks.append(data);
+ pAdvSink->AddRef();
+ return S_OK;
+}
+
+/*
+ Closes the control.
+*/
+HRESULT WINAPI QAxServerBase::Close(DWORD dwSaveOption)
+{
+ if (dwSaveOption != OLECLOSE_NOSAVE && m_spClientSite)
+ m_spClientSite->SaveObject();
+ if (isInPlaceActive) {
+ HRESULT hr = InPlaceDeactivate();
+ if (FAILED(hr))
+ return hr;
+ }
+ if (m_hWnd) {
+ if (IsWindow(m_hWnd))
+ DestroyWindow(m_hWnd);
+ m_hWnd = 0;
+ if (m_spClientSite)
+ m_spClientSite->OnShowWindow(false);
+ }
+
+ if (m_spInPlaceSite) m_spInPlaceSite->Release();
+ m_spInPlaceSite = 0;
+
+ if (m_spAdviseSink)
+ m_spAdviseSink->OnClose();
+ for (int i = 0; i < adviseSinks.count(); ++i) {
+ adviseSinks.at(i).pAdvSink->OnClose();
+ }
+
+ return S_OK;
+}
+
+bool qax_disable_inplaceframe = true;
+
+/*
+ Executes the steps to activate the control.
+*/
+HRESULT QAxServerBase::internalActivate()
+{
+ if (!m_spClientSite)
+ return S_OK;
+ if (!m_spInPlaceSite)
+ m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void**)&m_spInPlaceSite);
+ if (!m_spInPlaceSite)
+ return E_FAIL;
+
+ HRESULT hr = E_FAIL;
+ if (!isInPlaceActive) {
+ BOOL bNoRedraw = false;
+ hr = m_spInPlaceSite->CanInPlaceActivate();
+ if (FAILED(hr))
+ return hr;
+ if (hr != S_OK)
+ return E_FAIL;
+ m_spInPlaceSite->OnInPlaceActivate();
+ }
+
+ isInPlaceActive = true;
+ OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
+
+ if (isWidget) {
+ IOleInPlaceUIWindow *spInPlaceUIWindow = 0;
+ HWND hwndParent;
+ if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK) {
+ // get location in the parent window, as well as some information about the parent
+ if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
+ m_spInPlaceFrame = 0;
+ RECT rcPos, rcClip;
+ OLEINPLACEFRAMEINFO frameInfo;
+ frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
+ m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
+ if (m_hWnd) {
+ ::ShowWindow(m_hWnd, SW_SHOW);
+ if (!::IsChild(m_hWnd, ::GetFocus()) && qt.widget->focusPolicy() != Qt::NoFocus)
+ ::SetFocus(m_hWnd);
+ } else {
+ create(hwndParent, rcPos);
+ }
+ }
+
+ // Gone active by now, take care of UIACTIVATE
+ canTakeFocus = qt.widget->focusPolicy() != Qt::NoFocus && !inDesignMode;
+ if (!canTakeFocus && !inDesignMode) {
+ QList<QWidget*> widgets = qt.widget->findChildren<QWidget*>();
+ for (int w = 0; w < widgets.count(); ++w) {
+ QWidget *widget = widgets[w];
+ canTakeFocus = widget->focusPolicy() != Qt::NoFocus;
+ if (canTakeFocus)
+ break;
+ }
+ }
+ if (!isUIActive && canTakeFocus) {
+ isUIActive = true;
+ hr = m_spInPlaceSite->OnUIActivate();
+ if (FAILED(hr)) {
+ if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
+ m_spInPlaceFrame = 0;
+ if (spInPlaceUIWindow) spInPlaceUIWindow->Release();
+ return hr;
+ }
+
+ if (isInPlaceActive) {
+ if (!::IsChild(m_hWnd, ::GetFocus()))
+ ::SetFocus(m_hWnd);
+ }
+
+ if (m_spInPlaceFrame) {
+ hr = m_spInPlaceFrame->SetActiveObject(this, QStringToBSTR(class_name));
+ if (!FAILED(hr)) {
+ menuBar = (qt.widget && !qax_disable_inplaceframe) ? qt.widget->findChild<QMenuBar*>() : 0;
+ if (menuBar && !menuBar->isVisible()) {
+ createMenu(menuBar);
+ menuBar->hide();
+ menuBar->installEventFilter(this);
+ }
+ statusBar = qt.widget ? qt.widget->findChild<QStatusBar*>() : 0;
+ if (statusBar && !statusBar->isVisible()) {
+ const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)");
+ QMetaObject::connect(statusBar, index, this, -1);
+ statusBar->hide();
+ statusBar->installEventFilter(this);
+ }
+ }
+ }
+ if (spInPlaceUIWindow) {
+ spInPlaceUIWindow->SetActiveObject(this, QStringToBSTR(class_name));
+ spInPlaceUIWindow->SetBorderSpace(0);
+ }
+ }
+ if (spInPlaceUIWindow) spInPlaceUIWindow->Release();
+ ShowWindow(m_hWnd, SW_NORMAL);
+ }
+
+ m_spClientSite->ShowObject();
+
+ return S_OK;
+}
+
+/*
+ Executes the "verb" \a iVerb.
+*/
+HRESULT WINAPI QAxServerBase::DoVerb(LONG iVerb, LPMSG /*lpmsg*/, IOleClientSite* /*pActiveSite*/, LONG /*lindex*/,
+ HWND /*hwndParent*/, LPCRECT /*prcPosRect*/)
+{
+ HRESULT hr = E_NOTIMPL;
+ switch (iVerb)
+ {
+ case OLEIVERB_SHOW:
+ hr = internalActivate();
+ if (SUCCEEDED(hr))
+ hr = S_OK;
+ break;
+
+ case OLEIVERB_PRIMARY:
+ case OLEIVERB_INPLACEACTIVATE:
+ hr = internalActivate();
+ if (SUCCEEDED(hr)) {
+ hr = S_OK;
+ update();
+ }
+ break;
+
+ case OLEIVERB_UIACTIVATE:
+ if (!isUIActive) {
+ hr = internalActivate();
+ if (SUCCEEDED(hr))
+ hr = S_OK;
+ }
+ break;
+
+ case OLEIVERB_HIDE:
+ UIDeactivate();
+ if (m_hWnd)
+ ::ShowWindow(m_hWnd, SW_HIDE);
+ hr = S_OK;
+ return hr;
+
+ default:
+ break;
+ }
+ return hr;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::EnumAdvise(IEnumSTATDATA** /*ppenumAdvise*/)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Returns an enumerator for the verbs registered for this class.
+*/
+HRESULT WINAPI QAxServerBase::EnumVerbs(IEnumOLEVERB** ppEnumOleVerb)
+{
+ if (!ppEnumOleVerb)
+ return E_POINTER;
+ return OleRegEnumVerbs(qAxFactory()->classID(class_name), ppEnumOleVerb);
+}
+
+/*
+ Returns the current client site..
+*/
+HRESULT WINAPI QAxServerBase::GetClientSite(IOleClientSite** ppClientSite)
+{
+ if (!ppClientSite)
+ return E_POINTER;
+ *ppClientSite = m_spClientSite;
+ if (*ppClientSite)
+ (*ppClientSite)->AddRef();
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::GetClipboardData(DWORD, IDataObject**)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Returns the current extent.
+*/
+HRESULT WINAPI QAxServerBase::GetExtent(DWORD dwDrawAspect, SIZEL* psizel)
+{
+ if (dwDrawAspect != DVASPECT_CONTENT || !isWidget || !qt.widget)
+ return E_FAIL;
+ if (!psizel)
+ return E_POINTER;
+
+ psizel->cx = MAP_PIX_TO_LOGHIM(m_currentExtent.width(), qt.widget->logicalDpiX());
+ psizel->cy = MAP_PIX_TO_LOGHIM(m_currentExtent.height(), qt.widget->logicalDpiY());
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::GetMoniker(DWORD, DWORD, IMoniker** )
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Returns the CLSID of this class.
+*/
+HRESULT WINAPI QAxServerBase::GetUserClassID(CLSID* pClsid)
+{
+ if (!pClsid)
+ return E_POINTER;
+ *pClsid = qAxFactory()->classID(class_name);
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::InitFromData(IDataObject*, BOOL, DWORD)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::IsUpToDate()
+{
+ return S_OK;
+}
+
+/*
+ Stores the client site.
+*/
+HRESULT WINAPI QAxServerBase::SetClientSite(IOleClientSite* pClientSite)
+{
+ // release all client site interfaces
+ if (m_spClientSite) m_spClientSite->Release();
+ if (m_spInPlaceSite) m_spInPlaceSite->Release();
+ m_spInPlaceSite = 0;
+ if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
+ m_spInPlaceFrame = 0;
+
+ m_spClientSite = pClientSite;
+ if (m_spClientSite) {
+ m_spClientSite->AddRef();
+ m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
+ }
+
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::SetColorScheme(LOGPALETTE*)
+{
+ return E_NOTIMPL;
+}
+
+
+#ifdef QT_DLL // avoid conflict with symbol in static lib
+bool qt_sendSpontaneousEvent(QObject *o, QEvent *e)
+{
+ return QCoreApplication::sendSpontaneousEvent(o, e);
+}
+#endif
+
+/*
+ Tries to set the size of the control.
+*/
+HRESULT WINAPI QAxServerBase::SetExtent(DWORD dwDrawAspect, SIZEL* psizel)
+{
+ if (dwDrawAspect != DVASPECT_CONTENT)
+ return DV_E_DVASPECT;
+ if (!psizel)
+ return E_POINTER;
+
+ if (!isWidget || !qt.widget) // nothing to do
+ return S_OK;
+
+ QSize proposedSize(MAP_LOGHIM_TO_PIX(psizel->cx, qt.widget->logicalDpiX()),
+ MAP_LOGHIM_TO_PIX(psizel->cy, qt.widget->logicalDpiY()));
+
+ // can the widget be resized at all?
+ if (qt.widget->minimumSize() == qt.widget->maximumSize() && qt.widget->minimumSize() != proposedSize)
+ return E_FAIL;
+ //Save the extent, bound to the widget restrictions.
+ m_currentExtent.rwidth() = qBound(qt.widget->minimumWidth(), proposedSize.width(), qt.widget->maximumWidth());
+ m_currentExtent.rheight() = qBound(qt.widget->minimumHeight(), proposedSize.height(), qt.widget->maximumHeight());
+
+ resize(proposedSize);
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
+{
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::SetMoniker(DWORD, IMoniker*)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Disconnects an advise sink.
+*/
+HRESULT WINAPI QAxServerBase::Unadvise(DWORD dwConnection)
+{
+ for (int i = 0; i < adviseSinks.count(); ++i) {
+ STATDATA entry = adviseSinks.at(i);
+ if (entry.dwConnection == dwConnection) {
+ entry.pAdvSink->Release();
+ adviseSinks.removeAt(i);
+ return S_OK;
+ }
+ }
+ return OLE_E_NOCONNECTION;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::Update()
+{
+ return S_OK;
+}
+
+//**** IDataObject
+/*
+ Calls IViewObject::Draw after setting up the parameters.
+*/
+HRESULT WINAPI QAxServerBase::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
+{
+ if (!pmedium)
+ return E_POINTER;
+ if ((pformatetcIn->tymed & TYMED_MFPICT) == 0)
+ return DATA_E_FORMATETC;
+
+ internalCreate();
+ if (!isWidget || !qt.widget)
+ return E_UNEXPECTED;
+
+ // Container wants to draw, but the size is not defined yet - ask container
+ if (m_spInPlaceSite && !qt.widget->testAttribute(Qt::WA_Resized)) {
+ IOleInPlaceUIWindow *spInPlaceUIWindow = 0;
+ RECT rcPos, rcClip;
+ OLEINPLACEFRAMEINFO frameInfo;
+ frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
+
+ HRESULT hres = m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
+ if (hres == S_OK) {
+ QSize size(rcPos.right - rcPos.left, rcPos.bottom - rcPos.top);
+ resize(size);
+ } else {
+ qt.widget->adjustSize();
+ }
+ if (spInPlaceUIWindow) spInPlaceUIWindow->Release(); // no need for it
+ }
+
+ int width = qt.widget->width();
+ int height = qt.widget->height();
+ RECTL rectl = {0, 0, width, height};
+
+ HDC hdc = CreateMetaFile(0);
+ SaveDC(hdc);
+ SetWindowOrgEx(hdc, 0, 0, 0);
+ SetWindowExtEx(hdc, rectl.right, rectl.bottom, 0);
+
+ Draw(pformatetcIn->dwAspect, pformatetcIn->lindex, 0, pformatetcIn->ptd, 0, hdc, &rectl, &rectl, 0, 0);
+
+ RestoreDC(hdc, -1);
+ HMETAFILE hMF = CloseMetaFile(hdc);
+ if (!hMF)
+ return E_UNEXPECTED;
+
+ HGLOBAL hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
+ if (!hMem) {
+ DeleteMetaFile(hMF);
+ return ResultFromScode(STG_E_MEDIUMFULL);
+ }
+
+ LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMem);
+ pMF->hMF = hMF;
+ pMF->mm = MM_ANISOTROPIC;
+ pMF->xExt = MAP_PIX_TO_LOGHIM(width, qt.widget->logicalDpiX());
+ pMF->yExt = MAP_PIX_TO_LOGHIM(height, qt.widget->logicalDpiY());
+ GlobalUnlock(hMem);
+
+ memset(pmedium, 0, sizeof(STGMEDIUM));
+ pmedium->tymed = TYMED_MFPICT;
+ pmedium->hGlobal = hMem;
+ pmedium->pUnkForRelease = 0;
+
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::DAdvise(FORMATETC *pformatetc, DWORD advf,
+ IAdviseSink *pAdvSink, DWORD *pdwConnection)
+{
+ if (pformatetc->dwAspect != DVASPECT_CONTENT)
+ return E_FAIL;
+
+ *pdwConnection = adviseSinks.count() + 1;
+ STATDATA data = {
+ {pformatetc->cfFormat,pformatetc->ptd,pformatetc->dwAspect,pformatetc->lindex,pformatetc->tymed},
+ advf, pAdvSink, *pdwConnection
+ };
+ adviseSinks.append(data);
+ pAdvSink->AddRef();
+ return S_OK;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::DUnadvise(DWORD dwConnection)
+{
+ return Unadvise(dwConnection);
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::EnumDAdvise(IEnumSTATDATA ** /*ppenumAdvise*/)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::GetDataHere(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::QueryGetData(FORMATETC* /* pformatetc */)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::GetCanonicalFormatEtc(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::SetData(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */)
+{
+ return E_NOTIMPL;
+}
+
+/*
+ Not implemented.
+*/
+HRESULT WINAPI QAxServerBase::EnumFormatEtc(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */)
+{
+ return E_NOTIMPL;
+}
+
+
+
+static int mapModifiers(int state)
+{
+ int ole = 0;
+ if (state & Qt::ShiftModifier)
+ ole |= 1;
+ if (state & Qt::ControlModifier)
+ ole |= 2;
+ if (state & Qt::AltModifier)
+ ole |= 4;
+
+ return ole;
+}
+
+/*
+ \reimp
+*/
+bool QAxServerBase::eventFilter(QObject *o, QEvent *e)
+{
+ if (!theObject)
+ return QObject::eventFilter(o, e);
+
+ if ((e->type() == QEvent::Show || e->type() == QEvent::Hide) && (o == statusBar || o == menuBar)) {
+ if (o == menuBar) {
+ if (e->type() == QEvent::Hide) {
+ createMenu(menuBar);
+ } else if (e->type() == QEvent::Show) {
+ removeMenu();
+ }
+ } else if (statusBar) {
+ statusBar->setSizeGripEnabled(false);
+ }
+ updateGeometry();
+ if (m_spInPlaceSite && qt.widget->sizeHint().isValid()) {
+ RECT rect = {0, 0, qt.widget->sizeHint().width(), qt.widget->sizeHint().height()};
+ m_spInPlaceSite->OnPosRectChange(&rect);
+ }
+ }
+ switch (e->type()) {
+ case QEvent::ChildAdded:
+ static_cast<QChildEvent*>(e)->child()->installEventFilter(this);
+ break;
+ case QEvent::ChildRemoved:
+ static_cast<QChildEvent*>(e)->child()->removeEventFilter(this);
+ break;
+ case QEvent::KeyPress:
+ if (o == qt.object && hasStockEvents) {
+ QKeyEvent *ke = (QKeyEvent*)e;
+ int key = ke->key();
+ int state = ke->modifiers();
+ void *argv[] = {
+ 0,
+ &key,
+ &state
+ };
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYDOWN, argv);
+ if (!ke->text().isEmpty())
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYPRESS, argv);
+ }
+ break;
+ case QEvent::KeyRelease:
+ if (o == qt.object && hasStockEvents) {
+ QKeyEvent *ke = (QKeyEvent*)e;
+ int key = ke->key();
+ int state = ke->modifiers();
+ void *argv[] = {
+ 0,
+ &key,
+ &state
+ };
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYUP, argv);
+ }
+ break;
+ case QEvent::MouseMove:
+ if (o == qt.object && hasStockEvents) {
+ QMouseEvent *me = (QMouseEvent*)e;
+ int button = me->buttons() & Qt::MouseButtonMask;
+ int state = mapModifiers(me->modifiers());
+ int x = me->x();
+ int y = me->y();
+ void *argv[] = {
+ 0,
+ &button,
+ &state,
+ &x,
+ &y
+ };
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEMOVE, argv);
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if (o == qt.object && hasStockEvents) {
+ QMouseEvent *me = (QMouseEvent*)e;
+ int button = me->button();
+ int state = mapModifiers(me->modifiers());
+ int x = me->x();
+ int y = me->y();
+ void *argv[] = {
+ 0,
+ &button,
+ &state,
+ &x,
+ &y
+ };
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEUP, argv);
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_CLICK, 0);
+ }
+ break;
+ case QEvent::MouseButtonDblClick:
+ if (o == qt.object && hasStockEvents) {
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_DBLCLICK, 0);
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ if (m_spInPlaceSite && !isUIActive) {
+ internalActivate();
+ }
+ if (o == qt.widget && hasStockEvents) {
+ QMouseEvent *me = (QMouseEvent*)e;
+ int button = me->button();
+ int state = mapModifiers(me->modifiers());
+ int x = me->x();
+ int y = me->y();
+ void *argv[] = {
+ 0,
+ &button,
+ &state,
+ &x,
+ &y
+ };
+ qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEDOWN, argv);
+ }
+ break;
+ case QEvent::Show:
+ if (m_hWnd && o == qt.widget)
+ ShowWindow(m_hWnd, SW_SHOW);
+ updateMask();
+ break;
+ case QEvent::Hide:
+ if (m_hWnd && o == qt.widget)
+ ShowWindow(m_hWnd, SW_HIDE);
+ break;
+
+ case QEvent::EnabledChange:
+ if (m_hWnd && o == qt.widget)
+ EnableWindow(m_hWnd, qt.widget->isEnabled());
+ // Fall Through
+ case QEvent::FontChange:
+ case QEvent::ActivationChange:
+ case QEvent::StyleChange:
+ case QEvent::IconTextChange:
+ case QEvent::ModifiedChange:
+ case QEvent::Resize:
+ updateMask();
+ break;
+ case QEvent::WindowBlocked: {
+ if (!m_spInPlaceFrame)
+ break;
+ m_spInPlaceFrame->EnableModeless(FALSE);
+ MSG msg;
+ // Visual Basic 6.0 posts the message WM_USER+3078 from the EnableModeless().
+ // While handling this message, VB will disable all current top-levels. After
+ // this we have to re-enable the Qt modal widget to receive input events.
+ if (PeekMessage(&msg, 0, WM_USER+3078, WM_USER+3078, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ QWidget *modalWidget = QApplication::activeModalWidget();
+ if (modalWidget && modalWidget->isVisible() && modalWidget->isEnabled()
+ && !IsWindowEnabled(modalWidget->effectiveWinId()))
+ EnableWindow(modalWidget->effectiveWinId(), TRUE);
+ }
+ break;
+ }
+ case QEvent::WindowUnblocked:
+ if (!m_spInPlaceFrame)
+ break;
+ m_spInPlaceFrame->EnableModeless(TRUE);
+ break;
+ default:
+ break;
+ }
+ return QObject::eventFilter(o, e);
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/control/qaxserverdll.cpp b/src/activeqt/control/qaxserverdll.cpp
new file mode 100644
index 0000000..22c01d8
--- /dev/null
+++ b/src/activeqt/control/qaxserverdll.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QT_NO_WIN_ACTIVEQT
+
+#include <qapplication.h>
+#include <qwidget.h>
+
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+bool qax_ownQApp = false;
+HHOOK qax_hhook = 0;
+
+// in qaxserver.cpp
+extern wchar_t qAxModuleFilename[MAX_PATH];
+extern bool qAxIsServer;
+extern ITypeLib *qAxTypeLibrary;
+extern unsigned long qAxLockCount();
+extern QString qAxInit();
+extern void qAxCleanup();
+extern HANDLE qAxInstance;
+static uint qAxThreadId = 0;
+
+extern HRESULT UpdateRegistry(int bRegister);
+extern HRESULT GetClassObject(const GUID &clsid, const GUID &iid, void **ppUnk);
+
+STDAPI DllRegisterServer()
+{
+ return UpdateRegistry(true);
+}
+
+STDAPI DllUnregisterServer()
+{
+ return UpdateRegistry(false);
+}
+
+STDAPI DllGetClassObject(const GUID &clsid, const GUID &iid, void** ppv)
+{
+ if (!qAxThreadId)
+ qAxThreadId = GetCurrentThreadId();
+ else if (GetCurrentThreadId() != qAxThreadId)
+ return E_FAIL;
+
+ GetClassObject(clsid, iid, ppv);
+ if (!*ppv)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ return S_OK;
+}
+
+STDAPI DllCanUnloadNow()
+{
+ if (GetCurrentThreadId() != qAxThreadId)
+ return S_FALSE;
+ if (qAxLockCount())
+ return S_FALSE;
+ if (!qax_ownQApp)
+ return S_OK;
+
+ // check if qApp still runs widgets (in other DLLs)
+ QWidgetList widgets = qApp->allWidgets();
+ int count = widgets.count();
+ for (int w = 0; w < widgets.count(); ++w) {
+ // remove all Qt generated widgets
+ QWidget *widget = widgets.at(w);
+ if (widget->windowType() == Qt::Desktop || widget->objectName() == QLatin1String("Qt internal tablet widget"))
+ count--;
+ }
+ if (count)
+ return S_FALSE;
+
+ // no widgets left - destroy qApp
+ if (qax_hhook)
+ UnhookWindowsHookEx(qax_hhook);
+
+ delete qApp;
+ qax_ownQApp = false;
+
+ // never allow unloading - safety net for Internet Explorer
+ return S_FALSE;
+}
+
+
+EXTERN_C BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved)
+{
+ GetModuleFileName(hInstance, qAxModuleFilename, MAX_PATH);
+ qAxInstance = hInstance;
+ qAxIsServer = true;
+
+ if (dwReason == DLL_PROCESS_ATTACH) {
+ DisableThreadLibraryCalls(hInstance);
+ qAxInit();
+ } else if (dwReason == DLL_PROCESS_DETACH) {
+ qAxCleanup();
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/control/qaxservermain.cpp b/src/activeqt/control/qaxservermain.cpp
new file mode 100644
index 0000000..43ec8cd
--- /dev/null
+++ b/src/activeqt/control/qaxservermain.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include <qstringlist.h>
+#include <qvector.h>
+
+#include "qaxfactory.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+static DWORD *classRegistration = 0;
+static DWORD dwThreadID;
+static bool qAxActivity = false;
+static HANDLE hEventShutdown;
+
+#ifdef QT_DEBUG
+QT_STATIC_CONST DWORD dwTimeOut = 1000;
+QT_STATIC_CONST DWORD dwPause = 500;
+#else
+QT_STATIC_CONST DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting down
+QT_STATIC_CONST DWORD dwPause = 1000; // time to wait for threads to finish up
+#endif
+
+extern HANDLE hEventShutdown;
+extern bool qAxActivity;
+extern HANDLE qAxInstance;
+extern bool qAxIsServer;
+extern bool qAxOutProcServer;
+extern wchar_t qAxModuleFilename[MAX_PATH];
+extern QString qAxInit();
+extern void qAxCleanup();
+extern HRESULT UpdateRegistry(BOOL bRegister);
+extern HRESULT GetClassObject(const GUID &clsid, const GUID &iid, void **ppUnk);
+extern ulong qAxLockCount();
+extern bool qax_winEventFilter(void *message);
+
+#if defined(Q_CC_BOR)
+extern "C" __stdcall HRESULT DumpIDL(const QString &outfile, const QString &ver);
+#else
+STDAPI DumpIDL(const QString &outfile, const QString &ver);
+#endif
+
+// Monitors the shutdown event
+static DWORD WINAPI MonitorProc(void* pv)
+{
+ while (1) {
+ WaitForSingleObject(hEventShutdown, INFINITE);
+ DWORD dwWait=0;
+ do {
+ qAxActivity = false;
+ dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
+ } while (dwWait == WAIT_OBJECT_0);
+ // timed out
+ if (!qAxActivity && !qAxLockCount()) // if no activity let's really bail
+ break;
+ }
+ CloseHandle(hEventShutdown);
+ PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
+ PostQuitMessage(0);
+
+ return 0;
+}
+
+// Starts the monitoring thread
+static bool StartMonitor()
+{
+ dwThreadID = GetCurrentThreadId();
+ hEventShutdown = CreateEvent(0, false, false, 0);
+ if (hEventShutdown == 0)
+ return false;
+ DWORD dwThreadID;
+ HANDLE h = CreateThread(0, 0, MonitorProc, 0, 0, &dwThreadID);
+ return (h != NULL);
+}
+
+void qax_shutDown()
+{
+ qAxActivity = true;
+ if (hEventShutdown)
+ SetEvent(hEventShutdown); // tell monitor that we transitioned to zero
+}
+
+/*
+ Start the COM server (if necessary).
+*/
+bool qax_startServer(QAxFactory::ServerType type)
+{
+ if (qAxIsServer)
+ return true;
+
+ const QStringList keys = qAxFactory()->featureList();
+ if (!keys.count())
+ return false;
+
+ if (!qAxFactory()->isService())
+ StartMonitor();
+
+ classRegistration = new DWORD[keys.count()];
+ int object = 0;
+ for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object) {
+ IUnknown* p = 0;
+ CLSID clsid = qAxFactory()->classID(*key);
+
+ // Create a QClassFactory (implemented in qaxserverbase.cpp)
+ HRESULT hRes = GetClassObject(clsid, IID_IClassFactory, (void**)&p);
+ if (SUCCEEDED(hRes))
+ hRes = CoRegisterClassObject(clsid, p, CLSCTX_LOCAL_SERVER,
+ type == QAxFactory::MultipleInstances ? REGCLS_MULTIPLEUSE : REGCLS_SINGLEUSE,
+ classRegistration+object);
+ if (p)
+ p->Release();
+ }
+
+ qAxIsServer = true;
+ return true;
+}
+
+/*
+ Stop the COM server (if necessary).
+*/
+bool qax_stopServer()
+{
+ if (!qAxIsServer || !classRegistration)
+ return true;
+
+ qAxIsServer = false;
+
+ const QStringList keys = qAxFactory()->featureList();
+ int object = 0;
+ for (QStringList::ConstIterator key = keys.begin(); key != keys.end(); ++key, ++object)
+ CoRevokeClassObject(classRegistration[object]);
+
+ delete []classRegistration;
+ classRegistration = 0;
+
+ Sleep(dwPause); //wait for any threads to finish
+
+ return true;
+}
+
+#if defined(Q_OS_WINCE)
+extern void __cdecl qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &);
+#else
+extern void qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &);
+#endif
+
+QT_END_NAMESPACE
+
+#if defined(QT_NEEDS_QMAIN)
+int qMain(int, char **);
+#define main qMain
+#else
+#if defined(Q_OS_WINCE)
+extern "C" int __cdecl main(int, char **);
+#else
+extern "C" int main(int, char **);
+#endif
+#endif
+
+
+EXTERN_C int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, int nShowCmd)
+{
+ QT_USE_NAMESPACE
+
+ qAxOutProcServer = true;
+ GetModuleFileName(0, qAxModuleFilename, MAX_PATH);
+ qAxInstance = hInstance;
+
+ QByteArray cmdParam = QString::fromWCharArray(GetCommandLine()).toLocal8Bit();
+ QList<QByteArray> cmds = cmdParam.split(' ');
+ QByteArray unprocessed;
+
+ int nRet = 0;
+ bool run = true;
+ bool runServer = false;
+ for (int i = 0; i < cmds.count(); ++i) {
+ QByteArray cmd = cmds.at(i).toLower();
+ if (cmd == "-activex" || cmd == "/activex" || cmd == "-embedding" || cmd == "/embedding") {
+ runServer = true;
+ } else if (cmd == "-unregserver" || cmd == "/unregserver") {
+ nRet = UpdateRegistry(false);
+ run = false;
+ break;
+ } else if (cmd == "-regserver" || cmd == "/regserver") {
+ nRet = UpdateRegistry(true);
+ run = false;
+ break;
+ } else if (cmd == "-dumpidl" || cmd == "/dumpidl") {
+ ++i;
+ if (i < cmds.count()) {
+ QByteArray outfile = cmds.at(i);
+ ++i;
+ QByteArray version;
+ if (i < cmds.count() && (cmds.at(i) == "-version" || cmds.at(i) == "/version")) {
+ ++i;
+ if (i < cmds.count())
+ version = cmds.at(i);
+ else
+ version = "1.0";
+ }
+
+ nRet = DumpIDL(QString::fromLatin1(outfile.constData()), QString::fromLatin1(version.constData()));
+ } else {
+ qWarning("Wrong commandline syntax: <app> -dumpidl <idl file> [-version <x.y.z>]");
+ }
+ run = false;
+ break;
+ } else {
+ unprocessed += cmds.at(i) + ' ';
+ }
+ }
+
+ if (run) {
+ HRESULT hRes = CoInitialize(0);
+
+ int argc;
+ QVector<char*> argv(8);
+ qWinMain(hInstance, hPrevInstance, unprocessed.data(), nShowCmd, argc, argv);
+ qAxInit();
+ if (runServer)
+ QAxFactory::startServer();
+ nRet = ::main(argc, argv.data());
+ QAxFactory::stopServer();
+ qAxCleanup();
+ CoUninitialize();
+
+ }
+
+ return nRet;
+}
+
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp
new file mode 100644
index 0000000..c48b55b
--- /dev/null
+++ b/src/activeqt/shared/qaxtypes.cpp
@@ -0,0 +1,1484 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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$
+**
+****************************************************************************/
+
+#include <ocidl.h>
+#include <olectl.h>
+
+#include "qaxtypes.h"
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+#include <qcolormap.h>
+#include <qcursor.h>
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qobject.h>
+#ifdef QAX_SERVER
+# include <qaxfactory.h>
+# include <private/qsystemlibrary_p.h>
+#else
+# include <quuid.h>
+# include <qaxobject.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QAX_SERVER
+extern ITypeLib *qAxTypeLibrary;
+
+CLSID CLSID_QRect = { 0x34030f30, 0xe359, 0x4fe6, {0xab, 0x82, 0x39, 0x76, 0x6f, 0x5d, 0x91, 0xee } };
+CLSID CLSID_QSize = { 0xcb5f84b3, 0x29e5, 0x491d, {0xba, 0x18, 0x54, 0x72, 0x48, 0x8e, 0xef, 0xba } };
+CLSID CLSID_QPoint = { 0x3be838a3, 0x3fac, 0xbfc4, {0x4c, 0x6c, 0x37, 0xc4, 0x4d, 0x03, 0x02, 0x52 } };
+
+GUID IID_IAxServerBase = { 0xbd2ec165, 0xdfc9, 0x4319, { 0x8b, 0x9b, 0x60, 0xa5, 0x74, 0x78, 0xe9, 0xe3} };
+#else
+extern void *qax_createObjectWrapper(int metaType, IUnknown *iface);
+#endif
+
+static IFontDisp *QFontToIFont(const QFont &font)
+{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(font);
+ return 0;
+#else
+ FONTDESC fdesc;
+ memset(&fdesc, 0, sizeof(fdesc));
+ fdesc.cbSizeofstruct = sizeof(FONTDESC);
+ fdesc.cySize.Lo = font.pointSize() * 10000;
+ fdesc.fItalic = font.italic();
+ fdesc.fStrikethrough = font.strikeOut();
+ fdesc.fUnderline = font.underline();
+ fdesc.lpstrName = QStringToBSTR(font.family());
+ fdesc.sWeight = font.weight() * 10;
+
+ IFontDisp *f;
+ HRESULT res = OleCreateFontIndirect(&fdesc, IID_IFontDisp, (void**)&f);
+ if (res != S_OK) {
+ if (f) f->Release();
+ f = 0;
+#if defined(QT_CHECK_STATE)
+ qWarning("QFontToIFont: Failed to create IFont");
+#endif
+ }
+ return f;
+#endif
+}
+
+static QFont IFontToQFont(IFont *f)
+{
+ BSTR name;
+ BOOL bold;
+ SHORT charset;
+ BOOL italic;
+ CY size;
+ BOOL strike;
+ BOOL underline;
+ SHORT weight;
+ f->get_Name(&name);
+ f->get_Bold(&bold);
+ f->get_Charset(&charset);
+ f->get_Italic(&italic);
+ f->get_Size(&size);
+ f->get_Strikethrough(&strike);
+ f->get_Underline(&underline);
+ f->get_Weight(&weight);
+ QFont font(QString::fromWCharArray(name), size.Lo/9750, weight / 97, italic);
+ font.setBold(bold);
+ font.setStrikeOut(strike);
+ font.setUnderline(underline);
+ SysFreeString(name);
+
+ return font;
+}
+
+static IPictureDisp *QPixmapToIPicture(const QPixmap &pixmap)
+{
+#if defined(Q_OS_WINCE)
+ Q_UNUSED(pixmap);
+ return 0;
+#else
+ IPictureDisp *pic = 0;
+
+ PICTDESC desc;
+ desc.cbSizeofstruct = sizeof(PICTDESC);
+ desc.picType = PICTYPE_BITMAP;
+
+ desc.bmp.hbitmap = 0;
+ desc.bmp.hpal = QColormap::hPal();
+
+ if (!pixmap.isNull()) {
+ desc.bmp.hbitmap = pixmap.toWinHBITMAP();
+ Q_ASSERT(desc.bmp.hbitmap);
+ }
+
+ HRESULT res = OleCreatePictureIndirect(&desc, IID_IPictureDisp, true, (void**)&pic);
+ if (res != S_OK) {
+ if (pic) pic->Release();
+ pic = 0;
+#if defined(QT_CHECK_STATE)
+ qWarning("QPixmapToIPicture: Failed to create IPicture");
+#endif
+ }
+ return pic;
+#endif
+}
+
+static QPixmap IPictureToQPixmap(IPicture *ipic)
+{
+ SHORT type;
+ ipic->get_Type(&type);
+ if (type != PICTYPE_BITMAP)
+ return QPixmap();
+
+ HBITMAP hbm = 0;
+ ipic->get_Handle((OLE_HANDLE*)&hbm);
+ if (!hbm)
+ return QPixmap();
+
+ return QPixmap::fromWinHBITMAP(hbm);
+}
+
+static QDateTime DATEToQDateTime(DATE ole)
+{
+ SYSTEMTIME stime;
+ if (ole >= 949998 || VariantTimeToSystemTime(ole, &stime) == false)
+ return QDateTime();
+
+ QDate date(stime.wYear, stime.wMonth, stime.wDay);
+ QTime time(stime.wHour, stime.wMinute, stime.wSecond, stime.wMilliseconds);
+ return QDateTime(date, time);
+}
+
+static DATE QDateTimeToDATE(const QDateTime &dt)
+{
+ if (!dt.isValid() || dt.isNull())
+ return 949998;
+
+ SYSTEMTIME stime;
+ memset(&stime, 0, sizeof(stime));
+ QDate date = dt.date();
+ QTime time = dt.time();
+ if (date.isValid() && !date.isNull()) {
+ stime.wDay = date.day();
+ stime.wMonth = date.month();
+ stime.wYear = date.year();
+ }
+ if (time.isValid() && !time.isNull()) {
+ stime.wMilliseconds = time.msec();
+ stime.wSecond = time.second();
+ stime.wMinute = time.minute();
+ stime.wHour = time.hour();
+ }
+
+ double vtime;
+ SystemTimeToVariantTime(&stime, &vtime);
+
+ return vtime;
+}
+
+QColor OLEColorToQColor(uint col)
+{
+#if defined(Q_OS_WINCE)
+ return QColor(GetBValue(col),GetGValue(col),GetRValue(col));
+#else
+ COLORREF cref;
+ OleTranslateColor(col, QColormap::hPal(), &cref);
+ return QColor(GetRValue(cref),GetGValue(cref),GetBValue(cref));
+#endif
+}
+
+/*
+ Converts \a var to \a arg, and tries to coerce \a arg to \a type.
+
+ Used by
+
+ QAxServerBase:
+ - QAxServerBase::qt_metacall
+ - IDispatch::Invoke(PROPERTYGET, METHOD)
+ - IPersistPropertyBag::Save
+
+ QAxBase:
+ - IDispatch::Invoke (QAxEventSink)
+ - QAxBase::internalProperty(WriteProperty)
+ - QAxBase::internalInvoke()
+ - QAxBase::dynamicCallHelper()
+ - IPropertyBag::Read (QtPropertyBag)
+
+ Also called recoursively for lists.
+*/
+bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out)
+{
+ QVariant qvar = var;
+ // "type" is the expected type, so coerce if necessary
+ QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName);
+ if (proptype == QVariant::UserType && !typeName.isEmpty()) {
+ if (typeName == "short" || typeName == "char")
+ proptype = QVariant::Int;
+ else if (typeName == "float")
+ proptype = QVariant::Double;
+ }
+ if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != qvar.type()) {
+ if (qvar.canConvert(proptype))
+ qvar.convert(proptype);
+ else
+ qvar = QVariant(proptype);
+ }
+
+ if (out && arg.vt == (VT_VARIANT|VT_BYREF) && arg.pvarVal) {
+ return QVariantToVARIANT(var, *arg.pvarVal, typeName, false);
+ }
+
+ if (out && proptype == QVariant::Invalid && typeName == "QVariant") {
+ VARIANT *pVariant = new VARIANT;
+ QVariantToVARIANT(var, *pVariant, QByteArray(), false);
+ arg.vt = VT_VARIANT|VT_BYREF;
+ arg.pvarVal = pVariant;
+ return true;
+ }
+
+ switch ((int)qvar.type()) {
+ case QVariant::String:
+ if (out && arg.vt == (VT_BSTR|VT_BYREF)) {
+ if (*arg.pbstrVal)
+ SysFreeString(*arg.pbstrVal);
+ *arg.pbstrVal = QStringToBSTR(qvar.toString());
+ arg.vt = VT_BSTR|VT_BYREF;
+ } else {
+ arg.vt = VT_BSTR;
+ arg.bstrVal = QStringToBSTR(qvar.toString());
+ if (out) {
+ arg.pbstrVal = new BSTR(arg.bstrVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::Int:
+ if (out && arg.vt == (VT_I4|VT_BYREF)) {
+ *arg.plVal = qvar.toInt();
+ } else {
+ arg.vt = VT_I4;
+ arg.lVal = qvar.toInt();
+ if (out) {
+ if (typeName == "short") {
+ arg.vt = VT_I2;
+ arg.piVal = new short(arg.lVal);
+ } else if (typeName == "char") {
+ arg.vt = VT_I1;
+ arg.pcVal= new char(arg.lVal);
+ } else {
+ arg.plVal = new long(arg.lVal);
+ }
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::UInt:
+ if (out && (arg.vt == (VT_UINT|VT_BYREF) || arg.vt == (VT_I4|VT_BYREF))) {
+ *arg.puintVal = qvar.toUInt();
+ } else {
+ arg.vt = VT_UINT;
+ arg.uintVal = qvar.toUInt();
+ if (out) {
+ arg.puintVal = new uint(arg.uintVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::LongLong:
+ if (out && arg.vt == (VT_CY|VT_BYREF)) {
+ arg.pcyVal->int64 = qvar.toLongLong();
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ } else if (out && arg.vt == (VT_I8|VT_BYREF)) {
+ *arg.pllVal = qvar.toLongLong();
+ } else {
+ arg.vt = VT_I8;
+ arg.llVal = qvar.toLongLong();
+ if (out) {
+ arg.pllVal = new LONGLONG(arg.llVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#else
+ } else {
+ arg.vt = VT_CY;
+ arg.cyVal.int64 = qvar.toLongLong();
+ if (out) {
+ arg.pcyVal = new CY(arg.cyVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#endif
+ break;
+
+ case QVariant::ULongLong:
+ if (out && arg.vt == (VT_CY|VT_BYREF)) {
+ arg.pcyVal->int64 = qvar.toULongLong();
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ } else if (out && arg.vt == (VT_UI8|VT_BYREF)) {
+ *arg.pullVal = qvar.toULongLong();
+ } else {
+ arg.vt = VT_UI8;
+ arg.ullVal = qvar.toULongLong();
+ if (out) {
+ arg.pullVal = new ULONGLONG(arg.ullVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#else
+ } else {
+ arg.vt = VT_CY;
+ arg.cyVal.int64 = qvar.toULongLong();
+ if (out) {
+ arg.pcyVal = new CY(arg.cyVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+
+#endif
+
+ break;
+
+ case QVariant::Bool:
+ if (out && arg.vt == (VT_BOOL|VT_BYREF)) {
+ *arg.pboolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE;
+ } else {
+ arg.vt = VT_BOOL;
+ arg.boolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE;
+ if (out) {
+ arg.pboolVal = new short(arg.boolVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+ case QVariant::Double:
+ if (out && arg.vt == (VT_R8|VT_BYREF)) {
+ *arg.pdblVal = qvar.toDouble();
+ } else {
+ arg.vt = VT_R8;
+ arg.dblVal = qvar.toDouble();
+ if (out) {
+ if (typeName == "float") {
+ arg.vt = VT_R4;
+ arg.pfltVal = new float(arg.dblVal);
+ } else {
+ arg.pdblVal = new double(arg.dblVal);
+ }
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+ case QVariant::Color:
+ if (out && arg.vt == (VT_COLOR|VT_BYREF)) {
+
+ *arg.plVal = QColorToOLEColor(qvariant_cast<QColor>(qvar));
+ } else {
+ arg.vt = VT_COLOR;
+ arg.lVal = QColorToOLEColor(qvariant_cast<QColor>(qvar));
+ if (out) {
+ arg.plVal = new long(arg.lVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::Date:
+ case QVariant::Time:
+ case QVariant::DateTime:
+ if (out && arg.vt == (VT_DATE|VT_BYREF)) {
+ *arg.pdate = QDateTimeToDATE(qvar.toDateTime());
+ } else {
+ arg.vt = VT_DATE;
+ arg.date = QDateTimeToDATE(qvar.toDateTime());
+ if (out) {
+ arg.pdate = new DATE(arg.date);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+ case QVariant::Font:
+ if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) {
+ if (*arg.ppdispVal)
+ (*arg.ppdispVal)->Release();
+ *arg.ppdispVal = QFontToIFont(qvariant_cast<QFont>(qvar));
+ } else {
+ arg.vt = VT_DISPATCH;
+ arg.pdispVal = QFontToIFont(qvariant_cast<QFont>(qvar));
+ if (out) {
+ arg.ppdispVal = new IDispatch*(arg.pdispVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::Pixmap:
+ if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) {
+ if (*arg.ppdispVal)
+ (*arg.ppdispVal)->Release();
+ *arg.ppdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar));
+ } else {
+ arg.vt = VT_DISPATCH;
+ arg.pdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar));
+ if (out) {
+ arg.ppdispVal = new IDispatch*(arg.pdispVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::Cursor:
+ {
+#ifndef QT_NO_CURSOR
+ int shape = qvariant_cast<QCursor>(qvar).shape();
+ if (out && (arg.vt & VT_BYREF)) {
+ switch(arg.vt & ~VT_BYREF) {
+ case VT_I4:
+ *arg.plVal = shape;
+ break;
+ case VT_I2:
+ *arg.piVal = shape;
+ break;
+ case VT_UI4:
+ *arg.pulVal = shape;
+ break;
+ case VT_UI2:
+ *arg.puiVal = shape;
+ break;
+ case VT_INT:
+ *arg.pintVal = shape;
+ break;
+ case VT_UINT:
+ *arg.puintVal = shape;
+ break;
+ }
+ } else {
+ arg.vt = VT_I4;
+ arg.lVal = shape;
+ if (out) {
+ arg.plVal = new long(arg.lVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#endif
+ }
+ break;
+
+ case QVariant::List:
+ {
+ const QList<QVariant> list = qvar.toList();
+ const int count = list.count();
+ VARTYPE vt = VT_VARIANT;
+ QVariant::Type listType = QVariant::LastType; // == QVariant
+ if (!typeName.isEmpty() && typeName.startsWith("QList<")) {
+ const QByteArray listTypeName = typeName.mid(6, typeName.length() - 7); // QList<int> -> int
+ listType = QVariant::nameToType(listTypeName);
+ }
+
+ VARIANT variant;
+ void *pElement = &variant;
+ switch(listType) {
+ case QVariant::Int:
+ vt = VT_I4;
+ pElement = &variant.lVal;
+ break;
+ case QVariant::Double:
+ vt = VT_R8;
+ pElement = &variant.dblVal;
+ break;
+ case QVariant::DateTime:
+ vt = VT_DATE;
+ pElement = &variant.date;
+ break;
+ case QVariant::Bool:
+ vt = VT_BOOL;
+ pElement = &variant.boolVal;
+ break;
+ case QVariant::LongLong:
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ vt = VT_I8;
+ pElement = &variant.llVal;
+#else
+ vt = VT_CY;
+ pElement = &variant.cyVal;
+#endif
+ break;
+ default:
+ break;
+ }
+ SAFEARRAY *array = 0;
+ bool is2D = false;
+ // If the first element in the array is a list the whole list is
+ // treated as a 2D array. The column count is taken from the 1st element.
+ if (count) {
+ QVariantList col = list.at(0).toList();
+ int maxColumns = col.count();
+ if (maxColumns) {
+ is2D = true;
+ SAFEARRAYBOUND rgsabound[2] = { {0} };
+ rgsabound[0].cElements = count;
+ rgsabound[1].cElements = maxColumns;
+ array = SafeArrayCreate(VT_VARIANT, 2, rgsabound);
+ LONG rgIndices[2];
+ for (LONG i = 0; i < count; ++i) {
+ rgIndices[0] = i;
+ QVariantList columns = list.at(i).toList();
+ int columnCount = qMin(maxColumns, columns.count());
+ for (LONG j = 0; j < columnCount; ++j) {
+ QVariant elem = columns.at(j);
+ VariantInit(&variant);
+ QVariantToVARIANT(elem, variant, elem.typeName());
+ rgIndices[1] = j;
+ SafeArrayPutElement(array, rgIndices, pElement);
+ clearVARIANT(&variant);
+ }
+ }
+
+ }
+ }
+ if (!is2D) {
+ array = SafeArrayCreateVector(vt, 0, count);
+ for (LONG index = 0; index < count; ++index) {
+ QVariant elem = list.at(index);
+ if (listType != QVariant::LastType)
+ elem.convert(listType);
+ VariantInit(&variant);
+ QVariantToVARIANT(elem, variant, elem.typeName());
+ SafeArrayPutElement(array, &index, pElement);
+ clearVARIANT(&variant);
+ }
+ }
+ if (out && arg.vt == (VT_ARRAY|vt|VT_BYREF)) {
+ if (*arg.pparray)
+ SafeArrayDestroy(*arg.pparray);
+ *arg.pparray = array;
+ } else {
+ arg.vt = VT_ARRAY|vt;
+ arg.parray = array;
+ if (out) {
+ arg.pparray = new SAFEARRAY*(arg.parray);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ }
+ break;
+
+ case QVariant::StringList:
+ {
+ const QStringList list = qvar.toStringList();
+ const int count = list.count();
+ SAFEARRAY *array = SafeArrayCreateVector(VT_BSTR, 0, count);
+ for (LONG index = 0; index < count; ++index) {
+ QString elem = list.at(index);
+ BSTR bstr = QStringToBSTR(elem);
+ SafeArrayPutElement(array, &index, bstr);
+ SysFreeString(bstr);
+ }
+
+ if (out && arg.vt == (VT_ARRAY|VT_BSTR|VT_BYREF)) {
+ if (*arg.pparray)
+ SafeArrayDestroy(*arg.pparray);
+ *arg.pparray = array;
+ } else {
+ arg.vt = VT_ARRAY|VT_BSTR;
+ arg.parray = array;
+ if (out) {
+ arg.pparray = new SAFEARRAY*(arg.parray);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ }
+ break;
+
+ case QVariant::ByteArray:
+ {
+ const QByteArray bytes = qvar.toByteArray();
+ const uint count = bytes.count();
+ SAFEARRAY *array = SafeArrayCreateVector(VT_UI1, 0, count);
+ if (count) {
+ const char *data = bytes.constData();
+ char *dest;
+ SafeArrayAccessData(array, (void **)&dest);
+ memcpy(dest, data, count);
+ SafeArrayUnaccessData(array);
+ }
+
+ if (out && arg.vt == (VT_ARRAY|VT_UI1|VT_BYREF)) {
+ if (*arg.pparray)
+ SafeArrayDestroy(*arg.pparray);
+ *arg.pparray = array;
+ } else {
+ arg.vt = VT_ARRAY|VT_UI1;
+ arg.parray = array;
+ if (out) {
+ arg.pparray = new SAFEARRAY*(arg.parray);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ }
+ break;
+
+#ifdef QAX_SERVER
+ case QVariant::Rect:
+ case QVariant::Size:
+ case QVariant::Point:
+ {
+ typedef HRESULT(WINAPI* PGetRecordInfoFromTypeInfo)(ITypeInfo *, IRecordInfo **);
+ static PGetRecordInfoFromTypeInfo pGetRecordInfoFromTypeInfo = 0;
+ static bool resolved = false;
+ if (!resolved) {
+ resolved = true;
+ pGetRecordInfoFromTypeInfo = (PGetRecordInfoFromTypeInfo)QSystemLibrary::resolve(QLatin1String("oleaut32"),
+ "GetRecordInfoFromTypeInfo");
+ }
+ if (!pGetRecordInfoFromTypeInfo)
+ break;
+
+ ITypeInfo *typeInfo = 0;
+ IRecordInfo *recordInfo = 0;
+ CLSID clsid = qvar.type() == QVariant::Rect ? CLSID_QRect
+ :qvar.type() == QVariant::Size ? CLSID_QSize
+ :CLSID_QPoint;
+ qAxTypeLibrary->GetTypeInfoOfGuid(clsid, &typeInfo);
+ if (!typeInfo)
+ break;
+ pGetRecordInfoFromTypeInfo(typeInfo, &recordInfo);
+ typeInfo->Release();
+ if (!recordInfo)
+ break;
+
+ void *record = 0;
+ switch (qvar.type()) {
+ case QVariant::Rect:
+ {
+ QRect qrect(qvar.toRect());
+ recordInfo->RecordCreateCopy(&qrect, &record);
+ }
+ break;
+ case QVariant::Size:
+ {
+ QSize qsize(qvar.toSize());
+ recordInfo->RecordCreateCopy(&qsize, &record);
+ }
+ break;
+ case QVariant::Point:
+ {
+ QPoint qpoint(qvar.toPoint());
+ recordInfo->RecordCreateCopy(&qpoint, &record);
+ }
+ break;
+ }
+
+ arg.vt = VT_RECORD;
+ arg.pRecInfo = recordInfo,
+ arg.pvRecord = record;
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for records");
+ return false;
+ }
+ }
+ break;
+#endif // QAX_SERVER
+ case QVariant::UserType:
+ {
+ QByteArray subType = qvar.typeName();
+#ifdef QAX_SERVER
+ if (subType.endsWith('*'))
+ subType.truncate(subType.length() - 1);
+#endif
+ if (!qstrcmp(qvar.typeName(), "IDispatch*")) {
+ arg.vt = VT_DISPATCH;
+ arg.pdispVal = *(IDispatch**)qvar.data();
+ if (arg.pdispVal)
+ arg.pdispVal->AddRef();
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for IDispatch");
+ return false;
+ }
+ } else if (!qstrcmp(qvar.typeName(), "IDispatch**")) {
+ arg.vt = VT_DISPATCH;
+ arg.ppdispVal = *(IDispatch***)qvar.data();
+ if (out)
+ arg.vt |= VT_BYREF;
+ } else if (!qstrcmp(qvar.typeName(), "IUnknown*")) {
+ arg.vt = VT_UNKNOWN;
+ arg.punkVal = *(IUnknown**)qvar.data();
+ if (arg.punkVal)
+ arg.punkVal->AddRef();
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for IUnknown");
+ return false;
+ }
+#ifdef QAX_SERVER
+ } else if (qAxFactory()->metaObject(QString::fromLatin1(subType.constData()))) {
+ arg.vt = VT_DISPATCH;
+ void *user = *(void**)qvar.constData();
+// qVariantGet(qvar, user, qvar.typeName());
+ if (!user) {
+ arg.pdispVal = 0;
+ } else {
+ qAxFactory()->createObjectWrapper(static_cast<QObject*>(user), &arg.pdispVal);
+ }
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for subtype");
+ return false;
+ }
+#else
+ } else if (QMetaType::type(subType)) {
+ QAxObject *object = *(QAxObject**)qvar.constData();
+// qVariantGet(qvar, object, subType);
+ arg.vt = VT_DISPATCH;
+ object->queryInterface(IID_IDispatch, (void**)&arg.pdispVal);
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for subtype");
+ return false;
+ }
+#endif
+ } else {
+ return false;
+ }
+ }
+ break;
+ case QVariant::Invalid: // default-parameters not set
+ if (out && arg.vt == (VT_ERROR|VT_BYREF)) {
+ *arg.plVal = DISP_E_PARAMNOTFOUND;
+ } else {
+ arg.vt = VT_ERROR;
+ arg.lVal = DISP_E_PARAMNOTFOUND;
+ if (out) {
+ arg.plVal = new long(arg.lVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ Q_ASSERT(!out || (arg.vt & VT_BYREF));
+ return true;
+}
+
+/*!
+ Copies the data in \a var into \a data.
+
+ Used by
+
+ QAxServerBase:
+ - QAxServerBase::qt_metacall (update out parameters/return value)
+
+ QAxBase:
+ - internalProperty(ReadProperty)
+ - internalInvoke(update out parameters/return value)
+
+*/
+bool QVariantToVoidStar(const QVariant &var, void *data, const QByteArray &typeName, uint type)
+{
+ if (!data)
+ return true;
+
+ if (type == QVariant::LastType || (type == 0 && typeName == "QVariant")) {
+ *(QVariant*)data = var;
+ return true;
+ }
+
+ switch (var.type()) {
+ case QVariant::Invalid:
+ break;
+ case QVariant::String:
+ *(QString*)data = var.toString();
+ break;
+ case QVariant::Int:
+ *(int*)data = var.toInt();
+ break;
+ case QVariant::UInt:
+ *(uint*)data = var.toUInt();
+ break;
+ case QVariant::Bool:
+ *(bool*)data = var.toBool();
+ break;
+ case QVariant::Double:
+ *(double*)data = var.toDouble();
+ break;
+ case QVariant::Color:
+ *(QColor*)data = qvariant_cast<QColor>(var);
+ break;
+ case QVariant::Date:
+ *(QDate*)data = var.toDate();
+ break;
+ case QVariant::Time:
+ *(QTime*)data = var.toTime();
+ break;
+ case QVariant::DateTime:
+ *(QDateTime*)data = var.toDateTime();
+ break;
+ case QVariant::Font:
+ *(QFont*)data = qvariant_cast<QFont>(var);
+ break;
+ case QVariant::Pixmap:
+ *(QPixmap*)data = qvariant_cast<QPixmap>(var);
+ break;
+#ifndef QT_NO_CURSOR
+ case QVariant::Cursor:
+ *(QCursor*)data = qvariant_cast<QCursor>(var);
+ break;
+#endif
+ case QVariant::List:
+ *(QList<QVariant>*)data = var.toList();
+ break;
+ case QVariant::StringList:
+ *(QStringList*)data = var.toStringList();
+ break;
+ case QVariant::ByteArray:
+ *(QByteArray*)data = var.toByteArray();
+ break;
+ case QVariant::LongLong:
+ *(qint64*)data = var.toLongLong();
+ break;
+ case QVariant::ULongLong:
+ *(quint64*)data = var.toULongLong();
+ break;
+ case QVariant::Rect:
+ *(QRect*)data = var.toRect();
+ break;
+ case QVariant::Size:
+ *(QSize*)data = var.toSize();
+ break;
+ case QVariant::Point:
+ *(QPoint*)data = var.toPoint();
+ break;
+ case QVariant::UserType:
+ *(void**)data = *(void**)var.constData();
+// qVariantGet(var, *(void**)data, typeName);
+ break;
+ default:
+ qWarning("QVariantToVoidStar: Unhandled QVariant type");
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ Returns \a arg as a QVariant of type \a type.
+
+ Used by
+
+ QAxServerBase:
+ - QAxServerBase::qt_metacall(update out parameters/return value)
+ - IDispatch::Invoke(METHOD, PROPERTYPUT)
+ - IPersistPropertyBag::Load
+
+ QAxBase:
+ - IDispatch::Invoke (QAxEventSink)
+ - QAxBase::internalProperty(ReadProperty)
+ - QAxBase::internalInvoke(update out parameters/return value)
+ - QAxBase::dynamicCallHelper(update out parameters)
+ - QAxBase::dynamicCall(return value)
+ - IPropertyBag::Write (QtPropertyBag)
+*/
+QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint type)
+{
+ QVariant var;
+ switch(arg.vt) {
+ case VT_BSTR:
+ var = QString::fromWCharArray(arg.bstrVal);
+ break;
+ case VT_BSTR|VT_BYREF:
+ var = QString::fromWCharArray(*arg.pbstrVal);
+ break;
+ case VT_BOOL:
+ var = QVariant((bool)arg.boolVal);
+ break;
+ case VT_BOOL|VT_BYREF:
+ var = QVariant((bool)*arg.pboolVal);
+ break;
+ case VT_I1:
+ var = arg.cVal;
+ if (typeName == "char")
+ type = QVariant::Int;
+ break;
+ case VT_I1|VT_BYREF:
+ var = *arg.pcVal;
+ if (typeName == "char")
+ type = QVariant::Int;
+ break;
+ case VT_I2:
+ var = arg.iVal;
+ if (typeName == "short")
+ type = QVariant::Int;
+ break;
+ case VT_I2|VT_BYREF:
+ var = *arg.piVal;
+ if (typeName == "short")
+ type = QVariant::Int;
+ break;
+ case VT_I4:
+ if (type == QVariant::Color || (!type && typeName == "QColor"))
+ var = QVariant::fromValue(OLEColorToQColor(arg.lVal));
+#ifndef QT_NO_CURSOR
+ else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*")))
+ var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal)));
+#endif
+ else
+ var = (int)arg.lVal;
+ break;
+ case VT_I4|VT_BYREF:
+ if (type == QVariant::Color || (!type && typeName == "QColor"))
+ var = QVariant::fromValue(OLEColorToQColor((int)*arg.plVal));
+#ifndef QT_NO_CURSOR
+ else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*")))
+ var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal)));
+#endif
+ else
+ var = (int)*arg.plVal;
+ break;
+ case VT_INT:
+ var = arg.intVal;
+ break;
+ case VT_INT|VT_BYREF:
+ var = *arg.pintVal;
+ break;
+ case VT_UI1:
+ var = arg.bVal;
+ break;
+ case VT_UI1|VT_BYREF:
+ var = *arg.pbVal;
+ break;
+ case VT_UI2:
+ var = arg.uiVal;
+ break;
+ case VT_UI2|VT_BYREF:
+ var = *arg.puiVal;
+ break;
+ case VT_UI4:
+ if (type == QVariant::Color || (!type && typeName == "QColor"))
+ var = QVariant::fromValue(OLEColorToQColor(arg.ulVal));
+#ifndef QT_NO_CURSOR
+ else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*")))
+ var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal)));
+#endif
+ else
+ var = (int)arg.ulVal;
+ break;
+ case VT_UI4|VT_BYREF:
+ if (type == QVariant::Color || (!type && typeName == "QColor"))
+ var = QVariant::fromValue(OLEColorToQColor((uint)*arg.pulVal));
+#ifndef QT_NO_CURSOR
+ else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*")))
+ var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal)));
+#endif
+ else
+ var = (int)*arg.pulVal;
+ break;
+ case VT_UINT:
+ var = arg.uintVal;
+ break;
+ case VT_UINT|VT_BYREF:
+ var = *arg.puintVal;
+ break;
+ case VT_CY:
+ var = arg.cyVal.int64;
+ break;
+ case VT_CY|VT_BYREF:
+ var = arg.pcyVal->int64;
+ break;
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ case VT_I8:
+ var = arg.llVal;
+ break;
+ case VT_I8|VT_BYREF:
+ var = *arg.pllVal;
+ break;
+ case VT_UI8:
+ var = arg.ullVal;
+ break;
+ case VT_UI8|VT_BYREF:
+ var = *arg.pullVal;
+ break;
+#endif
+ case VT_R4:
+ var = arg.fltVal;
+ break;
+ case VT_R4|VT_BYREF:
+ var = *arg.pfltVal;
+ break;
+ case VT_R8:
+ var = arg.dblVal;
+ break;
+ case VT_R8|VT_BYREF:
+ var = *arg.pdblVal;
+ break;
+ case VT_DATE:
+ var = DATEToQDateTime(arg.date);
+ if (type == QVariant::Date || (!type && (typeName == "QDate" || typeName == "QDate*"))) {
+ var.convert(QVariant::Date);
+ } else if (type == QVariant::Time || (!type && (typeName == "QTime" || typeName == "QTime*"))) {
+ var.convert(QVariant::Time);
+ }
+ break;
+ case VT_DATE|VT_BYREF:
+ var = DATEToQDateTime(*arg.pdate);
+ if (type == QVariant::Date || (!type && (typeName == "QDate" || typeName == "QDate*"))) {
+ var.convert(QVariant::Date);
+ } else if (type == QVariant::Time || (!type && (typeName == "QTime" || typeName == "QTime*"))) {
+ var.convert(QVariant::Time);
+ }
+ break;
+ case VT_VARIANT:
+ case VT_VARIANT|VT_BYREF:
+ if (arg.pvarVal)
+ var = VARIANTToQVariant(*arg.pvarVal, typeName);
+ break;
+
+ case VT_DISPATCH:
+ case VT_DISPATCH|VT_BYREF:
+ {
+ // pdispVal and ppdispVal are a union
+ IDispatch *disp = 0;
+ if (arg.vt & VT_BYREF)
+ disp = *arg.ppdispVal;
+ else
+ disp = arg.pdispVal;
+ if (type == QVariant::Font || (!type && (typeName == "QFont" || typeName == "QFont*"))) {
+ IFont *ifont = 0;
+ if (disp)
+ disp->QueryInterface(IID_IFont, (void**)&ifont);
+ if (ifont) {
+ var = QVariant::fromValue(IFontToQFont(ifont));
+ ifont->Release();
+ } else {
+ var = QVariant::fromValue(QFont());
+ }
+ } else if (type == QVariant::Pixmap || (!type && (typeName == "QPixmap" || typeName == "QPixmap*"))) {
+ IPicture *ipic = 0;
+ if (disp)
+ disp->QueryInterface(IID_IPicture, (void**)&ipic);
+ if (ipic) {
+ var = QVariant::fromValue(IPictureToQPixmap(ipic));
+ ipic->Release();
+ } else {
+ var = QVariant::fromValue(QPixmap());
+ }
+ } else {
+#ifdef QAX_SERVER
+ IAxServerBase *iface = 0;
+ if (disp && typeName != "IDispatch*")
+ disp->QueryInterface(IID_IAxServerBase, (void**)&iface);
+ if (iface) {
+ QObject *qObj = iface->qObject();
+ iface->Release();
+ var = QVariant(qRegisterMetaType<QObject*>(qObj ? QByteArray(qObj->metaObject()->className()) + '*' : typeName), &qObj);
+ } else
+#endif
+ {
+ if (!typeName.isEmpty()) {
+ if (arg.vt & VT_BYREF) {
+ var = QVariant(qRegisterMetaType<IDispatch**>("IDispatch**"), &arg.ppdispVal);
+ } else {
+#ifndef QAX_SERVER
+ if (typeName == "QVariant") {
+ QAxObject *object = new QAxObject(disp);
+ var = QVariant::fromValue<QAxObject*>(object);
+ } else if (typeName != "IDispatch*" && QMetaType::type(typeName)) {
+ QByteArray typeNameStr = QByteArray(typeName);
+ int pIndex = typeName.lastIndexOf('*');
+ if (pIndex != -1)
+ typeNameStr = typeName.left(pIndex);
+ int metaType = QMetaType::type(typeNameStr);
+ Q_ASSERT(metaType != 0);
+ QAxObject *object = (QAxObject*)qax_createObjectWrapper(metaType, disp);
+ var = QVariant(QMetaType::type(typeName), &object);
+ } else
+#endif
+ var = QVariant(qRegisterMetaType<IDispatch*>(typeName), &disp);
+ }
+ }
+ }
+ }
+ }
+ break;
+ case VT_UNKNOWN:
+ case VT_UNKNOWN|VT_BYREF:
+ {
+ IUnknown *unkn = 0;
+ if (arg.vt & VT_BYREF)
+ unkn = *arg.ppunkVal;
+ else
+ unkn = arg.punkVal;
+ var.setValue(unkn);
+ }
+ break;
+ case VT_ARRAY|VT_VARIANT:
+ case VT_ARRAY|VT_VARIANT|VT_BYREF:
+ {
+ SAFEARRAY *array = 0;
+ if ( arg.vt & VT_BYREF )
+ array = *arg.pparray;
+ else
+ array = arg.parray;
+
+ UINT cDims = array ? SafeArrayGetDim(array) : 0;
+ switch(cDims) {
+ case 1:
+ {
+ QVariantList list;
+
+ long lBound, uBound;
+ SafeArrayGetLBound( array, 1, &lBound );
+ SafeArrayGetUBound( array, 1, &uBound );
+
+ for ( long i = lBound; i <= uBound; ++i ) {
+ VARIANT var;
+ VariantInit( &var );
+ SafeArrayGetElement( array, &i, &var );
+
+ QVariant qvar = VARIANTToQVariant( var, 0 );
+ clearVARIANT( &var );
+ list << qvar;
+ }
+
+ var = list;
+ }
+ break;
+
+ case 2:
+ {
+ QVariantList listList; // a list of lists
+ long dimIndices[2];
+
+ long xlBound, xuBound, ylBound, yuBound;
+ SafeArrayGetLBound(array, 1, &xlBound);
+ SafeArrayGetUBound(array, 1, &xuBound);
+ SafeArrayGetLBound(array, 2, &ylBound);
+ SafeArrayGetUBound(array, 2, &yuBound);
+
+ for (long x = xlBound; x <= xuBound; ++x) {
+ QVariantList list;
+
+ dimIndices[0] = x;
+ for (long y = ylBound; y <= yuBound; ++y) {
+ VARIANT var;
+ VariantInit(&var);
+ dimIndices[1] = y;
+ SafeArrayGetElement(array, dimIndices, &var);
+
+ QVariant qvar = VARIANTToQVariant(var, 0);
+ clearVARIANT(&var);
+ list << qvar;
+ }
+
+ listList << QVariant(list);
+ }
+ var = listList;
+ }
+ break;
+ default:
+ var = QVariantList();
+ break;
+ }
+ }
+ break;
+
+ case VT_ARRAY|VT_BSTR:
+ case VT_ARRAY|VT_BSTR|VT_BYREF:
+ {
+ SAFEARRAY *array = 0;
+ if (arg.vt & VT_BYREF)
+ array = *arg.pparray;
+ else
+ array = arg.parray;
+
+ QStringList strings;
+ if (!array || array->cDims != 1) {
+ var = strings;
+ break;
+ }
+
+ long lBound, uBound;
+ SafeArrayGetLBound(array, 1, &lBound);
+ SafeArrayGetUBound(array, 1, &uBound);
+
+ for (long i = lBound; i <= uBound; ++i) {
+ BSTR bstr;
+ SafeArrayGetElement(array, &i, &bstr);
+ strings << QString::fromWCharArray(bstr);
+ SysFreeString(bstr);
+ }
+
+ var = strings;
+ }
+ break;
+
+ case VT_ARRAY|VT_UI1:
+ case VT_ARRAY|VT_UI1|VT_BYREF:
+ {
+ SAFEARRAY *array = 0;
+ if (arg.vt & VT_BYREF)
+ array = *arg.pparray;
+ else
+ array = arg.parray;
+
+ QByteArray bytes;
+ if (!array || array->cDims != 1) {
+ var = bytes;
+ break;
+ }
+
+ long lBound, uBound;
+ SafeArrayGetLBound(array, 1, &lBound);
+ SafeArrayGetUBound(array, 1, &uBound);
+
+ if (uBound != -1) { // non-empty array
+ bytes.resize(uBound - lBound + 1);
+ char *data = bytes.data();
+ char *src;
+ SafeArrayAccessData(array, (void**)&src);
+ memcpy(data, src, bytes.size());
+ SafeArrayUnaccessData(array);
+ }
+
+ var = bytes;
+ }
+ break;
+
+#if defined(QAX_SERVER)
+ case VT_RECORD:
+ case VT_RECORD|VT_BYREF:
+ if (arg.pvRecord && arg.pRecInfo) {
+ IRecordInfo *recordInfo = arg.pRecInfo;
+ void *record = arg.pvRecord;
+ GUID guid;
+ recordInfo->GetGuid(&guid);
+
+ if (guid == CLSID_QRect) {
+ QRect qrect;
+ recordInfo->RecordCopy(record, &qrect);
+ var = qrect;
+ } else if (guid == CLSID_QSize) {
+ QSize qsize;
+ recordInfo->RecordCopy(record, &qsize);
+ var = qsize;
+ } else if (guid == CLSID_QPoint) {
+ QPoint qpoint;
+ recordInfo->RecordCopy(record, &qpoint);
+ var = qpoint;
+ }
+ }
+ break;
+#endif // QAX_SERVER
+ default:
+#if !defined(Q_OS_WINCE)
+ // support for any SAFEARRAY(Type) where Type can be converted to a QVariant
+ // -> QVariantList
+ if (arg.vt & VT_ARRAY) {
+ SAFEARRAY *array = 0;
+ if (arg.vt & VT_BYREF)
+ array = *arg.pparray;
+ else
+ array = arg.parray;
+
+ QVariantList list;
+ if (!array || array->cDims != 1) {
+ var = list;
+ break;
+ }
+
+ // find out where to store the element
+ VARTYPE vt;
+ VARIANT variant;
+ SafeArrayGetVartype(array, &vt);
+
+ void *pElement = 0;
+ switch(vt) {
+ case VT_BSTR: Q_ASSERT(false); break; // already covered
+ case VT_BOOL: pElement = &variant.boolVal; break;
+ case VT_I1: pElement = &variant.cVal; break;
+ case VT_I2: pElement = &variant.iVal; break;
+ case VT_I4: pElement = &variant.lVal; break;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ case VT_I8: pElement = &variant.llVal; break;
+ case VT_UI8: pElement = &variant.ullVal; break;
+#endif
+ case VT_INT: pElement = &variant.intVal; break;
+ case VT_UI1: Q_ASSERT(false); break; // already covered
+ case VT_UI2: pElement = &variant.uiVal; break;
+ case VT_UI4: pElement = &variant.ulVal; break;
+ case VT_UINT: pElement = &variant.uintVal; break;
+ case VT_CY: pElement = &variant.cyVal; break;
+ case VT_R4: pElement = &variant.fltVal; break;
+ case VT_R8: pElement = &variant.dblVal; break;
+ case VT_DATE: pElement = &variant.date; break;
+ case VT_VARIANT: Q_ASSERT(false); break; // already covered
+ default:
+ break;
+ }
+ if (!pElement) {
+ var = list;
+ break;
+ }
+
+ long lBound, uBound;
+ SafeArrayGetLBound( array, 1, &lBound );
+ SafeArrayGetUBound( array, 1, &uBound );
+
+ for ( long i = lBound; i <= uBound; ++i ) {
+ variant.vt = vt;
+ SafeArrayGetElement(array, &i, pElement);
+ QVariant qvar = VARIANTToQVariant(variant, 0);
+ clearVARIANT(&variant);
+ list << qvar;
+ }
+
+ var = list;
+ }
+#endif
+ break;
+ }
+
+ QVariant::Type proptype = (QVariant::Type)type;
+ if (proptype == QVariant::Invalid && !typeName.isEmpty()) {
+ if (typeName != "QVariant")
+ proptype = QVariant::nameToType(typeName);
+ }
+ if (proptype != QVariant::LastType && proptype != QVariant::Invalid && var.type() != proptype) {
+ if (var.canConvert(proptype)) {
+ QVariant oldvar = var;
+ if (oldvar.convert(proptype))
+ var = oldvar;
+ } else if (proptype == QVariant::StringList && var.type() == QVariant::List) {
+ bool allStrings = true;
+ QStringList strings;
+ const QList<QVariant> list(var.toList());
+ for (QList<QVariant>::ConstIterator it(list.begin()); it != list.end(); ++it) {
+ QVariant variant = *it;
+ if (variant.canConvert(QVariant::String))
+ strings << variant.toString();
+ else
+ allStrings = false;
+ }
+ if (allStrings)
+ var = strings;
+ } else {
+ var = QVariant();
+ }
+ }
+ return var;
+}
+
+void clearVARIANT(VARIANT *var)
+{
+ if (var->vt & VT_BYREF) {
+ switch(var->vt) {
+ case VT_BSTR|VT_BYREF:
+ SysFreeString(*var->pbstrVal);
+ delete var->pbstrVal;
+ break;
+ case VT_BOOL|VT_BYREF:
+ delete var->pboolVal;
+ break;
+ case VT_I1|VT_BYREF:
+ delete var->pcVal;
+ break;
+ case VT_I2|VT_BYREF:
+ delete var->piVal;
+ break;
+ case VT_I4|VT_BYREF:
+ delete var->plVal;
+ break;
+ case VT_INT|VT_BYREF:
+ delete var->pintVal;
+ break;
+ case VT_UI1|VT_BYREF:
+ delete var->pbVal;
+ break;
+ case VT_UI2|VT_BYREF:
+ delete var->puiVal;
+ break;
+ case VT_UI4|VT_BYREF:
+ delete var->pulVal;
+ break;
+ case VT_UINT|VT_BYREF:
+ delete var->puintVal;
+ break;
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ case VT_I8|VT_BYREF:
+ delete var->pllVal;
+ break;
+ case VT_UI8|VT_BYREF:
+ delete var->pullVal;
+ break;
+#endif
+ case VT_CY|VT_BYREF:
+ delete var->pcyVal;
+ break;
+ case VT_R4|VT_BYREF:
+ delete var->pfltVal;
+ break;
+ case VT_R8|VT_BYREF:
+ delete var->pdblVal;
+ break;
+ case VT_DATE|VT_BYREF:
+ delete var->pdate;
+ break;
+ case VT_DISPATCH|VT_BYREF:
+ (*var->ppdispVal)->Release();
+ delete var->ppdispVal;
+ break;
+ case VT_ARRAY|VT_VARIANT|VT_BYREF:
+ case VT_ARRAY|VT_UI1|VT_BYREF:
+ case VT_ARRAY|VT_BSTR|VT_BYREF:
+ SafeArrayDestroy(*var->pparray);
+ delete var->pparray;
+ break;
+ case VT_VARIANT|VT_BYREF:
+ delete var->pvarVal;
+ break;
+ }
+ VariantInit(var);
+ } else {
+ VariantClear(var);
+ }
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
diff --git a/src/activeqt/shared/qaxtypes.h b/src/activeqt/shared/qaxtypes.h
new file mode 100644
index 0000000..8f76390
--- /dev/null
+++ b/src/activeqt/shared/qaxtypes.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the ActiveQt framework of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 Nokia Corporation and its Subsidiary(-ies) 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 QAXTYPES_H
+#define QAXTYPES_H
+
+#if !defined(_WINDOWS_) && !defined(_WINDOWS_H) && !defined(__WINDOWS__)
+#error Must include windows.h first!
+#endif
+
+#include <QtGui/qcolor.h>
+#include <QtGui/qfont.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(ActiveQt)
+
+#ifndef QT_NO_WIN_ACTIVEQT
+
+extern GUID IID_IAxServerBase;
+struct IAxServerBase : public IUnknown
+{
+ virtual IUnknown *clientSite() const = 0;
+ virtual void emitPropertyChanged(const char*) = 0;
+ virtual bool emitRequestPropertyChange(const char*) = 0;
+ virtual QObject *qObject() const = 0;
+ virtual void reportError(int code, const QString &src, const QString &desc, const QString &context) = 0;
+};
+
+#define HIMETRIC_PER_INCH 2540
+#define MAP_PIX_TO_LOGHIM(x,ppli) ((HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) (((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH)
+#define QAX_NUM_PARAMS 8
+
+static inline BSTR QStringToBSTR(const QString &str)
+{
+ return SysAllocStringLen((OLECHAR*)str.unicode(), str.length());
+}
+
+static inline uint QColorToOLEColor(const QColor &col)
+{
+ return qRgba(col.blue(), col.green(), col.red(), 0x00);
+}
+
+extern QColor OLEColorToQColor(uint col);
+
+extern bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName = 0, bool out = false);
+extern QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint type = 0);
+extern bool QVariantToVoidStar(const QVariant &var, void *data, const QByteArray &typeName, uint type = 0);
+extern void clearVARIANT(VARIANT *var);
+
+#define QAX_INPROC_SERVER (0x51540001)
+#define QAX_OUTPROC_SERVER (0x51540002)
+
+QT_END_NAMESPACE
+#endif // QT_NO_WIN_ACTIVEQT
+
+QT_END_HEADER
+
+#endif // QAXTYPES_H
diff --git a/tools/dumpcpp/dumpcpp.pro b/tools/dumpcpp/dumpcpp.pro
new file mode 100644
index 0000000..09a339b
--- /dev/null
+++ b/tools/dumpcpp/dumpcpp.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+
+CONFIG += console qaxcontainer
+DESTDIR = ../../../bin
+
+SOURCES += main.cpp
diff --git a/tools/dumpcpp/main.cpp b/tools/dumpcpp/main.cpp
new file mode 100644
index 0000000..f95d31d
--- /dev/null
+++ b/tools/dumpcpp/main.cpp
@@ -0,0 +1,1504 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QAxObject>
+#include <QFile>
+#include <QMetaObject>
+#include <QMetaEnum>
+#include <QTextStream>
+#include <QSettings>
+#include <QStringList>
+#include <QUuid>
+#include <QWidget>
+#include <QFileInfo>
+#include <qt_windows.h>
+#include <ocidl.h>
+
+QT_BEGIN_NAMESPACE
+
+static ITypeInfo *currentTypeInfo = 0;
+
+enum ObjectCategory
+{
+ DefaultObject = 0x00,
+ SubObject = 0x001,
+ ActiveX = 0x002,
+ NoMetaObject = 0x004,
+ NoImplementation = 0x008,
+ NoDeclaration = 0x010,
+ NoInlines = 0x020,
+ OnlyInlines = 0x040,
+ DoNothing = 0x080,
+ Licensed = 0x100,
+ TypeLibID = 0x101
+};
+
+// this comes from moc/qmetaobject.cpp
+enum ProperyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resetable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+ Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000
+};
+
+enum MemberFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ MemberMethod = 0x00,
+ MemberSignal = 0x04,
+ MemberSlot = 0x08,
+ MemberCompatibility = 0x10,
+ MemberCloned = 0x20,
+ MemberScriptable = 0x40,
+};
+
+extern QMetaObject *qax_readEnumInfo(ITypeLib *typeLib, const QMetaObject *parentObject);
+extern QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject);
+extern QMetaObject *qax_readInterfaceInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject);
+extern QList<QByteArray> qax_qualified_usertypes;
+extern QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name);
+extern bool qax_dispatchEqualsIDispatch;
+
+QByteArray nameSpace;
+QMap<QByteArray, QByteArray> namespaceForType;
+
+void writeEnums(QTextStream &out, const QMetaObject *mo)
+{
+ // enums
+ for (int ienum = mo->enumeratorOffset(); ienum < mo->enumeratorCount(); ++ienum) {
+ QMetaEnum metaEnum = mo->enumerator(ienum);
+ out << " enum " << metaEnum.name() << " {" << endl;
+ for (int k = 0; k < metaEnum.keyCount(); ++k) {
+ QByteArray key(metaEnum.key(k));
+ out << " " << key.leftJustified(24) << "= " << metaEnum.value(k);
+ if (k < metaEnum.keyCount() - 1)
+ out << ",";
+ out << endl;
+ }
+ out << " };" << endl;
+ out << endl;
+ }
+}
+
+void writeHeader(QTextStream &out, const QByteArray &nameSpace, const QString &outFileName)
+{
+ out << "#ifndef QAX_DUMPCPP_" << outFileName.toUpper() << "_H" << endl;
+ out << "#define QAX_DUMPCPP_" << outFileName.toUpper() << "_H" << endl;
+ out << endl;
+ out << "// Define this symbol to __declspec(dllexport) or __declspec(dllimport)" << endl;
+ out << "#ifndef " << nameSpace.toUpper() << "_EXPORT" << endl;
+ out << "#define " << nameSpace.toUpper() << "_EXPORT" << endl;
+ out << "#endif" << endl;
+ out << endl;
+ out << "#include <qaxobject.h>" << endl;
+ out << "#include <qaxwidget.h>" << endl;
+ out << "#include <qdatetime.h>" << endl;
+ out << "#include <qpixmap.h>" << endl;
+ out << endl;
+ out << "struct IDispatch;" << endl;
+ out << endl;
+}
+
+void generateNameSpace(QTextStream &out, const QMetaObject *mo, const QByteArray &nameSpace)
+{
+ out << "namespace " << nameSpace << " {" << endl;
+ out << endl;
+ writeEnums(out, mo);
+
+ // don't close on purpose
+}
+
+static QByteArray joinParameterNames(const QList<QByteArray> &parameterNames)
+{
+ QByteArray slotParameters;
+ for (int p = 0; p < parameterNames.count(); ++p) {
+ slotParameters += parameterNames.at(p);
+ if (p < parameterNames.count() - 1)
+ slotParameters += ',';
+ }
+
+ return slotParameters;
+}
+
+QByteArray constRefify(const QByteArray &type)
+{
+ QByteArray ctype(type);
+ if (type == "QString" || type == "QPixmap"
+ || type == "QVariant" || type == "QDateTime"
+ || type == "QColor" || type == "QFont"
+ || type == "QByteArray" || type == "QValueList<QVariant>"
+ || type == "QStringList")
+ ctype = "const " + ctype + "&";
+
+ return ctype;
+}
+
+void generateClassDecl(QTextStream &out, const QString &controlID, const QMetaObject *mo, const QByteArray &className, const QByteArray &nameSpace, ObjectCategory category)
+{
+ QList<QByteArray> functions;
+
+ QByteArray indent;
+ if (!(category & OnlyInlines))
+ indent = " ";
+
+ if (!(category & OnlyInlines)) {
+ // constructors
+ out << "class " << nameSpace.toUpper() << "_EXPORT " << className << " : public ";
+ if (category & ActiveX)
+ out << "QAxWidget";
+ else
+ out << "QAxObject";
+ out << endl;
+
+ out << "{" << endl;
+ out << "public:" << endl;
+ out << " " << className << "(";
+ if (category & Licensed)
+ out << "const QString &licenseKey = QString(), ";
+ if (category & ActiveX)
+ out << "QWidget *parent = 0, Qt::WindowFlags f";
+ else if (category & SubObject)
+ out << "IDispatch *subobject = 0, QAxObject *parent";
+ else
+ out << "QObject *parent";
+ out << " = 0)" << endl;
+ out << " : ";
+ if (category & ActiveX)
+ out << "QAxWidget(parent, f";
+ else if (category & SubObject)
+ out << "QAxObject((IUnknown*)subobject, parent";
+ else
+ out << "QAxObject(parent";
+ out << ")" << endl;
+ out << " {" << endl;
+ if (category & SubObject)
+ out << " internalRelease();" << endl;
+ else if (category & Licensed) {
+ out << " if (licenseKey.isEmpty())" << endl;
+ out << " setControl(\"" << controlID << "\");" << endl;
+ out << " else" << endl;
+ out << " setControl(\"" << controlID << ":\" + licenseKey);" << endl;
+ } else {
+ out << " setControl(\"" << controlID << "\");" << endl;
+ }
+ out << " }" << endl;
+ out << endl;
+
+ for (int ci = mo->classInfoOffset(); ci < mo->classInfoCount(); ++ci) {
+ QMetaClassInfo info = mo->classInfo(ci);
+ QByteArray iface_name = info.name();
+ if (iface_name.startsWith("Event "))
+ continue;
+
+ QByteArray iface_class = info.value();
+
+ out << " " << className << "(" << iface_class << " *iface)" << endl;
+
+ if (category & ActiveX)
+ out << " : QAxWidget()" << endl;
+ else
+ out << " : QAxObject()" << endl;
+ out << " {" << endl;
+ out << " initializeFrom(iface);" << endl;
+ out << " delete iface;" << endl;
+ out << " }" << endl;
+ out << endl;
+ }
+ }
+
+ functions << className;
+
+ // enums
+ if (nameSpace.isEmpty() && !(category & OnlyInlines)) {
+ for (int ienum = mo->enumeratorOffset(); ienum < mo->enumeratorCount(); ++ienum) {
+ QMetaEnum metaEnum = mo->enumerator(ienum);
+ out << " enum " << metaEnum.name() << " {" << endl;
+ for (int k = 0; k < metaEnum.keyCount(); ++k) {
+ QByteArray key(metaEnum.key(k));
+ out << " " << key.leftJustified(24) << "= " << metaEnum.value(k);
+ if (k < metaEnum.keyCount() - 1)
+ out << ",";
+ out << endl;
+ }
+ out << " };" << endl;
+ out << endl;
+ }
+ }
+ // QAxBase public virtual functions.
+ QList<QByteArray> axBase_vfuncs;
+ axBase_vfuncs.append("metaObject");
+ axBase_vfuncs.append("qObject");
+ axBase_vfuncs.append("className");
+ axBase_vfuncs.append("propertyWritable");
+ axBase_vfuncs.append("setPropertyWritable");
+
+ // properties
+ for (int iprop = mo->propertyOffset(); iprop < mo->propertyCount(); ++iprop) {
+ QMetaProperty property = mo->property(iprop);
+ if (!property.isReadable())
+ continue;
+
+ QByteArray propertyName(property.name());
+ if (propertyName == "control" || propertyName == className)
+ continue;
+
+ if (!(category & OnlyInlines)) {
+ out << indent << "/*" << endl << indent << "Property " << propertyName << endl;
+ QString documentation = qax_docuFromName(currentTypeInfo, QString::fromLatin1(propertyName.constData()));
+ if (!documentation.isEmpty()) {
+ out << endl;
+ out << indent << documentation << endl;
+ }
+ out << indent << "*/" << endl;
+ }
+
+ // Check whether the new function conflicts with any of QAxBase public virtual functions.
+ // If so, prepend the function name with '<classname>_'. Since all internal metaobject magic
+ // remains the same, we have to use the original name when used with QObject::connect or QMetaObject
+ QByteArray propertyFunctionName(propertyName);
+ if (axBase_vfuncs.contains(propertyFunctionName)) {
+ propertyFunctionName = className + "_" + propertyName;
+ qWarning("property conflits with QAXBase: %s changed to %s", propertyName.constData(), propertyFunctionName.constData());
+ }
+
+ QByteArray propertyType(property.typeName());
+ QByteArray castType(propertyType);
+
+ QByteArray simplePropType = propertyType;
+ simplePropType.replace('*', "");
+
+ out << indent << "inline ";
+ bool foreignNamespace = true;
+ if (!propertyType.contains("::") &&
+ (qax_qualified_usertypes.contains(simplePropType) || qax_qualified_usertypes.contains("enum "+ simplePropType))
+ ) {
+ propertyType = nameSpace + "::" + propertyType;
+ foreignNamespace = false;
+ }
+
+ out << propertyType << " ";
+
+ if (category & OnlyInlines)
+ out << className << "::";
+ out << propertyFunctionName << "() const";
+
+ if (!(category & NoInlines)) {
+ out << endl << indent << "{" << endl;
+ if (qax_qualified_usertypes.contains(simplePropType)) {
+ out << indent << " " << propertyType << " qax_pointer = 0;" << endl;
+ out << indent << " qRegisterMetaType(\"" << property.typeName() << "\", &qax_pointer);" << endl;
+ if (foreignNamespace)
+ out << "#ifdef QAX_DUMPCPP_" << propertyType.left(propertyType.indexOf("::")).toUpper() << "_H" << endl;
+ out << indent << " qRegisterMetaType(\"" << simplePropType << "\", qax_pointer);" << endl;
+ if (foreignNamespace)
+ out << "#endif" << endl;
+ }
+ out << indent << " QVariant qax_result = property(\"" << propertyName << "\");" << endl;
+ if (propertyType.length() && propertyType.at(propertyType.length()-1) == '*')
+ out << indent << " if (!qax_result.constData()) return 0;" << endl;
+ out << indent << " Q_ASSERT(qax_result.isValid());" << endl;
+ if (qax_qualified_usertypes.contains(simplePropType)) {
+ simplePropType = propertyType;
+ simplePropType.replace('*', "");
+ if (foreignNamespace)
+ out << "#ifdef QAX_DUMPCPP_" << propertyType.left(propertyType.indexOf("::")).toUpper() << "_H" << endl;
+ out << indent << " return *(" << propertyType << "*)qax_result.constData();" << endl;
+ if (foreignNamespace) {
+ out << "#else" << endl;
+ out << indent << " return 0; // foreign namespace not included" << endl;
+ out << "#endif" << endl;
+ }
+
+ } else {
+ out << indent << " return *(" << propertyType << "*)qax_result.constData();" << endl;
+ }
+ out << indent << "}" << endl;
+ } else {
+ out << "; //Returns the value of " << propertyName << endl;
+ }
+
+ functions << propertyName;
+
+ if (property.isWritable()) {
+ QByteArray setter(propertyName);
+ QChar firstChar = QLatin1Char(setter.at(0));
+ if (isupper(setter.at(0))) {
+ setter = "Set" + setter;
+ } else {
+ setter[0] = toupper(setter[0]);
+ setter = "set" + setter;
+ }
+
+ out << indent << "inline " << "void ";
+ if (category & OnlyInlines)
+ out << className << "::";
+ out << setter << "(" << constRefify(propertyType) << " value)";
+
+ if (!(category & NoInlines)) {
+ if (propertyType.endsWith('*')) {
+ out << "{" << endl;
+ out << " int typeId = qRegisterMetaType(\"" << propertyType << "\", &value);" << endl;
+ out << " setProperty(\"" << propertyName << "\", QVariant(typeId, &value));" << endl;
+ out << "}" << endl;
+ } else {
+ out << "{ setProperty(\"" << propertyName << "\", QVariant(value)); }" << endl;
+ }
+ } else {
+ out << "; //Sets the value of the " << propertyName << " property" << endl;
+ }
+
+ functions << setter;
+ }
+
+ out << endl;
+ }
+
+ // slots - but not property setters
+ int defaultArguments = 0;
+ for (int islot = mo->methodOffset(); islot < mo->methodCount(); ++islot) {
+ const QMetaMethod slot(mo->method(islot));
+ if (slot.methodType() != QMetaMethod::Slot)
+ continue;
+
+#if 0
+ // makes not sense really to respect default arguments...
+ if (slot.attributes() & Cloned) {
+ ++defaultArguments;
+ continue;
+ }
+#endif
+
+ QByteArray slotSignature(slot.signature());
+ QByteArray slotName = slotSignature.left(slotSignature.indexOf('('));
+ if (functions.contains(slotName))
+ continue;
+
+ if (!(category & OnlyInlines)) {
+ out << indent << "/*" << endl << indent << "Method " << slotName << endl;
+ QString documentation = qax_docuFromName(currentTypeInfo, QString::fromLatin1(slotName.constData()));
+ if (!documentation.isEmpty()) {
+ out << endl;
+ out << indent << documentation << endl;
+ }
+ out << indent << "*/" << endl;
+ }
+
+ QByteArray slotParameters(joinParameterNames(slot.parameterNames()));
+ QByteArray slotTag(slot.tag());
+ QByteArray slotType(slot.typeName());
+
+ QByteArray simpleSlotType = slotType;
+ simpleSlotType.replace('*', "");
+ if (!slotType.contains("::") && qax_qualified_usertypes.contains(simpleSlotType))
+ slotType = nameSpace + "::" + slotType;
+
+
+ QByteArray slotNamedSignature;
+ if (slotSignature.endsWith("()")) { // no parameters - no names
+ slotNamedSignature = slotSignature;
+ } else {
+ slotNamedSignature = slotSignature.left(slotSignature.indexOf('(') + 1);
+ QByteArray slotSignatureTruncated(slotSignature.mid(slotNamedSignature.length()));
+ slotSignatureTruncated.truncate(slotSignatureTruncated.length() - 1);
+
+ QList<QByteArray> signatureSplit = slotSignatureTruncated.split(',');
+ QList<QByteArray> parameterSplit;
+ if (slotParameters.isEmpty()) { // generate parameter names
+ for (int i = 0; i < signatureSplit.count(); ++i)
+ parameterSplit << QByteArray("p") + QByteArray::number(i);
+ } else {
+ parameterSplit = slotParameters.split(',');
+ }
+
+ for (int i = 0; i < signatureSplit.count(); ++i) {
+ QByteArray parameterType = signatureSplit.at(i);
+ if (!parameterType.contains("::") && namespaceForType.contains(parameterType))
+ parameterType = namespaceForType.value(parameterType) + "::" + parameterType;
+
+ slotNamedSignature += constRefify(parameterType);
+ slotNamedSignature += " ";
+ slotNamedSignature += parameterSplit.at(i);
+ if (defaultArguments >= signatureSplit.count() - i) {
+ slotNamedSignature += " = ";
+ slotNamedSignature += parameterType + "()";
+ }
+ if (i + 1 < signatureSplit.count())
+ slotNamedSignature += ", ";
+ }
+ slotNamedSignature += ')';
+ }
+
+ out << indent << "inline ";
+
+ if (!slotTag.isEmpty())
+ out << slotTag << " ";
+ if (slotType.isEmpty())
+ out << "void ";
+ else
+ out << slotType << " ";
+ if (category & OnlyInlines)
+ out << className << "::";
+
+ // Update function name in case of conflicts with QAxBase public virtual functions.
+ int parnIdx = slotNamedSignature.indexOf('(');
+ QByteArray slotOriginalName = slotNamedSignature.left(parnIdx);
+ if (axBase_vfuncs.contains(slotOriginalName)) {
+ QByteArray newSignature = className + "_" + slotOriginalName;
+ newSignature += slotNamedSignature.mid(parnIdx);
+ qWarning("function name conflits with QAXBase %s changed to %s", slotNamedSignature.constData(), newSignature.constData());
+ slotNamedSignature = newSignature;
+ }
+
+ out << slotNamedSignature;
+
+ if (category & NoInlines) {
+ out << ";" << endl;
+ } else {
+ out << endl;
+ out << indent << "{" << endl;
+
+ if (!slotType.isEmpty()) {
+ out << indent << " " << slotType << " qax_result";
+ if (slotType.endsWith('*'))
+ out << " = 0";
+ out << ";" << endl;
+ if (qax_qualified_usertypes.contains(simpleSlotType)) {
+ out << indent << " qRegisterMetaType(\"" << simpleSlotType << "*\", &qax_result);" << endl;
+ bool foreignNamespace = simpleSlotType.contains("::");
+ if (foreignNamespace)
+ out << "#ifdef QAX_DUMPCPP_" << simpleSlotType.left(simpleSlotType.indexOf(':')).toUpper() << "_H" << endl;
+ out << indent << " qRegisterMetaType(\"" << simpleSlotType << "\", qax_result);" << endl;
+ if (foreignNamespace)
+ out << "#endif" << endl;
+ }
+ }
+ out << indent << " void *_a[] = {";
+ if (!slotType.isEmpty())
+ out << "(void*)&qax_result";
+ else
+ out << "0";
+ if (!slotParameters.isEmpty()) {
+ out << ", (void*)&";
+ out << slotParameters.replace(",", ", (void*)&");
+ }
+ out << "};" << endl;
+
+ out << indent << " qt_metacall(QMetaObject::InvokeMetaMethod, " << islot << ", _a);" << endl;
+ if (!slotType.isEmpty())
+ out << indent << " return qax_result;" << endl;
+ out << indent << "}" << endl;
+ }
+
+ out << endl;
+ defaultArguments = 0;
+ }
+
+ if (!(category & OnlyInlines)) {
+ if (!(category & NoMetaObject)) {
+ out << "// meta object functions" << endl;
+ out << " static const QMetaObject staticMetaObject;" << endl;
+ out << " virtual const QMetaObject *metaObject() const { return &staticMetaObject; }" << endl;
+ out << " virtual void *qt_metacast(const char *);" << endl;
+ }
+
+ out << "};" << endl;
+ }
+}
+
+#define addString(string, stringData) \
+ out << stringDataLength << ", "; \
+ stringData += string; \
+ stringDataLength += qstrlen(string); \
+ stringData += "\\0"; \
+ lineLength += qstrlen(string) + 1; \
+ if (lineLength > 200) { stringData += "\"\n \""; lineLength = 0; } \
+ ++stringDataLength;
+
+void generateClassImpl(QTextStream &out, const QMetaObject *mo, const QByteArray &className, const QByteArray &nameSpace, ObjectCategory category)
+{
+ QByteArray qualifiedClassName;
+ if (!nameSpace.isEmpty())
+ qualifiedClassName = nameSpace + "::";
+ qualifiedClassName += className;
+
+ QByteArray stringData(qualifiedClassName);
+ int stringDataLength = stringData.length();
+ stringData += "\\0\"\n";
+ ++stringDataLength;
+ int lineLength = 0;
+
+ int classInfoCount = mo->classInfoCount() - mo->classInfoOffset();
+ int enumCount = mo->enumeratorCount() - mo->enumeratorOffset();
+ int methodCount = mo->methodCount() - mo->methodOffset();
+ int propertyCount = mo->propertyCount() - mo->propertyOffset();
+ int enumStart = 10;
+
+ out << "static const uint qt_meta_data_" << qualifiedClassName.replace(':', '_') << "[] = {" << endl;
+ out << endl;
+ out << " // content:" << endl;
+ out << " 1, // revision" << endl;
+ out << " 0, // classname" << endl;
+ out << " " << classInfoCount << ", " << (classInfoCount ? enumStart : 0) << ", // classinfo" << endl;
+ enumStart += classInfoCount * 2;
+ out << " " << methodCount << ", " << (methodCount ? enumStart : 0) << ", // methods" << endl;
+ enumStart += methodCount * 5;
+ out << " " << propertyCount << ", " << (propertyCount ? enumStart : 0) << ", // properties" << endl;
+ enumStart += propertyCount * 3;
+ out << " " << enumCount << ", " << (enumCount ? enumStart : 0)
+ << ", // enums/sets" << endl;
+ out << endl;
+
+ if (classInfoCount) {
+ out << " // classinfo: key, value" << endl;
+ stringData += " \"";
+ for (int i = 0; i < classInfoCount; ++i) {
+ QMetaClassInfo classInfo = mo->classInfo(i + mo->classInfoOffset());
+ out << " ";
+ addString(classInfo.name(), stringData);
+ addString(classInfo.value(), stringData);
+ out << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+ }
+ if (methodCount) {
+ out << " // signals: signature, parameters, type, tag, flags" << endl;
+ stringData += " \"";
+ for (int i = 0; i < methodCount; ++i) {
+ const QMetaMethod signal(mo->method(i + mo->methodOffset()));
+ if (signal.methodType() != QMetaMethod::Signal)
+ continue;
+ out << " ";
+ addString(signal.signature(), stringData);
+ addString(joinParameterNames(signal.parameterNames()), stringData);
+ addString(signal.typeName(), stringData);
+ addString(signal.tag(), stringData);
+ out << (AccessProtected | signal.attributes() | MemberSignal) << "," << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+
+ out << " // slots: signature, parameters, type, tag, flags" << endl;
+ stringData += " \"";
+ for (int i = 0; i < methodCount; ++i) {
+ const QMetaMethod slot(mo->method(i + mo->methodOffset()));
+ if (slot.methodType() != QMetaMethod::Slot)
+ continue;
+ out << " ";
+ addString(slot.signature(), stringData);
+ addString(joinParameterNames(slot.parameterNames()), stringData);
+ addString(slot.typeName(), stringData);
+ addString(slot.tag(), stringData);
+ out << (0x01 | slot.attributes() | MemberSlot) << "," << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+ }
+ if (propertyCount) {
+ out << " // properties: name, type, flags" << endl;
+ stringData += " \"";
+ for (int i = 0; i < propertyCount; ++i) {
+ QMetaProperty property = mo->property(i + mo->propertyOffset());
+ out << " ";
+ addString(property.name(), stringData);
+ addString(property.typeName(), stringData);
+
+ uint flags = 0;
+ uint vartype = property.type();
+ if (vartype != QVariant::Invalid && vartype != QVariant::UserType)
+ flags = vartype << 24;
+ else if (QByteArray(property.typeName()) == "QVariant")
+ flags |= 0xff << 24;
+
+ if (property.isReadable())
+ flags |= Readable;
+ if (property.isWritable())
+ flags |= Writable;
+ if (property.isEnumType())
+ flags |= EnumOrFlag;
+ if (property.isDesignable())
+ flags |= Designable;
+ if (property.isScriptable())
+ flags |= Scriptable;
+ if (property.isStored())
+ flags |= Stored;
+ if (property.isEditable())
+ flags |= Editable;
+
+ out << "0x" << QString::number(flags, 16).rightJustified(8, '0') << ", \t\t // " << property.typeName() << " " << property.name();
+ out << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+ }
+
+ QByteArray enumStringData;
+ if (enumCount) {
+ out << " // enums: name, flags, count, data" << endl;
+ enumStringData += " \"";
+ enumStart += enumCount * 4;
+ for (int i = 0; i < enumCount; ++i) {
+ QMetaEnum enumerator = mo->enumerator(i + mo->enumeratorOffset());
+ out << " ";
+ addString(enumerator.name(), enumStringData);
+ out << (enumerator.isFlag() ? "0x1" : "0x0") << ", " << enumerator.keyCount() << ", " << enumStart << ", " << endl;
+ enumStart += enumerator.keyCount() * 2;
+ }
+ enumStringData += "\"\n";
+ out << endl;
+
+ out << " // enum data: key, value" << endl;
+ for (int i = 0; i < enumCount; ++i) {
+ enumStringData += " \"";
+ QMetaEnum enumerator = mo->enumerator(i + mo->enumeratorOffset());
+ for (int j = 0; j < enumerator.keyCount(); ++j) {
+ out << " ";
+ addString(enumerator.key(j), enumStringData);
+ if (nameSpace.isEmpty())
+ out << className << "::";
+ else
+ out << nameSpace << "::";
+ out << enumerator.key(j) << "," << endl;
+ }
+ enumStringData += "\"\n";
+ }
+ out << endl;
+ }
+ out << " 0 // eod" << endl;
+ out << "};" << endl;
+ out << endl;
+
+ QByteArray stringGenerator;
+
+ if (!nameSpace.isEmpty()) {
+ static bool firstStringData = true;
+ if (firstStringData) { // print enums only once
+ firstStringData = false;
+ if (!enumStringData.isEmpty()) {
+ // Maximum string length supported is 64K
+ int maxStringLength = 65535;
+ if (enumStringData.size() < maxStringLength) {
+ out << "static const char qt_meta_enumstringdata_" << nameSpace << "[] = {" << endl;
+ out << enumStringData << endl;
+ out << "};" << endl;
+ out << endl;
+ } else {
+ // split the string into fragments of 64k
+ int fragments = (enumStringData.size() / maxStringLength);
+ fragments += (enumStringData.size() % maxStringLength) ? 1 : 0;
+ int i, index;
+ // define the fragments (qt_meta_enumstringdata_<nameSpace>fragment#)
+ for (i = 0 , index = 0; i < fragments; i++, index += maxStringLength) {
+ out << "static const char qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) << "[] = {" << endl;
+ QByteArray fragment = enumStringData.mid(index, maxStringLength);
+ if (!(fragment[0] == ' ' || fragment[0] == '\n' || fragment[0] == '\"'))
+ out << "\"";
+ out << fragment;
+ int endIx = fragment.size() - 1;
+ if (!(fragment[endIx] == ' ' || fragment[endIx] == '\n' || fragment[endIx] == '\"' || fragment[endIx] == '\0'))
+ out << "\"" << endl;
+ else
+ out << endl;
+ out << "};" << endl;
+ }
+ // original array definition, size will be the combined size of the arrays defined above
+ out << "static char qt_meta_enumstringdata_" << nameSpace << "[" << endl;
+ for (i = 0; i < fragments; i++, index += maxStringLength) {
+ out << " ";
+ if (i)
+ out << "+ ";
+ out << "sizeof(qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) <<")" << endl;
+ }
+ out << "] = {0};" << endl << endl;
+ // this class will initializes the original array in constructor
+ out << "class qt_meta_enumstringdata_" << nameSpace << "_init " << endl <<"{" <<endl;
+ out << "public:"<<endl;
+ out << " qt_meta_enumstringdata_" << nameSpace << "_init() " << endl <<" {" <<endl;
+ out << " int index = 0;" << endl;
+ for (i = 0; i < fragments; i++, index += maxStringLength) {
+ out << " memcpy(qt_meta_enumstringdata_" << nameSpace << " + index, " <<"qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i);
+ out << ", sizeof(qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) <<") - 1);" << endl;
+ out << " index += sizeof(qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) <<") - 1;" << endl;
+ }
+ out << " }" << endl << "};" << endl;
+ // a global variable of the class
+ out << "static qt_meta_enumstringdata_" << nameSpace << "_init qt_meta_enumstringdata_" << nameSpace << "_init_instance;" << endl << endl;
+ }
+ }
+ }
+ stringGenerator = "qt_meta_stringdata_" + qualifiedClassName.replace(':','_') + "()";
+ out << "static const char *" << stringGenerator << " {" << endl;
+ QList<QByteArray> splitStrings;
+
+ // workaround for compilers that can't handle string literals longer than 64k
+ int splitCount = 0;
+ do {
+ int lastNewline = stringData.lastIndexOf('\n', 64000);
+ QByteArray splitString = stringData.left(lastNewline);
+
+ splitStrings << splitString;
+ out << " static const char stringdata" << splitCount << "[] = {" << endl;
+ out << " \"" << splitString << endl;
+ out << " };" << endl;
+ stringData = stringData.mid(lastNewline + 1);
+ if (stringData.startsWith(" \""))
+ stringData = stringData.mid(5);
+ ++splitCount;
+ } while (!stringData.isEmpty());
+
+ out << " static char data[";
+ for (int i = 0; i < splitCount; ++i) {
+ out << "sizeof(stringdata" << i << ") + ";
+ }
+ if (!enumStringData.isEmpty()) {
+ out << "sizeof(qt_meta_enumstringdata_" << nameSpace << ")";
+ } else {
+ out << "0";
+ }
+ out << "];" << endl;
+ out << " if (!data[0]) {" << endl;
+ out << " int index = 0;" << endl;
+
+ int dataIndex = 0;
+ for (int i = 0; i < splitCount; ++i) {
+ out << " memcpy(data + index";
+ out << ", stringdata" << i << ", sizeof(stringdata" << i << ") - 1);" << endl;
+ out << " index += sizeof(stringdata" << i << ") - 1;" << endl;
+ dataIndex += splitStrings.at(i).length();
+ }
+ if (!enumStringData.isEmpty()) {
+ out << " memcpy(data + index, qt_meta_enumstringdata_" << nameSpace << ", sizeof(qt_meta_enumstringdata_" << nameSpace << "));" << endl;
+ }
+ out << " }" << endl;
+ out << endl;
+ out << " return data;" << endl;
+ out << "};" << endl;
+ out << endl;
+ } else {
+ stringData += enumStringData;
+ stringGenerator = "qt_meta_stringdata_" + qualifiedClassName.replace(':','_');
+ out << "static const char qt_meta_stringdata_" << stringGenerator << "[] = {" << endl;
+ out << " \"" << stringData << endl;
+ out << "};" << endl;
+ out << endl;
+ }
+
+ out << "const QMetaObject " << className << "::staticMetaObject = {" << endl;
+ if (category & ActiveX)
+ out << "{ &QWidget::staticMetaObject," << endl;
+ else
+ out << "{ &QObject::staticMetaObject," << endl;
+ out << stringGenerator << "," << endl;
+ out << "qt_meta_data_" << qualifiedClassName.replace(':','_') << " }" << endl;
+ out << "};" << endl;
+ out << endl;
+
+ out << "void *" << className << "::qt_metacast(const char *_clname)" << endl;
+ out << "{" << endl;
+ out << " if (!_clname) return 0;" << endl;
+ out << " if (!strcmp(_clname, " << stringGenerator << "))" << endl;
+ out << " return static_cast<void*>(const_cast<" << className << "*>(this));" << endl;
+ if (category & ActiveX)
+ out << " return QAxWidget::qt_metacast(_clname);" << endl;
+ else
+ out << " return QAxObject::qt_metacast(_clname);" << endl;
+ out << "}" << endl;
+}
+
+bool generateClass(QAxObject *object, const QByteArray &className, const QByteArray &nameSpace, const QByteArray &outname, ObjectCategory category)
+{
+ IOleControl *control = 0;
+ object->queryInterface(IID_IOleControl, (void**)&control);
+ if (control) {
+ category = ActiveX;
+ control->Release();
+ }
+
+ const QMetaObject *mo = object->metaObject();
+
+ if (!nameSpace.isEmpty() && !(category & NoDeclaration)) {
+ QFile outfile(QString::fromLatin1(nameSpace.toLower().constData()) + QLatin1String(".h"));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(outfile.fileName()));
+ return false;
+ }
+ QTextStream out(&outfile);
+
+ out << "/****************************************************************************" << endl;
+ out << "**" << endl;
+ out << "** Namespace " << nameSpace << " generated by dumpcpp" << endl;
+ out << "**" << endl;
+ out << "****************************************************************************/" << endl;
+ out << endl;
+
+ writeHeader(out, nameSpace, outfile.fileName());
+ generateNameSpace(out, mo, nameSpace);
+
+ // close namespace file
+ out << "};" << endl;
+ out << endl;
+
+ out << "#endif" << endl;
+ out << endl;
+ }
+
+ if (!(category & NoDeclaration)) {
+ QFile outfile(QString::fromLatin1(outname.constData()) + QLatin1String(".h"));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(outfile.fileName()));
+ return false;
+ }
+ QTextStream out(&outfile);
+
+ out << "/****************************************************************************" << endl;
+ out << "**" << endl;
+ out << "** Class declaration generated by dumpcpp" << endl;
+ out << "**" << endl;
+ out << "****************************************************************************/" << endl;
+ out << endl;
+
+ out << "#include <qdatetime.h>" << endl;
+ if (category & ActiveX)
+ out << "#include <qaxwidget.h>" << endl;
+ else
+ out << "#include <qaxobject.h>" << endl;
+ out << endl;
+
+ out << "struct IDispatch;" << endl,
+ out << endl;
+
+ if (!nameSpace.isEmpty()) {
+ out << "#include \"" << nameSpace.toLower() << ".h\"" << endl;
+ out << endl;
+ out << "namespace " << nameSpace << " {" << endl;
+ }
+
+ generateClassDecl(out, object->control(), mo, className, nameSpace, category);
+
+ if (!nameSpace.isEmpty()) {
+ out << endl;
+ out << "};" << endl;
+ }
+ }
+
+ if (!(category & (NoMetaObject|NoImplementation))) {
+ QFile outfile(QString::fromLatin1(outname.constData()) + QLatin1String(".cpp"));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(outfile.fileName()));
+ return false;
+ }
+ QTextStream out(&outfile);
+
+ out << "#include <qmetaobject.h>" << endl;
+ out << "#include \"" << outname << ".h\"" << endl;
+ out << endl;
+
+ if (!nameSpace.isEmpty()) {
+ out << "using namespace " << nameSpace << ";" << endl;
+ out << endl;
+ }
+
+ generateClassImpl(out, mo, className, nameSpace, category);
+ }
+
+ return true;
+}
+
+bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, ObjectCategory category)
+{
+ QString typeLibFile(QString::fromLatin1(typeLib.constData()));
+ typeLibFile = typeLibFile.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ QString cppFile(QString::fromLatin1(outname.constData()));
+
+ ITypeLib *typelib;
+ LoadTypeLibEx(reinterpret_cast<const wchar_t *>(typeLibFile.utf16()), REGKIND_NONE, &typelib);
+ if (!typelib) {
+ qWarning("dumpcpp: loading '%s' as a type library failed", qPrintable(typeLibFile));
+ return false;
+ }
+
+ QString libName;
+ BSTR nameString;
+ typelib->GetDocumentation(-1, &nameString, 0, 0, 0);
+ libName = QString::fromWCharArray(nameString);
+ SysFreeString(nameString);
+ if (!nameSpace.isEmpty())
+ libName = QString(nameSpace);
+
+ QString libVersion(QLatin1String("1.0"));
+
+ TLIBATTR *tlibattr = 0;
+ typelib->GetLibAttr(&tlibattr);
+ if (tlibattr) {
+ libVersion = QString::fromLatin1("%1.%2").arg(tlibattr->wMajorVerNum).arg(tlibattr->wMinorVerNum);
+ typelib->ReleaseTLibAttr(tlibattr);
+ }
+
+ if (cppFile.isEmpty())
+ cppFile = libName.toLower();
+
+ if (cppFile.isEmpty()) {
+ qWarning("dumpcpp: no output filename provided, and cannot deduce output filename");
+ return false;
+ }
+
+ QMetaObject *namespaceObject = qax_readEnumInfo(typelib, 0);
+
+ QFile implFile(cppFile + QLatin1String(".cpp"));
+ QTextStream implOut(&implFile);
+ if (!(category & (NoMetaObject|NoImplementation))) {
+ if (!implFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(implFile.fileName()));
+ return false;
+ }
+
+ implOut << "/****************************************************************************" << endl;
+ implOut << "**" << endl;
+ implOut << "** Metadata for " << libName << " generated by dumpcpp from type library" << endl;
+ implOut << "** " << typeLibFile << endl;
+ implOut << "**" << endl;
+ implOut << "****************************************************************************/" << endl;
+ implOut << endl;
+
+ implOut << "#define QAX_DUMPCPP_" << libName.toUpper() << "_NOINLINES" << endl;
+
+ implOut << "#include \"" << cppFile << ".h\"" << endl;
+ implOut << endl;
+ implOut << "using namespace " << libName << ";" << endl;
+ implOut << endl;
+ }
+
+ QFile declFile(cppFile + QLatin1String(".h"));
+ QTextStream declOut(&declFile);
+ QByteArray classes;
+ QTextStream classesOut(&classes, QIODevice::WriteOnly);
+ QByteArray inlines;
+ QTextStream inlinesOut(&inlines, QIODevice::WriteOnly);
+
+ QMap<QByteArray, QList<QByteArray> > namespaces;
+
+ if(!(category & NoDeclaration)) {
+ if (!declFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(declFile.fileName()));
+ return false;
+ }
+
+ declOut << "/****************************************************************************" << endl;
+ declOut << "**" << endl;
+ declOut << "** Namespace " << libName << " generated by dumpcpp from type library" << endl;
+ declOut << "** " << typeLibFile << endl;
+ declOut << "**" << endl;
+ declOut << "****************************************************************************/" << endl;
+ declOut << endl;
+
+ QFileInfo cppFileInfo(cppFile);
+ writeHeader(declOut, libName.toLatin1(), cppFileInfo.fileName());
+
+ UINT typeCount = typelib->GetTypeInfoCount();
+ if (declFile.isOpen()) {
+ declOut << endl;
+ declOut << "// Referenced namespace" << endl;
+ for (UINT index = 0; index < typeCount; ++index) {
+ ITypeInfo *typeinfo = 0;
+ typelib->GetTypeInfo(index, &typeinfo);
+ if (!typeinfo)
+ continue;
+
+ TYPEATTR *typeattr;
+ typeinfo->GetTypeAttr(&typeattr);
+ if (!typeattr) {
+ typeinfo->Release();
+ continue;
+ }
+
+ TYPEKIND typekind;
+ typelib->GetTypeInfoType(index, &typekind);
+
+ QMetaObject *metaObject = 0;
+
+ // trigger meta object to collect references to other type libraries
+ switch (typekind) {
+ case TKIND_COCLASS:
+ if (category & ActiveX)
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_DISPATCH:
+ if (category & ActiveX)
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_RECORD:
+ case TKIND_ENUM:
+ case TKIND_INTERFACE: // only for forward declarations
+ {
+ QByteArray className;
+ BSTR bstr;
+ if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0))
+ break;
+ className = QString::fromWCharArray(bstr).toLatin1();
+ SysFreeString(bstr);
+ switch (typekind) {
+ case TKIND_RECORD:
+ className = "struct " + className;
+ break;
+ case TKIND_ENUM:
+ className = "enum " + className;
+ break;
+ default:
+ break;
+ }
+ namespaces[libName.toLatin1()].append(className);
+ if (!qax_qualified_usertypes.contains(className))
+ qax_qualified_usertypes << className;
+ }
+ break;
+ default:
+ break;
+ }
+
+ delete metaObject;
+ typeinfo->ReleaseTypeAttr(typeattr);
+ typeinfo->Release();
+ }
+
+ for (int i = 0; i < qax_qualified_usertypes.count(); ++i) {
+ QByteArray refType = qax_qualified_usertypes.at(i);
+ QByteArray refTypeLib;
+ if (refType.contains("::")) {
+ refTypeLib = refType;
+ refType = refType.mid(refType.lastIndexOf("::") + 2);
+ if (refTypeLib.contains(' ')) {
+ refType = refTypeLib.left(refTypeLib.indexOf(' ')) + ' ' + refType;
+ }
+ refTypeLib = refTypeLib.left(refTypeLib.indexOf("::"));
+ refTypeLib = refTypeLib.mid(refTypeLib.lastIndexOf(' ') + 1);
+ namespaces[refTypeLib].append(refType);
+ } else {
+ namespaces[libName.toLatin1()].append(refType);
+ }
+ }
+
+ QList<QByteArray> keys = namespaces.keys();
+ for (int n = 0; n < keys.count(); ++n) {
+ QByteArray nspace = keys.at(n);
+ if (QString::fromLatin1(nspace.constData()) != libName) {
+ declOut << "namespace " << nspace << " {" << endl;
+ QList<QByteArray> classList = namespaces.value(nspace);
+ for (int c = 0; c < classList.count(); ++c) {
+ QByteArray className = classList.at(c);
+ if (className.contains(' ')) {
+ declOut << " " << className << ";" << endl;
+ namespaceForType.insert(className.mid(className.indexOf(' ') + 1), nspace);
+ } else {
+ declOut << " class " << className << ";" << endl;
+ namespaceForType.insert(className, nspace);
+ namespaceForType.insert(className + "*", nspace);
+ }
+ }
+ declOut << "}" << endl << endl;
+ }
+ }
+
+ declOut << endl;
+ }
+ generateNameSpace(declOut, namespaceObject, libName.toLatin1());
+
+ QList<QByteArray> classList = namespaces.value(libName.toLatin1());
+ if (classList.count())
+ declOut << "// forward declarations" << endl;
+ for (int c = 0; c < classList.count(); ++c) {
+ QByteArray className = classList.at(c);
+ if (className.contains(' ')) {
+ declOut << " " << className << ";" << endl;
+ namespaceForType.insert(className.mid(className.indexOf(' ') + 1), libName.toLatin1());
+ } else {
+ declOut << " class " << className << ";" << endl;
+ namespaceForType.insert(className, libName.toLatin1());
+ namespaceForType.insert(className + "*", libName.toLatin1());
+ }
+ }
+
+ declOut << endl;
+ }
+
+ QList<QByteArray> subtypes;
+
+ UINT typeCount = typelib->GetTypeInfoCount();
+ for (UINT index = 0; index < typeCount; ++index) {
+ ITypeInfo *typeinfo = 0;
+ typelib->GetTypeInfo(index, &typeinfo);
+ if (!typeinfo)
+ continue;
+
+ TYPEATTR *typeattr;
+ typeinfo->GetTypeAttr(&typeattr);
+ if (!typeattr) {
+ typeinfo->Release();
+ continue;
+ }
+
+ TYPEKIND typekind;
+ typelib->GetTypeInfoType(index, &typekind);
+
+ uint object_category = category;
+ if (!(typeattr->wTypeFlags & TYPEFLAG_FCANCREATE))
+ object_category |= SubObject;
+ else if (typeattr->wTypeFlags & TYPEFLAG_FCONTROL)
+ object_category |= ActiveX;
+
+ QMetaObject *metaObject = 0;
+ QUuid guid(typeattr->guid);
+
+ if (!(object_category & ActiveX)) {
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID\\") + guid.toString(), QSettings::NativeFormat);
+ if (settings.childGroups().contains(QLatin1String("Control"))) {
+ object_category |= ActiveX;
+ object_category &= ~SubObject;
+ }
+ }
+
+ switch (typekind) {
+ case TKIND_COCLASS:
+ if (object_category & ActiveX)
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_DISPATCH:
+ if (object_category & ActiveX)
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_INTERFACE: // only stub
+ {
+ QByteArray className;
+ BSTR bstr;
+ if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0))
+ break;
+ className = QString::fromWCharArray(bstr).toLatin1();
+ SysFreeString(bstr);
+
+ declOut << "// stub for vtable-only interface" << endl;
+ declOut << "class " << className << " : public QAxObject {};" << endl << endl;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (metaObject) {
+ currentTypeInfo = typeinfo;
+ QByteArray className(metaObject->className());
+ if (!(typeattr->wTypeFlags & TYPEFLAG_FDUAL)
+ && (metaObject->propertyCount() - metaObject->propertyOffset()) == 1
+ && className.contains("Events")) {
+ declOut << "// skipping event interface " << className << endl << endl;
+ } else {
+ if (declFile.isOpen()) {
+ if (typeattr->wTypeFlags & TYPEFLAG_FLICENSED)
+ object_category |= Licensed;
+ if (typekind == TKIND_COCLASS) { // write those later...
+ generateClassDecl(classesOut, guid.toString(), metaObject, className, libName.toLatin1(), (ObjectCategory)(object_category|NoInlines));
+ classesOut << endl;
+ } else {
+ generateClassDecl(declOut, guid.toString(), metaObject, className, libName.toLatin1(), (ObjectCategory)(object_category|NoInlines));
+ declOut << endl;
+ }
+ subtypes << className;
+ generateClassDecl(inlinesOut, guid.toString(), metaObject, className, libName.toLatin1(), (ObjectCategory)(object_category|OnlyInlines));
+ inlinesOut << endl;
+ }
+ if (implFile.isOpen()) {
+ generateClassImpl(implOut, metaObject, className, libName.toLatin1(), (ObjectCategory)object_category);
+ implOut << endl;
+ }
+ }
+ currentTypeInfo = 0;
+ }
+
+ delete metaObject;
+
+ typeinfo->ReleaseTypeAttr(typeattr);
+ typeinfo->Release();
+ }
+
+ delete namespaceObject;
+
+ classesOut.flush();
+ inlinesOut.flush();
+
+ if (declFile.isOpen()) {
+ if (classes.size()) {
+ declOut << "// Actual coclasses" << endl;
+ declOut << classes;
+ }
+ if (inlines.size()) {
+ declOut << "// member function implementation" << endl;
+ declOut << "#ifndef QAX_DUMPCPP_" << libName.toUpper() << "_NOINLINES" << endl;
+ declOut << inlines << endl;
+ declOut << "#endif" << endl << endl;
+ }
+ // close namespace
+ declOut << "}" << endl;
+ declOut << endl;
+
+ // partial template specialization for qMetaTypeConstructHelper
+ for (int t = 0; t < subtypes.count(); ++t) {
+ QByteArray subType(subtypes.at(t));
+ declOut << "template<>" << endl;
+ declOut << "inline void *qMetaTypeConstructHelper(const " << libName << "::" << subType << " *t)" << endl;
+ declOut << "{ Q_ASSERT(!t); return new " << libName << "::" << subType << "; }" << endl;
+ declOut << endl;
+ }
+
+ declOut << "#endif" << endl;
+ declOut << endl;
+ }
+
+ typelib->Release();
+ return true;
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ qax_dispatchEqualsIDispatch = false;
+
+ CoInitialize(0);
+
+ uint category = DefaultObject;
+
+ enum State {
+ Default = 0,
+ Output,
+ NameSpace,
+ GetTypeLib
+ } state;
+ state = Default;
+
+ QByteArray outname;
+ QByteArray typeLib;
+
+ for (int a = 1; a < argc; ++a) {
+ QByteArray arg(argv[a]);
+ const char first = arg[0];
+ switch(state) {
+ case Default:
+ if (first == '-' || first == '/') {
+ arg = arg.mid(1);
+ arg.toLower();
+
+ if (arg == "o") {
+ state = Output;
+ } else if (arg == "n") {
+ state = NameSpace;
+ } else if (arg == "v") {
+ qWarning("dumpcpp: Version 1.0");
+ return 0;
+ } else if (arg == "nometaobject") {
+ category |= NoMetaObject;
+ } else if (arg == "impl") {
+ category |= NoDeclaration;
+ } else if (arg == "decl") {
+ category |= NoImplementation;
+ } else if (arg == "donothing") {
+ category = DoNothing;
+ break;
+ } else if (arg == "compat") {
+ qax_dispatchEqualsIDispatch = true;
+ break;
+ } else if (arg == "getfile") {
+ state = GetTypeLib;
+ break;
+ } else if (arg == "h") {
+ qWarning("dumpcpp Version1.0\n\n"
+ "Generate a C++ namespace from a type library.\n\n"
+ "Usage:\n"
+ "dumpcpp input [-[-n <namespace>] [-o <filename>]\n\n"
+ " input: A type library file, type library ID, ProgID or CLSID\n\n"
+ "Optional parameters:\n"
+ " namespace: The name of the generated C++ namespace\n"
+ " filename: The file name (without extension) of the generated files\n"
+ "\n"
+ "Other parameters:\n"
+ " -nometaobject Don't generate meta object information (no .cpp file)\n"
+ " -impl Only generate the .cpp file\n"
+ " -decl Only generate the .h file\n"
+ " -compat Treat all coclass parameters as IDispatch\n"
+ "\n"
+ "Examples:\n"
+ " dumpcpp Outlook.Application -o outlook\n"
+ " dumpcpp {3B756301-0075-4E40-8BE8-5A81DE2426B7}\n"
+ "\n");
+ return 0;
+ }
+ } else {
+ typeLib = arg;
+ }
+ break;
+
+ case Output:
+ outname = arg;
+ state = Default;
+ break;
+
+ case NameSpace:
+ nameSpace = arg;
+ state = Default;
+ break;
+
+ case GetTypeLib:
+ typeLib = arg;
+ state = Default;
+ category = TypeLibID;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (category == TypeLibID) {
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes\\TypeLib\\") +
+ QString::fromLatin1(typeLib.constData()), QSettings::NativeFormat);
+ typeLib = QByteArray();
+ QStringList codes = settings.childGroups();
+ for (int c = 0; c < codes.count(); ++c) {
+ typeLib = settings.value(QLatin1String("/") + codes.at(c) + QLatin1String("/0/win32/.")).toByteArray();
+ if (QFile::exists(QString::fromLatin1(typeLib))) {
+ break;
+ }
+ }
+
+ if (!typeLib.isEmpty())
+ fprintf(stdout, "\"%s\"\n", typeLib.data());
+ return 0;
+ }
+
+ if (category == DoNothing)
+ return 0;
+
+ if (typeLib.isEmpty()) {
+ qWarning("dumpcpp: No object class or type library name provided.\n"
+ " Use -h for help.");
+ return -1;
+ }
+
+ // not a file - search registry
+ if (!QFile::exists(QString::fromLatin1(typeLib.constData()))) {
+ bool isObject = false;
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"), QSettings::NativeFormat);
+
+ // regular string and not a file - must be ProgID
+ if (typeLib.at(0) != '{') {
+ CLSID clsid;
+ if (CLSIDFromProgID(reinterpret_cast<const wchar_t *>(QString(QLatin1String(typeLib)).utf16()), &clsid) != S_OK) {
+ qWarning("dumpcpp: '%s' is not a type library and not a registered ProgID", typeLib.constData());
+ return -2;
+ }
+ QUuid uuid(clsid);
+ typeLib = uuid.toString().toLatin1();
+ isObject = true;
+ }
+
+ // check if CLSID
+ if (!isObject) {
+ QVariant test = settings.value(QLatin1String("/CLSID/") +
+ QString::fromLatin1(typeLib.constData()) + QLatin1String("/."));
+ isObject = test.isValid();
+ }
+
+ // search typelib ID for CLSID
+ if (isObject)
+ typeLib = settings.value(QLatin1String("/CLSID/") +
+ QString::fromLatin1(typeLib.constData()) + QLatin1String("/Typelib/.")).toByteArray();
+
+ // interpret input as type library ID
+ QString key = QLatin1String("/TypeLib/") + QLatin1String(typeLib);
+ settings.beginGroup(key);
+ QStringList versions = settings.childGroups();
+ QStringList codes;
+ if (versions.count()) {
+ settings.beginGroup(QLatin1String("/") + versions.last());
+ codes = settings.childGroups();
+ key += QLatin1String("/") + versions.last();
+ settings.endGroup();
+ }
+ settings.endGroup();
+
+ for (int c = 0; c < codes.count(); ++c) {
+ typeLib = settings.value(key + QLatin1String("/") + codes.at(c) + QLatin1String("/win32/.")).toByteArray();
+ if (QFile::exists(QString::fromLatin1(typeLib.constData()))) {
+ break;
+ }
+ }
+ }
+
+ if (!QFile::exists(QString::fromLatin1(typeLib.constData()))) {
+ qWarning("dumpcpp: type library '%s' not found", typeLib.constData());
+ return -2;
+ }
+
+ if (!generateTypeLibrary(typeLib, outname, (ObjectCategory)category)) {
+ qWarning("dumpcpp: error processing type library '%s'", typeLib.constData());
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tools/dumpdoc/dumpdoc.pro b/tools/dumpdoc/dumpdoc.pro
new file mode 100644
index 0000000..3c93525
--- /dev/null
+++ b/tools/dumpdoc/dumpdoc.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+
+CONFIG += console qaxcontainer
+
+SOURCES += main.cpp
diff --git a/tools/dumpdoc/main.cpp b/tools/dumpdoc/main.cpp
new file mode 100644
index 0000000..ae1f60f
--- /dev/null
+++ b/tools/dumpdoc/main.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QAxObject>
+#include <QFile>
+#include <QTextStream>
+#include <qt_windows.h>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ CoInitialize(0);
+
+ enum State {
+ Default = 0,
+ OutOption
+ } state;
+ state = Default;
+
+ QByteArray outname;
+ QByteArray object;
+
+ for (int a = 1; a < argc; ++a) {
+ QByteArray arg(argv[a]);
+ const char first = arg[0];
+ switch(state) {
+ case Default:
+ if (first == '-' || first == '/') {
+ arg = arg.mid(1);
+ arg.toLower();
+ if (arg == "o")
+ state = OutOption;
+ else if (arg == "v") {
+ qWarning("dumpdoc: Version 1.0");
+ return 0;
+ } else if (arg == "h") {
+ qWarning("dumpdoc Usage:\n\tdumpdoc object [-o <file>]"
+ " \n\tobject : object[/subobject]*"
+ " \n\tsubobject: property\n"
+ " \nexample:\n\tdumpdoc Outlook.Application/Session/CurrentUser -o outlook.html");
+ return 0;
+ }
+ } else {
+ object = arg;
+ }
+ break;
+ case OutOption:
+ outname = arg;
+ state = Default;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (object.isEmpty()) {
+ qWarning("dumpdoc: No object name provided.\n"
+ " Use -h for help.");
+ return -1;
+ }
+ QFile outfile;
+ if (!outname.isEmpty()) {
+ outfile.setFileName(QString::fromLatin1(outname.constData()));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpdoc: Could not open output file '%s'", outname.data());
+ }
+ } else {
+ outfile.open(stdout, QIODevice::WriteOnly);
+ }
+ QTextStream out(&outfile);
+
+ QByteArray subobject = object;
+ int index = subobject.indexOf('/');
+ if (index != -1)
+ subobject = subobject.left(index);
+
+ QAxObject topobject(QString::fromLatin1(subobject.constData()));
+
+ if (topobject.isNull()) {
+ qWarning("dumpdoc: Could not instantiate COM object '%s'", subobject.data());
+ return -2;
+ }
+
+ QAxObject *axobject = &topobject;
+ while (index != -1 && axobject) {
+ index++;
+ subobject = object.mid(index);
+ if (object.indexOf('/', index) != -1) {
+ int oldindex = index;
+ index = object.indexOf('/', index);
+ subobject = object.mid(oldindex, index-oldindex);
+ } else {
+ index = -1;
+ }
+
+ axobject = axobject->querySubObject(subobject);
+ }
+ if (!axobject || axobject->isNull()) {
+ qWarning("dumpdoc: Subobject '%s' does not exist in '%s'", subobject.data(), object.data());
+ return -3;
+ }
+
+ QString docu = axobject->generateDocumentation();
+ out << docu;
+ return 0;
+}
diff --git a/tools/testcon/ambientproperties.cpp b/tools/testcon/ambientproperties.cpp
new file mode 100644
index 0000000..f0bc017
--- /dev/null
+++ b/tools/testcon/ambientproperties.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ambientproperties.h"
+
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+
+AmbientProperties::AmbientProperties(QWidget *parent)
+: QDialog(parent), container(0)
+{
+ setupUi(this);
+
+ connect(buttonClose, SIGNAL(clicked()), this, SLOT(close()));
+}
+
+void AmbientProperties::setControl(QWidget *widget)
+{
+ container = widget;
+
+ QColor c = container->palette().color(container->backgroundRole());
+ QPalette p = backSample->palette(); p.setColor(backSample->backgroundRole(), c); backSample->setPalette(p);
+
+ c = container->palette().color(container->foregroundRole());
+ p = foreSample->palette(); p.setColor(foreSample->backgroundRole(), c); foreSample->setPalette(p);
+
+ fontSample->setFont( container->font() );
+ buttonEnabled->setChecked( container->isEnabled() );
+ enabledSample->setEnabled( container->isEnabled() );
+}
+
+void AmbientProperties::on_buttonBackground_clicked()
+{
+ QColor c = QColorDialog::getColor(backSample->palette().color(backSample->backgroundRole()), this);
+ QPalette p = backSample->palette(); p.setColor(backSample->backgroundRole(), c); backSample->setPalette(p);
+ p = container->palette(); p.setColor(container->backgroundRole(), c); container->setPalette(p);
+
+ if (QWorkspace *ws = qobject_cast<QWorkspace*>(container)) {
+ QWidgetList list( ws->windowList() );
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ p = widget->palette(); p.setColor(widget->backgroundRole(), c); widget->setPalette(p);
+ }
+ }
+}
+
+void AmbientProperties::on_buttonForeground_clicked()
+{
+ QColor c = QColorDialog::getColor(foreSample->palette().color(foreSample->backgroundRole()), this);
+ QPalette p = foreSample->palette(); p.setColor(foreSample->backgroundRole(), c); foreSample->setPalette(p);
+ p = container->palette(); p.setColor(container->foregroundRole(), c); container->setPalette(p);
+
+ if (QWorkspace *ws = qobject_cast<QWorkspace*>(container)) {
+ QWidgetList list( ws->windowList() );
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ p = widget->palette(); p.setColor(widget->foregroundRole(), c); widget->setPalette(p);
+ }
+ }
+}
+
+void AmbientProperties::on_buttonFont_clicked()
+{
+ bool ok;
+ QFont f = QFontDialog::getFont( &ok, fontSample->font(), this );
+ if ( !ok )
+ return;
+ fontSample->setFont( f );
+ container->setFont( f );
+
+ if (QWorkspace *ws = qobject_cast<QWorkspace*>(container)) {
+ QWidgetList list( ws->windowList() );
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ widget->setFont( f );
+ }
+ }
+}
+
+void AmbientProperties::on_buttonEnabled_toggled(bool on)
+{
+ enabledSample->setEnabled( on );
+ container->setEnabled( on );
+}
+
+QT_END_NAMESPACE
diff --git a/tools/testcon/ambientproperties.h b/tools/testcon/ambientproperties.h
new file mode 100644
index 0000000..501ad8f
--- /dev/null
+++ b/tools/testcon/ambientproperties.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AMBIENTPROPERTIES_H
+#define AMBIENTPROPERTIES_H
+
+#include <QtCore/qglobal.h>
+
+#include "ui_ambientproperties.h"
+
+QT_BEGIN_NAMESPACE
+
+class AmbientProperties : public QDialog, Ui::AmbientProperties
+{
+ Q_OBJECT
+public:
+ AmbientProperties(QWidget *parent);
+
+ void setControl(QWidget *widget);
+
+public slots:
+ void on_buttonBackground_clicked();
+ void on_buttonForeground_clicked();
+ void on_buttonFont_clicked();
+ void on_buttonEnabled_toggled(bool on);
+
+private:
+ QWidget *container;
+};
+
+QT_END_NAMESPACE
+
+#endif // AMBIENTPROPERTIES_H
diff --git a/tools/testcon/ambientproperties.ui b/tools/testcon/ambientproperties.ui
new file mode 100644
index 0000000..502c3b2
--- /dev/null
+++ b/tools/testcon/ambientproperties.ui
@@ -0,0 +1,299 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>AmbientProperties</class>
+ <widget class="QDialog" name="AmbientProperties" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>185</width>
+ <height>173</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Change Ambient Properties</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="boxProperties" >
+ <property name="title" >
+ <string>&amp;Properties</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="text" >
+ <string>Background:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="TextLabel2" >
+ <property name="text" >
+ <string>Foreground:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="TextLabel3" >
+ <property name="text" >
+ <string>Font:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="TextLabel4" >
+ <property name="text" >
+ <string>Enabled:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QFrame" name="foreSample" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QFrame" name="backSample" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QToolButton" name="buttonBackground" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QToolButton" name="buttonForeground" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QToolButton" name="buttonFont" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QFrame" name="Frame6" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="enabledSample" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>&lt;sample></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="2" >
+ <widget class="QToolButton" name="buttonEnabled" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QFrame" name="fontSample" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="TextLabel6" >
+ <property name="text" >
+ <string>&lt;sample></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>1</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>AmbientProperties</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>141</x>
+ <y>150</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>51</x>
+ <y>141</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/testcon/changeproperties.cpp b/tools/testcon/changeproperties.cpp
new file mode 100644
index 0000000..ef896b6
--- /dev/null
+++ b/tools/testcon/changeproperties.cpp
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "changeproperties.h"
+
+#include <QtGui>
+#include <qt_windows.h>
+#include <ActiveQt/ActiveQt>
+
+QT_BEGIN_NAMESPACE
+
+ChangeProperties::ChangeProperties(QWidget *parent)
+: QDialog(parent), activex(0)
+{
+ setupUi(this);
+
+ listProperties->setColumnCount(3);
+ listProperties->headerItem()->setText(0, QLatin1String("Name"));
+ listProperties->headerItem()->setText(1, QLatin1String("Type"));
+ listProperties->headerItem()->setText(2, QLatin1String("Value"));
+
+ listEditRequests->setColumnCount(1);
+ listEditRequests->headerItem()->setText(0, QLatin1String("Name"));
+}
+
+void ChangeProperties::setControl(QAxWidget *ax)
+{
+ activex = ax;
+ updateProperties();
+}
+
+void ChangeProperties::on_listProperties_currentItemChanged(QTreeWidgetItem *current)
+{
+ editValue->setEnabled(current != 0);
+ buttonSet->setEnabled(current != 0);
+ valueLabel->setEnabled(current != 0);
+
+ if (!current)
+ return;
+
+ editValue->setText(current->text(2));
+ QString prop = current->text(0);
+ valueLabel->setText(prop + QLatin1String(" ="));
+
+ const QMetaObject *mo = activex->metaObject();
+ const QMetaProperty property = mo->property(mo->indexOfProperty(prop.toLatin1()));
+
+ valueLabel->setEnabled(property.isWritable());
+ editValue->setEnabled(property.isWritable());
+ buttonSet->setEnabled(property.isWritable());
+}
+
+void ChangeProperties::on_buttonSet_clicked()
+{
+ QTreeWidgetItem *item = listProperties->currentItem();
+ if (!item)
+ return;
+
+ QString prop = item->text(0);
+ QVariant value = activex->property(prop.toLatin1());
+ QVariant::Type type = value.type();
+ if (!value.isValid()) {
+ const QMetaObject *mo = activex->metaObject();
+ const QMetaProperty property = mo->property(mo->indexOfProperty(prop.toLatin1()));
+ type = QVariant::nameToType(property.typeName());
+ }
+ switch (type) {
+ case QVariant::Color:
+ {
+ QColor col;
+ col.setNamedColor(editValue->text());
+ if (col.isValid()) {
+ value = QVariant::fromValue(col);
+ } else {
+ QMessageBox::warning(this, tr("Can't parse input"),
+ tr("Failed to create a color from %1\n"
+ "The string has to be a valid color name (e.g. 'red')\n"
+ "or a RGB triple of format '#rrggbb'."
+ ).arg(editValue->text()));
+ }
+ }
+ break;
+ case QVariant::Font:
+ {
+ QFont fnt;
+ if (fnt.fromString(editValue->text())) {
+ value = QVariant::fromValue(fnt);
+ } else {
+ QMessageBox::warning(this, tr("Can't parse input"),
+ tr("Failed to create a font from %1\n"
+ "The string has to have a format family,<point size> or\n"
+ "family,pointsize,stylehint,weight,italic,underline,strikeout,fixedpitch,rawmode."
+ ).arg(editValue->text()));
+ }
+ }
+ break;
+ case QVariant::Pixmap:
+ {
+ QString fileName = editValue->text();
+ if (fileName.isEmpty())
+ fileName = QFileDialog::getOpenFileName(this);
+ QPixmap pm(fileName);
+ if (pm.isNull())
+ return;
+
+ value = QVariant::fromValue(pm);
+ }
+ break;
+ case QVariant::Bool:
+ {
+ QString txt = editValue->text().toLower();
+ value = QVariant(txt != QLatin1String("0") && txt != QLatin1String("false"));
+ }
+ break;
+ case QVariant::List:
+ {
+ QStringList txtList = editValue->text().split(QRegExp(QLatin1String("[,;]")));
+ QList<QVariant> varList;
+ for (int i = 0; i < txtList.count(); ++i) {
+ QVariant svar(txtList.at(i));
+ QString str = svar.toString();
+ str = str.trimmed();
+ bool ok;
+ int n = str.toInt(&ok);
+ if (ok) {
+ varList << n;
+ continue;
+ }
+ double d = str.toDouble(&ok);
+ if (ok) {
+ varList << d;
+ continue;
+ }
+ varList << str;
+ }
+ value = varList;
+ }
+ break;
+
+ default:
+ value = editValue->text();
+ break;
+ }
+
+ Q_ASSERT(activex->setProperty(prop.toLatin1(), value));
+ updateProperties();
+ listProperties->setCurrentItem(listProperties->findItems(prop, Qt::MatchExactly).at(0));
+}
+
+void ChangeProperties::on_listEditRequests_itemChanged(QTreeWidgetItem *item)
+{
+ if (!item)
+ return;
+
+ QString property = item->text(0);
+ activex->setPropertyWritable(property.toLatin1(), item->checkState(0) == Qt::Checked);
+}
+
+
+void ChangeProperties::updateProperties()
+{
+ bool hasControl = activex && !activex->isNull();
+ tabWidget->setEnabled(hasControl);
+
+ listProperties->clear();
+ listEditRequests->clear();
+ if (hasControl) {
+ const QMetaObject *mo = activex->metaObject();
+ const int numprops = mo->propertyCount();
+ for (int i = mo->propertyOffset(); i < numprops; ++i) {
+ const QMetaProperty property = mo->property(i);
+ QTreeWidgetItem *item = new QTreeWidgetItem(listProperties);
+ item->setText(0, QString::fromLatin1(property.name()));
+ item->setText(1, QString::fromLatin1(property.typeName()));
+ if (!property.isDesignable()) {
+ item->setTextColor(0, Qt::gray);
+ item->setTextColor(1, Qt::gray);
+ item->setTextColor(2, Qt::gray);
+ }
+ QVariant var = activex->property(property.name());
+
+ switch (var.type()) {
+ case QVariant::Color:
+ {
+ QColor col = qvariant_cast<QColor>(var);
+ item->setText(2, col.name());
+ }
+ break;
+ case QVariant::Font:
+ {
+ QFont fnt = qvariant_cast<QFont>(var);
+ item->setText(2, fnt.toString());
+ }
+ break;
+ case QVariant::Bool:
+ {
+ item->setText(2, var.toBool() ? QLatin1String("true") : QLatin1String("false"));
+ }
+ break;
+ case QVariant::Pixmap:
+ {
+ QPixmap pm = qvariant_cast<QPixmap>(var);
+ item->setIcon(2, pm);
+ }
+ break;
+ case QVariant::List:
+ {
+ QList<QVariant> varList = var.toList();
+ QStringList strList;
+ for (int i = 0; i < varList.count(); ++i) {
+ QVariant var = varList.at(i);
+ strList << var.toString();
+ }
+ item->setText(2, strList.join(QLatin1String(", ")));
+ }
+ break;
+ case QVariant::Int:
+ if (property.isEnumType()) {
+ const QMetaEnum enumerator = mo->enumerator(mo->indexOfEnumerator(property.typeName()));
+ item->setText(2, QString::fromLatin1(enumerator.valueToKey(var.toInt())));
+ break;
+ }
+ //FALLTHROUGH
+ default:
+ item->setText(2, var.toString());
+ break;
+ }
+
+ bool requesting = false;
+#if 0
+ {
+ void *argv[] = { &requesting };
+ activex->qt_metacall(QMetaObject::Call(0x10000000) /*RequestingEdit*/, i, argv);
+ }
+#endif
+ if (requesting) {
+ QTreeWidgetItem *check = new QTreeWidgetItem(listEditRequests);
+ check->setText(0, QString::fromLatin1(property.name()));
+ check->setCheckState(0, activex->propertyWritable(property.name()) ? Qt::Checked : Qt::Unchecked);
+ }
+ }
+ listProperties->setCurrentItem(listProperties->topLevelItem(0));
+ } else {
+ editValue->clear();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/testcon/changeproperties.h b/tools/testcon/changeproperties.h
new file mode 100644
index 0000000..c08e933
--- /dev/null
+++ b/tools/testcon/changeproperties.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CHANGEPROPERTIES_H
+#define CHANGEPROPERTIES_H
+
+#include <QtCore/qglobal.h>
+#include "ui_changeproperties.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAxWidget;
+
+class ChangeProperties : public QDialog, Ui::ChangeProperties
+{
+ Q_OBJECT
+public:
+ ChangeProperties(QWidget *parent);
+
+ void setControl(QAxWidget *control);
+
+public slots:
+ void updateProperties();
+
+protected slots:
+ void on_listProperties_currentItemChanged(QTreeWidgetItem *current);
+ void on_listEditRequests_itemChanged(QTreeWidgetItem *item);
+ void on_buttonSet_clicked();
+
+private:
+ QAxWidget *activex;
+};
+
+QT_END_NAMESPACE
+
+#endif // CHANGEPROPERTIES_H
diff --git a/tools/testcon/changeproperties.ui b/tools/testcon/changeproperties.ui
new file mode 100644
index 0000000..ef98f5c
--- /dev/null
+++ b/tools/testcon/changeproperties.ui
@@ -0,0 +1,211 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>ChangeProperties</class>
+ <widget class="QDialog" name="ChangeProperties" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>728</width>
+ <height>584</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Change Control Properties</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget" >
+ <widget class="QWidget" name="propertiesTab" >
+ <attribute name="title" >
+ <string>&amp;Properties</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listProperties" >
+ <property name="rootIsDecorated" >
+ <bool>false</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Property</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Type</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="valueLabel" >
+ <property name="text" >
+ <string>Property &amp;Value:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>editValue</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="editValue" />
+ </item>
+ <item>
+ <widget class="QToolButton" name="buttonSet" >
+ <property name="text" >
+ <string>&amp;Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="requestTab" >
+ <attribute name="title" >
+ <string>Property Edit &amp;Requests</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listEditRequests" >
+ <column>
+ <property name="text" >
+ <string>Property</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>1</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>ChangeProperties</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>669</x>
+ <y>558</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>566</x>
+ <y>551</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/testcon/controlinfo.cpp b/tools/testcon/controlinfo.cpp
new file mode 100644
index 0000000..7b9dbb7
--- /dev/null
+++ b/tools/testcon/controlinfo.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "controlinfo.h"
+
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+
+ControlInfo::ControlInfo(QWidget *parent)
+ : QDialog(parent)
+{
+ setupUi(this);
+
+ listInfo->setColumnCount(2);
+ listInfo->headerItem()->setText(0, tr("Item"));
+ listInfo->headerItem()->setText(1, tr("Details"));
+}
+
+void ControlInfo::setControl(QWidget *activex)
+{
+ listInfo->clear();
+
+ const QMetaObject *mo = activex->metaObject();
+ QTreeWidgetItem *group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Class Info"));
+ group->setText(1, QString::number(mo->classInfoCount()));
+
+ QTreeWidgetItem *item = 0;
+ int i;
+ int count;
+ for (i = mo->classInfoOffset(); i < mo->classInfoCount(); ++i) {
+ const QMetaClassInfo info = mo->classInfo(i);
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(info.name()));
+ item->setText(1, QString::fromLatin1(info.value()));
+ }
+ group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Signals"));
+
+ count = 0;
+ for (i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Signal) {
+ ++count;
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(method.signature()));
+ }
+ }
+ group->setText(1, QString::number(count));
+
+ group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Slots"));
+
+ count = 0;
+ for (i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Slot) {
+ ++count;
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(method.signature()));
+ }
+ }
+ group->setText(1, QString::number(count));
+
+ group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Properties"));
+
+ count = 0;
+ for (i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
+ ++count;
+ const QMetaProperty property = mo->property(i);
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(property.name()));
+ item->setText(1, QString::fromLatin1(property.typeName()));
+ if (!property.isDesignable()) {
+ item->setTextColor(0, Qt::gray);
+ item->setTextColor(1, Qt::gray);
+ }
+ }
+ group->setText(1, QString::number(count));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/testcon/controlinfo.h b/tools/testcon/controlinfo.h
new file mode 100644
index 0000000..6f7c356
--- /dev/null
+++ b/tools/testcon/controlinfo.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONTROLINFO_H
+#define CONTROLINFO_H
+
+#include <QtCore/qglobal.h>
+#include "ui_controlinfo.h"
+
+QT_BEGIN_NAMESPACE
+
+class ControlInfo : public QDialog, Ui::ControlInfo
+{
+ Q_OBJECT
+public:
+ ControlInfo(QWidget *parent);
+
+ void setControl(QWidget *activex);
+};
+
+QT_END_NAMESPACE
+
+#endif // CONTROLINFO_H
diff --git a/tools/testcon/controlinfo.ui b/tools/testcon/controlinfo.ui
new file mode 100644
index 0000000..905ef43
--- /dev/null
+++ b/tools/testcon/controlinfo.ui
@@ -0,0 +1,134 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>ControlInfo</class>
+ <widget class="QDialog" name="ControlInfo" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Control Details</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listInfo" >
+ <column>
+ <property name="text" >
+ <string>Item</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>1</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>ControlInfo</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>536</x>
+ <y>457</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>428</x>
+ <y>449</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/testcon/docuwindow.cpp b/tools/testcon/docuwindow.cpp
new file mode 100644
index 0000000..14459b5
--- /dev/null
+++ b/tools/testcon/docuwindow.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "docuwindow.h"
+#include <QTextBrowser>
+#include <QTextDocument>
+#include <QToolBar>
+#include <QToolButton>
+#include <QFileDialog>
+#include <QFile>
+#include <QStatusBar>
+#include <QPrinter>
+#include <QPainter>
+#include <QPrintDialog>
+#include <QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+static const char *filesave[] = {
+" 14 14 4 1",
+". c #040404",
+"# c #808304",
+"a c #bfc2bf",
+"b c None",
+"..............",
+".#.aaaaaaaa.a.",
+".#.aaaaaaaa...",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".##........##.",
+".############.",
+".##.........#.",
+".##......aa.#.",
+".##......aa.#.",
+".##......aa.#.",
+"b............."
+};
+
+static const char *fileprint[] = {
+" 16 14 6 1",
+". c #000000",
+"# c #848284",
+"a c #c6c3c6",
+"b c #ffff00",
+"c c #ffffff",
+"d c None",
+"ddddd.........dd",
+"dddd.cccccccc.dd",
+"dddd.c.....c.ddd",
+"ddd.cccccccc.ddd",
+"ddd.c.....c....d",
+"dd.cccccccc.a.a.",
+"d..........a.a..",
+".aaaaaaaaaa.a.a.",
+".............aa.",
+".aaaaaa###aa.a.d",
+".aaaaaabbbaa...d",
+".............a.d",
+"d.aaaaaaaaa.a.dd",
+"dd...........ddd"
+};
+
+
+DocuWindow::DocuWindow(const QString& docu, QWidget *parent, QWidget *source)
+ : QMainWindow(parent)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle(tr("%1 - Documentation").arg(source->windowTitle()));
+
+ browser = new QTextBrowser(this);
+ browser->setHtml(docu);
+
+ setCentralWidget(browser);
+
+ QToolBar *fileTools = new QToolBar(tr("File Operations"), this);
+ fileTools->addAction(QPixmap(filesave), tr("Save File"), this, SLOT(save()));
+ fileTools->addAction(QPixmap(fileprint), tr("Print"), this, SLOT(print()));
+
+ addToolBar(fileTools);
+ statusBar();
+}
+
+void DocuWindow::save()
+{
+ QString filename = QFileDialog::getSaveFileName(this);
+
+ if (filename.isEmpty())
+ return;
+
+ QString text = browser->document()->toHtml();
+ QFile f(filename);
+ if (!f.open(QIODevice::WriteOnly)) {
+ statusBar()->showMessage(tr("Could not write to %1").arg(filename), 2000);
+ return;
+ }
+
+ QTextStream t(&f);
+ t << text;
+ f.close();
+
+ statusBar()->showMessage(tr("File %1 saved").arg(filename), 2000);
+}
+
+void DocuWindow::print()
+{
+ QPrinter printer;
+ if (printer.printerName().isEmpty()) {
+ statusBar()->showMessage(tr("No printer installed"), 2000);
+ return;
+ }
+
+ QPrintDialog printDialog(&printer, this);
+ if (!printDialog.exec()) {
+ statusBar()->showMessage(tr("Printing aborted"), 2000);
+ return;
+ }
+
+ browser->document()->print(&printer);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/testcon/docuwindow.h b/tools/testcon/docuwindow.h
new file mode 100644
index 0000000..727534e
--- /dev/null
+++ b/tools/testcon/docuwindow.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DOCUWINDOW_H
+#define DOCUWINDOW_H
+
+#include <QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+class QTextBrowser;
+
+class DocuWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ DocuWindow( const QString& docu, QWidget *parent, QWidget *source );
+
+public slots:
+ void save();
+ void print();
+
+private:
+ QTextBrowser *browser;
+};
+
+QT_END_NAMESPACE
+
+#endif // DOCUWINDOW_H
diff --git a/tools/testcon/invokemethod.cpp b/tools/testcon/invokemethod.cpp
new file mode 100644
index 0000000..4e2be1a
--- /dev/null
+++ b/tools/testcon/invokemethod.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "invokemethod.h"
+
+#include <qt_windows.h>
+#include <ActiveQt/ActiveQt>
+
+QT_BEGIN_NAMESPACE
+
+InvokeMethod::InvokeMethod(QWidget *parent)
+: QDialog(parent), activex(0)
+{
+ setupUi(this);
+
+ listParameters->setColumnCount(3);
+ listParameters->headerItem()->setText(0, tr("Parameter"));
+ listParameters->headerItem()->setText(1, tr("Type"));
+ listParameters->headerItem()->setText(2, tr("Value"));
+}
+
+void InvokeMethod::setControl(QAxBase *ax)
+{
+ activex = ax;
+ bool hasControl = activex && !activex->isNull();
+ labelMethods->setEnabled(hasControl);
+ comboMethods->setEnabled(hasControl);
+ buttonInvoke->setEnabled(hasControl);
+ boxParameters->setEnabled(hasControl);
+
+ comboMethods->clear();
+ listParameters->clear();
+
+ if (!hasControl) {
+ editValue->clear();
+ return;
+ }
+
+ const QMetaObject *mo = activex->metaObject();
+ if (mo->methodCount()) {
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Slot)
+ comboMethods->addItem(QString::fromLatin1(method.signature()));
+ }
+ comboMethods->model()->sort(0);
+
+ on_comboMethods_activated(comboMethods->currentText());
+ }
+}
+
+void InvokeMethod::on_buttonInvoke_clicked()
+{
+ if (!activex)
+ return;
+
+ on_buttonSet_clicked();
+ QString method = comboMethods->currentText();
+ QList<QVariant> vars;
+
+ int itemCount = listParameters->topLevelItemCount();
+ for (int i = 0; i < itemCount; ++i) {
+ QTreeWidgetItem *parameter = listParameters->topLevelItem(i);
+ vars << parameter->text(2);
+ }
+ QVariant result = activex->dynamicCall(method.toLatin1(), vars);
+
+ int v = 0;
+ for (int i = 0; i < itemCount; ++i) {
+ QTreeWidgetItem *parameter = listParameters->topLevelItem(i);
+ parameter->setText(2, vars[v++].toString());
+ }
+
+ QString resString = result.toString();
+ QString resType = QString::fromLatin1(result.typeName());
+ editReturn->setText(resType + QLatin1String(" ") + resString);
+}
+
+void InvokeMethod::on_comboMethods_activated(const QString &method)
+{
+ if (!activex)
+ return;
+ listParameters->clear();
+
+ const QMetaObject *mo = activex->metaObject();
+ const QMetaMethod slot = mo->method(mo->indexOfSlot(method.toLatin1()));
+ QString signature = QString::fromLatin1(slot.signature());
+ signature = signature.mid(signature.indexOf(QLatin1Char('(')) + 1);
+ signature.truncate(signature.length()-1);
+
+ QList<QByteArray> pnames = slot.parameterNames();
+ QList<QByteArray> ptypes = slot.parameterTypes();
+
+ for (int p = 0; p < ptypes.count(); ++p) {
+ QString ptype(QString::fromLatin1(ptypes.at(p)));
+ if (ptype.isEmpty())
+ continue;
+ QString pname(QString::fromLatin1(pnames.at(p).constData()));
+ if (pname.isEmpty())
+ pname = QString::fromLatin1("<unnamed %1>").arg(p);
+ QTreeWidgetItem *item = new QTreeWidgetItem(listParameters);
+ item->setText(0, pname);
+ item->setText(1, ptype);
+ }
+
+ if (listParameters->topLevelItemCount())
+ listParameters->setCurrentItem(listParameters->topLevelItem(0));
+ editReturn->setText(QString::fromLatin1(slot.typeName()));
+}
+
+void InvokeMethod::on_listParameters_currentItemChanged(QTreeWidgetItem *item)
+{
+ if (!activex)
+ return;
+ editValue->setEnabled(item != 0);
+ buttonSet->setEnabled(item != 0);
+ if (!item)
+ return;
+ editValue->setText(item->text(2));
+}
+
+void InvokeMethod::on_buttonSet_clicked()
+{
+ if (!activex)
+ return;
+ QTreeWidgetItem *item = listParameters->currentItem();
+ if (!item)
+ return;
+ item->setText(2, editValue->text());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/testcon/invokemethod.h b/tools/testcon/invokemethod.h
new file mode 100644
index 0000000..cbaaa0d
--- /dev/null
+++ b/tools/testcon/invokemethod.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INVOKEMETHOD_H
+#define INVOKEMETHOD_H
+
+#include <QtCore/qglobal.h>
+#include "ui_invokemethod.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAxBase;
+
+class InvokeMethod : public QDialog, Ui::InvokeMethod
+{
+ Q_OBJECT
+public:
+ InvokeMethod(QWidget *parent);
+
+ void setControl(QAxBase *ax);
+
+protected slots:
+ void on_buttonInvoke_clicked();
+ void on_buttonSet_clicked();
+
+ void on_comboMethods_activated(const QString &method);
+ void on_listParameters_currentItemChanged(QTreeWidgetItem *item);
+
+private:
+ QAxBase *activex;
+};
+
+QT_END_NAMESPACE
+
+#endif // INVOKEMETHOD_H
diff --git a/tools/testcon/invokemethod.ui b/tools/testcon/invokemethod.ui
new file mode 100644
index 0000000..f912b06
--- /dev/null
+++ b/tools/testcon/invokemethod.ui
@@ -0,0 +1,270 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>InvokeMethod</class>
+ <widget class="QDialog" name="InvokeMethod" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>503</width>
+ <height>416</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Invoke Methods</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="1" column="0" colspan="2" >
+ <widget class="QGroupBox" name="boxParameters" >
+ <property name="title" >
+ <string>&amp;Parameter List</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" colspan="3" >
+ <widget class="QTreeWidget" name="listParameters" >
+ <property name="rootIsDecorated" >
+ <bool>false</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Parameter</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Type</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QToolButton" name="buttonSet" >
+ <property name="text" >
+ <string>&amp;Set</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="editValue" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="TextLabel3" >
+ <property name="text" >
+ <string>Parameter &amp;Value:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>editValue</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2" >
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="editReturn" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QComboBox" name="comboMethods" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable" >
+ <bool>true</bool>
+ </property>
+ <property name="insertPolicy" >
+ <enum>QComboBox::NoInsert</enum>
+ </property>
+ <property name="autoCompletion" >
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="labelMethods" >
+ <property name="text" >
+ <string>&amp;Method Name:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>comboMethods</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Preferred</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="text" >
+ <string>Returned Value:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" >
+ <widget class="QPushButton" name="buttonInvoke" >
+ <property name="text" >
+ <string>&amp;Invoke</string>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>111</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>361</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>InvokeMethod</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>453</x>
+ <y>396</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>327</x>
+ <y>384</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/testcon/main.cpp b/tools/testcon/main.cpp
new file mode 100644
index 0000000..39887c2
--- /dev/null
+++ b/tools/testcon/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QAxFactory>
+
+QAXFACTORY_DEFAULT(MainWindow,
+ QLatin1String("{5f5ce700-48a8-47b1-9b06-3b7f79e41d7c}"),
+ QLatin1String("{3fc86f5f-8b15-4428-8f6b-482bae91f1ae}"),
+ QLatin1String("{02a268cd-24b4-4fd9-88ff-b01b683ef39d}"),
+ QLatin1String("{4a43e44d-9d1d-47e5-a1e5-58fe6f7be0a4}"),
+ QLatin1String("{16ee5998-77d2-412f-ad91-8596e29f123f}"))
+
+QT_USE_NAMESPACE
+
+int main( int argc, char **argv )
+{
+ QApplication app( argc, argv );
+
+ MainWindow mw;
+ mw.show();
+
+ return app.exec();;
+}
diff --git a/tools/testcon/mainwindow.cpp b/tools/testcon/mainwindow.cpp
new file mode 100644
index 0000000..2090c19
--- /dev/null
+++ b/tools/testcon/mainwindow.cpp
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "changeproperties.h"
+#include "invokemethod.h"
+#include "ambientproperties.h"
+#include "controlinfo.h"
+#include "docuwindow.h"
+
+#include <QtGui>
+#include <qt_windows.h>
+#include <ActiveQt/ActiveQt>
+
+QT_BEGIN_NAMESPACE
+
+QAxObject *ax_mainWindow = 0;
+
+static QTextEdit *debuglog = 0;
+
+static void redirectDebugOutput(QtMsgType type, const char*msg)
+{
+ Q_UNUSED(type);
+ debuglog->append(QLatin1String(msg));
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+{
+ setupUi(this);
+ setObjectName(QLatin1String("MainWindow"));
+
+ QAxScriptManager::registerEngine(QLatin1String("PerlScript"), QLatin1String(".pl"));
+ QAxScriptManager::registerEngine(QLatin1String("Python"), QLatin1String(".py"));
+
+ dlgInvoke = 0;
+ dlgProperties = 0;
+ dlgAmbient = 0;
+ scripts = 0;
+ debuglog = logDebug;
+ oldDebugHandler = qInstallMsgHandler(redirectDebugOutput);
+ QHBoxLayout *layout = new QHBoxLayout(Workbase);
+ workspace = new QWorkspace(Workbase);
+ layout->addWidget(workspace);
+ layout->setMargin(0);
+
+ connect(workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(updateGUI()));
+ connect(actionFileExit, SIGNAL(triggered()), qApp, SLOT(quit()));
+}
+
+MainWindow::~MainWindow()
+{
+ qInstallMsgHandler(oldDebugHandler);
+ debuglog = 0;
+}
+
+
+void MainWindow::on_actionFileNew_triggered()
+{
+ QAxSelect select(this);
+ if (select.exec()) {
+ QAxWidget *container = new QAxWidget(workspace);
+ container->setAttribute(Qt::WA_DeleteOnClose);
+ container->setControl(select.clsid());
+ container->setObjectName(container->windowTitle());
+ workspace->addWindow(container);
+ container->show();
+ }
+ updateGUI();
+}
+
+void MainWindow::on_actionFileLoad_triggered()
+{
+ QString fname = QFileDialog::getOpenFileName(this, tr("Load"), QString(), QLatin1String("*.qax"));
+ if (fname.isEmpty())
+ return;
+
+ QFile file(fname);
+ if (!file.open(QIODevice::ReadOnly)) {
+ QMessageBox::information(this, tr("Error Loading File"), tr("The file could not be opened for reading.\n%1").arg(fname));
+ return;
+ }
+
+ QAxWidget *container = new QAxWidget(workspace);
+ workspace->addWindow(container);
+
+ QDataStream d(&file);
+ d >> *container;
+
+ container->setObjectName(container->windowTitle());
+ container->show();
+
+ updateGUI();
+}
+
+void MainWindow::on_actionFileSave_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QString fname = QFileDialog::getSaveFileName(this, tr("Save"), QString(), QLatin1String("*.qax"));
+ if (fname.isEmpty())
+ return;
+
+ QFile file(fname);
+ if (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox::information(this, tr("Error Saving File"), tr("The file could not be opened for writing.\n%1").arg(fname));
+ return;
+ }
+ QDataStream d(&file);
+ d << *container;
+}
+
+
+void MainWindow::on_actionContainerSet_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QAxSelect select(this);
+ if (select.exec())
+ container->setControl(select.clsid());
+ updateGUI();
+}
+
+void MainWindow::on_actionContainerClear_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (container)
+ container->clear();
+ updateGUI();
+}
+
+void MainWindow::on_actionContainerProperties_triggered()
+{
+ if (!dlgAmbient) {
+ dlgAmbient = new AmbientProperties(this);
+ dlgAmbient->setControl(workspace);
+ }
+ dlgAmbient->show();
+}
+
+
+void MainWindow::on_actionControlInfo_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ ControlInfo info(this);
+ info.setControl(container);
+ info.exec();
+}
+
+void MainWindow::on_actionControlProperties_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ if (!dlgProperties) {
+ dlgProperties = new ChangeProperties(this);
+ connect(container, SIGNAL(propertyChanged(QString)), dlgProperties, SLOT(updateProperties()));
+ }
+ dlgProperties->setControl(container);
+ dlgProperties->show();
+}
+
+void MainWindow::on_actionControlMethods_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ if (!dlgInvoke)
+ dlgInvoke = new InvokeMethod(this);
+ dlgInvoke->setControl(container);
+ dlgInvoke->show();
+}
+
+void MainWindow::on_VerbMenu_aboutToShow()
+{
+ VerbMenu->clear();
+
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QStringList verbs = container->verbs();
+ for (int i = 0; i < verbs.count(); ++i) {
+ VerbMenu->addAction(verbs.at(i));
+ }
+
+ if (!verbs.count()) { // no verbs?
+ VerbMenu->addAction(tr("-- Object does not support any verbs --"))->setEnabled(false);
+ }
+}
+
+void MainWindow::on_VerbMenu_triggered(QAction *action)
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ container->doVerb(action->text());
+}
+
+void MainWindow::on_actionControlDocumentation_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QString docu = container->generateDocumentation();
+ if (docu.isEmpty())
+ return;
+
+ DocuWindow *docwindow = new DocuWindow(docu, workspace, container);
+ workspace->addWindow(docwindow);
+ docwindow->show();
+}
+
+
+void MainWindow::on_actionControlPixmap_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QPixmap pm = QPixmap::grabWidget(container);
+
+ QLabel *label = new QLabel(workspace);
+ label->setAttribute(Qt::WA_DeleteOnClose);
+ label->setPixmap(pm);
+ label->setWindowTitle(tr("%1 - Pixmap").arg(container->windowTitle()));
+
+ workspace->addWindow(label);
+ label->show();
+}
+
+void MainWindow::on_actionScriptingRun_triggered()
+{
+#ifndef QT_NO_QAXSCRIPT
+ if (!scripts)
+ return;
+
+ // If we have only one script loaded we can use the cool dialog
+ QStringList scriptList = scripts->scriptNames();
+ if (scriptList.count() == 1) {
+ InvokeMethod scriptInvoke(this);
+ scriptInvoke.setWindowTitle(tr("Execute Script Function"));
+ scriptInvoke.setControl(scripts->script(scriptList[0])->scriptEngine());
+ scriptInvoke.exec();
+ return;
+ }
+
+ bool ok = false;
+ QStringList macroList = scripts->functions(QAxScript::FunctionNames);
+ QString macro = QInputDialog::getItem(this, tr("Select Macro"), tr("Macro:"), macroList, 0, true, &ok);
+
+ if (!ok)
+ return;
+
+ QVariant result = scripts->call(macro);
+ if (result.isValid())
+ logMacros->append(tr("Return value of %1: %2").arg(macro).arg(result.toString()));
+#endif
+}
+
+void MainWindow::on_actionScriptingLoad_triggered()
+{
+#ifndef QT_NO_QAXSCRIPT
+ QString file = QFileDialog::getOpenFileName(this, tr("Open Script"), QString(), QAxScriptManager::scriptFileFilter());
+
+ if (file.isEmpty())
+ return;
+
+ if (!scripts) {
+ scripts = new QAxScriptManager(this);
+ scripts->addObject(this);
+ }
+
+ QWidgetList widgets = workspace->windowList();
+ QWidgetList::Iterator it(widgets.begin());
+ while (it != widgets.end()) {
+ QAxBase *ax = (QAxBase*)(*it)->qt_metacast("QAxBase");
+ ++it;
+ if (!ax)
+ continue;
+ scripts->addObject(ax);
+ }
+
+ QAxScript *script = scripts->load(file, file);
+ if (script) {
+ connect(script, SIGNAL(error(int,QString,int,QString)),
+ this, SLOT(logMacro(int,QString,int,QString)));
+ actionScriptingRun->setEnabled(true);
+ }
+#else
+ QMessageBox::information(this, tr("Function not available"),
+ tr("QAxScript functionality is not available with this compiler."));
+#endif
+}
+
+void MainWindow::updateGUI()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+
+ bool hasControl = container && !container->isNull();
+ actionFileNew->setEnabled(true);
+ actionFileLoad->setEnabled(true);
+ actionFileSave->setEnabled(hasControl);
+ actionContainerSet->setEnabled(container != 0);
+ actionContainerClear->setEnabled(hasControl);
+ actionControlProperties->setEnabled(hasControl);
+ actionControlMethods->setEnabled(hasControl);
+ actionControlInfo->setEnabled(hasControl);
+ actionControlDocumentation->setEnabled(hasControl);
+ actionControlPixmap->setEnabled(hasControl);
+ VerbMenu->setEnabled(hasControl);
+ if (dlgInvoke)
+ dlgInvoke->setControl(hasControl ? container : 0);
+ if (dlgProperties)
+ dlgProperties->setControl(hasControl ? container : 0);
+
+ QWidgetList list = workspace->windowList();
+ QWidgetList::Iterator it = list.begin();
+ while (it != list.end()) {
+ QWidget *container = *it;
+
+ QAxWidget *ax = qobject_cast<QAxWidget*>(container);
+ if (ax) {
+ container->disconnect(SIGNAL(signal(QString,int,void*)));
+ if (actionLogSignals->isChecked())
+ connect(container, SIGNAL(signal(QString,int,void*)), this, SLOT(logSignal(QString,int,void*)));
+
+ 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)));
+ if (actionLogProperties->isChecked())
+ connect(container, SIGNAL(propertyChanged(QString)), this, SLOT(logPropertyChanged(QString)));
+ container->blockSignals(actionFreezeEvents->isChecked());
+ }
+
+ ++it;
+ }
+}
+
+
+void MainWindow::logPropertyChanged(const QString &prop)
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QVariant var = container->property(prop.toLatin1());
+ logProperties->append(tr("%1: Property Change: %2 - { %3 }").arg(container->windowTitle(), prop, var.toString()));
+}
+
+void MainWindow::logSignal(const QString &signal, int argc, void *argv)
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QString paramlist;
+ VARIANT *params = (VARIANT*)argv;
+ for (int a = argc-1; a >= 0; --a) {
+ if (a == argc-1)
+ paramlist = QLatin1String(" - {");
+ QVariant qvar = VARIANTToQVariant(params[a], 0);
+ paramlist += QLatin1String(" ") + qvar.toString();
+ if (a > 0)
+ paramlist += QLatin1String(",");
+ else
+ paramlist += QLatin1String(" ");
+ }
+ if (argc)
+ paramlist += QLatin1String("}");
+ logSignals->append(container->windowTitle() + QLatin1String(": ") + signal + paramlist);
+}
+
+void MainWindow::logException(int code, const QString&source, const QString&desc, const QString&help)
+{
+ Q_UNUSED(desc);
+ QAxWidget *container = qobject_cast<QAxWidget*>(sender());
+ if (!container)
+ return;
+
+ QString str = tr("%1: Exception code %2 thrown by %3").
+ arg(container->windowTitle()).arg(code).arg(source);
+ logDebug->append(str);
+ logDebug->append(tr("\tDescription: %1").arg(desc));
+
+ if (!help.isEmpty())
+ logDebug->append(tr("\tHelp available at %1").arg(help));
+ else
+ logDebug->append(tr("\tNo help available."));
+}
+
+void MainWindow::logMacro(int code, const QString &description, int sourcePosition, const QString &sourceText)
+{
+ /* FIXME This needs to be rewritten to not use string concatentation, such
+ * that it can be translated in a sane way. */
+ QString message = tr("Script: ");
+ if (code)
+ message += QString::number(code) + QLatin1String(" ");
+ message += QLatin1String("'") + description + QLatin1String("'");
+ if (sourcePosition)
+ message += tr(" at position ") + QString::number(sourcePosition);
+ if (!sourceText.isEmpty())
+ message += QLatin1String(" '") + sourceText + QLatin1String("'");
+
+ logMacros->append(message);
+}
diff --git a/tools/testcon/mainwindow.h b/tools/testcon/mainwindow.h
new file mode 100644
index 0000000..a2abc37
--- /dev/null
+++ b/tools/testcon/mainwindow.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "ui_mainwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+class InvokeMethod;
+class ChangeProperties;
+class AmbientProperties;
+class QAxScriptManager;
+
+class QWorkspace;
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+
+class MainWindow : public QMainWindow, public Ui::MainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+protected slots:
+ void on_actionFileNew_triggered();
+ void on_actionFileLoad_triggered();
+ void on_actionFileSave_triggered();
+
+ void on_actionContainerSet_triggered();
+ void on_actionContainerClear_triggered();
+ void on_actionContainerProperties_triggered();
+
+ void on_actionControlInfo_triggered();
+ void on_actionControlDocumentation_triggered();
+ void on_actionControlPixmap_triggered();
+ void on_actionControlProperties_triggered();
+ void on_actionControlMethods_triggered();
+ void on_VerbMenu_aboutToShow();
+
+ void on_actionScriptingLoad_triggered();
+ void on_actionScriptingRun_triggered();
+
+private:
+ InvokeMethod *dlgInvoke;
+ ChangeProperties *dlgProperties;
+ AmbientProperties *dlgAmbient;
+ QAxScriptManager *scripts;
+ QWorkspace *workspace;
+
+ QtMsgHandler oldDebugHandler;
+
+private slots:
+ void updateGUI();
+ void logPropertyChanged(const QString &prop);
+ void logSignal(const QString &signal, int argc, void *argv);
+ void logException(int code, const QString&source, const QString&desc, const QString&help);
+ void logMacro(int code, const QString &description, int sourcePosition, const QString &sourceText);
+
+ void on_VerbMenu_triggered(QAction *action);
+};
+
+#endif // MAINWINDOW_H
diff --git a/tools/testcon/mainwindow.ui b/tools/testcon/mainwindow.ui
new file mode 100644
index 0000000..54889f0
--- /dev/null
+++ b/tools/testcon/mainwindow.ui
@@ -0,0 +1,682 @@
+<ui version="4.0" stdsetdef="1" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="objectName" >
+ <string notr="true" >MainWindow</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>929</width>
+ <height>620</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>ActiveX Control Test Container</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="Frame" >
+ <property name="objectName" >
+ <string notr="true" >Frame</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>Sunken</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSplitter" name="Splitter2" >
+ <property name="objectName" >
+ <string notr="true" >Splitter2</string>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QFrame" name="Workbase" >
+ <property name="objectName" >
+ <string notr="true" >Workbase</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>Raised</enum>
+ </property>
+ </widget>
+ <widget class="QTabWidget" name="TabWidget2" >
+ <property name="objectName" >
+ <string notr="true" >TabWidget2</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget" name="logSignalsTab" >
+ <property name="objectName" >
+ <string notr="true" >logSignalsTab</string>
+ </property>
+ <attribute name="title" >
+ <string>Signal log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logSignals" >
+ <property name="objectName" >
+ <string notr="true" >logSignals</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="logPropertiesTab" >
+ <property name="objectName" >
+ <string notr="true" >logPropertiesTab</string>
+ </property>
+ <attribute name="title" >
+ <string>Property log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logProperties" >
+ <property name="objectName" >
+ <string notr="true" >logProperties</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="TabPage" >
+ <property name="objectName" >
+ <string notr="true" >TabPage</string>
+ </property>
+ <attribute name="title" >
+ <string>Macro Log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logMacros" >
+ <property name="objectName" >
+ <string notr="true" >logMacros</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="logDebugTab" >
+ <property name="objectName" >
+ <string notr="true" >logDebugTab</string>
+ </property>
+ <attribute name="title" >
+ <string>Debug log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logDebug" >
+ <property name="objectName" >
+ <string notr="true" >logDebug</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolBar" name="Toolbar_2" >
+ <property name="objectName" >
+ <string notr="true" >Toolbar_2</string>
+ </property>
+ <property name="windowTitle" >
+ <string>Toolbar_2</string>
+ </property>
+ <addaction name="actionFileNew" />
+ <addaction name="actionControlMethods" />
+ <addaction name="actionControlProperties" />
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="objectName" >
+ <string notr="true" >menubar</string>
+ </property>
+ <widget class="QMenu" name="FileMenu" >
+ <property name="objectName" >
+ <string notr="true" >FileMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;File</string>
+ </property>
+ <addaction name="actionFileNew" />
+ <addaction name="actionFileLoad" />
+ <addaction name="actionFileSave" />
+ <addaction name="separator" />
+ <addaction name="actionFileExit" />
+ </widget>
+ <widget class="QMenu" name="ContainerMenu" >
+ <property name="objectName" >
+ <string notr="true" >ContainerMenu</string>
+ </property>
+ <property name="title" >
+ <string>Con&amp;tainer</string>
+ </property>
+ <addaction name="actionContainerSet" />
+ <addaction name="actionContainerClear" />
+ <addaction name="separator" />
+ <addaction name="actionContainerProperties" />
+ </widget>
+ <widget class="QMenu" name="ControlMenu" >
+ <property name="objectName" >
+ <string notr="true" >ControlMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Control</string>
+ </property>
+ <widget class="QMenu" name="VerbMenu" >
+ <property name="objectName" >
+ <string notr="true" >VerbMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Verbs...</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ <addaction name="actionControlMethods" />
+ <addaction name="actionControlProperties" />
+ <addaction name="VerbMenu" />
+ <addaction name="separator" />
+ <addaction name="actionControlInfo" />
+ <addaction name="actionControlDocumentation" />
+ <addaction name="actionControlPixmap" />
+ </widget>
+ <widget class="QMenu" name="ScriptMenu" >
+ <property name="objectName" >
+ <string notr="true" >ScriptMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Scripting</string>
+ </property>
+ <addaction name="actionScriptingLoad" />
+ <addaction name="actionScriptingRun" />
+ </widget>
+ <widget class="QMenu" name="OptionsMenu" >
+ <property name="objectName" >
+ <string notr="true" >OptionsMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Options</string>
+ </property>
+ <widget class="QMenu" name="LoggingMenu" >
+ <property name="objectName" >
+ <string notr="true" >LoggingMenu</string>
+ </property>
+ <property name="title" >
+ <string>Log...</string>
+ </property>
+ <addaction name="actionLogSignals" />
+ <addaction name="actionLogProperties" />
+ </widget>
+ <addaction name="actionFreezeEvents" />
+ <addaction name="actionGroupLogging" />
+ <addaction name="LoggingMenu" />
+ </widget>
+ <addaction name="FileMenu" />
+ <addaction name="ContainerMenu" />
+ <addaction name="ControlMenu" />
+ <addaction name="ScriptMenu" />
+ <addaction name="OptionsMenu" />
+ </widget>
+ <action name="actionFileExit" >
+ <property name="objectName" >
+ <string>actionFileExit</string>
+ </property>
+ <property name="iconText" >
+ <string>Exit</string>
+ </property>
+ <property name="text" >
+ <string>E&amp;xit</string>
+ </property>
+ </action>
+ <action name="actionContainerSet" >
+ <property name="objectName" >
+ <string>actionContainerSet</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Set Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Set Control</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+S</string>
+ </property>
+ </action>
+ <action name="actionControlMethods" >
+ <property name="objectName" >
+ <string>actionControlMethods</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="icon" >
+ <iconset>image0</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Invoke Methods</string>
+ </property>
+ <property name="text" >
+ <string>Invoke &amp;Methods</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+M</string>
+ </property>
+ </action>
+ <action name="actionControlProperties" >
+ <property name="objectName" >
+ <string>actionControlProperties</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="icon" >
+ <iconset>image1</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Change Properties</string>
+ </property>
+ <property name="text" >
+ <string>Change &amp;Properties</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+P</string>
+ </property>
+ </action>
+ <action name="actionContainerClear" >
+ <property name="objectName" >
+ <string>actionContainerClear</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Clear Control</string>
+ </property>
+ <property name="text" >
+ <string>C&amp;lear Control</string>
+ </property>
+ <property name="shortcut" >
+ <string/>
+ </property>
+ </action>
+ <action name="actionContainerProperties" >
+ <property name="objectName" >
+ <string>actionContainerProperties</string>
+ </property>
+ <property name="iconText" >
+ <string>Ambient Properties</string>
+ </property>
+ <property name="text" >
+ <string>Ambient &amp;Properties</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+A</string>
+ </property>
+ </action>
+ <action name="actionControlInfo" >
+ <property name="objectName" >
+ <string>actionControlInfo</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Details</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Details</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+I</string>
+ </property>
+ </action>
+ <action name="actionFileSave" >
+ <property name="objectName" >
+ <string>actionFileSave</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Save Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Save Control</string>
+ </property>
+ </action>
+ <action name="actionFileLoad" >
+ <property name="objectName" >
+ <string>actionFileLoad</string>
+ </property>
+ <property name="iconText" >
+ <string>Load Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Load Control</string>
+ </property>
+ </action>
+ <action name="actionFreezeEvents" >
+ <property name="objectName" >
+ <string>actionFreezeEvents</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="iconText" >
+ <string>Freeze Events</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Freeze Events</string>
+ </property>
+ </action>
+ <action name="actionFileNew" >
+ <property name="objectName" >
+ <string>actionFileNew</string>
+ </property>
+ <property name="icon" >
+ <iconset>image2</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Insert Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Insert Control</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <action name="actionControlDocumentation" >
+ <property name="objectName" >
+ <string>actionControlDocumentation</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Show Documentation</string>
+ </property>
+ <property name="text" >
+ <string>Show D&amp;ocumentation</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ <action name="actionControlPixmap" >
+ <property name="objectName" >
+ <string>actionControlPixmap</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Render to Pixmap</string>
+ </property>
+ <property name="text" >
+ <string>Render to Pi&amp;xmap</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+X</string>
+ </property>
+ </action>
+ <action name="actionScriptingLoad" >
+ <property name="objectName" >
+ <string>actionScriptingLoad</string>
+ </property>
+ <property name="iconText" >
+ <string>Load Script</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Load Script</string>
+ </property>
+ </action>
+ <action name="actionScriptingRun" >
+ <property name="objectName" >
+ <string>actionScriptingRun</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Run Macro</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Run Macro...</string>
+ </property>
+ </action>
+ <actiongroup name="actionGroupLogging" >
+ <action name="actionLogSignals" >
+ <property name="objectName" >
+ <string>actionLogSignals</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="iconText" >
+ <string>Signals</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Signals</string>
+ </property>
+ </action>
+ <action name="actionLogProperties" >
+ <property name="objectName" >
+ <string>actionLogProperties</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="iconText" >
+ <string>Properties</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Properties</string>
+ </property>
+ </action>
+ <property name="objectName" >
+ <string>actionGroupLogging</string>
+ </property>
+ <property name="exclusive" >
+ <bool>false</bool>
+ </property>
+ </actiongroup>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <images>
+ <image name="image0" >
+ <data format="XPM.GZ" length="3502" >789cdd95c96e1c371086ef7a8a81eb6604e56e92bd21c84192175996648d6559b2831cd85cb4ef23d95290770fe72f36e3003ee41220485373f8543f975a587cf17c76b8bb3d7bfe62e56e6117276ee68eededecb9bfbfb878fcf5b75f7e5f79a6d42cfdd54d3553cf7e5a79365fccdc6ce7ea322cc19e26a0aa51aaeb964c31b3ee46d8a9b05b32b7994d27f3178523ecbb99bbbe87fdaef000be06b7ca0e067c9b791c5af04d6637c87e8f99fde0c11edc6935c2193e01f7dab91a1cc083314ef4c7e0b15141ece29f6b4c68c047998720fb7d01473d8e60b24bae2b1d1cf416faba36cacbfe1b99b597f5e04f6d4c081af335b86f5c80ff74091eda3a20beb40376ad8b381fbd0487ce44890f83a3a92cf6a3fd25abca682beb7d15ee42141ec0e90016fed366e6c6223ff498b91d2b30ceab5462d93f1416ff9accdd28e741bc9531e388fcd3c7c292fff7e0c67827febf05b74de5e47c3db84b2cfedf64ae9dc4df1496fc55e0bed15eceb75758ce578387a6f1a81fda288cfa639db9f5d89f55610b7d07b64defc51f3f71407c18f95163aa0fd9ff43662bf543a867e51b9ff3391696fa719943107f241ea189926f96fc84b68a92df3785113fdece5c47a9af77e09818fef2566615e5bea1de75ddb6c284fbaa753b487df03770d34ef532070f5d9bf90aecbb18253ec8bf317d88f08f719f4d3ba8cca83f330c5d147f5f67ee33239fc60e6366ec6fc6c10933fa87f1b6ca7c9fb98e12af0770b05a98d05f4cb42633eaade9c6364afe5e816d2a47e94fb86f9dafea0af1b617e05018fe76b1f0f9927b5df80c1c2a55213f16fd607085d14f6c5d18f7c7b6f5584b3da03e6d5718f567fb494f5bc2c5be061e26b6a847ebea3460477c6c2c8cfa18abb2de2ab8ae7d2df15907ab625f084f768bfa1c4d61d4ef38d4a196787e02db693e8bbef84f88d718ea584b7f417cdd5fe7c1fbe14a7c08f7d9a9e581c088af3385515fae298cfcbbb6d295f49327e1c9ce9fc1dd6467dc1fd7173dfab9f3aa5672dfd06f5c2c76f4575fa9f481b19eaf0be37df46a623e04ebc2e8b7de28ad64ff03705318f7c1b73a7d60c4d35b6514fa29a19ffa7162467ff7ae30f2e17d39afecef8b1dfdd7c7c2a8ff6074aba53f20fea1cc679bd954a2473f0d41754ade7ff497d8a85e49ffc47b145b6db5f403f817fb62477ca29dd623f49fe8d4a0a4dff4994725fde25a58a701463f8d5e375afadb7ae6c9be96396aa92fbcbf3198f4c1de656e8ccc9f67b606e7e5d5ccde483fb9126efa46ce7f29dc9a56d6bbc8dcb4b21eea2dc6f41ccbfb762edca6171b7c26dc990ef3e78b7f3efe2f7a26b6e9473cb24be43970e4a3328ef9e47b3d9ff2199ff3055ff2155ff34dfacf2ddff182eff901e32b7fe3c7499f567d4ada555ee3757ec9aff835bf493336f82d6ff23bde4a639b77f83def66bde5397fe03dfec8fb697ce2033ee4cf69c617aeb866958666c30db765fd8efbac9619437285e60bb2349223bfd453a038e9e9888e8b7a9f4ee894cee89c2ed28c4bbaa26bd67443b73fd6d3091fd01d2de89e1e92fe2b7d4b3e2cf58f3fd243fd44abb446eb49fd925ed16b7a431bf496368b7ee4757af737f5166d27f50ebda75d9ad307daa38fb43fe9e9131dd0217d4e3e7ea12aa96b5249adc950432d75d427f560d9d2942f6be9c98ed6d1c27a1b6c5ac71ed9e3149b3d7b92e2b249fb497dfa7d3dd8337b6e2fd2b8b45789aeed8dbdb5777661693952b3a0ff763dff6bfa3f7e5ef9138fb14e09</data>
+ </image>
+ <image name="image1" >
+ <data format="XPM.GZ" length="2493" >789ca59459531b391446dff9152ef4464dddb8dbbd566a1eb2af10c84a929a87de8c0dd86c76623235ff3dfa8eb0878c3309a9e850a64fe9d3b5a4967c6babb7bfbbdddbbab57131ab66e3a6d78caaf3de563b9f4c2e3ffef5e7df1b9b71dcf37f45de8b37ffd8d8dc9bf59adecec9b493d8dc8bebd3f0311e09fc151e0b7c07af05fe146f84dca9b88b1241ff17794cc347782ac89fc90791a07f8a27026ff042e043bc128c3fc51b417f8db7028ff14ee0bbc1b3a62af177f850e07bc1b3b60aeb3b90277d81bfc0a33caac37c3b9c86bfc67381b77821f00778990f9bd09fe0b5c01fe26d91b561bf2a79da17acf7088f044e7db693bc9be003c1f847c1cb7e17fad9ff341178a84f23ff12cf04fe18cfcbbc633f1dfb91760277f2ac2fc8e7782ce83fc60782fe90e70be83fc77dbbdaef27782ee83fc40b814f975e87fdb8c0ebacaec3f933bc13f878e94d582fe7271b0afc64e94da8cff9c9fdfb6dc2f9e1fbf381c039df795aa55d78df255e0abcc03b81bf97737cc378e65b1455d186f1295e099cfd28ea2a6d42bd7dbc15cc8ffb500e04fd039c463ff7b96c05fd91bc4a05fe1c2f57f7611baf57e7bf8fb702ff20e7ba87f7fb0c4f933809e7330b2ef0b7f850e097f22616cc8ffbc2750df35fe089c0efe079522661fdbc9fa62cea229c8f37782df0bbf2364eda24cc77125ce0fc3eb449e11bfe19678138e7b3ed047e4fdec5abfbc3ef5397e4691ed6c7fdeb0a817fc22b81df970fe3b44ccbf0637b737e276fce2aabadf14fad7536bc7a3ab0918dd7f376684776ec99d8d44e3ca776e69fce3d1736b3f9b7799ffe649f6de1b9f47cb13b76d7eed97dfff4c01eda237b1c4684bc3df1b5437a39e2a93db3e7b6edd9b117b66b7b9ef92affd2cf63710d8d187b5e79c6365fb2cabffe4f5e23deb09a7f797b2dff6e2d2ff6ed3dff3f58df7f46d7f2f177f3034b2cb5cc726c3d5f58e9cc3957b93a8c708d1f915c8dfe79fd856b9577ddffe44b3774076ee419933ef4335fb8237774d3fadfb09677c77ee6233771ad9b527f0427eb7977fa6bf5dd19f54757d55b774efd095c7c273ffbc5f9cffddb8e7e8cbb767e18f1537ef73ede28ffcfed8daf804d6c7a</data>
+ </image>
+ <image name="image2" >
+ <data format="XPM.GZ" length="1232" >789ccdd24b4fe2501c86f13d9fa2811d99a8ad9442cc2c44f082327169625c1c4e5b4f552e721398cc771f9f570907837bff0f8bfef226400287d5e0eeb617540f4bd399991536b0ce4c826a3a1f0c56f70fbfff96ca5114bcbf6a6110967f95ca07810dfe8c8619cfeefdb972a483e7306c107c84518de0293c360473312598c15a83602a1a8256b404fb30d64103eb09c10a4c9a047bb019119c8931c12e3475821dd88f094ec53ac1b5a8834bd1127c13738237d08604afc498e0b5a88313982604dba221f82a5a82633127b882594470211e137c116382976242f0496c121c8929c10b3127f80cf3238267624870282604e76293604bd4978603516f0d0b51a7ffd8dedb2c15d3b7699ae58feecb522936e7dcee62b6cb93db59fadbe5f9c5f98bdd0c03371c8d9db7a4dee770fb96e275329ded5f8af9e2eddb65f9a396cc5f566b6f392d8ad6fcf3ceda1d6f396f5d5c2e3e6ed5beea7a8b1b5fdf2c3f6edde9f6bce5c0ed9cff6b7fff3fd8b3fc3b29fd07f8c43cbd</data>
+ </image>
+ </images>
+</ui>
diff --git a/tools/testcon/scripts/javascript.js b/tools/testcon/scripts/javascript.js
new file mode 100644
index 0000000..e2bd54b
--- /dev/null
+++ b/tools/testcon/scripts/javascript.js
@@ -0,0 +1,25 @@
+function QAxWidget2::Click()
+{
+ QAxWidget2.lineWidth++;
+ MainWindow.logMacro(0, "Hello from JavaScript: QAxWidget2::Click", 0, "");
+}
+
+function fatLines()
+{
+ QAxWidget2.lineWidth = 25;
+}
+
+function thinLines()
+{
+ QAxWidget2.lineWidth = 1;
+}
+
+function setLineWidth(width)
+{
+ QAxWidget2.lineWidth = width;
+}
+
+function getLineWidth()
+{
+ return(QAxWidget2.lineWidth)
+}
diff --git a/tools/testcon/scripts/perlscript.pl b/tools/testcon/scripts/perlscript.pl
new file mode 100644
index 0000000..232ec91
--- /dev/null
+++ b/tools/testcon/scripts/perlscript.pl
@@ -0,0 +1,65 @@
+#############################################################################
+##
+## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is part of the ActiveQt module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the Technology Preview License Agreement accompanying
+## this package.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, 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.
+##
+## If you have questions regarding the use of this file, please contact
+## Nokia at qt-info@nokia.com.
+##
+##
+##
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+sub QAxWidget2_Click {
+ $QAxWidget2->{'lineWidth'} = $QAxWidget2->{'lineWidth'} + 1;
+ $MainWindow->logMacro(0, "Hello from Perl: QAxWidget2_Click", 0, "");
+}
+
+sub fatLines
+{
+ $QAxWidget2->{'lineWidth'} = 25;
+}
+
+sub thinLines
+{
+ $QAxWidget2->{'lineWidth'} = 1;
+}
+
+sub setLineWidth(width)
+{
+ $QAxWidget2->{'lineWidth'} = width;
+}
+
+sub getLineWidth()
+{
+ return $QAxWidget2->{'lineWidth'};
+}
diff --git a/tools/testcon/scripts/pythonscript.py b/tools/testcon/scripts/pythonscript.py
new file mode 100644
index 0000000..81aa926
--- /dev/null
+++ b/tools/testcon/scripts/pythonscript.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+#############################################################################
+##
+## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the Technology Preview License Agreement accompanying
+## this package.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, 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.
+##
+## If you have questions regarding the use of this file, please contact
+## Nokia at qt-info@nokia.com.
+##
+##
+##
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+def QAxWidget2_Click():
+ QAxWidget2.lineWidth = QAxWidget2.lineWidth + 1;
+ MainWindow.logMacro(0, "Hello from Python: QAxWidget2_Click", 0, "");
+
+def fatLines():
+ QAxWidget2.lineWidth = 25;
+
+def thinLines():
+ QAxWidget2.lineWidth = 1;
+
+def setLineWidth(width):
+ QAxWidget2.lineWidth = width;
+
+def getLineWidth():
+ return QAxWidget2.lineWidth;
diff --git a/tools/testcon/scripts/vbscript.vbs b/tools/testcon/scripts/vbscript.vbs
new file mode 100644
index 0000000..bd29f19
--- /dev/null
+++ b/tools/testcon/scripts/vbscript.vbs
@@ -0,0 +1,20 @@
+Sub QAxWidget2_Click
+ QAxWidget2.lineWidth = QAxWidget2.lineWidth + 1
+ MainWindow.logMacro 0, "Hello from VBScript: QAxWidget2_Click", 0, ""
+End Sub
+
+Sub fatLines
+ QAxWidget2.lineWidth = 25
+End Sub
+
+Sub thinLines
+ QAxWidget2.lineWidth = 1
+End Sub
+
+Sub setLineWidth(width)
+ QAxWidget2.lineWidth = width
+End Sub
+
+Public Function getLineWidth
+ getLineWidth = QAxWidget2.lineWidth
+End Function
diff --git a/tools/testcon/testcon.idl b/tools/testcon/testcon.idl
new file mode 100644
index 0000000..7dd88a5
--- /dev/null
+++ b/tools/testcon/testcon.idl
@@ -0,0 +1,44 @@
+/****************************************************************************
+** Interface definition generated for ActiveQt project
+**
+** 'C:\depot\qt\3.3\extensions\activeqt\tools\testcon\testcon.exe'
+**
+** Created: Fr 31. Okt 15:33:50 2003
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+
+import "ocidl.idl";
+#include <olectl.h>
+
+[
+ uuid(4A43E44D-9D1D-47E5-A1E5-58FE6F7BE0A4),
+ version(1.0),
+ helpstring("testcon 1.0 Type Library")
+]
+library testconLib
+{
+ importlib("stdole32.tlb");
+ importlib("stdole2.tlb");
+
+ [
+ uuid(3FC86F5F-8B15-4428-8F6B-482BAE91F1AE),
+ helpstring("MainWindow Interface")
+ ]
+ dispinterface IMainWindow
+ {
+ properties:
+ methods:
+ [id(7)] void logMacro( [in] int p_code, [in] BSTR p_description, [in] int p_sourcePosition, [in] BSTR p_sourceText);
+ };
+
+ [
+ aggregatable,
+ helpstring("MainWindow Class"),
+ uuid(5F5CE700-48A8-47B1-9B06-3B7F79E41D7C)
+ ]
+ coclass MainWindow
+ {
+ [default] dispinterface IMainWindow;
+ };
+};
diff --git a/tools/testcon/testcon.pro b/tools/testcon/testcon.pro
new file mode 100644
index 0000000..89f8067
--- /dev/null
+++ b/tools/testcon/testcon.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+
+CONFIG += qaxserver qaxserver_no_postlink qaxcontainer
+# QT += qt3support
+
+# ui_qaxselect.h
+INCLUDEPATH += $$QT_SOURCE_TREE/tools/activeqt/container/debug \
+ $$QT_SOURCE_TREE/tools/activeqt/container/release \
+ $$QT_BUILD_TREE/src/activeqt/container \
+
+SOURCES = main.cpp docuwindow.cpp mainwindow.cpp invokemethod.cpp changeproperties.cpp ambientproperties.cpp controlinfo.cpp
+HEADERS = docuwindow.h mainwindow.h invokemethod.h changeproperties.h ambientproperties.h controlinfo.h
+FORMS = mainwindow.ui invokemethod.ui changeproperties.ui ambientproperties.ui controlinfo.ui
+RC_FILE = testcon.rc
+
+win32-borland {
+ QMAKE_POST_LINK = -midl $$QT_SOURCE_TREE/tools/activeqt/testcon/testcon.idl
+} else {
+ !win32-g++*:QMAKE_POST_LINK = midl $$QT_SOURCE_TREE/tools/activeqt/testcon/testcon.idl && move testcon.tlb $(TARGETDIR)
+
+}
diff --git a/tools/testcon/testcon.rc b/tools/testcon/testcon.rc
new file mode 100644
index 0000000..f17bd26
--- /dev/null
+++ b/tools/testcon/testcon.rc
@@ -0,0 +1,35 @@
+#ifndef Q_CC_BOR
+#include <winver.h>
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 3, 2, 0, 0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)\0"
+ VALUE "FileDescription", "ActiveQt Test Container\0"
+ VALUE "FileVersion", "1,0,0,1\0"
+ VALUE "InternalName", "testcon\0"
+ VALUE "LegalCopyright", "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "testcon.exe\0"
+ VALUE "ProductName", "ActiveQt Test Container\0"
+ VALUE "ProductVersion", "3, 2, 0, 0\0"
+ END
+ END
+ END
+/* End of Version info */
+
diff --git a/tools/tools.pro b/tools/tools.pro
new file mode 100644
index 0000000..c50010c
--- /dev/null
+++ b/tools/tools.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+
+CONFIG += ordered
+
+SUBDIRS = dumpdoc \
+ dumpcpp \
+ testcon
+