You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
939 lines
31 KiB
939 lines
31 KiB
15 years ago
|
/**********************************************************************
|
||
|
** Copyright (C) 2000 Trolltech AS. All rights reserved.
|
||
|
**
|
||
|
** 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 info@trolltech.com if any conditions of this licensing are
|
||
|
** not clear to you.
|
||
|
**
|
||
|
**********************************************************************/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include "uic.h"
|
||
|
#include "parser.h"
|
||
|
#include "widgetdatabase.h"
|
||
|
#include "domtool.h"
|
||
|
#include <qstringlist.h>
|
||
|
#include <qfile.h>
|
||
|
#include <qfileinfo.h>
|
||
|
#include <qregexp.h>
|
||
|
#define NO_STATIC_COLORS
|
||
|
#include <globaldefs.h>
|
||
|
|
||
|
#if QT_VERSION < 0x030100
|
||
|
#include <zlib.h>
|
||
|
#endif
|
||
|
|
||
|
static QByteArray unzipXPM( QString data, ulong& length )
|
||
|
{
|
||
|
#if QT_VERSION >= 0x030100
|
||
|
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;
|
||
|
#else
|
||
|
uchar *ba = new uchar[ data.length() / 2 ];
|
||
|
for ( int i = 0; i < (int)data.length() / 2; ++i ) {
|
||
|
char h = data[ 2 * i ].latin1();
|
||
|
char l = data[ 2 * i + 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;
|
||
|
}
|
||
|
// I'm not sure this makes sense. Why couldn't the compressed data be
|
||
|
// less than 20% of the original data? Maybe it's enough to trust the
|
||
|
// `length' passed as an argument. Quoting the zlib header:
|
||
|
// Upon entry, destLen is the total size of the destination
|
||
|
// buffer, which must be large enough to hold the entire
|
||
|
// uncompressed data. (The size of the uncompressed data must
|
||
|
// have been saved previously by the compressor and transmitted
|
||
|
// to the decompressor by some mechanism outside the scope of
|
||
|
// this compression library.)
|
||
|
// Which is the role of `length'. On the other hand this could prevent
|
||
|
// crashes in some cases of slightly corrupt UIC files.
|
||
|
if ( length < data.length() * 5 )
|
||
|
length = data.length() * 5;
|
||
|
QByteArray baunzip( length );
|
||
|
::uncompress( (uchar*) baunzip.data(), &length, ba, data.length()/2 );
|
||
|
delete[] ba;
|
||
|
return baunzip;
|
||
|
#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 );
|
||
|
|
||
|
// generate local and local includes required
|
||
|
QStringList globalIncludes;
|
||
|
QStringList::Iterator it;
|
||
|
QStringList sqlClasses;
|
||
|
QStringList axwidgets, databrowsers;
|
||
|
|
||
|
QMap<QString, CustomInclude> customWidgetIncludes;
|
||
|
QMap<QString, QString> functionImpls;
|
||
|
// find additional slots and functions
|
||
|
QStringList extraSlots;
|
||
|
QStringList extraSlotTypes;
|
||
|
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;
|
||
|
if ( n.attribute( "language", "C++" ) != "C++" )
|
||
|
continue;
|
||
|
QString slotName = n.firstChild().toText().data().stripWhiteSpace();
|
||
|
if ( slotName.endsWith( ";" ) )
|
||
|
slotName = slotName.left( slotName.length() - 1 );
|
||
|
|
||
|
extraSlots += Parser::cleanArgs(slotName);
|
||
|
extraSlotTypes += n.attribute( "returnType", "void" );
|
||
|
}
|
||
|
|
||
|
for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
|
||
|
if ( n.tagName() == "functions" ) { // compatibility
|
||
|
for ( QDomElement n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() ) {
|
||
|
if ( n2.tagName() == "function" ) {
|
||
|
QString fname = n2.attribute( "name" );
|
||
|
fname = Parser::cleanArgs( fname );
|
||
|
functionImpls.insert( fname, n2.firstChild().toText().data() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 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" && !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
|
||
|
QFileInfo fi(fileName);
|
||
|
|
||
|
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" )
|
||
|
continue;
|
||
|
|
||
|
if ( !QFile::exists( s ) )
|
||
|
{
|
||
|
s = fi.dirPath() + "/" + s;
|
||
|
|
||
|
if ( !QFile::exists( s ) )
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( QFile::exists( s ) )
|
||
|
{
|
||
|
QFile f(s);
|
||
|
f.open(IO_ReadOnly);
|
||
|
QTextStream headerStream(&f);
|
||
|
QString line;
|
||
|
QString functionText;
|
||
|
QString functionName;
|
||
|
QRegExp rx("void .*::(.*\\(.*\\))");
|
||
|
int pos, inFunction = 0;
|
||
|
|
||
|
while (line = headerStream.readLine())
|
||
|
{
|
||
|
pos = rx.search(line);
|
||
|
|
||
|
if (pos > -1)
|
||
|
{
|
||
|
if (inFunction)
|
||
|
functionImpls.insert(Parser::cleanArgs(functionName),functionText);
|
||
|
|
||
|
functionName = rx.cap(1);
|
||
|
functionText = "";
|
||
|
inFunction = 1;
|
||
|
}
|
||
|
functionText += line + "\n";
|
||
|
}
|
||
|
|
||
|
if (inFunction)
|
||
|
functionImpls.insert(Parser::cleanArgs(functionName),functionText);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
// 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( 1 ) == "ListView" )
|
||
|
globalIncludes += "qheader.h";
|
||
|
else if ( name == "QAxWidget" )
|
||
|
axwidgets += getObjectName(nl.item(i).toElement());
|
||
|
else if ( name == "QDataBrowser" )
|
||
|
databrowsers += getObjectName(nl.item(i).toElement());
|
||
|
if ( name != objClass ) {
|
||
|
int wid = WidgetDatabase::idFromClassName( name );
|
||
|
QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find( name );
|
||
|
if ( it == customWidgetIncludes.end() )
|
||
|
globalIncludes += WidgetDatabase::includeFile( wid );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (globalIncludes.findIndex("qtable.h") >= 0)
|
||
|
out << indent << "from qttable import QTable" << endl;
|
||
|
|
||
|
if (!axwidgets.empty())
|
||
|
out << indent << "from qtaxcontainer import QAxWidget" << endl;
|
||
|
|
||
|
if (globalIncludes.findIndex("qextscintilla.h") >= 0)
|
||
|
out << indent << "from qtext import QextScintilla" << endl;
|
||
|
|
||
|
registerDatabases( e );
|
||
|
dbConnections = unique( dbConnections );
|
||
|
if ( dbConnections.count() )
|
||
|
sqlClasses += "QSqlDatabase";
|
||
|
if ( dbCursors.count() )
|
||
|
sqlClasses += "QSqlCursor";
|
||
|
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 += "QSqlForm";
|
||
|
sqlClasses += "QSqlRecord";
|
||
|
}
|
||
|
|
||
|
if (globalIncludes.findIndex("qdatatable.h") >= 0)
|
||
|
sqlClasses += "QDataTable";
|
||
|
|
||
|
if (globalIncludes.findIndex("qtableview.h") >= 0)
|
||
|
sqlClasses += "QTableView";
|
||
|
|
||
|
if (globalIncludes.findIndex("qdatabrowser.h") >= 0)
|
||
|
sqlClasses += "QDataBrowser";
|
||
|
|
||
|
if (globalIncludes.findIndex("qdataview.h") >= 0)
|
||
|
sqlClasses += "QDataView";
|
||
|
|
||
|
if ( !sqlClasses.empty() ) {
|
||
|
out << indent << "from qtsql import";
|
||
|
const char *sep = " ";
|
||
|
|
||
|
for ( it = sqlClasses.begin(); it != sqlClasses.end(); ++it ) {
|
||
|
out << sep << (*it);
|
||
|
sep = ", ";
|
||
|
}
|
||
|
|
||
|
out << endl;
|
||
|
}
|
||
|
|
||
|
// Add any code from the comments.
|
||
|
if (!pyCode.isEmpty())
|
||
|
out << pyCode;
|
||
|
|
||
|
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();
|
||
|
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 << img << "_data = [" << endl;
|
||
|
while ( baunzip[a] != '\"' )
|
||
|
a++;
|
||
|
for ( ; a < (int) length; a++ )
|
||
|
{
|
||
|
char ch;
|
||
|
|
||
|
if ((ch = baunzip[a]) == '}')
|
||
|
{
|
||
|
out << endl << "]";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
out << ch;
|
||
|
}
|
||
|
out << endl;
|
||
|
} else {
|
||
|
images += img;
|
||
|
out << indent << img << "_data = \\" << endl;
|
||
|
++indent;
|
||
|
out << indent << "\"";
|
||
|
int a ;
|
||
|
for ( a = 0; a < (int) (data.length()/2)-1; a++ ) {
|
||
|
out << "\\x" << QString(data[2*a]) << QString(data[2*a+1]);
|
||
|
if ( a % 12 == 11 )
|
||
|
out << "\" \\" << endl << indent << "\"";
|
||
|
}
|
||
|
out << "\\x" << QString(data[2*a]) << QString(data[2*a+1]) << "\"" << endl;
|
||
|
--indent;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
out << endl;
|
||
|
} else if ( externPixmaps ) {
|
||
|
#if QT_VERSION >= 0x030100
|
||
|
pixmapLoaderFunction = "QPixmap.fromMimeSource";
|
||
|
#else
|
||
|
out << indent << "def uic_load_pixmap_" << objName << "(name):" << endl;
|
||
|
++indent;
|
||
|
out << indent << "pix = QPixmap()" << endl;
|
||
|
out << indent << "m = QMimeSourceFactory.defaultFactory().data(name)" << endl;
|
||
|
out << endl;
|
||
|
out << indent << "if m:" << endl;
|
||
|
++indent;
|
||
|
out << indent << "QImageDrag.decode(m,pix)" << endl;
|
||
|
--indent;
|
||
|
out << endl;
|
||
|
out << indent << "return pix" << endl;
|
||
|
--indent;
|
||
|
out << endl;
|
||
|
out << endl;
|
||
|
pixmapLoaderFunction = "uic_load_pixmap_" + objName;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
// constructor(s)
|
||
|
|
||
|
out << indent << "class " << nameOfClass << "(" << objClass << "):" << endl;
|
||
|
++indent;
|
||
|
|
||
|
if ( objClass == "QDialog" || objClass == "QWizard" ) {
|
||
|
out << indent << "def __init__(self,parent = None,name = None,modal = 0,fl = 0):" << endl;
|
||
|
++indent;
|
||
|
out << indent << objClass << ".__init__(self,parent,name,modal,fl)" << endl;
|
||
|
} else if ( objClass == "QWidget" ) {
|
||
|
out << indent << "def __init__(self,parent = None,name = None,fl = 0):" << endl;
|
||
|
++indent;
|
||
|
out << indent << objClass << ".__init__(self,parent,name,fl)" << endl;
|
||
|
} else if ( objClass == "QMainWindow" ) {
|
||
|
out << indent << "def __init__(self,parent = None,name = None,fl = 0):" << endl;
|
||
|
++indent;
|
||
|
out << indent << objClass << ".__init__(self,parent,name,fl)" << endl;
|
||
|
out << indent << "self.statusBar()" << endl;
|
||
|
isMainWindow = TRUE;
|
||
|
} else {
|
||
|
out << indent << "def __init__(self,parent = None,name = None):" << endl;
|
||
|
++indent;
|
||
|
out << indent << objClass << ".__init__(self,parent,name)" << endl;
|
||
|
}
|
||
|
|
||
|
out << endl;
|
||
|
|
||
|
// create pixmaps for all images
|
||
|
if ( !images.isEmpty() ) {
|
||
|
QStringList::Iterator it;
|
||
|
for ( it = images.begin(); it != images.end(); ++it ) {
|
||
|
out << indent << "self." << (*it) << " = QPixmap()" << endl;
|
||
|
out << indent << "self." << (*it) << ".loadFromData(" << (*it) << "_data,\"PNG\")" << endl;
|
||
|
}
|
||
|
}
|
||
|
// create pixmaps for all images
|
||
|
if ( !xpmImages.isEmpty() ) {
|
||
|
for ( it = xpmImages.begin(); it != xpmImages.end(); ++it ) {
|
||
|
out << indent << "self." << (*it) << " = QPixmap(" << (*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 = "self." + mkStdSet( prop ) + "(" + value + ")";
|
||
|
else
|
||
|
call = "self.setProperty(\"" + prop + "\",QVariant(" + value + "))";
|
||
|
|
||
|
if ( n2.tagName() == "string" ) {
|
||
|
trout << trindent << call << endl;
|
||
|
} else if ( prop == "name" ) {
|
||
|
out << indent << "if not name:" << endl;
|
||
|
++indent;
|
||
|
out << indent << call << endl;
|
||
|
--indent;
|
||
|
out << endl;
|
||
|
} else {
|
||
|
out << indent << call << endl;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
out << endl;
|
||
|
|
||
|
// create all children, some forms have special requirements
|
||
|
|
||
|
if ( objClass == "QWizard" ) {
|
||
|
for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
|
||
|
if ( tags.contains( n.tagName() ) ) {
|
||
|
QString page = createObjectImpl( n, objClass, "self" );
|
||
|
QString comment;
|
||
|
QString label = DomTool::readAttribute( n, "title", "", comment ).toString();
|
||
|
out << indent << "self.addPage(" << page << ",QString(\"\"))" << endl;
|
||
|
trout << trindent << "self.setTitle(" << page << ","<< trcall( label, comment ) << ")" << endl;
|
||
|
QVariant def( FALSE, 0 );
|
||
|
if ( DomTool::hasAttribute( n, "backEnabled" ) )
|
||
|
out << indent << "self.setBackEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "backEnabled", def).toBool() ) << ")" << endl;
|
||
|
if ( DomTool::hasAttribute( n, "nextEnabled" ) )
|
||
|
out << indent << "self.setNextEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "nextEnabled", def).toBool() ) << ")" << endl;
|
||
|
if ( DomTool::hasAttribute( n, "finishEnabled" ) )
|
||
|
out << indent << "self.setFinishEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "finishEnabled", def).toBool() ) << ")" << endl;
|
||
|
if ( DomTool::hasAttribute( n, "helpEnabled" ) )
|
||
|
out << indent << "self.setHelpEnabled(" << page << "," << mkBool( DomTool::readAttribute( n, "helpEnabled", def).toBool() ) << ")" << endl;
|
||
|
if ( DomTool::hasAttribute( n, "finish" ) )
|
||
|
out << indent << "self.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, "self" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 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 << "self." << (*it) << "Connection = QSqlDatabase.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 == "QDataBrowser" || s == "QDataView") ) {
|
||
|
QString objName = getObjectName( n );
|
||
|
QString tab = getDatabaseInfo( n, "table" );
|
||
|
QString con = getDatabaseInfo( n, "connection" );
|
||
|
out << indent << objName << "Form = QSqlForm(self,\"" << objName << "Form\")" << endl;
|
||
|
QDomElement n2;
|
||
|
for ( n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() )
|
||
|
createFormImpl( n2, objName, con, tab );
|
||
|
out << indent << "self." << 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(), "self" );
|
||
|
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 << endl;
|
||
|
out << indent << "self.languageChange()" << endl;
|
||
|
out << endl;
|
||
|
|
||
|
// take minimumSizeHint() into account, for height-for-width widgets
|
||
|
if ( !geometry.isNull() ) {
|
||
|
out << indent << "self.resize(QSize(" << geometry.width() << ","
|
||
|
<< geometry.height() <<").expandedTo(self.minimumSizeHint()))" << endl;
|
||
|
out << indent << "self.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;
|
||
|
if ( sender[0] == '<' ||
|
||
|
receiver[0] == '<' ||
|
||
|
signal[0] == '<' ||
|
||
|
slot[0] == '<' )
|
||
|
continue;
|
||
|
|
||
|
sender = registeredName( sender );
|
||
|
receiver = registeredName( receiver );
|
||
|
|
||
|
// translate formwindow name to "self"
|
||
|
if ( sender == objName )
|
||
|
sender = "self";
|
||
|
else
|
||
|
sender = "self." + sender;
|
||
|
|
||
|
bool isaxwidget = (axwidgets.findIndex(receiver) >= 0);
|
||
|
bool isdatabrowser = (databrowsers.findIndex(receiver) >= 0);
|
||
|
|
||
|
if ( receiver == objName )
|
||
|
receiver = "self";
|
||
|
else
|
||
|
receiver = "self." + receiver;
|
||
|
|
||
|
out << indent << "self.connect(" << sender
|
||
|
<< ",SIGNAL(\"" << signal << "\")," << receiver;
|
||
|
|
||
|
// Normally we never use the SLOT() macro in case the
|
||
|
// connection is to a method of a Python custom widget. The
|
||
|
// exception is if the receiver is a QAxWidget where it must be
|
||
|
// used because the slots are dynamic.
|
||
|
if (isaxwidget)
|
||
|
out << ",SLOT(\"" << slot << "\")";
|
||
|
else
|
||
|
{
|
||
|
QString mname = slot.left(slot.find('('));
|
||
|
|
||
|
// Rename slots that have different names in PyQt.
|
||
|
if (isdatabrowser && mname == "del")
|
||
|
mname = "delOnCursor";
|
||
|
|
||
|
out << "." << mname;
|
||
|
}
|
||
|
|
||
|
out << ")" << 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 << "self.setTabOrder(self." << lastName << ",self." << 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 << "self." << (*buddy).key << ".setBuddy(self." << registeredName( (*buddy).buddy ) << ")" << endl;
|
||
|
firstBuddy = FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( extraSlots.find( "init()" ) != extraSlots.end() )
|
||
|
out << endl << indent << "self.init()" << endl;
|
||
|
|
||
|
// end of constructor
|
||
|
--indent;
|
||
|
|
||
|
// destructor
|
||
|
if ( extraSlots.find( "destroy()" ) != extraSlots.end() ) {
|
||
|
out << endl;
|
||
|
out << indent << "def __del__(self):" << endl;
|
||
|
++indent;
|
||
|
out << indent << "self.destroy()" << endl;
|
||
|
--indent;
|
||
|
}
|
||
|
|
||
|
// 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 == "QDataTable" || s == "QDataBrowser" ) {
|
||
|
if ( !isFrameworkCodeGenerated( nl.item(i).toElement() ) )
|
||
|
continue;
|
||
|
if ( s == "QDataTable" )
|
||
|
needSqlTableEventHandler = TRUE;
|
||
|
if ( s == "QDataBrowser" )
|
||
|
needSqlDataBrowserEventHandler = TRUE;
|
||
|
}
|
||
|
if ( needFontEventHandler && needSqlTableEventHandler && needSqlDataBrowserEventHandler )
|
||
|
break;
|
||
|
}
|
||
|
if ( needFontEventHandler && FALSE ) {
|
||
|
// indent = "\t"; // increase indentation for if-clause below
|
||
|
out << "/* " << endl;
|
||
|
out << " * Main event handler. Reimplemented to handle" << endl;
|
||
|
out << " * application font changes";
|
||
|
out << " */" << endl;
|
||
|
out << "bool " << nameOfClass << "::event( QEvent* ev )" << endl;
|
||
|
out << "{" << endl;
|
||
|
out << " bool ret = " << objClass << "::event( ev ); " << endl;
|
||
|
if ( needFontEventHandler ) {
|
||
|
++indent;
|
||
|
out << " if ( ev->type() == QEvent::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 << "def polish(self):" << endl;
|
||
|
++indent;
|
||
|
if ( needSqlTableEventHandler ) {
|
||
|
for ( i = 0; i < (int) nl.length(); i++ ) {
|
||
|
QString s = getClassName( nl.item(i).toElement() );
|
||
|
if ( s == "QDataTable" ) {
|
||
|
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 self." << c << ":" << endl;
|
||
|
++indent;
|
||
|
out << indent << "cursor = self." << c << ".sqlCursor()" << endl;
|
||
|
out << endl;
|
||
|
out << indent << "if not cursor:" << endl;
|
||
|
++indent;
|
||
|
if ( conn == "(default)" )
|
||
|
out << indent << "cursor = QSqlCursor(\"" << tab << "\")" << endl;
|
||
|
else
|
||
|
out << indent << "cursor = QSqlCursor(\"" << tab << "\",1,self." << conn << "Connection)" << endl;
|
||
|
out << indent << "if self." << c << ".isReadOnly():" << endl;
|
||
|
++indent;
|
||
|
out << indent << "cursor.setMode(QSqlCursor.ReadOnly)" << endl;
|
||
|
--indent;
|
||
|
out << indent << "self." << c << ".setSqlCursor(cursor,0,1)" << endl;
|
||
|
--indent;
|
||
|
out << endl;
|
||
|
out << indent << "if not cursor.isActive():" << endl;
|
||
|
++indent;
|
||
|
out << indent << "self." << c << ".refresh(QDataTable.RefreshAll)" << endl;
|
||
|
--indent;
|
||
|
--indent;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( needSqlDataBrowserEventHandler ) {
|
||
|
nl = e.elementsByTagName( "widget" );
|
||
|
for ( i = 0; i < (int) nl.length(); i++ ) {
|
||
|
QString s = getClassName( nl.item(i).toElement() );
|
||
|
if ( s == "QDataBrowser" ) {
|
||
|
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 self." << obj << ":" << endl;
|
||
|
++indent;
|
||
|
out << indent << "if not self." << obj << ".sqlCursor():" << endl;
|
||
|
++indent;
|
||
|
if ( conn == "(default)" )
|
||
|
out << indent << "cursor = QSqlCursor(\"" << tab << "\")" << endl;
|
||
|
else
|
||
|
out << indent << "cursor = QSqlCursor(\"" << tab << "\",1,self." << conn << "Connection)" << endl;
|
||
|
out << indent << "self." << obj << ".setSqlCursor(cursor,1)" << endl;
|
||
|
out << indent << "self." << obj << ".refresh()" << endl;
|
||
|
out << indent << "self." << obj << ".first()" << endl;
|
||
|
--indent;
|
||
|
--indent;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
out << indent << objClass << ".polish(self)" << endl;
|
||
|
--indent;
|
||
|
}
|
||
|
|
||
|
out << endl;
|
||
|
out << endl;
|
||
|
out << indent << "def languageChange(self):" << endl;
|
||
|
uint old = indent.setIndent(0);
|
||
|
out << languageChangeBody << endl;
|
||
|
indent.setIndent(old);
|
||
|
|
||
|
// create stubs for additional slots if necessary
|
||
|
if ( !extraSlots.isEmpty() && writeFunctImpl ) {
|
||
|
QStringList::ConstIterator cit;
|
||
|
|
||
|
for ( cit = extraSlots.begin(); cit != extraSlots.end(); ++cit ) {
|
||
|
pySlot(cit);
|
||
|
|
||
|
bool createWarning = TRUE;
|
||
|
QString fname = Parser::cleanArgs( *cit );
|
||
|
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 )
|
||
|
{
|
||
|
++indent;
|
||
|
QString formatted_body = body.replace(QRegExp("\n"), QString("\n") + QString(indent));
|
||
|
out << formatted_body << endl;
|
||
|
--indent;
|
||
|
}
|
||
|
}
|
||
|
if ( createWarning ) {
|
||
|
out << endl;
|
||
|
++indent;
|
||
|
if ( *cit != "init()" && *cit != "destroy()" )
|
||
|
out << indent << "print \"" << nameOfClass << "." << (*cit) << ": Not implemented yet\"" << endl;
|
||
|
else
|
||
|
out << indent << "pass" << endl;
|
||
|
--indent;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
--indent;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*! 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" ) != "QDataTable" ) {
|
||
|
QString field = getDatabaseInfo( e, "field" );
|
||
|
if ( !field.isEmpty() ) {
|
||
|
if ( isWidgetInTable( e, connection, table ) )
|
||
|
out << indent << form << "Form.insert(self." << 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 Python slot definition.
|
||
|
|
||
|
void Uic::pySlot(QStringList::ConstIterator &it)
|
||
|
{
|
||
|
out << endl;
|
||
|
|
||
|
int astart = (*it).find('(');
|
||
|
out << indent << "def " << (*it).left(astart) << "(self";
|
||
|
|
||
|
// We don't reproduce the argument names (if any) because we would have to
|
||
|
// remove the types - too complicated for the moment, so we just count them
|
||
|
// and give them names based on their position.
|
||
|
|
||
|
QString args = (*it).mid(astart + 1,(*it).find(')') - astart - 1).stripWhiteSpace();
|
||
|
|
||
|
if (!args.isEmpty()) {
|
||
|
int nrargs = args.contains(',') + 1;
|
||
|
|
||
|
for (int i = 0; i < nrargs; ++i)
|
||
|
out << ",a" << i;
|
||
|
}
|
||
|
|
||
|
out << "):";
|
||
|
}
|