~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to kdevdesigner/shared/ui2uib.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2010-05-05 07:21:55 UTC
  • mfrom: (1.2.3 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505072155-h78lx19pu04sbhtn
Tags: 4:4.0.0-2
* Upload to unstable (Closes: #579947, #481832).
* Acknowledge obsolete NMU fixes (Closes: #562410, #546961).

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
137
 
static 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
 
 
150
 
class UibHack : public QObject
151
 
{
152
 
public:
153
 
    static QString normalize( const QString& member ) {
154
 
        return QString::fromUtf8( QObject::normalizeSignalSlot(member.utf8()) );
155
 
    }
156
 
};
157
 
 
158
 
class UibIndexMap
159
 
{
160
 
public:
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
 
 
170
 
private:
171
 
    QMap<QString, int> nameMap;
172
 
    QMap<QString, int> conflicts;
173
 
    int next;
174
 
};
175
 
 
176
 
void 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
 
 
184
 
int 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
 
 
194
 
static 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
 
 
204
 
static 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
 
 
214
 
static void packByteArray( QDataStream& out, const QByteArray& array )
215
 
{
216
 
    packUInt32( out, array.size() );
217
 
    out.writeRawBytes( array.data(), array.size() );
218
 
}
219
 
 
220
 
static void packCString( UibStrTable& strings, QDataStream& out,
221
 
                         const char *cstr )
222
 
{
223
 
    packUInt32( out, strings.insertCString(cstr) );
224
 
}
225
 
 
226
 
static void packString( UibStrTable& strings, QDataStream& out,
227
 
                        const QString& str )
228
 
{
229
 
    packUInt32( out, strings.insertString(str) );
230
 
}
231
 
 
232
 
static 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
 
 
242
 
static 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
 
 
321
 
static 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
 
 
421
 
static 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
 
 
441
 
static int outputObject( QMap<int, QStringList>& buddies,
442
 
                         UibIndexMap& objects, UibStrTable& strings,
443
 
                         QDataStream& out, QDomElement elem,
444
 
                         QCString className = "" );
445
 
 
446
 
static 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
 
 
486
 
static 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
 
 
585
 
static 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
 
 
594
 
void 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
 
}