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

« back to all changes in this revision

Viewing changes to kdevdesigner/designer/layout.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 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 "formwindow.h"
28
 
#include "layout.h"
29
 
#include <widgetdatabase.h>
30
 
#include "widgetfactory.h"
31
 
 
32
 
#include <qlayout.h>
33
 
#include <qevent.h>
34
 
#include <qpainter.h>
35
 
#include <qpen.h>
36
 
#include <qbitmap.h>
37
 
#include <qsplitter.h>
38
 
#include <qvaluevector.h>
39
 
#include <qmainwindow.h>
40
 
 
41
 
bool operator<( const QGuardedPtr<QWidget> &p1, const QGuardedPtr<QWidget> &p2 )
42
 
{
43
 
    return p1.operator->() < p2.operator->();
44
 
}
45
 
 
46
 
/*!
47
 
  \class Layout layout.h
48
 
  \brief Baseclass for layouting widgets in the Designer
49
 
 
50
 
  Classes derived from this abstract base class are used for layouting
51
 
  operations in the Designer.
52
 
 
53
 
*/
54
 
 
55
 
/*!  \a p specifies the parent of the layoutBase \a lb. The parent
56
 
  might be changed in setup(). If the layoutBase is a
57
 
  container, the parent and the layoutBase are the same. Also they
58
 
  always have to be a widget known to the designer (e.g. in the case
59
 
  of the tabwidget parent and layoutBase are the tabwidget and not the
60
 
  page which actually gets laid out. For actual usage the correct
61
 
  widget is found later by Layout.)
62
 
 */
63
 
 
64
 
Layout::Layout( const QWidgetList &wl, QWidget *p, FormWindow *fw, QWidget *lb, bool doSetup, bool splitter )
65
 
    : widgets( wl ), parent( p ), formWindow( fw ), isBreak( !doSetup ), useSplitter( splitter )
66
 
{
67
 
    widgets.setAutoDelete( FALSE );
68
 
    layoutBase = lb;
69
 
    if ( !doSetup && layoutBase )
70
 
        oldGeometry = layoutBase->geometry();
71
 
}
72
 
 
73
 
/*!  The widget list we got in the constructor might contain too much
74
 
  widgets (like widgets with different parents, already laid out
75
 
  widgets, etc.). Here we set up the list and so the only the "best"
76
 
  widgets get laid out.
77
 
*/
78
 
 
79
 
void Layout::setup()
80
 
{
81
 
    startPoint = QPoint( 32767, 32767 );
82
 
    QValueList<QWidgetList> lists;
83
 
    QWidget *lastParent = 0;
84
 
    QWidgetList *lastList = 0;
85
 
    QWidget *w = 0;
86
 
 
87
 
    // Go through all widgets of the list we got. As we can only
88
 
    // layout widgets which have the same parent, we first do some
89
 
    // sorting which means create a list for each parent containing
90
 
    // its child here. After that we keep working on the list of
91
 
    // childs which has the most entries.
92
 
    // Widgets which are already laid out are thrown away here too
93
 
    for ( w = widgets.first(); w; w = widgets.next() ) {
94
 
        if ( w->parentWidget() && WidgetFactory::layoutType( w->parentWidget() ) != WidgetFactory::NoLayout )
95
 
            continue;
96
 
        if ( lastParent != w->parentWidget() ) {
97
 
            lastList = 0;
98
 
            lastParent = w->parentWidget();
99
 
            QValueList<QWidgetList>::Iterator it = lists.begin();
100
 
            for ( ; it != lists.end(); ++it ) {
101
 
                if ( ( *it ).first()->parentWidget() == w->parentWidget() )
102
 
                    lastList = &( *it );
103
 
            }
104
 
            if ( !lastList ) {
105
 
                QWidgetList l;
106
 
                l.setAutoDelete( FALSE );
107
 
                lists.append( l );
108
 
                lastList = &lists.last();
109
 
            }
110
 
        }
111
 
        lastList->append( w );
112
 
    }
113
 
 
114
 
    // So, now find the list with the most entries
115
 
    lastList = 0;
116
 
    QValueList<QWidgetList>::Iterator it = lists.begin();
117
 
    for ( ; it != lists.end(); ++it ) {
118
 
        if ( !lastList || ( *it ).count() > lastList->count() )
119
 
            lastList = &( *it );
120
 
    }
121
 
 
122
 
    // If we found no list (because no widget did fit at all) or the
123
 
    // best list has only one entry and we do not layout a container,
124
 
    // we leave here.
125
 
    if ( !lastList || ( lastList->count() < 2 &&
126
 
                        ( !layoutBase ||
127
 
                          ( !WidgetDatabase::isContainer( WidgetDatabase::idFromClassName( WidgetFactory::classNameOf( layoutBase ) ) ) &&
128
 
                            layoutBase != formWindow->mainContainer() ) )
129
 
                        ) ) {
130
 
        widgets.clear();
131
 
        startPoint = QPoint( 0, 0 );
132
 
        return;
133
 
    }
134
 
 
135
 
    // Now we have a new and clean widget list, which makes sense
136
 
    // to layout
137
 
    widgets = *lastList;
138
 
    // Also use the only correct parent later, so store it
139
 
    parent = WidgetFactory::widgetOfContainer( widgets.first()->parentWidget() );
140
 
    // Now calculate the position where the layout-meta-widget should
141
 
    // be placed and connect to widgetDestroyed() signals of the
142
 
    // widgets to get informed if one gets deleted to be able to
143
 
    // handle that and do not crash in this case
144
 
    for ( w = widgets.first(); w; w = widgets.next() ) {
145
 
        connect( w, SIGNAL( destroyed() ),
146
 
                 this, SLOT( widgetDestroyed() ) );
147
 
        startPoint = QPoint( QMIN( startPoint.x(), w->x() ),
148
 
                             QMIN( startPoint.y(), w->y() ) );
149
 
        geometries.insert( w, QRect( w->pos(), w->size() ) );
150
 
        // Change the Z-order, as saving/loading uses the Z-order for
151
 
        // writing/creating widgets and this has to be the same as in
152
 
        // the layout. Else saving + loading will give different results
153
 
        w->raise();
154
 
    }
155
 
}
156
 
 
157
 
void Layout::widgetDestroyed()
158
 
{
159
 
     if ( sender() && sender()->isWidgetType() )
160
 
        widgets.removeRef( (QWidget*)sender() );
161
 
}
162
 
 
163
 
bool Layout::prepareLayout( bool &needMove, bool &needReparent )
164
 
{
165
 
    if ( !widgets.count() )
166
 
        return FALSE;
167
 
    for ( QWidget *w = widgets.first(); w; w = widgets.next() )
168
 
        w->raise();
169
 
    needMove = !layoutBase;
170
 
    needReparent = needMove || ::qt_cast<QLayoutWidget*>(layoutBase) || ::qt_cast<QSplitter*>(layoutBase);
171
 
    if ( !layoutBase ) {
172
 
        if ( !useSplitter )
173
 
            layoutBase = WidgetFactory::create( WidgetDatabase::idFromClassName( "QLayoutWidget" ),
174
 
                                                WidgetFactory::containerOfWidget( parent ) );
175
 
        else
176
 
            layoutBase = WidgetFactory::create( WidgetDatabase::idFromClassName( "QSplitter" ),
177
 
                                                WidgetFactory::containerOfWidget( parent ) );
178
 
    } else {
179
 
        WidgetFactory::deleteLayout( layoutBase );
180
 
    }
181
 
 
182
 
    return TRUE;
183
 
}
184
 
 
185
 
void Layout::finishLayout( bool needMove, QLayout *layout )
186
 
{
187
 
    if ( needMove )
188
 
        layoutBase->move( startPoint );
189
 
    QRect g( QRect( layoutBase->pos(), layoutBase->size() ) );
190
 
    if ( WidgetFactory::layoutType( layoutBase->parentWidget() ) == WidgetFactory::NoLayout && !isBreak )
191
 
        layoutBase->adjustSize();
192
 
    else if ( isBreak )
193
 
        layoutBase->setGeometry( oldGeometry );
194
 
    oldGeometry = g;
195
 
    layoutBase->show();
196
 
    layout->activate();
197
 
    formWindow->insertWidget( layoutBase );
198
 
    formWindow->selectWidget( layoutBase );
199
 
    QString n = layoutBase->name();
200
 
    if ( n.find( "qt_dead_widget_" ) != -1 ) {
201
 
        n.remove( 0, QString( "qt_dead_widget_" ).length() );
202
 
        layoutBase->setName( n );
203
 
    }
204
 
}
205
 
 
206
 
void Layout::undoLayout()
207
 
{
208
 
    if ( !widgets.count() )
209
 
        return;
210
 
    QMap<QGuardedPtr<QWidget>, QRect>::Iterator it = geometries.begin();
211
 
    for ( ; it != geometries.end(); ++it ) {
212
 
        if ( !it.key() )
213
 
            continue;
214
 
        it.key()->reparent( WidgetFactory::containerOfWidget( parent ), 0, ( *it ).topLeft(), it.key()->isVisibleTo( formWindow ) );
215
 
        it.key()->resize( ( *it ).size() );
216
 
    }
217
 
    formWindow->selectWidget( layoutBase, FALSE );
218
 
    WidgetFactory::deleteLayout( layoutBase );
219
 
    if ( parent != layoutBase && !::qt_cast<QMainWindow*>(layoutBase) ) {
220
 
        layoutBase->hide();
221
 
        QString n = layoutBase->name();
222
 
        n.prepend( "qt_dead_widget_" );
223
 
        layoutBase->setName( n );
224
 
    } else {
225
 
        layoutBase->setGeometry( oldGeometry );
226
 
    }
227
 
    if ( widgets.first() )
228
 
        formWindow->selectWidget( widgets.first() );
229
 
    else
230
 
        formWindow->selectWidget( formWindow );
231
 
}
232
 
 
233
 
void Layout::breakLayout()
234
 
{
235
 
    QMap<QWidget*, QRect> rects;
236
 
    if ( !widgets.isEmpty() ) {
237
 
        QWidget *w;
238
 
        for ( w = widgets.first(); w; w = widgets.next() )
239
 
            rects.insert( w, w->geometry() );
240
 
    }
241
 
    WidgetFactory::deleteLayout( layoutBase );
242
 
    bool needReparent = qstrcmp( layoutBase->className(), "QLayoutWidget" ) == 0 ||
243
 
                        qstrcmp( layoutBase->className(), "QSplitter" ) == 0 ||
244
 
                        ( !WidgetDatabase::isContainer( WidgetDatabase::idFromClassName( WidgetFactory::classNameOf( layoutBase ) ) ) &&
245
 
                          layoutBase != formWindow->mainContainer() );
246
 
    bool needResize = qstrcmp( layoutBase->className(), "QSplitter" ) == 0;
247
 
    bool add = geometries.isEmpty();
248
 
    for ( QWidget *w = widgets.first(); w; w = widgets.next() ) {
249
 
        if ( needReparent )
250
 
            w->reparent( layoutBase->parentWidget(), 0,
251
 
                         layoutBase->pos() + w->pos(), TRUE );
252
 
        if ( needResize ) {
253
 
            QMap<QWidget*, QRect>::Iterator it = rects.find( w );
254
 
            if ( it != rects.end() )
255
 
                w->setGeometry( QRect( layoutBase->pos() + (*it).topLeft(), (*it).size() ) );
256
 
        }
257
 
        if ( add )
258
 
            geometries.insert( w, QRect( w->pos(), w->size() ) );
259
 
    }
260
 
    if ( needReparent ) {
261
 
        layoutBase->hide();
262
 
        parent = layoutBase->parentWidget();
263
 
        QString n = layoutBase->name();
264
 
        n.prepend( "qt_dead_widget_" );
265
 
        layoutBase->setName( n );
266
 
    } else {
267
 
        parent = layoutBase;
268
 
    }
269
 
    if ( widgets.first() && widgets.first()->isVisibleTo( formWindow ) )
270
 
        formWindow->selectWidget( widgets.first() );
271
 
    else
272
 
        formWindow->selectWidget( formWindow );
273
 
}
274
 
 
275
 
class HorizontalLayoutList : public QWidgetList
276
 
{
277
 
public:
278
 
    HorizontalLayoutList( const QWidgetList &l )
279
 
        : QWidgetList( l ) {}
280
 
 
281
 
    int compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 ) {
282
 
        QWidget *w1 = (QWidget*)item1;
283
 
        QWidget *w2 = (QWidget*)item2;
284
 
        if ( w1->x() == w2->x() )
285
 
            return 0;
286
 
        if ( w1->x() > w2->x() )
287
 
            return 1;
288
 
        return -1;
289
 
    }
290
 
 
291
 
};
292
 
 
293
 
HorizontalLayout::HorizontalLayout( const QWidgetList &wl, QWidget *p, FormWindow *fw, QWidget *lb, bool doSetup, bool splitter )
294
 
    : Layout( wl, p, fw, lb, doSetup, splitter )
295
 
{
296
 
    if ( doSetup )
297
 
        setup();
298
 
}
299
 
 
300
 
void HorizontalLayout::setup()
301
 
{
302
 
    HorizontalLayoutList l( widgets );
303
 
    l.sort();
304
 
    widgets = l;
305
 
    Layout::setup();
306
 
}
307
 
 
308
 
void HorizontalLayout::doLayout()
309
 
{
310
 
    bool needMove, needReparent;
311
 
    if ( !prepareLayout( needMove, needReparent ) )
312
 
        return;
313
 
 
314
 
    QHBoxLayout *layout = (QHBoxLayout*)WidgetFactory::createLayout( layoutBase, 0, WidgetFactory::HBox );
315
 
 
316
 
    for ( QWidget *w = widgets.first(); w; w = widgets.next() ) {
317
 
        if ( needReparent && w->parent() != layoutBase )
318
 
            w->reparent( layoutBase, 0, QPoint( 0, 0 ), FALSE );
319
 
        if ( !useSplitter ) {
320
 
            if ( qstrcmp( w->className(), "Spacer" ) == 0 )
321
 
                layout->addWidget( w, 0, ( (Spacer*)w )->alignment() );
322
 
            else
323
 
                layout->addWidget( w );
324
 
            if ( ::qt_cast<QLayoutWidget*>(w) )
325
 
                ( (QLayoutWidget*)w )->updateSizePolicy();
326
 
        }
327
 
        w->show();
328
 
    }
329
 
 
330
 
    if ( ::qt_cast<QSplitter*>(layoutBase) )
331
 
        ( (QSplitter*)layoutBase )->setOrientation( Qt::Horizontal );
332
 
 
333
 
    finishLayout( needMove, layout );
334
 
}
335
 
 
336
 
 
337
 
 
338
 
 
339
 
class VerticalLayoutList : public QWidgetList
340
 
{
341
 
public:
342
 
    VerticalLayoutList( const QWidgetList &l )
343
 
        : QWidgetList( l ) {}
344
 
 
345
 
    int compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 ) {
346
 
        QWidget *w1 = (QWidget*)item1;
347
 
        QWidget *w2 = (QWidget*)item2;
348
 
        if ( w1->y() == w2->y() )
349
 
            return 0;
350
 
        if ( w1->y() > w2->y() )
351
 
            return 1;
352
 
        return -1;
353
 
    }
354
 
 
355
 
};
356
 
 
357
 
VerticalLayout::VerticalLayout( const QWidgetList &wl, QWidget *p, FormWindow *fw, QWidget *lb, bool doSetup, bool splitter )
358
 
    : Layout( wl, p, fw, lb, doSetup, splitter )
359
 
{
360
 
    if ( doSetup )
361
 
        setup();
362
 
}
363
 
 
364
 
void VerticalLayout::setup()
365
 
{
366
 
    VerticalLayoutList l( widgets );
367
 
    l.sort();
368
 
    widgets = l;
369
 
    Layout::setup();
370
 
}
371
 
 
372
 
void VerticalLayout::doLayout()
373
 
{
374
 
    bool needMove, needReparent;
375
 
    if ( !prepareLayout( needMove, needReparent ) )
376
 
        return;
377
 
 
378
 
    QVBoxLayout *layout = (QVBoxLayout*)WidgetFactory::createLayout( layoutBase, 0, WidgetFactory::VBox );
379
 
 
380
 
    for ( QWidget *w = widgets.first(); w; w = widgets.next() ) {
381
 
        if ( needReparent && w->parent() != layoutBase )
382
 
            w->reparent( layoutBase, 0, QPoint( 0, 0 ), FALSE );
383
 
        if ( !useSplitter ) {
384
 
            if ( qstrcmp( w->className(), "Spacer" ) == 0 )
385
 
                layout->addWidget( w, 0, ( (Spacer*)w )->alignment() );
386
 
            else
387
 
                layout->addWidget( w );
388
 
            if ( ::qt_cast<QLayoutWidget*>(w) )
389
 
                ( (QLayoutWidget*)w )->updateSizePolicy();
390
 
        }
391
 
        w->show();
392
 
    }
393
 
 
394
 
    if ( ::qt_cast<QSplitter*>(layoutBase) )
395
 
        ( (QSplitter*)layoutBase )->setOrientation( Qt::Vertical );
396
 
 
397
 
    finishLayout( needMove, layout );
398
 
}
399
 
 
400
 
 
401
 
 
402
 
 
403
 
 
404
 
class Grid
405
 
{
406
 
public:
407
 
    Grid( int rows, int cols );
408
 
    ~Grid();
409
 
 
410
 
    QWidget* cell( int row, int col ) const { return cells[ row * ncols + col]; }
411
 
    void setCell( int row, int col, QWidget* w ) { cells[ row*ncols + col] = w; }
412
 
    void setCells( QRect c, QWidget* w ) {
413
 
        for ( int rows = c.bottom()-c.top(); rows >= 0; rows--)
414
 
            for ( int cols = c.right()-c.left(); cols >= 0; cols--) {
415
 
                setCell(c.top()+rows, c.left()+cols, w);
416
 
            }
417
 
    }
418
 
    int numRows() const { return nrows; }
419
 
    int numCols() const { return ncols; }
420
 
 
421
 
    void simplify();
422
 
    bool locateWidget( QWidget* w, int& row, int& col, int& rowspan, int& colspan );
423
 
 
424
 
private:
425
 
    void merge();
426
 
    int countRow( int r, int c ) const;
427
 
    int countCol( int r, int c ) const;
428
 
    void setRow( int r, int c, QWidget* w, int count );
429
 
    void setCol( int r, int c, QWidget* w, int count );
430
 
    bool isWidgetStartCol( int c ) const;
431
 
    bool isWidgetEndCol( int c ) const;
432
 
    bool isWidgetStartRow( int r ) const;
433
 
    bool isWidgetEndRow( int r ) const;
434
 
    bool isWidgetTopLeft( int r, int c ) const;
435
 
    void extendLeft();
436
 
    void extendRight();
437
 
    void extendUp();
438
 
    void extendDown();
439
 
    QWidget** cells;
440
 
    bool* cols;
441
 
    bool* rows;
442
 
    int nrows, ncols;
443
 
 
444
 
};
445
 
 
446
 
Grid::Grid( int r, int c )
447
 
    : nrows( r ), ncols( c )
448
 
{
449
 
    cells = new QWidget*[ r * c ];
450
 
    memset( cells, 0, sizeof( cells ) * r * c );
451
 
    rows = new bool[ r ];
452
 
    cols = new bool[ c ];
453
 
 
454
 
}
455
 
 
456
 
Grid::~Grid()
457
 
{
458
 
    delete [] cells;
459
 
    delete [] cols;
460
 
    delete [] rows;
461
 
}
462
 
 
463
 
int Grid::countRow( int r, int c ) const
464
 
{
465
 
    QWidget* w = cell( r, c );
466
 
    int i = c + 1;
467
 
    while ( i < ncols && cell( r, i ) == w )
468
 
        i++;
469
 
    return i - c;
470
 
}
471
 
 
472
 
int Grid::countCol( int r, int c ) const
473
 
{
474
 
    QWidget* w = cell( r, c );
475
 
    int i = r + 1;
476
 
    while ( i < nrows && cell( i, c ) == w )
477
 
        i++;
478
 
    return i - r;
479
 
}
480
 
 
481
 
void Grid::setCol( int r, int c, QWidget* w, int count )
482
 
{
483
 
    for (int i = 0; i < count; i++ )
484
 
        setCell( r + i, c, w );
485
 
}
486
 
 
487
 
void Grid::setRow( int r, int c, QWidget* w, int count )
488
 
{
489
 
    for (int i = 0; i < count; i++ )
490
 
        setCell( r, c + i, w );
491
 
}
492
 
 
493
 
bool Grid::isWidgetStartCol( int c ) const
494
 
{
495
 
    int r;
496
 
    for ( r = 0; r < nrows; r++ ) {
497
 
        if ( cell( r, c ) && ( (c==0) || (cell( r, c)  != cell( r, c-1) )) ) {
498
 
            return TRUE;
499
 
        }
500
 
    }
501
 
    return FALSE;
502
 
}
503
 
 
504
 
bool Grid::isWidgetEndCol( int c ) const
505
 
{
506
 
    int r;
507
 
    for ( r = 0; r < nrows; r++ ) {
508
 
        if ( cell( r, c ) && ((c == ncols-1) || (cell( r, c) != cell( r, c+1) )) )
509
 
            return TRUE;
510
 
    }
511
 
    return FALSE;
512
 
}
513
 
 
514
 
bool Grid::isWidgetStartRow( int r ) const
515
 
{
516
 
    int c;
517
 
    for ( c = 0; c < ncols; c++ ) {
518
 
        if ( cell( r, c ) && ( (r==0) || (cell( r, c) != cell( r-1, c) )) )
519
 
            return TRUE;
520
 
    }
521
 
    return FALSE;
522
 
}
523
 
 
524
 
bool Grid::isWidgetEndRow( int r ) const
525
 
{
526
 
    int c;
527
 
    for ( c = 0; c < ncols; c++ ) {
528
 
        if ( cell( r, c ) && ((r == nrows-1) || (cell( r, c) != cell( r+1, c) )) )
529
 
            return TRUE;
530
 
    }
531
 
    return FALSE;
532
 
}
533
 
 
534
 
 
535
 
bool Grid::isWidgetTopLeft( int r, int c ) const
536
 
{
537
 
    QWidget* w = cell( r, c );
538
 
    if ( !w )
539
 
        return FALSE;
540
 
    return ( !r || cell( r-1, c) != w ) && (!c || cell( r, c-1) != w);
541
 
}
542
 
 
543
 
void Grid::extendLeft()
544
 
{
545
 
    int r,c,i;
546
 
    for ( c = 1; c < ncols; c++ ) {
547
 
        for ( r = 0; r < nrows; r++ ) {
548
 
            QWidget* w = cell( r, c );
549
 
            if ( !w )
550
 
                continue;
551
 
            int cc = countCol( r, c);
552
 
            int stretch = 0;
553
 
            for ( i = c-1; i >= 0; i-- ) {
554
 
                if ( cell( r, i ) )
555
 
                    break;
556
 
                if ( countCol( r, i ) < cc )
557
 
                    break;
558
 
                if ( isWidgetEndCol( i ) )
559
 
                    break;
560
 
                if ( isWidgetStartCol( i ) ) {
561
 
                    stretch = c - i;
562
 
                    break;
563
 
                }
564
 
            }
565
 
            if ( stretch ) {
566
 
                for ( i = 0; i < stretch; i++ )
567
 
                    setCol( r, c-i-1, w, cc );
568
 
            }
569
 
        }
570
 
    }
571
 
}
572
 
 
573
 
 
574
 
void Grid::extendRight()
575
 
{
576
 
    int r,c,i;
577
 
    for ( c = ncols - 2; c >= 0; c-- ) {
578
 
        for ( r = 0; r < nrows; r++ ) {
579
 
            QWidget* w = cell( r, c );
580
 
            if ( !w )
581
 
                continue;
582
 
            int cc = countCol( r, c);
583
 
            int stretch = 0;
584
 
            for ( i = c+1; i < ncols; i++ ) {
585
 
                if ( cell( r, i ) )
586
 
                    break;
587
 
                if ( countCol( r, i ) < cc )
588
 
                    break;
589
 
                if ( isWidgetStartCol( i ) )
590
 
                    break;
591
 
                if ( isWidgetEndCol( i ) ) {
592
 
                    stretch = i - c;
593
 
                    break;
594
 
                }
595
 
            }
596
 
            if ( stretch ) {
597
 
                for ( i = 0; i < stretch; i++ )
598
 
                    setCol( r, c+i+1, w, cc );
599
 
            }
600
 
        }
601
 
    }
602
 
 
603
 
}
604
 
 
605
 
void Grid::extendUp()
606
 
{
607
 
    int r,c,i;
608
 
    for ( r = 1; r < nrows; r++ ) {
609
 
        for ( c = 0; c < ncols; c++ ) {
610
 
            QWidget* w = cell( r, c );
611
 
            if ( !w )
612
 
                continue;
613
 
            int cr = countRow( r, c);
614
 
            int stretch = 0;
615
 
            for ( i = r-1; i >= 0; i-- ) {
616
 
                if ( cell( i, c ) )
617
 
                    break;
618
 
                if ( countRow( i, c ) < cr )
619
 
                    break;
620
 
                if ( isWidgetEndRow( i ) )
621
 
                    break;
622
 
                if ( isWidgetStartRow( i ) ) {
623
 
                    stretch = r - i;
624
 
                    break;
625
 
                }
626
 
            }
627
 
            if ( stretch ) {
628
 
                for ( i = 0; i < stretch; i++ )
629
 
                    setRow( r-i-1, c, w, cr );
630
 
            }
631
 
        }
632
 
    }
633
 
}
634
 
 
635
 
void Grid::extendDown()
636
 
{
637
 
    int r,c,i;
638
 
    for ( r = nrows - 2; r >= 0; r-- ) {
639
 
        for ( c = 0; c < ncols; c++ ) {
640
 
            QWidget* w = cell( r, c );
641
 
            if ( !w )
642
 
                continue;
643
 
            int cr = countRow( r, c);
644
 
            int stretch = 0;
645
 
            for ( i = r+1; i < nrows; i++ ) {
646
 
                if ( cell( i, c ) )
647
 
                    break;
648
 
                if ( countRow( i, c ) < cr )
649
 
                    break;
650
 
                if ( isWidgetStartRow( i ) )
651
 
                    break;
652
 
                if ( isWidgetEndRow( i ) ) {
653
 
                    stretch = i - r;
654
 
                    break;
655
 
                }
656
 
            }
657
 
            if ( stretch ) {
658
 
                for ( i = 0; i < stretch; i++ )
659
 
                    setRow( r+i+1, c, w, cr );
660
 
            }
661
 
        }
662
 
    }
663
 
 
664
 
}
665
 
 
666
 
void Grid::simplify()
667
 
{
668
 
    extendLeft();
669
 
    extendRight();
670
 
    extendUp();
671
 
    extendDown();
672
 
    merge();
673
 
}
674
 
 
675
 
 
676
 
void Grid::merge()
677
 
{
678
 
    int r,c;
679
 
    for ( c = 0; c < ncols; c++ )
680
 
        cols[c] = FALSE;
681
 
 
682
 
    for ( r = 0; r < nrows; r++ )
683
 
        rows[r] = FALSE;
684
 
 
685
 
    for ( c = 0; c < ncols; c++ ) {
686
 
        for ( r = 0; r < nrows; r++ ) {
687
 
            if ( isWidgetTopLeft( r, c ) ) {
688
 
                rows[r] = TRUE;
689
 
                cols[c] = TRUE;
690
 
            }
691
 
        }
692
 
    }
693
 
}
694
 
 
695
 
bool Grid::locateWidget( QWidget* w, int& row, int& col, int& rowspan, int & colspan )
696
 
{
697
 
    int r,c, r2, c2;
698
 
    for ( c = 0; c < ncols; c++ ) {
699
 
        for ( r = 0; r < nrows; r++ ) {
700
 
            if ( cell( r, c ) == w  ) {
701
 
                row = 0;
702
 
                for ( r2 = 1; r2 <= r; r2++ ) {
703
 
                    if ( rows[ r2-1 ] )
704
 
                        row++;
705
 
                }
706
 
                col = 0;
707
 
                for ( c2 = 1; c2 <= c; c2++ ) {
708
 
                    if ( cols[ c2-1 ] )
709
 
                        col++;
710
 
                }
711
 
                rowspan = 0;
712
 
                for ( r2 = r ; r2 < nrows && cell( r2, c) == w; r2++ ) {
713
 
                    if ( rows[ r2 ] )
714
 
                        rowspan++;
715
 
                }
716
 
                colspan = 0;
717
 
                for ( c2 = c; c2 < ncols && cell( r, c2) == w; c2++ ) {
718
 
                    if ( cols[ c2] )
719
 
                        colspan++;
720
 
                }
721
 
                return TRUE;
722
 
            }
723
 
        }
724
 
    }
725
 
    return FALSE;
726
 
}
727
 
 
728
 
 
729
 
 
730
 
 
731
 
GridLayout::GridLayout( const QWidgetList &wl, QWidget *p, FormWindow *fw, QWidget *lb, const QSize &res, bool doSetup )
732
 
    : Layout( wl, p, fw, lb, doSetup ), resolution( res )
733
 
{
734
 
    grid = 0;
735
 
    if ( doSetup )
736
 
        setup();
737
 
}
738
 
 
739
 
GridLayout::~GridLayout()
740
 
{
741
 
    delete grid;
742
 
}
743
 
 
744
 
void GridLayout::doLayout()
745
 
{
746
 
    bool needMove, needReparent;
747
 
    if ( !prepareLayout( needMove, needReparent ) )
748
 
        return;
749
 
 
750
 
    QDesignerGridLayout *layout = (QDesignerGridLayout*)WidgetFactory::createLayout( layoutBase, 0, WidgetFactory::Grid );
751
 
 
752
 
    if ( !grid )
753
 
        buildGrid();
754
 
 
755
 
    QWidget* w;
756
 
    int r, c, rs, cs;
757
 
    for ( w = widgets.first(); w; w = widgets.next() ) {
758
 
        if ( grid->locateWidget( w, r, c, rs, cs) ) {
759
 
            if ( needReparent && w->parent() != layoutBase )
760
 
                w->reparent( layoutBase, 0, QPoint( 0, 0 ), FALSE );
761
 
            if ( rs * cs == 1 ) {
762
 
                layout->addWidget( w, r, c, ::qt_cast<Spacer*>(w) ? ( (Spacer*)w )->alignment() : 0 );
763
 
            } else {
764
 
                layout->addMultiCellWidget( w, r, r+rs-1, c, c+cs-1, ::qt_cast<Spacer*>(w) ? ( (Spacer*)w )->alignment() : 0 );
765
 
            }
766
 
            if ( ::qt_cast<QLayoutWidget*>(w) )
767
 
                ( (QLayoutWidget*)w )->updateSizePolicy();
768
 
            w->show();
769
 
        } else {
770
 
            qWarning("ooops, widget '%s' does not fit in layout", w->name() );
771
 
        }
772
 
    }
773
 
    finishLayout( needMove, layout );
774
 
}
775
 
 
776
 
void GridLayout::setup()
777
 
{
778
 
    Layout::setup();
779
 
    buildGrid();
780
 
}
781
 
 
782
 
void GridLayout::buildGrid()
783
 
{
784
 
    if ( !widgets.count() )
785
 
        return;
786
 
 
787
 
    // Pixel to cell conversion:
788
 
    // By keeping a list of start'n'stop values (x & y) for each widget,
789
 
    // it is possible to create a very small grid of cells to represent
790
 
    // the widget layout.
791
 
    // -----------------------------------------------------------------
792
 
 
793
 
    // We need a list of both start and stop values for x- & y-axis
794
 
    QValueVector<int> x( widgets.count()*2 );
795
 
    QValueVector<int> y( widgets.count()*2 );
796
 
 
797
 
    // Using push_back would look nicer, but operator[] is much faster
798
 
    int index  = 0;
799
 
    QWidget* w = 0;
800
 
    for ( w = widgets.first(); w; w = widgets.next() ) {
801
 
        QRect widgetPos = w->geometry();
802
 
        x[index]   = widgetPos.left();
803
 
        x[index+1] = widgetPos.right();
804
 
        y[index]   = widgetPos.top();
805
 
        y[index+1] = widgetPos.bottom();
806
 
        index += 2;
807
 
    }
808
 
 
809
 
    qHeapSort(x);
810
 
    qHeapSort(y);
811
 
 
812
 
    // Remove duplicate x enteries (Remove next, if equal to current)
813
 
    if ( !x.empty() ) {
814
 
        for (QValueVector<int>::iterator current = x.begin() ;
815
 
             (current != x.end()) && ((current+1) != x.end()) ; )
816
 
            if ( (*current == *(current+1)) )
817
 
                x.erase(current+1);
818
 
            else
819
 
                current++;
820
 
    }
821
 
 
822
 
    // Remove duplicate y enteries (Remove next, if equal to current)
823
 
    if ( !y.empty() ) {
824
 
        for (QValueVector<int>::iterator current = y.begin() ;
825
 
             (current != y.end()) && ((current+1) != y.end()) ; )
826
 
            if ( (*current == *(current+1)) )
827
 
                y.erase(current+1);
828
 
            else
829
 
                current++;
830
 
    }
831
 
 
832
 
    // Create the smallest grid possible to represent the current layout
833
 
    // Since no widget will be placed in the last row and column, we'll
834
 
    // skip them to increase speed even further
835
 
    delete grid;
836
 
    grid = new Grid( y.size()-1, x.size()-1 );
837
 
 
838
 
    // Mark the cells in the grid that contains a widget
839
 
    for ( w = widgets.first(); w; w = widgets.next() ) {
840
 
        QRect c(0,0,0,0), widgetPos = w->geometry();
841
 
        // From left til right (not including)
842
 
        for (uint cw=0; cw<x.size(); cw++) {
843
 
            if ( x[cw] == widgetPos.left() )
844
 
                c.setLeft(cw);
845
 
            if ( x[cw] <  widgetPos.right())
846
 
                c.setRight(cw);
847
 
        }
848
 
        // From top til bottom (not including)
849
 
        for (uint ch=0; ch<y.size(); ch++) {
850
 
            if ( y[ch] == widgetPos.top()    )
851
 
                c.setTop(ch);
852
 
            if ( y[ch] <  widgetPos.bottom() )
853
 
                c.setBottom(ch);
854
 
        }
855
 
        grid->setCells(c, w); // Mark cellblock
856
 
    }
857
 
    grid->simplify();
858
 
}
859
 
 
860
 
 
861
 
 
862
 
 
863
 
 
864
 
 
865
 
 
866
 
Spacer::Spacer( QWidget *parent, const char *name )
867
 
    : QWidget( parent, name, WMouseNoMask ),
868
 
      orient( Vertical ), interactive(TRUE), sh( QSize(20,20) )
869
 
{
870
 
    setSizeType( Expanding );
871
 
    setAutoMask( TRUE );
872
 
}
873
 
 
874
 
void Spacer::paintEvent( QPaintEvent * )
875
 
{
876
 
    QPainter p( this );
877
 
    p.setPen( Qt::blue );
878
 
 
879
 
    if ( orient == Horizontal ) {
880
 
        const int dist = 3;
881
 
        const int amplitude = QMIN( 3, height() / 3 );
882
 
        const int base = height() / 2;
883
 
        int i = 0;
884
 
        p.setPen( white );
885
 
        for ( i = 0; i < width() / 3 +2; ++i )
886
 
            p.drawLine( i * dist, base - amplitude, i * dist + dist / 2, base + amplitude );
887
 
        p.setPen( blue );
888
 
        for ( i = 0; i < width() / 3 +2; ++i )
889
 
            p.drawLine( i * dist + dist / 2, base + amplitude, i * dist + dist, base - amplitude );
890
 
        p.drawLine( 0, 0, 0, height() );
891
 
        p.drawLine( width() - 1, 0, width() - 1, height());
892
 
    } else {
893
 
        const int dist = 3;
894
 
        const int amplitude = QMIN( 3, width() / 3 );
895
 
        const int base = width() / 2;
896
 
        int i = 0;
897
 
        p.setPen( white );
898
 
        for ( i = 0; i < height() / 3 +2; ++i )
899
 
            p.drawLine( base - amplitude, i * dist, base + amplitude,i * dist + dist / 2 );
900
 
        p.setPen( blue );
901
 
        for ( i = 0; i < height() / 3 +2; ++i )
902
 
            p.drawLine( base + amplitude, i * dist + dist / 2, base - amplitude, i * dist + dist );
903
 
        p.drawLine( 0, 0, width(), 0 );
904
 
        p.drawLine( 0, height() - 1, width(), height() - 1 );
905
 
    }
906
 
}
907
 
 
908
 
void Spacer::resizeEvent( QResizeEvent* e)
909
 
{
910
 
    QWidget::resizeEvent( e );
911
 
    if ( !parentWidget() || WidgetFactory::layoutType( parentWidget() ) == WidgetFactory::NoLayout )
912
 
        sh = size();
913
 
}
914
 
 
915
 
void Spacer::updateMask()
916
 
{
917
 
    QRegion r( rect() );
918
 
    if ( orient == Horizontal ) {
919
 
        const int amplitude = QMIN( 3, height() / 3 );
920
 
        const int base = height() / 2;
921
 
        r = r.subtract( QRect(1, 0, width() - 2, base - amplitude ) );
922
 
        r = r.subtract( QRect(1, base + amplitude, width() - 2, height() - base - amplitude ) );
923
 
    } else {
924
 
        const int amplitude = QMIN( 3, width() / 3 );
925
 
        const int base = width() / 2;
926
 
        r = r.subtract( QRect(0, 1, base - amplitude, height() - 2 ) );
927
 
        r = r.subtract( QRect( base + amplitude, 1, width() - base - amplitude, height() - 2 ) );
928
 
    }
929
 
    setMask( r );
930
 
}
931
 
 
932
 
void Spacer::setSizeType( SizeType t )
933
 
{
934
 
    QSizePolicy sizeP;
935
 
    if ( orient == Vertical )
936
 
        sizeP = QSizePolicy( QSizePolicy::Minimum, (QSizePolicy::SizeType)t );
937
 
    else
938
 
        sizeP = QSizePolicy( (QSizePolicy::SizeType)t, QSizePolicy::Minimum );
939
 
    setSizePolicy( sizeP );
940
 
}
941
 
 
942
 
 
943
 
Spacer::SizeType Spacer::sizeType() const
944
 
{
945
 
    if ( orient == Vertical )
946
 
        return (SizeType)sizePolicy().verData();
947
 
    return (SizeType)sizePolicy().horData();
948
 
}
949
 
 
950
 
int Spacer::alignment() const
951
 
{
952
 
    if ( orient == Vertical )
953
 
        return AlignHCenter;
954
 
    return AlignVCenter;
955
 
}
956
 
 
957
 
QSize Spacer::minimumSize() const
958
 
{
959
 
    QSize s = QSize( 20,20 );
960
 
    if ( sizeType() == Expanding )
961
 
        if ( orient == Vertical )
962
 
            s.rheight() = 0;
963
 
        else
964
 
            s.rwidth() = 0;
965
 
    return s;
966
 
}
967
 
 
968
 
QSize Spacer::sizeHint() const
969
 
{
970
 
    return sh;
971
 
}
972
 
 
973
 
 
974
 
void Spacer::setSizeHint( const QSize &s )
975
 
{
976
 
    sh = s;
977
 
    if ( !parentWidget() || WidgetFactory::layoutType( parentWidget() ) == WidgetFactory::NoLayout )
978
 
        resize( sizeHint() );
979
 
    updateGeometry();
980
 
}
981
 
 
982
 
Qt::Orientation Spacer::orientation() const
983
 
{
984
 
    return orient;
985
 
}
986
 
 
987
 
void Spacer::setOrientation( Qt::Orientation o )
988
 
{
989
 
    if ( orient == o )
990
 
        return;
991
 
 
992
 
    SizeType st = sizeType();
993
 
    orient = o;
994
 
    setSizeType( st );
995
 
    if ( interactive ) {
996
 
        sh = QSize( sh.height(), sh.width() );
997
 
        if (!parentWidget() || WidgetFactory::layoutType( parentWidget() ) == WidgetFactory::NoLayout )
998
 
            resize( height(), width() );
999
 
    }
1000
 
    updateMask();
1001
 
    update();
1002
 
    updateGeometry();
1003
 
}
1004
 
 
1005
 
 
1006
 
void QDesignerGridLayout::addWidget( QWidget *w, int row, int col, int align_ )
1007
 
{
1008
 
    items.insert( w, Item(row, col, 1, 1) );
1009
 
    QGridLayout::addWidget( w, row, col, align_ );
1010
 
}
1011
 
 
1012
 
void QDesignerGridLayout::addMultiCellWidget( QWidget *w, int fromRow, int toRow,
1013
 
                                              int fromCol, int toCol, int align_ )
1014
 
{
1015
 
    items.insert( w, Item(fromRow, fromCol, toRow - fromRow + 1, toCol - fromCol +1) );
1016
 
    QGridLayout::addMultiCellWidget( w, fromRow, toRow, fromCol, toCol, align_ );
1017
 
}