summaryrefslogtreecommitdiffstats
path: root/puic/form.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'puic/form.cpp')
-rw-r--r--puic/form.cpp1224
1 files changed, 1224 insertions, 0 deletions
diff --git a/puic/form.cpp b/puic/form.cpp
new file mode 100644
index 0000000..56f44c2
--- /dev/null
+++ b/puic/form.cpp
@@ -0,0 +1,1224 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (c) 2002 Germain Garand <[email protected]>
+**
+** This file is part of Qt Designer.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact [email protected] if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+/*
+** 06/2002 : Initial release of puic, the PerlQt User Interface Compiler,
+** a work derivated from uic (the Qt User Interface Compiler)
+** and pyuic (the PyQt User Interface Compiler).
+**
+** G.Garand
+**
+**********************************************************************/
+
+#include <iostream>
+#include "uic.h"
+#include "parser.h"
+#include "widgetdatabase.h"
+#include "domtool.h"
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qregexp.h>
+#define NO_STATIC_COLORS
+#include <globaldefs.h>
+#if( QT_VERSION < 0x030101 )
+# include <zlib.h>
+
+static QByteArray qUncompress( const uchar* data, int nbytes )
+{
+ if ( !data ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "qUncompress: data is NULL." );
+#endif
+ return QByteArray();
+ }
+ if ( nbytes <= 4 ) {
+#if defined(QT_CHECK_RANGE)
+ if ( nbytes < 4 || ( data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0 ) )
+ qWarning( "qUncompress: Input data is corrupted." );
+#endif
+ return QByteArray();
+ }
+ ulong expectedSize = ( data[0] << 24 ) | ( data[1] << 16 ) | ( data[2] << 8 ) | data[3];
+ ulong len = QMAX( expectedSize, 1 );
+ QByteArray baunzip;
+ int res;
+ do {
+ baunzip.resize( len );
+ res = ::uncompress( (uchar*)baunzip.data(), &len,
+ (uchar*)data+4, nbytes-4 );
+
+ switch ( res ) {
+ case Z_OK:
+ if ( len != baunzip.size() )
+ baunzip.resize( len );
+ break;
+ case Z_MEM_ERROR:
+#if defined(QT_CHECK_RANGE)
+ qWarning( "qUncompress: Z_MEM_ERROR: Not enough memory." );
+#endif
+ break;
+ case Z_BUF_ERROR:
+ len *= 2;
+ break;
+ case Z_DATA_ERROR:
+#if defined(QT_CHECK_RANGE)
+ qWarning( "qUncompress: Z_DATA_ERROR: Input data is corrupted." );
+#endif
+ break;
+ }
+ } while ( res == Z_BUF_ERROR );
+
+ if ( res != Z_OK )
+ baunzip = QByteArray();
+
+ return baunzip;
+}
+#endif // QT_VERSION < 0x030101
+
+using namespace std;
+
+static QByteArray unzipXPM( QString data, ulong& length )
+{
+ const int lengthOffset = 4;
+ int baSize = data.length() / 2 + lengthOffset;
+ uchar *ba = new uchar[ baSize ];
+ for ( int i = lengthOffset; i < baSize; ++i ) {
+ char h = data[ 2 * (i-lengthOffset) ].latin1();
+ char l = data[ 2 * (i-lengthOffset) + 1 ].latin1();
+ uchar r = 0;
+ if ( h <= '9' )
+ r += h - '0';
+ else
+ r += h - 'a' + 10;
+ r = r << 4;
+ if ( l <= '9' )
+ r += l - '0';
+ else
+ r += l - 'a' + 10;
+ ba[ i ] = r;
+ }
+ // qUncompress() expects the first 4 bytes to be the expected length of the
+ // uncompressed data
+ ba[0] = ( length & 0xff000000 ) >> 24;
+ ba[1] = ( length & 0x00ff0000 ) >> 16;
+ ba[2] = ( length & 0x0000ff00 ) >> 8;
+ ba[3] = ( length & 0x000000ff );
+ QByteArray baunzip = qUncompress( ba, baSize );
+ delete[] ba;
+ return baunzip;
+}
+#if 0
+//- kept for diffs
+#if QT_VERSION >= 0x030900
+#error Add this functionality to QDir (relativePathTo() maybe?) and \
+remove it from here and from moc
+#endif
+
+QCString combinePath( const char *infile, const char *outfile )
+{
+ QFileInfo inFileInfo( QDir::current(), QFile::decodeName(infile) );
+ QFileInfo outFileInfo( QDir::current(), QFile::decodeName(outfile) );
+ int numCommonComponents = 0;
+
+ QStringList inSplitted =
+ QStringList::split( '/', inFileInfo.dir().canonicalPath(), TRUE );
+ QStringList outSplitted =
+ QStringList::split( '/', outFileInfo.dir().canonicalPath(), TRUE );
+
+ while ( !inSplitted.isEmpty() && !outSplitted.isEmpty() &&
+ inSplitted.first() == outSplitted.first() ) {
+ inSplitted.remove( inSplitted.begin() );
+ outSplitted.remove( outSplitted.begin() );
+ numCommonComponents++;
+ }
+
+ if ( numCommonComponents < 2 ) {
+ /*
+ The paths don't have the same drive, or they don't have the
+ same root directory. Use an absolute path.
+ */
+ return QFile::encodeName( inFileInfo.absFilePath() );
+ } else {
+ /*
+ The paths have something in common. Use a path relative to
+ the output file.
+ */
+ while ( !outSplitted.isEmpty() ) {
+ outSplitted.remove( outSplitted.begin() );
+ inSplitted.prepend( ".." );
+ }
+ inSplitted.append( inFileInfo.fileName() );
+ return QFile::encodeName( inSplitted.join("/") );
+ }
+}
+#endif
+
+/*!
+ Creates an implementation ( cpp-file ) for the form given in \a e
+
+ \sa createFormDecl(), createObjectImpl()
+ */
+void Uic::createFormImpl( const QDomElement &e )
+{
+ QDomElement n;
+ QDomNodeList nl;
+ int i;
+ QString objClass = getClassName( e );
+ if ( objClass.isEmpty() )
+ return;
+ QString objName = getObjectName( e );
+ out << indent << "package " << nameOfClass << ";" << endl;
+ out << indent << "use Qt;" << endl;
+
+ // generate local and local includes required
+ QStringList globalIncludes, localIncludes, useIncludes;
+ QStringList::Iterator it;
+ QStringList sqlClasses;
+
+ QMap<QString, CustomInclude> customWidgetIncludes;
+ QMap<QString, QString> functionImpls;
+ QString uiPmInclude;
+
+ // find additional slots
+ QStringList extraSlots;
+ QStringList extraSlotTyp;
+
+ nl = e.parentNode().toElement().elementsByTagName( "slot" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ n = nl.item(i).toElement();
+ if ( n.parentNode().toElement().tagName() != "slots"
+ && n.parentNode().toElement().tagName() != "connections" )
+ continue;
+ QString l = n.attribute( "language", "C++" );
+ if ( l != "C++" && l != "Perl" ) //- mmh
+ continue;
+ QString slotName = n.firstChild().toText().data().stripWhiteSpace();
+ if ( slotName.endsWith( ";" ) )
+ slotName = slotName.left( slotName.length() - 1 );
+
+ extraSlots += Parser::cleanArgs(slotName);
+ extraSlotTyp += n.attribute( "returnType", "void" );
+ }
+
+ // find additional functions
+ QStringList extraFuncts;
+ QStringList extraFunctTyp;
+
+ nl = e.parentNode().toElement().elementsByTagName( "function" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ n = nl.item(i).toElement();
+ if ( n.parentNode().toElement().tagName() != "functions" )
+ continue;
+ QString l = n.attribute( "language", "C++" );
+ if ( l != "C++" && l != "Perl" ) //- mmh
+ continue;
+ QString functionName = n.firstChild().toText().data().stripWhiteSpace();
+ if ( functionName.endsWith( ";" ) )
+ functionName = functionName.left( functionName.length() - 1 );
+ extraFuncts += Parser::cleanArgs(functionName);
+ extraFunctTyp += n.attribute( "returnType", "void" );
+ }
+
+ // find signals
+ QStringList extraSignals;
+ nl = e.parentNode().toElement().elementsByTagName( "signal" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ n = nl.item(i).toElement();
+ if ( n.parentNode().toElement().tagName() != "signals"
+ && n.parentNode().toElement().tagName() != "connections" )
+ continue;
+ QString l = n.attribute( "language", "C++" );
+ if ( l != "C++" && l != "Perl" ) //- mmh
+ continue;
+ QString sigName = n.firstChild().toText().data().stripWhiteSpace();
+ if ( sigName.endsWith( ";" ) )
+ sigName = sigName.left( sigName.length() - 1 );
+ extraSignals += sigName;
+ }
+
+#if 0
+ //- kept for diffs
+ QStringList customImages;
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "customwidgets" ) {
+ nl = n.elementsByTagName( "pixmap" );
+ for ( i = 0; i < (int) nl.length(); i++ )
+ customImages += nl.item( i ).firstChild().toText().data();
+ }
+ }
+#endif
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "customwidgets" ) {
+ QDomElement n2 = n.firstChild().toElement();
+ while ( !n2.isNull() ) {
+ if ( n2.tagName() == "customwidget" ) {
+ QDomElement n3 = n2.firstChild().toElement();
+ QString cl, header;
+ WidgetDatabaseRecord *r = new WidgetDatabaseRecord;
+ while ( !n3.isNull() ) {
+ if ( n3.tagName() == "class" ) {
+ cl = n3.firstChild().toText().data();
+ r->name = cl;
+ } else if ( n3.tagName() == "header" ) {
+ CustomInclude ci;
+ ci.header = n3.firstChild().toText().data();
+ ci.location = n3.attribute( "location", "global" );
+ r->includeFile = ci.header;
+ header = ci.header;
+ customWidgetIncludes.insert( cl, ci );
+ }
+ WidgetDatabase::append( r );
+ n3 = n3.nextSibling().toElement();
+ }
+
+ if (cl.isEmpty())
+ cl = "UnnamedCustomClass";
+
+ int ext = header.findRev('.');
+
+ if (ext >= 0)
+ header.truncate(ext);
+
+ if (header.isEmpty())
+ header = cl.lower();
+
+ if (!nofwd)
+ out << "use " << cl << ";" << endl; // FIXME: what about header ?
+ }
+ n2 = n2.nextSibling().toElement();
+ }
+ }
+ }
+
+ out << indent << "use Qt::isa qw(" << objClass << ");" << endl;
+
+ // PerlQt sig/slot declaration
+ if ( !extraSlots.isEmpty() ) {
+ out << indent << "use Qt::slots" << endl;
+ ++indent;
+ for ( it = extraSlots.begin(); it != extraSlots.end(); ++it )
+ {
+ perlSlot( it );
+ out << ( ((*it) == extraSlots.last()) ? ";":",") << endl;
+ }
+ --indent;
+ }
+
+ // create signals
+ if ( !extraSignals.isEmpty() ) {
+ out << indent << "use Qt::signals" << endl;
+ ++indent;
+ for ( it = extraSignals.begin(); it != extraSignals.end(); ++it )
+ {
+ perlSlot( it );
+ out << ( ((*it) == extraSignals.last()) ? ";":",") << endl;
+ }
+ --indent;
+ }
+
+ // PerlQt attributes
+ out << indent << "use Qt::attributes qw("<< endl;
+ ++indent;
+
+ // children
+ if( !objectNames.isEmpty() )
+ cerr << "WARNING : objectNames should be empty at form.cpp line" << __LINE__ << endl;
+ nl = e.parentNode().toElement().elementsByTagName( "widget" );
+ for ( i = 1; i < (int) nl.length(); i++ )
+ { // start at 1, 0 is the toplevel widget
+ n = nl.item(i).toElement();
+ createAttrDecl( n );
+ }
+ objectNames.clear();
+
+ // additional attributes (from Designer)
+ QStringList publicVars, protectedVars, privateVars;
+ nl = e.parentNode().toElement().elementsByTagName( "variable" );
+ for ( i = 0; i < (int)nl.length(); i++ ) {
+ n = nl.item( i ).toElement();
+ // Because of compatibility the next lines have to be commented out.
+ // Someday it should be uncommented.
+ //if ( n.parentNode().toElement().tagName() != "variables" )
+ // continue;
+ QString access = n.attribute( "access", "protected" );
+ QString var = n.firstChild().toText().data().stripWhiteSpace();
+ if ( var.endsWith( ";" ) )
+ var.truncate(var.length() - 1);
+ if ( access == "public" )
+ publicVars += var;
+ else if ( access == "private" )
+ privateVars += var;
+ else
+ protectedVars += var;
+ }
+
+ // for now, all member variables are public.
+
+ if ( !publicVars.isEmpty() ) {
+ for ( it = publicVars.begin(); it != publicVars.end(); ++it )
+ out << indent << *it << endl;
+ }
+ if ( !protectedVars.isEmpty() ) {
+ for ( it = protectedVars.begin(); it != protectedVars.end(); ++it )
+ out << indent << *it << endl;
+ }
+ if ( !privateVars.isEmpty() ) {
+ for ( it = privateVars.begin(); it != privateVars.end(); ++it )
+ out << indent << *it << endl;
+ }
+
+
+ // actions, toolbars, menus
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() )
+ {
+ if ( n.tagName() == "actions" )
+ {
+ for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
+ createActionDecl( a );
+ }
+ else if ( n.tagName() == "toolbars" )
+ {
+ for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
+ {
+ if ( a.tagName() == "toolbar" )
+ out << indent << getObjectName( a ) << endl;
+ }
+
+ }
+ else if ( n.tagName() == "menubar" )
+ {
+ out << indent << getObjectName( n ) << endl;
+ for ( QDomElement a = n.firstChild().toElement(); !a.isNull(); a = a.nextSibling().toElement() )
+ {
+ if ( a.tagName() == "item" )
+ out << indent << a.attribute( "name" ) << endl;
+ }
+ }
+ }
+
+ // Databases Connection holders
+
+ registerDatabases( e );
+ dbConnections = unique( dbConnections );
+ for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
+ if ( !(*it).isEmpty() && (*it) != "(default)") {
+ out << indent << (*it) << "Connection" << endl;
+ }
+ }
+
+ --indent;
+ out << indent << ");" << endl;
+ out << endl;
+
+
+ // additional includes (local or global ) and forward declaractions
+ nl = e.parentNode().toElement().elementsByTagName( "include" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ QDomElement n2 = nl.item(i).toElement();
+ QString s = n2.firstChild().toText().data();
+ if ( n2.attribute( "location" ) != "local" ) {
+ if ( (s.right( 5 ) == ".ui.h" || s.right( 6 ) == ".ui.pm") && !QFile::exists( s ) )
+ continue;
+ if ( n2.attribute( "impldecl", "in implementation" ) != "in implementation" )
+ continue;
+ globalIncludes += s;
+ }
+ }
+
+ // do the local includes afterwards, since global includes have priority on clashes
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ QDomElement n2 = nl.item(i).toElement();
+ QString s = n2.firstChild().toText().data();
+ if ( n2.attribute( "location" ) == "local" &&!globalIncludes.contains( s ) ) {
+ if ( (s.right( 5 ) == ".ui.h" || s.right( 6 ) == ".ui.pm") && !QFile::exists( s ) )
+ continue;
+ if ( n2.attribute( "impldecl", "in declaration" ) == "in declaration" )
+ {
+ useIncludes += s;
+ }
+ else if ( n2.attribute( "impldecl", "in implementation" ) == "in implementation" )
+ {
+ localIncludes += s;
+ }
+ }
+ }
+
+ // additional custom widget headers
+ nl = e.parentNode().toElement().elementsByTagName( "header" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ QDomElement n2 = nl.item(i).toElement();
+ QString s = n2.firstChild().toText().data();
+ if ( n2.attribute( "location" ) != "local" )
+ globalIncludes += s;
+ else
+ localIncludes += s;
+ }
+
+ // Output the "use" clauses for extra stuff in "Includes (In Declaration)"
+ // => in the perleditor plugin, this is content of the "Use clauses" list
+ for(QStringList::Iterator it = useIncludes.begin(); it != useIncludes.end(); ++it)
+ out << indent << (*it) << endl;
+
+ // grab slots/funcs defined in ui.h files / ui.pm files
+ for(QStringList::Iterator it = localIncludes.begin(); it != localIncludes.end(); ++it)
+ {
+ if((*it).right( 5 ) == ".ui.h")
+ {
+ QFile f((*it));
+ if( f.open( IO_ReadOnly ) )
+ {
+ QRegExp re("^.*([a-zA-Z0-9_]+\\s*\\(.*\\))\\s*$");
+ QRegExp re2("^\\}.*");
+ QTextStream t( &f );
+ QString s, s2, s3;
+ while ( !t.eof() )
+ {
+ s = t.readLine();
+ int pos = re.search(s);
+ if(pos == -1)
+ continue;
+ s2 = re.cap(1);
+ s2 = Parser::cleanArgs(s2);
+ s3 = QString::null;
+ while( !t.eof() )
+ {
+ s = t.readLine();
+ s3 += s + "\n";
+ if(re2.search(s) != -1)
+ break;
+ }
+ functionImpls.insert( s2, s3 );
+ if( t.eof() ) break;
+ }
+ f.close();
+ }
+ }
+ else if((*it).right( 6 ) == ".ui.pm")
+ {
+ //QFileInfo fname( fileName ); //- FIXME: .ui files seem to require being in CWD?
+ //QString path = fname.absFilePath();
+ //path = path.left( path.length() - fname.fileName().length() );
+ QFile f(*it);
+ if( f.open( IO_ReadOnly ) )
+ {
+ QTextStream t( &f );
+ QString s;
+ bool skip = true;
+ int count = 0;
+ while ( !t.eof() )
+ {
+ s = t.readLine();
+ if( skip )
+ {
+ if( s[0] == '#' )
+ {
+ count++;
+ continue;
+ }
+ else
+ {
+ skip = false;
+ uiPmInclude += "# line " + QString::number( count+1 ) + " \"" + *it + "\"\n";
+ }
+ }
+ uiPmInclude += s + "\n";
+ }
+ f.close();
+ }
+ }
+
+ }
+
+ // includes for child widgets
+ for ( it = tags.begin(); it != tags.end(); ++it ) {
+ nl = e.parentNode().toElement().elementsByTagName( *it );
+ for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
+ QString name = getClassName( nl.item(i).toElement() );
+ if ( name == "Spacer" ) {
+ globalIncludes += "qlayout.h";
+ globalIncludes += "qapplication.h";
+ continue;
+ }
+ if ( name.mid( 4 ) == "ListView" )
+ globalIncludes += "qheader.h";
+ if ( name != objClass ) {
+ int wid = WidgetDatabase::idFromClassName( name.replace( QRegExp("^Qt::"), "Q" ) );
+ QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find( name );
+ if ( it == customWidgetIncludes.end() )
+ globalIncludes += WidgetDatabase::includeFile( wid );
+ }
+ }
+ }
+
+ dbConnections = unique( dbConnections );
+ if ( dbConnections.count() )
+ sqlClasses += "Qt::SqlDatabase";
+ if ( dbCursors.count() )
+ sqlClasses += "Qt::SqlCursor";
+ bool dbForm = FALSE;
+ if ( dbForms[ "(default)" ].count() )
+ dbForm = TRUE;
+ bool subDbForms = FALSE;
+ for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
+ if ( !(*it).isEmpty() && (*it) != "(default)" ) {
+ if ( dbForms[ (*it) ].count() ) {
+ subDbForms = TRUE;
+ break;
+ }
+ }
+ }
+ if ( dbForm || subDbForms ) {
+ sqlClasses += "Qt::SqlForm";
+ sqlClasses += "Qt::SqlRecord";
+ }
+
+ if (globalIncludes.findIndex("qdatatable.h") >= 0)
+ sqlClasses += "Qt::DataTable";
+
+ if (globalIncludes.findIndex("qtableview.h") >= 0)
+ sqlClasses += "Qt::TableView";
+
+ if (globalIncludes.findIndex("qdatabrowser.h") >= 0)
+ sqlClasses += "Qt::DataBrowser";
+
+ out << endl;
+
+ // find out what images are required
+ QStringList requiredImages;
+ static const char *imgTags[] = { "pixmap", "iconset", 0 };
+ for ( i = 0; imgTags[i] != 0; i++ ) {
+ nl = e.parentNode().toElement().elementsByTagName( imgTags[i] );
+ for ( int j = 0; j < (int) nl.length(); j++ ) {
+ QDomNode nn = nl.item(j);
+ while ( nn.parentNode() != e.parentNode() )
+ nn = nn.parentNode();
+ if ( nn.nodeName() != "customwidgets" )
+ requiredImages += nl.item(j).firstChild().toText().data();
+ }
+ }
+
+ // register the object and unify its name
+ objName = registerObject( objName );
+
+ QStringList images;
+ QStringList xpmImages;
+ if ( pixmapLoaderFunction.isEmpty() && !externPixmaps )
+ {
+ // create images
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() )
+ {
+ if ( n.tagName() == "images" )
+ {
+ nl = n.elementsByTagName( "image" );
+ for ( i = 0; i < (int) nl.length(); i++ )
+ {
+ QString img = registerObject( nl.item(i).toElement().attribute( "name" ) );
+ if ( !requiredImages.contains( img ) )
+ continue;
+ QDomElement tmp = nl.item(i).firstChild().toElement();
+ if ( tmp.tagName() != "data" )
+ continue;
+ QString format = tmp.attribute("format", "PNG" );
+ QString data = tmp.firstChild().toText().data();
+ out << indent << "our $" << img << ";" << endl;
+ if ( format == "XPM.GZ" )
+ {
+ xpmImages += img;
+ ulong length = tmp.attribute("length").toULong();
+ QByteArray baunzip = unzipXPM( data, length );
+ length = baunzip.size();
+ // shouldn't we test the initial `length' against the
+ // resulting `length' to catch corrupt UIC files?
+ int a = 0;
+ out << indent << "our $" << img << "_data =\n[";
+
+ while ( baunzip[a] != '\"' )
+ a++;
+ for ( ; a < (int) length; a++ )
+ {
+ char ch;
+ if ((ch = baunzip[a]) == '}')
+ {
+ out << "];\n" << endl;
+
+ break;
+ }
+ out << ch;
+ }
+ }
+ else
+ {
+ images += img;
+ out << indent << "our $" << img << "_data = pack 'C*'," << endl;
+ ++indent;
+ int a ;
+ for ( a = 0; a < (int) (data.length()/2)-1; a++ ) {
+ out << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << ",";
+ if ( a % 12 == 11 )
+ out << endl << " ";
+ else
+ out << " ";
+ }
+ out << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << ";" << endl;
+ --indent;
+ out << endl;
+ }
+ }
+ }
+ }
+ out << endl;
+ }
+ else if ( externPixmaps )
+ {
+ pixmapLoaderFunction = "Qt::Pixmap::fromMimeSource";
+ }
+
+
+ // constructor(s)
+ out << indent << "sub NEW" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ if ( objClass == "Qt::Dialog" || objClass == "Qt::Wizard" ) {
+ out << indent << "shift->SUPER::NEW(@_[0..3]);" << endl;
+ } else if ( objClass == "Qt::Widget") {
+ out << indent << "shift->SUPER::NEW(@_[0..2]);" << endl;
+ } else if ( objClass == "Qt::MainWindow" ) {
+ out << indent << "shift->SUPER::NEW(@_[0..2]);" << endl;
+ out << indent << "statusBar();" << endl;
+ isMainWindow = TRUE;
+ } else {
+ out << indent << "shift->SUPER::NEW(@_[0,1]);" << endl;
+ }
+
+ out << endl;
+
+ // create pixmaps for all images
+ if ( !images.isEmpty() ) {
+ QStringList::Iterator it;
+ for ( it = images.begin(); it != images.end(); ++it ) {
+ out << indent << "$" << (*it) << " = Qt::Pixmap();" << endl;
+ out << indent << "$" << (*it) << "->loadFromData($" << (*it) << "_data, length ($" << (*it) << "_data), \"PNG\");" << endl;
+ }
+ out << endl;
+ }
+ // create pixmaps for all images
+ if ( !xpmImages.isEmpty() ) {
+ for ( it = xpmImages.begin(); it != xpmImages.end(); ++it ) {
+ out << indent << "$" << (*it) << " = Qt::Pixmap($" << (*it) << "_data);" << endl;
+ }
+ out << endl;
+ }
+
+
+ // set the properties
+ QSize geometry( 0, 0 );
+
+ for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "property" ) {
+ bool stdset = stdsetdef;
+ if ( n.hasAttribute( "stdset" ) )
+ stdset = toBool( n.attribute( "stdset" ) );
+ QString prop = n.attribute("name");
+ QDomElement n2 = n.firstChild().toElement();
+ QString value = setObjectProperty( objClass, QString::null, prop, n2, stdset );
+ if ( value.isEmpty() )
+ continue;
+
+ if ( prop == "geometry" && n2.tagName() == "rect" ) {
+ QDomElement n3 = n2.firstChild().toElement();
+ while ( !n3.isNull() ) {
+ if ( n3.tagName() == "width" )
+ geometry.setWidth( n3.firstChild().toText().data().toInt() );
+ else if ( n3.tagName() == "height" )
+ geometry.setHeight( n3.firstChild().toText().data().toInt() );
+ n3 = n3.nextSibling().toElement();
+ }
+ } else {
+ QString call;
+ if ( stdset )
+ call = mkStdSet( prop ) + "(" + value;
+ else
+ call = "setProperty(\"" + prop + "\", Qt::Variant(" + value + ")";
+ call += " );";
+ if ( n2.tagName() == "string" ) {
+ trout << indent << call << endl;
+ } else if ( prop == "name" ) {
+ out << indent << "if ( name() eq \"unnamed\" )" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ out << indent << call << endl;
+ --indent;
+ out << indent << "}" << endl;
+ } else {
+ out << indent << call << endl;
+ }
+ }
+ }
+ }
+
+ out << endl;
+
+ // create all children, some forms have special requirements
+
+ if ( objClass == "Qt::Wizard" )
+ {
+ for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() )
+ {
+ if ( tags.contains( n.tagName() ) )
+ {
+ QString page = createObjectImpl( n, objClass, "this" );
+ QString comment;
+ QString label = DomTool::readAttribute( n, "title", "", comment ).toString();
+ out << indent << "addPage( " << page << ", \"\" );" << endl;
+ trout << indent << "setTitle( " << page << ", " << trcall( label, comment ) << " );" << endl;
+ QVariant def( FALSE, 0 );
+ if ( DomTool::hasAttribute( n, "backEnabled" ) )
+ out << indent << "setBackEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "backEnabled", def).toBool() ) << ");" << endl;
+ if ( DomTool::hasAttribute( n, "nextEnabled" ) )
+ out << indent << "setNextEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "nextEnabled", def).toBool() ) << ");" << endl;
+ if ( DomTool::hasAttribute( n, "finishEnabled" ) )
+ out << indent << "setFinishEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "finishEnabled", def).toBool() ) << ");" << endl;
+ if ( DomTool::hasAttribute( n, "helpEnabled" ) )
+ out << indent << "setHelpEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "helpEnabled", def).toBool() ) << ");" << endl;
+ if ( DomTool::hasAttribute( n, "finish" ) )
+ out << indent << "setFinish( " << page << "," << mkBool( DomTool::readAttribute( n, "finish", def).toBool() ) << ");" << endl;
+ }
+ }
+ }
+ else
+ { // standard widgets
+ for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() )
+ {
+ if ( tags.contains( n.tagName() ) )
+ createObjectImpl( n, objName, "this" );
+ }
+ }
+
+ // database support
+ dbConnections = unique( dbConnections );
+ if ( dbConnections.count() )
+ out << endl;
+ for ( it = dbConnections.begin(); it != dbConnections.end(); ++it ) {
+ if ( !(*it).isEmpty() && (*it) != "(default)") {
+ out << indent << (*it) << "Connection = Qt::SqlDatabase::database(\"" <<(*it) << "\");" << endl;
+ }
+ }
+
+ nl = e.parentNode().toElement().elementsByTagName( "widget" );
+ for ( i = 1; i < (int) nl.length(); i++ ) { // start at 1, 0 is the toplevel widget
+ n = nl.item(i).toElement();
+ QString s = getClassName( n );
+ if ( (dbForm || subDbForms) && ( s == "Qt::DataBrowser" || s == "Qt::DataView" ) ) {
+ QString objName = getObjectName( n );
+ QString tab = getDatabaseInfo( n, "table" );
+ QString con = getDatabaseInfo( n, "connection" );
+ out << indent << "my $" << objName << "Form = Qt::SqlForm(this, \"" << objName << "Form\");" << endl;
+ QDomElement n2;
+ for ( n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() )
+ createFormImpl( n2, objName, con, tab );
+ out << indent << objName << "->setForm($" << objName << "Form);" << endl;
+ }
+ }
+
+ // actions, toolbars, menubar
+ bool needEndl = FALSE;
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "actions" ) {
+ if ( !needEndl )
+ out << endl;
+ createActionImpl( n.firstChild().toElement(), "this" );
+ needEndl = TRUE;
+ }
+ }
+ if ( needEndl )
+ out << endl;
+ needEndl = FALSE;
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "toolbars" ) {
+ if ( !needEndl )
+ out << endl;
+ createToolbarImpl( n, objClass, objName );
+ needEndl = TRUE;
+ }
+ }
+ if ( needEndl )
+ out << endl;
+ needEndl = FALSE;
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "menubar" ) {
+ if ( !needEndl )
+ out << endl;
+ createMenuBarImpl( n, objClass, objName );
+ needEndl = TRUE;
+ }
+ }
+ if ( needEndl )
+ out << endl;
+
+ out << indent << "languageChange();" << endl;
+
+ // take minimumSizeHint() into account, for height-for-width widgets
+ if ( !geometry.isNull() ) {
+ out << indent << "my $resize = Qt::Size(" << geometry.width() << ", "
+ << geometry.height() << ");" << endl;
+ out << indent << "$resize = $resize->expandedTo(minimumSizeHint());" << endl;
+ out << indent << "resize( $resize );" << endl;
+ out << indent << "clearWState( &Qt::WState_Polished );" << endl;
+ }
+
+ for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "connections" ) {
+ // setup signals and slots connections
+ out << endl;
+ nl = n.elementsByTagName( "connection" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ QString sender, receiver, signal, slot;
+ for ( QDomElement n2 = nl.item(i).firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() ) {
+ if ( n2.tagName() == "sender" )
+ sender = n2.firstChild().toText().data();
+ else if ( n2.tagName() == "receiver" )
+ receiver = n2.firstChild().toText().data();
+ else if ( n2.tagName() == "signal" )
+ signal = n2.firstChild().toText().data();
+ else if ( n2.tagName() == "slot" )
+ slot = n2.firstChild().toText().data();
+ }
+ if ( sender.isEmpty() ||
+ receiver.isEmpty() ||
+ signal.isEmpty() ||
+ slot.isEmpty() )
+ continue;
+ else if ( sender[0] == '<' ||
+ receiver[0] == '<' ||
+ signal[0] == '<' ||
+ slot[0] == '<' )
+ continue;
+ sender = registeredName( sender );
+ receiver = registeredName( receiver );
+
+ if ( sender == objName )
+ sender = "this";
+ if ( receiver == objName )
+ receiver = "this";
+
+ out << indent << "Qt::Object::connect(" << sender
+ << ", SIGNAL \"" << signal << "\", "<< receiver << ", SLOT \"" << slot << "\");" << endl;
+ }
+ } else if ( n.tagName() == "tabstops" ) {
+ // setup tab order
+ out << endl;
+ QString lastName;
+ QDomElement n2 = n.firstChild().toElement();
+ while ( !n2.isNull() ) {
+ if ( n2.tagName() == "tabstop" ) {
+ QString name = n2.firstChild().toText().data();
+ name = registeredName( name );
+ if ( !lastName.isEmpty() )
+ out << indent << "setTabOrder(" << lastName << ", " << name << ");" << endl;
+ lastName = name;
+ }
+ n2 = n2.nextSibling().toElement();
+ }
+ }
+ }
+
+ // buddies
+ bool firstBuddy = TRUE;
+ for ( QValueList<Buddy>::Iterator buddy = buddies.begin(); buddy != buddies.end(); ++buddy ) {
+ if ( isObjectRegistered( (*buddy).buddy ) ) {
+ if ( firstBuddy ) {
+ out << endl;
+ }
+ out << indent << (*buddy).key << "->setBuddy(this->" << registeredName( (*buddy).buddy ) << ");" << endl;
+ firstBuddy = FALSE;
+ }
+
+ }
+ if ( extraFuncts.find( "init()" ) != extraFuncts.end() ||
+ extraSlots.find( "init()" ) != extraSlots.end() )
+ out << endl << indent << "init();" << endl;
+
+ // end of constructor
+ --indent;
+ out << indent << "}" << endl;
+ out << endl;
+
+ if ( extraFuncts.find( "destroy()" ) != extraFuncts.end() ||
+ extraSlots.find( "destroy()" ) != extraSlots.end() ) {
+ out << endl;
+ out << indent << "sub DESTROY" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ out << indent << "destroy();" << endl;
+ out << indent << "SUPER->DESTROY()" << endl;
+ --indent;
+ out << indent << "}" << endl;
+ }
+
+
+ // handle application events if required
+ bool needFontEventHandler = FALSE;
+ bool needSqlTableEventHandler = FALSE;
+ bool needSqlDataBrowserEventHandler = FALSE;
+ nl = e.elementsByTagName( "widget" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ if ( !DomTool::propertiesOfType( nl.item(i).toElement() , "font" ).isEmpty() )
+ needFontEventHandler = TRUE;
+ QString s = getClassName( nl.item(i).toElement() );
+ if ( s == "Qt::DataTable" || s == "Qt::DataBrowser" ) {
+ if ( !isFrameworkCodeGenerated( nl.item(i).toElement() ) )
+ continue;
+ if ( s == "Qt::DataTable" )
+ needSqlTableEventHandler = TRUE;
+ if ( s == "Qt::DataBrowser" )
+ needSqlDataBrowserEventHandler = TRUE;
+ }
+ if ( needFontEventHandler && needSqlTableEventHandler && needSqlDataBrowserEventHandler )
+ break;
+ }
+
+// PerlQt - TODO: is this needed ?
+// Seems not.. let's ifzero for now...
+
+ if ( 0 && needFontEventHandler ) {
+ // indent = "\t"; // increase indentation for if-clause below
+ out << endl;
+ out << "# Main event handler. Reimplemented to handle" << endl;
+ out << "# application font changes" << endl;
+ out << endl;
+ out << "sub event" << endl;
+ out << "{" << endl;
+ out << " my $ev = shift;" << endl;
+ out << " my $ret = SUPER->event( $ev ); " << endl;
+ if ( needFontEventHandler ) {
+ ++indent;
+ out << " if ( $ev->type() == &Qt::Event::ApplicationFontChange ) {" << endl;
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ n = nl.item(i).toElement();
+ QStringList list = DomTool::propertiesOfType( n, "font" );
+ for ( it = list.begin(); it != list.end(); ++it )
+ createExclusiveProperty( n, *it );
+ }
+ out << " }" << endl;
+ --indent;
+ }
+ out << "}" << endl;
+ out << endl;
+ }
+
+ if ( needSqlTableEventHandler || needSqlDataBrowserEventHandler ) {
+ out << endl;
+ out << indent << "# Widget polish. Reimplemented to handle default data" << endl;
+ if ( needSqlTableEventHandler )
+ out << indent << "# table initialization." << endl;
+ if ( needSqlDataBrowserEventHandler )
+ out << indent << "# browser initialization." << endl;
+ out << indent << "sub polish" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ if ( needSqlTableEventHandler ) {
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ QString s = getClassName( nl.item(i).toElement() );
+ if ( s == "Qt::DataTable" ) {
+ n = nl.item(i).toElement();
+ QString c = getObjectName( n );
+ QString conn = getDatabaseInfo( n, "connection" );
+ QString tab = getDatabaseInfo( n, "table" );
+ if ( !( conn.isEmpty() || tab.isEmpty() || !isFrameworkCodeGenerated( nl.item(i).toElement() ) ) ) {
+ out << indent << "if(" << c << ")" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ out << indent << "my $cursor = " << c << "->sqlCursor();" << endl;
+ out << endl;
+ out << indent << "if(!$cursor)" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ if ( conn == "(default)" )
+ out << indent << "$cursor = Qt::SqlCursor(\"" << tab << "\");" << endl;
+ else
+ out << indent << "$cursor = Qt::SqlCursor(\"" << tab << "\", 1, " << conn << "Connection);" << endl;
+ out << indent << "if ( " << c << "->isReadOnly() ) " << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ out << indent << "$cursor->setMode( &Qt::SqlCursor::ReadOnly )" << endl;
+ --indent;
+ out << indent << "}" << endl;
+ out << indent << c << "->setSqlCursor($cursor, 0, 1);" << endl;
+ --indent;
+ out << endl;
+ out << indent << "}" << endl;
+ out << indent << "if(!$cursor->isActive())" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ out << indent << c << "->refresh( &Qt::DataTable::RefreshAll );" << endl;
+ --indent;
+ out << indent << "}" << endl;
+ --indent;
+ out << indent << "}" << endl;
+ }
+ }
+ }
+ }
+ if ( needSqlDataBrowserEventHandler ) {
+ nl = e.elementsByTagName( "widget" );
+ for ( i = 0; i < (int) nl.length(); i++ ) {
+ QString s = getClassName( nl.item(i).toElement() );
+ if ( s == "Qt::DataBrowser" ) {
+ QString obj = getObjectName( nl.item(i).toElement() );
+ QString tab = getDatabaseInfo( nl.item(i).toElement(),
+ "table" );
+ QString conn = getDatabaseInfo( nl.item(i).toElement(),
+ "connection" );
+ if ( !(tab).isEmpty() || !isFrameworkCodeGenerated( nl.item(i).toElement() ) ) {
+ out << indent << "if(" << obj << ")" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ out << indent << "if(!" << obj << "->sqlCursor())" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ if ( conn == "(default)" )
+ out << indent << "my $cursor = Qt::SqlCursor(\"" << tab << "\");" << endl;
+ else
+ out << indent << "my $cursor = Qt::SqlCursor(\"" << tab << "\", 1, " << conn << "Connection);" << endl;
+ out << indent << obj << "->setSqlCursor($cursor, 1);" << endl;
+ out << indent << obj << "->refresh();" << endl;
+ out << indent << obj << "->first();" << endl;
+ --indent;
+ out << indent << "}" << endl;
+ --indent;
+ out << indent << "}" << endl;
+ }
+ }
+ }
+ }
+ out << indent << "SUPER->polish();" << endl;
+ --indent;
+ out << indent << "}" << endl;
+ }
+
+ out << endl;
+ out << indent << "# Sets the strings of the subwidgets using the current" << endl;
+ out << indent << "# language." << endl;
+ out << endl;
+ out << indent << "sub languageChange" << endl;
+ out << indent << "{" << endl;
+ ++indent;
+ out << languageChangeBody;
+ --indent;
+ out << indent << "}" << endl;
+ out << endl;
+
+ // create stubs for additional functs/slots if necessary
+
+ for ( it = extraSlots.begin(); it != extraSlots.end(); ++it )
+ extraFuncts << *it;
+
+ if ( !extraFuncts.isEmpty() && writeFunctImpl && uiPmInclude.isNull() ) {
+ for ( it = extraFuncts.begin(); it != extraFuncts.end(); ++it ) {
+ out << endl;
+ int astart = (*it).find('(');
+ out << indent << "sub " << (*it).left(astart)<< endl;
+ out << indent << "{" << endl;
+ bool createWarning = TRUE;
+ QString fname = Parser::cleanArgs( *it );
+ QMap<QString, QString>::Iterator fit = functionImpls.find( fname );
+ if ( fit != functionImpls.end() ) {
+ int begin = (*fit).find( "{" );
+ QString body = (*fit).mid( begin + 1, (*fit).findRev( "}" ) - begin - 1 );
+ createWarning = body.simplifyWhiteSpace().isEmpty();
+ if ( !createWarning )
+ out << body << endl;
+ }
+ if ( createWarning ) {
+ ++indent;
+ if ( *it != "init()" && *it != "destroy()" )
+ out << indent << "print \"" << nameOfClass << "->" << (*it) << ": Not implemented yet.\\n\";" << endl;
+ --indent;
+ }
+ out << indent << "}" << endl;
+
+ }
+ }
+ else if( !extraFuncts.isEmpty() && writeFunctImpl )
+ {
+ ++indent;
+ for ( it = extraFuncts.begin(); it != extraFuncts.end(); ++it ) {
+ if ( *it == "init()" || *it == "destroy()" )
+ continue;
+ int astart = (*it).find('(');
+ QRegExp r( "(\\nsub\\s+" + (*it).left(astart) + "(?:\\s*#\\s*SLOT:[^\\n]+|[ \t]+)?\\n\\{)(\\s*)(\\}\\n)" );
+ r.setMinimal( true );
+ uiPmInclude.replace( r, "\\1\n" +
+ indent + "print \"" + nameOfClass + "->" + (*it) +
+ ": Not implemented yet.\\n\";" + "\n\\3" );
+ }
+ --indent;
+
+ }
+
+ if( !uiPmInclude.isNull() )
+ out << uiPmInclude;
+
+ out << endl;
+ out << "1;" << endl; // Perl modules must return true
+}
+
+
+/*! Creates form support implementation code for the widgets given
+ in \a e.
+
+ Traverses recursively over all children.
+ */
+
+void Uic::createFormImpl( const QDomElement& e, const QString& form, const QString& connection, const QString& table )
+{
+ if ( e.tagName() == "widget" &&
+ e.attribute( "class" ) != "Qt::DataTable" ) {
+ QString field = getDatabaseInfo( e, "field" );
+ if ( !field.isEmpty() ) {
+ if ( isWidgetInTable( e, connection, table ) )
+ out << indent << "$" << form << "Form->insert(" << getObjectName( e ) << ", " << fixString( field ) << ");" << endl;
+ }
+ }
+ QDomElement n;
+ for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
+ createFormImpl( n, form, connection, table );
+ }
+}
+
+
+// Generate a PerlQt signal/slot definition.
+
+void Uic::perlSlot(QStringList::Iterator &it)
+{
+ int astart = (*it).find('(');
+ out << indent << (*it).left(astart) << " => ";
+ QString args = (*it).mid(astart + 1,(*it).find(')') - astart - 1).stripWhiteSpace();
+ out << "[";
+ if (!args.isEmpty())
+ {
+ QStringList arglist = QStringList::split( QRegExp(","), args );
+ out << "'" << arglist.join( "', '") << "'";
+ }
+ out << "]";
+}