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

« back to all changes in this revision

Viewing changes to src/gui/widgets/qscrollarea.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 widgets 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 "qscrollarea.h"
 
30
#include "qscrollbar.h"
 
31
#include "private/qabstractscrollarea_p.h"
 
32
#include "qlayout.h"
 
33
#include "private/qlayoutengine_p.h"
 
34
class QScrollAreaPrivate: public QAbstractScrollAreaPrivate
 
35
{
 
36
    Q_DECLARE_PUBLIC(QScrollArea)
 
37
 
 
38
public:
 
39
    QScrollAreaPrivate(): resizable(false){}
 
40
    void updateScrollBars();
 
41
    QPointer<QWidget> widget;
 
42
    mutable QSize widgetSize;
 
43
    bool resizable;
 
44
};
 
45
 
 
46
/*!
 
47
    \class QScrollArea
 
48
    \brief The QScrollArea class provides a scrolling view onto another widget.
 
49
 
 
50
    \ingroup basic
 
51
    \mainclass
 
52
 
 
53
    A scroll area is used to display the contents of a child widget within
 
54
    a frame. If the widget exceeds the size of the frame, the view can
 
55
    provide scroll bars so that the entire area of the child widget can be
 
56
    viewed.
 
57
 
 
58
    The child widget must be specified with setWidget(); it can be
 
59
    retrieved with widget(). The view can be made to be resizable with
 
60
    the setWidgetResizable() function.
 
61
 
 
62
    When using a scroll area to display the contents of a custom widget,
 
63
    it is important to ensure that the \l{QWidget::sizeHint}{size hint} of the
 
64
    child widget is set to a suitable value. If a standard QWidget is used
 
65
    for the child widget, it may be necessary to call
 
66
    QWidget::setMinimumSize() to ensure that the contents of the widget are
 
67
    shown correctly within the scroll area.
 
68
*/
 
69
 
 
70
 
 
71
/*!
 
72
    Constructs a scroll area with the given \a parent, and with no
 
73
    widget; see setWidget().
 
74
*/
 
75
QScrollArea::QScrollArea(QWidget *parent)
 
76
    :QAbstractScrollArea(*new QScrollAreaPrivate,parent)
 
77
{
 
78
    Q_D(QScrollArea);
 
79
    d->viewport->setBackgroundRole(QPalette::NoRole);
 
80
    d->vbar->setSingleStep(20);
 
81
    d->hbar->setSingleStep(20);
 
82
    d->layoutChildren();
 
83
}
 
84
 
 
85
/*!
 
86
    Destroys the scroll area.
 
87
*/
 
88
QScrollArea::~QScrollArea()
 
89
{
 
90
}
 
91
 
 
92
void QScrollAreaPrivate::updateScrollBars()
 
93
{
 
94
    Q_Q(QScrollArea);
 
95
    if (!widget)
 
96
        return;
 
97
    QSize p = viewport->size();
 
98
    QSize m = q->maximumViewportSize();
 
99
 
 
100
    QSize min = qSmartMinSize(widget);
 
101
    QSize max = qSmartMaxSize(widget);
 
102
    if ((resizable && m.expandedTo(min) == m && m.boundedTo(max) == m)
 
103
        || (!resizable && m.expandedTo(widget->size()) == m))
 
104
        p = m; // no scroll bars needed
 
105
 
 
106
    if (resizable)
 
107
        widget->resize(p.expandedTo(min).boundedTo(max));
 
108
    QSize v = widget->size();
 
109
 
 
110
    hbar->setRange(0, v.width() - p.width());
 
111
    hbar->setPageStep(p.width());
 
112
    vbar->setRange(0, v.height() - p.height());
 
113
    vbar->setPageStep(p.height());
 
114
}
 
115
 
 
116
/*!
 
117
    Returns the view widget's widget, or 0 if there is none.
 
118
 
 
119
    \sa setWidget()
 
120
*/
 
121
 
 
122
QWidget *QScrollArea::widget() const
 
123
{
 
124
    Q_D(const QScrollArea);
 
125
    return d->widget;
 
126
}
 
127
 
 
128
/*!
 
129
    Set's the view widget's widget to \a w.
 
130
 
 
131
    \a w becomes a child of the scroll area, and will be destroyed
 
132
    when the scroll area is deleted or when a new view widget is set.
 
133
 
 
134
    \sa widget()
 
135
*/
 
136
void QScrollArea::setWidget(QWidget *w)
 
137
{
 
138
    Q_D(QScrollArea);
 
139
    if (w == d->widget || !w)
 
140
        return;
 
141
 
 
142
    delete d->widget;
 
143
    d->widget = 0;
 
144
    d->hbar->setValue(0);
 
145
    d->vbar->setValue(0);
 
146
    if (w->parentWidget() != d->viewport)
 
147
        w->setParent(d->viewport);
 
148
    else
 
149
        w->move(0,0);
 
150
     if (!w->testAttribute(Qt::WA_Resized))
 
151
         w->resize(w->sizeHint());
 
152
    d->widget = w;
 
153
    w->installEventFilter(this);
 
154
    d->widgetSize = QSize();
 
155
    d->updateScrollBars();
 
156
 
 
157
}
 
158
 
 
159
/*!  Removes the view widget's widget from the view, and passes
 
160
  ownership of the widget to the caller.
 
161
 */
 
162
QWidget *QScrollArea::takeWidget()
 
163
{
 
164
    Q_D(QScrollArea);
 
165
    QWidget *w = d->widget;
 
166
    d->widget = 0;
 
167
    if (w)
 
168
        w->setParent(0);
 
169
    return w;
 
170
}
 
171
 
 
172
/*!\reimp
 
173
 */
 
174
bool QScrollArea::event(QEvent *e)
 
175
{
 
176
    Q_D(QScrollArea);
 
177
    if (e->type() == QEvent::StyleChange) {
 
178
        d->updateScrollBars();
 
179
    }
 
180
    return QAbstractScrollArea::event(e);
 
181
}
 
182
 
 
183
 
 
184
/*!\reimp
 
185
 */
 
186
bool QScrollArea::eventFilter(QObject *o, QEvent *e)
 
187
{
 
188
    Q_D(QScrollArea);
 
189
    if (o == d->widget && e->type() == QEvent::Resize)
 
190
        d->updateScrollBars();
 
191
    return false;
 
192
}
 
193
 
 
194
/*! \reimp
 
195
 */
 
196
void QScrollArea::resizeEvent(QResizeEvent *)
 
197
{
 
198
    Q_D(QScrollArea);
 
199
    d->updateScrollBars();
 
200
}
 
201
 
 
202
 
 
203
/*!\reimp
 
204
 */
 
205
void QScrollArea::scrollContentsBy(int, int)
 
206
{
 
207
    Q_D(QScrollArea);
 
208
    if (!d->widget)
 
209
        return;
 
210
    d->widget->move(-d->hbar->value(), -d->vbar->value());
 
211
}
 
212
 
 
213
 
 
214
/*!
 
215
    \property QScrollArea::widgetResizable
 
216
    \brief whether the scroll area should resize the view widget
 
217
 
 
218
    If this property is set to false (the default), the view honors
 
219
    the size of its widget. Regardless of this property, you can
 
220
    programmatically resize the widget using widget()->resize(), and
 
221
    the scroll area will automatically adjust itself to the new size.
 
222
 
 
223
    If this property is set to true, the view will automatically
 
224
    resize the widget in order to avoid scroll bars where they can be
 
225
    avoided, or to take advantage of extra space.
 
226
*/
 
227
bool QScrollArea::widgetResizable() const
 
228
{
 
229
    Q_D(const QScrollArea);
 
230
    return d->resizable;
 
231
}
 
232
 
 
233
void QScrollArea::setWidgetResizable(bool resizable)
 
234
{
 
235
    Q_D(QScrollArea);
 
236
    d->resizable = resizable;
 
237
    updateGeometry();
 
238
    d->updateScrollBars();
 
239
}
 
240
 
 
241
/*!\reimp
 
242
 */
 
243
QSize QScrollArea::sizeHint() const
 
244
{
 
245
    Q_D(const QScrollArea);
 
246
    int f = 2 * d->frameWidth;
 
247
    QSize sz(f, f);
 
248
    int h = fontMetrics().height();
 
249
    if (d->widget) {
 
250
        if (!d->widgetSize.isValid())
 
251
            d->widgetSize = d->resizable ? d->widget->sizeHint() : d->widget->size();
 
252
        sz += d->widgetSize;
 
253
    } else {
 
254
        sz += QSize(12 * h, 8 * h);
 
255
    }
 
256
    if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
 
257
        sz.setWidth(sz.width() + d->vbar->sizeHint().width());
 
258
    if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
 
259
        sz.setHeight(sz.height() + d->hbar->sizeHint().height());
 
260
    return sz.boundedTo(QSize(36 * h, 24 * h));
 
261
}
 
262
 
 
263
 
 
264
 
 
265
/*!\reimp
 
266
 */
 
267
bool QScrollArea::focusNextPrevChild(bool next)
 
268
{
 
269
    Q_D(QScrollArea);
 
270
    if (QWidget::focusNextPrevChild(next)) {
 
271
        if (QWidget *fw = focusWidget()) {
 
272
            if (d->widget && fw != d->widget && d->widget->isAncestorOf(fw)) {
 
273
                QRect focusRect(fw->mapTo(d->widget, QPoint(0,0)), fw->size());
 
274
                QRect visibleRect(-d->widget->pos(), d->viewport->size());
 
275
                if (!visibleRect.contains(focusRect)) {
 
276
                    if (focusRect.right() > visibleRect.right())
 
277
                        d->hbar->setValue(focusRect.right() - d->viewport->width());
 
278
                    else if (focusRect.left() < visibleRect.left())
 
279
                        d->hbar->setValue(focusRect.left());
 
280
                    if (focusRect.bottom() > visibleRect.bottom())
 
281
                        d->vbar->setValue(focusRect.bottom() - d->viewport->height());
 
282
                    else if (focusRect.top() < visibleRect.top())
 
283
                        d->vbar->setValue(focusRect.top());
 
284
                }
 
285
            }
 
286
        }
 
287
        return true;
 
288
    }
 
289
    return false;
 
290
}