diff options
Diffstat (limited to 'pyuic3/form.cpp')
-rw-r--r-- | pyuic3/form.cpp | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/pyuic3/form.cpp b/pyuic3/form.cpp new file mode 100644 index 0000000..aedb4ac --- /dev/null +++ b/pyuic3/form.cpp @@ -0,0 +1,938 @@ +/********************************************************************** +** 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 << "):"; +} |