util/src/gui/widgets/qabstractscrollarea.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    66 QT_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 
       
   159 QAbstractScrollAreaPrivate::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 
       
   169 QAbstractScrollAreaScrollBarContainer::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 */
       
   183 void 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 */
       
   201 QWidgetList 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 */
       
   222 int 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 */
       
   234 void 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 
       
   269 void 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     viewport->grabGesture(Qt::PanGesture);
       
   299 #endif
       
   300 }
       
   301 
       
   302 #ifdef Q_WS_WIN
       
   303 void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on)
       
   304 {
       
   305     singleFingerPanEnabled = on;
       
   306     QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport));
       
   307     if (dd)
       
   308         dd->winSetupGestures();
       
   309 }
       
   310 #endif // Q_WS_WIN
       
   311 
       
   312 void QAbstractScrollAreaPrivate::layoutChildren()
       
   313 {
       
   314     Q_Q(QAbstractScrollArea);
       
   315     bool needh = (hbarpolicy == Qt::ScrollBarAlwaysOn
       
   316                   || (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum()));
       
   317 
       
   318     bool needv = (vbarpolicy == Qt::ScrollBarAlwaysOn
       
   319                   || (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum()));
       
   320 
       
   321 #ifdef Q_WS_MAC
       
   322     QWidget * const window = q->window();
       
   323 
       
   324     // Use small scroll bars for tool windows, to match the native size grip.
       
   325     bool hbarIsSmall = hbar->testAttribute(Qt::WA_MacSmallSize);
       
   326     bool vbarIsSmall = vbar->testAttribute(Qt::WA_MacSmallSize);
       
   327     const Qt::WindowType windowType = window->windowType();
       
   328     if (windowType == Qt::Tool) {
       
   329         if (!hbarIsSmall) {
       
   330             hbar->setAttribute(Qt::WA_MacMiniSize, false);
       
   331             hbar->setAttribute(Qt::WA_MacNormalSize, false);
       
   332             hbar->setAttribute(Qt::WA_MacSmallSize, true);
       
   333         }
       
   334         if (!vbarIsSmall) {
       
   335             vbar->setAttribute(Qt::WA_MacMiniSize, false);
       
   336             vbar->setAttribute(Qt::WA_MacNormalSize, false);
       
   337             vbar->setAttribute(Qt::WA_MacSmallSize, true);
       
   338         }
       
   339     } else {
       
   340         if (hbarIsSmall) {
       
   341             hbar->setAttribute(Qt::WA_MacMiniSize, false);
       
   342             hbar->setAttribute(Qt::WA_MacNormalSize, false);
       
   343             hbar->setAttribute(Qt::WA_MacSmallSize, false);
       
   344         }
       
   345         if (vbarIsSmall) {
       
   346             vbar->setAttribute(Qt::WA_MacMiniSize, false);
       
   347             vbar->setAttribute(Qt::WA_MacNormalSize, false);
       
   348             vbar->setAttribute(Qt::WA_MacSmallSize, false);
       
   349         }
       
   350      }
       
   351 #endif
       
   352 
       
   353     const int hsbExt = hbar->sizeHint().height();
       
   354     const int vsbExt = vbar->sizeHint().width();
       
   355     const QPoint extPoint(vsbExt, hsbExt);
       
   356     const QSize extSize(vsbExt, hsbExt);
       
   357 
       
   358     const QRect widgetRect = q->rect();
       
   359     QStyleOption opt(0);
       
   360     opt.init(q);
       
   361 
       
   362     const bool hasCornerWidget = (cornerWidget != 0);
       
   363 
       
   364 // If the scroll bars are at the very right and bottom of the window we
       
   365 // move their positions to be aligned with the size grip.
       
   366 #ifdef Q_WS_MAC
       
   367     // Check if a native sizegrip is present.
       
   368     bool hasMacReverseSizeGrip = false;
       
   369     bool hasMacSizeGrip = false;
       
   370     bool nativeGripPresent = false;
       
   371     if (q->testAttribute(Qt::WA_WState_Created))
       
   372         nativeGripPresent = qt_mac_checkForNativeSizeGrip(q);
       
   373 
       
   374     if (nativeGripPresent) {
       
   375         // Look for a native size grip at the visual window bottom right and at the
       
   376         // absolute window bottom right. In reverse mode, the native size grip does not
       
   377         // swich side, so we need to check if it is on the "wrong side".
       
   378         const QPoint scrollAreaBottomRight = q->mapTo(window, widgetRect.bottomRight() - QPoint(frameWidth, frameWidth));
       
   379         const QPoint windowBottomRight = window->rect().bottomRight();
       
   380         const QPoint visualWindowBottomRight = QStyle::visualPos(opt.direction, opt.rect, windowBottomRight);
       
   381         const QPoint offset = windowBottomRight - scrollAreaBottomRight;
       
   382         const QPoint visualOffset = visualWindowBottomRight - scrollAreaBottomRight;
       
   383         hasMacSizeGrip = (visualOffset.manhattanLength() < vsbExt);
       
   384         hasMacReverseSizeGrip = (hasMacSizeGrip == false && (offset.manhattanLength() < hsbExt));
       
   385     }
       
   386 #endif
       
   387 
       
   388     QPoint cornerOffset(needv ? vsbExt : 0, needh ? hsbExt : 0);
       
   389     QRect controlsRect;
       
   390     QRect viewportRect;
       
   391 
       
   392     // In FrameOnlyAroundContents mode the frame is drawn between the controls and
       
   393     // the viewport, else the frame rect is equal to the widget rect.
       
   394     if ((frameStyle != QFrame::NoFrame) &&
       
   395         q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, q)) {
       
   396         controlsRect = widgetRect;
       
   397         const int extra = q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing);
       
   398         const QPoint cornerExtra(needv ? extra : 0, needh ? extra : 0);
       
   399         QRect frameRect = widgetRect;
       
   400         frameRect.adjust(0, 0, -cornerOffset.x() - cornerExtra.x(), -cornerOffset.y() - cornerExtra.y());
       
   401         q->setFrameRect(QStyle::visualRect(opt.direction, opt.rect, frameRect));
       
   402         // The frame rect needs to be in logical coords, however we need to flip
       
   403         // the contentsRect back before passing it on to the viewportRect
       
   404         // since the viewportRect has its logical coords calculated later.
       
   405         viewportRect = QStyle::visualRect(opt.direction, opt.rect, q->contentsRect());
       
   406     } else {
       
   407         q->setFrameRect(QStyle::visualRect(opt.direction, opt.rect, widgetRect));
       
   408         controlsRect = q->contentsRect();
       
   409         viewportRect = QRect(controlsRect.topLeft(), controlsRect.bottomRight() - cornerOffset);
       
   410     }
       
   411 
       
   412     // If we have a corner widget and are only showing one scroll bar, we need to move it
       
   413     // to make room for the corner widget.
       
   414     if (hasCornerWidget && (needv || needh))
       
   415         cornerOffset =  extPoint;
       
   416 
       
   417 #ifdef Q_WS_MAC
       
   418     // Also move the scroll bars if they are covered by the native Mac size grip.
       
   419     if (hasMacSizeGrip)
       
   420         cornerOffset =  extPoint;
       
   421 #endif
       
   422 
       
   423     // The corner point is where the scroll bar rects, the corner widget rect and the
       
   424     // viewport rect meets.
       
   425     const QPoint cornerPoint(controlsRect.bottomRight() + QPoint(1, 1) - cornerOffset);
       
   426 
       
   427     // Some styles paints the corner if both scorllbars are showing and there is
       
   428     // no corner widget. Also, on the Mac we paint if there is a native
       
   429     // (transparent) sizegrip in the area where a corner widget would be.
       
   430     if ((needv && needh && hasCornerWidget == false)
       
   431         || ((needv || needh) 
       
   432 #ifdef Q_WS_MAC
       
   433         && hasMacSizeGrip
       
   434 #endif
       
   435         )
       
   436     ) {
       
   437         cornerPaintingRect = QStyle::visualRect(opt.direction, opt.rect, QRect(cornerPoint, extSize));
       
   438     } else {
       
   439         cornerPaintingRect = QRect();
       
   440     }
       
   441 
       
   442 #ifdef Q_WS_MAC
       
   443     if (hasMacReverseSizeGrip)
       
   444         reverseCornerPaintingRect = QRect(controlsRect.bottomRight() + QPoint(1, 1) - extPoint, extSize);
       
   445     else
       
   446         reverseCornerPaintingRect = QRect();
       
   447 #endif
       
   448 
       
   449     if (needh) {
       
   450         QRect horizontalScrollBarRect(QPoint(controlsRect.left(), cornerPoint.y()), QPoint(cornerPoint.x() - 1, controlsRect.bottom()));
       
   451 #ifdef Q_WS_MAC
       
   452         if (hasMacReverseSizeGrip)
       
   453             horizontalScrollBarRect.adjust(vsbExt, 0, 0, 0);
       
   454 #endif
       
   455         scrollBarContainers[Qt::Horizontal]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, horizontalScrollBarRect));
       
   456         scrollBarContainers[Qt::Horizontal]->raise();
       
   457     }
       
   458 
       
   459     if (needv) {
       
   460         const QRect verticalScrollBarRect  (QPoint(cornerPoint.x(), controlsRect.top()),  QPoint(controlsRect.right(), cornerPoint.y() - 1));
       
   461         scrollBarContainers[Qt::Vertical]->setGeometry(QStyle::visualRect(opt.direction, opt.rect, verticalScrollBarRect));
       
   462         scrollBarContainers[Qt::Vertical]->raise();
       
   463     }
       
   464 
       
   465     if (cornerWidget) {
       
   466         const QRect cornerWidgetRect(cornerPoint, controlsRect.bottomRight());
       
   467         cornerWidget->setGeometry(QStyle::visualRect(opt.direction, opt.rect, cornerWidgetRect));
       
   468     }
       
   469 
       
   470     scrollBarContainers[Qt::Horizontal]->setVisible(needh);
       
   471     scrollBarContainers[Qt::Vertical]->setVisible(needv);
       
   472 
       
   473     if (q->isRightToLeft())
       
   474         viewportRect.adjust(right, top, -left, -bottom);
       
   475     else
       
   476         viewportRect.adjust(left, top, -right, -bottom);
       
   477 
       
   478     viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last
       
   479 }
       
   480 
       
   481 /*!
       
   482     \internal
       
   483 
       
   484     Creates a new QAbstractScrollAreaPrivate, \a dd with the given \a parent.
       
   485 */
       
   486 QAbstractScrollArea::QAbstractScrollArea(QAbstractScrollAreaPrivate &dd, QWidget *parent)
       
   487     :QFrame(dd, parent)
       
   488 {
       
   489     Q_D(QAbstractScrollArea);
       
   490     QT_TRY {
       
   491         d->init();
       
   492     } QT_CATCH(...) {
       
   493         d->viewportFilter.reset();
       
   494         QT_RETHROW;
       
   495     }
       
   496 }
       
   497 
       
   498 /*!
       
   499     Constructs a viewport.
       
   500 
       
   501     The \a parent arguments is sent to the QWidget constructor.
       
   502 */
       
   503 QAbstractScrollArea::QAbstractScrollArea(QWidget *parent)
       
   504     :QFrame(*new QAbstractScrollAreaPrivate, parent)
       
   505 {
       
   506     Q_D(QAbstractScrollArea);
       
   507     QT_TRY {
       
   508         d->init();
       
   509     } QT_CATCH(...) {
       
   510         d->viewportFilter.reset();
       
   511         QT_RETHROW;
       
   512     }
       
   513 }
       
   514 
       
   515 
       
   516 /*!
       
   517   Destroys the viewport.
       
   518  */
       
   519 QAbstractScrollArea::~QAbstractScrollArea()
       
   520 {
       
   521     Q_D(QAbstractScrollArea);
       
   522     // reset it here, otherwise we'll have a dangling pointer in ~QWidget
       
   523     d->viewportFilter.reset();
       
   524 }
       
   525 
       
   526 
       
   527 /*!
       
   528   \since 4.2
       
   529   Sets the viewport to be the given \a widget.
       
   530   The QAbstractScrollArea will take ownership of the given \a widget.
       
   531 
       
   532   If \a widget is 0, QAbstractScrollArea will assign a new QWidget instance
       
   533   for the viewport.
       
   534 
       
   535   \sa viewport()
       
   536 */
       
   537 void QAbstractScrollArea::setViewport(QWidget *widget)
       
   538 {
       
   539     Q_D(QAbstractScrollArea);
       
   540     if (widget != d->viewport) {
       
   541         QWidget *oldViewport = d->viewport;
       
   542         if (!widget)
       
   543             widget = new QWidget;
       
   544         d->viewport = widget;
       
   545         d->viewport->setParent(this);
       
   546         d->viewport->setFocusProxy(this);
       
   547         d->viewport->installEventFilter(d->viewportFilter.data());
       
   548 #ifndef Q_WS_MAC
       
   549         d->viewport->grabGesture(Qt::PanGesture);
       
   550 #endif
       
   551         d->layoutChildren();
       
   552         if (isVisible())
       
   553             d->viewport->show();
       
   554         QMetaObject::invokeMethod(this, "setupViewport", Q_ARG(QWidget *, widget));
       
   555         delete oldViewport;
       
   556     }
       
   557 }
       
   558 
       
   559 /*!
       
   560     Returns the viewport widget.
       
   561 
       
   562     Use the QScrollArea::widget() function to retrieve the contents of
       
   563     the viewport widget.
       
   564 
       
   565     \sa QScrollArea::widget()
       
   566 */
       
   567 QWidget *QAbstractScrollArea::viewport() const
       
   568 {
       
   569     Q_D(const QAbstractScrollArea);
       
   570     return d->viewport;
       
   571 }
       
   572 
       
   573 
       
   574 /*!
       
   575 Returns the size of the viewport as if the scroll bars had no valid
       
   576 scrolling range.
       
   577 */
       
   578 // ### still thinking about the name
       
   579 QSize QAbstractScrollArea::maximumViewportSize() const
       
   580 {
       
   581     Q_D(const QAbstractScrollArea);
       
   582     int hsbExt = d->hbar->sizeHint().height();
       
   583     int vsbExt = d->vbar->sizeHint().width();
       
   584 
       
   585     int f = 2 * d->frameWidth;
       
   586     QSize max = size() - QSize(f + d->left + d->right, f + d->top + d->bottom);
       
   587     if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
       
   588         max.rwidth() -= vsbExt;
       
   589     if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
       
   590         max.rheight() -= hsbExt;
       
   591     return max;
       
   592 }
       
   593 
       
   594 /*!
       
   595     \property QAbstractScrollArea::verticalScrollBarPolicy
       
   596     \brief the policy for the vertical scroll bar
       
   597 
       
   598     The default policy is Qt::ScrollBarAsNeeded.
       
   599 
       
   600     \sa horizontalScrollBarPolicy
       
   601 */
       
   602 
       
   603 Qt::ScrollBarPolicy QAbstractScrollArea::verticalScrollBarPolicy() const
       
   604 {
       
   605     Q_D(const QAbstractScrollArea);
       
   606     return d->vbarpolicy;
       
   607 }
       
   608 
       
   609 void QAbstractScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy)
       
   610 {
       
   611     Q_D(QAbstractScrollArea);
       
   612     const Qt::ScrollBarPolicy oldPolicy = d->vbarpolicy;
       
   613     d->vbarpolicy = policy;
       
   614     if (isVisible())
       
   615         d->layoutChildren();
       
   616     if (oldPolicy != d->vbarpolicy)
       
   617         d->scrollBarPolicyChanged(Qt::Vertical, d->vbarpolicy);
       
   618 }
       
   619 
       
   620 
       
   621 /*!
       
   622   Returns the vertical scroll bar.
       
   623 
       
   624   \sa verticalScrollBarPolicy, horizontalScrollBar()
       
   625  */
       
   626 QScrollBar *QAbstractScrollArea::verticalScrollBar() const
       
   627 {
       
   628     Q_D(const QAbstractScrollArea);
       
   629     return d->vbar;
       
   630 }
       
   631 
       
   632 /*!
       
   633    \since 4.2
       
   634    Replaces the existing vertical scroll bar with \a scrollBar, and sets all
       
   635    the former scroll bar's slider properties on the new scroll bar. The former
       
   636    scroll bar is then deleted.
       
   637 
       
   638    QAbstractScrollArea already provides vertical and horizontal scroll bars by
       
   639    default. You can call this function to replace the default vertical
       
   640    scroll bar with your own custom scroll bar.
       
   641 
       
   642    \sa verticalScrollBar(), setHorizontalScrollBar()
       
   643 */
       
   644 void QAbstractScrollArea::setVerticalScrollBar(QScrollBar *scrollBar)
       
   645 {
       
   646     Q_D(QAbstractScrollArea);
       
   647     if (!scrollBar) {
       
   648         qWarning("QAbstractScrollArea::setVerticalScrollBar: Cannot set a null scroll bar");
       
   649         return;
       
   650     }
       
   651 
       
   652     d->replaceScrollBar(scrollBar, Qt::Vertical);
       
   653 }
       
   654 
       
   655 /*!
       
   656     \property QAbstractScrollArea::horizontalScrollBarPolicy
       
   657     \brief the policy for the horizontal scroll bar
       
   658 
       
   659     The default policy is Qt::ScrollBarAsNeeded.
       
   660 
       
   661     \sa verticalScrollBarPolicy
       
   662 */
       
   663 
       
   664 Qt::ScrollBarPolicy QAbstractScrollArea::horizontalScrollBarPolicy() const
       
   665 {
       
   666     Q_D(const QAbstractScrollArea);
       
   667     return d->hbarpolicy;
       
   668 }
       
   669 
       
   670 void QAbstractScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
       
   671 {
       
   672     Q_D(QAbstractScrollArea);
       
   673     const Qt::ScrollBarPolicy oldPolicy = d->hbarpolicy;
       
   674     d->hbarpolicy = policy;
       
   675     if (isVisible())
       
   676         d->layoutChildren();
       
   677     if (oldPolicy != d->hbarpolicy)
       
   678         d->scrollBarPolicyChanged(Qt::Horizontal, d->hbarpolicy);
       
   679 }
       
   680 
       
   681 /*!
       
   682   Returns the horizontal scroll bar.
       
   683 
       
   684   \sa horizontalScrollBarPolicy, verticalScrollBar()
       
   685  */
       
   686 QScrollBar *QAbstractScrollArea::horizontalScrollBar() const
       
   687 {
       
   688     Q_D(const QAbstractScrollArea);
       
   689     return d->hbar;
       
   690 }
       
   691 
       
   692 /*!
       
   693     \since 4.2
       
   694 
       
   695     Replaces the existing horizontal scroll bar with \a scrollBar, and sets all
       
   696     the former scroll bar's slider properties on the new scroll bar. The former
       
   697     scroll bar is then deleted.
       
   698 
       
   699     QAbstractScrollArea already provides horizontal and vertical scroll bars by
       
   700     default. You can call this function to replace the default horizontal
       
   701     scroll bar with your own custom scroll bar.
       
   702 
       
   703     \sa horizontalScrollBar(), setVerticalScrollBar()
       
   704 */
       
   705 void QAbstractScrollArea::setHorizontalScrollBar(QScrollBar *scrollBar)
       
   706 {
       
   707     Q_D(QAbstractScrollArea);
       
   708     if (!scrollBar) {
       
   709         qWarning("QAbstractScrollArea::setHorizontalScrollBar: Cannot set a null scroll bar");
       
   710         return;
       
   711     }
       
   712 
       
   713     d->replaceScrollBar(scrollBar, Qt::Horizontal);
       
   714 }
       
   715 
       
   716 /*!
       
   717     \since 4.2
       
   718 
       
   719     Returns the widget in the corner between the two scroll bars.
       
   720 
       
   721     By default, no corner widget is present.
       
   722 */
       
   723 QWidget *QAbstractScrollArea::cornerWidget() const
       
   724 {
       
   725     Q_D(const QAbstractScrollArea);
       
   726     return d->cornerWidget;
       
   727 }
       
   728 
       
   729 /*!
       
   730     \since 4.2
       
   731 
       
   732     Sets the widget in the corner between the two scroll bars to be
       
   733     \a widget.
       
   734 
       
   735     You will probably also want to set at least one of the scroll bar
       
   736     modes to \c AlwaysOn.
       
   737 
       
   738     Passing 0 shows no widget in the corner.
       
   739 
       
   740     Any previous corner widget is hidden.
       
   741 
       
   742     You may call setCornerWidget() with the same widget at different
       
   743     times.
       
   744 
       
   745     All widgets set here will be deleted by the scroll area when it is
       
   746     destroyed unless you separately reparent the widget after setting
       
   747     some other corner widget (or 0).
       
   748 
       
   749     Any \e newly set widget should have no current parent.
       
   750 
       
   751     By default, no corner widget is present.
       
   752 
       
   753     \sa horizontalScrollBarPolicy, horizontalScrollBarPolicy
       
   754 */
       
   755 void QAbstractScrollArea::setCornerWidget(QWidget *widget)
       
   756 {
       
   757     Q_D(QAbstractScrollArea);
       
   758     QWidget* oldWidget = d->cornerWidget;
       
   759     if (oldWidget != widget) {
       
   760         if (oldWidget)
       
   761             oldWidget->hide();
       
   762         d->cornerWidget = widget;
       
   763 
       
   764         if (widget && widget->parentWidget() != this)
       
   765             widget->setParent(this);
       
   766 
       
   767         d->layoutChildren();
       
   768         if (widget)
       
   769             widget->show();
       
   770     } else {
       
   771         d->cornerWidget = widget;
       
   772         d->layoutChildren();
       
   773     }
       
   774 }
       
   775 
       
   776 /*!
       
   777     \since 4.2
       
   778     Adds \a widget as a scroll bar widget in the location specified
       
   779     by \a alignment.
       
   780 
       
   781     Scroll bar widgets are shown next to the horizontal or vertical
       
   782     scroll bar, and can be placed on either side of it. If you want
       
   783     the scroll bar widgets to be always visible, set the
       
   784     scrollBarPolicy for the corresponding scroll bar to \c AlwaysOn.
       
   785 
       
   786     \a alignment must be one of Qt::Alignleft and Qt::AlignRight,
       
   787     which maps to the horizontal scroll bar, or Qt::AlignTop and
       
   788     Qt::AlignBottom, which maps to the vertical scroll bar.
       
   789 
       
   790     A scroll bar widget can be removed by either re-parenting the
       
   791     widget or deleting it. It's also possible to hide a widget with
       
   792     QWidget::hide()
       
   793 
       
   794     The scroll bar widget will be resized to fit the scroll bar
       
   795     geometry for the current style. The following describes the case
       
   796     for scroll bar widgets on the horizontal scroll bar:
       
   797 
       
   798     The height of the widget will be set to match the height of the
       
   799     scroll bar. To control the width of the widget, use
       
   800     QWidget::setMinimumWidth and QWidget::setMaximumWidth, or
       
   801     implement QWidget::sizeHint() and set a horizontal size policy.
       
   802     If you want a square widget, call
       
   803     QStyle::pixelMetric(QStyle::PM_ScrollBarExtent) and set the
       
   804     width to this value.
       
   805 
       
   806     \sa scrollBarWidgets()
       
   807 */
       
   808 void QAbstractScrollArea::addScrollBarWidget(QWidget *widget, Qt::Alignment alignment)
       
   809 {
       
   810     Q_D(QAbstractScrollArea);
       
   811 
       
   812     if (widget == 0)
       
   813         return;
       
   814 
       
   815     const Qt::Orientation scrollBarOrientation
       
   816         = ((alignment & Qt::AlignLeft) || (alignment & Qt::AlignRight)) ? Qt::Horizontal : Qt::Vertical;
       
   817     const QAbstractScrollAreaScrollBarContainer::LogicalPosition position
       
   818         = ((alignment & Qt::AlignRight) || (alignment & Qt::AlignBottom))
       
   819           ? QAbstractScrollAreaScrollBarContainer::LogicalRight : QAbstractScrollAreaScrollBarContainer::LogicalLeft;
       
   820     d->scrollBarContainers[scrollBarOrientation]->addWidget(widget, position);
       
   821     d->layoutChildren();
       
   822     if (isHidden() == false)
       
   823         widget->show();
       
   824 }
       
   825 
       
   826 /*!
       
   827     \since 4.2
       
   828     Returns a list of the currently set scroll bar widgets. \a alignment
       
   829     can be any combination of the four location flags.
       
   830 
       
   831     \sa addScrollBarWidget()
       
   832 */
       
   833 QWidgetList QAbstractScrollArea::scrollBarWidgets(Qt::Alignment alignment)
       
   834 {
       
   835     Q_D(QAbstractScrollArea);
       
   836 
       
   837     QWidgetList list;
       
   838 
       
   839     if (alignment & Qt::AlignLeft)
       
   840         list += d->scrollBarContainers[Qt::Horizontal]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalLeft);
       
   841     if (alignment & Qt::AlignRight)
       
   842         list += d->scrollBarContainers[Qt::Horizontal]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalRight);
       
   843     if (alignment & Qt::AlignTop)
       
   844         list += d->scrollBarContainers[Qt::Vertical]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalLeft);
       
   845     if (alignment & Qt::AlignBottom)
       
   846         list += d->scrollBarContainers[Qt::Vertical]->widgets(QAbstractScrollAreaScrollBarContainer::LogicalRight);
       
   847 
       
   848     return list;
       
   849 }
       
   850 
       
   851 /*!
       
   852     Sets the margins around the scrolling area to \a left, \a top, \a
       
   853     right and \a bottom. This is useful for applications such as
       
   854     spreadsheets with "locked" rows and columns. The marginal space is
       
   855     is left blank; put widgets in the unused area.
       
   856 
       
   857     Note that this function is frequently called by QTreeView and
       
   858     QTableView, so margins must be implemented by QAbstractScrollArea
       
   859     subclasses. Also, if the subclasses are to be used in item views,
       
   860     they should not call this function.
       
   861 
       
   862     By default all margins are zero.
       
   863 
       
   864 */
       
   865 void QAbstractScrollArea::setViewportMargins(int left, int top, int right, int bottom)
       
   866 {
       
   867     Q_D(QAbstractScrollArea);
       
   868     d->left = left;
       
   869     d->top = top;
       
   870     d->right = right;
       
   871     d->bottom = bottom;
       
   872     d->layoutChildren();
       
   873 }
       
   874 
       
   875 /*!
       
   876     \since 4.6
       
   877     Sets \a margins around the scrolling area. This is useful for
       
   878     applications such as spreadsheets with "locked" rows and columns.
       
   879     The marginal space is is left blank; put widgets in the unused
       
   880     area.
       
   881 
       
   882     By default all margins are zero.
       
   883 
       
   884 */
       
   885 void QAbstractScrollArea::setViewportMargins(const QMargins &margins)
       
   886 {
       
   887     setViewportMargins(margins.left(), margins.top(),
       
   888                        margins.right(), margins.bottom());
       
   889 }
       
   890 
       
   891 /*!
       
   892     \fn bool QAbstractScrollArea::event(QEvent *event)
       
   893 
       
   894     \reimp
       
   895 
       
   896     This is the main event handler for the QAbstractScrollArea widget (\e not
       
   897     the scrolling area viewport()). The specified \a event is a general event
       
   898     object that may need to be cast to the appropriate class depending on its
       
   899     type.
       
   900 
       
   901     \sa QEvent::type()
       
   902 */
       
   903 bool QAbstractScrollArea::event(QEvent *e)
       
   904 {
       
   905     Q_D(QAbstractScrollArea);
       
   906     switch (e->type()) {
       
   907     case QEvent::AcceptDropsChange:
       
   908         // There was a chance that with accessibility client we get an
       
   909         // event before the viewport was created.
       
   910         // Also, in some cases we might get here from QWidget::event() virtual function which is (indirectly) called
       
   911         // from the viewport constructor at the time when the d->viewport is not yet initialized even without any
       
   912         // accessibility client. See qabstractscrollarea autotest for a test case.
       
   913         if (d->viewport)
       
   914             d->viewport->setAcceptDrops(acceptDrops());
       
   915         break;
       
   916     case QEvent::MouseTrackingChange:
       
   917         d->viewport->setMouseTracking(hasMouseTracking());
       
   918         break;
       
   919     case QEvent::Resize:
       
   920             d->layoutChildren();
       
   921             break;
       
   922     case QEvent::Paint: {
       
   923         QStyleOption option;
       
   924         option.initFrom(this);
       
   925         if (d->cornerPaintingRect.isValid()) {
       
   926             option.rect = d->cornerPaintingRect;
       
   927             QPainter p(this);
       
   928             style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
       
   929         }
       
   930 #ifdef Q_WS_MAC
       
   931         if (d->reverseCornerPaintingRect.isValid()) {
       
   932             option.rect = d->reverseCornerPaintingRect;
       
   933             QPainter p(this);
       
   934             style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
       
   935         }
       
   936 #endif
       
   937         }
       
   938         QFrame::paintEvent((QPaintEvent*)e);
       
   939         break;
       
   940 #ifndef QT_NO_CONTEXTMENU
       
   941     case QEvent::ContextMenu:
       
   942         if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard)
       
   943            return QFrame::event(e);
       
   944         e->ignore();
       
   945         break;
       
   946 #endif // QT_NO_CONTEXTMENU
       
   947     case QEvent::MouseButtonPress:
       
   948     case QEvent::MouseButtonRelease:
       
   949     case QEvent::MouseButtonDblClick:
       
   950     case QEvent::MouseMove:
       
   951     case QEvent::Wheel:
       
   952 #ifndef QT_NO_DRAGANDDROP
       
   953     case QEvent::Drop:
       
   954     case QEvent::DragEnter:
       
   955     case QEvent::DragMove:
       
   956     case QEvent::DragLeave:
       
   957 #endif
       
   958         // ignore touch events in case they have been propagated from the viewport
       
   959     case QEvent::TouchBegin:
       
   960     case QEvent::TouchUpdate:
       
   961     case QEvent::TouchEnd:
       
   962         return false;
       
   963     case QEvent::Gesture:
       
   964     {
       
   965         QGestureEvent *ge = static_cast<QGestureEvent *>(e);
       
   966         QPanGesture *g = static_cast<QPanGesture *>(ge->gesture(Qt::PanGesture));
       
   967         if (g) {
       
   968             QScrollBar *hBar = horizontalScrollBar();
       
   969             QScrollBar *vBar = verticalScrollBar();
       
   970             QPointF delta = g->delta();
       
   971             if (!delta.isNull()) {
       
   972                 if (QApplication::isRightToLeft())
       
   973                     delta.rx() *= -1;
       
   974                 int newX = hBar->value() - delta.x();
       
   975                 int newY = vBar->value() - delta.y();
       
   976                 hBar->setValue(newX);
       
   977                 vBar->setValue(newY);
       
   978             }
       
   979             return true;
       
   980         }
       
   981         return false;
       
   982     }
       
   983     case QEvent::StyleChange:
       
   984     case QEvent::LayoutDirectionChange:
       
   985     case QEvent::ApplicationLayoutDirectionChange:
       
   986         d->layoutChildren();
       
   987         // fall through
       
   988     default:
       
   989         return QFrame::event(e);
       
   990     }
       
   991     return true;
       
   992 }
       
   993 
       
   994 /*!
       
   995   \fn bool QAbstractScrollArea::viewportEvent(QEvent *event)
       
   996 
       
   997   The main event handler for the scrolling area (the viewport() widget).
       
   998   It handles the \a event specified, and can be called by subclasses to
       
   999   provide reasonable default behavior.
       
  1000 
       
  1001   Returns true to indicate to the event system that the event has been
       
  1002   handled, and needs no further processing; otherwise returns false to
       
  1003   indicate that the event should be propagated further.
       
  1004 
       
  1005   You can reimplement this function in a subclass, but we recommend
       
  1006   using one of the specialized event handlers instead.
       
  1007 
       
  1008   Specialised handlers for viewport events are: paintEvent(),
       
  1009   mousePressEvent(), mouseReleaseEvent(), mouseDoubleClickEvent(),
       
  1010   mouseMoveEvent(), wheelEvent(), dragEnterEvent(), dragMoveEvent(),
       
  1011   dragLeaveEvent(), dropEvent(), contextMenuEvent(), and
       
  1012   resizeEvent().
       
  1013 */
       
  1014 bool QAbstractScrollArea::viewportEvent(QEvent *e)
       
  1015 {
       
  1016     switch (e->type()) {
       
  1017     case QEvent::Resize:
       
  1018     case QEvent::Paint:
       
  1019     case QEvent::MouseButtonPress:
       
  1020     case QEvent::MouseButtonRelease:
       
  1021     case QEvent::MouseButtonDblClick:
       
  1022     case QEvent::TouchBegin:
       
  1023     case QEvent::TouchUpdate:
       
  1024     case QEvent::TouchEnd:
       
  1025     case QEvent::MouseMove:
       
  1026     case QEvent::ContextMenu:
       
  1027 #ifndef QT_NO_WHEELEVENT
       
  1028     case QEvent::Wheel:
       
  1029 #endif
       
  1030 #ifndef QT_NO_DRAGANDDROP
       
  1031     case QEvent::Drop:
       
  1032     case QEvent::DragEnter:
       
  1033     case QEvent::DragMove:
       
  1034     case QEvent::DragLeave:
       
  1035 #endif
       
  1036         return QFrame::event(e);
       
  1037     case QEvent::LayoutRequest:
       
  1038     case QEvent::Gesture:
       
  1039     case QEvent::GestureOverride:
       
  1040         return event(e);
       
  1041     default:
       
  1042         break;
       
  1043     }
       
  1044     return false; // let the viewport widget handle the event
       
  1045 }
       
  1046 
       
  1047 /*!
       
  1048     \fn void QAbstractScrollArea::resizeEvent(QResizeEvent *event)
       
  1049 
       
  1050     This event handler can be reimplemented in a subclass to receive
       
  1051     resize events (passed in \a event), for the viewport() widget.
       
  1052 
       
  1053     When resizeEvent() is called, the viewport already has its new
       
  1054     geometry: Its new size is accessible through the
       
  1055     QResizeEvent::size() function, and the old size through
       
  1056     QResizeEvent::oldSize().
       
  1057 
       
  1058     \sa QWidget::resizeEvent()
       
  1059  */
       
  1060 void QAbstractScrollArea::resizeEvent(QResizeEvent *)
       
  1061 {
       
  1062 }
       
  1063 
       
  1064 /*!
       
  1065     \fn void QAbstractScrollArea::paintEvent(QPaintEvent *event)
       
  1066 
       
  1067     This event handler can be reimplemented in a subclass to receive
       
  1068     paint events (passed in \a event), for the viewport() widget.
       
  1069 
       
  1070     \note If you open a painter, make sure to open it on the viewport().
       
  1071 
       
  1072     \sa QWidget::paintEvent()
       
  1073 */
       
  1074 void QAbstractScrollArea::paintEvent(QPaintEvent*)
       
  1075 {
       
  1076 }
       
  1077 
       
  1078 /*!
       
  1079     This event handler can be reimplemented in a subclass to receive
       
  1080     mouse press events for the viewport() widget. The event is passed
       
  1081     in \a e.
       
  1082 
       
  1083     \sa QWidget::mousePressEvent()
       
  1084 */
       
  1085 void QAbstractScrollArea::mousePressEvent(QMouseEvent *e)
       
  1086 {
       
  1087     e->ignore();
       
  1088 }
       
  1089 
       
  1090 /*!
       
  1091     This event handler can be reimplemented in a subclass to receive
       
  1092     mouse release events for the viewport() widget. The event is
       
  1093     passed in \a e.
       
  1094 
       
  1095     \sa QWidget::mouseReleaseEvent()
       
  1096 */
       
  1097 void QAbstractScrollArea::mouseReleaseEvent(QMouseEvent *e)
       
  1098 {
       
  1099     e->ignore();
       
  1100 }
       
  1101 
       
  1102 /*!
       
  1103     This event handler can be reimplemented in a subclass to receive
       
  1104     mouse double click events for the viewport() widget. The event is
       
  1105     passed in \a e.
       
  1106 
       
  1107     \sa QWidget::mouseDoubleClickEvent()
       
  1108 */
       
  1109 void QAbstractScrollArea::mouseDoubleClickEvent(QMouseEvent *e)
       
  1110 {
       
  1111     e->ignore();
       
  1112 }
       
  1113 
       
  1114 /*!
       
  1115     This event handler can be reimplemented in a subclass to receive
       
  1116     mouse move events for the viewport() widget. The event is passed
       
  1117     in \a e.
       
  1118 
       
  1119     \sa QWidget::mouseMoveEvent()
       
  1120 */
       
  1121 void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e)
       
  1122 {
       
  1123     e->ignore();
       
  1124 }
       
  1125 
       
  1126 /*!
       
  1127     This event handler can be reimplemented in a subclass to receive
       
  1128     wheel events for the viewport() widget. The event is passed in \a
       
  1129     e.
       
  1130 
       
  1131     \sa QWidget::wheelEvent()
       
  1132 */
       
  1133 #ifndef QT_NO_WHEELEVENT
       
  1134 void QAbstractScrollArea::wheelEvent(QWheelEvent *e)
       
  1135 {
       
  1136     Q_D(QAbstractScrollArea);
       
  1137     if (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal)
       
  1138         QApplication::sendEvent(d->hbar, e);
       
  1139     else
       
  1140         QApplication::sendEvent(d->vbar, e);
       
  1141 }
       
  1142 #endif
       
  1143 
       
  1144 #ifndef QT_NO_CONTEXTMENU
       
  1145 /*!
       
  1146     This event handler can be reimplemented in a subclass to receive
       
  1147     context menu events for the viewport() widget. The event is passed
       
  1148     in \a e.
       
  1149 
       
  1150     \sa QWidget::contextMenuEvent()
       
  1151 */
       
  1152 void QAbstractScrollArea::contextMenuEvent(QContextMenuEvent *e)
       
  1153 {
       
  1154     e->ignore();
       
  1155 }
       
  1156 #endif // QT_NO_CONTEXTMENU
       
  1157 
       
  1158 /*!
       
  1159     This function is called with key event \a e when key presses
       
  1160     occur. It handles PageUp, PageDown, Up, Down, Left, and Right, and
       
  1161     ignores all other key presses.
       
  1162 */
       
  1163 void QAbstractScrollArea::keyPressEvent(QKeyEvent * e)
       
  1164 {
       
  1165     Q_D(QAbstractScrollArea);
       
  1166     if (false){
       
  1167 #ifndef QT_NO_SHORTCUT
       
  1168     } else if (e == QKeySequence::MoveToPreviousPage) {
       
  1169         d->vbar->triggerAction(QScrollBar::SliderPageStepSub);
       
  1170     } else if (e == QKeySequence::MoveToNextPage) {
       
  1171         d->vbar->triggerAction(QScrollBar::SliderPageStepAdd);
       
  1172 #endif
       
  1173     } else {
       
  1174 #ifdef QT_KEYPAD_NAVIGATION
       
  1175         if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
       
  1176             e->ignore();
       
  1177             return;
       
  1178         }
       
  1179 #endif
       
  1180         switch (e->key()) {
       
  1181         case Qt::Key_Up:
       
  1182             d->vbar->triggerAction(QScrollBar::SliderSingleStepSub);
       
  1183             break;
       
  1184         case Qt::Key_Down:
       
  1185             d->vbar->triggerAction(QScrollBar::SliderSingleStepAdd);
       
  1186             break;
       
  1187         case Qt::Key_Left:
       
  1188 #ifdef QT_KEYPAD_NAVIGATION
       
  1189         if (QApplication::keypadNavigationEnabled() && hasEditFocus()
       
  1190             && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->minimum())) {
       
  1191             //if we aren't using the hbar or we are already at the leftmost point ignore
       
  1192             e->ignore();
       
  1193             return;
       
  1194         }
       
  1195 #endif
       
  1196             d->hbar->triggerAction(
       
  1197                 layoutDirection() == Qt::LeftToRight
       
  1198                 ? QScrollBar::SliderSingleStepSub : QScrollBar::SliderSingleStepAdd);
       
  1199             break;
       
  1200         case Qt::Key_Right:
       
  1201 #ifdef QT_KEYPAD_NAVIGATION
       
  1202         if (QApplication::keypadNavigationEnabled() && hasEditFocus()
       
  1203             && (!d->hbar->isVisible() || d->hbar->value() == d->hbar->maximum())) {
       
  1204             //if we aren't using the hbar or we are already at the rightmost point ignore
       
  1205             e->ignore();
       
  1206             return;
       
  1207         }
       
  1208 #endif
       
  1209             d->hbar->triggerAction(
       
  1210                 layoutDirection() == Qt::LeftToRight
       
  1211                 ? QScrollBar::SliderSingleStepAdd : QScrollBar::SliderSingleStepSub);
       
  1212             break;
       
  1213         default:
       
  1214             e->ignore();
       
  1215             return;
       
  1216         }
       
  1217     }
       
  1218     e->accept();
       
  1219 }
       
  1220 
       
  1221 
       
  1222 #ifndef QT_NO_DRAGANDDROP
       
  1223 /*!
       
  1224     \fn void QAbstractScrollArea::dragEnterEvent(QDragEnterEvent *event)
       
  1225 
       
  1226     This event handler can be reimplemented in a subclass to receive
       
  1227     drag enter events (passed in \a event), for the viewport() widget.
       
  1228 
       
  1229     \sa QWidget::dragEnterEvent()
       
  1230 */
       
  1231 void QAbstractScrollArea::dragEnterEvent(QDragEnterEvent *)
       
  1232 {
       
  1233 }
       
  1234 
       
  1235 /*!
       
  1236     \fn void QAbstractScrollArea::dragMoveEvent(QDragMoveEvent *event)
       
  1237 
       
  1238     This event handler can be reimplemented in a subclass to receive
       
  1239     drag move events (passed in \a event), for the viewport() widget.
       
  1240 
       
  1241     \sa QWidget::dragMoveEvent()
       
  1242 */
       
  1243 void QAbstractScrollArea::dragMoveEvent(QDragMoveEvent *)
       
  1244 {
       
  1245 }
       
  1246 
       
  1247 /*!
       
  1248     \fn void QAbstractScrollArea::dragLeaveEvent(QDragLeaveEvent *event)
       
  1249 
       
  1250     This event handler can be reimplemented in a subclass to receive
       
  1251     drag leave events (passed in \a event), for the viewport() widget.
       
  1252 
       
  1253     \sa QWidget::dragLeaveEvent()
       
  1254 */
       
  1255 void QAbstractScrollArea::dragLeaveEvent(QDragLeaveEvent *)
       
  1256 {
       
  1257 }
       
  1258 
       
  1259 /*!
       
  1260     \fn void QAbstractScrollArea::dropEvent(QDropEvent *event)
       
  1261 
       
  1262     This event handler can be reimplemented in a subclass to receive
       
  1263     drop events (passed in \a event), for the viewport() widget.
       
  1264 
       
  1265     \sa QWidget::dropEvent()
       
  1266 */
       
  1267 void QAbstractScrollArea::dropEvent(QDropEvent *)
       
  1268 {
       
  1269 }
       
  1270 
       
  1271 
       
  1272 #endif
       
  1273 
       
  1274 /*!
       
  1275     This virtual handler is called when the scroll bars are moved by
       
  1276     \a dx, \a dy, and consequently the viewport's contents should be
       
  1277     scrolled accordingly.
       
  1278 
       
  1279     The default implementation simply calls update() on the entire
       
  1280     viewport(), subclasses can reimplement this handler for
       
  1281     optimization purposes, or - like QScrollArea - to move a contents
       
  1282     widget. The parameters \a dx and \a dy are there for convenience,
       
  1283     so that the class knows how much should be scrolled (useful
       
  1284     e.g. when doing pixel-shifts). You may just as well ignore these
       
  1285     values and scroll directly to the position the scroll bars
       
  1286     indicate.
       
  1287 
       
  1288     Calling this function in order to scroll programmatically is an
       
  1289     error, use the scroll bars instead (e.g. by calling
       
  1290     QScrollBar::setValue() directly).
       
  1291 */
       
  1292 void QAbstractScrollArea::scrollContentsBy(int, int)
       
  1293 {
       
  1294     viewport()->update();
       
  1295 }
       
  1296 
       
  1297 void QAbstractScrollAreaPrivate::_q_hslide(int x)
       
  1298 {
       
  1299     Q_Q(QAbstractScrollArea);
       
  1300     int dx = xoffset - x;
       
  1301     xoffset = x;
       
  1302     q->scrollContentsBy(dx, 0);
       
  1303 }
       
  1304 
       
  1305 void QAbstractScrollAreaPrivate::_q_vslide(int y)
       
  1306 {
       
  1307     Q_Q(QAbstractScrollArea);
       
  1308     int dy = yoffset - y;
       
  1309     yoffset = y;
       
  1310     q->scrollContentsBy(0, dy);
       
  1311 }
       
  1312 
       
  1313 void QAbstractScrollAreaPrivate::_q_showOrHideScrollBars()
       
  1314 {
       
  1315     layoutChildren();
       
  1316 #ifdef Q_WS_WIN
       
  1317     // Need to re-subscribe to gestures as the content changes to make sure we
       
  1318     // enable/disable panning when needed.
       
  1319     QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport));
       
  1320     if (dd)
       
  1321         dd->winSetupGestures();
       
  1322 #endif // Q_WS_WIN
       
  1323 }
       
  1324 
       
  1325 QPoint QAbstractScrollAreaPrivate::contentsOffset() const
       
  1326 {
       
  1327     Q_Q(const QAbstractScrollArea);
       
  1328     QPoint offset;
       
  1329     if (vbar->isVisible())
       
  1330         offset.setY(vbar->value());
       
  1331     if (hbar->isVisible()) {
       
  1332         if (q->isRightToLeft())
       
  1333             offset.setX(hbar->maximum() - hbar->value());
       
  1334         else
       
  1335             offset.setX(hbar->value());
       
  1336     }
       
  1337     return offset;
       
  1338 }
       
  1339 
       
  1340 /*!
       
  1341     \reimp
       
  1342 
       
  1343 */
       
  1344 QSize QAbstractScrollArea::minimumSizeHint() const
       
  1345 {
       
  1346     Q_D(const QAbstractScrollArea);
       
  1347     int hsbExt = d->hbar->sizeHint().height();
       
  1348     int vsbExt = d->vbar->sizeHint().width();
       
  1349     int extra = 2 * d->frameWidth;
       
  1350     QStyleOption opt;
       
  1351     opt.initFrom(this);
       
  1352     if ((d->frameStyle != QFrame::NoFrame)
       
  1353         && style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, this)) {
       
  1354         extra += style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, this);
       
  1355     }
       
  1356     return QSize(d->scrollBarContainers[Qt::Horizontal]->sizeHint().width() + vsbExt + extra,
       
  1357                  d->scrollBarContainers[Qt::Vertical]->sizeHint().height() + hsbExt + extra);
       
  1358 }
       
  1359 
       
  1360 /*!
       
  1361     \reimp
       
  1362 */
       
  1363 QSize QAbstractScrollArea::sizeHint() const
       
  1364 {
       
  1365     return QSize(256, 192);
       
  1366 #if 0
       
  1367     Q_D(const QAbstractScrollArea);
       
  1368     int h = qMax(10, fontMetrics().height());
       
  1369     int f = 2 * d->frameWidth;
       
  1370     return QSize((6 * h) + f, (4 * h) + f);
       
  1371 #endif
       
  1372 }
       
  1373 
       
  1374 /*!
       
  1375     This slot is called by QAbstractScrollArea after setViewport(\a
       
  1376     viewport) has been called. Reimplement this function in a
       
  1377     subclass of QAbstractScrollArea to initialize the new \a viewport
       
  1378     before it is used.
       
  1379 
       
  1380     \sa setViewport()
       
  1381 */
       
  1382 void QAbstractScrollArea::setupViewport(QWidget *viewport)
       
  1383 {
       
  1384     Q_UNUSED(viewport);
       
  1385 }
       
  1386 
       
  1387 QT_END_NAMESPACE
       
  1388 
       
  1389 #include "moc_qabstractscrollarea.cpp"
       
  1390 #include "moc_qabstractscrollarea_p.cpp"
       
  1391 
       
  1392 #endif // QT_NO_SCROLLAREA