1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the widgets module of the Qt Toolkit.
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.
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.
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.
21
** Contact info@trolltech.com if any conditions of this licensing are
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.
27
****************************************************************************/
29
#include "qscrollarea.h"
30
#include "qscrollbar.h"
31
#include "private/qabstractscrollarea_p.h"
33
#include "private/qlayoutengine_p.h"
34
class QScrollAreaPrivate: public QAbstractScrollAreaPrivate
36
Q_DECLARE_PUBLIC(QScrollArea)
39
QScrollAreaPrivate(): resizable(false){}
40
void updateScrollBars();
41
QPointer<QWidget> widget;
42
mutable QSize widgetSize;
48
\brief The QScrollArea class provides a scrolling view onto another widget.
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
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.
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.
72
Constructs a scroll area with the given \a parent, and with no
73
widget; see setWidget().
75
QScrollArea::QScrollArea(QWidget *parent)
76
:QAbstractScrollArea(*new QScrollAreaPrivate,parent)
79
d->viewport->setBackgroundRole(QPalette::NoRole);
80
d->vbar->setSingleStep(20);
81
d->hbar->setSingleStep(20);
86
Destroys the scroll area.
88
QScrollArea::~QScrollArea()
92
void QScrollAreaPrivate::updateScrollBars()
97
QSize p = viewport->size();
98
QSize m = q->maximumViewportSize();
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
107
widget->resize(p.expandedTo(min).boundedTo(max));
108
QSize v = widget->size();
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());
117
Returns the view widget's widget, or 0 if there is none.
122
QWidget *QScrollArea::widget() const
124
Q_D(const QScrollArea);
129
Set's the view widget's widget to \a w.
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.
136
void QScrollArea::setWidget(QWidget *w)
139
if (w == d->widget || !w)
144
d->hbar->setValue(0);
145
d->vbar->setValue(0);
146
if (w->parentWidget() != d->viewport)
147
w->setParent(d->viewport);
150
if (!w->testAttribute(Qt::WA_Resized))
151
w->resize(w->sizeHint());
153
w->installEventFilter(this);
154
d->widgetSize = QSize();
155
d->updateScrollBars();
159
/*! Removes the view widget's widget from the view, and passes
160
ownership of the widget to the caller.
162
QWidget *QScrollArea::takeWidget()
165
QWidget *w = d->widget;
174
bool QScrollArea::event(QEvent *e)
177
if (e->type() == QEvent::StyleChange) {
178
d->updateScrollBars();
180
return QAbstractScrollArea::event(e);
186
bool QScrollArea::eventFilter(QObject *o, QEvent *e)
189
if (o == d->widget && e->type() == QEvent::Resize)
190
d->updateScrollBars();
196
void QScrollArea::resizeEvent(QResizeEvent *)
199
d->updateScrollBars();
205
void QScrollArea::scrollContentsBy(int, int)
210
d->widget->move(-d->hbar->value(), -d->vbar->value());
215
\property QScrollArea::widgetResizable
216
\brief whether the scroll area should resize the view widget
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.
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.
227
bool QScrollArea::widgetResizable() const
229
Q_D(const QScrollArea);
233
void QScrollArea::setWidgetResizable(bool resizable)
236
d->resizable = resizable;
238
d->updateScrollBars();
243
QSize QScrollArea::sizeHint() const
245
Q_D(const QScrollArea);
246
int f = 2 * d->frameWidth;
248
int h = fontMetrics().height();
250
if (!d->widgetSize.isValid())
251
d->widgetSize = d->resizable ? d->widget->sizeHint() : d->widget->size();
254
sz += QSize(12 * h, 8 * h);
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));
267
bool QScrollArea::focusNextPrevChild(bool next)
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());