summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/activeqt/container/qaxbase.cpp33
-rw-r--r--src/activeqt/shared/qaxtypes.cpp7
-rw-r--r--tests/auto/auto.pro3
-rw-r--r--tests/auto/dumpcpp/dumpcpp.pro11
-rw-r--r--tests/auto/dumpcpp/tst_dumpcpp.cpp67
-rw-r--r--tools/dumpcpp/dumpcpp.pro9
-rw-r--r--tools/dumpcpp/main.cpp653
7 files changed, 492 insertions, 291 deletions
diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp
index b8809cc..6785716 100644
--- a/src/activeqt/container/qaxbase.cpp
+++ b/src/activeqt/container/qaxbase.cpp
@@ -1564,15 +1564,19 @@ private:
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;
+ if (type.isEmpty()) {
+ return QByteArray("void");
+ } else {
+ 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;
}
- ++i;
}
return type;
}
@@ -1681,17 +1685,6 @@ private:
if (flags & Writable)
flags |= Stored;
prop.flags = flags;
- QVariant::Type vartype = QVariant::nameToType(prop.type);
- switch(vartype) {
- case QVariant::Invalid:
- case QVariant::UserType:
- if (QMetaType::type(prop.type) == QMetaType::UnknownType)
- qWarning("QAxBase: Unsupported property '%s' type: %s (%d)",
- name.constData(), prop.type.data(), vartype);
- break;
- default:
- break;
- }
}
inline bool hasProperty(const QByteArray &name)
@@ -3673,7 +3666,7 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v)
QByteArray type = d->metaobj->paramType(signature, p, &out);
QVariant::Type vt = QVariant::nameToType(type);
QVariant qvar;
- if (vt != QVariant::UserType)
+ if (vt != QVariant::UserType && vt != QMetaType::QVariant)
qvar = QVariant(vt, v[p + 1]);
if (!qvar.isValid()) {
diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp
index b1ffa91..b51311c 100644
--- a/src/activeqt/shared/qaxtypes.cpp
+++ b/src/activeqt/shared/qaxtypes.cpp
@@ -244,13 +244,16 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type
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 ((proptype == QVariant::UserType || proptype == QMetaType::QVariant) && !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 (proptype != QVariant::Invalid
+ && proptype != QVariant::UserType
+ && proptype != QMetaType::QVariant
+ && proptype != qvar.type()) {
if (qvar.canConvert(proptype))
qvar.convert(proptype);
else
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 8e3a63f..82cce69 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -1,3 +1,4 @@
TEMPLATE = subdirs
SUBDIRS += \
- qaxobject
+ qaxobject \
+ dumpcpp
diff --git a/tests/auto/dumpcpp/dumpcpp.pro b/tests/auto/dumpcpp/dumpcpp.pro
new file mode 100644
index 0000000..776aa32
--- /dev/null
+++ b/tests/auto/dumpcpp/dumpcpp.pro
@@ -0,0 +1,11 @@
+CONFIG += testcase qaxcontainer
+QT += widgets testlib
+SOURCES += tst_dumpcpp.cpp
+TARGET = tst_dumpcpp
+
+# Assume Web Browser type library is available in all windows installations
+TYPELIBS = $$(SystemRoot)\\system32\\ieframe.dll
+
+!exists($$TYPELIBS) {
+ message("Web Browser type library for test not found!")
+} \ No newline at end of file
diff --git a/tests/auto/dumpcpp/tst_dumpcpp.cpp b/tests/auto/dumpcpp/tst_dumpcpp.cpp
new file mode 100644
index 0000000..191f079
--- /dev/null
+++ b/tests/auto/dumpcpp/tst_dumpcpp.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include "ieframe.h" // generated header
+#include <QApplication>
+
+class tst_dumpcpp : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void toggleAddressBar();
+};
+
+// A simple test to verify that an object can be instantiated and interacted with
+void tst_dumpcpp::toggleAddressBar()
+{
+ SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser;
+ QVERIFY(webBrowser);
+ bool addressBar = webBrowser->AddressBar();
+ addressBar = !addressBar;
+ webBrowser->SetAddressBar(addressBar);
+ QVERIFY(webBrowser->AddressBar() == addressBar);
+ delete webBrowser;
+}
+
+QTEST_MAIN(tst_dumpcpp)
+#include "tst_dumpcpp.moc"
diff --git a/tools/dumpcpp/dumpcpp.pro b/tools/dumpcpp/dumpcpp.pro
index 240ae74..27ea7d5 100644
--- a/tools/dumpcpp/dumpcpp.pro
+++ b/tools/dumpcpp/dumpcpp.pro
@@ -1,9 +1,8 @@
-TEMPLATE = app
+DESTDIR = $$QT.activeqt.bins
CONFIG += console qaxcontainer
-QT += widgets
+QT += widgets core-private
-SOURCES += main.cpp
+SOURCES = main.cpp
-target.path = $$[QT_INSTALL_BINS]
-INSTALLS += target
+load(qt_tool)
diff --git a/tools/dumpcpp/main.cpp b/tools/dumpcpp/main.cpp
index 1eee3cd..4c1cd85 100644
--- a/tools/dumpcpp/main.cpp
+++ b/tools/dumpcpp/main.cpp
@@ -51,7 +51,7 @@
#include <QFileInfo>
#include <qt_windows.h>
#include <ocidl.h>
-
+#include <private/qmetaobject_p.h>
QT_BEGIN_NAMESPACE
static ITypeInfo *currentTypeInfo = 0;
@@ -71,37 +71,6 @@ enum ObjectCategory
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);
@@ -111,6 +80,8 @@ extern bool qax_dispatchEqualsIDispatch;
QByteArray nameSpace;
QMap<QByteArray, QByteArray> namespaceForType;
+QVector<QByteArray> strings;
+QHash<QByteArray, int> stringIndex; // Optimization, speeds up generation
void writeEnums(QTextStream &out, const QMetaObject *mo)
{
@@ -335,13 +306,13 @@ void generateClassDecl(QTextStream &out, const QString &controlID, const QMetaOb
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 << " " << propertyType << " qax_pointer = 0;" << endl;
+ QByteArray simplePropTypeWithNamespace = propertyType;
+ simplePropTypeWithNamespace.replace('*', "");
+ out << indent << " qRegisterMetaType<" << propertyType << ">(\"" << property.typeName() << "\", &qax_pointer);" << endl;
+ out << indent << " qRegisterMetaType<" << simplePropTypeWithNamespace << ">(\"" << simplePropType << "\", qax_pointer);" << endl;
}
out << indent << " QVariant qax_result = property(\"" << propertyName << "\");" << endl;
if (propertyType.length() && propertyType.at(propertyType.length()-1) == '*')
@@ -350,8 +321,6 @@ void generateClassDecl(QTextStream &out, const QString &controlID, const QMetaOb
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;
@@ -386,7 +355,7 @@ void generateClassDecl(QTextStream &out, const QString &controlID, const QMetaOb
if (!(category & NoInlines)) {
if (propertyType.endsWith('*')) {
out << "{" << endl;
- out << " int typeId = qRegisterMetaType(\"" << propertyType << "\", &value);" << endl;
+ out << " int typeId = qRegisterMetaType<" << propertyType << ">(\"" << propertyType << "\", &value);" << endl;
out << " setProperty(\"" << propertyName << "\", QVariant(typeId, &value));" << endl;
out << "}" << endl;
} else {
@@ -510,11 +479,13 @@ void generateClassDecl(QTextStream &out, const QString &controlID, const QMetaOb
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;
+ QByteArray simpleSlotTypeWithNamespace = slotType;
+ simpleSlotTypeWithNamespace.replace('*', "");
+ out << indent << " qRegisterMetaType<" << simpleSlotTypeWithNamespace << "*>(\"" << simpleSlotType << "*\", &qax_result);" << endl;
+ out << indent << " qRegisterMetaType<" << simpleSlotTypeWithNamespace << ">(\"" << simpleSlotType << "\", qax_result);" << endl;
if (foreignNamespace)
out << "#endif" << endl;
}
@@ -552,103 +523,273 @@ void generateClassDecl(QTextStream &out, const QString &controlID, const QMetaOb
}
}
-#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;
+#define addStringIdx(string) \
+ out << stridx(string) << ", ";
+
+// The following functions were copied from moc generator with only some minor changes
+void strreg(const QByteArray &s)
+{
+ if (!stringIndex.contains(s)) {
+ stringIndex.insert(s, strings.size());
+ strings.append(s);
+ }
+}
+
+int stridx(const QByteArray &s)
+{
+ int i = stringIndex.value(s);
+ Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings");
+ return i;
+}
+
+bool isBuiltinType(const QByteArray &type)
+{
+ int id = QMetaType::type(type.constData());
+ if (id == QMetaType::UnknownType)
+ return false;
+ return (id < QMetaType::User);
+}
+
+const char *metaTypeEnumValueString(int type)
+{
+#define RETURN_METATYPENAME_STRING(MetaTypeName, MetaTypeId, RealType) \
+ case QMetaType::MetaTypeName: return #MetaTypeName;
+
+ switch (type) {
+QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
+ }
+#undef RETURN_METATYPENAME_STRING
+ return 0;
+}
+
+uint nameToBuiltinType(const QByteArray &name)
+{
+ if (name.isEmpty())
+ return 0;
+
+ uint tp = QMetaType::type(name.constData());
+ return tp < uint(QMetaType::User) ? tp : uint(QMetaType::UnknownType);
+}
+
+void generateTypeInfo(QTextStream &out, const QByteArray &typeName)
+{
+ if (isBuiltinType(typeName)) {
+ int type;
+ QByteArray valueString;
+ if (typeName == "qreal") {
+ type = QMetaType::UnknownType;
+ valueString = "QReal";
+ } else {
+ type = nameToBuiltinType(typeName);
+ valueString = metaTypeEnumValueString(type);
+ }
+ if (!valueString.isEmpty()) {
+ out << "QMetaType::" << valueString;
+ } else {
+ Q_ASSERT(type != QMetaType::UnknownType);
+ out << type;
+ }
+ } else {
+ Q_ASSERT(!typeName.isEmpty());
+ out << "0x80000000 | " << stridx(typeName);
+ }
+}
+// End functions copied from moc generator
+
+void generateMethods(QTextStream &out, const QMetaObject *mo, const QMetaMethod::MethodType funcType, int &paramsIndex)
+{
+ out << "// ";
+ MethodFlags funcTypeFlag;
+ if (funcType == QMetaMethod::Signal) {
+ out << "signal";
+ funcTypeFlag = MethodSignal;
+ } else {
+ out << "slot";
+ funcTypeFlag = MethodSlot;
+ }
+ out << ": name, argc, parameters, tag, flags" << endl;
+
+ int methodCount = mo->methodCount();
+ for (int i = mo->methodOffset(); i < methodCount; ++i) {
+ const QMetaMethod method(mo->method(i));
+ if (method.methodType() != funcType)
+ continue;
+ out << " ";
+ addStringIdx(method.name());
+ out << method.parameterCount() << ", ";
+ out << paramsIndex << ", ";
+ addStringIdx(method.tag());
+ out << (AccessProtected | method.attributes() | funcTypeFlag) << "," << endl;
+ paramsIndex += 1 + method.parameterCount() * 2;
+ }
+ out << endl;
+}
+
+void generateMethodParameters(QTextStream &out, const QMetaObject *mo, const QMetaMethod::MethodType funcType)
+{
+ out << "// ";
+ if (funcType == QMetaMethod::Signal)
+ out << "signal";
+ else if (funcType == QMetaMethod::Slot)
+ out << "slot";
+ out << ": parameters" << endl;
+
+ int methodCount = mo->methodCount();
+ for (int i = mo->methodOffset(); i < methodCount; ++i) {
+ const QMetaMethod method(mo->method(i));
+ if (method.methodType() != funcType)
+ continue;
+
+ out << " ";
+
+ int argsCount = method.parameterCount();
+
+ // Return type
+ generateTypeInfo(out, method.typeName());
+ out << ",";
+
+ // Parameter types
+ const QList<QByteArray> parameterTypes = method.parameterTypes();
+ for (int j = 0; j < argsCount; ++j) {
+ out << " ";
+ generateTypeInfo(out, parameterTypes.at(j));
+ out << ",";
+ }
+
+ // Parameter names
+ const QList<QByteArray> parameterNames = method.parameterNames();
+ for (int j = 0; j < argsCount; ++j)
+ out << " " << stridx(parameterNames.at(j)) << ",";
+
+ out << endl;
+ }
+ out << endl;
+}
void generateClassImpl(QTextStream &out, const QMetaObject *mo, const QByteArray &className, const QByteArray &nameSpace, ObjectCategory category)
{
+ Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "dumpcpp should generate the same version as moc");
+
QByteArray qualifiedClassName;
if (!nameSpace.isEmpty())
qualifiedClassName = nameSpace + "::";
qualifiedClassName += className;
+ QByteArray qualifiedClassNameIdentifier = qualifiedClassName;
+ qualifiedClassNameIdentifier.replace(':', '_');
+
+ int allClassInfoCount = mo->classInfoCount();
+ int allMethodCount = mo->methodCount();
+ int allPropertyCount = mo->propertyCount();
+ int allEnumCount = mo->enumeratorCount();
+
+ int thisClassInfoCount = allClassInfoCount - mo->classInfoOffset();
+ int thisEnumCount = allEnumCount - mo->enumeratorOffset();
+ int thisMethodCount = allMethodCount - mo->methodOffset();
+ int thisPropertyCount = allPropertyCount - mo->propertyOffset();
+
+ int signalCount = 0;
+ int slotCount = 0;
+ int combinedParameterCount = 0;
+ int enumStart = MetaObjectPrivateFieldCount;
+
+ // Register strings
+ strreg(qualifiedClassName);
+ for (int i = mo->classInfoOffset(); i < allClassInfoCount; ++i) {
+ const QMetaClassInfo classInfo = mo->classInfo(i);
+ strreg(classInfo.name());
+ strreg(classInfo.value());
+ }
+ for (int i = mo->methodOffset(); i < allMethodCount; ++i) {
+ const QMetaMethod method(mo->method(i));
+ if (method.methodType() == QMetaMethod::Signal)
+ signalCount++;
+ if (method.methodType() == QMetaMethod::Slot)
+ slotCount++;
+ int argsCount = method.parameterCount();
+ combinedParameterCount += argsCount;
+
+ strreg(method.name());
+ QByteArray typeName = method.typeName();
+ if (!isBuiltinType(typeName))
+ strreg(typeName);
+ strreg(method.tag());
+
+ const QList<QByteArray> parameterNames = method.parameterNames();
+ const QList<QByteArray> parameterTypes = method.parameterTypes();
+ for (int j = 0; j < argsCount; ++j) {
+ if (!isBuiltinType(parameterTypes.at(j)))
+ strreg(parameterTypes.at(j));
+ strreg(parameterNames.at(j));
+ }
+ }
+ for (int i = mo->propertyOffset(); i < allPropertyCount; ++i) {
+ const QMetaProperty property = mo->property(i);
+ strreg(property.name());
+ if (!isBuiltinType(property.typeName()))
+ strreg(property.typeName());
+ }
+ for (int i = mo->enumeratorOffset(); i < allEnumCount; ++i) {
+ const QMetaEnum enumerator = mo->enumerator(i);
+ strreg(enumerator.name());
+ for (int j = 0; j < enumerator.keyCount(); ++j)
+ strreg(enumerator.key(j));
+ }
- 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;
+ // Build data array
+ out << "static const uint qt_meta_data_" << qualifiedClassNameIdentifier << "[] = {" << 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 << " 7, // revision" << endl;
+ out << " ";
+ addStringIdx(qualifiedClassName);
+ out << " // classname" << endl;
+ out << " " << thisClassInfoCount << ", " << (thisClassInfoCount ? enumStart : 0) << ", // classinfo" << endl;
+ enumStart += thisClassInfoCount * 2;
+ out << " " << thisMethodCount << ", " << (thisMethodCount ? enumStart : 0) << ", // methods" << endl;
+ enumStart += thisMethodCount * 5;
+ int paramsIndex = enumStart;
+ enumStart += (combinedParameterCount * 2); // parameter types + names
+ enumStart += thisMethodCount; // return types
+ out << " " << thisPropertyCount << ", " << (thisPropertyCount ? enumStart : 0) << ", // properties" << endl;
+ enumStart += thisPropertyCount * 3;
+ out << " " << thisEnumCount << ", " << (thisEnumCount ? enumStart : 0) << ", // enums/sets" << endl;
+ out << " 0, 0, // constructors" << endl;
+ out << " 0, // flags" << endl;
+ out << " " << signalCount << ", // signal count" << endl;
out << endl;
- if (classInfoCount) {
+ if (thisClassInfoCount) {
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);
+ for (int i = mo->classInfoOffset(); i < allClassInfoCount; ++i) {
+ QMetaClassInfo classInfo = mo->classInfo(i);
+ out << " ";
+ addStringIdx(classInfo.name());
+ addStringIdx(classInfo.value());
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.methodSignature().constData(), 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.methodSignature().constData(), 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) {
+ // Signal/Slot arrays
+ if (signalCount)
+ generateMethods(out, mo, QMetaMethod::Signal, paramsIndex);
+ if (slotCount)
+ generateMethods(out, mo, QMetaMethod::Slot, paramsIndex);
+
+ // Method parameter arrays
+ if (signalCount)
+ generateMethodParameters(out, mo, QMetaMethod::Signal);
+ if (slotCount)
+ generateMethodParameters(out, mo, QMetaMethod::Slot);
+
+ if (thisPropertyCount) {
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);
+ for (int i = mo->propertyOffset(); i < allPropertyCount; ++i) {
+ QMetaProperty property = mo->property(i);
+ out << " ";
+ addStringIdx(property.name());
+ generateTypeInfo(out, property.typeName());
+ out << ", ";
uint flags = 0;
uint vartype = property.type();
@@ -673,175 +814,55 @@ void generateClassImpl(QTextStream &out, const QMetaObject *mo, const QByteArray
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) {
+ if (thisEnumCount) {
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);
+ enumStart += thisEnumCount * 4;
+ for (int i = mo->enumeratorOffset(); i < allEnumCount; ++i) {
+ QMetaEnum enumerator = mo->enumerator(i);
+ out << " ";
+ addStringIdx(enumerator.name());
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 i = mo->enumeratorOffset(); i < allEnumCount; ++i) {
+ QMetaEnum enumerator = mo->enumerator(i);
for (int j = 0; j < enumerator.keyCount(); ++j) {
- out << " ";
- addString(enumerator.key(j), enumStringData);
+ out << " ";
+ addStringIdx(enumerator.key(j));
+ out << "uint(";
if (nameSpace.isEmpty())
out << className << "::";
else
out << nameSpace << "::";
- out << enumerator.key(j) << "," << endl;
+ out << enumerator.key(j) << ")," << endl;
}
- enumStringData += "\"\n";
}
- out << endl;
}
- out << " 0 // eod" << 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 << "qt_meta_stringdata_all.data," << endl;
+ out << "qt_meta_data_" << qualifiedClassNameIdentifier << ", 0, 0, 0 }" << 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 << " if (!strcmp(_clname, \"" << qualifiedClassName << "\"))" << endl;
out << " return static_cast<void*>(const_cast<" << className << "*>(this));" << endl;
if (category & ActiveX)
out << " return QAxWidget::qt_metacast(_clname);" << endl;
@@ -989,6 +1010,8 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O
QMetaObject *namespaceObject = qax_readEnumInfo(typelib, 0);
+ QByteArray classImplBuffer;
+ QTextStream classImplOut(&classImplBuffer, QIODevice::WriteOnly);
QFile implFile(cppFile + QLatin1String(".cpp"));
QTextStream implOut(&implFile);
if (!(category & (NoMetaObject|NoImplementation))) {
@@ -1257,10 +1280,8 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O
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;
- }
+ if (implFile.isOpen())
+ generateClassImpl(classImplOut, metaObject, className, libName.toLatin1(), (ObjectCategory)object_category);
}
currentTypeInfo = 0;
}
@@ -1271,6 +1292,104 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O
typeinfo->Release();
}
+ // String table generation logic was ported from moc generator, with some modifications
+ // required to split large stringdata arrays.
+ if (!strings.isEmpty() && implFile.isOpen()) {
+ //
+ // Build stringdata struct
+ //
+ implOut << "struct qt_meta_stringdata_all_t {" << endl;
+ implOut << " QByteArrayData data[" << strings.size() << "];" << endl;
+
+ QVector<QList<QByteArray> > listVector;
+ QList<QByteArray> currentList;
+
+ int currentTableLen = 0;
+ for (int i = 0; i < strings.size(); ++i) {
+ currentTableLen += strings.at(i).length() + 1;
+ currentList.append(strings.at(i));
+ // Split strings into chunks less than 64k to work around compiler limits.
+ if (currentTableLen > 60000) {
+ implOut << " char stringdata" << listVector.size() << "[" << currentTableLen + 1 << "];" << endl;
+ listVector.append(currentList);
+ currentList.clear();
+ currentTableLen = 0;
+ }
+ }
+ implOut << " char stringdata" << listVector.size() << "[" << currentTableLen + 1 << "];" << endl;
+ implOut << "};" << endl;
+ listVector.append(currentList);
+
+ // Macro that expands into a QByteArrayData. The offset member is
+ // calculated from 1) the offset of the actual characters in the
+ // stringdata.stringdata member, and 2) the stringdata.data index of the
+ // QByteArrayData being defined. This calculation relies on the
+ // QByteArrayData::data() implementation returning simply "this + offset".
+ implOut << "#define QT_MOC_LITERAL(idx, ofs, len, table) \\" << endl
+ << " Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \\" << endl
+ << " offsetof(qt_meta_stringdata_all_t, stringdata##table) + ofs \\" << endl
+ << " - idx * sizeof(QByteArrayData) \\" << endl
+ << " )" << endl;
+
+ implOut << "static const qt_meta_stringdata_all_t qt_meta_stringdata_all = {" << endl;
+ implOut << " {" << endl;
+
+ int totalStringCount = 0;
+ for (int i = 0; i < listVector.size(); ++i) {
+ int idx = 0;
+ for (int j = 0; j < listVector[i].size(); j++) {
+ if (totalStringCount)
+ implOut << "," << endl;
+ const QByteArray &str = listVector[i].at(j);
+ implOut << "QT_MOC_LITERAL(" << totalStringCount++ << ", " << idx << ", " << str.length() << ", " << i << ")";
+ idx += str.length() + 1;
+ }
+ }
+ implOut << endl << " }";
+
+ //
+ // Build stringdata arrays
+ //
+ for (int i = 0; i < listVector.size(); ++i) {
+ int col = 0;
+ int len = 0;
+ implOut << "," << endl;
+ implOut << " \"";
+ for (int j = 0; j < listVector[i].size(); ++j) {
+ QByteArray s = listVector[i].at(j);
+ len = s.length();
+ if (col && col + len >= 150) {
+ implOut << "\"" << endl << " \"";
+ col = 0;
+ } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
+ implOut << "\"\"";
+ len += 2;
+ }
+ int idx = 0;
+ while (idx < s.length()) {
+ if (idx > 0) {
+ col = 0;
+ implOut << "\"" << endl << " \"";
+ }
+ int spanLen = qMin(150, s.length() - idx);
+ implOut << s.mid(idx, spanLen);
+ idx += spanLen;
+ col += spanLen;
+ }
+
+ implOut << "\\0";
+ col += len + 2;
+ }
+ implOut << "\"";
+ }
+ // Terminate stringdata struct
+ implOut << endl << "};" << endl;
+
+ implOut << "#undef QT_MOC_LITERAL" << endl << endl;
+
+ implOut << classImplBuffer << endl;
+ }
+
delete namespaceObject;
classesOut.flush();
@@ -1291,15 +1410,23 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O
declOut << "}" << endl;
declOut << endl;
- // partial template specialization for qMetaTypeCreateHelper
+ // partial template specialization for qMetaTypeCreateHelper and qMetaTypeConstructHelper
+ declOut << "QT_BEGIN_NAMESPACE" << endl << endl;
for (int t = 0; t < subtypes.count(); ++t) {
QByteArray subType(subtypes.at(t));
declOut << "template<>" << endl;
declOut << "inline void *qMetaTypeCreateHelper<" << libName << "::" << subType << " >(const void *t)" << endl;
- declOut << "{ Q_ASSERT(!t); return new " << libName << "::" << subType << "; }" << endl;
+ declOut << "{ Q_ASSERT(!t); Q_UNUSED(t); return new " << libName << "::" << subType << "; }" << endl;
declOut << endl;
- }
+ // qMetaTypeConstructHelper is required to make generated files compile,
+ // though it doesn't seem to be used in practice.
+ declOut << "template<>" << endl;
+ declOut << "inline void *qMetaTypeConstructHelper<" << libName << "::" << subType << " >(void *where, const void *t)" << endl;
+ declOut << "{ Q_ASSERT(!t); Q_UNUSED(t); return new (where) " << libName << "::" << subType << "; }" << endl;
+ declOut << endl;
+ }
+ declOut << "QT_END_NAMESPACE" << endl << endl;
declOut << "#endif" << endl;
declOut << endl;
}