diff options
| author | Darrell Anderson <humanreadable@yahoo.com> | 2014-03-02 20:05:33 +0100 | 
|---|---|---|
| committer | Slávek Banko <slavek.banko@axis.cz> | 2014-03-02 20:05:33 +0100 | 
| commit | 722ce1efbac31c61b1d4b13f7e075c9f311e3e73 (patch) | |
| tree | db1b6b28566e5fe9accb4a688f7257673cecb080 /tdevdesigner/shared/ui2uib.cpp | |
| parent | afb74575caf7dd8ccb6c235b1c8d788e320c19da (diff) | |
| download | tdevelop-722ce1efbac31c61b1d4b13f7e075c9f311e3e73.tar.gz tdevelop-722ce1efbac31c61b1d4b13f7e075c9f311e3e73.zip | |
Finish renaming tdevelop components
Diffstat (limited to 'tdevdesigner/shared/ui2uib.cpp')
| -rw-r--r-- | tdevdesigner/shared/ui2uib.cpp | 893 | 
1 files changed, 893 insertions, 0 deletions
| diff --git a/tdevdesigner/shared/ui2uib.cpp b/tdevdesigner/shared/ui2uib.cpp new file mode 100644 index 00000000..5cff46e0 --- /dev/null +++ b/tdevdesigner/shared/ui2uib.cpp @@ -0,0 +1,893 @@ +/********************************************************************** +** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved. +** +** This file is part of TQt 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. +** +** Licensees holding valid TQt Enterprise Edition or TQt Professional Edition +** licenses may use this file in accordance with the TQt Commercial License +** Agreement provided with the Software. +** +** 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. +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +**   information about TQt Commercial License Agreements. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "ui2uib.h" +#include "uib.h" + +#include <domtool.h> + +#include <tqcolor.h> +#include <tqcursor.h> +#include <tqdatetime.h> +#include <tqdom.h> +#include <tqfile.h> +#include <tqfont.h> +#include <tqobject.h> +#include <tqrect.h> +#include <tqsizepolicy.h> + +/* +    The .uib file format is the binary counterpart of the .ui file +    format. It is generated by the ui2uib converter and understood by +    TQWidgetFactory; in a future version, it might also be understood +    by a uib2ui converter. Experiments show that .uib files are about +    2.5 times faster to load and 6 times smaller than .ui files. + +    The .uib format, unlike the .ui format, is internal to Trolltech +    and is not officially documented; it is assumed that anybody who +    needs to understand the file format can read the ui2uib and +    TQWidgetFactory source code, with some guidance. And here's some +    guidance. + +    A .uib file starts with a 32-bit magic number that allows +    TQWidgetFactory to determine the file type. The magic number is +    followed by '\n' (0x0a) and '\r' (0x0d), which ensure that the +    file wasn't corrupted during transfer between different +    platforms. For example, transferring a .ui file from Windows to +    Unix using FTP with type ASCII will produce a file with '\r\n\r' +    in place of '\n\r'. This is followed by the TQDataStream format +    version number used. + +    The rest of the file is made up of blocks, each of which starts +    with a block type (Block_XXX) and a block length. Block_Intro and +    Block_Widget are mandatory; the others are optional. +    TQWidgetFactory makes certain assumptions about the order of the +    blocks; for example, it expects Block_String before any other +    block that refers to a string and Block_Images before +    Block_Widget. The order generated by ui2uib is one of the orders +    that make sense. Just after the last block, a Block_End marker +    indicates the end of the file. + +    The division of .uib files into blocks corresponds grossly to the +    division of .ui files in top-level XML elements. Thus, +    Block_Widget corresponds to <widget> and Block_Toolbars to +    <toolbars>. The internal organization of each block also mimics +    the organization of the corresponding XML elements. + +    These are the major differences, all of which contribute to +    making .uib files more compact: + +    1.  The strings are gathered in Block_Strings, a string-table. +	When a string is needed later, it is referenced by a 32-bit +	index into that table. The UicStringTable class makes the +	whole process of inserting and looking up strings very +	simple. The advantage of this scheme is that if a string is +	used more than once, it is stored only once. Also, the +	string-table is preinitialized with very common strings, so +	that these need not be stored along with .uib files. + +    2.  TQObjects are referred to by index in a table rather than by +	name. The table itself is not stored in the .uib file; it is +	rather build dynamically by ui2uib and TQWidgetFactory as new +	objects are specified. In ui2uib, the table is represented by +	a UibIndexMap object; in TQWidgetFactory, a plain array of +	TQObject pointers suffices. + +    3.  The data is packed to take as little place as possible, +	without slowing down TQLayoutFactory too much. For example, an +	index into the string-table is a 32-bit integer, but in +	practice it is rarely above 65534, so only 16 bits are used +	for them; when an index above 65534 is met, the index is +	saved as 65535 followed by the 32-bit index, for a total of +	48 bits. + +    4.  The name of a signal or slot and its signature are saved +	separately. That way, if a signal 'foo(const TQString&)' is +	connected to a slot 'bar(const TQString&)', the string-table +	will only contain 'foo', 'bar', and '(const TQString&)', +	instead of the longer 'foo(const TQString&)' and 'bar(const +	TQString&)'. The signatures are normalized beforehand to +	ensure that trivial spacing problems don't result in multiple +	string-table entries. + +    5.  In a signal-to-slot connection, a sender, signal, receiver, +	or slot is not repeated if it's the same as for the previous +	connection. Bit flags indicate what is repeated and what is +	specified. + +    6.  Some of the information stored in a .ui file is useful only +	by uic, not to TQLayoutFactory. That information is, for now, +	not taken along in the .uib file. Likewise, needless +	TQLayoutWidget objects are not taken along. + +    The arbitrary constants related to the .uib file formats are +    defined in uib.h. Constants such as Block_Actions and +    Object_SubWidget are given values such as 'A' and 'W' to make +    .uib files easier to read in a hexadecimal editor. + +    The file format isn't designed to be extensible. Any extension +    that prevents an older version of TQLayoutWidget of reading the +    file correctly must have a different magic number. The plan is to +    use UibMagic + 1 for version 2, UibMagic + 2 for version 3, etc. +*/ + +static TQCString layoutForTag( const TQString& tag ) +{ +    if ( tag == "grid" ) { +	return TQGRIDLAYOUT_OBJECT_NAME_STRING; +    } else if ( tag == "hbox" ) { +	return TQHBOXLAYOUT_OBJECT_NAME_STRING; +    } else if ( tag == "vbox" ) { +	return TQVBOXLAYOUT_OBJECT_NAME_STRING; +    } else { +	return TQLAYOUT_OBJECT_NAME_STRING; +    } +} + +class UibHack : public TQObject +{ +public: +    static TQString normalize( const TQString& member ) { +	return TQString::fromUtf8( TQObject::normalizeSignalSlot(member.utf8()) ); +    } +}; + +class UibIndexMap +{ +public: +    UibIndexMap() : next( 0 ) { } + +    void insert( const TQString& name ) { setName( insert(), name ); } +    int insert() { return next++; } +    void setName( int no, const TQString& name ); + +    int find( const TQString& name, int deflt = -1 ) const; +    int count() const { return next; } + +private: +    TQMap<TQString, int> nameMap; +    TQMap<TQString, int> conflicts; +    int next; +}; + +void UibIndexMap::setName( int no, const TQString& name ) +{ +    if ( !name.isEmpty() ) { +	if ( *nameMap.insert(name, no, FALSE) != no ) +	    conflicts.insert( name, 0 ); +    } +} + +int UibIndexMap::find( const TQString& name, int deflt ) const +{ +    TQMap<TQString, int>::ConstIterator no = nameMap.find( name ); +    if ( no == nameMap.end() || conflicts.contains(name) ) { +	return deflt; +    } else { +	return *no; +    } +} + +static void packUInt16( TQDataStream& out, TQ_UINT16 n ) +{ +    if ( n < 255 ) { +	out << (TQ_UINT8) n; +    } else { +	out << (TQ_UINT8) 255; +	out << n; +    } +} + +static void packUInt32( TQDataStream& out, TQ_UINT32 n ) +{ +    if ( n < 65535 ) { +	out << (TQ_UINT16) n; +    } else { +	out << (TQ_UINT16) 65535; +	out << n; +    } +} + +static void packByteArray( TQDataStream& out, const TQByteArray& array ) +{ +    packUInt32( out, array.size() ); +    out.writeRawBytes( array.data(), array.size() ); +} + +static void packCString( UibStrTable& strings, TQDataStream& out, +			 const char *cstr ) +{ +    packUInt32( out, strings.insertCString(cstr) ); +} + +static void packString( UibStrTable& strings, TQDataStream& out, +			const TQString& str ) +{ +    packUInt32( out, strings.insertString(str) ); +} + +static void packStringSplit( UibStrTable& strings, TQDataStream& out, +			     const TQString& str, TQChar sep ) +{ +    int pos = str.find( sep ); +    if ( pos == -1 ) +	pos = str.length(); +    packString( strings, out, str.left(pos) ); +    packString( strings, out, str.mid(pos) ); +} + +static void packVariant( UibStrTable& strings, TQDataStream& out, +			 TQVariant value, TQString tag = "" ) +{ +    TQStringList::ConstIterator s; + +    TQ_UINT8 type = value.type(); +    if ( tag == "pixmap" ) { +	type = TQVariant::Pixmap; +    } else if ( tag == "image" ) { +	type = TQVariant::Image; +    } else if ( tag == "iconset" ) { +	type = TQVariant::IconSet; +    } +    out << type; + +    switch ( type ) { +    case TQVariant::String: +    case TQVariant::Pixmap: +    case TQVariant::Image: +    case TQVariant::IconSet: +	packString( strings, out, value.asString() ); +	break; +    case TQVariant::StringList: +	packUInt16( out, value.asStringList().count() ); +	s = value.asStringList().begin(); +	while ( s != value.asStringList().end() ) { +	    packString( strings, out, *s ); +	    ++s; +	} +	break; +    case TQVariant::Font: +	out << value.asFont(); +	break; +    case TQVariant::Rect: +	packUInt16( out, value.asRect().x() ); +	packUInt16( out, value.asRect().y() ); +	packUInt16( out, value.asRect().width() ); +	packUInt16( out, value.asRect().height() ); +	break; +    case TQVariant::Size: +	packUInt16( out, value.asSize().width() ); +	packUInt16( out, value.asSize().height() ); +	break; +    case TQVariant::Color: +	out << value.asColor(); +	break; +    case TQVariant::Point: +	packUInt16( out, value.asPoint().x() ); +	packUInt16( out, value.asPoint().y() ); +	break; +    case TQVariant::Int: +	packUInt32( out, value.asInt() ); +	break; +    case TQVariant::Bool: +	out << (TQ_UINT8) value.asBool(); +	break; +    case TQVariant::Double: +	out << value.asDouble(); +	break; +    case TQVariant::CString: +	packCString( strings, out, value.asCString() ); +	break; +    case TQVariant::Cursor: +	out << value.asCursor(); +	break; +    case TQVariant::Date: +	out << value.asDate(); +	break; +    case TQVariant::Time: +	out << value.asTime(); +	break; +    case TQVariant::DateTime: +	out << value.asDateTime(); +	break; +    default: +	out << value; +    } +} + +static void outputProperty( TQMap<int, TQStringList>& buddies, int objectNo, +			    UibStrTable& strings, TQDataStream& out, +			    TQDomElement elem ) +{ +    TQCString name = elem.attribute( "name" ).latin1(); +    TQDomElement f = elem.firstChild().toElement(); +    TQString tag = f.tagName(); +    TQString comment; +    TQVariant value; + +    if ( name == "resizeable" ) +	name = "resizable"; + +    if ( tag == "font" ) { +	TQString family; +	TQ_UINT16 pointSize = 65535; +	TQ_UINT8 fontFlags = 0; + +	TQDomElement g = f.firstChild().toElement(); +	while ( !g.isNull() ) { +	    TQString text = g.firstChild().toText().data(); +	    if ( g.tagName() == "family" ) { +		fontFlags |= Font_Family; +		family = text; +	    } else if ( g.tagName() == "pointsize" ) { +		fontFlags |= Font_PointSize; +		pointSize = (TQ_UINT16) text.toUInt(); +	    } else { +		if ( g.firstChild().toText().data().toInt() != 0 ) { +		    if ( g.tagName() == "bold" ) { +			fontFlags |= Font_Bold; +		    } else if ( g.tagName() == "italic" ) { +			fontFlags |= Font_Italic; +		    } else if ( g.tagName() == "underline" ) { +			fontFlags |= Font_Underline; +		    } else if ( g.tagName() == "strikeout" ) { +			fontFlags |= Font_StrikeOut; +		    } +		} +	    } +	    g = g.nextSibling().toElement(); +	} + +	out << (TQ_UINT8) Object_FontProperty; +	packCString( strings, out, name ); +	out << fontFlags; +	if ( fontFlags & Font_Family ) +	    packString( strings, out, family ); +	if ( fontFlags & Font_PointSize ) +	    packUInt16( out, pointSize ); +    } else if ( tag == "palette" ) { +	out << (TQ_UINT8) Object_PaletteProperty; +	packCString( strings, out, name ); + +	TQDomElement g = f.firstChild().toElement(); +	while ( !g.isNull() ) { +	    TQDomElement h = g.firstChild().toElement(); +	    while ( !h.isNull() ) { +		value = DomTool::elementToVariant( h, TQt::gray ); +		if ( h.tagName() == "color" ) { +		    out << (TQ_UINT8) Palette_Color; +		    out << value.asColor(); +		} else if ( h.tagName() == "pixmap" ) { +		    out << (TQ_UINT8) Palette_Pixmap; +		    packVariant( strings, out, value, "pixmap" ); +		} +		h = h.nextSibling().toElement(); +	    } + +	    if ( g.tagName() == "active" ) { +		out << (TQ_UINT8) Palette_Active; +	    } else if ( g.tagName() == "inactive" ) { +		out << (TQ_UINT8) Palette_Inactive; +	    } else { +		out << (TQ_UINT8) Palette_Disabled; +	    } +	    g = g.nextSibling().toElement(); +	} +	out << (TQ_UINT8) Palette_End; +    } else { +	value = DomTool::elementToVariant( f, value, comment ); +	if ( value.isValid() ) { +	    if ( name == "buddy" ) { +		buddies[objectNo] += value.asString(); +	    } else { +		if ( tag == "string" ) { +		    out << (TQ_UINT8) Object_TextProperty; +		    packCString( strings, out, name ); +		    packCString( strings, out, value.asString().utf8() ); +		    packCString( strings, out, comment.utf8() ); +		} else { +		    out << (TQ_UINT8) Object_VariantProperty; +		    packCString( strings, out, name ); +		    packVariant( strings, out, value, tag ); +		} +	    } +	} +    } +} + +static void outputGridCell( TQDataStream& out, TQDomElement elem ) +{ +    int column = elem.attribute( "column", "0" ).toInt(); +    int row = elem.attribute( "row", "0" ).toInt(); +    int colspan = elem.attribute( "colspan", "1" ).toInt(); +    int rowspan = elem.attribute( "rowspan", "1" ).toInt(); +    if ( colspan < 1 ) +	colspan = 1; +    if ( rowspan < 1 ) +	rowspan = 1; + +    if ( column != 0 || row != 0 || colspan != 1 || rowspan != 1 ) { +	out << (TQ_UINT8) Object_GridCell; +	packUInt16( out, column ); +	packUInt16( out, row ); +	packUInt16( out, colspan ); +	packUInt16( out, rowspan ); +    } +} + +static int outputObject( TQMap<int, TQStringList>& buddies, +			 UibIndexMap& objects, UibStrTable& strings, +			 TQDataStream& out, TQDomElement elem, +			 TQCString className = "" ); + +static void outputLayoutWidgetsSubLayout( TQMap<int, TQStringList>& buddies, +					  UibIndexMap& objects, +					  UibStrTable& strings, +					  TQDataStream& out, TQDomElement elem ) +{ +    int subLayoutNo = -1; +    TQCString name; +    TQDomElement nameElem; + +    TQDomElement f = elem.firstChild().toElement(); +    while ( !f.isNull() ) { +	TQString tag = f.tagName(); +	if ( tag == "grid" || tag == "hbox" || tag == "vbox" ) { +	    out << (TQ_UINT8) Object_SubLayout; +	    subLayoutNo = outputObject( buddies, objects, strings, out, f, +					layoutForTag(tag) ); +	} else if ( tag == "property" ) { +	    if ( f.attribute("name") == "name" ) { +		name = DomTool::elementToVariant( f, name ).asCString(); +		nameElem = f; +	    } +	} +	f = f.nextSibling().toElement(); +    } + +    if ( subLayoutNo != -1 ) { +	/* +	  Remove the sub-layout's Object_End marker, append the grid +	  cell and the correct name property, and put the Object_End +	  marker back. +	*/ +	out.device()->at( out.device()->at() - 1 ); +	outputGridCell( out, elem ); +	outputProperty( buddies, subLayoutNo, strings, out, nameElem ); +	out << (TQ_UINT8) Object_End; + +	objects.setName( subLayoutNo, name ); +    } +} + +static int outputObject( TQMap<int, TQStringList>& buddies, +			 UibIndexMap& objects, UibStrTable& strings, +			 TQDataStream& out, TQDomElement elem, +			 TQCString className ) +{ +    bool isTQObject = !className.isEmpty(); + +    if ( className == TQTOOLBAR_OBJECT_NAME_STRING ) +	out << (TQ_UINT8) elem.attribute( "dock", "0" ).toInt(); +    if ( className == TQWIDGET_OBJECT_NAME_STRING ) +	className = elem.attribute( "class", className ).latin1(); + +    int objectNo = -1; +    if ( isTQObject ) { +	packCString( strings, out, className ); +	objectNo = objects.insert(); +    } + +    outputGridCell( out, elem ); + +    // optimization: insert '&Foo' into string-table before 'Foo' +    if ( className == TQACTION_OBJECT_NAME_STRING || className == TQACTIONGROUP_OBJECT_NAME_STRING ) { +	TQVariant value = DomTool::readProperty( elem, "menuText", TQVariant() ); +	if ( value.asString().startsWith("&") ) +	    strings.insertString( value.asString() ); +    } + +    TQDomElement f = elem.firstChild().toElement(); +    while ( !f.isNull() ) { +	TQString tag = f.tagName(); +	if ( tag == "action" ) { +	    if ( elem.tagName() == "item" || elem.tagName() == "toolbar" ) { +		TQString actionName = f.attribute( "name" ); +		int no = objects.find( actionName ); +		if ( no != -1 ) { +		    out << (TQ_UINT8) Object_ActionRef; +		    packUInt16( out, no ); +		} +	    } else { +		out << (TQ_UINT8) Object_SubAction; +		outputObject( buddies, objects, strings, out, f, TQACTION_OBJECT_NAME_STRING ); +	    } +	} else if ( tag == "actiongroup" ) { +	    out << (TQ_UINT8) Object_SubAction; +	    outputObject( buddies, objects, strings, out, f, TQACTIONGROUP_OBJECT_NAME_STRING ); +	} else if ( tag == "attribute" ) { +	    out << (TQ_UINT8) Object_Attribute; +	    outputProperty( buddies, objectNo, strings, out, f ); +	} else if ( tag == "column" ) { +	    out << (TQ_UINT8) Object_Column; +	    outputObject( buddies, objects, strings, out, f ); +	} else if ( tag == "event" ) { +	    out << (TQ_UINT8) Object_Event; +	    packCString( strings, out, f.attribute("name").latin1() ); +	    packVariant( strings, out, +			 TQStringList::split(',', f.attribute("functions")) ); +	} else if ( tag == "grid" || tag == "hbox" || tag == "vbox" ) { +	    out << (TQ_UINT8) Object_SubLayout; +	    outputObject( buddies, objects, strings, out, f, +			  layoutForTag(tag) ); +	} else if ( tag == "item" ) { +	    if ( elem.tagName() == "menubar" ) { +		out << (TQ_UINT8) Object_MenuItem; +		packCString( strings, out, f.attribute("name").latin1() ); +		packCString( strings, out, f.attribute("text").utf8() ); +		outputObject( buddies, objects, strings, out, f ); +	    } else { +		out << (TQ_UINT8) Object_Item; +		outputObject( buddies, objects, strings, out, f ); +	    } +	} else if ( tag == "property" ) { +	    outputProperty( buddies, objectNo, strings, out, f ); +	} else if ( tag == "row" ) { +	    out << (TQ_UINT8) Object_Row; +	    outputObject( buddies, objects, strings, out, f ); +	} else if ( tag == "separator" ) { +	    out << (TQ_UINT8) Object_Separator; +	} else if ( tag == "spacer" ) { +	    out << (TQ_UINT8) Object_Spacer; +	    outputObject( buddies, objects, strings, out, f ); +	} else if ( tag == "widget" ) { +	    if ( f.attribute("class") == TQLAYOUTWIDGET_OBJECT_NAME_STRING && +		 elem.tagName() != "widget" ) { +		outputLayoutWidgetsSubLayout( buddies, objects, strings, out, +					      f ); +	    } else { +		out << (TQ_UINT8) Object_SubWidget; +		outputObject( buddies, objects, strings, out, f, TQWIDGET_OBJECT_NAME_STRING ); +	    } +	} +	f = f.nextSibling().toElement(); +    } +    out << (TQ_UINT8) Object_End; +    if ( isTQObject ) +	objects.setName( objectNo, +			 DomTool::readProperty(elem, "name", "").asString() ); +    return objectNo; +} + +static void outputBlock( TQDataStream& out, BlockTag tag, +			 const TQByteArray& data ) +{ +    if ( !data.isEmpty() ) { +	out << (TQ_UINT8) tag; +	packByteArray( out, data ); +    } +} + +void convertUiToUib( TQDomDocument& doc, TQDataStream& out ) +{ +    TQByteArray introBlock; +    TQByteArray actionsBlock; +    TQByteArray buddiesBlock; +    TQByteArray connectionsBlock; +    TQByteArray functionsBlock; +    TQByteArray imagesBlock; +    TQByteArray menubarBlock; +    TQByteArray slotsBlock; +    TQByteArray tabstopsBlock; +    TQByteArray toolbarsBlock; +    TQByteArray variablesBlock; +    TQByteArray widgetBlock; + +    TQDomElement actionsElem; +    TQDomElement connectionsElem; +    TQDomElement imagesElem; +    TQDomElement menubarElem; +    TQDomElement tabstopsElem; +    TQDomElement toolbarsElem; +    TQDomElement widgetElem; + +    TQMap<int, TQStringList> buddies; +    UibStrTable strings; +    UibIndexMap objects; +    int widgetNo = -1; +    TQCString className; +    TQ_INT16 defaultMargin = -32768; +    TQ_INT16 defaultSpacing = -32768; +    TQ_UINT8 introFlags = 0; + +    TQDomElement elem = doc.firstChild().toElement().firstChild().toElement(); +    while ( !elem.isNull() ) { +	TQString tag = elem.tagName(); + +	switch ( tag[0].latin1() ) { +	case 'a': +	    if ( tag == "actions" ) +		actionsElem = elem; +	    break; +	case 'c': +	    if ( tag == "class" ) { +		className = elem.firstChild().toText().data().latin1(); +	    } else if ( tag == "connections" ) { +		connectionsElem = elem; +	    } +	    break; +	case 'f': +	    if ( tag == "functions" ) { +		TQDataStream out2( functionsBlock, IO_WriteOnly ); +		TQDomElement f = elem.firstChild().toElement(); +		while ( !f.isNull() ) { +		    if ( f.tagName() == "function" ) { +			packStringSplit( strings, out2, +					 f.attribute("name").latin1(), '(' ); +			packString( strings, out2, +				    f.firstChild().toText().data() ); +		    } +		    f = f.nextSibling().toElement(); +		} +	    } +	    break; +	case 'i': +	    if ( tag == "images" ) { +		TQDataStream out2( imagesBlock, IO_WriteOnly ); +		TQDomElement f = elem.firstChild().toElement(); +		while ( !f.isNull() ) { +		    if ( f.tagName() == "image" ) { +			TQString name = f.attribute( "name" ); +			TQDomElement g = f.firstChild().toElement(); +			if ( g.tagName() == "data" ) { +			    TQString format = g.attribute( "format", "PNG" ); +			    TQString hex = g.firstChild().toText().data(); +			    int n = hex.length() / 2; +			    TQByteArray data( n ); +			    for ( int i = 0; i < n; i++ ) +				data[i] = (char) hex.mid( 2 * i, 2 ) +						    .toUInt( 0, 16 ); + +			    packString( strings, out2, name ); +			    packString( strings, out2, format ); +			    packUInt32( out2, g.attribute("length").toInt() ); +			    packByteArray( out2, data ); +			} +		    } +		    f = f.nextSibling().toElement(); +		} +	    } +	    break; +	case 'l': +	    if ( tag == "layoutdefaults" ) { +		TQString margin = elem.attribute( "margin" ); +		if ( !margin.isEmpty() ) +		    defaultMargin = margin.toInt(); +		TQString spacing = elem.attribute( "spacing" ); +		if ( !spacing.isEmpty() ) +		    defaultSpacing = spacing.toInt(); +	    } +	    break; +	case 'm': +	    if ( tag == "menubar" ) +		menubarElem = elem; +	    break; +	case 'p': +	    if ( tag == "pixmapinproject" ) +		introFlags |= Intro_Pixmapinproject; +	    break; +	case 's': +	    if ( tag == "slots" ) { +		TQDataStream out2( slotsBlock, IO_WriteOnly ); +		TQDomElement f = elem.firstChild().toElement(); +		while ( !f.isNull() ) { +		    if ( f.tagName() == "slot" ) { +			TQString language = f.attribute( "language", "C++" ); +			TQString slot = UibHack::normalize( +				f.firstChild().toText().data() ); +			packString( strings, out2, language ); +			packStringSplit( strings, out2, slot, '(' ); +		    } +		    f = f.nextSibling().toElement(); +		} +	    } +	    break; +	case 't': +	    if ( tag == "tabstops" ) { +		tabstopsElem = elem; +	    } else if ( tag == "toolbars" ) { +		toolbarsElem = elem; +	    } +	    break; +	case 'v': +	    if ( tag == "variable" ) { +		TQDataStream out2( variablesBlock, IO_WriteOnly | IO_Append ); +		packString( strings, out2, elem.firstChild().toText().data() ); +	    } else if ( tag == "variables" ) { +		TQDataStream out2( variablesBlock, IO_WriteOnly ); +		TQDomElement f = elem.firstChild().toElement(); +		while ( !f.isNull() ) { +		    if ( f.tagName() == "variable" ) +			packString( strings, out2, +				    f.firstChild().toText().data() ); +		    f = f.nextSibling().toElement(); +		} +	    } +	    break; +	case 'w': +	    if ( tag == "widget" ) +		widgetElem = elem; +	} +	elem = elem.nextSibling().toElement(); +    } + +    { +	TQDataStream out2( widgetBlock, IO_WriteOnly ); +	widgetNo = outputObject( buddies, objects, strings, out2, widgetElem, +				 TQWIDGET_OBJECT_NAME_STRING ); +    } + +    if ( !tabstopsElem.isNull() ) { +	TQDataStream out2( tabstopsBlock, IO_WriteOnly ); +	TQDomElement f = tabstopsElem.firstChild().toElement(); +	while ( !f.isNull() ) { +	    if ( f.tagName() == "tabstop" ) { +		TQString widgetName = f.firstChild().toText().data(); +		int no = objects.find( widgetName ); +		if ( no != -1 ) +		    packUInt16( out2, no ); +	    } +	    f = f.nextSibling().toElement(); +	} +    } + +    if ( !actionsElem.isNull() ) { +	TQDataStream out2( actionsBlock, IO_WriteOnly ); +	outputObject( buddies, objects, strings, out2, actionsElem ); +    } + +    if ( !menubarElem.isNull() ) { +	TQDataStream out2( menubarBlock, IO_WriteOnly ); +	outputObject( buddies, objects, strings, out2, menubarElem, +		      TQMENUBAR_OBJECT_NAME_STRING ); +    } + +    if ( !toolbarsElem.isNull() ) { +	TQDataStream out2( toolbarsBlock, IO_WriteOnly ); +	TQDomElement f = toolbarsElem.firstChild().toElement(); +	while ( !f.isNull() ) { +	    if ( f.tagName() == "toolbar" ) +		outputObject( buddies, objects, strings, out2, f, TQTOOLBAR_OBJECT_NAME_STRING ); +	    f = f.nextSibling().toElement(); +	} +    } + +    if ( !buddies.isEmpty() ) { +	TQDataStream out2( buddiesBlock, IO_WriteOnly ); +	TQMap<int, TQStringList>::ConstIterator a = buddies.begin(); +	while ( a != buddies.end() ) { +	    TQStringList::ConstIterator b = (*a).begin(); +	    while ( b != (*a).end() ) { +		int no = objects.find( *b ); +		if ( no != -1 ) { +		    packUInt16( out2, a.key() ); +		    packUInt16( out2, no ); +		} +		++b; +	    } +	    ++a; +	} +    } + +    if ( !connectionsElem.isNull() ) { +	TQString prevLanguage = "C++"; +	int prevSenderNo = 0; +	TQString prevSignal = "clicked()"; +	int prevReceiverNo = 0; +	TQString prevSlot = "accept()"; + +	TQDataStream out2( connectionsBlock, IO_WriteOnly ); +	TQDomElement f = connectionsElem.firstChild().toElement(); +	while ( !f.isNull() ) { +	    if ( f.tagName() == "connection" ) { +		TQMap<TQString, TQString> argMap; + +		TQDomElement g = f.firstChild().toElement(); +		while ( !g.isNull() ) { +		    argMap[g.tagName()] = g.firstChild().toText().data(); +		    g = g.nextSibling().toElement(); +		} + +		TQString language = f.attribute( "language", "C++" ); +		int senderNo = objects.find( argMap["sender"], widgetNo ); +		int receiverNo = objects.find( argMap["receiver"], widgetNo ); +		TQString signal = UibHack::normalize( argMap["signal"] ); +		TQString slot = UibHack::normalize( argMap["slot"] ); + +		TQ_UINT8 connectionFlags = 0; +		if ( language != prevLanguage ) +		    connectionFlags |= Connection_Language; +		if ( senderNo != prevSenderNo ) +		    connectionFlags |= Connection_Sender; +		if ( signal != prevSignal ) +		    connectionFlags |= Connection_Signal; +		if ( receiverNo != prevReceiverNo ) +		    connectionFlags |= Connection_Receiver; +		if ( slot != prevSlot ) +		    connectionFlags |= Connection_Slot; +		out2 << connectionFlags; + +		if ( connectionFlags & Connection_Language ) +		    packString( strings, out2, language ); +		if ( connectionFlags & Connection_Sender ) +		    packUInt16( out2, senderNo ); +		if ( connectionFlags & Connection_Signal ) +		    packStringSplit( strings, out2, signal, '(' ); +		if ( connectionFlags & Connection_Receiver ) +		    packUInt16( out2, receiverNo ); +		if ( connectionFlags & Connection_Slot ) +		    packStringSplit( strings, out2, slot, '(' ); + +		prevLanguage = language; +		prevSenderNo = senderNo; +		prevSignal = signal; +		prevReceiverNo = receiverNo; +		prevSlot = slot; +	    } else if ( f.tagName() == "slot" ) { +		// ### +	    } +	    f = f.nextSibling().toElement(); +	} +    } + +    { +	TQDataStream out2( introBlock, IO_WriteOnly ); +	out2 << introFlags; +	out2 << defaultMargin; +	out2 << defaultSpacing; +	packUInt16( out2, objects.count() ); +	packCString( strings, out2, className ); +    } + +    out << UibMagic; +    out << (TQ_UINT8) '\n'; +    out << (TQ_UINT8) '\r'; +    out << (TQ_UINT8) out.version(); +    outputBlock( out, Block_Strings, strings.block() ); +    outputBlock( out, Block_Intro, introBlock ); +    outputBlock( out, Block_Images, imagesBlock ); +    outputBlock( out, Block_Widget, widgetBlock ); +    outputBlock( out, Block_Slots, slotsBlock ); +    outputBlock( out, Block_Tabstops, tabstopsBlock ); +    outputBlock( out, Block_Actions, actionsBlock ); +    outputBlock( out, Block_Menubar, menubarBlock ); +    outputBlock( out, Block_Toolbars, toolbarsBlock ); +    outputBlock( out, Block_Variables, variablesBlock ); +    outputBlock( out, Block_Functions, functionsBlock ); +    outputBlock( out, Block_Buddies, buddiesBlock ); +    outputBlock( out, Block_Connections, connectionsBlock ); +    out << (TQ_UINT8) Block_End; +} | 
