summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
+