1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qabstractscrollarea.h"
44 #ifndef QT_NO_SCROLLAREA
46 #include "qscrollbar.h"
47 #include "qapplication.h"
49 #include "qstyleoption.h"
52 #include "qboxlayout.h"
55 #include "qheaderview.h"
59 #include "qabstractscrollarea_p.h"
60 #include "qscrollbar_p.h"
63 #include <private/qapplication_p.h>
66 #include <private/qt_mac_p.h>
67 #include <private/qt_cocoa_helpers_mac_p.h>
70 # include <qlibrary.h>
71 # include <qt_windows.h>
77 \class QAbstractScrollArea
78 \brief The QAbstractScrollArea widget provides a scrolling area with
79 on-demand scroll bars.
81 \ingroup abstractwidgets
84 QAbstractScrollArea is a low-level abstraction of a scrolling
85 area. The area provides a central widget called the viewport, in
86 which the contents of the area is to be scrolled (i.e, the
87 visible parts of the contents are rendered in the viewport).
89 Next to the viewport is a vertical scroll bar, and below is a
90 horizontal scroll bar. When all of the area contents fits in the
91 viewport, each scroll bar can be either visible or hidden
92 depending on the scroll bar's Qt::ScrollBarPolicy. When a scroll
93 bar is hidden, the viewport expands in order to cover all
94 available space. When a scroll bar becomes visible again, the
95 viewport shrinks in order to make room for the scroll bar.
97 It is possible to reserve a margin area around the viewport, see
98 setViewportMargins(). The feature is mostly used to place a
99 QHeaderView widget above or beside the scrolling area. Subclasses
100 of QAbstractScrollArea should implement margins.
102 When inheriting QAbstractScrollArea, you need to do the
106 \li Control the scroll bars by setting their
107 range, value, page step, and tracking their
109 \li Draw the contents of the area in the viewport according
110 to the values of the scroll bars.
111 \li Handle events received by the viewport in
112 viewportEvent() - notably resize events.
113 \li Use \c{viewport->update()} to update the contents of the
114 viewport instead of \l{QWidget::update()}{update()}
115 as all painting operations take place on the viewport.
118 With a scroll bar policy of Qt::ScrollBarAsNeeded (the default),
119 QAbstractScrollArea shows scroll bars when they provide a non-zero
120 scrolling range, and hides them otherwise.
122 The scroll bars and viewport should be updated whenever the viewport
123 receives a resize event or the size of the contents changes.
124 The viewport also needs to be updated when the scroll bars
125 values change. The initial values of the scroll bars are often
126 set when the area receives new contents.
128 We give a simple example, in which we have implemented a scroll area
129 that can scroll any QWidget. We make the widget a child of the
130 viewport; this way, we do not have to calculate which part of
131 the widget to draw but can simply move the widget with
132 QWidget::move(). When the area contents or the viewport size
133 changes, we do the following:
135 \snippet myscrollarea.cpp 1
137 When the scroll bars change value, we need to update the widget
138 position, i.e., find the part of the widget that is to be drawn in
141 \snippet myscrollarea.cpp 0
143 In order to track scroll bar movements, reimplement the virtual
144 function scrollContentsBy(). In order to fine-tune scrolling
145 behavior, connect to a scroll bar's
146 QAbstractSlider::actionTriggered() signal and adjust the \l
147 QAbstractSlider::sliderPosition as you wish.
149 For convenience, QAbstractScrollArea makes all viewport events
150 available in the virtual viewportEvent() handler. QWidget's
151 specialized handlers are remapped to viewport events in the cases
152 where this makes sense. The remapped specialized handlers are:
153 paintEvent(), mousePressEvent(), mouseReleaseEvent(),
154 mouseDoubleClickEvent(), mouseMoveEvent(), wheelEvent(),
155 dragEnterEvent(), dragMoveEvent(), dragLeaveEvent(), dropEvent(),
156 contextMenuEvent(), and resizeEvent().
158 QScrollArea, which inherits QAbstractScrollArea, provides smooth
159 scrolling for any QWidget (i.e., the widget is scrolled pixel by
160 pixel). You only need to subclass QAbstractScrollArea if you need
161 more specialized behavior. This is, for instance, true if the
162 entire contents of the area is not suitable for being drawn on a
163 QWidget or if you do not want smooth scrolling.
168 QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate()
169 :hbar(0), vbar(0), vbarpolicy(Qt::ScrollBarAsNeeded), hbarpolicy(Qt::ScrollBarAsNeeded),
170 viewport(0), cornerWidget(0), left(0), top(0), right(0), bottom(0),
171 xoffset(0), yoffset(0), viewportFilter(0)
173 , singleFingerPanEnabled(false)
178 QAbstractScrollAreaScrollBarContainer::QAbstractScrollAreaScrollBarContainer(Qt::Orientation orientation, QWidget *parent)
179 :QWidget(parent), scrollBar(new QScrollBar(orientation, this)),
180 layout(new QBoxLayout(orientation == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom)),
181 orientation(orientation)
184 layout->setMargin(0);
185 layout->setSpacing(0);
186 layout->addWidget(scrollBar);
187 layout->setSizeConstraint(QLayout::SetMaximumSize);
191 Adds a widget to the scroll bar container.
193 void QAbstractScrollAreaScrollBarContainer::addWidget(QWidget *widget, LogicalPosition position)
195 QSizePolicy policy = widget->sizePolicy();
196 if (orientation == Qt::Vertical)
197 policy.setHorizontalPolicy(QSizePolicy::Ignored);
199 policy.setVerticalPolicy(QSizePolicy::Ignored);
200 widget->setSizePolicy(policy);
201 widget->setParent(this);
203 const int insertIndex = (position & LogicalLeft) ? 0 : scrollBarLayoutIndex() + 1;
204 layout->insertWidget(insertIndex, widget);
208 Retuns a list of scroll bar widgets for the given position. The scroll bar
209 itself is not returned.
211 QWidgetList QAbstractScrollAreaScrollBarContainer::widgets(LogicalPosition position)
214 const int scrollBarIndex = scrollBarLayoutIndex();
215 if (position == LogicalLeft) {
216 for (int i = 0; i < scrollBarIndex; ++i)
217 list.append(layout->itemAt(i)->widget());
218 } else if (position == LogicalRight) {
219 const int layoutItemCount = layout->count();
220 for (int i = scrollBarIndex + 1; i < layoutItemCount; ++i)
221 list.append(layout->itemAt(i)->widget());
227 Returns the layout index for the scroll bar. This needs to be
228 recalculated by a linear search for each use, since items in
229 the layout can be removed at any time (i.e. when a widget is
230 deleted or re-parented).
232 int QAbstractScrollAreaScrollBarContainer::scrollBarLayoutIndex() const
234 const int layoutItemCount = layout->count();
235 for (int i = 0; i < layoutItemCount; ++i) {
236 if (qobject_cast<QScrollBar *>(layout->itemAt(i)->widget()))
244 void QAbstractScrollAreaPrivate::replaceScrollBar(QScrollBar *scrollBar,
245 Qt::Orientation orientation)
247 Q_Q(QAbstractScrollArea);
249 QAbstractScrollAreaScrollBarContainer *container = scrollBarContainers[orientation];
250 bool horizontal = (orientation == Qt::Horizontal);
251 QScrollBar *oldBar = horizontal ? hbar : vbar;
256 scrollBar->setParent(container);
257 container->scrollBar = scrollBar;
258 container->layout->removeWidget(oldBar);
259 container->layout->insertWidget(0, scrollBar);
260 scrollBar->setVisible(oldBar->isVisibleTo(container));
261 scrollBar->setInvertedAppearance(oldBar->invertedAppearance());
262 scrollBar->setInvertedControls(oldBar->invertedControls());
263 scrollBar->setRange(oldBar->minimum(), oldBar->maximum());
264 scrollBar->setOrientation(oldBar->orientation());
265 scrollBar->setPageStep(oldBar->pageStep());
266 scrollBar->setSingleStep(oldBar->singleStep());
267 scrollBar->setSliderDown(oldBar->isSliderDown());
268 scrollBar->setSliderPosition(oldBar->sliderPosition());
269 scrollBar->setTracking(oldBar->hasTracking());
270 scrollBar->setValue(oldBar->value());
271 scrollBar->installEventFilter(q);
272 oldBar->removeEventFilter(q);
275 QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
276 q, horizontal ? SLOT(_q_hslide(int)) : SLOT(_q_vslide(int)));
277 QObject::connect(scrollBar, SIGNAL(rangeChanged(int,int)),
278 q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
281 void QAbstractScrollAreaPrivate::init()
283 Q_Q(QAbstractScrollArea);
284 viewport = new QWidget(q);
285 viewport->setObjectName(QLatin1String("qt_scrollarea_viewport"));
286 viewport->setBackgroundRole(QPalette::Base);
287 viewport->setAutoFillBackground(true);
288 scrollBarContainers[Qt::Horizontal] = new QAbstractScrollAreaScrollBarContainer(Qt::Horizontal, q);
289 scrollBarContainers[Qt::Horizontal]->setObjectName(QLatin1String("qt_scrollarea_hcontainer"));
290 hbar = scrollBarContainers[Qt::Horizontal]->scrollBar;
292 scrollBarContainers[Qt::Horizontal]->setVisible(false);
293 hbar->installEventFilter(q);
294 QObject::connect(hbar, SIGNAL(valueChanged(int)), q, SLOT(_q_hslide(int)));
295 QObject::connect(hbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
296 scrollBarContainers[Qt::Vertical] = new QAbstractScrollAreaScrollBarContainer(Qt::Vertical, q);
297 scrollBarContainers[Qt::Vertical]->setObjectName(QLatin1String("qt_scrollarea_vcontainer"));
298 vbar = scrollBarContainers[Qt::Vertical]->scrollBar;
300 scrollBarContainers[Qt::Vertical]->setVisible(false);
301 vbar->installEventFilter(q);
302 QObject::connect(vbar, SIGNAL(valueChanged(int)), q, SLOT(_q_vslide(int)));
303 QObject::connect(vbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
304 viewportFilter.reset(new QAbstractScrollAreaFilter(this));
305 viewport->installEventFilter(viewportFilter.data());
306 viewport->setFocusProxy(q);
307 q->setFocusPolicy(Qt::WheelFocus);
308 q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
309 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
312 # ifndef QT_NO_GESTURES
313 viewport->grabGesture(Qt::PanGesture);
319 void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on)
321 singleFingerPanEnabled = on;
322 QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport));
324 dd->winSetupGestures();
328 void QAbstractScrollAreaPrivate::layoutChildren()
330 Q_Q(QAbstractScrollArea);
331 bool needh = (hbarpolicy == Qt::ScrollBarAlwaysOn
332 || (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum() && !hbar->sizeHint().isEmpty()));
334 bool needv = (vbarpolicy == Qt::ScrollBarAlwaysOn
335 || (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum() && !vbar->sizeHint().isEmpty()));
339 const int scrollOverlap = q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap,
343 QWidget * const window = q->window();
345 // Use small scroll bars for tool windows, to match the native size grip.
346 bool hbarIsSmall = hbar->testAttribute(Qt::WA_MacSmallSize);
347 bool vbarIsSmall = vbar->testAttribute(Qt::WA_MacSmallSize);
348 const Qt::WindowType windowType = window->windowType();
349 if (windowType == Qt::Tool) {
351 hbar->setAttribute(Qt::WA_MacMiniSize, false);
352 hbar->setAttribute(Qt::WA_MacNormalSize, false);
353 hbar->setAttribute(Qt::WA_MacSmallSize, true);
356 vbar->setAttribute(Qt::WA_MacMiniSize, false);
357 vbar->setAttribute(Qt::WA_MacNormalSize, false);
358 vbar->setAttribute(Qt::WA_MacSmallSize, true);
362 hbar->setAttribute(Qt::WA_MacMiniSize, false);
363 hbar->setAttribute(Qt::WA_MacNormalSize, false);
364 hbar->setAttribute(Qt::WA_MacSmallSize, false);
367 vbar->setAttribute(Qt::WA_MacMiniSize, false);
368 vbar->setAttribute(Qt::WA_MacNormalSize, false);
369 vbar->setAttribute(Qt::WA_MacSmallSize, false);
374 const int hsbExt = hbar->sizeHint().height();
375 const int vsbExt = vbar->sizeHint().width();
376 const QPoint extPoint(vsbExt, hsbExt);
377 const QSize extSize(vsbExt, hsbExt);
379 const QRect widgetRect = q->rect();
381 const bool hasCornerWidget = (cornerWidget != 0);
383 // If the scroll bars are at the very right and bottom of the window we
384 // move their positions to be aligned with the size grip.
386 // Check if a native sizegrip is present.
387 bool hasMacReverseSizeGrip = false;
388 bool hasMacSizeGrip = false;
389 bool nativeGripPresent = false;
390 if (q->testAttribute(Qt::WA_WState_Created))
391 nativeGripPresent = qt_mac_checkForNativeSizeGrip(q);
393 if (nativeGripPresent) {
394 // Look for a native size grip at the visual window bottom right and at the
395 // absolute window bottom right. In reverse mode, the native size grip does not
396 // swich side, so we need to check if it is on the "wrong side".
397 const QPoint scrollAreaBottomRight = q->mapTo(window, widgetRect.bottomRight() - QPoint(frameWidth, frameWidth));
398 const QPoint windowBottomRight = window->rect().bottomRight();
399 const QPoint visualWindowBottomRight = QStyle::visualPos(opt.direction, opt.rect, windowBottomRight);
400 const QPoint offset = windowBottomRight - scrollAreaBottomRight;
401 const QPoint visualOffset = visualWindowBottomRight - scrollAreaBottomRight;
402 hasMacSizeGrip = (visualOffset.manhattanLength() < vsbExt);
403 hasMacReverseSizeGrip = (hasMacSizeGrip == false && (offset.manhattanLength() < hsbExt));
407 QPoint cornerOffset((needv && scrollOverlap == 0) ? vsbExt : 0, (needh && scrollOverlap == 0) ? hsbExt : 0);
411 // In FrameOnlyAroundContents mode the frame is drawn between the controls and
412 // the viewport, else the frame rect is equal to the widget rect.
413 if ((frameStyle != QFrame::NoFrame) &&
414 q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, q)) {
415 controlsRect = widgetRect;
416 const int extra = scrollOverlap + q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, q);
417 const QPoint cornerExtra(needv ? extra : 0, needh ? extra : 0);
418 QRect frameRect = widgetRect;
419 frameRect.adjust(0, 0, -cornerOffset.x() - cornerExtra.x(), -cornerOffset.y() - cornerExtra.y());
420 q->setFrameRect(QStyle::visualRect(opt.direction, opt.rect, frameRect));
421 // The frame rect needs to be in logical coords, however we need to flip
422 // the contentsRect back before passing it on to the viewportRect
423 // since the viewportRect has its logical coords calculated later.
424 viewportRect = QStyle::visualRect(opt.direction, opt.rect, q->contentsRect());
426 q->setFrameRect(QStyle::visualRect(opt.direction, opt.rect, widgetRect));
427 controlsRect = q->contentsRect();
428 viewportRect = QRect(controlsRect.topLeft(), controlsRect.bottomRight() - cornerOffset);
431 cornerOffset = QPoint(needv ? vsbExt : 0, needh ? hsbExt : 0);
433 // If we have a corner widget and are only showing one scroll bar, we need to move it
434 // to make room for the corner widget.
435 if (hasCornerWidget && (needv || needh) && scrollOverlap == 0)
436 cornerOffset = extPoint;
439 // Also move the scroll bars if they are covered by the native Mac size grip.
441 cornerOffset = extPoint;
444 // The corner point is where the scroll bar rects, the corner widget rect and the
445 // viewport rect meets.
446 const QPoint cornerPoint(controlsRect.bottomRight() + QPoint(1, 1) - cornerOffset);
448 // Some styles paints the corner if both scorllbars are showing and there is
449 // no corner widget. Also, on the Mac we paint if there is a native
450 // (transparent) sizegrip in the area where a corner widget would be.
451 if ((needv && needh && hasCornerWidget == false && scrollOverlap == 0)
458 cornerPaintingRect = QStyle::visualRect(opt.direction, opt.rect, QRect(cornerPoint, extSize));
460 cornerPaintingRect = QRect();
464 if (hasMacReverseSizeGrip)
465 reverseCornerPaintingRect = QRect(controlsRect.bottomRight() + QPoint(1, 1) - extPoint, extSize);
467 reverseCornerPaintingRect = QRect();
470 // move the scrollbars away from top/left headers
471 int vHeaderRight = 0;
472 int hHeaderBottom = 0;
473 if (scrollOverlap > 0 && (needv || needh)) {
474 const QList<QHeaderView *> headers = q->findChildren<QHeaderView*>();
475 if (headers.count() <= 2) {
476 Q_FOREACH (const QHeaderView *header, headers) {
477 const QRect geo = header->geometry();
478 if (header->orientation() == Qt::Vertical && header->isVisible() && QStyle::visualRect(opt.direction, opt.rect, geo).left() <= opt.rect.width() / 2)
479 vHeaderRight = QStyle::visualRect(opt.direction, opt.rect, geo).right();
480 else if (header->orientation() == Qt::Horizontal && header->isVisible() && geo.top() <= q->frameWidth())
481 hHeaderBottom = geo.bottom();
487 QRect horizontalScrollBarRect(QPoint(controlsRect.left() + vHeaderRight, cornerPoint.y()), QPoint(cornerPoint.x() - 1, controlsRect.bottom()));
489 if (hasMacReverseSizeGrip)
490 horizontalScrollBarRect.adjust(vsbExt, 0, 0, 0);
493 if (!hasCornerWidget && QSysInfo::macVersion() >= QSysInfo::MV_10_8 && q->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, hbar))
494 horizontalScrollBarRect.adjust(0, 0, cornerOffset.x(), 0);
496 scrollBarContainers[Qt::Horizontal]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, horizontalScrollBarRect));
497 scrollBarContainers[Qt::Horizontal]->raise();
501 QRect verticalScrollBarRect (QPoint(cornerPoint.x(), controlsRect.top() + hHeaderBottom), QPoint(controlsRect.right(), cornerPoint.y() - 1));
503 if (!hasCornerWidget && QSysInfo::macVersion() >= QSysInfo::MV_10_8 && q->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, vbar))
504 verticalScrollBarRect.adjust(0, 0, 0, cornerOffset.y());
506 scrollBarContainers[Qt::Vertical]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, verticalScrollBarRect));
507 scrollBarContainers[Qt::Vertical]->raise();
511 const QRect cornerWidgetRect(cornerPoint, controlsRect.bottomRight());
512 cornerWidget->setGeometry(QStyle::visualRect(opt.direction, opt.rect, cornerWidgetRect));
515 scrollBarContainers[Qt::Horizontal]->setVisible(needh);
516 scrollBarContainers[Qt::Vertical]->setVisible(needv);
518 if (q->isRightToLeft())
519 viewportRect.adjust(right, top, -left, -bottom);
521 viewportRect.adjust(left, top, -right, -bottom);
523 viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last
529 Creates a new QAbstractScrollAreaPrivate, \a dd with the given \a parent.
531 QAbstractScrollArea::QAbstractScrollArea(QAbstractScrollAreaPrivate &dd, QWidget *parent)
534 Q_D(QAbstractScrollArea);
538 d->viewportFilter.reset();
544 Constructs a viewport.
546 The \a parent argument is sent to the QWidget constructor.
548 QAbstractScrollArea::QAbstractScrollArea(QWidget *parent)
549 :QFrame(*new QAbstractScrollAreaPrivate, parent)
551 Q_D(QAbstractScrollArea);
555 d->viewportFilter.reset();
562 Destroys the viewport.
564 QAbstractScrollArea::~QAbstractScrollArea()
566 Q_D(QAbstractScrollArea);
567 // reset it here, otherwise we'll have a dangling pointer in ~QWidget
568 d->viewportFilter.reset();
574 Sets the viewport to be the given \a widget.
575 The QAbstractScrollArea will take ownership of the given \a widget.
577 If \a widget is 0, QAbstractScrollArea will assign a new QWidget instance
582 void QAbstractScrollArea::setViewport(QWidget *widget)
584 Q_D(QAbstractScrollArea);
585 if (widget != d->viewport) {
586 QWidget *oldViewport = d->viewport;
588 widget = new QWidget;
589 d->viewport = widget;
590 d->viewport->setParent(this);
591 d->viewport->setFocusProxy(this);
592 d->viewport->installEventFilter(d->viewportFilter.data());
594 #ifndef QT_NO_GESTURES
595 d->viewport->grabGesture(Qt::PanGesture);
601 setupViewport(widget);
607 Returns the viewport widget.
609 Use the QScrollArea::widget() function to retrieve the contents of
612 \sa QScrollArea::widget()
614 QWidget *QAbstractScrollArea::viewport() const
616 Q_D(const QAbstractScrollArea);
622 Returns the size of the viewport as if the scroll bars had no valid
625 // ### still thinking about the name
626 QSize QAbstractScrollArea::maximumViewportSize() const
628 Q_D(const QAbstractScrollArea);
629 int hsbExt = d->hbar->sizeHint().height();
630 int vsbExt = d->vbar->sizeHint().width();
632 int f = 2 * d->frameWidth;
633 QSize max = size() - QSize(f + d->left + d->right, f + d->top + d->bottom);
634 if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
635 max.rwidth() -= vsbExt;
636 if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
637 max.rheight() -= hsbExt;
642 \property QAbstractScrollArea::verticalScrollBarPolicy
643 \brief the policy for the vertical scroll bar
645 The default policy is Qt::ScrollBarAsNeeded.
647 \sa horizontalScrollBarPolicy
650 Qt::ScrollBarPolicy QAbstractScrollArea::verticalScrollBarPolicy() const
652 Q_D(const QAbstractScrollArea);
653 return d->vbarpolicy;
656 void QAbstractScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy)
658 Q_D(QAbstractScrollArea);
659 const Qt::ScrollBarPolicy oldPolicy = d->vbarpolicy;
660 d->vbarpolicy = policy;
663 if (oldPolicy != d->vbarpolicy)
664 d->scrollBarPolicyChanged(Qt::Vertical, d->vbarpolicy);
665 d->setScrollBarTransient(d->vbar, policy == Qt::ScrollBarAsNeeded);
670 Returns the vertical scroll bar.
672 \sa verticalScrollBarPolicy, horizontalScrollBar()
674 QScrollBar *QAbstractScrollArea::verticalScrollBar() const
676 Q_D(const QAbstractScrollArea);
682 Replaces the existing vertical scroll bar with \a scrollBar, and sets all
683 the former scroll bar's slider properties on the new scroll bar. The former
684 scroll bar is then deleted.
686 QAbstractScrollArea already provides vertical and horizontal scroll bars by
687 default. You can call this function to replace the default vertical
688 scroll bar with your own custom scroll bar.
690 \sa verticalScrollBar(), setHorizontalScrollBar()
692 void QAbstractScrollArea::setVerticalScrollBar(QScrollBar *scrollBar)
694 Q_D(QAbstractScrollArea);
696 qWarning("QAbstractScrollArea::setVerticalScrollBar: Cannot set a null scroll bar");
700 d->replaceScrollBar(scrollBar, Qt::Vertical);
704 \property QAbstractScrollArea::horizontalScrollBarPolicy
705 \brief the policy for the horizontal scroll bar
707 The default policy is Qt::ScrollBarAsNeeded.
709 \sa verticalScrollBarPolicy
712 Qt::ScrollBarPolicy QAbstractScrollArea::horizontalScrollBarPolicy() const
714 Q_D(const QAbstractScrollArea);
715 return d->hbarpolicy;
718 void QAbstractScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
720 Q_D(QAbstractScrollArea);
721 const Qt::ScrollBarPolicy oldPolicy = d->hbarpolicy;
722 d->hbarpolicy = policy;
725 if (oldPolicy != d->hbarpolicy)
726 d->scrollBarPolicyChanged(Qt::Horizontal, d->hbarpolicy);
727 d->setScrollBarTransient(d->hbar, policy == Qt::ScrollBarAsNeeded);
731 Returns the horizontal scroll bar.
733 \sa horizontalScrollBarPolicy, verticalScrollBar()
735 QScrollBar *QAbstractScrollArea::horizontalScrollBar() const
737 Q_D(const QAbstractScrollArea);
744 Replaces the existing horizontal scroll bar with \a scrollBar, and sets all
745 the former scroll bar's slider properties on the new scroll bar. The former
746 scroll bar is then deleted.
748 QAbstractScrollArea already provides horizontal and vertical scroll bars by
749 default. You can call this function to replace the default horizontal
750 scroll bar with your own custom scroll bar.
752 \sa horizontalScrollBar(), setVerticalScrollBar()
754 void QAbstractScrollArea::setHorizontalScrollBar(QScrollBar *scrollBar)
756 Q_D(QAbstractScrollArea);
758 qWarning("QAbstractScrollArea::setHorizontalScrollBar: Cannot set a null scroll bar");
762 d->replaceScrollBar(scrollBar, Qt::Horizontal);
768 Returns the widget in the corner between the two scroll bars.
770 By default, no corner widget is present.
772 QWidget *QAbstractScrollArea::cornerWidget() const
774 Q_D(const QAbstractScrollArea);
775 return d->cornerWidget;
781 Sets the widget in the corner between the two scroll bars to be
784 You will probably also want to set at least one of the scroll bar
785 modes to \c AlwaysOn.
787 Passing 0 shows no widget in the corner.
789 Any previous corner widget is hidden.
791 You may call setCornerWidget() with the same widget at different
794 All widgets set here will be deleted by the scroll area when it is
795 destroyed unless you separately reparent the widget after setting
796 some other corner widget (or 0).
798 Any \e newly set widget should have no current parent.
800 By default, no corner widget is present.
802 \sa horizontalScrollBarPolicy, horizontalScrollBarPolicy
804 void QAbstractScrollArea::setCornerWidget(QWidget *widget)
806 Q_D(QAbstractScrollArea);
807 QWidget* oldWidget = d->cornerWidget;
808 if (oldWidget != widget) {
811 d->cornerWidget = widget;
813 if (widget && widget->parentWidget() != this)
814 widget->setParent(this);
820 d->cornerWidget = widget;
827 Adds \a widget as a scroll bar widget in the location specified
830 Scroll bar widgets are shown next to the horizontal or vertical
831 scroll bar, and can be placed on either side of it. If you want
832 the scroll bar widgets to be always visible, set the
833 scrollBarPolicy for the corresponding scroll bar to \c AlwaysOn.
835 \a alignment must be one of Qt::Alignleft and Qt::AlignRight,
836 which maps to the horizontal scroll bar, or Qt::AlignTop and
837 Qt::AlignBottom, which maps to the vertical scroll bar.
839 A scroll bar widget can be removed by either re-parenting the
840 widget or deleting it. It's also possible to hide a widget with
843 The scroll bar widget will be resized to fit the scroll bar
844 geometry for the current style. The following describes the case
845 for scroll bar widgets on the horizontal scroll bar:
847 The height of the widget will be set to match the height of the
848 scroll bar. To control the width of the widget, use
849 QWidget::setMinimumWidth and QWidget::setMaximumWidth, or
850 implement QWidget::sizeHint() and set a horizontal size policy.
851 If you want a square widget, call
852 QStyle::pixelMetric(QStyle::PM_ScrollBarExtent) and set the
855 \sa scrollBarWidgets()
857 void QAbstractScrollArea::addScrollBarWidget(QWidget *widget, Qt::Alignment alignment)
859 Q_D(QAbstractScrollArea);
864 const Qt::Orientation scrollBarOrientation
865 = ((alignment & Qt::AlignLeft) || (alignment & Qt::AlignRight)) ? Qt::Horizontal : Qt::Vertical;
866 const QAbstractScrollAreaScrollBarContainer::LogicalPosition position
867 = ((alignment & Qt::AlignRight) || (alignment & Qt::AlignBottom))
868 ? QAbstractScrollAreaScrollBarContainer::LogicalRight : QAbstractScrollAreaScrollBarContainer::LogicalLeft;
869 d->scrollBarContainers[scrollBarOrientation]->addWidget(widget, position);
871 if (isHidden() == false)
877 Returns a list of the currently set scroll bar widgets. \a alignment
878 can be any combination of the four location flags.
880 \sa addScrollBarWidget()
882 QWidgetList QAbstractScrollArea::scrollBarWidgets(Qt::Alignment alignment)
884 Q_D(QAbstractScrollArea);
888 if (alignment & Qt::AlignLeft)
889 list += d->scrollBarContainers[Qt::Horizontal]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalLeft);
890 if (alignment & Qt::AlignRight)
891 list += d->scrollBarContainers[Qt::Horizontal]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalRight);
892 if (alignment & Qt::AlignTop)
893 list += d->scrollBarContainers[Qt::Vertical]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalLeft);
894 if (alignment & Qt::AlignBottom)
895 list += d->scrollBarContainers[Qt::Vertical]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalRight);
901 Sets the margins around the scrolling area to \a left, \a top, \a
902 right and \a bottom. This is useful for applications such as
903 spreadsheets with "locked" rows and columns. The marginal space is
904 is left blank; put widgets in the unused area.
906 Note that this function is frequently called by QTreeView and
907 QTableView, so margins must be implemented by QAbstractScrollArea
908 subclasses. Also, if the subclasses are to be used in item views,
909 they should not call this function.
911 By default all margins are zero.
914 void QAbstractScrollArea::setViewportMargins(int left, int top, int right, int bottom)
916 Q_D(QAbstractScrollArea);
926 Sets \a margins around the scrolling area. This is useful for
927 applications such as spreadsheets with "locked" rows and columns.
928 The marginal space is is left blank; put widgets in the unused
931 By default all margins are zero.
934 void QAbstractScrollArea::setViewportMargins(const QMargins &margins)
936 setViewportMargins(margins.left(), margins.top(),
937 margins.right(), margins.bottom());
941 bool QAbstractScrollArea::eventFilter(QObject *o, QEvent *e)
943 Q_D(QAbstractScrollArea);
944 if ((o == d->hbar || o == d->vbar) && (e->type() == QEvent::HoverEnter || e->type() == QEvent::HoverLeave)) {
945 Qt::ScrollBarPolicy policy = o == d->hbar ? d->vbarpolicy : d->hbarpolicy;
946 if (policy == Qt::ScrollBarAsNeeded) {
947 QScrollBar *sibling = o == d->hbar ? d->vbar : d->hbar;
948 d->setScrollBarTransient(sibling, e->type() == QEvent::HoverLeave);
951 return QFrame::eventFilter(o, e);
955 \fn bool QAbstractScrollArea::event(QEvent *event)
959 This is the main event handler for the QAbstractScrollArea widget (\e not
960 the scrolling area viewport()). The specified \a event is a general event
961 object that may need to be cast to the appropriate class depending on its
966 bool QAbstractScrollArea::event(QEvent *e)
968 Q_D(QAbstractScrollArea);
970 case QEvent::AcceptDropsChange:
971 // There was a chance that with accessibility client we get an
972 // event before the viewport was created.
973 // Also, in some cases we might get here from QWidget::event() virtual function which is (indirectly) called
974 // from the viewport constructor at the time when the d->viewport is not yet initialized even without any
975 // accessibility client. See qabstractscrollarea autotest for a test case.
977 d->viewport->setAcceptDrops(acceptDrops());
979 case QEvent::MouseTrackingChange:
980 d->viewport->setMouseTracking(hasMouseTracking());
985 case QEvent::Paint: {
987 option.initFrom(this);
988 if (d->cornerPaintingRect.isValid()) {
989 option.rect = d->cornerPaintingRect;
991 style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
994 if (d->reverseCornerPaintingRect.isValid()) {
995 option.rect = d->reverseCornerPaintingRect;
997 style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
1001 QFrame::paintEvent((QPaintEvent*)e);
1003 #ifndef QT_NO_CONTEXTMENU
1004 case QEvent::ContextMenu:
1005 if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard)
1006 return QFrame::event(e);
1009 #endif // QT_NO_CONTEXTMENU
1010 case QEvent::MouseButtonPress:
1011 case QEvent::MouseButtonRelease:
1012 case QEvent::MouseButtonDblClick:
1013 case QEvent::MouseMove:
1015 #ifndef QT_NO_DRAGANDDROP
1017 case QEvent::DragEnter:
1018 case QEvent::DragMove:
1019 case QEvent::DragLeave:
1021 // ignore touch events in case they have been propagated from the viewport
1022 case QEvent::TouchBegin:
1023 case QEvent::TouchUpdate:
1024 case QEvent::TouchEnd:
1026 #ifndef QT_NO_GESTURES
1027 case QEvent::Gesture:
1029 QGestureEvent *ge = static_cast<QGestureEvent *>(e);
1030 QPanGesture *g = static_cast<QPanGesture *>(ge->gesture(Qt::PanGesture));
1032 QScrollBar *hBar = horizontalScrollBar();
1033 QScrollBar *vBar = verticalScrollBar();
1034 QPointF delta = g->delta();
1035 if (!delta.isNull()) {
1036 if (QApplication::isRightToLeft())
1038 int newX = hBar->value() - delta.x();
1039 int newY = vBar->value() - delta.y();
1040 hBar->setValue(newX);
1041 vBar->setValue(newY);
1047 #endif // QT_NO_GESTURES
1048 case QEvent::ScrollPrepare:
1050 QScrollPrepareEvent *se = static_cast<QScrollPrepareEvent *>(e);
1051 if (d->canStartScrollingAt(se->startPos().toPoint())) {
1052 QScrollBar *hBar = horizontalScrollBar();
1053 QScrollBar *vBar = verticalScrollBar();
1055 se->setViewportSize(QSizeF(viewport()->size()));
1056 se->setContentPosRange(QRectF(0, 0, hBar->maximum(), vBar->maximum()));
1057 se->setContentPos(QPointF(hBar->value(), vBar->value()));
1063 case QEvent::Scroll:
1065 QScrollEvent *se = static_cast<QScrollEvent *>(e);
1067 QScrollBar *hBar = horizontalScrollBar();
1068 QScrollBar *vBar = verticalScrollBar();
1069 hBar->setValue(se->contentPos().x());
1070 vBar->setValue(se->contentPos().y());
1073 typedef BOOL (*PtrBeginPanningFeedback)(HWND);
1074 typedef BOOL (*PtrUpdatePanningFeedback)(HWND, LONG, LONG, BOOL);
1075 typedef BOOL (*PtrEndPanningFeedback)(HWND, BOOL);
1077 static PtrBeginPanningFeedback ptrBeginPanningFeedback = 0;
1078 static PtrUpdatePanningFeedback ptrUpdatePanningFeedback = 0;
1079 static PtrEndPanningFeedback ptrEndPanningFeedback = 0;
1081 if (!ptrBeginPanningFeedback)
1082 ptrBeginPanningFeedback = (PtrBeginPanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "BeginPanningFeedback");
1083 if (!ptrUpdatePanningFeedback)
1084 ptrUpdatePanningFeedback = (PtrUpdatePanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "UpdatePanningFeedback");
1085 if (!ptrEndPanningFeedback)
1086 ptrEndPanningFeedback = (PtrEndPanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "EndPanningFeedback");
1088 if (ptrBeginPanningFeedback && ptrUpdatePanningFeedback && ptrEndPanningFeedback) {
1089 WId wid = window()->winId();
1091 if (!se->overshootDistance().isNull() && d->overshoot.isNull())
1092 ptrBeginPanningFeedback(wid);
1093 if (!se->overshootDistance().isNull())
1094 ptrUpdatePanningFeedback(wid, -se->overshootDistance().x(), -se->overshootDistance().y(), false);
1095 if (se->overshootDistance().isNull() && !d->overshoot.isNull())
1096 ptrEndPanningFeedback(wid, true);
1100 QPoint delta = d->overshoot - se->overshootDistance().toPoint();
1101 if (!delta.isNull())
1102 viewport()->move(viewport()->pos() + delta);
1104 d->overshoot = se->overshootDistance().toPoint();
1108 case QEvent::StyleChange:
1109 case QEvent::LayoutDirectionChange:
1110 case QEvent::ApplicationLayoutDirectionChange:
1111 case QEvent::LayoutRequest:
1112 d->layoutChildren();
1115 return QFrame::event(e);
1121 \fn bool QAbstractScrollArea::viewportEvent(QEvent *event)
1123 The main event handler for the scrolling area (the viewport() widget).
1124 It handles the \a event specified, and can be called by subclasses to
1125 provide reasonable default behavior.
1127 Returns true to indicate to the event system that the event has been
1128 handled, and needs no further processing; otherwise returns false to
1129 indicate that the event should be propagated further.
1131 You can reimplement this function in a subclass, but we recommend
1132 using one of the specialized event handlers instead.
1134 Specialized handlers for viewport events are: paintEvent(),
1135 mousePressEvent(), mouseReleaseEvent(), mouseDoubleClickEvent(),
1136 mouseMoveEvent(), wheelEvent(), dragEnterEvent(), dragMoveEvent(),
1137 dragLeaveEvent(), dropEvent(), contextMenuEvent(), and
1140 bool QAbstractScrollArea::viewportEvent(QEvent *e)
1142 switch (e->type()) {
1143 case QEvent::Resize:
1145 case QEvent::MouseButtonPress:
1146 case QEvent::MouseButtonRelease:
1147 case QEvent::MouseButtonDblClick:
1148 case QEvent::TouchBegin:
1149 case QEvent::TouchUpdate:
1150 case QEvent::TouchEnd:
1151 case QEvent::MouseMove:
1152 case QEvent::ContextMenu:
1153 #ifndef QT_NO_WHEELEVENT
1156 #ifndef QT_NO_DRAGANDDROP
1158 case QEvent::DragEnter:
1159 case QEvent::DragMove:
1160 case QEvent::DragLeave:
1162 return QFrame::event(e);
1163 case QEvent::LayoutRequest:
1164 #ifndef QT_NO_GESTURES
1165 case QEvent::Gesture:
1166 case QEvent::GestureOverride:
1169 case QEvent::ScrollPrepare:
1170 case QEvent::Scroll:
1175 return false; // let the viewport widget handle the event
1179 \fn void QAbstractScrollArea::resizeEvent(QResizeEvent *event)
1181 This event handler can be reimplemented in a subclass to receive
1182 resize events (passed in \a event), for the viewport() widget.
1184 When resizeEvent() is called, the viewport already has its new
1185 geometry: Its new size is accessible through the
1186 QResizeEvent::size() function, and the old size through
1187 QResizeEvent::oldSize().
1189 \sa QWidget::resizeEvent()
1191 void QAbstractScrollArea::resizeEvent(QResizeEvent *)
1196 \fn void QAbstractScrollArea::paintEvent(QPaintEvent *event)
1198 This event handler can be reimplemented in a subclass to receive
1199 paint events (passed in \a event), for the viewport() widget.
1201 \note If you open a painter, make sure to open it on the viewport().
1203 \sa QWidget::paintEvent()
1205 void QAbstractScrollArea::paintEvent(QPaintEvent*)
1210 This event handler can be reimplemented in a subclass to receive
1211 mouse press events for the viewport() widget. The event is passed
1214 \sa QWidget::mousePressEvent()
1216 void QAbstractScrollArea::mousePressEvent(QMouseEvent *e)
1222 This event handler can be reimplemented in a subclass to receive
1223 mouse release events for the viewport() widget. The event is
1226 \sa QWidget::mouseReleaseEvent()
1228 void QAbstractScrollArea::mouseReleaseEvent(QMouseEvent *e)
1234 This event handler can be reimplemented in a subclass to receive
1235 mouse double click events for the viewport() widget. The event is
1238 \sa QWidget::mouseDoubleClickEvent()
1240 void QAbstractScrollArea::mouseDoubleClickEvent(QMouseEvent *e)
1246 This event handler can be reimplemented in a subclass to receive
1247 mouse move events for the viewport() widget. The event is passed
1250 \sa QWidget::mouseMoveEvent()
1252 void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e)
1258 This event handler can be reimplemented in a subclass to receive
1259 wheel events for the viewport() widget. The event is passed in \a
1262 \sa QWidget::wheelEvent()
1264 #ifndef QT_NO_WHEELEVENT
1265 void QAbstractScrollArea::wheelEvent(QWheelEvent *e)
1267 Q_D(QAbstractScrollArea);
1268 if (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal)
1269 QApplication::sendEvent(d->hbar, e);
1271 QApplication::sendEvent(d->vbar, e);
1275 #ifndef QT_NO_CONTEXTMENU
1277 This event handler can be reimplemented in a subclass to receive
1278 context menu events for the viewport() widget. The event is passed
1281 \sa QWidget::contextMenuEvent()
1283 void QAbstractScrollArea::contextMenuEvent(QContextMenuEvent *e)
1287 #endif // QT_NO_CONTEXTMENU
1290 This function is called with key event \a e when key presses
1291 occur. It handles PageUp, PageDown, Up, Down, Left, and Right, and
1292 ignores all other key presses.
1294 void QAbstractScrollArea::keyPressEvent(QKeyEvent * e)
1296 Q_D(QAbstractScrollArea);
1298 #ifndef QT_NO_SHORTCUT
1299 } else if (e == QKeySequence::MoveToPreviousPage) {
1300 d->vbar->triggerAction(QScrollBar::SliderPageStepSub);
1301 } else if (e == QKeySequence::MoveToNextPage) {
1302 d->vbar->triggerAction(QScrollBar::SliderPageStepAdd);
1305 #ifdef QT_KEYPAD_NAVIGATION
1306 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1313 d->vbar->triggerAction(QScrollBar::SliderSingleStepSub);
1316 d->vbar->triggerAction(QScrollBar::SliderSingleStepAdd);
1319 #ifdef QT_KEYPAD_NAVIGATION
1320 if (QApplication::keypadNavigationEnabled() && hasEditFocus()
1321 && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->minimum())) {
1322 //if we aren't using the hbar or we are already at the leftmost point ignore
1327 d->hbar->triggerAction(
1328 layoutDirection() == Qt::LeftToRight
1329 ? QScrollBar::SliderSingleStepSub : QScrollBar::SliderSingleStepAdd);
1332 #ifdef QT_KEYPAD_NAVIGATION
1333 if (QApplication::keypadNavigationEnabled() && hasEditFocus()
1334 && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->maximum())) {
1335 //if we aren't using the hbar or we are already at the rightmost point ignore
1340 d->hbar->triggerAction(
1341 layoutDirection() == Qt::LeftToRight
1342 ? QScrollBar::SliderSingleStepAdd : QScrollBar::SliderSingleStepSub);
1353 #ifndef QT_NO_DRAGANDDROP
1355 \fn void QAbstractScrollArea::dragEnterEvent(QDragEnterEvent *event)
1357 This event handler can be reimplemented in a subclass to receive
1358 drag enter events (passed in \a event), for the viewport() widget.
1360 \sa QWidget::dragEnterEvent()
1362 void QAbstractScrollArea::dragEnterEvent(QDragEnterEvent *)
1367 \fn void QAbstractScrollArea::dragMoveEvent(QDragMoveEvent *event)
1369 This event handler can be reimplemented in a subclass to receive
1370 drag move events (passed in \a event), for the viewport() widget.
1372 \sa QWidget::dragMoveEvent()
1374 void QAbstractScrollArea::dragMoveEvent(QDragMoveEvent *)
1379 \fn void QAbstractScrollArea::dragLeaveEvent(QDragLeaveEvent *event)
1381 This event handler can be reimplemented in a subclass to receive
1382 drag leave events (passed in \a event), for the viewport() widget.
1384 \sa QWidget::dragLeaveEvent()
1386 void QAbstractScrollArea::dragLeaveEvent(QDragLeaveEvent *)
1391 \fn void QAbstractScrollArea::dropEvent(QDropEvent *event)
1393 This event handler can be reimplemented in a subclass to receive
1394 drop events (passed in \a event), for the viewport() widget.
1396 \sa QWidget::dropEvent()
1398 void QAbstractScrollArea::dropEvent(QDropEvent *)
1406 This virtual handler is called when the scroll bars are moved by
1407 \a dx, \a dy, and consequently the viewport's contents should be
1408 scrolled accordingly.
1410 The default implementation simply calls update() on the entire
1411 viewport(), subclasses can reimplement this handler for
1412 optimization purposes, or - like QScrollArea - to move a contents
1413 widget. The parameters \a dx and \a dy are there for convenience,
1414 so that the class knows how much should be scrolled (useful
1415 e.g. when doing pixel-shifts). You may just as well ignore these
1416 values and scroll directly to the position the scroll bars
1419 Calling this function in order to scroll programmatically is an
1420 error, use the scroll bars instead (e.g. by calling
1421 QScrollBar::setValue() directly).
1423 void QAbstractScrollArea::scrollContentsBy(int, int)
1425 viewport()->update();
1428 bool QAbstractScrollAreaPrivate::canStartScrollingAt( const QPoint &startPos )
1430 Q_Q(QAbstractScrollArea);
1432 #ifndef QT_NO_GRAPHICSVIEW
1433 // don't start scrolling when a drag mode has been set.
1434 // don't start scrolling on a movable item.
1435 if (QGraphicsView *view = qobject_cast<QGraphicsView *>(q)) {
1436 if (view->dragMode() != QGraphicsView::NoDrag)
1439 QGraphicsItem *childItem = view->itemAt(startPos);
1441 if (childItem && (childItem->flags() & QGraphicsItem::ItemIsMovable))
1446 // don't start scrolling on a QAbstractSlider
1447 if (qobject_cast<QAbstractSlider *>(q->viewport()->childAt(startPos))) {
1454 void QAbstractScrollAreaPrivate::flashScrollBars()
1456 if (hbarpolicy == Qt::ScrollBarAsNeeded)
1457 hbar->d_func()->flash();
1458 if (vbarpolicy == Qt::ScrollBarAsNeeded)
1459 vbar->d_func()->flash();
1462 void QAbstractScrollAreaPrivate::setScrollBarTransient(QScrollBar *scrollBar, bool transient)
1464 scrollBar->d_func()->setTransient(transient);
1467 void QAbstractScrollAreaPrivate::_q_hslide(int x)
1469 Q_Q(QAbstractScrollArea);
1470 int dx = xoffset - x;
1472 q->scrollContentsBy(dx, 0);
1476 void QAbstractScrollAreaPrivate::_q_vslide(int y)
1478 Q_Q(QAbstractScrollArea);
1479 int dy = yoffset - y;
1481 q->scrollContentsBy(0, dy);
1485 void QAbstractScrollAreaPrivate::_q_showOrHideScrollBars()
1489 // Need to re-subscribe to gestures as the content changes to make sure we
1490 // enable/disable panning when needed.
1491 QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport));
1493 dd->winSetupGestures();
1497 QPoint QAbstractScrollAreaPrivate::contentsOffset() const
1499 Q_Q(const QAbstractScrollArea);
1501 if (vbar->isVisible())
1502 offset.setY(vbar->value());
1503 if (hbar->isVisible()) {
1504 if (q->isRightToLeft())
1505 offset.setX(hbar->maximum() - hbar->value());
1507 offset.setX(hbar->value());
1516 QSize QAbstractScrollArea::minimumSizeHint() const
1518 Q_D(const QAbstractScrollArea);
1519 int hsbExt = d->hbar->sizeHint().height();
1520 int vsbExt = d->vbar->sizeHint().width();
1521 int extra = 2 * d->frameWidth;
1524 if ((d->frameStyle != QFrame::NoFrame)
1525 && style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, this)) {
1526 extra += style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, this);
1528 return QSize(d->scrollBarContainers[Qt::Horizontal]->sizeHint().width() + vsbExt + extra,
1529 d->scrollBarContainers[Qt::Vertical]->sizeHint().height() + hsbExt + extra);
1535 QSize QAbstractScrollArea::sizeHint() const
1537 return QSize(256, 192);
1539 Q_D(const QAbstractScrollArea);
1540 int h = qMax(10, fontMetrics().height());
1541 int f = 2 * d->frameWidth;
1542 return QSize((6 * h) + f, (4 * h) + f);
1547 This slot is called by QAbstractScrollArea after setViewport(\a
1548 viewport) has been called. Reimplement this function in a
1549 subclass of QAbstractScrollArea to initialize the new \a viewport
1554 void QAbstractScrollArea::setupViewport(QWidget *viewport)
1562 This method is reserved for future use.
1564 QSize QAbstractScrollArea::viewportSizeHint() const
1571 #include "moc_qabstractscrollarea.cpp"
1572 #include "moc_qabstractscrollarea_p.cpp"
1574 #endif // QT_NO_SCROLLAREA