blob: d11685aca3a310d3fe5ed6ebda8d0193bbfd4826 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the ActiveQt framework of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, 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 The Qt Company Ltd 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/qcompilerdetection.h>
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Woverloaded-virtual") // gcc complains about QObject::metaObject() being hidden.
QT_WARNING_DISABLE_CLANG("-Woverloaded-virtual") // clang-cl complains about QObject::metaObject() being hidden.
#include <QtCore/qhash.h>
#include <QtCore/quuid.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qsettings.h>
struct IUnknown;
struct IDispatch;
QT_BEGIN_NAMESPACE
class QWidget;
class QSettings;
class QAxFactory : public QObject
{
Q_DISABLE_COPY_MOVE(QAxFactory)
public:
QAxFactory(const QUuid &libId, const QUuid &appId);
~QAxFactory() override;
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 override \
{ \
QStringList list; \
list << className; \
return list; \
} \
const QMetaObject *metaObject(const QString &key) const override \
{ \
if (key == className) \
return &Class::staticMetaObject; \
return nullptr; \
} \
QObject *createObject(const QString &key) override \
{ \
if (key == className) \
return new Class(nullptr); \
return nullptr; \
} \
QUuid classID(const QString &key) const override \
{ \
if (key == className) \
return QUuid(IIDClass); \
return QUuid(); \
} \
QUuid interfaceID(const QString &key) const override \
{ \
if (key == className) \
return QUuid(IIDInterface); \
return QUuid(); \
} \
QUuid eventsID(const QString &key) const override \
{ \
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 override { return &T::staticMetaObject; }
QStringList featureList() const override { return QStringList(QLatin1String(T::staticMetaObject.className())); }
QObject *createObject(const QString &key) override
{
const QMetaObject &mo = T::staticMetaObject;
if (key != QLatin1String(mo.className()))
return nullptr;
if (!qstrcmp(mo.classInfo(mo.indexOfClassInfo("Creatable")).value(), "no"))
return nullptr;
return new T(nullptr);
}
void registerClass(const QString &key, QSettings *settings) const override
{
const QStringList categories = getImplementedCategories();
for (const auto &cat : categories) {
settings->setValue(QLatin1String("/CLSID/") + classID(key).toString()
+ QLatin1String("/Implemented Categories/") + cat + QLatin1String("/."),
QString());
}
}
void unregisterClass(const QString &key, QSettings *settings) const override
{
const QStringList categories = getImplementedCategories();
for (const auto &cat : categories) {
settings->remove(QLatin1String("/CLSID/") + classID(key).toString()
+ QLatin1String("/Implemented Categories/") + cat + QLatin1String("/."));
}
}
private:
/*! Retrieve list of comma-separated "Implemented Categories" Q_CLASSINFO UUIDs from T. */
static QStringList getImplementedCategories()
{
const QMetaObject &mo = T::staticMetaObject;
QString catids = QLatin1String(mo.classInfo(mo.indexOfClassInfo("Implemented Categories")).value());
return catids.split(QLatin1Char(','));
}
};
#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 = nullptr; \
QStringList keys; \
QStringList::Iterator it; \
#define QAXCLASS(Class) \
factory = new QAxClass<Class>(typeLibID().toString(), appID().toString()); \
qRegisterMetaType<Class*>(#Class"*"); \
keys = factory->featureList(); \
for (const QString &key : qAsConst(keys)) { \
factoryKeys += key; \
factories.insert(key, factory); \
creatable.insert(key, true); \
}\
#define QAXTYPE(Class) \
factory = new QAxClass<Class>(typeLibID().toString(), appID().toString()); \
qRegisterMetaType<Class*>(#Class"*"); \
keys = factory->featureList(); \
for (const QString &key : qAsConst(keys)) { \
factoryKeys += key; \
factories.insert(key, factory); \
creatable.insert(key, false); \
}\
#define QAXFACTORY_END() \
} \
~QAxFactoryList() override { qDeleteAll(factories); } \
QStringList featureList() const override { return factoryKeys; } \
const QMetaObject *metaObject(const QString&key) const override { \
QAxFactory *f = factories[key]; \
return f ? f->metaObject(key) : nullptr; \
} \
QObject *createObject(const QString &key) override { \
if (!creatable.value(key)) \
return nullptr; \
QAxFactory *f = factories[key]; \
return f ? f->createObject(key) : nullptr; \
} \
QUuid classID(const QString &key) const override { \
QAxFactory *f = factories.value(key); \
return f ? f->classID(key) : QUuid(); \
} \
QUuid interfaceID(const QString &key) const override { \
QAxFactory *f = factories.value(key); \
return f ? f->interfaceID(key) : QUuid(); \
} \
QUuid eventsID(const QString &key) const override { \
QAxFactory *f = factories.value(key); \
return f ? f->eventsID(key) : QUuid(); \
} \
void registerClass(const QString &key, QSettings *s) const override { \
QAxFactory *f = factories.value(key); \
if (f) f->registerClass(key, s); \
} \
void unregisterClass(const QString &key, QSettings *s) const override { \
QAxFactory *f = factories.value(key); \
if (f) f->unregisterClass(key, s); \
} \
QString exposeToSuperClass(const QString &key) const override { \
QAxFactory *f = factories.value(key); \
return f ? f->exposeToSuperClass(key) : QString(); \
} \
bool stayTopLevel(const QString &key) const override { \
QAxFactory *f = factories.value(key); \
return f ? f->stayTopLevel(key) : false; \
} \
bool hasStockEvents(const QString &key) const override { \
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
QT_WARNING_POP
#ifndef Q_COM_METATYPE_DECLARED
#define Q_COM_METATYPE_DECLARED
Q_DECLARE_OPAQUE_POINTER(IUnknown*)
Q_DECLARE_OPAQUE_POINTER(IDispatch*)
Q_DECLARE_METATYPE(IUnknown*)
Q_DECLARE_METATYPE(IDispatch*)
#endif
#endif // QAXFACTORY_H