~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/kernel/qstackedlayout.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the gui module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qstackedlayout.h"
 
30
#include "qlayout_p.h"
 
31
 
 
32
#include <qlist.h>
 
33
#include <qwidget.h>
 
34
 
 
35
class QStackedLayoutPrivate : public QLayoutPrivate
 
36
{
 
37
    Q_DECLARE_PUBLIC(QStackedLayout)
 
38
public:
 
39
    QStackedLayoutPrivate() : index(-1) {}
 
40
    QList<QLayoutItem *> list;
 
41
    int index;
 
42
};
 
43
 
 
44
/*!
 
45
    \class QStackedLayout
 
46
 
 
47
    \brief The QStackedLayout class provides a stack of widgets where
 
48
    only one widget is visible at a time.
 
49
 
 
50
    \ingroup geomanagement
 
51
    \ingroup appearance
 
52
    \mainclass
 
53
 
 
54
    QStackedLayout can be used to create a user interface similar to
 
55
    the one provided by QTabWidget. There is also a convenience
 
56
    QStackedWidget class built on top of QStackedLayout.
 
57
 
 
58
    A QStackedLayout can be populated with a number of child widgets
 
59
    ("pages"):
 
60
 
 
61
    \code
 
62
        QWidget *firstPageWidget = new QWidget;
 
63
        QWidget *secondPageWidget = new QWidget;
 
64
        QWidget *thirdPageWidget = new QWidget;
 
65
        ...
 
66
 
 
67
        QStackedLayout *layout = new QStackedLayout;
 
68
        layout->addWidget(firstPageWidget);
 
69
        layout->addWidget(secondPageWidget);
 
70
        layout->addWidget(thirdPageWidget);
 
71
        setLayout(layout);
 
72
    \endcode
 
73
 
 
74
    When inserted, the widgets are added to an internal list. The
 
75
    indexOf() function returns the index of a widget in that list.
 
76
    The widget() function returns the widget at a given index
 
77
    position. The index of the widget that is shown on screen is
 
78
    given by currentIndex() and can be changed using setCurrentIndex().
 
79
 
 
80
    QStackedLayout provides no intrinsic means for the user to switch
 
81
    page. This is typically done through a QComboBox or a QListWidget
 
82
    that stores the titles of the QStackedLayout's pages. For
 
83
    example:
 
84
 
 
85
    \code
 
86
        QComboBox *pageComboBox = new QComboBox;
 
87
        pageComboBox->addItem(tr("Page 1"));
 
88
        pageComboBox->addItem(tr("Page 2"));
 
89
        pageComboBox->addItem(tr("Page 3"));
 
90
        connect(pageComboBox, SIGNAL(activated(int)),
 
91
                layout, SLOT(setCurrentIndex(int)));
 
92
    \endcode
 
93
 
 
94
    \sa QStackedWidget, QTabWidget
 
95
*/
 
96
 
 
97
/*!
 
98
    \fn void QStackedLayout::currentChanged(int index)
 
99
 
 
100
    This signal is emitted when the current widget in the layout changes.
 
101
    The \a index specifies the index of the new current widget.
 
102
 
 
103
    \sa currentWidget(), setCurrentWidget()
 
104
*/
 
105
 
 
106
/*!
 
107
    \fn void QStackedLayout::widgetRemoved(int index)
 
108
 
 
109
    This signal is emitted when the widget at position \a index
 
110
    is removed from the layout.
 
111
 
 
112
    \sa removeWidget()
 
113
*/
 
114
 
 
115
/*!
 
116
    Constructs a QStackedLayout with no parent.
 
117
 
 
118
    This QStackedLayout must be added to another layout later on to
 
119
    become effective.
 
120
*/
 
121
QStackedLayout::QStackedLayout()
 
122
    : QLayout(*new QStackedLayoutPrivate, 0, 0)
 
123
{
 
124
}
 
125
 
 
126
/*!
 
127
    Constructs a new QStackedLayout with the given \a parent.
 
128
 
 
129
    This layout will install itself on the \a parent widget and
 
130
    manage the geometry of its children.
 
131
*/
 
132
QStackedLayout::QStackedLayout(QWidget *parent)
 
133
    : QLayout(*new QStackedLayoutPrivate, 0, parent)
 
134
{
 
135
}
 
136
 
 
137
/*!
 
138
    Constructs a new QStackedLayout and inserts it into
 
139
    the given \a parentLayout.
 
140
*/
 
141
QStackedLayout::QStackedLayout(QLayout *parentLayout)
 
142
    : QLayout(*new QStackedLayoutPrivate, parentLayout, 0)
 
143
{
 
144
}
 
145
 
 
146
/*!
 
147
    Destroys this QStackedLayout.
 
148
 
 
149
    The layout's widgets are \e not destroyed.
 
150
*/
 
151
QStackedLayout::~QStackedLayout()
 
152
{
 
153
    Q_D(QStackedLayout);
 
154
    qDeleteAll(d->list);
 
155
}
 
156
 
 
157
/*!
 
158
    Adds \a widget to the end of this layout and returns the
 
159
    index position of \a widget.
 
160
 
 
161
    If the QStackedLayout is empty before this function is called,
 
162
    \a widget becomes the current widget.
 
163
 
 
164
    \sa insertWidget(), removeWidget(), currentWidget()
 
165
*/
 
166
int QStackedLayout::addWidget(QWidget *widget)
 
167
{
 
168
    Q_D(QStackedLayout);
 
169
    return insertWidget(d->list.count(), widget);
 
170
}
 
171
 
 
172
/*!
 
173
    Inserts \a widget at position \a index in this QStackedLayout. If
 
174
    \a index is out of range, the widget is appended. Returns the
 
175
    actual index of \a widget.
 
176
 
 
177
    If the QStackedLayout is empty before this function is called,
 
178
    \a widget becomes the current widget.
 
179
 
 
180
    \sa addWidget()
 
181
*/
 
182
int QStackedLayout::insertWidget(int index, QWidget *widget)
 
183
{
 
184
    Q_D(QStackedLayout);
 
185
    addChildWidget(widget);
 
186
    index = qMin(index, d->list.count());
 
187
    if (index < 0)
 
188
        index = d->list.count();
 
189
    QWidgetItem *wi = new QWidgetItem(widget);
 
190
    d->list.insert(index, wi);
 
191
    invalidate();
 
192
    if (d->index < 0) {
 
193
        setCurrentIndex(index);
 
194
    } else {
 
195
        widget->hide();
 
196
        widget->lower();
 
197
    }
 
198
    return index;
 
199
}
 
200
 
 
201
/*!
 
202
    \reimp
 
203
*/
 
204
QLayoutItem *QStackedLayout::itemAt(int index) const
 
205
{
 
206
    Q_D(const QStackedLayout);
 
207
    return d->list.value(index);
 
208
}
 
209
 
 
210
/*!
 
211
    \reimp
 
212
*/
 
213
QLayoutItem *QStackedLayout::takeAt(int index)
 
214
{
 
215
    Q_D(QStackedLayout);
 
216
    if (index <0 || index >= d->list.size())
 
217
        return 0;
 
218
    QLayoutItem *item = d->list.takeAt(index);
 
219
    if (index == d->index) {
 
220
        d->index = -1;
 
221
        if ( d->list.count() > 0 ) {
 
222
            int newIndex = index > 0 ? index - 1 : 0;
 
223
            setCurrentIndex(newIndex);
 
224
        }
 
225
    } else if (index < d->index) {
 
226
        --d->index;
 
227
    }
 
228
    emit widgetRemoved(index);
 
229
    return item;
 
230
}
 
231
 
 
232
/*!
 
233
    \property QStackedLayout::currentIndex
 
234
    \brief the index position of the widget that is visible
 
235
 
 
236
    The current index is -1 if there is no current widget.
 
237
 
 
238
    \sa currentWidget(), indexOf()
 
239
*/
 
240
void QStackedLayout::setCurrentIndex(int index)
 
241
{
 
242
    Q_D(QStackedLayout);
 
243
    QWidget *prev = currentWidget();
 
244
    QWidget *next = widget(index);
 
245
    if (!next || next == prev)
 
246
        return;
 
247
 
 
248
    bool reenableUpdates = false;
 
249
    QWidget *parent = parentWidget();
 
250
 
 
251
    if (parent && parent->updatesEnabled()) {
 
252
        reenableUpdates = true;
 
253
        parent->setUpdatesEnabled(false);
 
254
    }
 
255
 
 
256
    d->index = index;
 
257
    next->raise();
 
258
    next->show();
 
259
 
 
260
    // try to move focus onto the incoming widget if focus
 
261
    // was somewhere on the outgoing widget.
 
262
 
 
263
    if (parent) {
 
264
        QWidget * fw = parent->window()->focusWidget();
 
265
        if (prev->isAncestorOf(fw)) { // focus was on old page
 
266
            // look for the best focus widget we can find
 
267
            if (QWidget *nfw = next->focusWidget())
 
268
                nfw->setFocus();
 
269
            else {
 
270
                // second best: first child widget in the focus chain
 
271
                QWidget *i = fw;
 
272
                while ((i = i->nextInFocusChain()) != fw) {
 
273
                    if (((i->focusPolicy() & Qt::TabFocus) == Qt::TabFocus)
 
274
                        && !i->focusProxy() && i->isVisibleTo(next) && i->isEnabled()
 
275
                        && next->isAncestorOf(i)) {
 
276
                        i->setFocus();
 
277
                        break;
 
278
                    }
 
279
                }
 
280
                // third best: incoming widget
 
281
                if (i == fw )
 
282
                    next->setFocus();
 
283
            }
 
284
        }
 
285
    }
 
286
    if (prev)
 
287
        prev->hide();
 
288
    if (reenableUpdates)
 
289
        parent->setUpdatesEnabled(true);
 
290
    emit currentChanged(index);
 
291
}
 
292
 
 
293
int QStackedLayout::currentIndex() const
 
294
{
 
295
    Q_D(const QStackedLayout);
 
296
    return d->index;
 
297
}
 
298
 
 
299
 
 
300
/*!
 
301
  \fn void QStackedLayout::setCurrentWidget(QWidget *widget)
 
302
 
 
303
  Sets the current widget to the \a widget specified. The new widget
 
304
  must already be contained in this stacked layout.
 
305
 
 
306
  \sa setCurrentIndex(), currentWidget()
 
307
 */
 
308
void QStackedLayout::setCurrentWidget(QWidget *widget)
 
309
{
 
310
    Q_ASSERT_X(indexOf(widget) >= 0, "QStackedLayout::setCurrentWidget", "widget not contained in stack");
 
311
    setCurrentIndex(indexOf(widget));
 
312
}
 
313
 
 
314
 
 
315
/*!
 
316
    Returns the current widget, or 0 if there are no widgets in this
 
317
    layout.
 
318
 
 
319
    Equivalent to widget(currentIndex()).
 
320
 
 
321
    \sa currentIndex()
 
322
*/
 
323
QWidget *QStackedLayout::currentWidget() const
 
324
{
 
325
    Q_D(const QStackedLayout);
 
326
    return d->index >= 0 ? d->list.at(d->index)->widget() : 0;
 
327
}
 
328
 
 
329
/*!
 
330
    Returns the widget at position \a index, or 0 if there is no
 
331
    widget at the given position.
 
332
 
 
333
    \sa currentWidget(), indexOf()
 
334
*/
 
335
QWidget *QStackedLayout::widget(int index) const
 
336
{
 
337
    Q_D(const QStackedLayout);
 
338
     if (index < 0 || index >= d->list.size())
 
339
        return 0;
 
340
    return d->list.at(index)->widget();
 
341
}
 
342
 
 
343
/*!
 
344
    \property QStackedLayout::count
 
345
    \brief the number of widgets contained in the layout
 
346
*/
 
347
int QStackedLayout::count() const
 
348
{
 
349
    Q_D(const QStackedLayout);
 
350
    return d->list.size();
 
351
}
 
352
 
 
353
 
 
354
/*!
 
355
    \reimp
 
356
*/
 
357
void QStackedLayout::addItem(QLayoutItem *item)
 
358
{
 
359
    QWidget *widget = item->widget();
 
360
    if (widget) {
 
361
        addWidget(widget);
 
362
        delete item;
 
363
    } else {
 
364
        qWarning("QStackedLayout::addItem: Only widgets can be added");
 
365
    }
 
366
}
 
367
 
 
368
/*!
 
369
    \reimp
 
370
*/
 
371
QSize QStackedLayout::sizeHint() const
 
372
{
 
373
    Q_D(const QStackedLayout);
 
374
    QSize s(0, 0);
 
375
    int n = d->list.count();
 
376
 
 
377
    for (int i = 0; i < n; ++i)
 
378
        if (QWidget *widget = d->list.at(i)->widget())
 
379
            s = s.expandedTo(widget->sizeHint());
 
380
    return s;
 
381
}
 
382
 
 
383
/*!
 
384
    \reimp
 
385
*/
 
386
QSize QStackedLayout::minimumSize() const
 
387
{
 
388
    Q_D(const QStackedLayout);
 
389
    QSize s(0, 0);
 
390
    int n = d->list.count();
 
391
 
 
392
    for (int i = 0; i < n; ++i)
 
393
        if (QWidget *widget = d->list.at(i)->widget())
 
394
            s = s.expandedTo(widget->minimumSizeHint());
 
395
    return s;
 
396
}
 
397
 
 
398
/*!
 
399
    \reimp
 
400
*/
 
401
void QStackedLayout::setGeometry(const QRect &rect)
 
402
{
 
403
    QWidget *widget = currentWidget();
 
404
    if (widget)
 
405
        widget->setGeometry(rect);
 
406
}