summaryrefslogtreecommitdiffstats
path: root/src/activeqt/control/qaxfactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/activeqt/control/qaxfactory.cpp')
-rw-r--r--src/activeqt/control/qaxfactory.cpp591
1 files changed, 591 insertions, 0 deletions
diff --git a/src/activeqt/control/qaxfactory.cpp b/src/activeqt/control/qaxfactory.cpp
new file mode 100644
index 0000000..ec72c830
--- /dev/null
+++ b/src/activeqt/control/qaxfactory.cpp
@@ -0,0 +1,591 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 char 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(QFile::decodeName(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 char 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::fromLocal8Bit(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::fromLocal8Bit(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::fromLocal8Bit(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