source: trunk/src/gui/widgets/qabstractscrollarea.cpp@ 1012

Last change on this file since 1012 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 45.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qabstractscrollarea.h"
43
44#ifndef QT_NO_SCROLLAREA
45
46#include "qscrollbar.h"
47#include "qapplication.h"
48#include "qstyle.h"
49#include "qstyleoption.h"
50#include "qevent.h"
51#include "qdebug.h"
52#include "qboxlayout.h"
53#include "qpainter.h"
54#include "qmargins.h"
55
56#include "qabstractscrollarea_p.h"
57#include <qwidget.h>
58
59#include <private/qapplication_p.h>
60
61#ifdef Q_WS_MAC
62#include <private/qt_mac_p.h>
63#include <private/qt_cocoa_helpers_mac_p.h>
64#endif
65
66QT_BEGIN_NAMESPACE
67
68/*!
69 \class QAbstractScrollArea
70 \brief The QAbstractScrollArea widget provides a scrolling area with
71 on-demand scroll bars.
72
73 \ingroup abstractwidgets
74
75 QAbstractScrollArea is a low-level abstraction of a scrolling
76 area. The area provides a central widget called the viewport, in
77 which the contents of the area is to be scrolled (i.e, the
78 visible parts of the contents are rendered in the viewport).
79
80 Next to the viewport is a vertical scroll bar, and below is a
81 horizontal scroll bar. When all of the area contents fits in the
82 viewport, each scroll bar can be either visible or hidden
83 depending on the scroll bar's Qt::ScrollBarPolicy. When a scroll
84 bar is hidden, the viewport expands in order to cover all
85 available space. When a scroll bar becomes visible again, the
86 viewport shrinks in order to make room for the scroll bar.
87
88 It is possible to reserve a margin area around the viewport, see
89 setViewportMargins(). The feature is mostly used to place a
90 QHeaderView widget above or beside the scrolling area. Subclasses
91 of QAbstractScrollArea should implement margins.
92
93 When inheriting QAbstractScrollArea, you need to do the
94 following:
95
96 \list
97 \o Control the scroll bars by setting their
98 range, value, page step, and tracking their
99 movements.
100 \o Draw the contents of the area in the viewport according
101 to the values of the scroll bars.
102 \o Handle events received by the viewport in
103 viewportEvent() - notably resize events.
104 \o Use \c{viewport->update()} to update the contents of the
105 viewport instead of \l{QWidget::update()}{update()}
106 as all painting operations take place on the viewport.
107 \endlist
108
109 With a scroll bar policy of Qt::ScrollBarAsNeeded (the default),
110 QAbstractScrollArea shows scroll bars when they provide a non-zero
111 scrolling range, and hides them otherwise.
112
113 The scroll bars and viewport should be updated whenever the viewport
114 receives a resize event or the size of the contents changes.
115 The viewport also needs to be updated when the scroll bars
116 values change. The initial values of the scroll bars are often
117 set when the area receives new contents.
118
119 We give a simple example, in which we have implemented a scroll area
120 that can scroll any QWidget. We make the widget a child of the
121 viewport; this way, we do not have to calculate which part of
122 the widget to draw but can simply move the widget with
123 QWidget::move(). When the area contents or the viewport size
124 changes, we do the following:
125
126 \snippet doc/src/snippets/myscrollarea.cpp 1
127
128 When the scroll bars change value, we need to update the widget
129 position, i.e., find the part of the widget that is to be drawn in
130 the viewport:
131
132 \snippet doc/src/snippets/myscrollarea.cpp 0
133
134 In order to track scroll bar movements, reimplement the virtual
135 function scrollContentsBy(). In order to fine-tune scrolling
136 behavior, connect to a scroll bar's
137 QAbstractSlider::actionTriggered() signal and adjust the \l
138 QAbstractSlider::sliderPosition as you wish.
139
140 For convenience, QAbstractScrollArea makes all viewport events
141 available in the virtual viewportEvent() handler. QWidget's
142 specialized handlers are remapped to viewport events in the cases
143 where this makes sense. The remapped specialized handlers are:
144 paintEvent(), mousePressEvent(), mouseReleaseEvent(),
145 mouseDoubleClickEvent(), mouseMoveEvent(), wheelEvent(),
146 dragEnterEvent(), dragMoveEvent(), dragLeaveEvent(), dropEvent(),
147 contextMenuEvent(), and resizeEvent().
148
149 QScrollArea, which inherits QAbstractScrollArea, provides smooth
150 scrolling for any QWidget (i.e., the widget is scrolled pixel by
151 pixel). You only need to subclass QAbstractScrollArea if you need
152 more specialized behavior. This is, for instance, true if the
153 entire contents of the area is not suitable for being drawn on a
154 QWidget or if you do not want smooth scrolling.
155
156 \sa QScrollArea
157*/
158
159QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate()
160 :hbar(0), vbar(0), vbarpolicy(Qt::ScrollBarAsNeeded), hbarpolicy(Qt::ScrollBarAsNeeded),
161 viewport(0), cornerWidget(0), left(0), top(0), right(0), bottom(0),
162 xoffset(0), yoffset(0), viewportFilter(0)
163#ifdef Q_WS_WIN
164 , singleFingerPanEnabled(false)
165#endif
166{
167}
168
169QAbstractScrollAreaScrollBarContainer::QAbstractScrollAreaScrollBarContainer(Qt::Orientation orientation, QWidget *parent)
170 :QWidget(parent), scrollBar(new QScrollBar(orientation, this)),
171 layout(new QBoxLayout(orientation == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom)),
172 orientation(orientation)
173{
174 setLayout(layout);
175 layout->setMargin(0);
176 layout->setSpacing(0);
177 layout->addWidget(scrollBar);
178}
179
180/*! \internal
181 Adds a widget to the scroll bar container.
182*/
183void QAbstractScrollAreaScrollBarContainer::addWidget(QWidget *widget, LogicalPosition position)
184{
185 QSizePolicy policy = widget->sizePolicy();
186 if (orientation == Qt::Vertical)
187 policy.setHorizontalPolicy(QSizePolicy::Ignored);
188 else
189 policy.setVerticalPolicy(QSizePolicy::Ignored);
190 widget->setSizePolicy(policy);
191 widget->setParent(this);
192
193 const int insertIndex = (position & LogicalLeft) ? 0 : scrollBarLayoutIndex() + 1;
194 layout->insertWidget(insertIndex, widget);
195}
196
197/*! \internal
198 Retuns a list of scroll bar widgets for the given position. The scroll bar
199 itself is not returned.
200*/
201QWidgetList QAbstractScrollAreaScrollBarContainer::widgets(LogicalPosition position)
202{
203 QWidgetList list;
204 const int scrollBarIndex = scrollBarLayoutIndex();
205 if (position == LogicalLeft) {
206 for (int i = 0; i < scrollBarIndex; ++i)
207 list.append(layout->itemAt(i)->widget());
208 } else if (position == LogicalRight) {
209 const int layoutItemCount = layout->count();
210 for (int i = scrollBarIndex + 1; i < layoutItemCount; ++i)
211 list.append(layout->itemAt(i)->widget());
212 }
213 return list;
214}
215
216/*! \internal
217 Returns the layout index for the scroll bar. This needs to be
218 recalculated by a linear search for each use, since items in
219 the layout can be removed at any time (i.e. when a widget is
220 deleted or re-parented).
221*/
222int QAbstractScrollAreaScrollBarContainer::scrollBarLayoutIndex() const
223{
224 const int layoutItemCount = layout->count();
225 for (int i = 0; i < layoutItemCount; ++i) {
226 if (qobject_cast<QScrollBar *>(layout->itemAt(i)->widget()))
227 return i;
228 }
229 return -1;
230}
231
232/*! \internal
233*/
234void QAbstractScrollAreaPrivate::replaceScrollBar(QScrollBar *scrollBar,
235 Qt::Orientation orientation)
236{
237 Q_Q(QAbstractScrollArea);
238
239 QAbstractScrollAreaScrollBarContainer *container = scrollBarContainers[orientation];
240 bool horizontal = (orientation == Qt::Horizontal);
241 QScrollBar *oldBar = horizontal ? hbar : vbar;
242 if (horizontal)
243 hbar = scrollBar;
244 else
245 vbar = scrollBar;
246 scrollBar->setParent(container);
247 container->scrollBar = scrollBar;
248 container->layout->removeWidget(oldBar);
249 container->layout->insertWidget(0, scrollBar);
250 scrollBar->setVisible(oldBar->isVisibleTo(container));
251 scrollBar->setInvertedAppearance(oldBar->invertedAppearance());
252 scrollBar->setInvertedControls(oldBar->invertedControls());
253 scrollBar->setRange(oldBar->minimum(), oldBar->maximum());
254 scrollBar->setOrientation(oldBar->orientation());
255 scrollBar->setPageStep(oldBar->pageStep());
256 scrollBar->setSingleStep(oldBar->singleStep());
257 scrollBar->setSliderDown(oldBar->isSliderDown());
258 scrollBar->setSliderPosition(oldBar->sliderPosition());
259 scrollBar->setTracking(oldBar->hasTracking());
260 scrollBar->setValue(oldBar->value());
261 delete oldBar;
262
263 QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
264 q, horizontal ? SLOT(_q_hslide(int)) : SLOT(_q_vslide(int)));
265 QObject::connect(scrollBar, SIGNAL(rangeChanged(int,int)),
266 q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
267}
268
269void QAbstractScrollAreaPrivate::init()
270{
271 Q_Q(QAbstractScrollArea);
272 viewport = new QWidget(q);
273 viewport->setObjectName(QLatin1String("qt_scrollarea_viewport"));
274 viewport->setBackgroundRole(QPalette::Base);
275 viewport->setAutoFillBackground(true);
276 scrollBarContainers[Qt::Horizontal] = new QAbstractScrollAreaScrollBarContainer(Qt::Horizontal, q);
277 scrollBarContainers[Qt::Horizontal]->setObjectName(QLatin1String("qt_scrollarea_hcontainer"));
278 hbar = scrollBarContainers[Qt::Horizontal]->scrollBar;
279 hbar->setRange(0,0);
280 scrollBarContainers[Qt::Horizontal]->setVisible(false);
281 QObject::connect(hbar, SIGNAL(valueChanged(int)), q, SLOT(_q_hslide(int)));
282 QObject::connect(hbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
283 scrollBarContainers[Qt::Vertical] = new QAbstractScrollAreaScrollBarContainer(Qt::Vertical, q);
284 scrollBarContainers[Qt::Vertical]->setObjectName(QLatin1String("qt_scrollarea_vcontainer"));
285 vbar = scrollBarContainers[Qt::Vertical]->scrollBar;
286 vbar->setRange(0,0);
287 scrollBarContainers[Qt::Vertical]->setVisible(false);
288 QObject::connect(vbar, SIGNAL(valueChanged(int)), q, SLOT(_q_vslide(int)));
289 QObject::connect(vbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
290 viewportFilter.reset(new QAbstractScrollAreaFilter(this));
291 viewport->installEventFilter(viewportFilter.data());
292 viewport->setFocusProxy(q);
293 q->setFocusPolicy(Qt::WheelFocus);
294 q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
295 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
296 layoutChildren();
297#ifndef Q_WS_MAC
298#ifndef QT_NO_GESTURES
299 viewport->grabGesture(Qt::PanGesture);
300#endif
301#endif
302}
303
304#ifdef Q_WS_WIN
305void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on)
306{
307 singleFingerPanEnabled = on;
308 QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport));
309 if (dd)
310 dd->winSetupGestures();
311}
312#endif // Q_WS_WIN
313
314void QAbstractScrollAreaPrivate::layoutChildren()
315{
316 Q_Q(QAbstractScrollArea);
317 bool needh = (hbarpolicy == Qt::ScrollBarAlwaysOn
318 || (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum()));
319
320 bool needv = (vbarpolicy == Qt::ScrollBarAlwaysOn
321 || (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum()));
322
323#ifdef Q_WS_MAC
324 QWidget * const window = q->window();
325
326 // Use small scroll bars for tool windows, to match the native size grip.
327 bool hbarIsSmall = hbar->testAttribute(Qt::WA_MacSmallSize);
328 bool vbarIsSmall = vbar->testAttribute(Qt::WA_MacSmallSize);
329 const Qt::WindowType windowType = window->windowType();
330 if (windowType == Qt::Tool) {
331 if (!hbarIsSmall) {
332 hbar->setAttribute(Qt::WA_MacMiniSize, false);
333 hbar->setAttribute(Qt::WA_MacNormalSize, false);
334 hbar->setAttribute(Qt::WA_MacSmallSize, true);
335 }
336 if (!vbarIsSmall) {
337 vbar->setAttribute(Qt::WA_MacMiniSize, false);
338 vbar->setAttribute(Qt::WA_MacNormalSize, false);
339 vbar->setAttribute(Qt::WA_MacSmallSize, true);
340 }
341 } else {
342 if (hbarIsSmall) {
343 hbar->setAttribute(Qt::WA_MacMiniSize, false);
344 hbar->setAttribute(Qt::WA_MacNormalSize, false);
345 hbar->setAttribute(Qt::WA_MacSmallSize, false);
346 }
347 if (vbarIsSmall) {
348 vbar->setAttribute(Qt::WA_MacMiniSize, false);
349 vbar->setAttribute(Qt::WA_MacNormalSize, false);
350 vbar->setAttribute(Qt::WA_MacSmallSize, false);
351 }
352 }
353#endif
354
355 const int hsbExt = hbar->sizeHint().height();
356 const int vsbExt = vbar->sizeHint().width();
357 const QPoint extPoint(vsbExt, hsbExt);
358 const QSize extSize(vsbExt, hsbExt);
359
360 const QRect widgetRect = q->rect();
361 QStyleOption opt(0);
362 opt.init(q);
363
364 const bool hasCornerWidget = (cornerWidget != 0);
365
366// If the scroll bars are at the very right and bottom of the window we
367// move their positions to be aligned with the size grip.
368#ifdef Q_WS_MAC
369 // Check if a native sizegrip is present.
370 bool hasMacReverseSizeGrip = false;
371 bool hasMacSizeGrip = false;
372 bool nativeGripPresent = false;
373 if (q->testAttribute(Qt::WA_WState_Created))
374 nativeGripPresent = qt_mac_checkForNativeSizeGrip(q);
375
376 if (nativeGripPresent) {
377 // Look for a native size grip at the visual window bottom right and at the
378 // absolute window bottom right. In reverse mode, the native size grip does not
379 // swich side, so we need to check if it is on the "wrong side".
380 const QPoint scrollAreaBottomRight = q->mapTo(window, widgetRect.bottomRight() - QPoint(frameWidth, frameWidth));
381 const QPoint windowBottomRight = window->rect().bottomRight();
382 const QPoint visualWindowBottomRight = QStyle::visualPos(opt.direction, opt.rect, windowBottomRight);
383 const QPoint offset = windowBottomRight - scrollAreaBottomRight;
384 const QPoint visualOffset = visualWindowBottomRight - scrollAreaBottomRight;
385 hasMacSizeGrip = (visualOffset.manhattanLength() < vsbExt);
386 hasMacReverseSizeGrip = (hasMacSizeGrip == false && (offset.manhattanLength() < hsbExt));
387 }
388#endif
389
390 QPoint cornerOffset(needv ? vsbExt : 0, needh ? hsbExt : 0);
391 QRect controlsRect;
392 QRect viewportRect;
393
394 // In FrameOnlyAroundContents mode the frame is drawn between the controls and
395 // the viewport, else the frame rect is equal to the widget rect.
396 if ((frameStyle != QFrame::NoFrame) &&
397 q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, q)) {
398 controlsRect = widgetRect;
399 const int extra = q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, q);
400 const QPoint cornerExtra(needv ? extra : 0, needh ? extra : 0);
401 QRect frameRect = widgetRect;
402 frameRect.adjust(0, 0, -cornerOffset.x() - cornerExtra.x(), -cornerOffset.y() - cornerExtra.y());
403 q->setFrameRect(QStyle::visualRect(opt.direction, opt.rect, frameRect));
404 // The frame rect needs to be in logical coords, however we need to flip
405 // the contentsRect back before passing it on to the viewportRect
406 // since the viewportRect has its logical coords calculated later.
407 viewportRect = QStyle::visualRect(opt.direction, opt.rect, q->contentsRect());
408 } else {
409 q->setFrameRect(QStyle::visualRect(opt.direction, opt.rect, widgetRect));
410 controlsRect = q->contentsRect();
411 viewportRect = QRect(controlsRect.topLeft(), controlsRect.bottomRight() - cornerOffset);
412 }
413
414 // If we have a corner widget and are only showing one scroll bar, we need to move it
415 // to make room for the corner widget.
416 if (hasCornerWidget && (needv || needh))
417 cornerOffset = extPoint;
418
419#ifdef Q_WS_MAC
420 // Also move the scroll bars if they are covered by the native Mac size grip.
421 if (hasMacSizeGrip)
422 cornerOffset = extPoint;
423#endif
424
425 // The corner point is where the scroll bar rects, the corner widget rect and the
426 // viewport rect meets.
427 const QPoint cornerPoint(controlsRect.bottomRight() + QPoint(1, 1) - cornerOffset);
428
429 // Some styles paints the corner if both scorllbars are showing and there is
430 // no corner widget. Also, on the Mac we paint if there is a native
431 // (transparent) sizegrip in the area where a corner widget would be.
432 if ((needv && needh && hasCornerWidget == false)
433 || ((needv || needh)
434#ifdef Q_WS_MAC
435 && hasMacSizeGrip
436#endif
437 )
438 ) {
439 cornerPaintingRect = QStyle::visualRect(opt.direction, opt.rect, QRect(cornerPoint, extSize));
440 } else {
441 cornerPaintingRect = QRect();
442 }
443
444#ifdef Q_WS_MAC
445 if (hasMacReverseSizeGrip)
446 reverseCornerPaintingRect = QRect(controlsRect.bottomRight() + QPoint(1, 1) - extPoint, extSize);
447 else
448 reverseCornerPaintingRect = QRect();
449#endif
450
451 if (needh) {
452 QRect horizontalScrollBarRect(QPoint(controlsRect.left(), cornerPoint.y()), QPoint(cornerPoint.x() - 1, controlsRect.bottom()));
453#ifdef Q_WS_MAC
454 if (hasMacReverseSizeGrip)
455 horizontalScrollBarRect.adjust(vsbExt, 0, 0, 0);
456#endif
457 scrollBarContainers[Qt::Horizontal]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, horizontalScrollBarRect));
458 scrollBarContainers[Qt::Horizontal]->raise();
459 }
460
461 if (needv) {
462 const QRect verticalScrollBarRect (QPoint(cornerPoint.x(), controlsRect.top()), QPoint(controlsRect.right(), cornerPoint.y() - 1));
463 scrollBarContainers[Qt::Vertical]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, verticalScrollBarRect));
464 scrollBarContainers[Qt::Vertical]->raise();
465 }
466
467 if (cornerWidget) {
468 const QRect cornerWidgetRect(cornerPoint, controlsRect.bottomRight());
469 cornerWidget->setGeometry(QStyle::visualRect(opt.direction, opt.rect, cornerWidgetRect));
470 }
471
472 scrollBarContainers[Qt::Horizontal]->setVisible(needh);
473 scrollBarContainers[Qt::Vertical]->setVisible(needv);
474
475 if (q->isRightToLeft())
476 viewportRect.adjust(right, top, -left, -bottom);
477 else
478 viewportRect.adjust(left, top, -right, -bottom);
479
480 viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last
481}
482
483/*!
484 \internal
485
486 Creates a new QAbstractScrollAreaPrivate, \a dd with the given \a parent.
487*/
488QAbstractScrollArea::QAbstractScrollArea(QAbstractScrollAreaPrivate &dd, QWidget *parent)
489 :QFrame(dd, parent)
490{
491 Q_D(QAbstractScrollArea);
492 QT_TRY {
493 d->init();
494 } QT_CATCH(...) {
495 d->viewportFilter.reset();
496 QT_RETHROW;
497 }
498}
499
500/*!
501 Constructs a viewport.
502
503 The \a parent arguments is sent to the QWidget constructor.
504*/
505QAbstractScrollArea::QAbstractScrollArea(QWidget *parent)
506 :QFrame(*new QAbstractScrollAreaPrivate, parent)
507{
508 Q_D(QAbstractScrollArea);
509 QT_TRY {
510 d->init();
511 } QT_CATCH(...) {
512 d->viewportFilter.reset();
513 QT_RETHROW;
514 }
515}
516
517
518/*!
519 Destroys the viewport.
520 */
521QAbstractScrollArea::~QAbstractScrollArea()
522{
523 Q_D(QAbstractScrollArea);
524 // reset it here, otherwise we'll have a dangling pointer in ~QWidget
525 d->viewportFilter.reset();
526}
527
528
529/*!
530 \since 4.2
531 Sets the viewport to be the given \a widget.
532 The QAbstractScrollArea will take ownership of the given \a widget.
533
534 If \a widget is 0, QAbstractScrollArea will assign a new QWidget instance
535 for the viewport.
536
537 \sa viewport()
538*/
539void QAbstractScrollArea::setViewport(QWidget *widget)
540{
541 Q_D(QAbstractScrollArea);
542 if (widget != d->viewport) {
543 QWidget *oldViewport = d->viewport;
544 if (!widget)
545 widget = new QWidget;
546 d->viewport = widget;
547 d->viewport->setParent(this);
548 d->viewport->setFocusProxy(this);
549 d->viewport->installEventFilter(d->viewportFilter.data());
550#ifndef Q_WS_MAC
551#ifndef QT_NO_GESTURES
552 d->viewport->grabGesture(Qt::PanGesture);
553#endif
554#endif
555 d->layoutChildren();
556 if (isVisible())
557 d->viewport->show();
558 QMetaObject::invokeMethod(this, "setupViewport", Q_ARG(QWidget *, widget));
559 delete oldViewport;
560 }
561}
562
563/*!
564 Returns the viewport widget.
565
566 Use the QScrollArea::widget() function to retrieve the contents of
567 the viewport widget.
568
569 \sa QScrollArea::widget()
570*/
571QWidget *QAbstractScrollArea::viewport() const
572{
573 Q_D(const QAbstractScrollArea);
574 return d->viewport;
575}
576
577
578/*!
579Returns the size of the viewport as if the scroll bars had no valid
580scrolling range.
581*/
582// ### still thinking about the name
583QSize QAbstractScrollArea::maximumViewportSize() const
584{
585 Q_D(const QAbstractScrollArea);
586 int hsbExt = d->hbar->sizeHint().height();
587 int vsbExt = d->vbar->sizeHint().width();
588
589 int f = 2 * d->frameWidth;
590 QSize max = size() - QSize(f + d->left + d->right, f + d->top + d->bottom);
591 if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
592 max.rwidth() -= vsbExt;
593 if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
594 max.rheight() -= hsbExt;
595 return max;
596}
597
598/*!
599 \property QAbstractScrollArea::verticalScrollBarPolicy
600 \brief the policy for the vertical scroll bar
601
602 The default policy is Qt::ScrollBarAsNeeded.
603
604 \sa horizontalScrollBarPolicy
605*/
606
607Qt::ScrollBarPolicy QAbstractScrollArea::verticalScrollBarPolicy() const
608{
609 Q_D(const QAbstractScrollArea);
610 return d->vbarpolicy;
611}
612
613void QAbstractScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy)
614{
615 Q_D(QAbstractScrollArea);
616 const Qt::ScrollBarPolicy oldPolicy = d->vbarpolicy;
617 d->vbarpolicy = policy;
618 if (isVisible())
619 d->layoutChildren();
620 if (oldPolicy != d->vbarpolicy)
621 d->scrollBarPolicyChanged(Qt::Vertical, d->vbarpolicy);
622}
623
624
625/*!
626 Returns the vertical scroll bar.
627
628 \sa verticalScrollBarPolicy, horizontalScrollBar()
629 */
630QScrollBar *QAbstractScrollArea::verticalScrollBar() const
631{
632 Q_D(const QAbstractScrollArea);
633 return d->vbar;
634}
635
636/*!
637 \since 4.2
638 Replaces the existing vertical scroll bar with \a scrollBar, and sets all
639 the former scroll bar's slider properties on the new scroll bar. The former
640 scroll bar is then deleted.
641
642 QAbstractScrollArea already provides vertical and horizontal scroll bars by
643 default. You can call this function to replace the default vertical
644 scroll bar with your own custom scroll bar.
645
646 \sa verticalScrollBar(), setHorizontalScrollBar()
647*/
648void QAbstractScrollArea::setVerticalScrollBar(QScrollBar *scrollBar)
649{
650 Q_D(QAbstractScrollArea);
651 if (!scrollBar) {
652 qWarning("QAbstractScrollArea::setVerticalScrollBar: Cannot set a null scroll bar");
653 return;
654 }
655
656 d->replaceScrollBar(scrollBar, Qt::Vertical);
657}
658
659/*!
660 \property QAbstractScrollArea::horizontalScrollBarPolicy
661 \brief the policy for the horizontal scroll bar
662
663 The default policy is Qt::ScrollBarAsNeeded.
664
665 \sa verticalScrollBarPolicy
666*/
667
668Qt::ScrollBarPolicy QAbstractScrollArea::horizontalScrollBarPolicy() const
669{
670 Q_D(const QAbstractScrollArea);
671 return d->hbarpolicy;
672}
673
674void QAbstractScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
675{
676 Q_D(QAbstractScrollArea);
677 const Qt::ScrollBarPolicy oldPolicy = d->hbarpolicy;
678 d->hbarpolicy = policy;
679 if (isVisible())
680 d->layoutChildren();
681 if (oldPolicy != d->hbarpolicy)
682 d->scrollBarPolicyChanged(Qt::Horizontal, d->hbarpolicy);
683}
684
685/*!
686 Returns the horizontal scroll bar.
687
688 \sa horizontalScrollBarPolicy, verticalScrollBar()
689 */
690QScrollBar *QAbstractScrollArea::horizontalScrollBar() const
691{
692 Q_D(const QAbstractScrollArea);
693 return d->hbar;
694}
695
696/*!
697 \since 4.2
698
699 Replaces the existing horizontal scroll bar with \a scrollBar, and sets all
700 the former scroll bar's slider properties on the new scroll bar. The former
701 scroll bar is then deleted.
702
703 QAbstractScrollArea already provides horizontal and vertical scroll bars by
704 default. You can call this function to replace the default horizontal
705 scroll bar with your own custom scroll bar.
706
707 \sa horizontalScrollBar(), setVerticalScrollBar()
708*/
709void QAbstractScrollArea::setHorizontalScrollBar(QScrollBar *scrollBar)
710{
711 Q_D(QAbstractScrollArea);
712 if (!scrollBar) {
713 qWarning("QAbstractScrollArea::setHorizontalScrollBar: Cannot set a null scroll bar");
714 return;
715 }
716
717 d->replaceScrollBar(scrollBar, Qt::Horizontal);
718}
719
720/*!
721 \since 4.2
722
723 Returns the widget in the corner between the two scroll bars.
724
725 By default, no corner widget is present.
726*/
727QWidget *QAbstractScrollArea::cornerWidget() const
728{
729 Q_D(const QAbstractScrollArea);
730 return d->cornerWidget;
731}
732
733/*!
734 \since 4.2
735
736 Sets the widget in the corner between the two scroll bars to be
737 \a widget.
738
739 You will probably also want to set at least one of the scroll bar
740 modes to \c AlwaysOn.
741
742 Passing 0 shows no widget in the corner.
743
744 Any previous corner widget is hidden.
745
746 You may call setCornerWidget() with the same widget at different
747 times.
748
749 All widgets set here will be deleted by the scroll area when it is
750 destroyed unless you separately reparent the widget after setting
751 some other corner widget (or 0).
752
753 Any \e newly set widget should have no current parent.
754
755 By default, no corner widget is present.
756
757 \sa horizontalScrollBarPolicy, horizontalScrollBarPolicy
758*/
759void QAbstractScrollArea::setCornerWidget(QWidget *widget)
760{
761 Q_D(QAbstractScrollArea);
762 QWidget* oldWidget = d->cornerWidget;
763 if (oldWidget != widget) {
764 if (oldWidget)
765 oldWidget->hide();
766 d->cornerWidget = widget;
767
768 if (widget && widget->parentWidget() != this)
769 widget->setParent(this);
770
771 d->layoutChildren();
772 if (widget)
773 widget->show();
774 } else {
775 d->cornerWidget = widget;
776 d->layoutChildren();
777 }
778}
779
780/*!
781 \since 4.2
782 Adds \a widget as a scroll bar widget in the location specified
783 by \a alignment.
784
785 Scroll bar widgets are shown next to the horizontal or vertical
786 scroll bar, and can be placed on either side of it. If you want
787 the scroll bar widgets to be always visible, set the
788 scrollBarPolicy for the corresponding scroll bar to \c AlwaysOn.
789
790 \a alignment must be one of Qt::Alignleft and Qt::AlignRight,
791 which maps to the horizontal scroll bar, or Qt::AlignTop and
792 Qt::AlignBottom, which maps to the vertical scroll bar.
793
794 A scroll bar widget can be removed by either re-parenting the
795 widget or deleting it. It's also possible to hide a widget with
796 QWidget::hide()
797
798 The scroll bar widget will be resized to fit the scroll bar
799 geometry for the current style. The following describes the case
800 for scroll bar widgets on the horizontal scroll bar:
801
802 The height of the widget will be set to match the height of the
803 scroll bar. To control the width of the widget, use
804 QWidget::setMinimumWidth and QWidget::setMaximumWidth, or
805 implement QWidget::sizeHint() and set a horizontal size policy.
806 If you want a square widget, call
807 QStyle::pixelMetric(QStyle::PM_ScrollBarExtent) and set the
808 width to this value.
809
810 \sa scrollBarWidgets()
811*/
812void QAbstractScrollArea::addScrollBarWidget(QWidget *widget, Qt::Alignment alignment)
813{
814 Q_D(QAbstractScrollArea);
815
816 if (widget == 0)
817 return;
818
819 const Qt::Orientation scrollBarOrientation
820 = ((alignment & Qt::AlignLeft) || (alignment & Qt::AlignRight)) ? Qt::Horizontal : Qt::Vertical;
821 const QAbstractScrollAreaScrollBarContainer::LogicalPosition position
822 = ((alignment & Qt::AlignRight) || (alignment & Qt::AlignBottom))
823 ? QAbstractScrollAreaScrollBarContainer::LogicalRight : QAbstractScrollAreaScrollBarContainer::LogicalLeft;
824 d->scrollBarContainers[scrollBarOrientation]->addWidget(widget, position);
825 d->layoutChildren();
826 if (isHidden() == false)
827 widget->show();
828}
829
830/*!
831 \since 4.2
832 Returns a list of the currently set scroll bar widgets. \a alignment
833 can be any combination of the four location flags.
834
835 \sa addScrollBarWidget()
836*/
837QWidgetList QAbstractScrollArea::scrollBarWidgets(Qt::Alignment alignment)
838{
839 Q_D(QAbstractScrollArea);
840
841 QWidgetList list;
842
843 if (alignment & Qt::AlignLeft)
844 list += d->scrollBarContainers[Qt::Horizontal]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalLeft);
845 if (alignment & Qt::AlignRight)
846 list += d->scrollBarContainers[Qt::Horizontal]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalRight);
847 if (alignment & Qt::AlignTop)
848 list += d->scrollBarContainers[Qt::Vertical]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalLeft);
849 if (alignment & Qt::AlignBottom)
850 list += d->scrollBarContainers[Qt::Vertical]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalRight);
851
852 return list;
853}
854
855/*!
856 Sets the margins around the scrolling area to \a left, \a top, \a
857 right and \a bottom. This is useful for applications such as
858 spreadsheets with "locked" rows and columns. The marginal space is
859 is left blank; put widgets in the unused area.
860
861 Note that this function is frequently called by QTreeView and
862 QTableView, so margins must be implemented by QAbstractScrollArea
863 subclasses. Also, if the subclasses are to be used in item views,
864 they should not call this function.
865
866 By default all margins are zero.
867
868*/
869void QAbstractScrollArea::setViewportMargins(int left, int top, int right, int bottom)
870{
871 Q_D(QAbstractScrollArea);
872 d->left = left;
873 d->top = top;
874 d->right = right;
875 d->bottom = bottom;
876 d->layoutChildren();
877}
878
879/*!
880 \since 4.6
881 Sets \a margins around the scrolling area. This is useful for
882 applications such as spreadsheets with "locked" rows and columns.
883 The marginal space is is left blank; put widgets in the unused
884 area.
885
886 By default all margins are zero.
887
888*/
889void QAbstractScrollArea::setViewportMargins(const QMargins &margins)
890{
891 setViewportMargins(margins.left(), margins.top(),
892 margins.right(), margins.bottom());
893}
894
895/*!
896 \fn bool QAbstractScrollArea::event(QEvent *event)
897
898 \reimp
899
900 This is the main event handler for the QAbstractScrollArea widget (\e not
901 the scrolling area viewport()). The specified \a event is a general event
902 object that may need to be cast to the appropriate class depending on its
903 type.
904
905 \sa QEvent::type()
906*/
907bool QAbstractScrollArea::event(QEvent *e)
908{
909 Q_D(QAbstractScrollArea);
910 switch (e->type()) {
911 case QEvent::AcceptDropsChange:
912 // There was a chance that with accessibility client we get an
913 // event before the viewport was created.
914 // Also, in some cases we might get here from QWidget::event() virtual function which is (indirectly) called
915 // from the viewport constructor at the time when the d->viewport is not yet initialized even without any
916 // accessibility client. See qabstractscrollarea autotest for a test case.
917 if (d->viewport)
918 d->viewport->setAcceptDrops(acceptDrops());
919 break;
920 case QEvent::MouseTrackingChange:
921 d->viewport->setMouseTracking(hasMouseTracking());
922 break;
923 case QEvent::Resize:
924 d->layoutChildren();
925 break;
926 case QEvent::Paint: {
927 QStyleOption option;
928 option.initFrom(this);
929 if (d->cornerPaintingRect.isValid()) {
930 option.rect = d->cornerPaintingRect;
931 QPainter p(this);
932 style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
933 }
934#ifdef Q_WS_MAC
935 if (d->reverseCornerPaintingRect.isValid()) {
936 option.rect = d->reverseCornerPaintingRect;
937 QPainter p(this);
938 style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
939 }
940#endif
941 }
942 QFrame::paintEvent((QPaintEvent*)e);
943 break;
944#ifndef QT_NO_CONTEXTMENU
945 case QEvent::ContextMenu:
946 if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard)
947 return QFrame::event(e);
948 e->ignore();
949 break;
950#endif // QT_NO_CONTEXTMENU
951 case QEvent::MouseButtonPress:
952 case QEvent::MouseButtonRelease:
953 case QEvent::MouseButtonDblClick:
954 case QEvent::MouseMove:
955 case QEvent::Wheel:
956#ifndef QT_NO_DRAGANDDROP
957 case QEvent::Drop:
958 case QEvent::DragEnter:
959 case QEvent::DragMove:
960 case QEvent::DragLeave:
961#endif
962 // ignore touch events in case they have been propagated from the viewport
963 case QEvent::TouchBegin:
964 case QEvent::TouchUpdate:
965 case QEvent::TouchEnd:
966 return false;
967#ifndef QT_NO_GESTURES
968 case QEvent::Gesture:
969 {
970 QGestureEvent *ge = static_cast<QGestureEvent *>(e);
971 QPanGesture *g = static_cast<QPanGesture *>(ge->gesture(Qt::PanGesture));
972 if (g) {
973 QScrollBar *hBar = horizontalScrollBar();
974 QScrollBar *vBar = verticalScrollBar();
975 QPointF delta = g->delta();
976 if (!delta.isNull()) {
977 if (QApplication::isRightToLeft())
978 delta.rx() *= -1;
979 int newX = hBar->value() - delta.x();
980 int newY = vBar->value() - delta.y();
981 hBar->setValue(newX);
982 vBar->setValue(newY);
983 }
984 return true;
985 }
986 return false;
987 }
988#endif // QT_NO_GESTURES
989 case QEvent::StyleChange:
990 case QEvent::LayoutDirectionChange:
991 case QEvent::ApplicationLayoutDirectionChange:
992 case QEvent::LayoutRequest:
993 d->layoutChildren();
994 // fall through
995 default:
996 return QFrame::event(e);
997 }
998 return true;
999}
1000
1001/*!
1002 \fn bool QAbstractScrollArea::viewportEvent(QEvent *event)
1003
1004 The main event handler for the scrolling area (the viewport() widget).
1005 It handles the \a event specified, and can be called by subclasses to
1006 provide reasonable default behavior.
1007
1008 Returns true to indicate to the event system that the event has been
1009 handled, and needs no further processing; otherwise returns false to
1010 indicate that the event should be propagated further.
1011
1012 You can reimplement this function in a subclass, but we recommend
1013 using one of the specialized event handlers instead.
1014
1015 Specialized handlers for viewport events are: paintEvent(),
1016 mousePressEvent(), mouseReleaseEvent(), mouseDoubleClickEvent(),
1017 mouseMoveEvent(), wheelEvent(), dragEnterEvent(), dragMoveEvent(),
1018 dragLeaveEvent(), dropEvent(), contextMenuEvent(), and
1019 resizeEvent().
1020*/
1021bool QAbstractScrollArea::viewportEvent(QEvent *e)
1022{
1023 switch (e->type()) {
1024 case QEvent::Resize:
1025 case QEvent::Paint:
1026 case QEvent::MouseButtonPress:
1027 case QEvent::MouseButtonRelease:
1028 case QEvent::MouseButtonDblClick:
1029 case QEvent::TouchBegin:
1030 case QEvent::TouchUpdate:
1031 case QEvent::TouchEnd:
1032 case QEvent::MouseMove:
1033 case QEvent::ContextMenu:
1034#ifndef QT_NO_WHEELEVENT
1035 case QEvent::Wheel:
1036#endif
1037#ifndef QT_NO_DRAGANDDROP
1038 case QEvent::Drop:
1039 case QEvent::DragEnter:
1040 case QEvent::DragMove:
1041 case QEvent::DragLeave:
1042#endif
1043 return QFrame::event(e);
1044 case QEvent::LayoutRequest:
1045#ifndef QT_NO_GESTURES
1046 case QEvent::Gesture:
1047 case QEvent::GestureOverride:
1048 return event(e);
1049#endif
1050 default:
1051 break;
1052 }
1053 return false; // let the viewport widget handle the event
1054}
1055
1056/*!
1057 \fn void QAbstractScrollArea::resizeEvent(QResizeEvent *event)
1058
1059 This event handler can be reimplemented in a subclass to receive
1060 resize events (passed in \a event), for the viewport() widget.
1061
1062 When resizeEvent() is called, the viewport already has its new
1063 geometry: Its new size is accessible through the
1064 QResizeEvent::size() function, and the old size through
1065 QResizeEvent::oldSize().
1066
1067 \sa QWidget::resizeEvent()
1068 */
1069void QAbstractScrollArea::resizeEvent(QResizeEvent *)
1070{
1071}
1072
1073/*!
1074 \fn void QAbstractScrollArea::paintEvent(QPaintEvent *event)
1075
1076 This event handler can be reimplemented in a subclass to receive
1077 paint events (passed in \a event), for the viewport() widget.
1078
1079 \note If you open a painter, make sure to open it on the viewport().
1080
1081 \sa QWidget::paintEvent()
1082*/
1083void QAbstractScrollArea::paintEvent(QPaintEvent*)
1084{
1085}
1086
1087/*!
1088 This event handler can be reimplemented in a subclass to receive
1089 mouse press events for the viewport() widget. The event is passed
1090 in \a e.
1091
1092 \sa QWidget::mousePressEvent()
1093*/
1094void QAbstractScrollArea::mousePressEvent(QMouseEvent *e)
1095{
1096 e->ignore();
1097}
1098
1099/*!
1100 This event handler can be reimplemented in a subclass to receive
1101 mouse release events for the viewport() widget. The event is
1102 passed in \a e.
1103
1104 \sa QWidget::mouseReleaseEvent()
1105*/
1106void QAbstractScrollArea::mouseReleaseEvent(QMouseEvent *e)
1107{
1108 e->ignore();
1109}
1110
1111/*!
1112 This event handler can be reimplemented in a subclass to receive
1113 mouse double click events for the viewport() widget. The event is
1114 passed in \a e.
1115
1116 \sa QWidget::mouseDoubleClickEvent()
1117*/
1118void QAbstractScrollArea::mouseDoubleClickEvent(QMouseEvent *e)
1119{
1120 e->ignore();
1121}
1122
1123/*!
1124 This event handler can be reimplemented in a subclass to receive
1125 mouse move events for the viewport() widget. The event is passed
1126 in \a e.
1127
1128 \sa QWidget::mouseMoveEvent()
1129*/
1130void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e)
1131{
1132 e->ignore();
1133}
1134
1135/*!
1136 This event handler can be reimplemented in a subclass to receive
1137 wheel events for the viewport() widget. The event is passed in \a
1138 e.
1139
1140 \sa QWidget::wheelEvent()
1141*/
1142#ifndef QT_NO_WHEELEVENT
1143void QAbstractScrollArea::wheelEvent(QWheelEvent *e)
1144{
1145 Q_D(QAbstractScrollArea);
1146 if (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal)
1147 QApplication::sendEvent(d->hbar, e);
1148 else
1149 QApplication::sendEvent(d->vbar, e);
1150}
1151#endif
1152
1153#ifndef QT_NO_CONTEXTMENU
1154/*!
1155 This event handler can be reimplemented in a subclass to receive
1156 context menu events for the viewport() widget. The event is passed
1157 in \a e.
1158
1159 \sa QWidget::contextMenuEvent()
1160*/
1161void QAbstractScrollArea::contextMenuEvent(QContextMenuEvent *e)
1162{
1163 e->ignore();
1164}
1165#endif // QT_NO_CONTEXTMENU
1166
1167/*!
1168 This function is called with key event \a e when key presses
1169 occur. It handles PageUp, PageDown, Up, Down, Left, and Right, and
1170 ignores all other key presses.
1171*/
1172void QAbstractScrollArea::keyPressEvent(QKeyEvent * e)
1173{
1174 Q_D(QAbstractScrollArea);
1175 if (false){
1176#ifndef QT_NO_SHORTCUT
1177 } else if (e == QKeySequence::MoveToPreviousPage) {
1178 d->vbar->triggerAction(QScrollBar::SliderPageStepSub);
1179 } else if (e == QKeySequence::MoveToNextPage) {
1180 d->vbar->triggerAction(QScrollBar::SliderPageStepAdd);
1181#endif
1182 } else {
1183#ifdef QT_KEYPAD_NAVIGATION
1184 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1185 e->ignore();
1186 return;
1187 }
1188#endif
1189 switch (e->key()) {
1190 case Qt::Key_Up:
1191 d->vbar->triggerAction(QScrollBar::SliderSingleStepSub);
1192 break;
1193 case Qt::Key_Down:
1194 d->vbar->triggerAction(QScrollBar::SliderSingleStepAdd);
1195 break;
1196 case Qt::Key_Left:
1197#ifdef QT_KEYPAD_NAVIGATION
1198 if (QApplication::keypadNavigationEnabled() && hasEditFocus()
1199 && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->minimum())) {
1200 //if we aren't using the hbar or we are already at the leftmost point ignore
1201 e->ignore();
1202 return;
1203 }
1204#endif
1205 d->hbar->triggerAction(
1206 layoutDirection() == Qt::LeftToRight
1207 ? QScrollBar::SliderSingleStepSub : QScrollBar::SliderSingleStepAdd);
1208 break;
1209 case Qt::Key_Right:
1210#ifdef QT_KEYPAD_NAVIGATION
1211 if (QApplication::keypadNavigationEnabled() && hasEditFocus()
1212 && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->maximum())) {
1213 //if we aren't using the hbar or we are already at the rightmost point ignore
1214 e->ignore();
1215 return;
1216 }
1217#endif
1218 d->hbar->triggerAction(
1219 layoutDirection() == Qt::LeftToRight
1220 ? QScrollBar::SliderSingleStepAdd : QScrollBar::SliderSingleStepSub);
1221 break;
1222 default:
1223 e->ignore();
1224 return;
1225 }
1226 }
1227 e->accept();
1228}
1229
1230
1231#ifndef QT_NO_DRAGANDDROP
1232/*!
1233 \fn void QAbstractScrollArea::dragEnterEvent(QDragEnterEvent *event)
1234
1235 This event handler can be reimplemented in a subclass to receive
1236 drag enter events (passed in \a event), for the viewport() widget.
1237
1238 \sa QWidget::dragEnterEvent()
1239*/
1240void QAbstractScrollArea::dragEnterEvent(QDragEnterEvent *)
1241{
1242}
1243
1244/*!
1245 \fn void QAbstractScrollArea::dragMoveEvent(QDragMoveEvent *event)
1246
1247 This event handler can be reimplemented in a subclass to receive
1248 drag move events (passed in \a event), for the viewport() widget.
1249
1250 \sa QWidget::dragMoveEvent()
1251*/
1252void QAbstractScrollArea::dragMoveEvent(QDragMoveEvent *)
1253{
1254}
1255
1256/*!
1257 \fn void QAbstractScrollArea::dragLeaveEvent(QDragLeaveEvent *event)
1258
1259 This event handler can be reimplemented in a subclass to receive
1260 drag leave events (passed in \a event), for the viewport() widget.
1261
1262 \sa QWidget::dragLeaveEvent()
1263*/
1264void QAbstractScrollArea::dragLeaveEvent(QDragLeaveEvent *)
1265{
1266}
1267
1268/*!
1269 \fn void QAbstractScrollArea::dropEvent(QDropEvent *event)
1270
1271 This event handler can be reimplemented in a subclass to receive
1272 drop events (passed in \a event), for the viewport() widget.
1273
1274 \sa QWidget::dropEvent()
1275*/
1276void QAbstractScrollArea::dropEvent(QDropEvent *)
1277{
1278}
1279
1280
1281#endif
1282
1283/*!
1284 This virtual handler is called when the scroll bars are moved by
1285 \a dx, \a dy, and consequently the viewport's contents should be
1286 scrolled accordingly.
1287
1288 The default implementation simply calls update() on the entire
1289 viewport(), subclasses can reimplement this handler for
1290 optimization purposes, or - like QScrollArea - to move a contents
1291 widget. The parameters \a dx and \a dy are there for convenience,
1292 so that the class knows how much should be scrolled (useful
1293 e.g. when doing pixel-shifts). You may just as well ignore these
1294 values and scroll directly to the position the scroll bars
1295 indicate.
1296
1297 Calling this function in order to scroll programmatically is an
1298 error, use the scroll bars instead (e.g. by calling
1299 QScrollBar::setValue() directly).
1300*/
1301void QAbstractScrollArea::scrollContentsBy(int, int)
1302{
1303 viewport()->update();
1304}
1305
1306void QAbstractScrollAreaPrivate::_q_hslide(int x)
1307{
1308 Q_Q(QAbstractScrollArea);
1309 int dx = xoffset - x;
1310 xoffset = x;
1311 q->scrollContentsBy(dx, 0);
1312}
1313
1314void QAbstractScrollAreaPrivate::_q_vslide(int y)
1315{
1316 Q_Q(QAbstractScrollArea);
1317 int dy = yoffset - y;
1318 yoffset = y;
1319 q->scrollContentsBy(0, dy);
1320}
1321
1322void QAbstractScrollAreaPrivate::_q_showOrHideScrollBars()
1323{
1324 layoutChildren();
1325#ifdef Q_WS_WIN
1326 // Need to re-subscribe to gestures as the content changes to make sure we
1327 // enable/disable panning when needed.
1328 QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport));
1329 if (dd)
1330 dd->winSetupGestures();
1331#endif // Q_WS_WIN
1332}
1333
1334QPoint QAbstractScrollAreaPrivate::contentsOffset() const
1335{
1336 Q_Q(const QAbstractScrollArea);
1337 QPoint offset;
1338 if (vbar->isVisible())
1339 offset.setY(vbar->value());
1340 if (hbar->isVisible()) {
1341 if (q->isRightToLeft())
1342 offset.setX(hbar->maximum() - hbar->value());
1343 else
1344 offset.setX(hbar->value());
1345 }
1346 return offset;
1347}
1348
1349/*!
1350 \reimp
1351
1352*/
1353QSize QAbstractScrollArea::minimumSizeHint() const
1354{
1355 Q_D(const QAbstractScrollArea);
1356 int hsbExt = d->hbar->sizeHint().height();
1357 int vsbExt = d->vbar->sizeHint().width();
1358 int extra = 2 * d->frameWidth;
1359 QStyleOption opt;
1360 opt.initFrom(this);
1361 if ((d->frameStyle != QFrame::NoFrame)
1362 && style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, this)) {
1363 extra += style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, this);
1364 }
1365 return QSize(d->scrollBarContainers[Qt::Horizontal]->sizeHint().width() + vsbExt + extra,
1366 d->scrollBarContainers[Qt::Vertical]->sizeHint().height() + hsbExt + extra);
1367}
1368
1369/*!
1370 \reimp
1371*/
1372QSize QAbstractScrollArea::sizeHint() const
1373{
1374 return QSize(256, 192);
1375#if 0
1376 Q_D(const QAbstractScrollArea);
1377 int h = qMax(10, fontMetrics().height());
1378 int f = 2 * d->frameWidth;
1379 return QSize((6 * h) + f, (4 * h) + f);
1380#endif
1381}
1382
1383/*!
1384 This slot is called by QAbstractScrollArea after setViewport(\a
1385 viewport) has been called. Reimplement this function in a
1386 subclass of QAbstractScrollArea to initialize the new \a viewport
1387 before it is used.
1388
1389 \sa setViewport()
1390*/
1391void QAbstractScrollArea::setupViewport(QWidget *viewport)
1392{
1393 Q_UNUSED(viewport);
1394}
1395
1396QT_END_NAMESPACE
1397
1398#include "moc_qabstractscrollarea.cpp"
1399#include "moc_qabstractscrollarea_p.cpp"
1400
1401#endif // QT_NO_SCROLLAREA
Note: See TracBrowser for help on using the repository browser.