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