📄 generator.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the tools applications of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "generator.h"#include "outputrevision.h"#include "utils.h"#include <QtCore/qmetatype.h>#include <stdio.h>// if the flags change, you MUST to change it in qmetaobject.cpp tooenum PropertyFlags { Invalid = 0x00000000, Readable = 0x00000001, Writable = 0x00000002, Resettable = 0x00000004, EnumOrFlag = 0x00000008, StdCppSet = 0x00000100,// Override = 0x00000200, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, ResolveScriptable = 0x00008000, Stored = 0x00010000, ResolveStored = 0x00020000, Editable = 0x00040000, ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000};enum MethodFlags { AccessPrivate = 0x00, AccessProtected = 0x01, AccessPublic = 0x02, MethodMethod = 0x00, MethodSignal = 0x04, MethodSlot = 0x08, MethodCompatibility = 0x10, MethodCloned = 0x20, MethodScriptable = 0x40};uint qvariant_nameToType(const char* name){ if (!name) return 0; if (strcmp(name, "QVariant") == 0) return 0xffffffff; if (strcmp(name, "QCString") == 0) return QMetaType::QByteArray; if (strcmp(name, "Q_LLONG") == 0) return QMetaType::LongLong; if (strcmp(name, "Q_ULLONG") == 0) return QMetaType::ULongLong; if (strcmp(name, "QIconSet") == 0) return QMetaType::QIcon; uint tp = QMetaType::type(name); return tp < QMetaType::User ? tp : 0;}/* Returns true if the type is a QVariant types.*/bool isVariantType(const char* type){ return qvariant_nameToType(type) != 0;}Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile) : out(outfile), cdef(classDef), metaTypes(metaTypes){ if (cdef->superclassList.size()) purestSuperClass = cdef->superclassList.first().first;}static inline int lengthOfEscapeSequence(const QByteArray &s, int i){ if (s.at(i) != '\\' || i >= s.length() - 1) return 1; const int startPos = i; ++i; char ch = s.at(i); if (ch == 'x') { ++i; while (i < s.length() && is_hex_char(s.at(i))) ++i; } else if (is_octal_char(ch)) { while (i < startPos + 4 && i < s.length() && is_octal_char(s.at(i))) { ++i; } } else { // single character escape sequence i = qMin(i + 1, s.length()); } return i - startPos;}int Generator::strreg(const char *s){ int idx = 0; if (!s) s = ""; for (int i = 0; i < strings.size(); ++i) { const QByteArray &str = strings.at(i); if (str == s) return idx; idx += str.length() + 1; for (int i = 0; i < str.length(); ++i) { if (str.at(i) == '\\') { int cnt = lengthOfEscapeSequence(str, i) - 1; idx -= cnt; i += cnt; } } } strings.append(s); return idx;}void Generator::generateCode(){ bool isQt = (cdef->classname == "Qt"); bool isQObject = (cdef->classname == "QObject");//// build the data array// int i = 0; // filter out undeclared enumerators and sets { QList<EnumDef> enumList; for (i = 0; i < cdef->enumList.count(); ++i) { EnumDef def = cdef->enumList.at(i); if (cdef->enumDeclarations.contains(def.name)) { enumList += def; } QByteArray alias = cdef->flagAliases.value(def.name); if (cdef->enumDeclarations.contains(alias)) { def.name = alias; enumList += def; } } cdef->enumList = enumList; } QByteArray qualifiedClassNameIdentifier = cdef->qualified; qualifiedClassNameIdentifier.replace(':', '_'); int index = 10; fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "\n // content:\n"); fprintf(out, " %4d, // revision\n", 1); fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); index += cdef->classInfoList.count() * 2; int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0); index += methodCount * 5; fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0); index += cdef->propertyList.count() * 3; fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0);//// Build classinfo array// generateClassInfos();//// Build signals array first, otherwise the signal indices would be wrong// generateFunctions(cdef->signalList, "signal", MethodSignal);//// Build slots array// generateFunctions(cdef->slotList, "slot", MethodSlot);//// Build method array// generateFunctions(cdef->methodList, "method", MethodMethod);//// Build property array// generateProperties();//// Build enums array// generateEnums(index);//// Terminate data array// fprintf(out, "\n 0 // eod\n};\n\n");//// Build stringdata array// fprintf(out, "static const char qt_meta_stringdata_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, " \""); int col = 0; int len = 0; for (i = 0; i < strings.size(); ++i) { QByteArray s = strings.at(i); len = s.length(); if (col && col + len >= 72) { fprintf(out, "\"\n \""); col = 0; } else if (len && s.at(0) >= '0' && s.at(0) <= '9') { fprintf(out, "\"\""); len += 2; } int idx = 0; while (idx < s.length()) { if (idx > 0) { col = 0; fprintf(out, "\"\n \""); } int spanLen = qMin(70, s.length() - idx); // don't cut escape sequences at the end of a line int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1); if (backSlashPos >= idx) { int escapeLen = lengthOfEscapeSequence(s, backSlashPos); spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx); } fwrite(s.constData() + idx, 1, spanLen, out); idx += spanLen; col += spanLen; } fputs("\\0", out); col += len + 2; } fprintf(out, "\"\n};\n\n");//// Build extra array// QList<QByteArray> extraList; for (int i = 0; i < cdef->propertyList.count(); ++i) { const PropertyDef &p = cdef->propertyList.at(i); if (!isVariantType(p.type) && !metaTypes.contains(p.type)) { int s = p.type.lastIndexOf("::"); if (s > 0) { QByteArray scope = p.type.left(s); if (scope != "Qt" && scope != cdef->classname && !extraList.contains(scope)) extraList += scope; } } } if (!extraList.isEmpty()) { fprintf(out, "static const QMetaObject *qt_meta_extradata_%s[] = {\n ", qualifiedClassNameIdentifier.constData()); for (int i = 0; i < extraList.count(); ++i) { if (i) fprintf(out, ",\n "); fprintf(out, " &%s::staticMetaObject", extraList.at(i).constData()); } fprintf(out, ",0\n};\n\n"); }//// Finally create and initialize the static meta object// if (isQt) fprintf(out, "const QMetaObject QObject::staticQtMetaObject = {\n"); else fprintf(out, "const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData()); if (isQObject) fprintf(out, " { 0, "); else if (cdef->superclassList.size()) fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData()); else fprintf(out, " { 0, "); fprintf(out, "qt_meta_stringdata_%s,\n qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); if (extraList.isEmpty()) fprintf(out, "0 }\n"); else fprintf(out, "qt_meta_extradata_%s }\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "};\n"); if (isQt || !cdef->hasQObject) return; fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return &staticMetaObject;\n}\n", cdef->qualified.constData());//// Generate smart cast function// fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData()); fprintf(out, " if (!_clname) return 0;\n"); fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s))\n" "\treturn static_cast<void*>(const_cast< %s*>(this));\n", qualifiedClassNameIdentifier.constData(), cdef->classname.constData()); for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one if (cdef->superclassList.at(i).second == FunctionDef::Private) continue; const char *cname = cdef->superclassList.at(i).first; fprintf(out, " if (!strcmp(_clname, \"%s\"))\n\treturn static_cast< %s*>(const_cast< %s*>(this));\n", cname, cname, cdef->classname.constData()); } for (int i = 0; i < cdef->interfaceList.size(); ++i) { const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i); for (int j = 0; j < iface.size(); ++j) { fprintf(out, " if (!strcmp(_clname, %s))\n\treturn ", iface.at(j).interfaceId.constData()); for (int k = j; k >= 0; --k) fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData()); fprintf(out, "const_cast< %s*>(this)%s;\n", cdef->classname.constData(), QByteArray(j+1, ')').constData()); } } if (!purestSuperClass.isEmpty() && !isQObject) { QByteArray superClass = purestSuperClass; // workaround for VC6 if (superClass.contains("::")) { fprintf(out, " typedef %s QMocSuperClass;\n", superClass.constData()); superClass = "QMocSuperClass"; } fprintf(out, " return %s::qt_metacast(_clname);\n", superClass.constData()); } else { fprintf(out, " return 0;\n"); } fprintf(out, "}\n");//// Generate internal qt_metacall() function// generateMetacall();//// Generate internal signal functions// for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex) generateSignal(&cdef->signalList[signalindex], signalindex);}void Generator::generateClassInfos(){ if (cdef->classInfoList.isEmpty()) return; fprintf(out, "\n // classinfo: key, value\n"); for (int i = 0; i < cdef->classInfoList.size(); ++i) { const ClassInfoDef &c = cdef->classInfoList.at(i); fprintf(out, " %4d, %4d,\n", strreg(c.name), strreg(c.value)); }}void Generator::generateFunctions(QList<FunctionDef>& list, const char *functype, int type){ if (list.isEmpty()) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -