source: trunk/tools/designer/uic/form.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 51.1 KB
Line 
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qt Designer.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
12** licenses may use this file in accordance with the Qt Commercial License
13** Agreement provided with the Software.
14**
15** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17**
18** See http://www.trolltech.com/gpl/ for GPL licensing information.
19** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
20** information about Qt Commercial License Agreements.
21**
22** Contact info@trolltech.com if any conditions of this licensing are
23** not clear to you.
24**
25**********************************************************************/
26
27#include "uic.h"
28#include "parser.h"
29#include "widgetdatabase.h"
30#include "domtool.h"
31#include <qstringlist.h>
32#include <qvaluelist.h>
33#include <qfile.h>
34#include <qfileinfo.h>
35#include <qdir.h>
36#include <qregexp.h>
37#define NO_STATIC_COLORS
38#include <globaldefs.h>
39
40static QByteArray unzipXPM( QString data, ulong& length )
41{
42 const int lengthOffset = 4;
43 int baSize = data.length() / 2 + lengthOffset;
44 uchar *ba = new uchar[ baSize ];
45 for ( int i = lengthOffset; i < baSize; ++i ) {
46 char h = data[ 2 * (i-lengthOffset) ].latin1();
47 char l = data[ 2 * (i-lengthOffset) + 1 ].latin1();
48 uchar r = 0;
49 if ( h <= '9' )
50 r += h - '0';
51 else
52 r += h - 'a' + 10;
53 r = r << 4;
54 if ( l <= '9' )
55 r += l - '0';
56 else
57 r += l - 'a' + 10;
58 ba[ i ] = r;
59 }
60 // qUncompress() expects the first 4 bytes to be the expected length of the
61 // uncompressed data
62 ba[0] = ( length & 0xff000000 ) >> 24;
63 ba[1] = ( length & 0x00ff0000 ) >> 16;
64 ba[2] = ( length & 0x0000ff00 ) >> 8;
65 ba[3] = ( length & 0x000000ff );
66 QByteArray baunzip = qUncompress( ba, baSize );
67 delete[] ba;
68 return baunzip;
69}
70
71#if QT_VERSION >= 0x030900
72#error Add this functionality to QDir (relativePathTo() maybe?) and \
73remove it from here and from moc
74#endif
75
76QCString combinePath( const char *infile, const char *outfile )
77{
78 QFileInfo inFileInfo( QDir::current(), QFile::decodeName(infile) );
79 QFileInfo outFileInfo( QDir::current(), QFile::decodeName(outfile) );
80 int numCommonComponents = 0;
81
82 QStringList inSplitted =
83 QStringList::split( '/', inFileInfo.dir().canonicalPath(), TRUE );
84 QStringList outSplitted =
85 QStringList::split( '/', outFileInfo.dir().canonicalPath(), TRUE );
86
87 while ( !inSplitted.isEmpty() && !outSplitted.isEmpty() &&
88 inSplitted.first() == outSplitted.first() ) {
89 inSplitted.remove( inSplitted.begin() );
90 outSplitted.remove( outSplitted.begin() );
91 numCommonComponents++;
92 }
93
94 if ( numCommonComponents < 2 ) {
95 /*
96 The paths don't have the same drive, or they don't have the
97 same root directory. Use an absolute path.
98 */
99 return QFile::encodeName( inFileInfo.absFilePath() );
100 } else {
101 /*
102 The paths have something in common. Use a path relative to
103 the output file.
104 */
105 while ( !outSplitted.isEmpty() ) {
106 outSplitted.remove( outSplitted.begin() );
107 inSplitted.prepend( ".." );
108 }
109 inSplitted.append( inFileInfo.fileName() );
110 return QFile::encodeName( inSplitted.join("/") );
111 }
112}
113
114/*!
115 Creates a declaration (header file) for the form given in \a e
116
117 \sa createFormImpl(), createObjectDecl()
118*/
119void Uic::createFormDecl( const QDomElement &e )
120{
121 QDomElement n;
122 QDomNodeList nl;
123 int i;
124 QString objClass = getClassName( e );
125 if ( objClass.isEmpty() )
126 return;
127 QString objName = getObjectName( e );
128
129 QStringList typeDefs;
130
131 QMap<QString, CustomInclude> customWidgetIncludes;
132
133 QString imageMembers;
134
135 /*
136 We are generating a few QImage members that are not strictly
137 necessary in some cases. Ideally, we would use requiredImage,
138 which is computed elsewhere, to keep the generated .h and .cpp
139 files synchronized.
140 */
141
142 // at first the images
143 QMap<QString, int> customWidgets;
144 QStringList forwardDecl;
145 QStringList forwardDecl2;
146 QString exportMacro;
147 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
148 if ( n.tagName() == "images" ) {
149 nl = n.elementsByTagName( "image" );
150 for ( i = 0; i < (int) nl.length(); i++ ) {
151 QString img = registerObject( nl.item(i).toElement().attribute("name") );
152 registerObject( img );
153 imageMembers += QString( " QPixmap %1;\n" ).arg( img );
154 }
155 } else if ( n.tagName() == "customwidgets" ) {
156 QDomElement n2 = n.firstChild().toElement();
157 while ( !n2.isNull() ) {
158 if ( n2.tagName() == "customwidget" ) {
159 QDomElement n3 = n2.firstChild().toElement();
160 QString cl;
161 WidgetDatabaseRecord *r = new WidgetDatabaseRecord;
162 while ( !n3.isNull() ) {
163 if ( n3.tagName() == "class" ) {
164 cl = n3.firstChild().toText().data();
165 if ( !nofwd )
166 forwardDecl << cl;
167 customWidgets.insert( cl, 0 );
168 r->name = cl;
169 } else if ( n3.tagName() == "header" ) {
170 CustomInclude ci;
171 ci.header = n3.firstChild().toText().data();
172 ci.location = n3.attribute( "location", "global" );
173 r->includeFile = ci.header;
174 customWidgetIncludes.insert( cl, ci );
175 }
176 WidgetDatabase::append( r );
177 n3 = n3.nextSibling().toElement();
178 }
179 }
180 n2 = n2.nextSibling().toElement();
181 }
182 }
183 }
184
185 // register the object and unify its name
186 objName = registerObject( objName );
187 QString protector = objName.upper() + "_H";
188 protector.replace( "::", "_" );
189 out << "#ifndef " << protector << endl;
190 out << "#define " << protector << endl;
191 out << endl;
192 out << "#include <qvariant.h>" << endl; // for broken HP-UX compilers
193
194 if ( !imageMembers.isEmpty() )
195 out << "#include <qpixmap.h>" << endl;
196
197 QStringList globalIncludes, localIncludes;
198 int wid = WidgetDatabase::idFromClassName( objClass );
199 {
200 QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find( objClass );
201 if ( it != customWidgetIncludes.end() ) {
202 if ( ( *it ).location == "global" )
203 globalIncludes += (*it).header;
204 else
205 localIncludes += (*it).header;
206 } else {
207 globalIncludes += WidgetDatabase::includeFile( wid );
208 }
209 }
210
211 nl = e.parentNode().toElement().elementsByTagName( "include" );
212 for ( i = 0; i < (int) nl.length(); i++ ) {
213 QDomElement n2 = nl.item(i).toElement();
214 QString s = n2.firstChild().toText().data();
215 if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
216 n2.attribute( "location" ) != "local" ) {
217 if ( s.right( 5 ) == ".ui.h" )
218 continue;
219 globalIncludes += s;
220 }
221 }
222 for ( i = 0; i < (int) nl.length(); i++ ) {
223 QDomElement n2 = nl.item(i).toElement();
224 QString s = n2.firstChild().toText().data();
225 if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
226 n2.attribute( "location" ) == "local" &&!globalIncludes.contains( s ) ) {
227 if ( s.right( 5 ) == ".ui.h" )
228 continue;
229 localIncludes += s;
230 }
231 }
232
233 QStringList::Iterator it;
234
235 globalIncludes = unique( globalIncludes );
236 for ( it = globalIncludes.begin(); it != globalIncludes.end(); ++it ) {
237 if ( !(*it).isEmpty() )
238 out << "#include <" << *it << ">" << endl;
239 }
240 localIncludes = unique( localIncludes );
241 for ( it = localIncludes.begin(); it != localIncludes.end(); ++it ) {
242 if ( !(*it).isEmpty() )
243 out << "#include \"" << *it << "\"" << endl;
244 }
245 out << endl;
246
247 // forward declarations for child widgets and layouts
248 out << "class QVBoxLayout;" << endl;
249 out << "class QHBoxLayout;" << endl;
250 out << "class QGridLayout;" << endl;
251 out << "class QSpacerItem;" << endl;
252 if ( objClass == "QMainWindow" ) {
253 out << "class QAction;" << endl;
254 out << "class QActionGroup;" << endl;
255 out << "class QToolBar;" << endl;
256 out << "class QPopupMenu;" << endl;
257 }
258
259 bool dbForm = FALSE;
260 registerDatabases( e );
261 dbConnections = unique( dbConnections );
262 if ( dbConnections.count() )
263 forwardDecl += "QSqlDatabase";
264 if ( dbCursors.count() )
265 forwardDecl += "QSqlCursor";
266 if ( dbForms[ "(default)" ].count() )
267 dbForm = TRUE;
268 bool subDbForms = FALSE;
269 for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
270 if ( !(*it).isEmpty() && (*it) != "(default)" ) {
271 if ( dbForms[ (*it) ].count() ) {
272 subDbForms = TRUE;
273 break;
274 }
275 }
276 }
277 if ( dbForm || subDbForms )
278 forwardDecl += "QSqlForm";
279
280 for ( it = tags.begin(); it != tags.end(); ++it ) {
281 nl = e.parentNode().toElement().elementsByTagName( *it );
282 for ( i = 1; i < (int) nl.length(); i++ ) { // begin at 1, 0 is the toplevel widget
283 QString s = getClassName( nl.item(i).toElement() );
284 if ( s == "QLayoutWidget" )
285 continue; // hide qlayoutwidgets
286 if ( s == "Line" )
287 s = "QFrame";
288 if ( !(nofwd && customWidgets.contains(s)) )
289 forwardDecl += s;
290 if ( s.mid( 1 ) == "ListBox" || s.mid( 1 ) == "ListView" || s.mid( 1 ) == "IconView" )
291 forwardDecl += "Q" + s.mid( 1 ) + "Item";
292 if ( s == "QDataTable" ) { // other convenience classes which are used in QDataTable signals, and thus should be forward-declared by uic for us
293 forwardDecl += "QSqlRecord";
294 }
295 }
296 }
297
298 // some typedefs, maybe
299 typeDefs = unique( typeDefs );
300 for ( it = typeDefs.begin(); it != typeDefs.end(); ++it ) {
301 if ( !(*it).isEmpty() )
302 out << "typedef " << *it << ";" << endl;
303 }
304
305 nl = e.parentNode().toElement().elementsByTagName( "forward" );
306 for ( i = 0; i < (int) nl.length(); i++ )
307 forwardDecl2 << nl.item(i).toElement().firstChild().toText().data();
308
309 nl = e.parentNode().toElement().elementsByTagName( "include" );
310 for ( i = 0; i < (int) nl.length(); i++ ) {
311 QDomElement n2 = nl.item(i).toElement();
312 QString s = n2.firstChild().toText().data();
313 if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
314 n2.attribute( "location" ) != "local" )
315 globalIncludes += s;
316 }
317 for ( i = 0; i < (int) nl.length(); i++ ) {
318 QDomElement n2 = nl.item(i).toElement();
319 QString s = n2.firstChild().toText().data();
320 if ( n2.attribute( "impldecl", "in implementation" ) == "in declaration" &&
321 n2.attribute( "location" ) == "local" &&!globalIncludes.contains( s ) )
322 localIncludes += s;
323 }
324 nl = e.parentNode().toElement().elementsByTagName( "exportmacro" );
325 if ( nl.length() == 1 )
326 exportMacro = nl.item( 0 ).firstChild().toText().data();
327
328 forwardDecl = unique( forwardDecl );
329 for ( it = forwardDecl.begin(); it != forwardDecl.end(); ++it ) {
330 if ( !(*it).isEmpty() && (*it) != objClass ) {
331 QString forwardName = *it;
332 QStringList forwardNamespaces = QStringList::split( "::",
333 forwardName );
334 forwardName = forwardNamespaces.last();
335 forwardNamespaces.remove( forwardNamespaces.fromLast() );
336
337 QStringList::ConstIterator ns = forwardNamespaces.begin();
338 while ( ns != forwardNamespaces.end() ) {
339 out << "namespace " << *ns << " {" << endl;
340 ++ns;
341 }
342 out << "class " << forwardName << ";" << endl;
343 for ( int i = 0; i < (int) forwardNamespaces.count(); i++ )
344 out << "}" << endl;
345 }
346 }
347
348 for ( it = forwardDecl2.begin(); it != forwardDecl2.end(); ++it ) {
349 QString fd = *it;
350 fd = fd.stripWhiteSpace();
351 if ( !fd.endsWith( ";" ) )
352 fd += ";";
353 out << fd << endl;
354 }
355
356 out << endl;
357
358 QStringList::ConstIterator ns = namespaces.begin();
359 while ( ns != namespaces.end() ) {
360 out << "namespace " << *ns << " {" << endl;
361 ++ns;
362 }
363
364 out << "class ";
365 if ( !exportMacro.isEmpty() )
366 out << exportMacro << " ";
367 out << bareNameOfClass << " : public " << objClass << endl << "{" << endl;
368
369 /* qmake ignore Q_OBJECT */
370 out << " Q_OBJECT" << endl;
371 out << endl;
372 out << "public:" << endl;
373
374 // constructor
375 if ( objClass == "QDialog" || objClass == "QWizard" ) {
376 out << " " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );" << endl;
377 } else if ( objClass == "QWidget" ) {
378 out << " " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );" << endl;
379 } else if ( objClass == "QMainWindow" ) {
380 out << " " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0, WFlags fl = WType_TopLevel );" << endl;
381 isMainWindow = TRUE;
382 } else {
383 out << " " << bareNameOfClass << "( QWidget* parent = 0, const char* name = 0 );" << endl;
384 }
385
386 // destructor
387 out << " ~" << bareNameOfClass << "();" << endl;
388 out << endl;
389
390 // children
391 bool needPolish = FALSE;
392 nl = e.parentNode().toElement().elementsByTagName( "widget" );
393 for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
394 n = nl.item(i).toElement();
395 createObjectDecl( n );
396 QString t = n.tagName();
397 if ( t == "vbox" || t == "hbox" || t == "grid" )
398 createSpacerDecl( n );
399 QString s = getClassName( n );
400 if ( s == "QDataTable" || s == "QDataBrowser" ) {
401 if ( isFrameworkCodeGenerated( n ) )
402 needPolish = TRUE;
403 }
404 }
405
406 // actions, toolbars, menus
407 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
408 if ( n.tagName() == "actions" ) {
409 for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
410 createActionDecl( a );
411 } else if ( n.tagName() == "toolbars" ) {
412 for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
413 createToolbarDecl( a );
414 } else if ( n.tagName() == "menubar" ) {
415 out << " " << "QMenuBar *" << getObjectName( n ) << ";" << endl;
416 for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
417 createMenuBarDecl( a );
418 }
419 }
420 out << endl;
421
422 // database connections
423 dbConnections = unique( dbConnections );
424 bool hadOutput = FALSE;
425 for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
426 if ( !(*it).isEmpty() ) {
427 // only need pointers to non-default connections
428 if ( (*it) != "(default)" && !(*it).isEmpty() ) {
429 out << indent << "QSqlDatabase* " << *it << "Connection;" << endl;
430 hadOutput = TRUE;
431 }
432 }
433 }
434 if ( hadOutput )
435 out << endl;
436
437 QStringList publicSlots, protectedSlots, privateSlots;
438 QStringList publicSlotTypes, protectedSlotTypes, privateSlotTypes;
439 QStringList publicSlotSpecifier, protectedSlotSpecifier, privateSlotSpecifier;
440
441 nl = e.parentNode().toElement().elementsByTagName( "slot" );
442 for ( i = 0; i < (int) nl.length(); i++ ) {
443 n = nl.item(i).toElement();
444 if ( n.parentNode().toElement().tagName() != "slots"
445 && n.parentNode().toElement().tagName() != "connections" )
446 continue;
447 if ( n.attribute( "language", "C++" ) != "C++" )
448 continue;
449 QString returnType = n.attribute( "returnType", "void" );
450 QString functionName = n.firstChild().toText().data().stripWhiteSpace();
451 if ( functionName.endsWith( ";" ) )
452 functionName = functionName.left( functionName.length() - 1 );
453 QString specifier = n.attribute( "specifier" );
454 QString access = n.attribute( "access" );
455 if ( access == "protected" ) {
456 protectedSlots += functionName;
457 protectedSlotTypes += returnType;
458 protectedSlotSpecifier += specifier;
459 } else if ( access == "private" ) {
460 privateSlots += functionName;
461 privateSlotTypes += returnType;
462 privateSlotSpecifier += specifier;
463 } else {
464 publicSlots += functionName;
465 publicSlotTypes += returnType;
466 publicSlotSpecifier += specifier;
467 }
468 }
469
470 QStringList publicFuncts, protectedFuncts, privateFuncts;
471 QStringList publicFunctRetTyp, protectedFunctRetTyp, privateFunctRetTyp;
472 QStringList publicFunctSpec, protectedFunctSpec, privateFunctSpec;
473
474 nl = e.parentNode().toElement().elementsByTagName( "function" );
475 for ( i = 0; i < (int) nl.length(); i++ ) {
476 n = nl.item( i ).toElement();
477 if ( n.parentNode().toElement().tagName() != "functions" )
478 continue;
479 if ( n.attribute( "language", "C++" ) != "C++" )
480 continue;
481 QString returnType = n.attribute( "returnType", "void" );
482 QString functionName = n.firstChild().toText().data().stripWhiteSpace();
483 if ( functionName.endsWith( ";" ) )
484 functionName = functionName.left( functionName.length() - 1 );
485 QString specifier = n.attribute( "specifier" );
486 QString access = n.attribute( "access" );
487 if ( access == "protected" ) {
488 protectedFuncts += functionName;
489 protectedFunctRetTyp += returnType;
490 protectedFunctSpec += specifier;
491 } else if ( access == "private" ) {
492 privateFuncts += functionName;
493 privateFunctRetTyp += returnType;
494 privateFunctSpec += specifier;
495 } else {
496 publicFuncts += functionName;
497 publicFunctRetTyp += returnType;
498 publicFunctSpec += specifier;
499 }
500 }
501
502 QStringList publicVars, protectedVars, privateVars;
503 nl = e.parentNode().toElement().elementsByTagName( "variable" );
504 for ( i = 0; i < (int)nl.length(); i++ ) {
505 n = nl.item( i ).toElement();
506 // Because of compatibility the next lines have to be commented out.
507 // Someday it should be uncommented.
508 //if ( n.parentNode().toElement().tagName() != "variables" )
509 // continue;
510 QString access = n.attribute( "access", "protected" );
511 QString var = n.firstChild().toText().data().stripWhiteSpace();
512 if ( !var.endsWith( ";" ) )
513 var += ";";
514 if ( access == "public" )
515 publicVars += var;
516 else if ( access == "private" )
517 privateVars += var;
518 else
519 protectedVars += var;
520 }
521
522 if ( !publicVars.isEmpty() ) {
523 for ( it = publicVars.begin(); it != publicVars.end(); ++it )
524 out << indent << *it << endl;
525 out << endl;
526 }
527 if ( !publicFuncts.isEmpty() )
528 writeFunctionsDecl( publicFuncts, publicFunctRetTyp, publicFunctSpec );
529
530 if ( needPolish || !publicSlots.isEmpty() ) {
531 out << "public slots:" << endl;
532 if ( needPolish ) {
533 out << indent << "virtual void polish();" << endl;
534 out << endl;
535 }
536 if ( !publicSlots.isEmpty() )
537 writeFunctionsDecl( publicSlots, publicSlotTypes, publicSlotSpecifier );
538 }
539
540 // find signals
541 QStringList extraSignals;
542 nl = e.parentNode().toElement().elementsByTagName( "signal" );
543 for ( i = 0; i < (int) nl.length(); i++ ) {
544 n = nl.item( i ).toElement();
545 if ( n.parentNode().toElement().tagName() != "signals"
546 && n.parentNode().toElement().tagName() != "connections" )
547 continue;
548 if ( n.attribute( "language", "C++" ) != "C++" )
549 continue;
550 QString sigName = n.firstChild().toText().data().stripWhiteSpace();
551 if ( sigName.endsWith( ";" ) )
552 sigName = sigName.left( sigName.length() - 1 );
553 extraSignals += sigName;
554 }
555
556 // create signals
557 if ( !extraSignals.isEmpty() ) {
558 out << "signals:" << endl;
559 for ( it = extraSignals.begin(); it != extraSignals.end(); ++it )
560 out << " void " << (*it) << ";" << endl;
561 out << endl;
562 }
563
564 out << "protected:" << endl;
565 if ( !protectedVars.isEmpty() ) {
566 for ( it = protectedVars.begin(); it != protectedVars.end(); ++it )
567 out << indent << *it << endl;
568 out << endl;
569 }
570 if ( !protectedFuncts.isEmpty() )
571 writeFunctionsDecl( protectedFuncts, protectedFunctRetTyp, protectedFunctSpec );
572
573 // child layouts
574 registerLayouts( e );
575 out << endl;
576
577#if QT_VERSION >= 0x030900
578#error Make languageChange() a virtual protected non-slot member of QWidget
579#endif
580
581 out << "protected slots:" << endl;
582 out << " virtual void languageChange();" << endl;
583 if ( !protectedSlots.isEmpty() ) {
584 out << endl;
585 writeFunctionsDecl( protectedSlots, protectedSlotTypes, protectedSlotSpecifier );
586 }
587 out << endl;
588
589 // create all private stuff
590 if ( !privateFuncts.isEmpty() || !privateVars.isEmpty() || !imageMembers.isEmpty() ) {
591 out << "private:" << endl;
592 if ( !privateVars.isEmpty() ) {
593 for ( it = privateVars.begin(); it != privateVars.end(); ++it )
594 out << indent << *it << endl;
595 out << endl;
596 }
597 if ( !imageMembers.isEmpty() ) {
598 out << imageMembers;
599 out << endl;
600 }
601 if ( !privateFuncts.isEmpty() )
602 writeFunctionsDecl( privateFuncts, privateFunctRetTyp, privateFunctSpec );
603 }
604
605 if ( !privateSlots.isEmpty() ) {
606 out << "private slots:" << endl;
607 writeFunctionsDecl( privateSlots, privateSlotTypes, privateSlotSpecifier );
608 }
609
610 out << "};" << endl;
611 for ( i = 0; i < (int) namespaces.count(); i++ )
612 out << "}" << endl;
613
614 out << endl;
615 out << "#endif // " << protector << endl;
616}
617
618void Uic::writeFunctionsDecl( const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst )
619{
620 QValueListConstIterator<QString> it, it2, it3;
621 for ( it = fuLst.begin(), it2 = typLst.begin(), it3 = specLst.begin();
622 it != fuLst.end(); ++it, ++it2, ++it3 ) {
623 QString signature = *it;
624 QString specifier;
625 QString pure;
626 QString type = *it2;
627 if ( type.isEmpty() )
628 type = "void";
629 if ( *it3 == "static" ) {
630 specifier = "static ";
631 } else {
632 if ( *it3 != "non virtual" && *it3 != "nonVirtual" )
633 specifier = "virtual ";
634 if ( *it3 == "pure virtual" || *it3 == "pureVirtual" )
635 pure = " = 0";
636 }
637 type.replace( ">>", "> >" );
638 if ( !signature.contains("operator") )
639 signature.replace( ">>", "> >" );
640 out << " " << specifier << type << " " << signature << pure << ";" << endl;
641 }
642 out << endl;
643}
644
645/*!
646 Creates an implementation (cpp-file) for the form given in \a e.
647
648 \sa createFormDecl(), createObjectImpl()
649 */
650void Uic::createFormImpl( const QDomElement &e )
651{
652 QDomElement n;
653 QDomNodeList nl;
654 int i;
655 QString objClass = getClassName( e );
656 if ( objClass.isEmpty() )
657 return;
658 QString objName = getObjectName( e );
659
660 // generate local and local includes required
661 QStringList globalIncludes, localIncludes;
662 QStringList::Iterator it;
663
664 QMap<QString, CustomInclude> customWidgetIncludes;
665
666 // find additional slots and functions
667 QStringList extraFuncts;
668 QStringList extraFunctTyp;
669 QStringList extraFunctSpecifier;
670
671 nl = e.parentNode().toElement().elementsByTagName( "slot" );
672 for ( i = 0; i < (int) nl.length(); i++ ) {
673 n = nl.item(i).toElement();
674 if ( n.parentNode().toElement().tagName() != "slots"
675 && n.parentNode().toElement().tagName() != "connections" )
676 continue;
677 if ( n.attribute( "language", "C++" ) != "C++" )
678 continue;
679 QString functionName = n.firstChild().toText().data().stripWhiteSpace();
680 if ( functionName.endsWith( ";" ) )
681 functionName = functionName.left( functionName.length() - 1 );
682 extraFuncts += functionName;
683 extraFunctTyp += n.attribute( "returnType", "void" );
684 extraFunctSpecifier += n.attribute( "specifier", "virtual" );
685 }
686
687 nl = e.parentNode().toElement().elementsByTagName( "function" );
688 for ( i = 0; i < (int) nl.length(); i++ ) {
689 n = nl.item(i).toElement();
690 if ( n.parentNode().toElement().tagName() != "functions" )
691 continue;
692 if ( n.attribute( "language", "C++" ) != "C++" )
693 continue;
694 QString functionName = n.firstChild().toText().data().stripWhiteSpace();
695 if ( functionName.endsWith( ";" ) )
696 functionName = functionName.left( functionName.length() - 1 );
697 extraFuncts += functionName;
698 extraFunctTyp += n.attribute( "returnType", "void" );
699 extraFunctSpecifier += n.attribute( "specifier", "virtual" );
700 }
701
702 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
703 if ( n.tagName() == "customwidgets" ) {
704 QDomElement n2 = n.firstChild().toElement();
705 while ( !n2.isNull() ) {
706 if ( n2.tagName() == "customwidget" ) {
707 QDomElement n3 = n2.firstChild().toElement();
708 QString cl;
709 WidgetDatabaseRecord *r = new WidgetDatabaseRecord;
710 while ( !n3.isNull() ) {
711 if ( n3.tagName() == "class" ) {
712 cl = n3.firstChild().toText().data();
713 r->name = cl;
714 } else if ( n3.tagName() == "header" ) {
715 CustomInclude ci;
716 ci.header = n3.firstChild().toText().data();
717 ci.location = n3.attribute( "location", "global" );
718 r->includeFile = ci.header;
719 customWidgetIncludes.insert( cl, ci );
720 }
721 WidgetDatabase::append( r );
722 n3 = n3.nextSibling().toElement();
723 }
724 }
725 n2 = n2.nextSibling().toElement();
726 }
727 }
728 }
729
730 // additional includes (local or global) and forward declaractions
731 nl = e.parentNode().toElement().elementsByTagName( "include" );
732 for ( i = 0; i < (int) nl.length(); i++ ) {
733 QDomElement n2 = nl.item(i).toElement();
734 QString s = n2.firstChild().toText().data();
735 if ( n2.attribute( "location" ) != "local" ) {
736 if ( s.right( 5 ) == ".ui.h" && !QFile::exists( s ) )
737 continue;
738 if ( n2.attribute( "impldecl", "in implementation" ) != "in implementation" )
739 continue;
740 globalIncludes += s;
741 }
742 }
743
744 registerDatabases( e );
745 dbConnections = unique( dbConnections );
746 if ( dbConnections.count() )
747 globalIncludes += "qsqldatabase.h";
748 if ( dbCursors.count() )
749 globalIncludes += "qsqlcursor.h";
750 bool dbForm = FALSE;
751 if ( dbForms[ "(default)" ].count() )
752 dbForm = TRUE;
753 bool subDbForms = FALSE;
754 for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
755 if ( !(*it).isEmpty() && (*it) != "(default)" ) {
756 if ( dbForms[ (*it) ].count() ) {
757 subDbForms = TRUE;
758 break;
759 }
760 }
761 }
762 if ( dbForm || subDbForms ) {
763 globalIncludes += "qsqlform.h";
764 globalIncludes += "qsqlrecord.h";
765 }
766
767 // do the local includes afterwards, since global includes have priority on clashes
768 for ( i = 0; i < (int) nl.length(); i++ ) {
769 QDomElement n2 = nl.item(i).toElement();
770 QString s = n2.firstChild().toText().data();
771 if ( n2.attribute( "location" ) == "local" &&!globalIncludes.contains( s ) ) {
772 if ( s.right( 5 ) == ".ui.h" && !QFile::exists( s ) )
773 continue;
774 if ( n2.attribute( "impldecl", "in implementation" ) != "in implementation" )
775 continue;
776 localIncludes += s;
777 }
778 }
779
780 // additional custom widget headers
781 nl = e.parentNode().toElement().elementsByTagName( "header" );
782 for ( i = 0; i < (int) nl.length(); i++ ) {
783 QDomElement n2 = nl.item(i).toElement();
784 QString s = n2.firstChild().toText().data();
785 if ( n2.attribute( "location" ) != "local" )
786 globalIncludes += s;
787 else
788 localIncludes += s;
789 }
790
791 // includes for child widgets
792 for ( it = tags.begin(); it != tags.end(); ++it ) {
793 nl = e.parentNode().toElement().elementsByTagName( *it );
794 for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
795 QString name = getClassName( nl.item(i).toElement() );
796 if ( name == "Spacer" ) {
797 globalIncludes += "qlayout.h";
798 globalIncludes += "qapplication.h";
799 continue;
800 }
801 if ( name.mid( 1 ) == "ListView" )
802 globalIncludes += "qheader.h";
803 if ( name != objClass ) {
804 int wid = WidgetDatabase::idFromClassName( name );
805 QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find( name );
806 if ( it == customWidgetIncludes.end() )
807 globalIncludes += WidgetDatabase::includeFile( wid );
808 }
809 }
810 }
811
812 out << "#include <qvariant.h>" << endl; // first for gcc 2.7.2
813
814 globalIncludes = unique( globalIncludes );
815 for ( it = globalIncludes.begin(); it != globalIncludes.end(); ++it ) {
816 if ( !(*it).isEmpty() )
817 out << "#include <" << *it << ">" << endl;
818 }
819
820 out << "#include <qlayout.h>" << endl;
821 out << "#include <qtooltip.h>" << endl;
822 out << "#include <qwhatsthis.h>" << endl;
823 if ( objClass == "QMainWindow" ) {
824 out << "#include <qaction.h>" << endl;
825 out << "#include <qmenubar.h>" << endl;
826 out << "#include <qpopupmenu.h>" << endl;
827 out << "#include <qtoolbar.h>" << endl;
828 }
829
830 // find out what images are required
831 QStringList requiredImages;
832 static const char *imgTags[] = { "pixmap", "iconset", 0 };
833 for ( i = 0; imgTags[i] != 0; i++ ) {
834 nl = e.parentNode().toElement().elementsByTagName( imgTags[i] );
835 for ( int j = 0; j < (int) nl.length(); j++ ) {
836 QDomNode nn = nl.item(j);
837 while ( nn.parentNode() != e.parentNode() )
838 nn = nn.parentNode();
839 if ( nn.nodeName() != "customwidgets" )
840 requiredImages += nl.item(j).firstChild().toText().data();
841 }
842 }
843
844 if ( !requiredImages.isEmpty() || externPixmaps ) {
845 out << "#include <qimage.h>" << endl;
846 out << "#include <qpixmap.h>" << endl << endl;
847 }
848
849 /*
850 Put local includes after all global includes
851 */
852 localIncludes = unique( localIncludes );
853 for ( it = localIncludes.begin(); it != localIncludes.end(); ++it ) {
854 if ( !(*it).isEmpty() && *it != QFileInfo( fileName + ".h" ).fileName() )
855 out << "#include \"" << *it << "\"" << endl;
856 }
857
858 QString uiDotH = fileName + ".h";
859 if ( QFile::exists( uiDotH ) ) {
860 if ( !outputFileName.isEmpty() )
861 uiDotH = combinePath( uiDotH, outputFileName );
862 out << "#include \"" << uiDotH << "\"" << endl;
863 writeFunctImpl = FALSE;
864 }
865
866 // register the object and unify its name
867 objName = registerObject( objName );
868
869 QStringList images;
870 QStringList xpmImages;
871 if ( pixmapLoaderFunction.isEmpty() && !externPixmaps ) {
872 // create images
873 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
874 if ( n.tagName() == "images" ) {
875 nl = n.elementsByTagName( "image" );
876 for ( i = 0; i < (int) nl.length(); i++ ) {
877 QString img = registerObject( nl.item(i).toElement().attribute("name") );
878 if ( !requiredImages.contains( img ) )
879 continue;
880 QDomElement tmp = nl.item(i).firstChild().toElement();
881 if ( tmp.tagName() != "data" )
882 continue;
883 QString format = tmp.attribute("format", "PNG" );
884 QString data = tmp.firstChild().toText().data();
885 if ( format == "XPM.GZ" ) {
886 xpmImages += img;
887 ulong length = tmp.attribute("length").toULong();
888 QByteArray baunzip = unzipXPM( data, length );
889 length = baunzip.size();
890 // shouldn't we test the initial 'length' against the
891 // resulting 'length' to catch corrupt UIC files?
892 int a = 0;
893 int column = 0;
894 bool inQuote = FALSE;
895 out << "static const char* const " << img << "_data[] = { " << endl;
896 while ( baunzip[a] != '\"' )
897 a++;
898 for ( ; a < (int) length; a++ ) {
899 out << baunzip[a];
900 if ( baunzip[a] == '\n' ) {
901 column = 0;
902 } else if ( baunzip[a] == '"' ) {
903 inQuote = !inQuote;
904 }
905
906 if ( column++ >= 511 && inQuote ) {
907 out << "\"\n\""; // be nice with MSVC & Co.
908 column = 1;
909 }
910 }
911 out << endl;
912 } else {
913 images += img;
914 out << "static const unsigned char " << img << "_data[] = { " << endl;
915 out << " ";
916 int a ;
917 for ( a = 0; a < (int) (data.length()/2)-1; a++ ) {
918 out << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << ",";
919 if ( a % 12 == 11 )
920 out << endl << " ";
921 else
922 out << " ";
923 }
924 out << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << endl;
925 out << "};" << endl << endl;
926 }
927 }
928 }
929 }
930 out << endl;
931 } else if ( externPixmaps ) {
932 pixmapLoaderFunction = "QPixmap::fromMimeSource";
933 }
934
935 // constructor
936 if ( objClass == "QDialog" || objClass == "QWizard" ) {
937 out << "/*" << endl;
938 out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl;
939 out << " * name 'name' and widget flags set to 'f'." << endl;
940 out << " *" << endl;
941 out << " * The " << objClass.mid(1).lower() << " will by default be modeless, unless you set 'modal' to" << endl;
942 out << " * TRUE to construct a modal " << objClass.mid(1).lower() << "." << endl;
943 out << " */" << endl;
944 out << nameOfClass << "::" << bareNameOfClass << "( QWidget* parent, const char* name, bool modal, WFlags fl )" << endl;
945 out << " : " << objClass << "( parent, name, modal, fl )";
946 } else if ( objClass == "QWidget" ) {
947 out << "/*" << endl;
948 out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl;
949 out << " * name 'name' and widget flags set to 'f'." << endl;
950 out << " */" << endl;
951 out << nameOfClass << "::" << bareNameOfClass << "( QWidget* parent, const char* name, WFlags fl )" << endl;
952 out << " : " << objClass << "( parent, name, fl )";
953 } else if ( objClass == "QMainWindow" ) {
954 out << "/*" << endl;
955 out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl;
956 out << " * name 'name' and widget flags set to 'f'." << endl;
957 out << " *" << endl;
958 out << " */" << endl;
959 out << nameOfClass << "::" << bareNameOfClass << "( QWidget* parent, const char* name, WFlags fl )" << endl;
960 out << " : " << objClass << "( parent, name, fl )";
961 isMainWindow = TRUE;
962 } else {
963 out << "/*" << endl;
964 out << " * Constructs a " << nameOfClass << " which is a child of 'parent', with the" << endl;
965 out << " * name 'name'.' " << endl;
966 out << " */" << endl;
967 out << nameOfClass << "::" << bareNameOfClass << "( QWidget* parent, const char* name )" << endl;
968 out << " : " << objClass << "( parent, name )";
969 }
970
971 // create pixmaps for all images
972 if ( !xpmImages.isEmpty() ) {
973 for ( it = xpmImages.begin(); it != xpmImages.end(); ++it ) {
974 out << "," << endl;
975 out << indent << " " << *it << "( (const char **) " << (*it) << "_data )";
976 }
977 }
978 out << endl;
979
980 out << "{" << endl;
981 if ( isMainWindow )
982 out << indent << "(void)statusBar();" << endl;
983
984 if ( !images.isEmpty() ) {
985 out << indent << "QImage img;" << endl;
986 for ( it = images.begin(); it != images.end(); ++it ) {
987 out << indent << "img.loadFromData( " << (*it) << "_data, sizeof( " << (*it) << "_data ), \"PNG\" );" << endl;
988 out << indent << (*it) << " = img;" << endl;
989 }
990 }
991
992 // set the properties
993 QSize geometry( 0, 0 );
994
995 for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
996 if ( n.tagName() == "property" ) {
997 bool stdset = stdsetdef;
998 if ( n.hasAttribute( "stdset" ) )
999 stdset = toBool( n.attribute( "stdset" ) );
1000 QString prop = n.attribute("name");
1001 QDomElement n2 = n.firstChild().toElement();
1002 QString value = setObjectProperty( objClass, QString::null, prop, n2, stdset );
1003 if ( value.isEmpty() )
1004 continue;
1005
1006 if ( prop == "geometry" && n2.tagName() == "rect" ) {
1007 QDomElement n3 = n2.firstChild().toElement();
1008 while ( !n3.isNull() ) {
1009 if ( n3.tagName() == "width" )
1010 geometry.setWidth( n3.firstChild().toText().data().toInt() );
1011 else if ( n3.tagName() == "height" )
1012 geometry.setHeight( n3.firstChild().toText().data().toInt() );
1013 n3 = n3.nextSibling().toElement();
1014 }
1015 } else {
1016 QString call;
1017 if ( stdset ) {
1018 call = mkStdSet( prop ) + "( ";
1019 } else {
1020 call = "setProperty( \"" + prop + "\", ";
1021 }
1022 call += value + " );";
1023
1024 if ( n2.tagName() == "string" ) {
1025 trout << indent << call << endl;
1026 } else if ( prop == "name" ) {
1027 out << indent << "if ( !name )" << endl;
1028 out << "\t" << call << endl;
1029 } else {
1030 out << indent << call << endl;
1031 }
1032 }
1033 }
1034 }
1035
1036 // create all children, some forms have special requirements
1037
1038 if ( objClass == "QWizard" ) {
1039 for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
1040 if ( tags.contains( n.tagName() ) ) {
1041 QString page = createObjectImpl( n, objClass, "this" );
1042 QString comment;
1043 QString label = DomTool::readAttribute( n, "title", "", comment ).toString();
1044 out << indent << "addPage( " << page << ", QString(\"\") );" << endl;
1045 trout << indent << "setTitle( " << page << ", " << trcall( label, comment ) << " );" << endl;
1046 QVariant def( FALSE, 0 );
1047 if ( DomTool::hasAttribute( n, "backEnabled" ) )
1048 out << indent << "setBackEnabled( " << page << ", " << mkBool( DomTool::readAttribute( n, "backEnabled", def).toBool() ) << endl;
1049 if ( DomTool::hasAttribute( n, "nextEnabled" ) )
1050 out << indent << "setNextEnabled( " << page << ", " << mkBool( DomTool::readAttribute( n, "nextEnabled", def).toBool() ) << endl;
1051 if ( DomTool::hasAttribute( n, "finishEnabled" ) )
1052 out << indent << "setFinishEnabled( " << page << ", " << mkBool( DomTool::readAttribute( n, "finishEnabled", def).toBool() ) << " );" << endl;
1053 if ( DomTool::hasAttribute( n, "helpEnabled" ) )
1054 out << indent << "setHelpEnabled( " << page << ", " << mkBool( DomTool::readAttribute( n, "helpEnabled", def).toBool() ) << endl;
1055 if ( DomTool::hasAttribute( n, "finish" ) )
1056 out << indent << "setFinish( " << page << ", " << mkBool( DomTool::readAttribute( n, "finish", def).toBool() ) << endl;
1057 }
1058 }
1059 } else { // standard widgets
1060 for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
1061 if ( tags.contains( n.tagName() ) )
1062 createObjectImpl( n, objName, "this" );
1063 }
1064 }
1065
1066 // database support
1067 dbConnections = unique( dbConnections );
1068 if ( dbConnections.count() )
1069 out << endl;
1070 for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
1071 if ( !(*it).isEmpty() && (*it) != "(default)") {
1072 out << indent << (*it) << "Connection = QSqlDatabase::database( \"" <<(*it) << "\" );" << endl;
1073 }
1074 }
1075
1076 nl = e.parentNode().toElement().elementsByTagName( "widget" );
1077 for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
1078 n = nl.item(i).toElement();
1079 QString s = getClassName( n );
1080 if ( (dbForm || subDbForms) && (s == "QDataBrowser" || s == "QDataView") ) {
1081 QString objName = getObjectName( n );
1082 QString tab = getDatabaseInfo( n, "table" );
1083 QString con = getDatabaseInfo( n, "connection" );
1084 out << indent << "QSqlForm* " << objName << "Form = new QSqlForm( this, \"" << objName << "Form\" );" << endl;
1085 QDomElement n2;
1086 for ( n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() )
1087 createFormImpl( n2, objName, con, tab );
1088 out << indent << objName << "->setForm( " << objName << "Form );" << endl;
1089 }
1090 }
1091
1092 // actions, toolbars, menubar
1093 bool needEndl = FALSE;
1094 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
1095 if ( n.tagName() == "actions" ) {
1096 if ( !needEndl )
1097 out << endl << indent << "// actions" << endl;
1098 createActionImpl( n.firstChild().toElement(), "this" );
1099 needEndl = TRUE;
1100 }
1101 }
1102 if ( needEndl )
1103 out << endl;
1104 needEndl = FALSE;
1105 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
1106 if ( n.tagName() == "toolbars" ) {
1107 if ( !needEndl )
1108 out << endl << indent << "// toolbars" << endl;
1109 createToolbarImpl( n, objClass, objName );
1110 needEndl = TRUE;
1111 }
1112 }
1113 if ( needEndl )
1114 out << endl;
1115 needEndl = FALSE;
1116 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
1117 if ( n.tagName() == "menubar" ) {
1118 if ( !needEndl )
1119 out << endl << indent << "// menubar" << endl;
1120 createMenuBarImpl( n, objClass, objName );
1121 needEndl = TRUE;
1122 }
1123 }
1124 if ( needEndl )
1125 out << endl;
1126
1127 out << indent << "languageChange();" << endl;
1128
1129 // take minimumSizeHint() into account, for height-for-width widgets
1130 if ( !geometry.isNull() ) {
1131 out << indent << "resize( QSize(" << geometry.width() << ", "
1132 << geometry.height() << ").expandedTo(minimumSizeHint()) );" << endl;
1133 out << indent << "clearWState( WState_Polished );" << endl;
1134 }
1135
1136 for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
1137 if ( n.tagName() == "connections" ) {
1138 // setup signals and slots connections
1139 out << endl << indent << "// signals and slots connections" << endl;
1140 nl = n.elementsByTagName( "connection" );
1141 for ( i = 0; i < (int) nl.length(); i++ ) {
1142 QString sender, receiver, signal, slot;
1143 for ( QDomElement n2 = nl.item(i).firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() ) {
1144 if ( n2.tagName() == "sender" )
1145 sender = n2.firstChild().toText().data();
1146 else if ( n2.tagName() == "receiver" )
1147 receiver = n2.firstChild().toText().data();
1148 else if ( n2.tagName() == "signal" )
1149 signal = n2.firstChild().toText().data();
1150 else if ( n2.tagName() == "slot" )
1151 slot = n2.firstChild().toText().data();
1152 }
1153 if ( sender.isEmpty() ||
1154 receiver.isEmpty() ||
1155 signal.isEmpty() ||
1156 slot.isEmpty() )
1157 continue;
1158 if ( sender[0] == '<' ||
1159 receiver[0] == '<' ||
1160 signal[0] == '<' ||
1161 slot[0] == '<' )
1162 continue;
1163
1164 sender = registeredName( sender );
1165 receiver = registeredName( receiver );
1166
1167 // translate formwindow name to "this"
1168 if ( sender == objName )
1169 sender = "this";
1170 if ( receiver == objName )
1171 receiver = "this";
1172
1173 out << indent << "connect( " << sender << ", SIGNAL( " << signal << " ), "
1174 << receiver << ", SLOT( " << slot << " ) );" << endl;
1175 }
1176 } else if ( n.tagName() == "tabstops" ) {
1177 // setup tab order
1178 out << endl << indent << "// tab order" << endl;
1179 QString lastName;
1180 QDomElement n2 = n.firstChild().toElement();
1181 while ( !n2.isNull() ) {
1182 if ( n2.tagName() == "tabstop" ) {
1183 QString name = n2.firstChild().toText().data();
1184 name = registeredName( name );
1185 if ( !lastName.isEmpty() )
1186 out << indent << "setTabOrder( " << lastName << ", " << name << " );" << endl;
1187 lastName = name;
1188 }
1189 n2 = n2.nextSibling().toElement();
1190 }
1191 }
1192 }
1193
1194 // buddies
1195 bool firstBuddy = TRUE;
1196 for ( QValueList<Buddy>::Iterator buddy = buddies.begin(); buddy != buddies.end(); ++buddy ) {
1197 if ( isObjectRegistered( (*buddy).buddy ) ) {
1198 if ( firstBuddy ) {
1199 out << endl << indent << "// buddies" << endl;
1200 }
1201 out << indent << (*buddy).key << "->setBuddy( " << registeredName( (*buddy).buddy ) << " );" << endl;
1202 firstBuddy = FALSE;
1203 }
1204 }
1205
1206 if ( extraFuncts.find( "init()" ) != extraFuncts.end() )
1207 out << indent << "init();" << endl;
1208
1209 // end of constructor
1210 out << "}" << endl;
1211 out << endl;
1212
1213 // destructor
1214 out << "/*" << endl;
1215 out << " * Destroys the object and frees any allocated resources" << endl;
1216 out << " */" << endl;
1217 out << nameOfClass << "::~" << bareNameOfClass << "()" << endl;
1218 out << "{" << endl;
1219 if ( extraFuncts.find( "destroy()" ) != extraFuncts.end() )
1220 out << indent << "destroy();" << endl;
1221 out << indent << "// no need to delete child widgets, Qt does it all for us" << endl;
1222 out << "}" << endl;
1223 out << endl;
1224
1225 // handle application events if required
1226 bool needFontEventHandler = FALSE;
1227 bool needSqlTableEventHandler = FALSE;
1228 bool needSqlDataBrowserEventHandler = FALSE;
1229 nl = e.elementsByTagName( "widget" );
1230 for ( i = 0; i < (int) nl.length(); i++ ) {
1231 if ( !DomTool::propertiesOfType( nl.item(i).toElement() , "font" ).isEmpty() )
1232 needFontEventHandler = TRUE;
1233 QString s = getClassName( nl.item(i).toElement() );
1234 if ( s == "QDataTable" || s == "QDataBrowser" ) {
1235 if ( !isFrameworkCodeGenerated( nl.item(i).toElement() ) )
1236 continue;
1237 if ( s == "QDataTable" )
1238 needSqlTableEventHandler = TRUE;
1239 if ( s == "QDataBrowser" )
1240 needSqlDataBrowserEventHandler = TRUE;
1241 }
1242 if ( needFontEventHandler && needSqlTableEventHandler && needSqlDataBrowserEventHandler )
1243 break;
1244 }
1245 if ( needFontEventHandler && FALSE ) {
1246 // indent = "\t"; // increase indentation for if-clause below
1247 out << "/*" << endl;
1248 out << " * Main event handler. Reimplemented to handle" << endl;
1249 out << " * application font changes";
1250 out << " */" << endl;
1251 out << "bool " << nameOfClass << "::event( QEvent* ev )" << endl;
1252 out << "{" << endl;
1253 out << " bool ret = " << objClass << "::event( ev ); " << endl;
1254 if ( needFontEventHandler ) {
1255 indent += "\t";
1256 out << " if ( ev->type() == QEvent::ApplicationFontChange ) {" << endl;
1257 for ( i = 0; i < (int) nl.length(); i++ ) {
1258 n = nl.item(i).toElement();
1259 QStringList list = DomTool::propertiesOfType( n, "font" );
1260 for ( it = list.begin(); it != list.end(); ++it )
1261 createExclusiveProperty( n, *it );
1262 }
1263 out << " }" << endl;
1264 indent = " ";
1265 }
1266 out << "}" << endl;
1267 out << endl;
1268 }
1269
1270 if ( needSqlTableEventHandler || needSqlDataBrowserEventHandler ) {
1271 out << "/*" << endl;
1272 out << " * Widget polish. Reimplemented to handle" << endl;
1273 if ( needSqlTableEventHandler )
1274 out << " * default data table initialization" << endl;
1275 if ( needSqlDataBrowserEventHandler )
1276 out << " * default data browser initialization" << endl;
1277 out << " */" << endl;
1278 out << "void " << nameOfClass << "::polish()" << endl;
1279 out << "{" << endl;
1280 if ( needSqlTableEventHandler ) {
1281 for ( i = 0; i < (int) nl.length(); i++ ) {
1282 QString s = getClassName( nl.item(i).toElement() );
1283 if ( s == "QDataTable" ) {
1284 n = nl.item(i).toElement();
1285 QString c = getObjectName( n );
1286 QString conn = getDatabaseInfo( n, "connection" );
1287 QString tab = getDatabaseInfo( n, "table" );
1288 if ( !( conn.isEmpty() || tab.isEmpty() || !isFrameworkCodeGenerated( nl.item(i).toElement() ) ) ) {
1289 out << indent << "if ( " << c << " ) {" << endl;
1290 out << indent << indent << "QSqlCursor* cursor = " << c << "->sqlCursor();" << endl;
1291 out << indent << indent << "if ( !cursor ) {" << endl;
1292 if ( conn == "(default)" )
1293 out << indent << indent << indent << "cursor = new QSqlCursor( \"" << tab << "\" );" << endl;
1294 else
1295 out << indent << indent << indent << "cursor = new QSqlCursor( \"" << tab << "\", TRUE, " << conn << "Connection );" << endl;
1296 out << indent << indent << indent << "if ( " << c << "->isReadOnly() ) " << endl;
1297 out << indent << indent << indent << indent << "cursor->setMode( QSqlCursor::ReadOnly );" << endl;
1298 out << indent << indent << indent << c << "->setSqlCursor( cursor, FALSE, TRUE );" << endl;
1299 out << indent << indent << "}" << endl;
1300 out << indent << indent << "if ( !cursor->isActive() )" << endl;
1301 out << indent << indent << indent << c << "->refresh( QDataTable::RefreshAll );" << endl;
1302 out << indent << "}" << endl;
1303 }
1304 }
1305 }
1306 }
1307 if ( needSqlDataBrowserEventHandler ) {
1308 nl = e.elementsByTagName( "widget" );
1309 for ( i = 0; i < (int) nl.length(); i++ ) {
1310 QString s = getClassName( nl.item(i).toElement() );
1311 if ( s == "QDataBrowser" ) {
1312 QString obj = getObjectName( nl.item(i).toElement() );
1313 QString tab = getDatabaseInfo( nl.item(i).toElement(),
1314 "table" );
1315 QString conn = getDatabaseInfo( nl.item(i).toElement(),
1316 "connection" );
1317 if ( !(tab.isEmpty() || !isFrameworkCodeGenerated( nl.item(i).toElement() ) ) ) {
1318 out << indent << "if ( " << obj << " ) {" << endl;
1319 out << indent << indent << "if ( !" << obj << "->sqlCursor() ) {" << endl;
1320 if ( conn == "(default)" )
1321 out << indent << indent << indent << "QSqlCursor* cursor = new QSqlCursor( \"" << tab << "\" );" << endl;
1322 else
1323 out << indent << indent << indent << "QSqlCursor* cursor = new QSqlCursor( \"" << tab << "\", TRUE, " << conn << "Connection );" << endl;
1324 out << indent << indent << indent << obj << "->setSqlCursor( cursor, TRUE );" << endl;
1325 out << indent << indent << indent << obj << "->refresh();" << endl;
1326 out << indent << indent << indent << obj << "->first();" << endl;
1327 out << indent << indent << "}" << endl;
1328 out << indent << "}" << endl;
1329 }
1330 }
1331 }
1332 }
1333 out << indent << objClass << "::polish();" << endl;
1334 out << "}" << endl;
1335 out << endl;
1336 }
1337
1338 out << "/*" << endl;
1339 out << " * Sets the strings of the subwidgets using the current" << endl;
1340 out << " * language." << endl;
1341 out << " */" << endl;
1342 out << "void " << nameOfClass << "::languageChange()" << endl;
1343 out << "{" << endl;
1344 out << languageChangeBody;
1345 out << "}" << endl;
1346 out << endl;
1347
1348 // create stubs for additional slots if necessary
1349 if ( !extraFuncts.isEmpty() && writeFunctImpl ) {
1350 it = extraFuncts.begin();
1351 QStringList::Iterator it2 = extraFunctTyp.begin();
1352 QStringList::Iterator it3 = extraFunctSpecifier.begin();
1353 while ( it != extraFuncts.end() ) {
1354 QString type = *it2;
1355 if ( type.isEmpty() )
1356 type = "void";
1357 type = type.simplifyWhiteSpace();
1358 QString fname = Parser::cleanArgs( *it );
1359 if ( !(*it3).startsWith("pure") ) { // "pure virtual" or "pureVirtual"
1360 out << type << " " << nameOfClass << "::" << fname << endl;
1361 out << "{" << endl;
1362 if ( *it != "init()" && *it != "destroy()" ) {
1363 QRegExp numeric( "^(?:signed|unsigned|u?char|u?short|u?int"
1364 "|u?long|Q_U?INT(?:8|16|32)|Q_U?LONG|float"
1365 "|double)$" );
1366 QString retVal;
1367
1368 /*
1369 We return some kind of dummy value to shut the
1370 compiler up.
1371
1372 1. If the type is 'void', we return nothing.
1373
1374 2. If the type is 'bool', we return 'FALSE'.
1375
1376 3. If the type is 'unsigned long' or
1377 'Q_UINT16' or 'double' or similar, we
1378 return '0'.
1379
1380 4. If the type is 'Foo *', we return '0'.
1381
1382 5. If the type is 'Foo &', we create a static
1383 variable of type 'Foo' and return it.
1384
1385 6. If the type is 'Foo', we assume there's a
1386 default constructor and use it.
1387 */
1388 if ( type != "void" ) {
1389 QStringList toks = QStringList::split( " ", type );
1390 bool isBasicNumericType =
1391 ( toks.grep(numeric).count() == toks.count() );
1392
1393 if ( type == "bool" ) {
1394 retVal = "FALSE";
1395 } else if ( isBasicNumericType || type.endsWith("*") ) {
1396 retVal = "0";
1397 } else if ( type.endsWith("&") ) {
1398 do {
1399 type.truncate( type.length() - 1 );
1400 } while ( type.endsWith(" ") );
1401 retVal = "uic_temp_var";
1402 out << indent << "static " << type << " " << retVal << ";" << endl;
1403 } else {
1404 retVal = type + "()";
1405 }
1406 }
1407
1408 out << indent << "qWarning( \"" << nameOfClass << "::" << fname << ": Not implemented yet\" );" << endl;
1409 if ( !retVal.isEmpty() )
1410 out << indent << "return " << retVal << ";" << endl;
1411 }
1412 out << "}" << endl;
1413 out << endl;
1414 }
1415 ++it;
1416 ++it2;
1417 ++it3;
1418 }
1419 }
1420}
1421
1422
1423/*! Creates form support implementation code for the widgets given
1424 in \a e.
1425
1426 Traverses recursively over all children.
1427 */
1428
1429void Uic::createFormImpl( const QDomElement& e, const QString& form, const QString& connection, const QString& table )
1430{
1431 if ( e.tagName() == "widget" &&
1432 e.attribute( "class" ) != "QDataTable" ) {
1433 QString field = getDatabaseInfo( e, "field" );
1434 if ( !field.isEmpty() ) {
1435 if ( isWidgetInTable( e, connection, table ) )
1436 out << indent << form << "Form->insert( " << getObjectName( e ) << ", " << fixString( field ) << " );" << endl;
1437 }
1438 }
1439 QDomElement n;
1440 for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
1441 createFormImpl( n, form, connection, table );
1442 }
1443}
Note: See TracBrowser for help on using the repository browser.