File indexing completed on 2024-12-08 12:18:20
0001 /* Copyright (C) 2004-2005 ian reinhart geiser <geiseri@sourcextreme.com> */ 0002 0003 #include <kconfig.h> 0004 #include <kmacroexpander.h> 0005 #include <kconfiggroup.h> 0006 #include <kaboutdata.h> 0007 #include <QCommandLineOption> 0008 #include <QCommandLineParser> 0009 #include <QCoreApplication> 0010 #include <QFile> 0011 #include <QFileInfo> 0012 #include <QHash> 0013 #include <QString> 0014 #include <QStringList> 0015 #include <QTextStream> 0016 0017 static const char classHeader[] = "/**\n" 0018 "* This file was autogenerated by kgendesignerplugin. Any changes will be lost!\n" 0019 "* The generated code in this file is licensed under the same license that the\n" 0020 "* input file.\n" 0021 "*/\n" 0022 "#include <QIcon>\n" 0023 "#include <QtDesigner/QDesignerContainerExtension>\n" 0024 "#if QT_VERSION >= 0x050500\n" 0025 "# include <QtUiPlugin/QDesignerCustomWidgetInterface>\n" 0026 "#else\n" 0027 "# include <QDesignerCustomWidgetInterface>\n" 0028 "#endif\n" 0029 "#include <qplugin.h>\n" 0030 "#include <qdebug.h>\n"; 0031 0032 static const char collClassDef[] = "class %CollName : public QObject, public QDesignerCustomWidgetCollectionInterface\n" 0033 "{\n" 0034 " Q_OBJECT\n" 0035 " Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)\n" 0036 " Q_PLUGIN_METADATA(IID \"org.qt-project.Qt.QDesignerCustomWidgetInterface\")\n" 0037 "public:\n" 0038 " %CollName(QObject *parent = nullptr);\n" 0039 " virtual ~%CollName() {}\n" 0040 " QList<QDesignerCustomWidgetInterface*> customWidgets() const Q_DECL_OVERRIDE { return m_plugins; } \n" 0041 " \n" 0042 "private:\n" 0043 " QList<QDesignerCustomWidgetInterface*> m_plugins;\n" 0044 "};\n\n" 0045 ; 0046 0047 static const char collClassImpl[] = "%CollName::%CollName(QObject *parent)\n" 0048 " : QObject(parent)" 0049 "{\n" 0050 "%CollectionAdd\n" 0051 "}\n\n"; 0052 0053 static const char classDef[] = "class %PluginName : public QObject, public QDesignerCustomWidgetInterface\n" 0054 "{\n" 0055 " Q_OBJECT\n" 0056 " Q_INTERFACES(QDesignerCustomWidgetInterface)\n" 0057 "public:\n" 0058 " %PluginName(QObject *parent = nullptr) :\n QObject(parent), mInitialized(false) {}\n" 0059 " virtual ~%PluginName() {}\n" 0060 " \n" 0061 " bool isContainer() const Q_DECL_OVERRIDE { return %IsContainer; }\n" 0062 " bool isInitialized() const Q_DECL_OVERRIDE { return mInitialized; }\n" 0063 " QIcon icon() const Q_DECL_OVERRIDE { return QIcon(QStringLiteral(\"%IconName\")); }\n" 0064 " QString codeTemplate() const Q_DECL_OVERRIDE { return QStringLiteral(\"%CodeTemplate\"); }\n" 0065 " QString domXml() const Q_DECL_OVERRIDE { return %DomXml; }\n" 0066 " QString group() const Q_DECL_OVERRIDE { return QStringLiteral(\"%Group\"); }\n" 0067 " QString includeFile() const Q_DECL_OVERRIDE { return QStringLiteral(\"%IncludeFile\"); }\n" 0068 " QString name() const Q_DECL_OVERRIDE { return QStringLiteral(\"%Class\"); }\n" 0069 " QString toolTip() const Q_DECL_OVERRIDE { return QStringLiteral(\"%ToolTip\"); }\n" 0070 " QString whatsThis() const Q_DECL_OVERRIDE { return QStringLiteral(\"%WhatsThis\"); }\n\n" 0071 " QWidget* createWidget( QWidget* parent ) Q_DECL_OVERRIDE \n {%CreateWidget\n }\n" 0072 " void initialize(QDesignerFormEditorInterface *core) Q_DECL_OVERRIDE \n {%Initialize\n }\n" 0073 "\n" 0074 "private:\n" 0075 " bool mInitialized;\n" 0076 "};\n\n"; 0077 0078 static QString denamespace(const QString &str); 0079 static QString buildCollClass(KConfig &input, const QStringList &classes, const QString &group); 0080 static QString buildWidgetClass(const QString &name, KConfig &input, const QString &group); 0081 static QString buildWidgetInclude(const QString &name, KConfig &input); 0082 static void buildFile(QTextStream &stream, const QString &group, const QString &fileName, const QString &pluginName); 0083 0084 int main(int argc, char **argv) 0085 { 0086 QCoreApplication app(argc, argv); 0087 0088 QString description = QCoreApplication::translate("main", "Builds Qt widget plugins from an ini style description file."); 0089 const QString version = QStringLiteral("0.5"); 0090 app.setApplicationVersion(version); 0091 0092 QCommandLineParser parser; 0093 parser.addVersionOption(); 0094 parser.addHelpOption(); 0095 parser.addPositionalArgument(QStringLiteral("file"), QCoreApplication::translate("main", "Input file.")); 0096 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("o"), QCoreApplication::translate("main", "Output file."), QStringLiteral("file"))); 0097 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("n"), QCoreApplication::translate("main", "Name of the plugin class to generate (deprecated, use PluginName in the input file)."), QStringLiteral("name"), QStringLiteral("WidgetsPlugin"))); 0098 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("g"), QCoreApplication::translate("main", "Default widget group name to display in designer (deprecated, use DefaultGroup in the input file)."), QStringLiteral("group"), QStringLiteral("Custom"))); 0099 0100 KAboutData about(QStringLiteral("kgendesignerplugin"), 0101 QCoreApplication::translate("kgendesignerplugin about data", "kgendesignerplugin"), 0102 version, 0103 description, 0104 KAboutLicense::GPL, 0105 QCoreApplication::translate("kgendesignerplugin about data", "(C) 2004-2005 Ian Reinhart Geiser"), 0106 QString(), 0107 QString(), 0108 QStringLiteral("geiseri@kde.org")); 0109 about.addAuthor(QCoreApplication::translate("kgendesignerplugin about data", "Ian Reinhart Geiser"), QString(), QStringLiteral("geiseri@kde.org")); 0110 about.addAuthor(QCoreApplication::translate("kgendesignerplugin about data", "Daniel Molkentin"), QString(), QStringLiteral("molkentin@kde.org")); 0111 about.setupCommandLine(&parser); 0112 0113 parser.process(app); 0114 about.processCommandLine(&parser); 0115 if (parser.positionalArguments().count() < 1) { 0116 parser.showHelp(); 0117 return 1; 0118 } 0119 0120 QFileInfo fi(parser.positionalArguments().at(0)); 0121 0122 QString outputFile = parser.value(QStringLiteral("o")); 0123 QString pluginName = parser.value(QStringLiteral("n")); 0124 QString group = parser.value(QStringLiteral("g")); 0125 QString fileName = fi.absoluteFilePath(); 0126 0127 if (parser.isSet(QStringLiteral("o"))) { 0128 QFile output(outputFile); 0129 if (output.open(QIODevice::WriteOnly)) { 0130 QTextStream ts(&output); 0131 buildFile(ts, group, fileName, pluginName); 0132 QString mocFile = output.fileName(); 0133 mocFile.replace(QStringLiteral(".cpp"), QStringLiteral(".moc")); 0134 ts << QStringLiteral("#include <%1>\n").arg(mocFile) << '\n'; 0135 } 0136 output.close(); 0137 } else { 0138 QTextStream ts(stdout, QIODevice::WriteOnly); 0139 buildFile(ts, group, fileName, pluginName); 0140 } 0141 } 0142 0143 void buildFile(QTextStream &ts, const QString &group, const QString &fileName, const QString &pluginName) 0144 { 0145 KConfig input(fileName, KConfig::NoGlobals); 0146 KConfigGroup cg(&input, "Global"); 0147 ts << classHeader << '\n'; 0148 0149 QString defaultGroup = cg.readEntry("DefaultGroup", group); 0150 QStringList includes = cg.readEntry("Includes", QStringList()); 0151 QStringList classes = input.groupList(); 0152 classes.removeAll(QStringLiteral("Global")); 0153 0154 for (const QString &myInclude : std::as_const(classes)) { 0155 includes += buildWidgetInclude(myInclude, input); 0156 } 0157 0158 for (const QString &myInclude : std::as_const(includes)) { 0159 ts << "#include <" << myInclude << ">\n"; 0160 } 0161 0162 ts << QLatin1String("\n\n"); 0163 0164 // Autogenerate widget defs here 0165 for (const QString &myClass : std::as_const(classes)) { 0166 ts << buildWidgetClass(myClass, input, defaultGroup) << "\n"; 0167 } 0168 0169 ts << buildCollClass(input, classes, pluginName); 0170 ts.flush(); 0171 0172 } 0173 0174 QString denamespace(const QString &str) 0175 { 0176 QString denamespaced = str; 0177 denamespaced.remove(QStringLiteral("::")); 0178 return denamespaced; 0179 } 0180 0181 QString buildCollClass(KConfig &_input, const QStringList &classes, const QString &pluginName) 0182 { 0183 KConfigGroup input(&_input, "Global"); 0184 QHash<QString, QString> defMap; 0185 const QString collName = input.readEntry("PluginName", pluginName); 0186 Q_ASSERT(!collName.isEmpty()); 0187 defMap.insert(QStringLiteral("CollName"), collName); 0188 QString genCode; 0189 0190 for (const QString &myClass : classes) { 0191 genCode += QStringLiteral(" m_plugins.append( new %1(this) );\n").arg(denamespace(myClass) + QStringLiteral("Plugin")); 0192 } 0193 0194 defMap.insert(QStringLiteral("CollectionAdd"), genCode); 0195 0196 QString str = KMacroExpander::expandMacros(QLatin1String(collClassDef), defMap); 0197 str += KMacroExpander::expandMacros(QLatin1String(collClassImpl), defMap); 0198 return str; 0199 } 0200 0201 QString buildWidgetClass(const QString &name, KConfig &_input, const QString &group) 0202 { 0203 KConfigGroup input(&_input, name); 0204 QHash<QString, QString> defMap; 0205 0206 defMap.insert(QStringLiteral("Group"), input.readEntry("Group", group).replace(QLatin1Char('\"'), QStringLiteral("\\\""))); 0207 defMap.insert(QStringLiteral("IncludeFile"), input.readEntry("IncludeFile", QString(name.toLower() + QStringLiteral(".h"))).remove(QLatin1Char(':'))); 0208 defMap.insert(QStringLiteral("ToolTip"), input.readEntry("ToolTip", QString(name + QStringLiteral(" Widget"))).replace(QLatin1Char('\"'), QStringLiteral("\\\""))); 0209 defMap.insert(QStringLiteral("WhatsThis"), input.readEntry("WhatsThis", QString(name + QStringLiteral(" Widget"))).replace(QLatin1Char('\"'), QStringLiteral("\\\""))); 0210 defMap.insert(QStringLiteral("IsContainer"), input.readEntry("IsContainer", QStringLiteral("false"))); 0211 defMap.insert(QStringLiteral("IconName"), input.readEntry("IconName", QString::fromLatin1(":/pics/%1.png").arg(denamespace(name).toLower()))); 0212 defMap.insert(QStringLiteral("Class"), name); 0213 defMap.insert(QStringLiteral("PluginName"), denamespace(name) + QLatin1String("Plugin")); 0214 0215 // FIXME: ### make this more useful, i.e. outsource to separate file 0216 QString domXml = input.readEntry("DomXML", QString()); 0217 // If domXml is empty then we should call base class function 0218 if (domXml.isEmpty()) { 0219 domXml = QStringLiteral("QDesignerCustomWidgetInterface::domXml()"); 0220 } else { 0221 domXml = QStringLiteral("QStringLiteral(\"%1\")").arg(domXml.replace(QLatin1Char('\"'), QStringLiteral("\\\""))); 0222 } 0223 defMap.insert(QStringLiteral("DomXml"), domXml); 0224 defMap.insert(QStringLiteral("CodeTemplate"), input.readEntry("CodeTemplate")); 0225 defMap.insert(QStringLiteral("CreateWidget"), input.readEntry("CreateWidget", 0226 QStringLiteral("\n return new %1%2;") 0227 .arg(input.readEntry("ImplClass", name)) 0228 .arg(input.readEntry("ConstructorArgs", "( parent )")))); 0229 defMap.insert(QStringLiteral("Initialize"), input.readEntry("Initialize", "\n Q_UNUSED(core);\n if (mInitialized) return;\n mInitialized=true;")); 0230 0231 QString code = KMacroExpander::expandMacros(QLatin1String(classDef), defMap); 0232 return code.replace(QLatin1String("QStringLiteral(\"\")"), QLatin1String("QString()")); 0233 } 0234 0235 QString buildWidgetInclude(const QString &name, KConfig &_input) 0236 { 0237 KConfigGroup input(&_input, name); 0238 return input.readEntry("IncludeFile", QString(name.toLower() + QStringLiteral(".h"))); 0239 }