1 | /* Copyright (C) 2004-2005 ian reinhart geiser <geiseri@sourcextreme.com> */ |
2 | #include <kaboutdata.h> |
3 | #include <kcomponentdata.h> |
4 | #include <kcmdlineargs.h> |
5 | #include <kconfig.h> |
6 | #include <kmacroexpander.h> |
7 | #include <kdebug.h> |
8 | #include <kconfiggroup.h> |
9 | #include <klocale.h> |
10 | #include <QtCore/QFile> |
11 | #include <QtCore/QFileInfo> |
12 | #include <QtCore/QHash> |
13 | #include <QtCore/QString> |
14 | #include <QtCore/QStringList> |
15 | #include <QtCore/QTextStream> |
16 | |
17 | static const char [] = "/**\n" |
18 | "* This file was autogenerated by makekdewidgets. Any changes will be lost!\n" |
19 | "* The generated code in this file is licensed under the same license that the\n" |
20 | "* input file.\n" |
21 | "*/\n" |
22 | "#include <QIcon>\n" |
23 | "#include <QtDesigner/QDesignerContainerExtension>\n" |
24 | "#include <QDesignerCustomWidgetInterface>\n" |
25 | "#include <qplugin.h>\n" |
26 | "#include <qdebug.h>\n" ; |
27 | |
28 | static const char collClassDef[] = "class %CollName : public QObject, public QDesignerCustomWidgetCollectionInterface\n" |
29 | "{\n" |
30 | " Q_OBJECT\n" |
31 | " Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)\n" |
32 | "public:\n" |
33 | " %CollName(QObject *parent = 0);\n" |
34 | " virtual ~%CollName() {}\n" |
35 | " QList<QDesignerCustomWidgetInterface*> customWidgets() const { return m_plugins; } \n" |
36 | " \n" |
37 | "private:\n" |
38 | " QList<QDesignerCustomWidgetInterface*> m_plugins;\n" |
39 | "};\n\n" |
40 | "Q_EXPORT_PLUGIN2(%CollName, %CollName)\n\n" ; |
41 | |
42 | static const char collClassImpl[] = "%CollName::%CollName(QObject *parent)\n" |
43 | " : QObject(parent)" |
44 | "{\n" |
45 | " (void) new KComponentData(\"makekdewidgets\");\n" |
46 | "%CollectionAdd\n" |
47 | "}\n\n" ; |
48 | |
49 | |
50 | static const char classDef[] = "class %PluginName : public QObject, public QDesignerCustomWidgetInterface\n" |
51 | "{\n" |
52 | " Q_OBJECT\n" |
53 | " Q_INTERFACES(QDesignerCustomWidgetInterface)\n" |
54 | "public:\n" |
55 | " %PluginName(QObject *parent = 0) :\n\t\tQObject(parent), mInitialized(false) {}\n" |
56 | " virtual ~%PluginName() {}\n" |
57 | " \n" |
58 | " bool isContainer() const { return %IsContainer; }\n" |
59 | " bool isInitialized() const { return mInitialized; }\n" |
60 | " QIcon icon() const { return QIcon(QLatin1String(\"%IconName\")); }\n" |
61 | " QString codeTemplate() const { return QLatin1String(\"%CodeTemplate\");}\n" |
62 | " QString domXml() const { return %DomXml; }\n" |
63 | " QString group() const { return QLatin1String(\"%Group\"); }\n" |
64 | " QString includeFile() const { return QLatin1String(\"%IncludeFile\"); }\n" |
65 | " QString name() const { return QLatin1String(\"%Class\"); }\n" |
66 | " QString toolTip() const { return QLatin1String(\"%ToolTip\"); }\n" |
67 | " QString whatsThis() const { return QLatin1String(\"%WhatsThis\"); }\n\n" |
68 | " QWidget* createWidget( QWidget* parent ) \n\t{%CreateWidget\n\t}\n" |
69 | " void initialize(QDesignerFormEditorInterface *core) \n\t{%Initialize\n\t}\n" |
70 | "\n" |
71 | "private:\n" |
72 | " bool mInitialized;\n" |
73 | "};\n\n" ; |
74 | |
75 | static QString denamespace ( const QString &str ); |
76 | static QString buildCollClass( KConfig &input, const QStringList& classes ); |
77 | static QString buildWidgetClass( const QString &name, KConfig &input, const QString &group ); |
78 | static QString buildWidgetInclude( const QString &name, KConfig &input ); |
79 | static void buildFile( QTextStream &stream, const QString& group, const QString& fileName, const QString& pluginName ); |
80 | |
81 | int main( int argc, char **argv ) { |
82 | new KComponentData( "makekdewidgets" ); |
83 | |
84 | KLocalizedString description = ki18n( "Builds Qt widget plugins from an ini style description file." ); |
85 | const char version[] = "0.4" ; |
86 | |
87 | KCmdLineOptions options; |
88 | options.add("+file" , ki18n( "Input file" ) ); |
89 | options.add("o <file>" , ki18n( "Output file" ) ); |
90 | options.add("n <plugin name>" , ki18n( "Name of the plugin class to generate" ), "WidgetsPlugin" ); |
91 | options.add("g <group>" , ki18n( "Default widget group name to display in designer" ), "Custom" ); |
92 | |
93 | |
94 | KAboutData about( "makekdewidgets" , 0, ki18n( "makekdewidgets" ), version, description, KAboutData::License_GPL, ki18n("(C) 2004-2005 Ian Reinhart Geiser" ), KLocalizedString(), 0, "geiseri@kde.org" ); |
95 | about.addAuthor( ki18n("Ian Reinhart Geiser" ), KLocalizedString(), "geiseri@kde.org" ); |
96 | about.addAuthor( ki18n("Daniel Molkentin" ), KLocalizedString(), "molkentin@kde.org" ); |
97 | KCmdLineArgs::init( argc, argv, &about ); |
98 | KCmdLineArgs::addCmdLineOptions( options ); |
99 | KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); |
100 | if ( args->count() < 1 ) { |
101 | args->usage(); |
102 | return ( 1 ); |
103 | } |
104 | |
105 | QFileInfo fi( args->arg( args->count() - 1 ) ); |
106 | |
107 | QString outputFile = args->getOption( "o" ); |
108 | QString pluginName = args->getOption( "n" ); |
109 | QString group = args->getOption( "g" ); |
110 | QString fileName = fi.absoluteFilePath(); |
111 | |
112 | if ( args->isSet( "o" ) ) { |
113 | QFile output( outputFile ); |
114 | if ( output.open( QIODevice::WriteOnly ) ) { |
115 | QTextStream ts( &output ); |
116 | buildFile( ts, group, fileName , pluginName ); |
117 | QString mocFile = output.fileName(); |
118 | mocFile.replace(".cpp" , ".moc" ); |
119 | ts << QString( "#include <%1>\n" ).arg(mocFile) << endl; |
120 | } |
121 | output.close(); |
122 | } else { |
123 | QTextStream ts( stdout, QIODevice::WriteOnly ); |
124 | buildFile( ts, group, fileName , pluginName ); |
125 | } |
126 | } |
127 | |
128 | void buildFile( QTextStream &ts, const QString& group, const QString& fileName, const QString& pluginName ) { |
129 | KConfig input( fileName, KConfig::NoGlobals ); |
130 | KConfigGroup cg(&input, "Global" ); |
131 | QHash<QString, QString> MainMap; |
132 | MainMap.insert( "PluginName" , cg.readEntry( "PluginName" , pluginName ) ); |
133 | MainMap.insert( "PluginNameLower" , cg.readEntry( "PluginName" , pluginName ).toLower() ); |
134 | MainMap.insert( "Init" , cg.readEntry( "Init" , "" ) ); |
135 | MainMap.insert( "Destroy" , cg.readEntry( "Destroy" , "" ) ); |
136 | ts << classHeader << endl; |
137 | |
138 | QStringList includes = cg.readEntry( "Includes" , QStringList() ); |
139 | QStringList classes = input.groupList(); |
140 | classes.removeAll( "Global" ); |
141 | |
142 | foreach ( const QString &myInclude, classes ) |
143 | includes += buildWidgetInclude( myInclude, input ); |
144 | |
145 | foreach ( const QString &myInclude, includes) |
146 | ts << "#include <" << myInclude << ">" << endl; |
147 | |
148 | ts << QLatin1String("\n\n" ); |
149 | |
150 | // Autogenerate widget defs here |
151 | foreach ( const QString &myClass, classes ) |
152 | ts << buildWidgetClass( myClass, input, group ) << endl; |
153 | |
154 | ts << buildCollClass( input, classes ); |
155 | |
156 | } |
157 | |
158 | QString denamespace ( const QString &str ) { |
159 | QString denamespaced = str; |
160 | denamespaced.remove("::" ); |
161 | return denamespaced; |
162 | } |
163 | |
164 | QString buildCollClass( KConfig &_input, const QStringList& classes ) { |
165 | KConfigGroup input(&_input, "Global" ); |
166 | QHash<QString, QString> defMap; |
167 | defMap.insert( "CollName" , input.readEntry( "PluginName" ) ); |
168 | QString genCode; |
169 | |
170 | foreach ( const QString &myClass, classes ) |
171 | { |
172 | genCode += QString("\t\tm_plugins.append( new %1(this) );\n" ).arg(denamespace( myClass ) +"Plugin" ); |
173 | } |
174 | |
175 | defMap.insert( "CollectionAdd" , genCode ); |
176 | |
177 | QString str = KMacroExpander::expandMacros(collClassDef, defMap); |
178 | str += KMacroExpander::expandMacros(collClassImpl, defMap); |
179 | return str; |
180 | } |
181 | |
182 | QString buildWidgetClass( const QString &name, KConfig &_input, const QString &group ) { |
183 | KConfigGroup input(&_input, name); |
184 | QHash<QString, QString> defMap; |
185 | |
186 | defMap.insert( "Group" , input.readEntry( "Group" , group ).replace( '\"', "\\\"" ) ); |
187 | defMap.insert( "IconSet" , input.readEntry( "IconSet" , QString(name.toLower() + ".png" ) ).replace( ':', '_' ) ); |
188 | defMap.insert( "Pixmap" , name.toLower().replace( ':', '_' ) + "_xpm" ); |
189 | defMap.insert( "IncludeFile" , input.readEntry( "IncludeFile" , QString(name.toLower() + ".h" ) ).remove( ':' ) ); |
190 | defMap.insert( "ToolTip" , input.readEntry( "ToolTip" , QString(name + " Widget" ) ).replace( '\"', "\\\"" ) ); |
191 | defMap.insert( "WhatsThis" , input.readEntry( "WhatsThis" , QString(name + " Widget" ) ).replace( '\"', "\\\"" ) ); |
192 | defMap.insert( "IsContainer" , input.readEntry( "IsContainer" , "false" ) ); |
193 | defMap.insert( "IconName" , input.readEntry( "IconName" , QString::fromLatin1(":/pics/%1.png" ).arg( denamespace( name ).toLower() ) ) ); |
194 | defMap.insert( "Class" , name ); |
195 | defMap.insert( "PluginName" , denamespace( name ) + QLatin1String( "Plugin" ) ); |
196 | |
197 | // FIXME: ### make this more useful, i.e. outsource to separate file |
198 | QString domXml = input.readEntry("DomXML" , QString()); |
199 | // If domXml is empty then we shoud call base class function |
200 | if ( domXml.isEmpty() ) { |
201 | domXml = QLatin1String("QDesignerCustomWidgetInterface::domXml()" ); |
202 | } |
203 | else { |
204 | // Wrap domXml value into QLatin1String |
205 | domXml = QString(QLatin1String("QLatin1String(\"%1\")" )).arg(domXml.replace( '\"', "\\\"" )); |
206 | } |
207 | defMap.insert( "DomXml" , domXml ); |
208 | defMap.insert( "CodeTemplate" , input.readEntry( "CodeTemplate" ) ); |
209 | defMap.insert( "CreateWidget" , input.readEntry( "CreateWidget" , |
210 | QString( "\n\t\treturn new %1%2;" ) |
211 | .arg( input.readEntry( "ImplClass" , name ) ) |
212 | .arg( input.readEntry( "ConstructorArgs" , "( parent )" ) ) ) ); |
213 | defMap.insert( "Initialize" , input.readEntry( "Initialize" , "\n\t\tQ_UNUSED(core);\n\t\tif (mInitialized) return;\n\t\tmInitialized=true;" ) ); |
214 | |
215 | return KMacroExpander::expandMacros( classDef, defMap ); |
216 | } |
217 | |
218 | QString buildWidgetInclude( const QString &name, KConfig &_input ) { |
219 | KConfigGroup input(&_input, name); |
220 | return input.readEntry( "IncludeFile" , QString(name.toLower() + ".h" ) ); |
221 | } |
222 | |