An error occurred while loading the file. Please try again.
-
Brett Stottlemyer authored
Having no SIGNALS (or no SLOTS) defined in a .rep file would cause a compilation error on some compilers due signalArgCount/signalArgTypes not being declared. Change-Id: Ibe70f96a63775f9cdbb062f4b764b94b0947b67b Reviewed-by:
Continuous Integration (KDAB) <build@kdab.com> Reviewed-by:
Björn Breitmeyer <bjoern.breitmeyer@kdab.com>
163007c2
/****************************************************************************
**
** Copyright (C) 2014 Ford Motor Company
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights. These rights are described in the Digia 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.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "repcodegenerator.h"
#include "repparser.h"
#include <QFileInfo>
#include <QMetaType>
#include <QTextStream>
QT_USE_NAMESPACE
template <typename C>
static int accumulatedSizeOfNames(const C &c)
{
int result = 0;
foreach (const typename C::value_type &e, c)
result += e.name.size();
return result;
}
template <typename C>
static int accumulatedSizeOfTypes(const C &c)
{
int result = 0;
foreach (const typename C::value_type &e, c)
result += e.type.size();
return result;
}
static QString cap(QString name)
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
{
if (!name.isEmpty())
name[0] = name[0].toUpper();
return name;
}
/*
Returns \c true if the type is a built-in type.
*/
static bool isBuiltinType(const QString &type)
{
int id = QMetaType::type(type.toLatin1().constData());
if (id == QMetaType::UnknownType)
return false;
return (id < QMetaType::User);
}
RepCodeGenerator::RepCodeGenerator(QIODevice *outputDevice)
: m_outputDevice(outputDevice)
{
Q_ASSERT(m_outputDevice);
}
void RepCodeGenerator::generate(const AST &ast, Mode mode, QString fileName)
{
QTextStream stream(m_outputDevice);
if (fileName.isEmpty())
stream << "#pragma once" << endl << endl;
else {
fileName = QFileInfo(fileName).fileName();
fileName = fileName.toUpper();
fileName.replace(QLatin1Char('.'), QLatin1Char('_'));
stream << "#ifndef " << fileName << endl;
stream << "#define " << fileName << endl << endl;
}
QStringList out;
generateHeader(mode, stream, ast);
foreach (const POD &pod, ast.pods)
generatePOD(stream, pod);
QSet<QString> metaTypes;
foreach (const POD &pod, ast.pods)
metaTypes << pod.name;
foreach (const ASTClass &astClass, ast.classes) {
foreach (const ASTProperty &property, astClass.properties)
metaTypes << property.type;
foreach (const ASTFunction &function, astClass.signalsList + astClass.slotsList) {
metaTypes << function.returnType;
foreach (const ASTDeclaration &decl, function.params) {
metaTypes << decl.type;
}
}
}
const QString metaTypeRegistrationCode = generateMetaTypeRegistration(metaTypes)
+ generateMetaTypeRegistrationForEnums(ast.enumUses);
foreach (const ASTClass &astClass, ast.classes) {
generateClass(mode, out, astClass, metaTypeRegistrationCode);
if (mode == SOURCE) {
generateClass(SIMPLE_SOURCE, out, astClass, metaTypeRegistrationCode);
generateSourceAPI(out, astClass);
}
}
stream << out.join(QLatin1Char('\n'));
generateStreamOperatorsForEnums(stream, ast.enumUses);
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
stream << endl;
if (!fileName.isEmpty())
stream << "#endif // " << fileName << endl;
}
void RepCodeGenerator::generateHeader(Mode mode, QTextStream &out, const AST &ast)
{
out << "// This is an autogenerated file.\n"
"// Do not edit this file, any changes made will be lost the next time it is generated.\n"
"\n"
"#include <QtCore/qobject.h>\n"
"#include <QtCore/qdatastream.h>\n"
"#include <QtCore/qvariant.h>\n"
"#include <QtCore/qmetatype.h>\n"
"\n"
"#include <QtRemoteObjects/qremoteobjectnode.h>\n"
;
if (mode == REPLICA) {
out << "#include <QtRemoteObjects/qremoteobjectpendingcall.h>\n";
out << "#include <QtRemoteObjects/qremoteobjectreplica.h>\n";
} else
out << "#include <QtRemoteObjects/qremoteobjectsource.h>\n";
out << "\n";
out << ast.includes.join(QLatin1Char('\n'));
out << "\n";
}
static QString formatTemplateStringArgTypeNameCapitalizedName(int numberOfTypeOccurrences, int numberOfNameOccurrences,
QString templateString, const POD &pod)
{
QString out;
const int LengthOfPlaceholderText = 2;
Q_ASSERT(templateString.count(QRegExp(QStringLiteral("%\\d"))) == numberOfNameOccurrences + numberOfTypeOccurrences);
const int expectedOutSize
= numberOfNameOccurrences * accumulatedSizeOfNames(pod.attributes)
+ numberOfTypeOccurrences * accumulatedSizeOfTypes(pod.attributes)
+ pod.attributes.size() * (templateString.size() - (numberOfNameOccurrences + numberOfTypeOccurrences) * LengthOfPlaceholderText);
out.reserve(expectedOutSize);
foreach (const PODAttribute &a, pod.attributes)
out += templateString.arg(a.type, a.name, cap(a.name));
return out;
}
QString RepCodeGenerator::formatQPropertyDeclarations(const POD &pod)
{
return formatTemplateStringArgTypeNameCapitalizedName(1, 4, QStringLiteral(" Q_PROPERTY(%1 %2 READ %2 WRITE set%3 NOTIFY %2Changed)\n"), pod);
}
QString RepCodeGenerator::formatConstructors(const POD &pod)
{
QString initializerString = QStringLiteral("QObject(parent)");
QString defaultInitializerString = initializerString;
QString argString;
foreach (const PODAttribute &a, pod.attributes) {
initializerString += QString::fromLatin1(", _%1(%1)").arg(a.name);
defaultInitializerString += QString::fromLatin1(", _%1()").arg(a.name);
argString += QString::fromLatin1("%1 %2, ").arg(a.type, a.name);
}
argString.chop(2);
return QString::fromLatin1(" explicit %1(QObject *parent = Q_NULLPTR) : %2 {}\n"
" explicit %1(%3, QObject *parent = Q_NULLPTR) : %4 {}\n")
.arg(pod.name, defaultInitializerString, argString, initializerString);
}
QString RepCodeGenerator::formatCopyConstructor(const POD &pod)
{
return QLatin1String(" ") + pod.name + QLatin1String("(const ") + pod.name + QLatin1String("& other)\n"
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
" : QObject()\n"
" {\n"
" QtRemoteObjects::copyStoredProperties(&other, this);\n"
" }\n"
"\n")
;
}
QString RepCodeGenerator::formatCopyAssignmentOperator(const POD &pod)
{
return QLatin1String(" ") + pod.name + QLatin1String(" &operator=(const ") + pod.name + QLatin1String(" &other)\n"
" {\n"
" if (this != &other)\n"
" QtRemoteObjects::copyStoredProperties(&other, this);\n"
" return *this;\n"
" }\n"
"\n")
;
}
QString RepCodeGenerator::formatPropertyGettersAndSetters(const POD &pod)
{
// MSVC doesn't like adjacent string literal concatenation within QStringLiteral, so keep it in one line:
QString templateString
= QStringLiteral(" %1 %2() const { return _%2; }\n void set%3(%1 %2) { if (%2 != _%2) { _%2 = %2; Q_EMIT %2Changed(_%2); } }\n");
return formatTemplateStringArgTypeNameCapitalizedName(2, 9, qMove(templateString), pod);
}
QString RepCodeGenerator::formatSignals(const POD &pod)
{
QString out;
const QString prefix = QStringLiteral(" void ");
const QString mid = QStringLiteral("Changed(");
const QString suffix = QStringLiteral(");\n");
const int expectedOutSize
= accumulatedSizeOfNames(pod.attributes) + accumulatedSizeOfTypes(pod.attributes)
+ pod.attributes.size() * (prefix.size() + mid.size() + suffix.size());
out.reserve(expectedOutSize);
foreach (const PODAttribute &a, pod.attributes) {
out += prefix;
out += a.name;
out += mid;
out += a.type;
out += suffix;
}
Q_ASSERT(out.size() == expectedOutSize);
return out;
}
QString RepCodeGenerator::formatDataMembers(const POD &pod)
{
QString out;
const QString prefix = QStringLiteral(" ");
const QString infix = QStringLiteral(" _");
const QString suffix = QStringLiteral(";\n");
const int expectedOutSize
= accumulatedSizeOfNames(pod.attributes)
+ accumulatedSizeOfTypes(pod.attributes)
+ pod.attributes.size() * (prefix.size() + infix.size() + suffix.size());
out.reserve(expectedOutSize);
foreach (const PODAttribute &a, pod.attributes) {
out += prefix;
out += a.type;
out += infix;
out += a.name;
out += suffix;
}
Q_ASSERT(out.size() == expectedOutSize);
return out;
}
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
QString RepCodeGenerator::formatMarshallingOperators(const POD &pod)
{
return QLatin1String("inline QDataStream &operator<<(QDataStream &ds, const ") + pod.name + QLatin1String(" &obj) {\n"
" QtRemoteObjects::copyStoredProperties(&obj, ds);\n"
" return ds;\n"
"}\n"
"\n"
"inline QDataStream &operator>>(QDataStream &ds, ") + pod.name + QLatin1String(" &obj) {\n"
" QtRemoteObjects::copyStoredProperties(ds, &obj);\n"
" return ds;\n"
"}\n")
;
}
void RepCodeGenerator::generatePOD(QTextStream &out, const POD &pod)
{
out << "class " << pod.name << " : public QObject\n"
"{\n"
" Q_OBJECT\n"
<< formatQPropertyDeclarations(pod)
<< "public:\n"
<< formatConstructors(pod)
<< formatCopyConstructor(pod)
<< formatCopyAssignmentOperator(pod)
<< formatPropertyGettersAndSetters(pod)
<< "Q_SIGNALS:\n"
<< formatSignals(pod)
<< "private:\n"
<< formatDataMembers(pod)
<< "};\n"
"\n"
<< formatMarshallingOperators(pod)
<< "\n"
"Q_DECLARE_METATYPE(" << pod.name << ")\n"
"\n"
;
}
QString RepCodeGenerator::generateMetaTypeRegistration(const QSet<QString> &metaTypes)
{
QString out;
const QString qRegisterMetaType = QStringLiteral(" qRegisterMetaType<");
const QString qRegisterMetaTypeStreamOperators = QStringLiteral(" qRegisterMetaTypeStreamOperators<");
const QString lineEnding = QStringLiteral(">();\n");
foreach (const QString &metaType, metaTypes) {
if (isBuiltinType(metaType))
continue;
out += qRegisterMetaType;
out += metaType;
out += lineEnding;
out += qRegisterMetaTypeStreamOperators;
out += metaType;
out += lineEnding;
}
return out;
}
QString RepCodeGenerator::generateMetaTypeRegistrationForEnums(const QVector<QString> &enumUses)
{
QString out;
foreach (const QString &enumName, enumUses) {
out += QLatin1String(" qRegisterMetaTypeStreamOperators<") + enumName + QLatin1String(">(\"") + enumName + QLatin1String("\");\n");
}
return out;
}
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
void RepCodeGenerator::generateStreamOperatorsForEnums(QTextStream &out, const QVector<QString> &enumUses)
{
foreach (const QString &enumName, enumUses) {
out << "inline QDataStream &operator<<(QDataStream &out, " << enumName << " value)" << endl;
out << "{" << endl;
out << " out << static_cast<qint32>(value);" << endl;
out << " return out;" << endl;
out << "}" << endl;
out << endl;
out << "inline QDataStream &operator>>(QDataStream &in, " << enumName << " &value)" << endl;
out << "{" << endl;
out << " qint32 intValue = 0;" << endl;
out << " in >> intValue;" << endl;
out << " value = static_cast<" << enumName << ">(intValue);" << endl;
out << " return in;" << endl;
out << "}" << endl;
out << endl;
}
}
void RepCodeGenerator::generateClass(Mode mode, QStringList &out, const ASTClass &astClass, const QString &metaTypeRegistrationCode)
{
const QString className = (astClass.name + (mode == REPLICA ? QStringLiteral("Replica") : mode == SOURCE ? QStringLiteral("Source") : QStringLiteral("SimpleSource")));
if (mode == REPLICA)
out << QString::fromLatin1("class %1 : public QRemoteObjectReplica").arg(className);
else
out << QString::fromLatin1("class %1 : public QObject").arg(className);
out << QStringLiteral("{");
out << QStringLiteral(" Q_OBJECT");
out << QStringLiteral(" Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_TYPE, \"%1\")").arg(astClass.name);
out << QStringLiteral(" friend class QRemoteObjectNode;");
if (mode == REPLICA)
out <<QStringLiteral("private:");
else
out <<QStringLiteral("public:");
if (mode == REPLICA) {
out << QStringLiteral(" %1() : QRemoteObjectReplica() {}").arg(className);
out << QStringLiteral(" void initialize()");
} else {
out << QStringLiteral(" %1(QObject *parent = Q_NULLPTR) : QObject(parent)").arg(className);
if (mode == SIMPLE_SOURCE) {
foreach (const ASTProperty &property, astClass.properties) {
if (!property.defaultValue.isEmpty()) {
out += QStringLiteral(" , _%1(%2)").arg(property.name).arg(property.defaultValue);
} else {
out += QStringLiteral(" , _%1()").arg(property.name);
}
}
}
}
out << QStringLiteral(" {");
if (!metaTypeRegistrationCode.isEmpty())
out << metaTypeRegistrationCode;
if (mode == REPLICA) {
out << QStringLiteral(" QVariantList properties;");
out << QString::fromLatin1(" properties.reserve(%1);").arg(astClass.properties.size());
foreach (const ASTProperty &property, astClass.properties) {
out << QString(QLatin1String(" properties << QVariant::fromValue(") + property.type + QLatin1String("(") + property.defaultValue + QLatin1String("));"));
}
out << QStringLiteral(" setProperties(properties);");
}
out << QStringLiteral(" }");
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
out << QStringLiteral("public:");
out << QStringLiteral(" virtual ~%1() {}").arg(className);
//First output properties
foreach (const ASTProperty &property, astClass.properties) {
if (property.modifier == ASTProperty::Constant)
out << QStringLiteral(" Q_PROPERTY(%1 %2 READ %2 CONSTANT)").arg(property.type, property.name);
else if (property.modifier == ASTProperty::ReadOnly)
out << QStringLiteral(" Q_PROPERTY(%1 %2 READ %2 NOTIFY %2Changed)").arg(property.type, property.name);
else if (property.modifier == ASTProperty::ReadWrite)
out << QStringLiteral(" Q_PROPERTY(%1 %2 READ %2 WRITE set%3 NOTIFY %2Changed)").arg(property.type, property.name, cap(property.name));
}
out << QStringLiteral("");
//Next output getter/setter
if (mode == REPLICA) {
int i = 0;
foreach (const ASTProperty &property, astClass.properties) {
out << QStringLiteral(" %1 %2() const").arg(property.type, property.name);
out << QStringLiteral(" {");
out << QStringLiteral(" return propAsVariant(%1).value<%2 >();").arg(i).arg(property.type);
out << QStringLiteral(" }");
i++;
if (property.modifier == ASTProperty::ReadWrite) {
out << QStringLiteral("");
out << QStringLiteral(" void set%3(%1 %2)").arg(property.type, property.name, cap(property.name));
out << QStringLiteral(" {");
out << QStringLiteral(" static int __repc_index = %1::staticMetaObject.indexOfProperty(\"%2\");").arg(className).arg( property.name);
out << QStringLiteral(" QVariantList __repc_args;");
out << QStringLiteral(" __repc_args << QVariant::fromValue(%1);").arg(property.name);
out << QStringLiteral(" send(QMetaObject::WriteProperty, __repc_index, __repc_args);");
out << QStringLiteral(" }");
}
out << QStringLiteral("");
}
} else if (mode == SOURCE) {
foreach (const ASTProperty &property, astClass.properties)
out << QString::fromLatin1(" virtual %1 %2() const = 0;").arg(property.type, property.name);
foreach (const ASTProperty &property, astClass.properties) {
if (property.modifier == ASTProperty::ReadWrite)
out << QStringLiteral(" virtual void set%3(%1 %2) = 0;").arg(property.type, property.name, cap(property.name));
}
} else {
foreach (const ASTProperty &property, astClass.properties) {
out << QString::fromLatin1(" virtual %1 %2() const { return _%2; }").arg(property.type, property.name);
}
foreach (const ASTProperty &property, astClass.properties) {
if (property.modifier == ASTProperty::ReadWrite) {
out << QStringLiteral(" virtual void set%3(%1 %2)").arg(property.type, property.name, cap(property.name));
out << QStringLiteral(" {");
out << QStringLiteral(" if (%1 != _%1)").arg(property.name);
out << QStringLiteral(" {");
out << QStringLiteral(" _%1 = %1;").arg(property.name);
out << QStringLiteral(" Q_EMIT %1Changed(_%1);").arg(property.name);
out << QStringLiteral(" }");
out << QStringLiteral(" }");
}
}
}
//Next output property signals
if (!astClass.properties.isEmpty() || !astClass.signalsList.isEmpty()) {
out << QStringLiteral("");
out << QStringLiteral("Q_SIGNALS:");
foreach (const ASTProperty &property, astClass.properties) {
if (property.modifier != ASTProperty::Constant)
out << QStringLiteral(" void %1Changed(%2);").arg(property.name).arg(property.type);
}
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
foreach (const ASTFunction &signal, astClass.signalsList)
out << QStringLiteral(" void %1(%2);").arg(signal.name).arg(signal.paramsAsString());
}
if (!astClass.slotsList.isEmpty()) {
out << QStringLiteral("");
out << QStringLiteral("public Q_SLOTS:");
foreach (const ASTFunction &slot, astClass.slotsList) {
if (mode != REPLICA) {
out << QStringLiteral(" virtual %1 %2(%3) = 0;").arg(slot.returnType).arg(slot.name).arg(slot.paramsAsString());
} else {
// TODO: Discuss whether it is a good idea to special-case for void here,
const bool isVoid = slot.returnType == QStringLiteral("void");
if (isVoid)
out << QStringLiteral(" void %1(%2)").arg(slot.name).arg(slot.paramsAsString());
else
out << QStringLiteral(" QRemoteObjectPendingReply<%1> %2(%3)").arg(slot.returnType).arg(slot.name).arg(slot.paramsAsString());
out << QStringLiteral(" {");
out << QStringLiteral(" static int __repc_index = %1::staticMetaObject.indexOfSlot(\"%2(%3)\");")
.arg(className).arg(slot.name).arg(slot.paramsAsString(ASTFunction::Normalized));
out << QStringLiteral(" QVariantList __repc_args;");
if (!slot.paramNames().isEmpty()) {
QStringList variantNames;
foreach (const QString &name, slot.paramNames())
variantNames << QStringLiteral("QVariant::fromValue(%1)").arg(name);
out << QStringLiteral(" __repc_args << %1;").arg(variantNames.join(QLatin1String(" << ")));
}
if (isVoid)
out << QStringLiteral(" send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);");
else
out << QStringLiteral(" return QRemoteObjectPendingReply<%1>(sendWithReply(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args));").arg(slot.returnType);
out << QStringLiteral(" }");
}
}
}
if (mode == SIMPLE_SOURCE)
{
//Next output data members
if (!astClass.properties.isEmpty()) {
out << QStringLiteral("");
out << QStringLiteral("private:");
foreach (const ASTProperty &property, astClass.properties) {
out << QStringLiteral(" %1 _%2;").arg(property.type, property.name);
}
}
}
out << QStringLiteral("};");
out << QStringLiteral("");
}
void RepCodeGenerator::generateSourceAPI(QStringList &out, const ASTClass &astClass)
{
const QString className = astClass.name + QStringLiteral("SourceAPI");
out << QStringLiteral("template <class ObjectType>");
out << QString::fromLatin1("struct %1 : public SourceApiMap").arg(className);
out << QStringLiteral("{");
out << QString::fromLatin1(" %1()").arg(className);
out << QStringLiteral(" {");
const int propCount = astClass.properties.count();
out << QString::fromLatin1(" _properties[0] = %1;").arg(propCount);
QStringList changeSignals;
QList<int> propertyChangeIndex;
for (int i = 0; i < propCount; ++i) {
const ASTProperty &prop = astClass.properties.at(i);
out << QString::fromLatin1(" _properties[%1] = qtro_prop_index<ObjectType>(&ObjectType::%2, "
"static_cast<%3 (QObject::*)()>(0),\"%2\");")
.arg(i+1).arg(prop.name).arg(prop.type);
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
if (prop.modifier == prop.ReadWrite) //Make sure we have a setter function
out << QStringLiteral(" qtro_method_test<ObjectType>(&ObjectType::set%1, static_cast<void (QObject::*)(%2)>(0));")
.arg(cap(prop.name)).arg(prop.type);
if (prop.modifier != prop.Constant) { //Make sure we have an onChange signal
out << QStringLiteral(" qtro_method_test<ObjectType>(&ObjectType::%1Changed, static_cast<void (QObject::*)()>(0));")
.arg(prop.name);
changeSignals << QString::fromLatin1("%1Changed").arg(prop.name);
propertyChangeIndex << i + 1; //_properties[0] is the count, so index is one higher
}
}
const int signalCount = astClass.signalsList.count();
const int changedCount = changeSignals.size();
out << QString::fromLatin1(" _signals[0] = %1;").arg(signalCount+changeSignals.size());
for (int i = 0; i < changedCount; ++i)
out << QString::fromLatin1(" _signals[%1] = qtro_signal_index<ObjectType>(&ObjectType::%2, "
"static_cast<void (QObject::*)()>(0),signalArgCount+%4,signalArgTypes[%4]);")
.arg(i+1).arg(changeSignals.at(i)).arg(i);
for (int i = 0; i < signalCount; ++i) {
const ASTFunction &sig = astClass.signalsList.at(i);
out << QString::fromLatin1(" _signals[%1] = qtro_signal_index<ObjectType>(&ObjectType::%2, "
"static_cast<void (QObject::*)(%3)>(0),signalArgCount+%4,signalArgTypes[%4]);")
.arg(changedCount+i+1).arg(sig.name).arg(sig.paramsAsString(ASTFunction::Normalized)).arg(i);
}
const int slotCount = astClass.slotsList.count();
out << QString::fromLatin1(" _methods[0] = %1;").arg(slotCount);
for (int i = 0; i < slotCount; ++i) {
const ASTFunction &slot = astClass.slotsList.at(i);
out << QString::fromLatin1(" _methods[%1] = qtro_method_index<ObjectType>(&ObjectType::%2, "
"static_cast<void (QObject::*)(%3)>(0),\"%2(%3)\",methodArgCount+%4,methodArgTypes[%4]);")
.arg(i+1).arg(slot.name).arg(slot.paramsAsString(ASTFunction::Normalized)).arg(i);
}
out << QStringLiteral(" }");
out << QStringLiteral("");
out << QString::fromLatin1(" QString name() const Q_DECL_OVERRIDE { return QStringLiteral(\"%1\"); }").arg(astClass.name);
out << QStringLiteral(" int propertyCount() const Q_DECL_OVERRIDE { return _properties[0]; }");
out << QStringLiteral(" int signalCount() const Q_DECL_OVERRIDE { return _signals[0]; }");
out << QStringLiteral(" int methodCount() const Q_DECL_OVERRIDE { return _methods[0]; }");
out << QStringLiteral(" int sourcePropertyIndex(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" if (index < 0 || index >= _properties[0])");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" return _properties[index+1];");
out << QStringLiteral(" }");
out << QStringLiteral(" int sourceSignalIndex(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" if (index < 0 || index >= _signals[0])");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" return _signals[index+1];");
out << QStringLiteral(" }");
out << QStringLiteral(" int sourceMethodIndex(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" if (index < 0 || index >= _methods[0])");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" return _methods[index+1];");
out << QStringLiteral(" }");
if (signalCount+changedCount > 0) {
out << QStringLiteral(" int signalParameterCount(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" if (index < 0 || index >= _signals[0])");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" return signalArgCount[index];");
out << QStringLiteral(" }");
out << QStringLiteral(" int signalParameterType(int sigIndex, int paramIndex) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" if (sigIndex < 0 || sigIndex >= _signals[0] || paramIndex < 0 || paramIndex >= signalArgCount[sigIndex])");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" return signalArgTypes[sigIndex][paramIndex];");
out << QStringLiteral(" }");
} else {
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
out << QStringLiteral(" int signalParameterCount(int index) const Q_DECL_OVERRIDE { Q_UNUSED(index); return -1; }");
out << QStringLiteral(" int signalParameterType(int sigIndex, int paramIndex) const Q_DECL_OVERRIDE");
out << QStringLiteral(" { Q_UNUSED(sigIndex); Q_UNUSED(paramIndex); return -1 }");
}
if (slotCount) {
out << QStringLiteral(" int methodParameterCount(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" if (index < 0 || index >= _methods[0])");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" return methodArgCount[index];");
out << QStringLiteral(" }");
out << QStringLiteral(" int methodParameterType(int methodIndex, int paramIndex) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" if (methodIndex < 0 || methodIndex >= _methods[0] || paramIndex < 0 || paramIndex >= methodArgCount[methodIndex])");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" return methodArgTypes[methodIndex][paramIndex];");
out << QStringLiteral(" }");
} else {
out << QStringLiteral(" int methodParameterCount(int index) const Q_DECL_OVERRIDE { Q_UNUSED(index); return -1; }");
out << QStringLiteral(" int methodParameterType(int methodIndex, int paramIndex) const Q_DECL_OVERRIDE");
out << QStringLiteral(" { Q_UNUSED(methodIndex); Q_UNUSED(paramIndex); return -1; }");
}
//propertyIndexFromSignal method
out << QStringLiteral(" int propertyIndexFromSignal(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
if (!propertyChangeIndex.isEmpty()) {
out << QStringLiteral(" switch (index) {");
for (int i = 0; i < propertyChangeIndex.size(); ++i)
out << QString::fromLatin1(" case %1: return _properties[%2];").arg(i).arg(propertyChangeIndex.at(i));
out << QStringLiteral(" }");
} else
out << QStringLiteral(" Q_UNUSED(index);");
out << QStringLiteral(" return -1;");
out << QStringLiteral(" }");
//signalSignature method
out << QStringLiteral(" const QByteArray signalSignature(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
if (signalCount+changedCount > 0) {
out << QStringLiteral(" switch (index) {");
for (int i = 0; i < changedCount; ++i)
out << QString::fromLatin1(" case %1: return QByteArrayLiteral(\"%2()\");").arg(i).arg(changeSignals.at(i));
for (int i = 0; i < signalCount; ++i)
{
const ASTFunction &sig = astClass.signalsList.at(i);
out << QString::fromLatin1(" case %1: return QByteArrayLiteral(\"%2(%3)\");")
.arg(i+changedCount).arg(sig.name).arg(sig.paramsAsString(ASTFunction::Normalized));
}
out << QStringLiteral(" }");
} else
out << QStringLiteral(" Q_UNUSED(index);");
out << QStringLiteral(" return QByteArrayLiteral(\"\");");
out << QStringLiteral(" }");
//methodSignature method
out << QStringLiteral(" const QByteArray methodSignature(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
if (slotCount) {
out << QStringLiteral(" switch (index) {");
for (int i = 0; i < slotCount; ++i)
{
const ASTFunction &slot = astClass.slotsList.at(i);
out << QString::fromLatin1(" case %1: return QByteArrayLiteral(\"%2(%3)\");")
.arg(i).arg(slot.name).arg(slot.paramsAsString(ASTFunction::Normalized));
}
out << QStringLiteral(" }");
} else
out << QStringLiteral(" Q_UNUSED(index);");
out << QStringLiteral(" return QByteArrayLiteral(\"\");");
out << QStringLiteral(" }");
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
//methodType method
out << QStringLiteral(" QMetaMethod::MethodType methodType(int) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
out << QStringLiteral(" return QMetaMethod::Slot;");
out << QStringLiteral(" }");
//typeName method
out << QStringLiteral(" const QByteArray typeName(int index) const Q_DECL_OVERRIDE");
out << QStringLiteral(" {");
if (slotCount) {
out << QStringLiteral(" switch (index) {");
for (int i = 0; i < slotCount; ++i)
{
const ASTFunction &slot = astClass.slotsList.at(i);
out << QString::fromLatin1(" case %1: return QByteArrayLiteral(\"%2\");").arg(i).arg(slot.returnType);
}
out << QStringLiteral(" }");
} else
out << QStringLiteral(" Q_UNUSED(index);");
out << QStringLiteral(" return QByteArrayLiteral(\"\");");
out << QStringLiteral(" }");
out << QStringLiteral("");
out << QString::fromLatin1(" int _properties[%1];").arg(propCount+1);
out << QString::fromLatin1(" int _signals[%1];").arg(signalCount+changedCount+1);
out << QString::fromLatin1(" int _methods[%1];").arg(slotCount+1);
if (signalCount+changedCount > 0) {
out << QString::fromLatin1(" int signalArgCount[%1];").arg(signalCount+changedCount);
out << QString::fromLatin1(" const int* signalArgTypes[%1];").arg(signalCount+changedCount);
}
out << QString::fromLatin1(" int methodArgCount[%1];").arg(slotCount);
out << QString::fromLatin1(" const int* methodArgTypes[%1];").arg(slotCount);
out << QStringLiteral("};");
}