// Copyright (c) 2000 - 2001 Phil Thompson <phil@river-bank.demon.co.uk>

/**********************************************************************
**   Copyright (C) 2000 Troll Tech AS.  All rights reserved.
**
**   This file is part of TQt GUI Designer.
**
**   This file may be distributed under the terms of the GNU General
**   Public License version 2 as published by the Free Software
**   Foundation and appearing in the file COPYING included in the
**   packaging of this file. If you did not get the file, send email
**   to info@trolltech.com
**
**   The file is provided AS IS with NO WARRANTY OF ANY KIND,
**   INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
**   A PARTICULAR PURPOSE.
**
**********************************************************************/

#include "uic.h"
#include <tqapplication.h>
#include <tqfile.h>
#include <tqfileinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <tqstringlist.h>
#include <tqstrlist.h>
#include <tqdatetime.h>
#include <widgetdatabase.h>
#include <domtool.h>
#include <globaldefs.h>
#include <tqregexp.h>
#include <zlib.h>

static TQString mkBool( bool b )
{
    return b? "1" : "0";
}

static TQString mkBool( const TQString& s )
{
    return mkBool( s == "true" || s == "1" );
}

static bool toBool( const TQString& s )
{
    return s == "true" || s.toInt() != 0;
}


// fixString is only used in conjunction with tr(). We need to write out the
// string in utf8 and make sure it's converted from utf8 when created.
static TQString fixString( const TQString &str )
{
    TQString s( str );
    s.replace( TQRegExp( "\\\\" ), "\\\\" );
    s.replace( TQRegExp( "\"" ), "\\\"" );
    s.replace( TQRegExp( "\n" ), "\\n\"\n\"" );
    s.replace( TQRegExp( "\r" ), "\\r" );

    bool onlyAscii = TRUE;
    unsigned int i;
    for ( i = 0; i < s.length(); i++ ) {
        if ( s.at(i).unicode() >= 0x80 ) {
            onlyAscii = FALSE;
            break;
        }
    }
    if ( onlyAscii )
        s = "\"" + s + "\"";
    else
        s = "TQString.fromUtf8(\"" + s + "\")";
    return s;
}

static TQString mkStdSet( const TQString& prop )
{
    return TQString( "set" ) + prop[0].upper() + prop.mid(1);
}


/*!
  \class Uic uic.h
  \brief User Interface Compiler

  The class Uic encapsulates the user interface compiler (uic).
 */

static TQString className;

Uic::Uic( TQTextStream &outStream, TQDomDocument doc, const TQString &trm )
    : out( outStream ), trmacro( trm )
{
    item_used = cg_used = pal_used = 0;

    initIndent();

    layouts << "hbox" << "vbox" << "grid";
    tags = layouts;
    tags << "widget";

    nameOfClass = getClassName( doc.firstChild().toElement() );

    TQDomElement firstWidget = doc.firstChild().firstChild().toElement();
    while ( firstWidget.tagName() != "widget" )
	firstWidget = firstWidget.nextSibling().toElement();

    if ( nameOfClass.isEmpty() )
	nameOfClass = getObjectName( firstWidget );

    // This is a hack.
    className = nameOfClass;

    createFormImpl( firstWidget );
}


/*! Extracts a class name from \a e
 */
TQString Uic::getClassName( const TQDomElement& e )
{
    TQDomElement n;
    TQString cn;
    for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName() == "class" ) {
	    TQString s = n.firstChild().toText().data();
	    int i;
	    while ( ( i = s.find(' ' )) != -1  )
		s[i] = '_';
	    cn = s;
	} else if ( n.tagName() == "pixmapfunction" ) {
	    pixmapLoaderFunction = n.firstChild().toText().data();
	}
    }
    return cn;
}

/*! Extracts an object name from \a e. It's stored in the 'name'
 property.
 */
TQString Uic::getObjectName( const TQDomElement& e )
{
    TQDomElement n;
    for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName() == "property" ) {
	    TQDomElement n2 = n.firstChild().toElement();
	    if ( n2.tagName() == "name" && n2.firstChild().toText().data() == "name" ) {
		return n2.nextSibling().toElement().firstChild().toText().data();
	    }
	}
    }
    return TQString::null;
}

/*! Extracts an layout name from \a e. It's stored in the 'name'
 property of the preceeding sibling (the first child of a TQLayoutWidget).
 */
TQString Uic::getLayoutName( const TQDomElement& e )
{
    TQDomElement p = e.parentNode().toElement();
    TQString tail = TQString::null;
 
    if (getClassName(p) != "TQLayoutWidget")
        tail = "Layout";
 
    TQDomElement n;
    for ( n = p.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
        if ( n.tagName() == "property" ) {
            TQDomElement n2 = n.firstChild().toElement();
            if ( n2.tagName() == "name" && n2.firstChild().toText().data() == "name" ) {
                return n2.nextSibling().toElement().firstChild().toText().data() + tail;
            }
        }
    }
    return e.tagName();
}

TQByteArray unzipXPM( TQString data, ulong& length )
{
    char *ba = new char[ 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;
    }
    if ( length <  data.length() * 5 )
	length = data.length() * 5;
    TQByteArray baunzip( length );
    ::uncompress( (uchar*) baunzip.data(), &length, (uchar*) ba, data.length()/2 );
    return baunzip;
}


/*!
  Creates an implementation ( cpp-file ) for the form given in \a e

  \sa createFormDecl(), createObjectImpl()
 */
void Uic::createFormImpl( const TQDomElement &e )
{
    TQStringList::Iterator it;
    TQDomElement n;
    TQDomNodeList nl;
    int i;
    TQString objClass = getClassName( e );
    if ( objClass.isEmpty() )
	return;
    TQString objName = getObjectName( e );

    // Handle custom widgets.
    for (n = e; !n.isNull(); n = n.nextSibling().toElement())
    {
	if (n.tagName() != "customwidgets")
		continue;

	TQDomElement n2 = n.firstChild().toElement();

	while (!n2.isNull())
	{
		if (n2.tagName() == "customwidget")
		{
			TQDomElement n3 = n2.firstChild().toElement();
			TQString cname, header;

			while (!n3.isNull())
			{
				if (n3.tagName() == "class")
					cname = n3.firstChild().toText().data();
				else if (n3.tagName() == "header")
					header = n3.firstChild().toText().data();

				n3 = n3.nextSibling().toElement();
			}

			if (cname.isEmpty())
				cname = "UnnamedCustomClass";

			int ext = header.findRev('.');

			if (ext >= 0)
				header.truncate(ext);

			if (header.isEmpty())
				header = cname.lower();

			out << "from " << header << " import " << cname << endl;
		}

		n2 = n2.nextSibling().toElement();
	}
    }

    // find out what images are required
    TQStringList requiredImages;
    nl = e.elementsByTagName( "pixmap" );
    for ( int j = 0; j < (int) nl.length(); j++ ) {
	requiredImages += nl.item(j).firstChild().toText().data();
    }
 
    TQStringList images;
    TQStringList xpmImages;
    if ( pixmapLoaderFunction.isEmpty() ) {
	// 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++ ) {
		    TQDomElement tmp = nl.item(i).firstChild().toElement();
		    TQString img = registerObject( tmp.firstChild().toText().data() );
		    if ( !requiredImages.contains( img ) )
			continue;
		    tmp = tmp.nextSibling().toElement();
		    TQString format = tmp.attribute("format", "PNG" );
		    TQString data = tmp.firstChild().toText().data();

		    out << endl;
		    out << endl;

		    if ( format == "XPM.GZ" ) {
			xpmImages += img;
			ulong length = tmp.attribute("length").toULong();
			TQByteArray baunzip = unzipXPM( data, length );
			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 << "]" << endl;
				break;
			    }

			    if (ch == '\"')
				ch = '\'';

			    out << ch;
			}
		    } else {
			images += img;
			out << indent << img << "_data = \\" << endl;
			pushIndent();
			out << indent << "'";
			int a ;
			for ( a = 0; a < (int) (data.length()/2)-1; a++ ) {
			    out << "\\x" << TQString(data[2*a]) << TQString(data[2*a+1]);
			    if ( a % 12 == 11 )
				out << "' \\" << endl << indent << "'";
			}
			out << "\\x" << TQString(data[2*a]) << TQString(data[2*a+1]) << "'" << endl;
			popIndent();
		    }
		}
	    }
	}
    }

    // register the object and unify its name
    objName = registerObject( objName );


    // constructor

    out << endl;
    out << endl;
    out << indent << "class " << nameOfClass << "(" << objClass << "):" << endl;
    pushIndent();

    if ( objClass == "TQDialog" || objClass == "TQWizard" ) {
	out << indent << "def __init__(self,parent = None,name = None,modal = 0,fl = 0):" << endl;
	pushIndent();
	out << indent << objClass << ".__init__(self,parent,name,modal,fl)" << endl;
    } else if ( objClass == "TQWidget" )  { // standard TQWidget
	out << indent << "def __init__(self,parent = None,name = None,fl = 0):" << endl;
	pushIndent();
	out << indent << objClass << ".__init__(self,parent,name,fl)" << endl;
    } else {
	out << indent << "def __init__(self,parent = None,name = None):" << endl;
	pushIndent();
	out << indent << objClass << ".__init__(self,parent,name)" << endl;
    }

    out << endl;

    // create pixmaps for all images
    if ( !images.isEmpty() ) {
	TQStringList::Iterator it;
	for ( it = images.begin(); it != images.end(); ++it ) {
	    out << indent << (*it) << " = TQPixmap()" << endl;
	    out << indent << (*it) << ".loadFromData(" << (*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) << " = TQPixmap(" << (*it) << "_data)" << endl;
	}

	out << endl;
    }


    // set the properties
    for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName() == "property" ) {
	    bool stdset = toBool( n.attribute( "stdset" ) );
	    TQDomElement n2 = n.firstChild().toElement();

	    if ( n2.tagName() == "name" ) {
		TQString prop = n2.firstChild().toText().data();
		TQString value = setObjectProperty( objClass, TQString::null, prop, n2.nextSibling().toElement(), stdset );

		if ( value.isEmpty() )
		    continue;

		if ( prop == "name" ) {
		    out << indent << "if name == None:" << endl;
		    pushIndent();
		}

		out << indent;

		if ( prop == "geometry" && n2.nextSibling().toElement().tagName() == "rect") {
		    TQDomElement n3 = n2.nextSibling().toElement().firstChild().toElement();
		    int w = 0, h = 0;

		    while ( !n3.isNull() ) {
			if ( n3.tagName() == "width" )
			    w = n3.firstChild().toText().data().toInt();
			else if ( n3.tagName() == "height" )
			    h = n3.firstChild().toText().data().toInt();
			n3 = n3.nextSibling().toElement();
		    }

		    out << "self.resize(" << w << "," << h << ")" << endl;
		} else {
		    if ( stdset )
			out << "self." << mkStdSet(prop) << "(" << value << ")" << endl;
		    else
			out << "self.setProperty('" << prop << "',TQVariant(" << value << "))" << endl;
		}

		if (prop == "name") {
		    popIndent();
		    out << endl;
		}
	    }
	}
    }


    // create all children, some forms have special requirements

    if ( objClass == "TQWizard" ) {
	for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	    if ( tags.contains( n.tagName()  ) ) {
		TQString page = createObjectImpl( n, objClass, "self" );
		TQString label = DomTool::readAttribute( n, "title", "" ).toString();
		out << indent << "self.addPage(" << page << ","<< trmacro << "(" << fixString( label ) << "))" << endl;
		TQVariant 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" );
	 }
     }

    // Get the list of any user defined slots.

    TQStringList userSlots;

    for ( n = e; !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName()  == "connections" ) {
	    for ( TQDomElement n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement() ) {
		if ( n2.tagName() == "slot" ) {
		    userSlots += n2.firstChild().toText().data();
		}
	    }
	}
    }

    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++ ) {
		TQString sender, receiver, signal, slot;
		for ( TQDomElement 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;

		sender = registeredName( sender );
		receiver = registeredName( receiver );

		 // translate formwindow name to "self"
		if ( sender == objName )
		    sender = "self";
		else
		    sender = "self." + sender;
		if ( receiver == objName )
		    receiver = "self";
		else
		    receiver = "self." + receiver;

		// Note that we never use the SLOT() macro in case we have
		// custom widgets implemented in Python.
		out << indent << "self.connect(" << sender
		    << ",SIGNAL('" << signal << "'),self."
		    << slot.left(slot.find('(')) << ")" << endl;
	    }
	} else if ( n.tagName()  == "tabstops" ) {
	    // setup tab order
	    out << endl;
	    TQString lastName;
	    TQDomElement n2 = n.firstChild().toElement();
	    while ( !n2.isNull() ) {
		if ( n2.tagName() == "tabstop" ) {
		    TQString 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 ( TQValueList<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;
	}

    }

    // end of constructor
    popIndent();

    // handle application font changes if required
    nl = e.elementsByTagName( "widget" );
    bool needEventHandler = FALSE;
    for ( i = 0; i < (int) nl.length(); i++ ) {
	if ( DomTool::hasProperty( nl.item(i).toElement() , "font" ) ) {
	    needEventHandler = TRUE;
	    break;
	}
    }
    if ( needEventHandler ) {
	out << endl;
	out << indent << "def event(self,ev):" << endl;
	pushIndent();
	out << indent << "ret = " << objClass << ".event(self,ev)" << endl;
	out << endl;
	out << indent << "if ev.type() == TQEvent.ApplicationFontChange:" << endl;
	pushIndent();

	for ( i = 0; i < (int) nl.length(); i++ ) {
	    n = nl.item(i).toElement();
	    if ( DomTool::hasProperty( n, "font" ) )
		createExclusiveProperty( n, "font" );
	}

	out << endl;
	popIndent();
	out << indent << "return ret" << endl;
	popIndent();
    }


    // Generate user defined slot hooks.

    for (it = userSlots.begin(); it != userSlots.end(); ++it) {
	int astart = (*it).find('(');

	out << endl;
	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.

	TQString 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 << "):" << endl;
	pushIndent();
	out << indent << "print '" << nameOfClass << "." << *it << ": not implemented yet'" << endl;
	popIndent();
    }

    popIndent();
}


/*!
  Creates an implementation for the object given in \a e.

  Traverses recursively over all children.

  Returns the name of the generated child object.

  \sa createObjectDecl()
 */
TQString Uic::createObjectImpl( const TQDomElement &e, const TQString& parentClass, const TQString& parent, const TQString& layout )
{

    TQDomElement n;
    TQString objClass, objName, fullObjName;

    if ( layouts.contains( e.tagName() ) )
	return createLayoutImpl( e, parentClass, parent, layout );

    objClass = getClassName( e );
    if ( objClass.isEmpty() )
	return objName;
    objName = getObjectName( e );

    TQString definedName = objName;
    bool isTmpObject = objName.isEmpty() || objClass == "TQLayoutWidget";
    if ( isTmpObject ) {
	if ( objClass[0] == 'Q' )
	    objName = objClass.mid(1);
	else
	    objName = objClass.lower();
    }

    bool isLine = objClass == "Line";
    if ( isLine )
	objClass = "TQFrame";

    out << endl;
    if ( objClass == "TQLayoutWidget" ) {
	if ( layout.isEmpty() ) {
            // register the object and unify its name
            objName = registerObject( objName );
	    out << indent << objName << " = TQWidget(" << parent << ",'" << definedName << "')" << endl;
	} else {
	    // the layout widget is not necessary, hide it by creating its child in the parent
	    TQString result;
	    for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
		if (tags.contains( n.tagName()  ) )
		    result = createObjectImpl( n, parentClass, parent, layout );
	    }
	    return result;
	}

	// Layouts don't go into the class instance dictionary.
	fullObjName = objName;
    } else {
        // register the object and unify its name
        objName = registerObject( objName );

	// Temporary objects don't go into the class instance dictionary.
	fullObjName = isTmpObject ? objName : "self." + objName;

	out << indent << fullObjName << " = " << createObjectInstance( objClass, parent, objName ) << endl;
    }

    lastItem = "None";
    // set the properties and insert items
    for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName() == "property" ) {
	    bool stdset = toBool( n.attribute( "stdset" ) );
	    TQDomElement n2 = n.firstChild().toElement();

	    if ( n2.tagName() == "name" ) {
		TQString prop = n2.firstChild().toText().data();
		TQString value = setObjectProperty( objClass, objName, prop, n2.nextSibling().toElement(), stdset );

		if ( value.isEmpty() )
		    continue;
		if ( prop == "name" )
		    continue;
		if ( prop == "buddy" && value[0] == '\'' && value[(int)value.length()-1] == '\'' ) {
		    buddies << Buddy( objName, value.mid(1, value.length() - 2 ) );
		    continue;
		}
		if ( isLine && prop == "orientation" ) {
		    prop = "frameStyle";
		    if ( value.right(10)  == "Horizontal" )
			value = "TQFrame.HLine | TQFrame.Sunken";
		    else
			value = "TQFrame.VLine | TQFrame.Sunken";
		}
		if ( prop == "buttonGroupId" ) {
		    if ( parentClass == "TQButtonGroup" )
			out << indent << parent << ".insert(" << fullObjName << "," << value << ")" << endl;
		    continue;
		}
		if ( prop == "geometry") {
			out << indent << fullObjName << ".setGeometry(" << value << ")" << endl;
		} else {
		    if ( stdset )
			out << indent << fullObjName << "." << mkStdSet(prop) << "(" << value << ")" << endl;
		    else
			out << indent << fullObjName << ".setProperty('" << prop << "',TQVariant(" << value << "))" << endl;
		}

	    }
	} else if ( n.tagName() == "item" ) {
	    if ( objClass.mid(1) == "ListBox" ) {
		TQString s = createListBoxItemImpl( n, fullObjName );
		if ( !s.isEmpty() )
		    out << indent << s << endl;
	    } else if ( objClass.mid(1) == "ComboBox" ) {
		TQString s = createListBoxItemImpl( n, fullObjName );
		if ( !s.isEmpty() )
		    out << indent << s << endl;
	    } else if ( objClass.mid(1) == "IconView" ) {
		TQString s = createIconViewItemImpl( n, fullObjName );
		if ( !s.isEmpty() )
		    out << indent << s << endl;
	    } else if ( objClass.mid(1) == "ListView" ) {
		TQString s = createListViewItemImpl( n, fullObjName, TQString::null );
		if ( !s.isEmpty() )
		    out << s << endl;
	    }
	} else if ( n.tagName() == "column" ) {
	    if ( objClass.mid(1) == "ListView" ) {
		TQString s = createListViewColumnImpl( n, fullObjName );
		if ( !s.isEmpty() )
		    out << s;
	    }
	}
    }

    // create all children, some widgets have special requirements

    if ( objClass == "TQTabWidget" ) {
	for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	    if ( tags.contains( n.tagName()  ) ) {
		TQString page = createObjectImpl( n, objClass, fullObjName );
		TQString label = DomTool::readAttribute( n, "title", "" ).toString();
		out << indent << fullObjName << ".insertTab(" << page << "," << trmacro << "(" << fixString( label ) << "))" << endl;
	    }
	}
     } else { // standard widgets
	for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	    if ( tags.contains( n.tagName()  ) )
		createObjectImpl( n, objClass, fullObjName );
	}
    }

    return fullObjName;
}

/*!
  Creates implementation of an listbox item tag.
*/

TQString Uic::createListBoxItemImpl( const TQDomElement &e, const TQString &parent )
{
    TQDomElement n = e.firstChild().toElement();
    TQString txt;
    TQString pix;
    while ( !n.isNull() ) {
	if ( n.tagName() == "property" ) {
	    TQDomElement n2 = n.firstChild().toElement();
	    if ( n2.tagName() == "name" ) {
		TQString attrib = n2.firstChild().toText().data();
		TQVariant v = DomTool::elementToVariant( n2.nextSibling().toElement(), TQVariant() );
		if ( attrib == "text" )
		    txt = v.toString();
		else if ( attrib == "pixmap" ) {
		    pix = v.toString();
		    if ( !pix.isEmpty() && !pixmapLoaderFunction.isEmpty() ) {
			pix.prepend( pixmapLoaderFunction + "(" );
			pix.append( ")" );
		    }
		}
	    }
	}
	n = n.nextSibling().toElement();
    }

    return pix.isEmpty() ?
      parent + ".insertItem(" + trmacro + "(" + fixString( txt ) + "))":
      parent + ".insertItem(" + pix + "," + trmacro + "(" + fixString( txt ) + "))";
}

/*!
  Creates implementation of an iconview item tag.
*/

TQString Uic::createIconViewItemImpl( const TQDomElement &e, const TQString &parent )
{
    TQDomElement n = e.firstChild().toElement();
    TQString txt;
    TQString pix;
    while ( !n.isNull() ) {
	if ( n.tagName() == "property" ) {
	    TQDomElement n2 = n.firstChild().toElement();
	    if ( n2.tagName() == "name" ) {
		TQString attrib = n2.firstChild().toText().data();
		TQVariant v = DomTool::elementToVariant( n2.nextSibling().toElement(), TQVariant() );
		if ( attrib == "text" )
		    txt = v.toString();
		else if ( attrib == "pixmap" ) {
		    pix = v.toString();
		    if ( !pix.isEmpty() && !pixmapLoaderFunction.isEmpty() ) {
			pix.prepend( pixmapLoaderFunction + "( " );
			pix.append( " )" );
		    }
		}
	    }
	}
	n = n.nextSibling().toElement();
    }

    if ( pix.isEmpty() )
	return "TQIconViewItem(" + parent + "," + trmacro + "(" + fixString( txt ) + "))";
    return "TQIconViewItem(" + parent + "," + trmacro + "(" + fixString( txt ) + ")," + pix + ")";

}

/*!
  Creates implementation of an listview item tag.
*/

TQString Uic::createListViewItemImpl( const TQDomElement &e, const TQString &parent,
				     const TQString &parentItem )
{
    TQString s;

    TQDomElement n = e.firstChild().toElement();

    bool hasChildren = e.elementsByTagName( "item" ).count() > 0;
    TQString item;

    if ( hasChildren ) {
	item = registerObject( "item" );
	s = indent + item + " = ";
    } else {
	item = "item";
	if ( item_used )
	    s = indent + item + " = ";
	else
	    s = indent + item + " = ";
	item_used = TRUE;
    }

    if ( !parentItem.isEmpty() )
	s += "TQListViewItem(" + parentItem + "," + lastItem + ")\n";
    else
	s += "TQListViewItem(" + parent + "," + lastItem + ")\n";

    TQStringList textes;
    TQStringList pixmaps;
    while ( !n.isNull() ) {
	if ( n.tagName() == "property" ) {
	    TQDomElement n2 = n.firstChild().toElement();
	    if ( n2.tagName() == "name" ) {
		TQString attrib = n2.firstChild().toText().data();
		TQVariant v = DomTool::elementToVariant( n2.nextSibling().toElement(), TQVariant() );
		if ( attrib == "text" )
		    textes << v.toString();
		else if ( attrib == "pixmap" ) {
		    TQString pix = v.toString();
		    if ( !pix.isEmpty() && !pixmapLoaderFunction.isEmpty() ) {
			pix.prepend( pixmapLoaderFunction + "( " );
			pix.append( " )" );
		    }
		    pixmaps << pix;
		}
	    }
	} else if ( n.tagName() == "item" ) {
	    s += indent + item + ".setOpen(1)\n";
	    s += createListViewItemImpl( n, parent, item );
	}
	n = n.nextSibling().toElement();
    }

    for ( int i = 0; i < (int)textes.count(); ++i ) {
	if ( !textes[ i ].isEmpty() )
	    s += indent + item + ".setText(" + TQString::number( i ) + "," + trmacro + "(" + fixString( textes[ i ] ) + "))\n";
	if ( !pixmaps[ i ].isEmpty() )
	    s += indent + item + ".setPixmap(" + TQString::number( i ) + "," + pixmaps[ i ] + ")\n";
    }

    lastItem = item;
    return s;
}

/*!
  Creates implementation of an listview column tag.
*/

TQString Uic::createListViewColumnImpl( const TQDomElement &e, const TQString &parent )
{
    TQDomElement n = e.firstChild().toElement();
    TQString txt;
    TQString pix;
    bool clickable = FALSE, resizeable = FALSE;
    while ( !n.isNull() ) {
	if ( n.tagName() == "property" ) {
	    TQDomElement n2 = n.firstChild().toElement();
	    if ( n2.tagName() == "name" ) {
		TQString attrib = n2.firstChild().toText().data();
		TQVariant v = DomTool::elementToVariant( n2.nextSibling().toElement(), TQVariant() );
		if ( attrib == "text" )
		    txt = v.toString();
		else if ( attrib == "pixmap" ) {
		    pix = v.toString();
		    if ( !pix.isEmpty() && !pixmapLoaderFunction.isEmpty() ) {
			pix.prepend( pixmapLoaderFunction + "( " );
			pix.append( " )" );
		    }
		} else if ( attrib == "clickable" )
		    clickable = v.toBool();
		else if ( attrib == "resizeable" )
		    resizeable = v.toBool();
	    }
	}
	n = n.nextSibling().toElement();
    }

    TQString s;
    s = indent + parent + ".addColumn(" + trmacro + "(" + fixString( txt ) + "))\n";
    if ( !pix.isEmpty() )
	s += indent + parent + ".header().setLabel(" + parent + ".header().count() - 1," + pix + "," + trmacro + "(" + fixString( txt ) + "))\n";
    if ( !clickable )
	s += indent + parent + ".header().setClickEnabled(0," + parent + ".header().count() - 1)\n";
    if ( !resizeable )
	s += indent + parent + ".header().setResizeEnabled(0," + parent + ".header().count() - 1)\n";

    return s;
}

/*!
  Creates the implementation of a layout tag. Called from createObjectImpl().
 */
TQString Uic::createLayoutImpl( const TQDomElement &e, const TQString& parentClass, const TQString& parent, const TQString& layout )
{
    TQDomElement n;
    TQString objClass, objName;
    objClass = e.tagName();

    TQString qlayout = "TQVBoxLayout";
    if ( objClass == "hbox" )
	qlayout = "TQHBoxLayout";
    else if ( objClass == "grid" )
	qlayout = "TQGridLayout";

    bool isGrid = e.tagName() == "grid" ;
    objName = registerObject( getLayoutName( e ) );
    layoutObjects += objName;
    int margin = DomTool::readProperty( e, "margin", BOXLAYOUT_DEFAULT_MARGIN ).toInt();
    int spacing = DomTool::readProperty( e, "spacing", BOXLAYOUT_DEFAULT_SPACING ).toInt();

    if ( (parentClass == "TQGroupBox" || parentClass == "TQButtonGroup") && layout.isEmpty() ) {
	// special case for group box
	out << indent << parent << ".setColumnLayout(0,TQt.Vertical)" << endl;
	out << indent << parent << ".layout().setSpacing(0)" << endl;
	out << indent << parent << ".layout().setMargin(0)" << endl;
	out << indent << objName << " = " << qlayout << "(" << parent << ".layout())" << endl;
	out << indent << objName << ".setAlignment(TQt.AlignTop)" << endl;
    } else {
	if ( layout.isEmpty() )
	    out << indent << objName << " = " << qlayout << "(" << parent << ")" << endl;
	else
	    out << indent << objName << " = " << qlayout << "()" << endl;
    }

    out << indent << objName << ".setSpacing(" << spacing << ")" << endl;
    out << indent << objName << ".setMargin(" << margin << ")" << endl;

    if ( !isGrid ) {
	for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	    if ( n.tagName() == "spacer" ) {
		TQString child = createSpacerImpl( n, parentClass, parent, objName );
		out << indent << objName << ".addItem(" << child << ")" << endl;
	    } else if ( tags.contains( n.tagName() ) ) {
		TQString child = createObjectImpl( n, parentClass, parent, objName );
		if ( isLayout( child ) )
		    out << indent << objName << ".addLayout(" << child << ")" << endl;
		else
		    out << indent << objName << ".addWidget(" << child << ")" << endl;
	    }
	}
    } else {
	for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	    TQDomElement ae = n;
	    int row = ae.attribute( "row" ).toInt();
	    int col = ae.attribute( "column" ).toInt();
	    int rowspan = ae.attribute( "rowspan" ).toInt();
	    int colspan = ae.attribute( "colspan" ).toInt();
	    if ( rowspan < 1 )
		rowspan = 1;
	    if ( colspan < 1 )
		colspan = 1;
	    if ( n.tagName() == "spacer" ) {
		TQString child = createSpacerImpl( n, parentClass, parent, objName );
		if ( rowspan * colspan != 1 )
		    out << indent << objName << ".addMultiCell(" << child << ","
			<< row << "," << row + rowspan - 1 << "," << col << ","
			<< col + colspan - 1 << ")" << endl;
		else
		    out << indent << objName << ".addItem(" << child << ","
			<< row << "," << col << ")" << endl;
	    } else if ( tags.contains( n.tagName() ) ) {
		TQString child = createObjectImpl( n, parentClass, parent, objName );
		out << endl;
		TQString o = "Widget";
		if ( isLayout( child ) )
		    o = "Layout";
		if ( rowspan * colspan != 1 )
		    out << indent << objName << ".addMultiCell" << o << "(" << child << ","
			<< row << "," << row + rowspan - 1 << "," << col << "," << col + colspan - 1 << ")" << endl;
		else
		    out << indent << objName << ".add" << o << "(" << child << ","
			<< row << "," << col << ")" << endl;
	    }
	}
    }

    return objName;
}



TQString Uic::createSpacerImpl( const TQDomElement &e, const TQString& /*parentClass*/, const TQString& /*parent*/, const TQString& /*layout*/)
{
    TQDomElement n;
    TQString objClass, objName;
    objClass = e.tagName();
    objName = registerObject( "spacer" );

    TQSize size = DomTool::readProperty( e, "sizeHint", TQSize(0,0) ).toSize();
    TQString sizeType = DomTool::readProperty( e, "sizeType", "Expanding" ).toString();
    bool isVspacer = DomTool::readProperty( e, "orientation", "Horizontal" ) == "Vertical";

    if ( sizeType != "Expanding" && sizeType != "MinimumExpanding" &&
         DomTool::hasProperty( e, "geometry" ) ) { // compatibility TQt 2.2
        TQRect geom = DomTool::readProperty( e, "geometry", TQRect(0,0,0,0) ).toRect();
        size = geom.size();
    }

    if ( isVspacer )
	out << indent << objName << " = TQSpacerItem("
	    << size.width() << "," << size.height()
	    << ",TQSizePolicy.Minimum,TQSizePolicy." << sizeType << ")" << endl;
    else
	out << indent << objName << " = TQSpacerItem("
	    << size.width() << "," << size.height()
	    << ",TQSizePolicy." << sizeType << ",TQSizePolicy.Minimum)" << endl;

    return objName;
}

/*!
  Creates a set-call for property \a exclusiveProp of the object
  given in \a e.

  If the object does not have this property, the function does nothing.

  Exclusive properties are used to generate the implementation of
  application font or palette change handlers in createFormImpl().

 */
void Uic::createExclusiveProperty( const TQDomElement & e, const TQString& exclusiveProp )
{
    TQDomElement n;
    TQString objClass = getClassName( e );
    if ( objClass.isEmpty() )
	return;
    TQString objName = getObjectName( e );
    if ( objClass.isEmpty() )
	return;
    for ( n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement() ) {
	if ( n.tagName() == "property" ) {
	    bool stdset = toBool( n.attribute( "stdset" ) );
	    TQDomElement n2 = n.firstChild().toElement();
	    if ( n2.tagName() == "name" ) {
		TQString prop = n2.firstChild().toText().data();
		if ( prop != exclusiveProp )
		    continue;
		TQString value = setObjectProperty( objClass, objName, prop, n2.nextSibling().toElement(), stdset );
		if ( value.isEmpty() )
		    continue;
		out << indent << objName << ".setProperty('" << prop << "',TQVariant(" << value << "))" << endl;
	    }
	}
    }

}


const char* const ColorRole[] = {
    "Foreground", "Button", "Light", "Midlight", "Dark", "Mid",
    "Text", "BrightText", "ButtonText", "Base", "Background", "Shadow",
    "Highlight", "HighlightedText", 0
};


/*!
  Attention: this function has to be in sync with Resource::setWidgetProperty(). If you change one, change both.
 */
TQString Uic::setObjectProperty( const TQString& objClass, const TQString& obj, const TQString &prop, const TQDomElement &e, bool stdset )
{
    TQString v;
    if ( e.tagName() == "rect" ) {
	TQDomElement n3 = e.firstChild().toElement();
	int x = 0, y = 0, w = 0, h = 0;
	while ( !n3.isNull() ) {
	    if ( n3.tagName() == "x" )
		x = n3.firstChild().toText().data().toInt();
	    else if ( n3.tagName() == "y" )
		y = n3.firstChild().toText().data().toInt();
	    else if ( n3.tagName() == "width" )
		w = n3.firstChild().toText().data().toInt();
	    else if ( n3.tagName() == "height" )
		h = n3.firstChild().toText().data().toInt();
	    n3 = n3.nextSibling().toElement();
	}
	v = "TQRect(%1,%2,%3,%4)";
	v = v.arg(x).arg(y).arg(w).arg(h);

    } else if ( e.tagName() == "point" ) {
	TQDomElement n3 = e.firstChild().toElement();
	int x = 0, y = 0;
	while ( !n3.isNull() ) {
	    if ( n3.tagName() == "x" )
		x = n3.firstChild().toText().data().toInt();
	    else if ( n3.tagName() == "y" )
		y = n3.firstChild().toText().data().toInt();
	    n3 = n3.nextSibling().toElement();
	}
	v = "TQPoint(%1,%2)";
	v = v.arg(x).arg(y);
    } else if ( e.tagName() == "size" ) {
	TQDomElement n3 = e.firstChild().toElement();
	int w = 0, h = 0;
	while ( !n3.isNull() ) {
	    if ( n3.tagName() == "width" )
		w = n3.firstChild().toText().data().toInt();
	    else if ( n3.tagName() == "height" )
		h = n3.firstChild().toText().data().toInt();
	    n3 = n3.nextSibling().toElement();
	}
	v = "TQSize(%1,%2)";
	v = v.arg(w).arg(h);
    } else if ( e.tagName() == "color" ) {
	TQDomElement n3 = e.firstChild().toElement();
	int r= 0, g = 0, b = 0;
	while ( !n3.isNull() ) {
	    if ( n3.tagName() == "red" )
		r = n3.firstChild().toText().data().toInt();
	    else if ( n3.tagName() == "green" )
		g = n3.firstChild().toText().data().toInt();
	    else if ( n3.tagName() == "blue" )
		b = n3.firstChild().toText().data().toInt();
	    n3 = n3.nextSibling().toElement();
	}
	v = "TQColor(%1,%2,%3)";
	v = v.arg(r).arg(g).arg(b);
    } else if ( e.tagName() == "font" ) {
	TQDomElement n3 = e.firstChild().toElement();
	TQString fontname = "f";
	if ( !obj.isEmpty() ) {
	    fontname = obj + "_font";
	    out << indent << fontname << " = TQFont(self." << obj << ".font())" << endl;
	} else {
	    out << indent << fontname << " = TQFont(self.font())" << endl;
	}
	while ( !n3.isNull() ) {
	    if ( n3.tagName() == "family" )
		out << indent << fontname << ".setFamily('" << n3.firstChild().toText().data() << "')" << endl;
	    else if ( n3.tagName() == "pointsize" )
		out << indent << fontname << ".setPointSize(" << n3.firstChild().toText().data() << ")" << endl;
	    else if ( n3.tagName() == "bold" )
		out << indent << fontname << ".setBold(" << mkBool( n3.firstChild().toText().data() ) << ")" << endl;
	    else if ( n3.tagName() == "italic" )
		out << indent << fontname << ".setItalic(" << mkBool( n3.firstChild().toText().data() ) << ")" << endl;
	    else if ( n3.tagName() == "underline" )
		out << indent << fontname << ".setUnderline(" << mkBool( n3.firstChild().toText().data() ) << ")" << endl;
	    else if ( n3.tagName() == "strikeout" )
		out << indent << fontname << ".setStrikeOut(" << mkBool( n3.firstChild().toText().data() ) << ")" << endl;
	    n3 = n3.nextSibling().toElement();
	}

	if ( prop == "font" ) {
	    if ( !obj.isEmpty() )
		out << indent << "self." << obj << ".setFont(" << fontname << ")" << endl;
	    else
		out << indent << "self.setFont(" << fontname << ")" << endl;
	} else {
	    v = fontname;
	}
    } else if ( e.tagName() == "string" ) {
	if ( prop == "toolTip" ) {
	    if ( !obj.isEmpty() )
		out << indent << "TQToolTip.add(self." << obj << "," + trmacro + "(" << fixString( e.firstChild().toText().data() ) << "))" << endl;
	    else
		out << indent << "TQToolTip.add(self," + trmacro + "(" << fixString( e.firstChild().toText().data() ) << "))" << endl;
	} else if ( prop == "whatsThis" ) {
	    if ( !obj.isEmpty() )
		out << indent << "TQWhatsThis.add(self." << obj << "," << trmacro << "(" << fixString( e.firstChild().toText().data() ) << "))" << endl;
	    else
		out << indent << "TQWhatsThis.add(self," << trmacro << "(" << fixString( e.firstChild().toText().data() ) << "))" << endl;
	} else {
	    v = trmacro + "(%1)";
	    v = v.arg( fixString( e.firstChild().toText().data() ) );
	}
    } else if ( e.tagName() == "cstring" ) {
	    v = "'%1'";
	    v = v.arg( e.firstChild().toText().data() );
    } else if ( e.tagName() == "number" ) {
	v = "%1";
	v = v.arg( e.firstChild().toText().data() );
    } else if ( e.tagName() == "bool" ) {
	if ( stdset )
	    v = "%1";
	else
	    v = "%1,0";
	v = v.arg( mkBool( e.firstChild().toText().data() ) );
    } else if ( e.tagName() == "pixmap" ) {
	v = e.firstChild().toText().data();
	if ( !pixmapLoaderFunction.isEmpty() ) {
	    v.prepend( pixmapLoaderFunction + "( " );
	    v.append( " )" );
	}
    } else if ( e.tagName() == "iconset" ) {
	v = "TQIconSet(%1)";
	v = v.arg( e.firstChild().toText().data() );
    } else if ( e.tagName() == "image" ) {
	v = e.firstChild().toText().data() + ".convertToImage()";
    } else if ( e.tagName() == "enum" ) {
	v = "%1.%2";
        TQString oc = objClass;
        TQString ev = e.firstChild().toText().data();
        if ( oc == "TQListView" && ev == "Manual" ) // #### workaround, rename TQListView::Manual of WithMode enum in 3.0
            oc = "TQScrollView";
        v = v.arg( oc ).arg( ev );
    } else if ( e.tagName() == "set" ) {
	TQString keys( e.firstChild().toText().data() );
	TQStringList lst = TQStringList::split( '|', keys );
	v = "";
	for ( TQStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
	    v += objClass + "." + *it;
	    if ( it != lst.fromLast() )
		v += " | ";
	}
    } else if ( e.tagName() == "sizepolicy" ) {
	TQDomElement n3 = e.firstChild().toElement();
	TQSizePolicy sp;
	while ( !n3.isNull() ) {
	    if ( n3.tagName() == "hsizetype" )
		sp.setHorData( (TQSizePolicy::SizeType)n3.firstChild().toText().data().toInt() );
	    else if ( n3.tagName() == "vsizetype" )
		sp.setVerData( (TQSizePolicy::SizeType)n3.firstChild().toText().data().toInt() );
	    n3 = n3.nextSibling().toElement();
	}
        TQString tmp;
        if ( !obj.isEmpty() )
            tmp = "self." + obj;
	else
	    tmp = "self";
	v = "TQSizePolicy(%1,%2," + tmp + ".sizePolicy().hasHeightForWidth())";
	v = v.arg( (int)sp.horData() ).arg( (int)sp.verData() );
    } else if ( e.tagName() == "palette" ) {
	TQPalette pal;
	bool no_pixmaps = e.elementsByTagName( "pixmap" ).count() == 0;
	TQDomElement n;
	if ( no_pixmaps ) {
	    n = e.firstChild().toElement();
	    while ( !n.isNull() ) {
		TQColorGroup cg;
		if ( n.tagName() == "active" ) {
		    cg = loadColorGroup( n );
		    pal.setActive( cg );
		} else if ( n.tagName() == "inactive" ) {
		    cg = loadColorGroup( n );
		    pal.setInactive( cg );
		} else if ( n.tagName() == "disabled" ) {
		    cg = loadColorGroup( n );
		    pal.setDisabled( cg );
		}
		n = n.nextSibling().toElement();
	    }
	}
	if ( no_pixmaps && pal == TQPalette( pal.active().button(), pal.active().background() ) ) {
	    v = "TQPalette(TQColor(%1,%2,%3),TQColor(%1,%2,%3))";
	    v = v.arg( pal.active().button().red() ).arg( pal.active().button().green() ).arg( pal.active().button().blue() );
	    v = v.arg( pal.active().background().red() ).arg( pal.active().background().green() ).arg( pal.active().background().blue() );
	} else {
	    TQString palette = "pal";
	    if ( !pal_used ) {
		out << indent << palette << " = TQPalette()" << endl;
		pal_used = TRUE;
	    }
	    TQString cg = "cg";
	    if ( !cg_used ) {
		out << indent << cg << " = TQColorGroup()" << endl;
		cg_used = TRUE;
	    }
	    n = e.firstChild().toElement();
	    while ( !n.isNull() && n.tagName() != "active")
		n = n.nextSibling().toElement();
	    createColorGroupImpl( cg, n );
	    out << indent << palette << ".setActive(" << cg << ")" << endl;

	    n = e.firstChild().toElement();
	    while ( !n.isNull() && n.tagName() != "inactive")
		n = n.nextSibling().toElement();
	    createColorGroupImpl( cg, n );
	    out << indent << palette << ".setInactive(" << cg << ")" << endl;

	    n = e.firstChild().toElement();
	    while ( !n.isNull() && n.tagName() != "disabled")
		n = n.nextSibling().toElement();
	    createColorGroupImpl( cg, n );
	    out << indent << palette << ".setDisabled(" << cg << ")" << endl;
	    v = palette;
	}
    } else if ( e.tagName() == "cursor" ) {
	v = "TQCursor(%1)";
	v = v.arg( e.firstChild().toText().data() );
    }
    return v;
}



/*!
  Creates a colorgroup with name \a name from the color group \a cg
 */
void Uic::createColorGroupImpl( const TQString& name, const TQDomElement& e )
{
    TQColorGroup cg;
    int r = -1;
    TQDomElement n = e.firstChild().toElement();
    TQString color;
    while ( !n.isNull() ) {
	if ( n.tagName() == "color" ) {
	    r++;
	    TQColor col = DomTool::readColor( n );
	    color = "TQColor(%1,%2,%3)";
	    color = color.arg( col.red() ).arg( col.green() ).arg( col.blue() );
	    if ( col == white )
		color = "TQt.white";
	    else if ( col == black )
	    color = "TQt.black";
	    if ( n.nextSibling().toElement().tagName() != "pixmap" ) {
		out << indent << name << ".setColor(TQColorGroup." << ColorRole[r] << "," << color << ")" << endl;
	    }
	} else if ( n.tagName() == "pixmap" ) {
	    TQString pixmap = n.firstChild().toText().data();
	    if ( !pixmapLoaderFunction.isEmpty() ) {
		pixmap.prepend( pixmapLoaderFunction + "(" );
		pixmap.append( ")" );
	    }
	    out << indent << name << ".setBrush(TQColorGroup."
		<< ColorRole[r] << ",TQBrush(" << color << "," << pixmap << "))" << endl;
	}
	n = n.nextSibling().toElement();
    }
}

/*!
  Auxiliary function to load a color group. The colorgroup must not
  contain pixmaps.
 */
TQColorGroup Uic::loadColorGroup( const TQDomElement &e )
{
    TQColorGroup cg;
    int r = -1;
    TQDomElement n = e.firstChild().toElement();
    TQColor col;
    while ( !n.isNull() ) {
	if ( n.tagName() == "color" ) {
	    r++;
	    cg.setColor( (TQColorGroup::ColorRole)r, (col = DomTool::readColor( n ) ) );
	}
	n = n.nextSibling().toElement();
    }
    return cg;
}



/*!
  Registers an object with name \a name.

  The returned name is a valid variable identifier, as similar to \a
  name as possible and guaranteed to be unique within the form.

  \sa registeredName(), isObjectRegistered()
 */
TQString Uic::registerObject( const TQString& name )
{
    if ( objectNames.isEmpty() ) {
	// some temporary variables we need
	objectNames += "img";
	objectNames += "item";
	objectNames += "cg";
	objectNames += "pal";
    }

    TQString result = name;
    int i;
    while ( ( i = result.find(' ' )) != -1  ) {
	result[i] = '_';
    }

    if ( objectNames.contains( result ) ) {
	int i = 2;
	while ( objectNames.contains( result + "_" + TQString::number(i) ) )
		i++;
	result += "_";
	result += TQString::number(i);
    }
    objectNames += result;
    objectMapper.insert( name, result );
    return result;
}

/*!
  Returns the registered name for the original name \a name
  or \a name if \a name  wasn't registered.

  \sa registerObject(), isObjectRegistered()
 */
TQString Uic::registeredName( const TQString& name )
{
    if ( !objectMapper.contains( name ) )
	return name;
    return objectMapper[name];
}

/*!
  Returns whether the object \a name was registered yet or not.
 */
bool Uic::isObjectRegistered( const TQString& name )
{
    return objectMapper.contains( name );
}


/*!
  Unifies the entries in stringlist \a list. Should really be a TQStringList feature.
 */
TQStringList Uic::unique( const TQStringList& list )
{
    TQStringList result;
    if (list.isEmpty() )
	return result;
    TQStringList l = list;
    l.sort();
    result += l.first();
    for ( TQStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
	if ( *it != result.last() )
	    result += *it;
    }
    return result;
}



/*!
  Creates an instance of class \a objClass, with parent \a parent and name \a objName
 */
TQString Uic::createObjectInstance( const TQString& objClass, const TQString& parent, const TQString& objName )
{

    if ( objClass.mid(1) == "ComboBox" ) {
	return objClass + "(0," + parent + ",'" + objName + "')";
    }
    return objClass + "(" + parent + ",'" + objName + "')";
}

bool Uic::isLayout( const TQString& name ) const
{
    return layoutObjects.contains( name );
}


#if defined(BLACKADDER)
#include "ba.h"

int BA::compilePython(const TQString &fileName,const TQString &outputFile,
		      const TQString &trmacro,bool execCode)
{
#else
int main( int argc, char * argv[] )
{
    const char *error = 0;
    TQString fileName;
    TQString outputFile;
    TQString trmacro;
    bool execCode = FALSE;

    for ( int n = 1; n < argc && error == 0; n++ ) {
	TQCString arg = argv[n];
	if ( arg[0] == '-' ) {			// option
	    TQCString opt = &arg[1];
	    if ( opt[0] == 'o' ) {		// output redirection
		if ( opt[1] == '\0' ) {
		    if ( !(n < argc-1) ) {
			error = "Missing output-file name";
			break;
		    }
		    outputFile = argv[++n];
		} else
		    outputFile = &opt[1];
	    } else if ( opt == "tr" ) {
		if ( opt == "tr" || opt[1] == '\0' ) {
		    if ( !(n < argc-1) ) {
			error = "Missing tr macro.";
			break;
		    }
		    trmacro = argv[++n];
		} else {
		    trmacro = &opt[1];
		}
	    } else if ( opt == "x" ) {
		execCode = TRUE;
	    }
	} else {
	    if (!fileName.isEmpty())		// can handle only one file
		error	 = "Too many input files specified";
	    else
		fileName = argv[n];
	}
    }

    if ( argc < 2 || error || fileName.isEmpty() ) {
	fprintf( stderr, "PyTQt user interface compiler\n" );
	if ( error )
	    fprintf( stderr, "pyuic: %s\n", error );

	fprintf( stderr, "Usage: %s [options] <uifile>\n"
		 "\nGenerate PyTQt implementation:\n"
		 "   %s [options] <uifile>\n"
		 "Options:\n"
		 "\t-o file 	Write output to file rather than stdout\n"
		 "\t-tr func	Use func(...) rather than tr(...) for i18n\n"
		 "\t-x		Generate extra code to test the class\n"
		 , argv[0], argv[0]);
	exit( 1 );
    }
#endif

    TQFile file( fileName );
    if ( !file.open( IO_ReadOnly ) )
	tqFatal( "pyuic: Could not open file '%s' ", (const char *)fileName );

    TQFile fileOut;
    if (!outputFile.isEmpty()) {
	fileOut.setName( outputFile );
	if (!fileOut.open( IO_WriteOnly ) )
	    tqFatal( "pyuic: Could not open output file '%s'", (const char *)outputFile );
    } else {
	fileOut.open( IO_WriteOnly, stdout );
    }
    TQTextStream out( &fileOut );
    out.setEncoding( TQTextStream::UnicodeUTF8 );

    TQDomDocument doc;
    if ( !doc.setContent( &file ) )
	tqFatal( "pyuic: Failed to parse %s\n", (const char *)fileName );

    out << "# Form implementation generated from reading ui file '" << fileName << "'" << endl;
    out << "#" << endl;
    out << "# Created: " << TQDateTime::currentDateTime().toString() << endl;
    out << "#      by: The Python User Interface Compiler (pyuic) " << PYTQT_VERSION << endl;
    out << "#" << endl;
    out << "# WARNING! All changes made in this file will be lost!" << endl;
    out << endl;
    out << endl;

    if (execCode)
	out << "import sys" << endl;

    out << "from python_tqt.qt import *" << endl;

    Uic( out, doc, trmacro.isEmpty() ? TQString("self.tr") : trmacro );

    if (execCode) {
	out << endl;
	out << endl;
	out << "if __name__ == '__main__':" << endl;
	out << "    a = TQApplication(sys.argv)" << endl;
	out << "    TQObject.connect(a,SIGNAL('lastWindowClosed()'),a,SLOT('quit()'))" << endl;
	out << "    w = " << className << "()" << endl;
	out << "    a.setMainWidget(w)" << endl;
	out << "    w.show()" << endl;
	out << "    a.exec_loop()" << endl;
    }

    return 0;
}
