source: trunk/tools/designer/shared/ui2uib.cpp@ 10

Last change on this file since 10 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 28.0 KB
Line 
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3**
4** This file is part of Qt Designer.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
12** licenses may use this file in accordance with the Qt Commercial License
13** Agreement provided with the Software.
14**
15** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17**
18** See http://www.trolltech.com/gpl/ for GPL licensing information.
19** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
20** information about Qt Commercial License Agreements.
21**
22** Contact info@trolltech.com if any conditions of this licensing are
23** not clear to you.
24**
25**********************************************************************/
26
27#include "ui2uib.h"
28#include "uib.h"
29
30#include <domtool.h>
31
32#include <qcolor.h>
33#include <qcursor.h>
34#include <qdatetime.h>
35#include <qdom.h>
36#include <qfile.h>
37#include <qfont.h>
38#include <qobject.h>
39#include <qrect.h>
40#include <qsizepolicy.h>
41
42/*
43 The .uib file format is the binary counterpart of the .ui file
44 format. It is generated by the ui2uib converter and understood by
45 QWidgetFactory; in a future version, it might also be understood
46 by a uib2ui converter. Experiments show that .uib files are about
47 2.5 times faster to load and 6 times smaller than .ui files.
48
49 The .uib format, unlike the .ui format, is internal to Trolltech
50 and is not officially documented; it is assumed that anybody who
51 needs to understand the file format can read the ui2uib and
52 QWidgetFactory source code, with some guidance. And here's some
53 guidance.
54
55 A .uib file starts with a 32-bit magic number that allows
56 QWidgetFactory to determine the file type. The magic number is
57 followed by '\n' (0x0a) and '\r' (0x0d), which ensure that the
58 file wasn't corrupted during transfer between different
59 platforms. For example, transferring a .ui file from Windows to
60 Unix using FTP with type ASCII will produce a file with '\r\n\r'
61 in place of '\n\r'. This is followed by the QDataStream format
62 version number used.
63
64 The rest of the file is made up of blocks, each of which starts
65 with a block type (Block_XXX) and a block length. Block_Intro and
66 Block_Widget are mandatory; the others are optional.
67 QWidgetFactory makes certain assumptions about the order of the
68 blocks; for example, it expects Block_String before any other
69 block that refers to a string and Block_Images before
70 Block_Widget. The order generated by ui2uib is one of the orders
71 that make sense. Just after the last block, a Block_End marker
72 indicates the end of the file.
73
74 The division of .uib files into blocks corresponds grossly to the
75 division of .ui files in top-level XML elements. Thus,
76 Block_Widget corresponds to <widget> and Block_Toolbars to
77 <toolbars>. The internal organization of each block also mimics
78 the organization of the corresponding XML elements.
79
80 These are the major differences, all of which contribute to
81 making .uib files more compact:
82
83 1. The strings are gathered in Block_Strings, a string-table.
84 When a string is needed later, it is referenced by a 32-bit
85 index into that table. The UicStringTable class makes the
86 whole process of inserting and looking up strings very
87 simple. The advantage of this scheme is that if a string is
88 used more than once, it is stored only once. Also, the
89 string-table is preinitialized with very common strings, so
90 that these need not be stored along with .uib files.
91
92 2. QObjects are referred to by index in a table rather than by
93 name. The table itself is not stored in the .uib file; it is
94 rather build dynamically by ui2uib and QWidgetFactory as new
95 objects are specified. In ui2uib, the table is represented by
96 a UibIndexMap object; in QWidgetFactory, a plain array of
97 QObject pointers suffices.
98
99 3. The data is packed to take as little place as possible,
100 without slowing down QLayoutFactory too much. For example, an
101 index into the string-table is a 32-bit integer, but in
102 practice it is rarely above 65534, so only 16 bits are used
103 for them; when an index above 65534 is met, the index is
104 saved as 65535 followed by the 32-bit index, for a total of
105 48 bits.
106
107 4. The name of a signal or slot and its signature are saved
108 separately. That way, if a signal 'foo(const QString&)' is
109 connected to a slot 'bar(const QString&)', the string-table
110 will only contain 'foo', 'bar', and '(const QString&)',
111 instead of the longer 'foo(const QString&)' and 'bar(const
112 QString&)'. The signatures are normalized beforehand to
113 ensure that trivial spacing problems don't result in multiple
114 string-table entries.
115
116 5. In a signal-to-slot connection, a sender, signal, receiver,
117 or slot is not repeated if it's the same as for the previous
118 connection. Bit flags indicate what is repeated and what is
119 specified.
120
121 6. Some of the information stored in a .ui file is useful only
122 by uic, not to QLayoutFactory. That information is, for now,
123 not taken along in the .uib file. Likewise, needless
124 QLayoutWidget objects are not taken along.
125
126 The arbitrary constants related to the .uib file formats are
127 defined in uib.h. Constants such as Block_Actions and
128 Object_SubWidget are given values such as 'A' and 'W' to make
129 .uib files easier to read in a hexadecimal editor.
130
131 The file format isn't designed to be extensible. Any extension
132 that prevents an older version of QLayoutWidget of reading the
133 file correctly must have a different magic number. The plan is to
134 use UibMagic + 1 for version 2, UibMagic + 2 for version 3, etc.
135*/
136
137static QCString layoutForTag( const QString& tag )
138{
139 if ( tag == "grid" ) {
140 return "QGridLayout";
141 } else if ( tag == "hbox" ) {
142 return "QHBoxLayout";
143 } else if ( tag == "vbox" ) {
144 return "QVBoxLayout";
145 } else {
146 return "QLayout";
147 }
148}
149
150class UibHack : public QObject
151{
152public:
153 static QString normalize( const QString& member ) {
154 return QString::fromUtf8( QObject::normalizeSignalSlot(member.utf8()) );
155 }
156};
157
158class UibIndexMap
159{
160public:
161 UibIndexMap() : next( 0 ) { }
162
163 void insert( const QString& name ) { setName( insert(), name ); }
164 int insert() { return next++; }
165 void setName( int no, const QString& name );
166
167 int find( const QString& name, int deflt = -1 ) const;
168 int count() const { return next; }
169
170private:
171 QMap<QString, int> nameMap;
172 QMap<QString, int> conflicts;
173 int next;
174};
175
176void UibIndexMap::setName( int no, const QString& name )
177{
178 if ( !name.isEmpty() ) {
179 if ( *nameMap.insert(name, no, FALSE) != no )
180 conflicts.insert( name, 0 );
181 }
182}
183
184int UibIndexMap::find( const QString& name, int deflt ) const
185{
186 QMap<QString, int>::ConstIterator no = nameMap.find( name );
187 if ( no == nameMap.end() || conflicts.contains(name) ) {
188 return deflt;
189 } else {
190 return *no;
191 }
192}
193
194static void packUInt16( QDataStream& out, Q_UINT16 n )
195{
196 if ( n < 255 ) {
197 out << (Q_UINT8) n;
198 } else {
199 out << (Q_UINT8) 255;
200 out << n;
201 }
202}
203
204static void packUInt32( QDataStream& out, Q_UINT32 n )
205{
206 if ( n < 65535 ) {
207 out << (Q_UINT16) n;
208 } else {
209 out << (Q_UINT16) 65535;
210 out << n;
211 }
212}
213
214static void packByteArray( QDataStream& out, const QByteArray& array )
215{
216 packUInt32( out, array.size() );
217 out.writeRawBytes( array.data(), array.size() );
218}
219
220static void packCString( UibStrTable& strings, QDataStream& out,
221 const char *cstr )
222{
223 packUInt32( out, strings.insertCString(cstr) );
224}
225
226static void packString( UibStrTable& strings, QDataStream& out,
227 const QString& str )
228{
229 packUInt32( out, strings.insertString(str) );
230}
231
232static void packStringSplit( UibStrTable& strings, QDataStream& out,
233 const QString& str, QChar sep )
234{
235 int pos = str.find( sep );
236 if ( pos == -1 )
237 pos = str.length();
238 packString( strings, out, str.left(pos) );
239 packString( strings, out, str.mid(pos) );
240}
241
242static void packVariant( UibStrTable& strings, QDataStream& out,
243 QVariant value, QString tag = "" )
244{
245 QStringList::ConstIterator s;
246
247 Q_UINT8 type = value.type();
248 if ( tag == "pixmap" ) {
249 type = QVariant::Pixmap;
250 } else if ( tag == "image" ) {
251 type = QVariant::Image;
252 } else if ( tag == "iconset" ) {
253 type = QVariant::IconSet;
254 }
255 out << type;
256
257 switch ( type ) {
258 case QVariant::String:
259 case QVariant::Pixmap:
260 case QVariant::Image:
261 case QVariant::IconSet:
262 packString( strings, out, value.asString() );
263 break;
264 case QVariant::StringList:
265 packUInt16( out, value.asStringList().count() );
266 s = value.asStringList().begin();
267 while ( s != value.asStringList().end() ) {
268 packString( strings, out, *s );
269 ++s;
270 }
271 break;
272 case QVariant::Font:
273 out << value.asFont();
274 break;
275 case QVariant::Rect:
276 packUInt16( out, value.asRect().x() );
277 packUInt16( out, value.asRect().y() );
278 packUInt16( out, value.asRect().width() );
279 packUInt16( out, value.asRect().height() );
280 break;
281 case QVariant::Size:
282 packUInt16( out, value.asSize().width() );
283 packUInt16( out, value.asSize().height() );
284 break;
285 case QVariant::Color:
286 out << value.asColor();
287 break;
288 case QVariant::Point:
289 packUInt16( out, value.asPoint().x() );
290 packUInt16( out, value.asPoint().y() );
291 break;
292 case QVariant::Int:
293 packUInt32( out, value.asInt() );
294 break;
295 case QVariant::Bool:
296 out << (Q_UINT8) value.asBool();
297 break;
298 case QVariant::Double:
299 out << value.asDouble();
300 break;
301 case QVariant::CString:
302 packCString( strings, out, value.asCString() );
303 break;
304 case QVariant::Cursor:
305 out << value.asCursor();
306 break;
307 case QVariant::Date:
308 out << value.asDate();
309 break;
310 case QVariant::Time:
311 out << value.asTime();
312 break;
313 case QVariant::DateTime:
314 out << value.asDateTime();
315 break;
316 default:
317 out << value;
318 }
319}
320
321static void outputProperty( QMap<int, QStringList>& buddies, int objectNo,
322 UibStrTable& strings, QDataStream& out,
323 QDomElement elem )
324{
325 QCString name = elem.attribute( "name" ).latin1();
326 QDomElement f = elem.firstChild().toElement();
327 QString tag = f.tagName();
328 QString comment;
329 QVariant value;
330
331 if ( name == "resizeable" )
332 name = "resizable";
333
334 if ( tag == "font" ) {
335 QString family;
336 Q_UINT16 pointSize = 65535;
337 Q_UINT8 fontFlags = 0;
338
339 QDomElement g = f.firstChild().toElement();
340 while ( !g.isNull() ) {
341 QString text = g.firstChild().toText().data();
342 if ( g.tagName() == "family" ) {
343 fontFlags |= Font_Family;
344 family = text;
345 } else if ( g.tagName() == "pointsize" ) {
346 fontFlags |= Font_PointSize;
347 pointSize = (Q_UINT16) text.toUInt();
348 } else {
349 if ( g.firstChild().toText().data().toInt() != 0 ) {
350 if ( g.tagName() == "bold" ) {
351 fontFlags |= Font_Bold;
352 } else if ( g.tagName() == "italic" ) {
353 fontFlags |= Font_Italic;
354 } else if ( g.tagName() == "underline" ) {
355 fontFlags |= Font_Underline;
356 } else if ( g.tagName() == "strikeout" ) {
357 fontFlags |= Font_StrikeOut;
358 }
359 }
360 }
361 g = g.nextSibling().toElement();
362 }
363
364 out << (Q_UINT8) Object_FontProperty;
365 packCString( strings, out, name );
366 out << fontFlags;
367 if ( fontFlags & Font_Family )
368 packString( strings, out, family );
369 if ( fontFlags & Font_PointSize )
370 packUInt16( out, pointSize );
371 } else if ( tag == "palette" ) {
372 out << (Q_UINT8) Object_PaletteProperty;
373 packCString( strings, out, name );
374
375 QDomElement g = f.firstChild().toElement();
376 while ( !g.isNull() ) {
377 QDomElement h = g.firstChild().toElement();
378 while ( !h.isNull() ) {
379 value = DomTool::elementToVariant( h, Qt::gray );
380 if ( h.tagName() == "color" ) {
381 out << (Q_UINT8) Palette_Color;
382 out << value.asColor();
383 } else if ( h.tagName() == "pixmap" ) {
384 out << (Q_UINT8) Palette_Pixmap;
385 packVariant( strings, out, value, "pixmap" );
386 }
387 h = h.nextSibling().toElement();
388 }
389
390 if ( g.tagName() == "active" ) {
391 out << (Q_UINT8) Palette_Active;
392 } else if ( g.tagName() == "inactive" ) {
393 out << (Q_UINT8) Palette_Inactive;
394 } else {
395 out << (Q_UINT8) Palette_Disabled;
396 }
397 g = g.nextSibling().toElement();
398 }
399 out << (Q_UINT8) Palette_End;
400 } else {
401 value = DomTool::elementToVariant( f, value, comment );
402 if ( value.isValid() ) {
403 if ( name == "buddy" ) {
404 buddies[objectNo] += value.asString();
405 } else {
406 if ( tag == "string" ) {
407 out << (Q_UINT8) Object_TextProperty;
408 packCString( strings, out, name );
409 packCString( strings, out, value.asString().utf8() );
410 packCString( strings, out, comment.utf8() );
411 } else {
412 out << (Q_UINT8) Object_VariantProperty;
413 packCString( strings, out, name );
414 packVariant( strings, out, value, tag );
415 }
416 }
417 }
418 }
419}
420
421static void outputGridCell( QDataStream& out, QDomElement elem )
422{
423 int column = elem.attribute( "column", "0" ).toInt();
424 int row = elem.attribute( "row", "0" ).toInt();
425 int colspan = elem.attribute( "colspan", "1" ).toInt();
426 int rowspan = elem.attribute( "rowspan", "1" ).toInt();
427 if ( colspan < 1 )
428 colspan = 1;
429 if ( rowspan < 1 )
430 rowspan = 1;
431
432 if ( column != 0 || row != 0 || colspan != 1 || rowspan != 1 ) {
433 out << (Q_UINT8) Object_GridCell;
434 packUInt16( out, column );
435 packUInt16( out, row );
436 packUInt16( out, colspan );
437 packUInt16( out, rowspan );
438 }
439}
440
441static int outputObject( QMap<int, QStringList>& buddies,
442 UibIndexMap& objects, UibStrTable& strings,
443 QDataStream& out, QDomElement elem,
444 QCString className = "" );
445
446static void outputLayoutWidgetsSubLayout( QMap<int, QStringList>& buddies,
447 UibIndexMap& objects,
448 UibStrTable& strings,
449 QDataStream& out, QDomElement elem )
450{
451 int subLayoutNo = -1;
452 QCString name;
453 QDomElement nameElem;
454
455 QDomElement f = elem.firstChild().toElement();
456 while ( !f.isNull() ) {
457 QString tag = f.tagName();
458 if ( tag == "grid" || tag == "hbox" || tag == "vbox" ) {
459 out << (Q_UINT8) Object_SubLayout;
460 subLayoutNo = outputObject( buddies, objects, strings, out, f,
461 layoutForTag(tag) );
462 } else if ( tag == "property" ) {
463 if ( f.attribute("name") == "name" ) {
464 name = DomTool::elementToVariant( f, name ).asCString();
465 nameElem = f;
466 }
467 }
468 f = f.nextSibling().toElement();
469 }
470
471 if ( subLayoutNo != -1 ) {
472 /*
473 Remove the sub-layout's Object_End marker, append the grid
474 cell and the correct name property, and put the Object_End
475 marker back.
476 */
477 out.device()->at( out.device()->at() - 1 );
478 outputGridCell( out, elem );
479 outputProperty( buddies, subLayoutNo, strings, out, nameElem );
480 out << (Q_UINT8) Object_End;
481
482 objects.setName( subLayoutNo, name );
483 }
484}
485
486static int outputObject( QMap<int, QStringList>& buddies,
487 UibIndexMap& objects, UibStrTable& strings,
488 QDataStream& out, QDomElement elem,
489 QCString className )
490{
491 bool isQObject = !className.isEmpty();
492
493 if ( className == "QToolBar" )
494 out << (Q_UINT8) elem.attribute( "dock", "0" ).toInt();
495 if ( className == "QWidget" )
496 className = elem.attribute( "class", className ).latin1();
497
498 int objectNo = -1;
499 if ( isQObject ) {
500 packCString( strings, out, className );
501 objectNo = objects.insert();
502 }
503
504 outputGridCell( out, elem );
505
506 // optimization: insert '&Foo' into string-table before 'Foo'
507 if ( className == "QAction" || className == "QActionGroup" ) {
508 QVariant value = DomTool::readProperty( elem, "menuText", QVariant() );
509 if ( value.asString().startsWith("&") )
510 strings.insertString( value.asString() );
511 }
512
513 QDomElement f = elem.firstChild().toElement();
514 while ( !f.isNull() ) {
515 QString tag = f.tagName();
516 if ( tag == "action" ) {
517 if ( elem.tagName() == "item" || elem.tagName() == "toolbar" ) {
518 QString actionName = f.attribute( "name" );
519 int no = objects.find( actionName );
520 if ( no != -1 ) {
521 out << (Q_UINT8) Object_ActionRef;
522 packUInt16( out, no );
523 }
524 } else {
525 out << (Q_UINT8) Object_SubAction;
526 outputObject( buddies, objects, strings, out, f, "QAction" );
527 }
528 } else if ( tag == "actiongroup" ) {
529 out << (Q_UINT8) Object_SubAction;
530 outputObject( buddies, objects, strings, out, f, "QActionGroup" );
531 } else if ( tag == "attribute" ) {
532 out << (Q_UINT8) Object_Attribute;
533 outputProperty( buddies, objectNo, strings, out, f );
534 } else if ( tag == "column" ) {
535 out << (Q_UINT8) Object_Column;
536 outputObject( buddies, objects, strings, out, f );
537 } else if ( tag == "event" ) {
538 out << (Q_UINT8) Object_Event;
539 packCString( strings, out, f.attribute("name").latin1() );
540 packVariant( strings, out,
541 QStringList::split(',', f.attribute("functions")) );
542 } else if ( tag == "grid" || tag == "hbox" || tag == "vbox" ) {
543 out << (Q_UINT8) Object_SubLayout;
544 outputObject( buddies, objects, strings, out, f,
545 layoutForTag(tag) );
546 } else if ( tag == "item" ) {
547 if ( elem.tagName() == "menubar" ) {
548 out << (Q_UINT8) Object_MenuItem;
549 packCString( strings, out, f.attribute("name").latin1() );
550 packCString( strings, out, f.attribute("text").utf8() );
551 outputObject( buddies, objects, strings, out, f );
552 } else {
553 out << (Q_UINT8) Object_Item;
554 outputObject( buddies, objects, strings, out, f );
555 }
556 } else if ( tag == "property" ) {
557 outputProperty( buddies, objectNo, strings, out, f );
558 } else if ( tag == "row" ) {
559 out << (Q_UINT8) Object_Row;
560 outputObject( buddies, objects, strings, out, f );
561 } else if ( tag == "separator" ) {
562 out << (Q_UINT8) Object_Separator;
563 } else if ( tag == "spacer" ) {
564 out << (Q_UINT8) Object_Spacer;
565 outputObject( buddies, objects, strings, out, f );
566 } else if ( tag == "widget" ) {
567 if ( f.attribute("class") == "QLayoutWidget" &&
568 elem.tagName() != "widget" ) {
569 outputLayoutWidgetsSubLayout( buddies, objects, strings, out,
570 f );
571 } else {
572 out << (Q_UINT8) Object_SubWidget;
573 outputObject( buddies, objects, strings, out, f, "QWidget" );
574 }
575 }
576 f = f.nextSibling().toElement();
577 }
578 out << (Q_UINT8) Object_End;
579 if ( isQObject )
580 objects.setName( objectNo,
581 DomTool::readProperty(elem, "name", "").asString() );
582 return objectNo;
583}
584
585static void outputBlock( QDataStream& out, BlockTag tag,
586 const QByteArray& data )
587{
588 if ( !data.isEmpty() ) {
589 out << (Q_UINT8) tag;
590 packByteArray( out, data );
591 }
592}
593
594void convertUiToUib( QDomDocument& doc, QDataStream& out )
595{
596 QByteArray introBlock;
597 QByteArray actionsBlock;
598 QByteArray buddiesBlock;
599 QByteArray connectionsBlock;
600 QByteArray functionsBlock;
601 QByteArray imagesBlock;
602 QByteArray menubarBlock;
603 QByteArray slotsBlock;
604 QByteArray tabstopsBlock;
605 QByteArray toolbarsBlock;
606 QByteArray variablesBlock;
607 QByteArray widgetBlock;
608
609 QDomElement actionsElem;
610 QDomElement connectionsElem;
611 QDomElement imagesElem;
612 QDomElement menubarElem;
613 QDomElement tabstopsElem;
614 QDomElement toolbarsElem;
615 QDomElement widgetElem;
616
617 QMap<int, QStringList> buddies;
618 UibStrTable strings;
619 UibIndexMap objects;
620 int widgetNo = -1;
621 QCString className;
622 Q_INT16 defaultMargin = -32768;
623 Q_INT16 defaultSpacing = -32768;
624 Q_UINT8 introFlags = 0;
625
626 QDomElement elem = doc.firstChild().toElement().firstChild().toElement();
627 while ( !elem.isNull() ) {
628 QString tag = elem.tagName();
629
630 switch ( tag[0].latin1() ) {
631 case 'a':
632 if ( tag == "actions" )
633 actionsElem = elem;
634 break;
635 case 'c':
636 if ( tag == "class" ) {
637 className = elem.firstChild().toText().data().latin1();
638 } else if ( tag == "connections" ) {
639 connectionsElem = elem;
640 }
641 break;
642 case 'f':
643 if ( tag == "functions" ) {
644 QDataStream out2( functionsBlock, IO_WriteOnly );
645 QDomElement f = elem.firstChild().toElement();
646 while ( !f.isNull() ) {
647 if ( f.tagName() == "function" ) {
648 packStringSplit( strings, out2,
649 f.attribute("name").latin1(), '(' );
650 packString( strings, out2,
651 f.firstChild().toText().data() );
652 }
653 f = f.nextSibling().toElement();
654 }
655 }
656 break;
657 case 'i':
658 if ( tag == "images" ) {
659 QDataStream out2( imagesBlock, IO_WriteOnly );
660 QDomElement f = elem.firstChild().toElement();
661 while ( !f.isNull() ) {
662 if ( f.tagName() == "image" ) {
663 QString name = f.attribute( "name" );
664 QDomElement g = f.firstChild().toElement();
665 if ( g.tagName() == "data" ) {
666 QString format = g.attribute( "format", "PNG" );
667 QString hex = g.firstChild().toText().data();
668 int n = hex.length() / 2;
669 QByteArray data( n );
670 for ( int i = 0; i < n; i++ )
671 data[i] = (char) hex.mid( 2 * i, 2 )
672 .toUInt( 0, 16 );
673
674 packString( strings, out2, name );
675 packString( strings, out2, format );
676 packUInt32( out2, g.attribute("length").toInt() );
677 packByteArray( out2, data );
678 }
679 }
680 f = f.nextSibling().toElement();
681 }
682 }
683 break;
684 case 'l':
685 if ( tag == "layoutdefaults" ) {
686 QString margin = elem.attribute( "margin" );
687 if ( !margin.isEmpty() )
688 defaultMargin = margin.toInt();
689 QString spacing = elem.attribute( "spacing" );
690 if ( !spacing.isEmpty() )
691 defaultSpacing = spacing.toInt();
692 }
693 break;
694 case 'm':
695 if ( tag == "menubar" )
696 menubarElem = elem;
697 break;
698 case 'p':
699 if ( tag == "pixmapinproject" )
700 introFlags |= Intro_Pixmapinproject;
701 break;
702 case 's':
703 if ( tag == "slots" ) {
704 QDataStream out2( slotsBlock, IO_WriteOnly );
705 QDomElement f = elem.firstChild().toElement();
706 while ( !f.isNull() ) {
707 if ( f.tagName() == "slot" ) {
708 QString language = f.attribute( "language", "C++" );
709 QString slot = UibHack::normalize(
710 f.firstChild().toText().data() );
711 packString( strings, out2, language );
712 packStringSplit( strings, out2, slot, '(' );
713 }
714 f = f.nextSibling().toElement();
715 }
716 }
717 break;
718 case 't':
719 if ( tag == "tabstops" ) {
720 tabstopsElem = elem;
721 } else if ( tag == "toolbars" ) {
722 toolbarsElem = elem;
723 }
724 break;
725 case 'v':
726 if ( tag == "variable" ) {
727 QDataStream out2( variablesBlock, IO_WriteOnly | IO_Append );
728 packString( strings, out2, elem.firstChild().toText().data() );
729 } else if ( tag == "variables" ) {
730 QDataStream out2( variablesBlock, IO_WriteOnly );
731 QDomElement f = elem.firstChild().toElement();
732 while ( !f.isNull() ) {
733 if ( f.tagName() == "variable" )
734 packString( strings, out2,
735 f.firstChild().toText().data() );
736 f = f.nextSibling().toElement();
737 }
738 }
739 break;
740 case 'w':
741 if ( tag == "widget" )
742 widgetElem = elem;
743 }
744 elem = elem.nextSibling().toElement();
745 }
746
747 {
748 QDataStream out2( widgetBlock, IO_WriteOnly );
749 widgetNo = outputObject( buddies, objects, strings, out2, widgetElem,
750 "QWidget" );
751 }
752
753 if ( !tabstopsElem.isNull() ) {
754 QDataStream out2( tabstopsBlock, IO_WriteOnly );
755 QDomElement f = tabstopsElem.firstChild().toElement();
756 while ( !f.isNull() ) {
757 if ( f.tagName() == "tabstop" ) {
758 QString widgetName = f.firstChild().toText().data();
759 int no = objects.find( widgetName );
760 if ( no != -1 )
761 packUInt16( out2, no );
762 }
763 f = f.nextSibling().toElement();
764 }
765 }
766
767 if ( !actionsElem.isNull() ) {
768 QDataStream out2( actionsBlock, IO_WriteOnly );
769 outputObject( buddies, objects, strings, out2, actionsElem );
770 }
771
772 if ( !menubarElem.isNull() ) {
773 QDataStream out2( menubarBlock, IO_WriteOnly );
774 outputObject( buddies, objects, strings, out2, menubarElem,
775 "QMenuBar" );
776 }
777
778 if ( !toolbarsElem.isNull() ) {
779 QDataStream out2( toolbarsBlock, IO_WriteOnly );
780 QDomElement f = toolbarsElem.firstChild().toElement();
781 while ( !f.isNull() ) {
782 if ( f.tagName() == "toolbar" )
783 outputObject( buddies, objects, strings, out2, f, "QToolBar" );
784 f = f.nextSibling().toElement();
785 }
786 }
787
788 if ( !buddies.isEmpty() ) {
789 QDataStream out2( buddiesBlock, IO_WriteOnly );
790 QMap<int, QStringList>::ConstIterator a = buddies.begin();
791 while ( a != buddies.end() ) {
792 QStringList::ConstIterator b = (*a).begin();
793 while ( b != (*a).end() ) {
794 int no = objects.find( *b );
795 if ( no != -1 ) {
796 packUInt16( out2, a.key() );
797 packUInt16( out2, no );
798 }
799 ++b;
800 }
801 ++a;
802 }
803 }
804
805 if ( !connectionsElem.isNull() ) {
806 QString prevLanguage = "C++";
807 int prevSenderNo = 0;
808 QString prevSignal = "clicked()";
809 int prevReceiverNo = 0;
810 QString prevSlot = "accept()";
811
812 QDataStream out2( connectionsBlock, IO_WriteOnly );
813 QDomElement f = connectionsElem.firstChild().toElement();
814 while ( !f.isNull() ) {
815 if ( f.tagName() == "connection" ) {
816 QMap<QString, QString> argMap;
817
818 QDomElement g = f.firstChild().toElement();
819 while ( !g.isNull() ) {
820 argMap[g.tagName()] = g.firstChild().toText().data();
821 g = g.nextSibling().toElement();
822 }
823
824 QString language = f.attribute( "language", "C++" );
825 int senderNo = objects.find( argMap["sender"], widgetNo );
826 int receiverNo = objects.find( argMap["receiver"], widgetNo );
827 QString signal = UibHack::normalize( argMap["signal"] );
828 QString slot = UibHack::normalize( argMap["slot"] );
829
830 Q_UINT8 connectionFlags = 0;
831 if ( language != prevLanguage )
832 connectionFlags |= Connection_Language;
833 if ( senderNo != prevSenderNo )
834 connectionFlags |= Connection_Sender;
835 if ( signal != prevSignal )
836 connectionFlags |= Connection_Signal;
837 if ( receiverNo != prevReceiverNo )
838 connectionFlags |= Connection_Receiver;
839 if ( slot != prevSlot )
840 connectionFlags |= Connection_Slot;
841 out2 << connectionFlags;
842
843 if ( connectionFlags & Connection_Language )
844 packString( strings, out2, language );
845 if ( connectionFlags & Connection_Sender )
846 packUInt16( out2, senderNo );
847 if ( connectionFlags & Connection_Signal )
848 packStringSplit( strings, out2, signal, '(' );
849 if ( connectionFlags & Connection_Receiver )
850 packUInt16( out2, receiverNo );
851 if ( connectionFlags & Connection_Slot )
852 packStringSplit( strings, out2, slot, '(' );
853
854 prevLanguage = language;
855 prevSenderNo = senderNo;
856 prevSignal = signal;
857 prevReceiverNo = receiverNo;
858 prevSlot = slot;
859 } else if ( f.tagName() == "slot" ) {
860 // ###
861 }
862 f = f.nextSibling().toElement();
863 }
864 }
865
866 {
867 QDataStream out2( introBlock, IO_WriteOnly );
868 out2 << introFlags;
869 out2 << defaultMargin;
870 out2 << defaultSpacing;
871 packUInt16( out2, objects.count() );
872 packCString( strings, out2, className );
873 }
874
875 out << UibMagic;
876 out << (Q_UINT8) '\n';
877 out << (Q_UINT8) '\r';
878 out << (Q_UINT8) out.version();
879 outputBlock( out, Block_Strings, strings.block() );
880 outputBlock( out, Block_Intro, introBlock );
881 outputBlock( out, Block_Images, imagesBlock );
882 outputBlock( out, Block_Widget, widgetBlock );
883 outputBlock( out, Block_Slots, slotsBlock );
884 outputBlock( out, Block_Tabstops, tabstopsBlock );
885 outputBlock( out, Block_Actions, actionsBlock );
886 outputBlock( out, Block_Menubar, menubarBlock );
887 outputBlock( out, Block_Toolbars, toolbarsBlock );
888 outputBlock( out, Block_Variables, variablesBlock );
889 outputBlock( out, Block_Functions, functionsBlock );
890 outputBlock( out, Block_Buddies, buddiesBlock );
891 outputBlock( out, Block_Connections, connectionsBlock );
892 out << (Q_UINT8) Block_End;
893}
Note: See TracBrowser for help on using the repository browser.