src/qt3support/widgets/q3scrollview.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 Qt3Support 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 "qwidget.h"
       
    43 #ifndef QT_NO_SCROLLVIEW
       
    44 #include "qscrollbar.h"
       
    45 #include "qpainter.h"
       
    46 #include "qpixmap.h"
       
    47 #include "qcursor.h"
       
    48 #include "q3scrollview.h"
       
    49 #include "q3ptrdict.h"
       
    50 #include "qapplication.h"
       
    51 #include "qtimer.h"
       
    52 #include "qstyle.h"
       
    53 #include "q3ptrlist.h"
       
    54 #include "qevent.h"
       
    55 #include "q3listview.h"
       
    56 #ifdef Q_WS_MAC
       
    57 # include "private/qt_mac_p.h"
       
    58 #endif
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 using namespace Qt;
       
    63 
       
    64 static const int coord_limit = 4000;
       
    65 static const int autoscroll_margin = 16;
       
    66 static const int initialScrollTime = 30;
       
    67 static const int initialScrollAccel = 5;
       
    68 
       
    69 struct QSVChildRec {
       
    70     QSVChildRec(QWidget* c, int xx, int yy) :
       
    71         child(c),
       
    72         x(xx), y(yy)
       
    73     {
       
    74     }
       
    75 
       
    76     void hideOrShow(Q3ScrollView* sv, QWidget* clipped_viewport);
       
    77     void moveTo(Q3ScrollView* sv, int xx, int yy, QWidget* clipped_viewport)
       
    78     {
       
    79         if (x != xx || y != yy) {
       
    80             x = xx;
       
    81             y = yy;
       
    82             hideOrShow(sv,clipped_viewport);
       
    83         }
       
    84     }
       
    85     QWidget* child;
       
    86     int x, y;
       
    87 };
       
    88 
       
    89 void QSVChildRec::hideOrShow(Q3ScrollView* sv, QWidget* clipped_viewport)
       
    90 {
       
    91     if (clipped_viewport) {
       
    92         if (x+child->width() < sv->contentsX()+clipped_viewport->x()
       
    93              || x > sv->contentsX()+clipped_viewport->width()
       
    94              || y+child->height() < sv->contentsY()+clipped_viewport->y()
       
    95              || y > sv->contentsY()+clipped_viewport->height()) {
       
    96             child->move(clipped_viewport->width(),
       
    97                         clipped_viewport->height());
       
    98         } else {
       
    99             child->move(x-sv->contentsX()-clipped_viewport->x(),
       
   100                         y-sv->contentsY()-clipped_viewport->y());
       
   101         }
       
   102     } else {
       
   103         child->move(x-sv->contentsX(), y-sv->contentsY());
       
   104     }
       
   105 }
       
   106 
       
   107 class QAbstractScrollAreaWidget : public QWidget
       
   108 {
       
   109     Q_OBJECT
       
   110 
       
   111 public:
       
   112     QAbstractScrollAreaWidget(Q3ScrollView* parent=0, const char* name=0, Qt::WindowFlags f = 0)
       
   113         : QWidget(parent, name, f)
       
   114     {
       
   115         setAutoFillBackground(true);
       
   116     }
       
   117 };
       
   118 
       
   119 class QClipperWidget : public QWidget
       
   120 {
       
   121     Q_OBJECT
       
   122 
       
   123 public:
       
   124     QClipperWidget(QWidget * parent=0, const char * name=0, Qt::WindowFlags f=0)
       
   125         : QWidget (parent,name,f) {}
       
   126 };
       
   127 
       
   128 QT_BEGIN_INCLUDE_NAMESPACE
       
   129 #include "q3scrollview.moc"
       
   130 QT_END_INCLUDE_NAMESPACE
       
   131 
       
   132 class Q3ScrollViewData {
       
   133 public:
       
   134     Q3ScrollViewData(Q3ScrollView* parent, int vpwflags) :
       
   135         hbar(new QScrollBar(Qt::Horizontal, parent, "qt_hbar")),
       
   136         vbar(new QScrollBar(Qt::Vertical, parent, "qt_vbar")),
       
   137         viewport(new QAbstractScrollAreaWidget(parent, "qt_viewport", QFlag(vpwflags))),
       
   138         clipped_viewport(0),
       
   139         flags(vpwflags),
       
   140         vx(0), vy(0), vwidth(1), vheight(1),
       
   141 #ifndef QT_NO_DRAGANDDROP
       
   142         autoscroll_timer(parent, "scrollview autoscroll timer"),
       
   143         drag_autoscroll(true),
       
   144 #endif
       
   145         scrollbar_timer(parent, "scrollview scrollbar timer"),
       
   146         inresize(false), use_cached_size_hint(true)
       
   147     {
       
   148         l_marg = r_marg = t_marg = b_marg = 0;
       
   149         viewport->polish();
       
   150         vMode = Q3ScrollView::Auto;
       
   151         hMode = Q3ScrollView::Auto;
       
   152         corner = 0;
       
   153         vbar->setSteps(20, 1/*set later*/);
       
   154         hbar->setSteps(20, 1/*set later*/);
       
   155         policy = Q3ScrollView::Default;
       
   156         signal_choke = false;
       
   157         static_bg = false;
       
   158         fake_scroll = false;
       
   159         hbarPressed = false;
       
   160         vbarPressed = false;
       
   161         hbar->setLayoutDirection(Qt::LeftToRight);
       
   162     }
       
   163     ~Q3ScrollViewData();
       
   164 
       
   165     QSVChildRec* rec(QWidget* w) { return childDict.find(w); }
       
   166     QSVChildRec* ancestorRec(QWidget* w);
       
   167     QSVChildRec* addChildRec(QWidget* w, int x, int y)
       
   168     {
       
   169         QSVChildRec *r = new QSVChildRec(w,x,y);
       
   170         children.append(r);
       
   171         childDict.insert(w, r);
       
   172         return r;
       
   173     }
       
   174     void deleteChildRec(QSVChildRec* r)
       
   175     {
       
   176         childDict.remove(r->child);
       
   177         children.removeRef(r);
       
   178         delete r;
       
   179     }
       
   180 
       
   181     void hideOrShowAll(Q3ScrollView* sv, bool isScroll = false);
       
   182     void moveAllBy(int dx, int dy);
       
   183     bool anyVisibleChildren();
       
   184     void autoMove(Q3ScrollView* sv);
       
   185     void autoResize(Q3ScrollView* sv);
       
   186     void autoResizeHint(Q3ScrollView* sv);
       
   187     void viewportResized(int w, int h);
       
   188 
       
   189     QScrollBar*  hbar;
       
   190     QScrollBar*  vbar;
       
   191     bool hbarPressed;
       
   192     bool vbarPressed;
       
   193     QAbstractScrollAreaWidget*    viewport;
       
   194     QClipperWidget*     clipped_viewport;
       
   195     int         flags;
       
   196     Q3PtrList<QSVChildRec>       children;
       
   197     Q3PtrDict<QSVChildRec>       childDict;
       
   198     QWidget*    corner;
       
   199     int         vx, vy, vwidth, vheight; // for drawContents-style usage
       
   200     int         l_marg, r_marg, t_marg, b_marg;
       
   201     Q3ScrollView::ResizePolicy policy;
       
   202     Q3ScrollView::ScrollBarMode  vMode;
       
   203     Q3ScrollView::ScrollBarMode  hMode;
       
   204 #ifndef QT_NO_DRAGANDDROP
       
   205     QPoint cpDragStart;
       
   206     QTimer autoscroll_timer;
       
   207     int autoscroll_time;
       
   208     int autoscroll_accel;
       
   209     bool drag_autoscroll;
       
   210 #endif
       
   211     QTimer scrollbar_timer;
       
   212 
       
   213     uint static_bg : 1;
       
   214     uint fake_scroll : 1;
       
   215 
       
   216     // This variable allows ensureVisible to move the contents then
       
   217     // update both the sliders.  Otherwise, updating the sliders would
       
   218     // cause two image scrolls, creating ugly flashing.
       
   219     //
       
   220     uint signal_choke : 1;
       
   221 
       
   222     // This variables indicates in updateScrollBars() that we are
       
   223     // in a resizeEvent() and thus don't want to flash scroll bars
       
   224     uint inresize : 1;
       
   225     uint use_cached_size_hint : 1;
       
   226     QSize cachedSizeHint;
       
   227 
       
   228     inline int contentsX() const { return -vx; }
       
   229     inline int contentsY() const { return -vy; }
       
   230     inline int contentsWidth() const { return vwidth; }
       
   231 };
       
   232 
       
   233 inline Q3ScrollViewData::~Q3ScrollViewData()
       
   234 {
       
   235     children.setAutoDelete(true);
       
   236 }
       
   237 
       
   238 QSVChildRec* Q3ScrollViewData::ancestorRec(QWidget* w)
       
   239 {
       
   240     if (clipped_viewport) {
       
   241         while (w->parentWidget() != clipped_viewport) {
       
   242             w = w->parentWidget();
       
   243             if (!w) return 0;
       
   244         }
       
   245     } else {
       
   246         while (w->parentWidget() != viewport) {
       
   247             w = w->parentWidget();
       
   248             if (!w) return 0;
       
   249         }
       
   250     }
       
   251     return rec(w);
       
   252 }
       
   253 
       
   254 void Q3ScrollViewData::hideOrShowAll(Q3ScrollView* sv, bool isScroll)
       
   255 {
       
   256     if (!clipped_viewport)
       
   257         return;
       
   258     if (clipped_viewport->x() <= 0
       
   259          && clipped_viewport->y() <= 0
       
   260          && clipped_viewport->width()+clipped_viewport->x() >=
       
   261          viewport->width()
       
   262          && clipped_viewport->height()+clipped_viewport->y() >=
       
   263          viewport->height()) {
       
   264         // clipped_viewport still covers viewport
       
   265         if(static_bg)
       
   266             clipped_viewport->repaint(true);
       
   267         else if ((!isScroll && !clipped_viewport->testAttribute(Qt::WA_StaticContents)) || static_bg)
       
   268             clipped_viewport->update();
       
   269     } else {
       
   270         // Re-center
       
   271         int nx = (viewport->width() - clipped_viewport->width()) / 2;
       
   272         int ny = (viewport->height() - clipped_viewport->height()) / 2;
       
   273         clipped_viewport->move(nx,ny);
       
   274         clipped_viewport->update();
       
   275     }
       
   276     for (QSVChildRec *r = children.first(); r; r=children.next()) {
       
   277         r->hideOrShow(sv, clipped_viewport);
       
   278     }
       
   279 }
       
   280 
       
   281 void Q3ScrollViewData::moveAllBy(int dx, int dy)
       
   282 {
       
   283     if (clipped_viewport && !static_bg) {
       
   284         clipped_viewport->move(clipped_viewport->x()+dx,
       
   285                                 clipped_viewport->y()+dy);
       
   286     } else {
       
   287         for (QSVChildRec *r = children.first(); r; r=children.next()) {
       
   288             r->child->move(r->child->x()+dx,r->child->y()+dy);
       
   289         }
       
   290         if (static_bg)
       
   291             viewport->repaint(true);
       
   292     }
       
   293 }
       
   294 
       
   295 bool Q3ScrollViewData::anyVisibleChildren()
       
   296 {
       
   297     for (QSVChildRec *r = children.first(); r; r=children.next()) {
       
   298         if (r->child->isVisible()) return true;
       
   299     }
       
   300     return false;
       
   301 }
       
   302 
       
   303 void Q3ScrollViewData::autoMove(Q3ScrollView* sv)
       
   304 {
       
   305     if (policy == Q3ScrollView::AutoOne) {
       
   306         QSVChildRec* r = children.first();
       
   307         if (r)
       
   308             sv->setContentsPos(-r->child->x(),-r->child->y());
       
   309     }
       
   310 }
       
   311 
       
   312 void Q3ScrollViewData::autoResize(Q3ScrollView* sv)
       
   313 {
       
   314     if (policy == Q3ScrollView::AutoOne) {
       
   315         QSVChildRec* r = children.first();
       
   316         if (r)
       
   317             sv->resizeContents(r->child->width(),r->child->height());
       
   318     }
       
   319 }
       
   320 
       
   321 void Q3ScrollViewData::autoResizeHint(Q3ScrollView* sv)
       
   322 {
       
   323     if (policy == Q3ScrollView::AutoOne) {
       
   324         QSVChildRec* r = children.first();
       
   325         if (r) {
       
   326             QSize s = r->child->sizeHint();
       
   327             if (s.isValid())
       
   328                 r->child->resize(s);
       
   329         }
       
   330     } else if (policy == Q3ScrollView::AutoOneFit) {
       
   331         QSVChildRec* r = children.first();
       
   332         if (r) {
       
   333             QSize sh = r->child->sizeHint();
       
   334             sh = sh.boundedTo(r->child->maximumSize());
       
   335             sv->resizeContents(sh.width(), sh.height());
       
   336         }
       
   337     }
       
   338 }
       
   339 
       
   340 void Q3ScrollViewData::viewportResized(int w, int h)
       
   341 {
       
   342     if (policy == Q3ScrollView::AutoOneFit) {
       
   343         QSVChildRec* r = children.first();
       
   344         if (r) {
       
   345             QSize sh = r->child->sizeHint();
       
   346             sh = sh.boundedTo(r->child->maximumSize());
       
   347             r->child->resize(QMAX(w,sh.width()), QMAX(h,sh.height()));
       
   348         }
       
   349 
       
   350     }
       
   351 }
       
   352 
       
   353 
       
   354 /*!
       
   355     \class Q3ScrollView
       
   356     \brief The Q3ScrollView widget provides a scrolling area with on-demand scroll bars.
       
   357 
       
   358     \compat
       
   359 
       
   360     The Q3ScrollView is a large canvas - potentially larger than the
       
   361     coordinate system normally supported by the underlying window
       
   362     system. This is important because it is quite easy to go beyond
       
   363     these limitations (e.g. many web pages are more than 32000 pixels
       
   364     high). Additionally, the Q3ScrollView can have QWidgets positioned
       
   365     on it that scroll around with the drawn content. These sub-widgets
       
   366     can also have positions outside the normal coordinate range (but
       
   367     they are still limited in size).
       
   368 
       
   369     To provide content for the widget, inherit from Q3ScrollView,
       
   370     reimplement drawContents() and use resizeContents() to set the
       
   371     size of the viewed area. Use addChild() and moveChild() to
       
   372     position widgets on the view.
       
   373 
       
   374     To use Q3ScrollView effectively it is important to understand its
       
   375     widget structure in the three styles of use: a single large child
       
   376     widget, a large panning area with some widgets and a large panning
       
   377     area with many widgets.
       
   378 
       
   379     \section1 Using One Big Widget
       
   380 
       
   381     \img qscrollview-vp2.png
       
   382 
       
   383     The first, simplest usage of Q3ScrollView (depicted above), is
       
   384     appropriate for scrolling areas that are never more than about
       
   385     4000 pixels in either dimension (this is about the maximum
       
   386     reliable size on X11 servers). In this usage, you just make one
       
   387     large child in the Q3ScrollView. The child should be a child of the
       
   388     viewport() of the scrollview and be added with addChild():
       
   389     \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 0
       
   390     You can go on to add arbitrary child widgets to the single child
       
   391     in the scrollview as you would with any widget:
       
   392     \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 1
       
   393 
       
   394     Here the Q3ScrollView has four children: the viewport(), the
       
   395     verticalScrollBar(), the horizontalScrollBar() and a small
       
   396     cornerWidget(). The viewport() has one child: the QWidget. The
       
   397     QWidget has the three QLabel objects as child widgets. When the view
       
   398     is scrolled, the QWidget is moved; its children move with it as
       
   399     child widgets normally do.
       
   400 
       
   401     \section1 Using a Very Big View with Some Widgets
       
   402 
       
   403     \img qscrollview-vp.png
       
   404 
       
   405     The second usage of Q3ScrollView (depicted above) is appropriate
       
   406     when few, if any, widgets are on a very large scrolling area that
       
   407     is potentially larger than 4000 pixels in either dimension. In
       
   408     this usage you call resizeContents() to set the size of the area
       
   409     and reimplement drawContents() to paint the contents. You may also
       
   410     add some widgets by making them children of the viewport() and
       
   411     adding them with addChild() (this is the same as the process for
       
   412     the single large widget in the previous example):
       
   413     \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 2
       
   414     Here, the Q3ScrollView has the same four children: the viewport(),
       
   415     the verticalScrollBar(), the horizontalScrollBar() and a small
       
   416     cornerWidget(). The viewport() has the three QLabel objects as
       
   417     child widgets. When the view is scrolled, the scrollview moves the
       
   418     child widgets individually.
       
   419 
       
   420     \section1 Using a Very Big View with Many Widgets
       
   421 
       
   422     \img qscrollview-cl.png
       
   423 
       
   424     The final usage of Q3ScrollView (depicted above) is appropriate
       
   425     when many widgets are on a very large scrolling area that is
       
   426     potentially larger than 4000 pixels in either dimension. In this
       
   427     usage you call resizeContents() to set the size of the area and
       
   428     reimplement drawContents() to paint the contents. You then call
       
   429     enableClipper(true) and add widgets, again by making them children
       
   430     of the viewport(), and adding them with addChild():
       
   431     \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 3
       
   432 
       
   433     Here, the Q3ScrollView has four children:  the clipper() (not the
       
   434     viewport() this time), the verticalScrollBar(), the
       
   435     horizontalScrollBar() and a small cornerWidget(). The clipper()
       
   436     has one child: the viewport(). The viewport() has the same three
       
   437     labels as child widgets. When the view is scrolled the viewport()
       
   438     is moved; its children move with it as child widgets normally do.
       
   439 
       
   440     \target allviews
       
   441     \section1 Details Relevant for All Views
       
   442 
       
   443     Normally you will use the first or third method if you want any
       
   444     child widgets in the view.
       
   445 
       
   446     Note that the widget you see in the scrolled area is the
       
   447     viewport() widget, not the Q3ScrollView itself. So to turn mouse
       
   448     tracking on, for example, use viewport()->setMouseTracking(true).
       
   449 
       
   450     To enable drag-and-drop, you would setAcceptDrops(true) on the
       
   451     Q3ScrollView (because drag-and-drop events propagate to the
       
   452     parent). But to work out the logical position in the view, you
       
   453     would need to map the drop co-ordinate from being relative to the
       
   454     Q3ScrollView to being relative to the contents; use the function
       
   455     viewportToContents() for this.
       
   456 
       
   457     To handle mouse events on the scrolling area, subclass scrollview
       
   458     as you would subclass other widgets, but rather than
       
   459     reimplementing mousePressEvent(), reimplement
       
   460     contentsMousePressEvent() instead. The contents specific event
       
   461     handlers provide translated events in the coordinate system of the
       
   462     scrollview. If you reimplement mousePressEvent(), you'll get
       
   463     called only when part of the Q3ScrollView is clicked: and the only
       
   464     such part is the "corner" (if you don't set a cornerWidget()) and
       
   465     the frame; everything else is covered up by the viewport, clipper
       
   466     or scroll bars.
       
   467 
       
   468     When you construct a Q3ScrollView, some of the window flags apply
       
   469     to the viewport() instead of being sent to the QWidget constructor
       
   470     for the Q3ScrollView.
       
   471 
       
   472     \list
       
   473 
       
   474     \i An image-manipulation widget would use \c
       
   475     WNoAutoErase|WStaticContents because the widget draws all pixels
       
   476     itself, and when its size increases, it only needs a paint event
       
   477     for the new part because the old part remains unchanged.
       
   478 
       
   479     \i A scrolling game widget in which the background scrolls as the
       
   480     characters move might use \c WNoAutoErase (in addition to \c
       
   481     WStaticContents) so that the window system background does not
       
   482     flash in and out during scrolling.
       
   483 
       
   484     \i A word processing widget might use \c WNoAutoErase and repaint
       
   485     itself line by line to get a less-flickery resizing. If the widget
       
   486     is in a mode in which no text justification can take place, it
       
   487     might use \c WStaticContents too, so that it would only get a
       
   488     repaint for the newly visible parts.
       
   489 
       
   490     \endlist
       
   491 
       
   492     Child widgets may be moved using addChild() or moveChild(). Use
       
   493     childX() and childY() to get the position of a child widget.
       
   494 
       
   495     A widget may be placed in the corner between the vertical and
       
   496     horizontal scroll bars with setCornerWidget(). You can get access
       
   497     to the scroll bars using horizontalScrollBar() and
       
   498     verticalScrollBar(), and to the viewport with viewport(). The
       
   499     scroll view can be scrolled using scrollBy(), ensureVisible(),
       
   500     setContentsPos() or center().
       
   501 
       
   502     The visible area is given by visibleWidth() and visibleHeight(),
       
   503     and the contents area by contentsWidth() and contentsHeight(). The
       
   504     contents may be repainted using one of the repaintContents() or
       
   505     updateContents() functions.
       
   506 
       
   507     Coordinate conversion is provided by contentsToViewport() and
       
   508     viewportToContents().
       
   509 
       
   510     The contentsMoving() signal is emitted just before the contents
       
   511     are moved to a new position.
       
   512 
       
   513     \warning Q3ScrollView currently does not erase the background when
       
   514     resized, i.e. you must always clear the background manually in
       
   515     scrollview subclasses. This will change in a future version of Qt
       
   516     and we recommend specifying the \c WNoAutoErase flag explicitly.
       
   517 */
       
   518 
       
   519 
       
   520 /*!
       
   521     \enum Q3ScrollView::ResizePolicy
       
   522 
       
   523     This enum type is used to control a Q3ScrollView's reaction to
       
   524     resize events.
       
   525 
       
   526     \value Default  the Q3ScrollView selects one of the other settings
       
   527     automatically when it has to. In this version of Qt, Q3ScrollView
       
   528     changes to \c Manual if you resize the contents with
       
   529     resizeContents() and to \c AutoOne if a child is added.
       
   530 
       
   531     \value Manual  the contents stays the size set by resizeContents().
       
   532 
       
   533     \value AutoOne  if there is only one child widget the contents stays
       
   534     the size of that widget. Otherwise the behavior is undefined.
       
   535 
       
   536     \value AutoOneFit if there is only one child widget the contents stays
       
   537     the size of that widget's sizeHint(). If the scrollview is resized
       
   538     larger than the child's sizeHint(), the child will be resized to
       
   539     fit. If there is more than one child, the behavior is undefined.
       
   540 
       
   541 */
       
   542 //####  The widget will be resized to its sizeHint() when a LayoutHint event
       
   543 //#### is received
       
   544 
       
   545 /*!
       
   546     Constructs a Q3ScrollView called \a name with parent \a parent and
       
   547     widget flags \a f.
       
   548 
       
   549     The widget flags \c WStaticContents, \c WNoAutoErase and \c
       
   550     WPaintClever are propagated to the viewport() widget. The other
       
   551     widget flags are propagated to the parent constructor as usual.
       
   552 */
       
   553 
       
   554 Q3ScrollView::Q3ScrollView(QWidget *parent, const char *name, Qt::WindowFlags f) :
       
   555     Q3Frame(parent, name, f & (~WStaticContents) & (~WNoAutoErase) & (~WResizeNoErase))
       
   556 {
       
   557     WindowFlags flags = WResizeNoErase | (f&WPaintClever) | (f&WRepaintNoErase) | (f&WStaticContents);
       
   558     d = new Q3ScrollViewData(this, flags);
       
   559 
       
   560 #ifndef QT_NO_DRAGANDDROP
       
   561     connect(&d->autoscroll_timer, SIGNAL(timeout()),
       
   562              this, SLOT(doDragAutoScroll()));
       
   563 #endif
       
   564 
       
   565     connect(d->hbar, SIGNAL(valueChanged(int)),
       
   566         this, SLOT(hslide(int)));
       
   567     connect(d->vbar, SIGNAL(valueChanged(int)),
       
   568         this, SLOT(vslide(int)));
       
   569 
       
   570     connect(d->hbar, SIGNAL(sliderPressed()), this, SLOT(hbarIsPressed()));
       
   571     connect(d->hbar, SIGNAL(sliderReleased()), this, SLOT(hbarIsReleased()));
       
   572     connect(d->vbar, SIGNAL(sliderPressed()), this, SLOT(vbarIsPressed()));
       
   573     connect(d->vbar, SIGNAL(sliderReleased()), this, SLOT(vbarIsReleased()));
       
   574 
       
   575 
       
   576     d->viewport->installEventFilter(this);
       
   577 
       
   578     connect(&d->scrollbar_timer, SIGNAL(timeout()),
       
   579              this, SLOT(updateScrollBars()));
       
   580 
       
   581     setFrameStyle(Q3Frame::StyledPanel | Q3Frame::Sunken);
       
   582     setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
       
   583     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
       
   584 }
       
   585 
       
   586 
       
   587 /*!
       
   588     Destroys the Q3ScrollView. Any children added with addChild() will
       
   589     be deleted.
       
   590 */
       
   591 Q3ScrollView::~Q3ScrollView()
       
   592 {
       
   593     // Be careful not to get all those useless events...
       
   594     if (d->clipped_viewport)
       
   595         d->clipped_viewport->removeEventFilter(this);
       
   596     else
       
   597         d->viewport->removeEventFilter(this);
       
   598 
       
   599     // order is important
       
   600     // ~QWidget may cause a WM_ERASEBKGND on Windows
       
   601     delete d->vbar;
       
   602     d->vbar = 0;
       
   603     delete d->hbar;
       
   604     d->hbar = 0;
       
   605     delete d->viewport;
       
   606     d->viewport = 0;
       
   607     delete d;
       
   608     d = 0;
       
   609 }
       
   610 
       
   611 /*!
       
   612     \fn void Q3ScrollView::horizontalSliderPressed()
       
   613 
       
   614     This signal is emitted whenever the user presses the horizontal slider.
       
   615 */
       
   616 /*!
       
   617     \fn void Q3ScrollView::horizontalSliderReleased()
       
   618 
       
   619     This signal is emitted whenever the user releases the horizontal slider.
       
   620 */
       
   621 /*!
       
   622     \fn void Q3ScrollView::verticalSliderPressed()
       
   623 
       
   624     This signal is emitted whenever the user presses the vertical slider.
       
   625 */
       
   626 /*!
       
   627     \fn void Q3ScrollView::verticalSliderReleased()
       
   628 
       
   629     This signal is emitted whenever the user releases the vertical slider.
       
   630 */
       
   631 void Q3ScrollView::hbarIsPressed()
       
   632 {
       
   633     d->hbarPressed = true;
       
   634     emit(horizontalSliderPressed());
       
   635 }
       
   636 
       
   637 void Q3ScrollView::hbarIsReleased()
       
   638 {
       
   639     d->hbarPressed = false;
       
   640     emit(horizontalSliderReleased());
       
   641 }
       
   642 
       
   643 /*!
       
   644     Returns true if horizontal slider is pressed by user; otherwise returns false.
       
   645 */
       
   646 bool Q3ScrollView::isHorizontalSliderPressed()
       
   647 {
       
   648     return d->hbarPressed;
       
   649 }
       
   650 
       
   651 void Q3ScrollView::vbarIsPressed()
       
   652 {
       
   653     d->vbarPressed = true;
       
   654     emit(verticalSliderPressed());
       
   655 }
       
   656 
       
   657 void Q3ScrollView::vbarIsReleased()
       
   658 {
       
   659     d->vbarPressed = false;
       
   660     emit(verticalSliderReleased());
       
   661 }
       
   662 
       
   663 /*!
       
   664     Returns true if vertical slider is pressed by user; otherwise returns false.
       
   665 */
       
   666 bool Q3ScrollView::isVerticalSliderPressed()
       
   667 {
       
   668     return d->vbarPressed;
       
   669 }
       
   670 
       
   671 /*!
       
   672     \internal
       
   673 */
       
   674 void Q3ScrollView::styleChange(QStyle& old)
       
   675 {
       
   676     QWidget::styleChange(old);
       
   677     updateScrollBars();
       
   678     d->cachedSizeHint = QSize();
       
   679 }
       
   680 
       
   681 /*!
       
   682     \internal
       
   683 */
       
   684 void Q3ScrollView::fontChange(const QFont &old)
       
   685 {
       
   686     QWidget::fontChange(old);
       
   687     updateScrollBars();
       
   688     d->cachedSizeHint = QSize();
       
   689 }
       
   690 
       
   691 void Q3ScrollView::hslide(int pos)
       
   692 {
       
   693     if (!d->signal_choke) {
       
   694         moveContents(-pos, -d->contentsY());
       
   695         QApplication::syncX();
       
   696     }
       
   697 }
       
   698 
       
   699 void Q3ScrollView::vslide(int pos)
       
   700 {
       
   701     if (!d->signal_choke) {
       
   702         moveContents(-d->contentsX(), -pos);
       
   703         QApplication::syncX();
       
   704     }
       
   705 }
       
   706 
       
   707 /*!
       
   708     Called when the horizontal scroll bar geometry changes. This is
       
   709     provided as a protected function so that subclasses can do
       
   710     interesting things such as providing extra buttons in some of the
       
   711     space normally used by the scroll bars.
       
   712 
       
   713     The default implementation simply gives all the space to \a hbar.
       
   714     The new geometry is given by \a x, \a y, \a w and \a h.
       
   715 
       
   716     \sa setVBarGeometry()
       
   717 */
       
   718 void Q3ScrollView::setHBarGeometry(QScrollBar& hbar,
       
   719     int x, int y, int w, int h)
       
   720 {
       
   721     hbar.setGeometry(x, y, w, h);
       
   722 }
       
   723 
       
   724 /*!
       
   725     Called when the vertical scroll bar geometry changes. This is
       
   726     provided as a protected function so that subclasses can do
       
   727     interesting things such as providing extra buttons in some of the
       
   728     space normally used by the scroll bars.
       
   729 
       
   730     The default implementation simply gives all the space to \a vbar.
       
   731     The new geometry is given by \a x, \a y, \a w and \a h.
       
   732 
       
   733     \sa setHBarGeometry()
       
   734 */
       
   735 void Q3ScrollView::setVBarGeometry(QScrollBar& vbar,
       
   736     int x, int y, int w, int h)
       
   737 {
       
   738     vbar.setGeometry(x, y, w, h);
       
   739 }
       
   740 
       
   741 
       
   742 /*!
       
   743     Returns the viewport size for size (\a x, \a y).
       
   744 
       
   745     The viewport size depends on (\a x, \a y) (the size of the contents),
       
   746     the size of this widget and the modes of the horizontal and
       
   747     vertical scroll bars.
       
   748 
       
   749     This function permits widgets that can trade vertical and
       
   750     horizontal space for each other to control scroll bar appearance
       
   751     better. For example, a word processor or web browser can control
       
   752     the width of the right margin accurately, whether or not there
       
   753     needs to be a vertical scroll bar.
       
   754 */
       
   755 
       
   756 QSize Q3ScrollView::viewportSize(int x, int y) const
       
   757 {
       
   758     int fw = frameWidth();
       
   759     int lmarg = fw+d->l_marg;
       
   760     int rmarg = fw+d->r_marg;
       
   761     int tmarg = fw+d->t_marg;
       
   762     int bmarg = fw+d->b_marg;
       
   763 
       
   764     int w = width();
       
   765     int h = height();
       
   766 
       
   767     bool needh, needv;
       
   768     bool showh, showv;
       
   769     int hsbExt = horizontalScrollBar()->sizeHint().height();
       
   770     int vsbExt = verticalScrollBar()->sizeHint().width();
       
   771 
       
   772     if (d->policy != AutoOne || d->anyVisibleChildren()) {
       
   773         // Do we definitely need the scroll bar?
       
   774         needh = w-lmarg-rmarg < x;
       
   775         needv = h-tmarg-bmarg < y;
       
   776 
       
   777         // Do we intend to show the scroll bar?
       
   778         if (d->hMode == AlwaysOn)
       
   779             showh = true;
       
   780         else if (d->hMode == AlwaysOff)
       
   781             showh = false;
       
   782         else
       
   783             showh = needh;
       
   784 
       
   785         if (d->vMode == AlwaysOn)
       
   786             showv = true;
       
   787         else if (d->vMode == AlwaysOff)
       
   788             showv = false;
       
   789         else
       
   790             showv = needv;
       
   791 
       
   792         // Given other scroll bar will be shown, NOW do we need one?
       
   793         if (showh && h-vsbExt-tmarg-bmarg < y) {
       
   794             if (d->vMode == Auto)
       
   795                 showv=true;
       
   796         }
       
   797         if (showv && w-hsbExt-lmarg-rmarg < x) {
       
   798             if (d->hMode == Auto)
       
   799                 showh=true;
       
   800         }
       
   801     } else {
       
   802         // Scroll bars not needed, only show scroll bar that are always on.
       
   803         showh = d->hMode == AlwaysOn;
       
   804         showv = d->vMode == AlwaysOn;
       
   805     }
       
   806 
       
   807     return QSize(w-lmarg-rmarg - (showv ? vsbExt : 0),
       
   808                   h-tmarg-bmarg - (showh ? hsbExt : 0));
       
   809 }
       
   810 
       
   811 
       
   812 /*!
       
   813     Updates scroll bars: all possibilities are considered. You should
       
   814     never need to call this in your code.
       
   815 */
       
   816 void Q3ScrollView::updateScrollBars()
       
   817 {
       
   818     if(!horizontalScrollBar() && !verticalScrollBar())
       
   819         return;
       
   820 
       
   821     // I support this should use viewportSize()... but it needs
       
   822     // so many of the temporary variables from viewportSize.  hm.
       
   823     int fw = frameWidth();
       
   824     int lmarg = fw+d->l_marg;
       
   825     int rmarg = fw+d->r_marg;
       
   826     int tmarg = fw+d->t_marg;
       
   827     int bmarg = fw+d->b_marg;
       
   828 
       
   829     int w = width();
       
   830     int h = height();
       
   831 
       
   832     int portw, porth;
       
   833 
       
   834     bool needh;
       
   835     bool needv;
       
   836     bool showh;
       
   837     bool showv;
       
   838     bool showc = false;
       
   839 
       
   840     int hsbExt = horizontalScrollBar()->sizeHint().height();
       
   841     int vsbExt = verticalScrollBar()->sizeHint().width();
       
   842 
       
   843     QSize oldVisibleSize(visibleWidth(), visibleHeight());
       
   844 
       
   845     if (d->policy != AutoOne || d->anyVisibleChildren()) {
       
   846         // Do we definitely need the scroll bar?
       
   847         needh = w-lmarg-rmarg < d->contentsWidth();
       
   848         if (d->inresize)
       
   849             needh  = !horizontalScrollBar()->isHidden();
       
   850         needv = h-tmarg-bmarg < contentsHeight();
       
   851 
       
   852         // Do we intend to show the scroll bar?
       
   853         if (d->hMode == AlwaysOn)
       
   854             showh = true;
       
   855         else if (d->hMode == AlwaysOff)
       
   856             showh = false;
       
   857         else
       
   858             showh = needh;
       
   859 
       
   860         if (d->vMode == AlwaysOn)
       
   861             showv = true;
       
   862         else if (d->vMode == AlwaysOff)
       
   863             showv = false;
       
   864         else
       
   865             showv = needv;
       
   866 
       
   867 #ifdef Q_WS_MAC
       
   868         bool mac_need_scroll = false;
       
   869         if(!parentWidget()) {
       
   870             mac_need_scroll = true;
       
   871         } else {
       
   872             QWidget *tlw = window();
       
   873 #ifndef QT_MAC_USE_COCOA
       
   874             QPoint tlw_br = QPoint(tlw->width(), tlw->height()),
       
   875                     my_br = qt_mac_posInWindow(this) + QPoint(w, h);
       
   876             if(my_br.x() >= tlw_br.x() - 3 && my_br.y() >= tlw_br.y() - 3)
       
   877 #endif
       
   878                 mac_need_scroll = true;
       
   879         }
       
   880         if(mac_need_scroll) {
       
   881 #ifndef QT_MAC_USE_COCOA
       
   882             WindowAttributes attr;
       
   883             GetWindowAttributes((WindowPtr)handle(), &attr);
       
   884             mac_need_scroll = (attr & kWindowResizableAttribute);
       
   885 #endif
       
   886         }
       
   887         if(mac_need_scroll) {
       
   888             showc = true;
       
   889             if(d->vMode == Auto)
       
   890                 showv = true;
       
   891             if(d->hMode == Auto)
       
   892                 showh = true;
       
   893         }
       
   894 #endif
       
   895 
       
   896         // Given other scroll bar will be shown, NOW do we need one?
       
   897         if (showh && h-vsbExt-tmarg-bmarg < contentsHeight()) {
       
   898             needv=true;
       
   899             if (d->vMode == Auto)
       
   900                 showv=true;
       
   901         }
       
   902         if (showv && !d->inresize && w-hsbExt-lmarg-rmarg < d->contentsWidth()) {
       
   903             needh=true;
       
   904             if (d->hMode == Auto)
       
   905                 showh=true;
       
   906         }
       
   907     } else {
       
   908         // Scrollbars not needed, only show scroll bar that are always on.
       
   909         needh = needv = false;
       
   910         showh = d->hMode == AlwaysOn;
       
   911         showv = d->vMode == AlwaysOn;
       
   912     }
       
   913 
       
   914     bool sc = d->signal_choke;
       
   915     d->signal_choke=true;
       
   916 
       
   917     // Hide unneeded scroll bar, calculate viewport size
       
   918     if (showh) {
       
   919         porth=h-hsbExt-tmarg-bmarg;
       
   920     } else {
       
   921         if (!needh)
       
   922             d->hbar->setValue(0);
       
   923         d->hbar->hide();
       
   924         porth=h-tmarg-bmarg;
       
   925     }
       
   926     if (showv) {
       
   927         portw=w-vsbExt-lmarg-rmarg;
       
   928     } else {
       
   929         if (!needv)
       
   930             d->vbar->setValue(0);
       
   931         d->vbar->hide();
       
   932         portw=w-lmarg-rmarg;
       
   933     }
       
   934 
       
   935     // Configure scroll bars that we will show
       
   936     if (needv) {
       
   937         d->vbar->setRange(0, contentsHeight()-porth);
       
   938         d->vbar->setSteps(Q3ScrollView::d->vbar->lineStep(), porth);
       
   939     } else {
       
   940         d->vbar->setRange(0, 0);
       
   941     }
       
   942     if (needh) {
       
   943         d->hbar->setRange(0, QMAX(0, d->contentsWidth()-portw));
       
   944         d->hbar->setSteps(Q3ScrollView::d->hbar->lineStep(), portw);
       
   945     } else {
       
   946         d->hbar->setRange(0, 0);
       
   947     }
       
   948 
       
   949     // Position the scroll bars, viewport and corner widget.
       
   950     int bottom;
       
   951     bool reverse = QApplication::reverseLayout();
       
   952     int xoffset = (reverse && (showv || cornerWidget())) ? vsbExt : 0;
       
   953     int xpos = reverse ? 0 : w - vsbExt;
       
   954     bool frameContentsOnly =
       
   955         style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
       
   956 
       
   957     if(! frameContentsOnly) {
       
   958         if (reverse)
       
   959             xpos += fw;
       
   960         else
       
   961             xpos -= fw;
       
   962     }
       
   963     if (showh) {
       
   964         int right = (showc || showv || cornerWidget()) ? w-vsbExt : w;
       
   965         if (! frameContentsOnly)
       
   966             setHBarGeometry(*d->hbar, fw + xoffset, h-hsbExt-fw,
       
   967                              right-fw-fw, hsbExt);
       
   968         else
       
   969             setHBarGeometry(*d->hbar, 0 + xoffset, h-hsbExt, right,
       
   970                              hsbExt);
       
   971         bottom=h-hsbExt;
       
   972     } else {
       
   973         bottom=h;
       
   974     }
       
   975     if (showv) {
       
   976         clipper()->setGeometry(lmarg + xoffset, tmarg,
       
   977                                 w-vsbExt-lmarg-rmarg,
       
   978                                 bottom-tmarg-bmarg);
       
   979         d->viewportResized(w-vsbExt-lmarg-rmarg, bottom-tmarg-bmarg);
       
   980         if (! frameContentsOnly)
       
   981             changeFrameRect(QRect(0, 0, w, h));
       
   982         else
       
   983             changeFrameRect(QRect(xoffset, 0, w-vsbExt, bottom));
       
   984         if (showc || cornerWidget()) {
       
   985             if (! frameContentsOnly)
       
   986                 setVBarGeometry(*d->vbar, xpos,
       
   987                                  fw, vsbExt,
       
   988                                  h-hsbExt-fw-fw);
       
   989             else
       
   990                 setVBarGeometry(*d->vbar, xpos, 0,
       
   991                                  vsbExt,
       
   992                                  h-hsbExt);
       
   993         }
       
   994         else {
       
   995             if (! frameContentsOnly)
       
   996                 setVBarGeometry(*d->vbar, xpos,
       
   997                                  fw, vsbExt,
       
   998                                  bottom-fw-fw);
       
   999             else
       
  1000                 setVBarGeometry(*d->vbar, xpos, 0,
       
  1001                                  vsbExt, bottom);
       
  1002         }
       
  1003     } else {
       
  1004         if (! frameContentsOnly)
       
  1005             changeFrameRect(QRect(0, 0, w, h));
       
  1006         else
       
  1007             changeFrameRect(QRect(0, 0, w, bottom));
       
  1008         clipper()->setGeometry(lmarg, tmarg,
       
  1009                                 w-lmarg-rmarg, bottom-tmarg-bmarg);
       
  1010         d->viewportResized(w-lmarg-rmarg, bottom-tmarg-bmarg);
       
  1011     }
       
  1012 
       
  1013     QWidget *corner = d->corner;
       
  1014     if (d->corner) {
       
  1015         if (! frameContentsOnly)
       
  1016             corner->setGeometry(xpos,
       
  1017                                 h-hsbExt-fw,
       
  1018                                 vsbExt,
       
  1019                                 hsbExt);
       
  1020         else
       
  1021             corner->setGeometry(xpos,
       
  1022                                 h-hsbExt,
       
  1023                                 vsbExt,
       
  1024                                 hsbExt);
       
  1025     }
       
  1026 
       
  1027     d->signal_choke=sc;
       
  1028 
       
  1029     if (d->contentsX()+visibleWidth() > d->contentsWidth()) {
       
  1030         int x;
       
  1031 #if 0
       
  1032         if (reverse)
       
  1033             x =QMIN(0,d->contentsWidth()-visibleWidth());
       
  1034         else
       
  1035 #endif
       
  1036             x =QMAX(0,d->contentsWidth()-visibleWidth());
       
  1037         d->hbar->setValue(x);
       
  1038         // Do it even if it is recursive
       
  1039         moveContents(-x, -d->contentsY());
       
  1040     }
       
  1041     if (d->contentsY()+visibleHeight() > contentsHeight()) {
       
  1042         int y=QMAX(0,contentsHeight()-visibleHeight());
       
  1043         d->vbar->setValue(y);
       
  1044         // Do it even if it is recursive
       
  1045         moveContents(-d->contentsX(), -y);
       
  1046     }
       
  1047 
       
  1048     // Finally, show the scroll bars
       
  1049     if (showh && (d->hbar->isHidden() || !d->hbar->isVisible()))
       
  1050         d->hbar->show();
       
  1051     if (showv && (d->vbar->isHidden() || !d->vbar->isVisible()))
       
  1052         d->vbar->show();
       
  1053 
       
  1054     d->signal_choke=true;
       
  1055     d->vbar->setValue(d->contentsY());
       
  1056     d->hbar->setValue(d->contentsX());
       
  1057     d->signal_choke=false;
       
  1058 
       
  1059     QSize newVisibleSize(visibleWidth(), visibleHeight());
       
  1060     if (d->clipped_viewport && oldVisibleSize != newVisibleSize) {
       
  1061         QResizeEvent e(newVisibleSize, oldVisibleSize);
       
  1062         viewportResizeEvent(&e);
       
  1063     }
       
  1064 }
       
  1065 
       
  1066 
       
  1067 /*!
       
  1068     \reimp
       
  1069 */
       
  1070 void Q3ScrollView::setVisible(bool visible)
       
  1071 {
       
  1072     if (visible && !isVisible()) {
       
  1073         QWidget::setVisible(visible);
       
  1074         updateScrollBars();
       
  1075         d->hideOrShowAll(this);
       
  1076     } else {
       
  1077         QWidget::setVisible(visible);
       
  1078     }
       
  1079 }
       
  1080 
       
  1081 /*!
       
  1082     \internal
       
  1083  */
       
  1084 void Q3ScrollView::resize(int w, int h)
       
  1085 {
       
  1086     QWidget::resize(w, h);
       
  1087 }
       
  1088 
       
  1089 /*!
       
  1090     \internal
       
  1091 */
       
  1092 void Q3ScrollView::resize(const QSize& s)
       
  1093 {
       
  1094     resize(s.width(), s.height());
       
  1095 }
       
  1096 
       
  1097 /*!
       
  1098     \reimp
       
  1099 */
       
  1100 void Q3ScrollView::resizeEvent(QResizeEvent* event)
       
  1101 {
       
  1102     Q3Frame::resizeEvent(event);
       
  1103 
       
  1104 #if 0
       
  1105     if (QApplication::reverseLayout()) {
       
  1106         d->fake_scroll = true;
       
  1107         scrollBy(-event->size().width() + event->oldSize().width(), 0);
       
  1108         d->fake_scroll = false;
       
  1109     }
       
  1110 #endif
       
  1111 
       
  1112     bool inresize = d->inresize;
       
  1113     d->inresize = true;
       
  1114     updateScrollBars();
       
  1115     d->inresize = inresize;
       
  1116     d->scrollbar_timer.start(0, true);
       
  1117 
       
  1118     d->hideOrShowAll(this);
       
  1119 }
       
  1120 
       
  1121 
       
  1122 
       
  1123 /*!
       
  1124     \reimp
       
  1125 */
       
  1126 void  Q3ScrollView::mousePressEvent(QMouseEvent * e)
       
  1127 {
       
  1128     e->ignore();
       
  1129 }
       
  1130 
       
  1131 /*!
       
  1132     \reimp
       
  1133 */
       
  1134 void  Q3ScrollView::mouseReleaseEvent(QMouseEvent *e)
       
  1135 {
       
  1136     e->ignore();
       
  1137 }
       
  1138 
       
  1139 
       
  1140 /*!
       
  1141     \reimp
       
  1142 */
       
  1143 void  Q3ScrollView::mouseDoubleClickEvent(QMouseEvent *e)
       
  1144 {
       
  1145     e->ignore();
       
  1146 }
       
  1147 
       
  1148 /*!
       
  1149     \reimp
       
  1150 */
       
  1151 void  Q3ScrollView::mouseMoveEvent(QMouseEvent *e)
       
  1152 {
       
  1153     e->ignore();
       
  1154 }
       
  1155 
       
  1156 /*!
       
  1157     \reimp
       
  1158 */
       
  1159 #ifndef QT_NO_WHEELEVENT
       
  1160 void Q3ScrollView::wheelEvent(QWheelEvent *e)
       
  1161 {
       
  1162     QWheelEvent ce(viewport()->mapFromGlobal(e->globalPos()),
       
  1163                     e->globalPos(), e->delta(), e->state());
       
  1164     viewportWheelEvent(&ce);
       
  1165     if (!ce.isAccepted()) {
       
  1166         if (e->orientation() == Horizontal && horizontalScrollBar())
       
  1167             horizontalScrollBar()->event(e);
       
  1168         else  if (e->orientation() == Vertical && verticalScrollBar())
       
  1169             verticalScrollBar()->event(e);
       
  1170     } else {
       
  1171         e->accept();
       
  1172     }
       
  1173 }
       
  1174 #endif
       
  1175 
       
  1176 /*!
       
  1177     \reimp
       
  1178 */
       
  1179 void Q3ScrollView::contextMenuEvent(QContextMenuEvent *e)
       
  1180 {
       
  1181     if (e->reason() != QContextMenuEvent::Keyboard) {
       
  1182         e->ignore();
       
  1183         return;
       
  1184     }
       
  1185 
       
  1186     QContextMenuEvent ce(e->reason(), viewport()->mapFromGlobal(e->globalPos()),
       
  1187                           e->globalPos(), e->state());
       
  1188     viewportContextMenuEvent(&ce);
       
  1189     if (ce.isAccepted())
       
  1190         e->accept();
       
  1191     else
       
  1192         e->ignore();
       
  1193 }
       
  1194 
       
  1195 Q3ScrollView::ScrollBarMode Q3ScrollView::vScrollBarMode() const
       
  1196 {
       
  1197     return d->vMode;
       
  1198 }
       
  1199 
       
  1200 
       
  1201 /*!
       
  1202     \enum Q3ScrollView::ScrollBarMode
       
  1203 
       
  1204     This enum type describes the various modes of Q3ScrollView's scroll
       
  1205     bars.
       
  1206 
       
  1207     \value Auto  Q3ScrollView shows a scroll bar when the content is
       
  1208     too large to fit and not otherwise. This is the default.
       
  1209 
       
  1210     \value AlwaysOff  Q3ScrollView never shows a scroll bar.
       
  1211 
       
  1212     \value AlwaysOn  Q3ScrollView always shows a scroll bar.
       
  1213 
       
  1214     (The modes for the horizontal and vertical scroll bars are
       
  1215     independent.)
       
  1216 */
       
  1217 
       
  1218 
       
  1219 /*!
       
  1220     \property Q3ScrollView::vScrollBarMode
       
  1221     \brief the mode for the vertical scroll bar
       
  1222 
       
  1223     The default mode is Q3ScrollView::Auto.
       
  1224 
       
  1225     \sa hScrollBarMode
       
  1226 */
       
  1227 void  Q3ScrollView::setVScrollBarMode(ScrollBarMode mode)
       
  1228 {
       
  1229     if (d->vMode != mode) {
       
  1230         d->vMode = mode;
       
  1231         updateScrollBars();
       
  1232     }
       
  1233 }
       
  1234 
       
  1235 
       
  1236 /*!
       
  1237     \property Q3ScrollView::hScrollBarMode
       
  1238     \brief the mode for the horizontal scroll bar
       
  1239 
       
  1240     The default mode is Q3ScrollView::Auto.
       
  1241 
       
  1242     \sa vScrollBarMode
       
  1243 */
       
  1244 Q3ScrollView::ScrollBarMode Q3ScrollView::hScrollBarMode() const
       
  1245 {
       
  1246     return d->hMode;
       
  1247 }
       
  1248 
       
  1249 void Q3ScrollView::setHScrollBarMode(ScrollBarMode mode)
       
  1250 {
       
  1251     if (d->hMode != mode) {
       
  1252         d->hMode = mode;
       
  1253         updateScrollBars();
       
  1254     }
       
  1255 }
       
  1256 
       
  1257 
       
  1258 /*!
       
  1259     Returns the widget in the corner between the two scroll bars.
       
  1260 
       
  1261     By default, no corner widget is present.
       
  1262 */
       
  1263 QWidget* Q3ScrollView::cornerWidget() const
       
  1264 {
       
  1265     return d->corner;
       
  1266 }
       
  1267 
       
  1268 /*!
       
  1269     Sets the widget in the \a corner between the two scroll bars.
       
  1270 
       
  1271     You will probably also want to set at least one of the scroll bar
       
  1272     modes to \c AlwaysOn.
       
  1273 
       
  1274     Passing 0 shows no widget in the corner.
       
  1275 
       
  1276     Any previous \a corner widget is hidden.
       
  1277 
       
  1278     You may call setCornerWidget() with the same widget at different
       
  1279     times.
       
  1280 
       
  1281     All widgets set here will be deleted by the Q3ScrollView when it is
       
  1282     destroyed unless you separately reparent the widget after setting
       
  1283     some other corner widget (or 0).
       
  1284 
       
  1285     Any \e newly set widget should have no current parent.
       
  1286 
       
  1287     By default, no corner widget is present.
       
  1288 
       
  1289     \sa setVScrollBarMode(), setHScrollBarMode()
       
  1290 */
       
  1291 void Q3ScrollView::setCornerWidget(QWidget* corner)
       
  1292 {
       
  1293     QWidget* oldcorner = d->corner;
       
  1294     if (oldcorner != corner) {
       
  1295         if (oldcorner) oldcorner->hide();
       
  1296         d->corner = corner;
       
  1297         if (corner) corner->setParent(this);
       
  1298         updateScrollBars();
       
  1299         if (corner) corner->show();
       
  1300     }
       
  1301 }
       
  1302 
       
  1303 
       
  1304 void Q3ScrollView::setResizePolicy(ResizePolicy r)
       
  1305 {
       
  1306     d->policy = r;
       
  1307 }
       
  1308 
       
  1309 /*!
       
  1310     \property Q3ScrollView::resizePolicy
       
  1311     \brief the resize policy
       
  1312 
       
  1313     The default is \c Default.
       
  1314 
       
  1315     \sa ResizePolicy
       
  1316 */
       
  1317 Q3ScrollView::ResizePolicy Q3ScrollView::resizePolicy() const
       
  1318 {
       
  1319     return d->policy;
       
  1320 }
       
  1321 
       
  1322 /*!
       
  1323     \internal
       
  1324 */
       
  1325 void Q3ScrollView::setEnabled(bool enable)
       
  1326 {
       
  1327     Q3Frame::setEnabled(enable);
       
  1328 }
       
  1329 
       
  1330 /*!
       
  1331     Removes the \a child widget from the scrolled area. Note that this
       
  1332     happens automatically if the \a child is deleted.
       
  1333 */
       
  1334 void Q3ScrollView::removeChild(QWidget* child)
       
  1335 {
       
  1336     if (!d || !child) // First check in case we are destructing
       
  1337         return;
       
  1338 
       
  1339     QSVChildRec *r = d->rec(child);
       
  1340     if (r) d->deleteChildRec(r);
       
  1341 }
       
  1342 
       
  1343 /*!
       
  1344     \internal
       
  1345 */
       
  1346 void Q3ScrollView::removeChild(QObject* child)
       
  1347 {
       
  1348     Q3Frame::removeChild(child);
       
  1349 }
       
  1350 
       
  1351 /*!
       
  1352     Inserts the widget, \a child, into the scrolled area positioned at
       
  1353     (\a x, \a y). The position defaults to (0, 0). If the child is
       
  1354     already in the view, it is just moved.
       
  1355 
       
  1356     You may want to call enableClipper(true) if you add a large number
       
  1357     of widgets.
       
  1358 */
       
  1359 void Q3ScrollView::addChild(QWidget* child, int x, int y)
       
  1360 {
       
  1361     if (!child) {
       
  1362 #if defined(QT_CHECK_NULL)
       
  1363         qWarning("Q3ScrollView::addChild(): Cannot add null child");
       
  1364 #endif
       
  1365         return;
       
  1366     }
       
  1367     child->polish();
       
  1368     child->setBackgroundOrigin(WidgetOrigin);
       
  1369 
       
  1370     if (child->parentWidget() == viewport()) {
       
  1371         // May already be there
       
  1372         QSVChildRec *r = d->rec(child);
       
  1373         if (r) {
       
  1374             r->moveTo(this,x,y,d->clipped_viewport);
       
  1375             if (d->policy > Manual) {
       
  1376                 d->autoResizeHint(this);
       
  1377                 d->autoResize(this); // #### better to just deal with this one widget!
       
  1378             }
       
  1379             return;
       
  1380         }
       
  1381     }
       
  1382 
       
  1383     if (d->children.isEmpty() && d->policy != Manual) {
       
  1384         if (d->policy == Default)
       
  1385             setResizePolicy(AutoOne);
       
  1386         child->installEventFilter(this);
       
  1387     } else if (d->policy == AutoOne) {
       
  1388         child->removeEventFilter(this); //#### ?????
       
  1389         setResizePolicy(Manual);
       
  1390     }
       
  1391     if (child->parentWidget() != viewport()) {
       
  1392             child->reparent(viewport(), 0, QPoint(0,0), false);
       
  1393     }
       
  1394     d->addChildRec(child,x,y)->hideOrShow(this, d->clipped_viewport);
       
  1395 
       
  1396     if (d->policy > Manual) {
       
  1397         d->autoResizeHint(this);
       
  1398         d->autoResize(this); // #### better to just deal with this one widget!
       
  1399     }
       
  1400 }
       
  1401 
       
  1402 /*!
       
  1403     Repositions the \a child widget to (\a x, \a y). This function is
       
  1404     the same as addChild().
       
  1405 */
       
  1406 void Q3ScrollView::moveChild(QWidget* child, int x, int y)
       
  1407 {
       
  1408     addChild(child,x,y);
       
  1409 }
       
  1410 
       
  1411 /*!
       
  1412     Returns the X position of the given \a child widget. Use this
       
  1413     rather than QWidget::x() for widgets added to the view.
       
  1414 
       
  1415     This function returns 0 if \a child has not been added to the view.
       
  1416 */
       
  1417 int Q3ScrollView::childX(QWidget* child)
       
  1418 {
       
  1419     QSVChildRec *r = d->rec(child);
       
  1420     return r ? r->x : 0;
       
  1421 }
       
  1422 
       
  1423 /*!
       
  1424     Returns the Y position of the given \a child widget. Use this
       
  1425     rather than QWidget::y() for widgets added to the view.
       
  1426 
       
  1427     This function returns 0 if \a child has not been added to the view.
       
  1428 */
       
  1429 int Q3ScrollView::childY(QWidget* child)
       
  1430 {
       
  1431     QSVChildRec *r = d->rec(child);
       
  1432     return r ? r->y : 0;
       
  1433 }
       
  1434 
       
  1435 /*! \fn bool Q3ScrollView::childIsVisible(QWidget*)
       
  1436   \obsolete
       
  1437 
       
  1438   Returns true if \a child is visible. This is equivalent
       
  1439   to child->isVisible().
       
  1440 */
       
  1441 
       
  1442 /*! \fn void Q3ScrollView::showChild(QWidget* child, bool y)
       
  1443   \obsolete
       
  1444 
       
  1445   Sets the visibility of \a child. Equivalent to
       
  1446   QWidget::show() or QWidget::hide().
       
  1447 */
       
  1448 
       
  1449 /*!
       
  1450     This event filter ensures the scroll bars are updated when a
       
  1451     single contents widget is resized, shown, hidden or destroyed; it
       
  1452     passes mouse events to the Q3ScrollView. The event is in \a e and
       
  1453     the object is in \a obj.
       
  1454 */
       
  1455 
       
  1456 bool Q3ScrollView::eventFilter(QObject *obj, QEvent *e)
       
  1457 {
       
  1458     bool disabled = !(qobject_cast<QWidget*>(obj)->isEnabled());
       
  1459     if (!d)
       
  1460         return false; // we are destructing
       
  1461     if (obj == d->viewport || obj == d->clipped_viewport) {
       
  1462         switch (e->type()) {
       
  1463             /* Forward many events to viewport...() functions */
       
  1464         case QEvent::Paint:
       
  1465             viewportPaintEvent((QPaintEvent*)e);
       
  1466             break;
       
  1467         case QEvent::Resize:
       
  1468             if (!d->clipped_viewport)
       
  1469                 viewportResizeEvent((QResizeEvent *)e);
       
  1470             break;
       
  1471         case QEvent::MouseButtonPress:
       
  1472             if (disabled)
       
  1473                 return false;
       
  1474             viewportMousePressEvent((QMouseEvent*)e);
       
  1475             if (((QMouseEvent*)e)->isAccepted())
       
  1476                 return true;
       
  1477             break;
       
  1478         case QEvent::MouseButtonRelease:
       
  1479             if (disabled)
       
  1480                 return false;
       
  1481             viewportMouseReleaseEvent((QMouseEvent*)e);
       
  1482             if (((QMouseEvent*)e)->isAccepted())
       
  1483                 return true;
       
  1484             break;
       
  1485         case QEvent::MouseButtonDblClick:
       
  1486             if (disabled)
       
  1487                 return false;
       
  1488             viewportMouseDoubleClickEvent((QMouseEvent*)e);
       
  1489             if (((QMouseEvent*)e)->isAccepted())
       
  1490                 return true;
       
  1491             break;
       
  1492         case QEvent::MouseMove:
       
  1493             if (disabled)
       
  1494                 return false;
       
  1495             viewportMouseMoveEvent((QMouseEvent*)e);
       
  1496             if (((QMouseEvent*)e)->isAccepted())
       
  1497                 return true;
       
  1498             break;
       
  1499 #ifndef QT_NO_DRAGANDDROP
       
  1500         case QEvent::DragEnter:
       
  1501             if (disabled)
       
  1502                 return false;
       
  1503             viewportDragEnterEvent((QDragEnterEvent*)e);
       
  1504             break;
       
  1505         case QEvent::DragMove: {
       
  1506             if (disabled)
       
  1507                 return false;
       
  1508             if (d->drag_autoscroll) {
       
  1509                 QPoint vp = ((QDragMoveEvent*) e)->pos();
       
  1510                 QRect inside_margin(autoscroll_margin, autoscroll_margin,
       
  1511                                      visibleWidth() - autoscroll_margin * 2,
       
  1512                                      visibleHeight() - autoscroll_margin * 2);
       
  1513                 if (!inside_margin.contains(vp)) {
       
  1514                     startDragAutoScroll();
       
  1515                     // Keep sending move events
       
  1516                     ((QDragMoveEvent*)e)->accept(QRect(0,0,0,0));
       
  1517                 }
       
  1518             }
       
  1519             viewportDragMoveEvent((QDragMoveEvent*)e);
       
  1520         } break;
       
  1521         case QEvent::DragLeave:
       
  1522             if (disabled)
       
  1523                 return false;
       
  1524             stopDragAutoScroll();
       
  1525             viewportDragLeaveEvent((QDragLeaveEvent*)e);
       
  1526             break;
       
  1527         case QEvent::Drop:
       
  1528             if (disabled)
       
  1529                 return false;
       
  1530             stopDragAutoScroll();
       
  1531             viewportDropEvent((QDropEvent*)e);
       
  1532             break;
       
  1533 #endif // QT_NO_DRAGANDDROP
       
  1534 #ifndef QT_NO_WHEELEVENT
       
  1535         case QEvent::Wheel:
       
  1536             if (disabled)
       
  1537                 return false;
       
  1538             break;
       
  1539 #endif
       
  1540         case QEvent::ContextMenu:
       
  1541             if (disabled)
       
  1542                 return false;
       
  1543             viewportContextMenuEvent((QContextMenuEvent*)e);
       
  1544             if (((QContextMenuEvent*)e)->isAccepted())
       
  1545                 return true;
       
  1546             break;
       
  1547         case QEvent::ChildRemoved:
       
  1548             removeChild((QWidget*)((QChildEvent*)e)->child());
       
  1549             break;
       
  1550         case QEvent::LayoutHint:
       
  1551             d->autoResizeHint(this);
       
  1552             break;
       
  1553         default:
       
  1554             break;
       
  1555         }
       
  1556     } else if (d && d->rec((QWidget*)obj)) {  // must be a child
       
  1557         if (e->type() == QEvent::Resize)
       
  1558             d->autoResize(this);
       
  1559         else if (e->type() == QEvent::Move)
       
  1560             d->autoMove(this);
       
  1561     }
       
  1562     return Q3Frame::eventFilter(obj, e);  // always continue with standard event processing
       
  1563 }
       
  1564 
       
  1565 /*!
       
  1566     This event handler is called whenever the Q3ScrollView receives a
       
  1567     mousePressEvent(): the press position in \a e is translated to be a point
       
  1568     on the contents.
       
  1569 */
       
  1570 void Q3ScrollView::contentsMousePressEvent(QMouseEvent* e)
       
  1571 {
       
  1572     e->ignore();
       
  1573 }
       
  1574 
       
  1575 /*!
       
  1576     This event handler is called whenever the Q3ScrollView receives a
       
  1577     mouseReleaseEvent(): the release position in \a e is translated to be a
       
  1578     point on the contents.
       
  1579 */
       
  1580 void Q3ScrollView::contentsMouseReleaseEvent(QMouseEvent* e)
       
  1581 {
       
  1582     e->ignore();
       
  1583 }
       
  1584 
       
  1585 /*!
       
  1586     This event handler is called whenever the Q3ScrollView receives a
       
  1587     mouseDoubleClickEvent(): the click position in \a e is translated to be a
       
  1588     point on the contents.
       
  1589 
       
  1590     The default implementation generates a normal mouse press event.
       
  1591 */
       
  1592 void Q3ScrollView::contentsMouseDoubleClickEvent(QMouseEvent* e)
       
  1593 {
       
  1594     contentsMousePressEvent(e);             // try mouse press event
       
  1595 }
       
  1596 
       
  1597 /*!
       
  1598     This event handler is called whenever the Q3ScrollView receives a
       
  1599     mouseMoveEvent(): the mouse position in \a e is translated to be a point
       
  1600     on the contents.
       
  1601 */
       
  1602 void Q3ScrollView::contentsMouseMoveEvent(QMouseEvent* e)
       
  1603 {
       
  1604     e->ignore();
       
  1605 }
       
  1606 
       
  1607 #ifndef QT_NO_DRAGANDDROP
       
  1608 
       
  1609 /*!
       
  1610     This event handler is called whenever the Q3ScrollView receives a
       
  1611     dragEnterEvent(): the drag position is translated to be a point
       
  1612     on the contents.
       
  1613 
       
  1614     The default implementation does nothing. The \a event parameter is
       
  1615     ignored.
       
  1616 */
       
  1617 void Q3ScrollView::contentsDragEnterEvent(QDragEnterEvent * /* event */)
       
  1618 {
       
  1619 }
       
  1620 
       
  1621 /*!
       
  1622     This event handler is called whenever the Q3ScrollView receives a
       
  1623     dragMoveEvent(): the drag position is translated to be a point on
       
  1624     the contents.
       
  1625 
       
  1626     The default implementation does nothing. The \a event parameter is
       
  1627     ignored.
       
  1628 */
       
  1629 void Q3ScrollView::contentsDragMoveEvent(QDragMoveEvent * /* event */)
       
  1630 {
       
  1631 }
       
  1632 
       
  1633 /*!
       
  1634     This event handler is called whenever the Q3ScrollView receives a
       
  1635     dragLeaveEvent(): the drag position is translated to be a point
       
  1636     on the contents.
       
  1637 
       
  1638     The default implementation does nothing. The \a event parameter is
       
  1639     ignored.
       
  1640 */
       
  1641 void Q3ScrollView::contentsDragLeaveEvent(QDragLeaveEvent * /* event */)
       
  1642 {
       
  1643 }
       
  1644 
       
  1645 /*!
       
  1646     This event handler is called whenever the Q3ScrollView receives a
       
  1647     dropEvent(): the drop position is translated to be a point on the
       
  1648     contents.
       
  1649 
       
  1650     The default implementation does nothing. The \a event parameter is
       
  1651     ignored.
       
  1652 */
       
  1653 
       
  1654 void Q3ScrollView::contentsDropEvent(QDropEvent * /* event */)
       
  1655 {
       
  1656 }
       
  1657 
       
  1658 #endif // QT_NO_DRAGANDDROP
       
  1659 
       
  1660 /*!
       
  1661     This event handler is called whenever the Q3ScrollView receives a
       
  1662     wheelEvent() in \a{e}: the mouse position is translated to be a
       
  1663     point on the contents.
       
  1664 */
       
  1665 #ifndef QT_NO_WHEELEVENT
       
  1666 void Q3ScrollView::contentsWheelEvent(QWheelEvent * e)
       
  1667 {
       
  1668     e->ignore();
       
  1669 }
       
  1670 #endif
       
  1671 /*!
       
  1672     This event handler is called whenever the Q3ScrollView receives a
       
  1673     contextMenuEvent() in \a{e}: the mouse position is translated to
       
  1674     be a point on the contents.
       
  1675 */
       
  1676 void Q3ScrollView::contentsContextMenuEvent(QContextMenuEvent *e)
       
  1677 {
       
  1678     e->ignore();
       
  1679 }
       
  1680 
       
  1681 /*!
       
  1682     This is a low-level painting routine that draws the viewport
       
  1683     contents. Reimplement this if drawContents() is too high-level
       
  1684     (for example, if you don't want to open a QPainter on the
       
  1685     viewport). The paint event is passed in \a pe.
       
  1686 */
       
  1687 void Q3ScrollView::viewportPaintEvent(QPaintEvent* pe)
       
  1688 {
       
  1689     QWidget* vp = viewport();
       
  1690 
       
  1691     QPainter p(vp);
       
  1692     QRect r = pe->rect();
       
  1693 
       
  1694     if (d->clipped_viewport) {
       
  1695         QRect rr(
       
  1696             -d->clipped_viewport->x(), -d->clipped_viewport->y(),
       
  1697             d->viewport->width(), d->viewport->height()
       
  1698            );
       
  1699         r &= rr;
       
  1700         if (r.isValid()) {
       
  1701             int ex = r.x() + d->clipped_viewport->x() + d->contentsX();
       
  1702             int ey = r.y() + d->clipped_viewport->y() + d->contentsY();
       
  1703             int ew = r.width();
       
  1704             int eh = r.height();
       
  1705             drawContentsOffset(&p,
       
  1706                 d->contentsX()+d->clipped_viewport->x(),
       
  1707                 d->contentsY()+d->clipped_viewport->y(),
       
  1708                 ex, ey, ew, eh);
       
  1709         }
       
  1710     } else {
       
  1711         r &= d->viewport->rect();
       
  1712         int ex = r.x() + d->contentsX();
       
  1713         int ey = r.y() + d->contentsY();
       
  1714         int ew = r.width();
       
  1715         int eh = r.height();
       
  1716         drawContentsOffset(&p, d->contentsX(), d->contentsY(), ex, ey, ew, eh);
       
  1717     }
       
  1718 }
       
  1719 
       
  1720 
       
  1721 /*!
       
  1722     To provide simple processing of events on the contents, this
       
  1723     function receives all resize events sent to the viewport.
       
  1724 
       
  1725     The default implementation does nothing. The \a event parameter is
       
  1726     ignored.
       
  1727 
       
  1728     \sa QWidget::resizeEvent()
       
  1729 */
       
  1730 void Q3ScrollView::viewportResizeEvent(QResizeEvent * /* event */)
       
  1731 {
       
  1732 }
       
  1733 
       
  1734 /*! \internal
       
  1735 
       
  1736   To provide simple processing of events on the contents, this
       
  1737   function receives all mouse press events sent to the viewport,
       
  1738   translates the event and calls contentsMousePressEvent().
       
  1739 
       
  1740   \sa contentsMousePressEvent(), QWidget::mousePressEvent()
       
  1741 */
       
  1742 void Q3ScrollView::viewportMousePressEvent(QMouseEvent* e)
       
  1743 {
       
  1744     QMouseEvent ce(e->type(), viewportToContents(e->pos()),
       
  1745         e->globalPos(), e->button(), e->state());
       
  1746     contentsMousePressEvent(&ce);
       
  1747     if (!ce.isAccepted())
       
  1748         e->ignore();
       
  1749 }
       
  1750 
       
  1751 /*!\internal
       
  1752 
       
  1753   To provide simple processing of events on the contents, this function
       
  1754   receives all mouse release events sent to the viewport, translates
       
  1755   the event and calls contentsMouseReleaseEvent().
       
  1756 
       
  1757   \sa QWidget::mouseReleaseEvent()
       
  1758 */
       
  1759 void Q3ScrollView::viewportMouseReleaseEvent(QMouseEvent* e)
       
  1760 {
       
  1761     QMouseEvent ce(e->type(), viewportToContents(e->pos()),
       
  1762         e->globalPos(), e->button(), e->state());
       
  1763     contentsMouseReleaseEvent(&ce);
       
  1764     if (!ce.isAccepted())
       
  1765         e->ignore();
       
  1766 }
       
  1767 
       
  1768 /*!\internal
       
  1769 
       
  1770   To provide simple processing of events on the contents, this function
       
  1771   receives all mouse double click events sent to the viewport,
       
  1772   translates the event and calls contentsMouseDoubleClickEvent().
       
  1773 
       
  1774   \sa QWidget::mouseDoubleClickEvent()
       
  1775 */
       
  1776 void Q3ScrollView::viewportMouseDoubleClickEvent(QMouseEvent* e)
       
  1777 {
       
  1778     QMouseEvent ce(e->type(), viewportToContents(e->pos()),
       
  1779         e->globalPos(), e->button(), e->state());
       
  1780     contentsMouseDoubleClickEvent(&ce);
       
  1781     if (!ce.isAccepted())
       
  1782         e->ignore();
       
  1783 }
       
  1784 
       
  1785 /*!\internal
       
  1786 
       
  1787   To provide simple processing of events on the contents, this function
       
  1788   receives all mouse move events sent to the viewport, translates the
       
  1789   event and calls contentsMouseMoveEvent().
       
  1790 
       
  1791   \sa QWidget::mouseMoveEvent()
       
  1792 */
       
  1793 void Q3ScrollView::viewportMouseMoveEvent(QMouseEvent* e)
       
  1794 {
       
  1795     QMouseEvent ce(e->type(), viewportToContents(e->pos()),
       
  1796         e->globalPos(), e->button(), e->state());
       
  1797     contentsMouseMoveEvent(&ce);
       
  1798     if (!ce.isAccepted())
       
  1799         e->ignore();
       
  1800 }
       
  1801 
       
  1802 #ifndef QT_NO_DRAGANDDROP
       
  1803 
       
  1804 /*!\internal
       
  1805 
       
  1806   To provide simple processing of events on the contents, this function
       
  1807   receives all drag enter events sent to the viewport, translates the
       
  1808   event and calls contentsDragEnterEvent().
       
  1809 
       
  1810   \sa QWidget::dragEnterEvent()
       
  1811 */
       
  1812 void Q3ScrollView::viewportDragEnterEvent(QDragEnterEvent* e)
       
  1813 {
       
  1814     e->setPoint(viewportToContents(e->pos()));
       
  1815     contentsDragEnterEvent(e);
       
  1816     e->setPoint(contentsToViewport(e->pos()));
       
  1817 }
       
  1818 
       
  1819 /*!\internal
       
  1820 
       
  1821   To provide simple processing of events on the contents, this function
       
  1822   receives all drag move events sent to the viewport, translates the
       
  1823   event and calls contentsDragMoveEvent().
       
  1824 
       
  1825   \sa QWidget::dragMoveEvent()
       
  1826 */
       
  1827 void Q3ScrollView::viewportDragMoveEvent(QDragMoveEvent* e)
       
  1828 {
       
  1829     e->setPoint(viewportToContents(e->pos()));
       
  1830     contentsDragMoveEvent(e);
       
  1831     e->setPoint(contentsToViewport(e->pos()));
       
  1832 }
       
  1833 
       
  1834 /*!\internal
       
  1835 
       
  1836   To provide simple processing of events on the contents, this function
       
  1837   receives all drag leave events sent to the viewport and calls
       
  1838   contentsDragLeaveEvent().
       
  1839 
       
  1840   \sa QWidget::dragLeaveEvent()
       
  1841 */
       
  1842 void Q3ScrollView::viewportDragLeaveEvent(QDragLeaveEvent* e)
       
  1843 {
       
  1844     contentsDragLeaveEvent(e);
       
  1845 }
       
  1846 
       
  1847 /*!\internal
       
  1848 
       
  1849   To provide simple processing of events on the contents, this function
       
  1850   receives all drop events sent to the viewport, translates the event
       
  1851   and calls contentsDropEvent().
       
  1852 
       
  1853   \sa QWidget::dropEvent()
       
  1854 */
       
  1855 void Q3ScrollView::viewportDropEvent(QDropEvent* e)
       
  1856 {
       
  1857     e->setPoint(viewportToContents(e->pos()));
       
  1858     contentsDropEvent(e);
       
  1859     e->setPoint(contentsToViewport(e->pos()));
       
  1860 }
       
  1861 
       
  1862 #endif // QT_NO_DRAGANDDROP
       
  1863 
       
  1864 /*!\internal
       
  1865 
       
  1866   To provide simple processing of events on the contents, this function
       
  1867   receives all wheel events sent to the viewport, translates the
       
  1868   event and calls contentsWheelEvent().
       
  1869 
       
  1870   \sa QWidget::wheelEvent()
       
  1871 */
       
  1872 #ifndef QT_NO_WHEELEVENT
       
  1873 void Q3ScrollView::viewportWheelEvent(QWheelEvent* e)
       
  1874 {
       
  1875     /*
       
  1876        Different than standard mouse events, because wheel events might
       
  1877        be sent to the focus widget if the widget-under-mouse doesn't want
       
  1878        the event itself.
       
  1879     */
       
  1880     QWheelEvent ce(viewportToContents(e->pos()),
       
  1881         e->globalPos(), e->delta(), e->state());
       
  1882     contentsWheelEvent(&ce);
       
  1883     if (ce.isAccepted())
       
  1884         e->accept();
       
  1885     else
       
  1886         e->ignore();
       
  1887 }
       
  1888 #endif
       
  1889 
       
  1890 /*! \internal
       
  1891 
       
  1892   To provide simple processing of events on the contents, this function
       
  1893   receives all context menu events sent to the viewport, translates the
       
  1894   event and calls contentsContextMenuEvent().
       
  1895 */
       
  1896 void Q3ScrollView::viewportContextMenuEvent(QContextMenuEvent *e)
       
  1897 {
       
  1898     QContextMenuEvent ce(e->reason(), viewportToContents(e->pos()), e->globalPos(), e->state());
       
  1899     contentsContextMenuEvent(&ce);
       
  1900     if (ce.isAccepted())
       
  1901         e->accept();
       
  1902     else
       
  1903         e->ignore();
       
  1904 }
       
  1905 
       
  1906 /*!
       
  1907     Returns the component horizontal scroll bar. It is made available
       
  1908     to allow accelerators, autoscrolling, etc.
       
  1909 
       
  1910     It should not be used for other purposes.
       
  1911 
       
  1912     This function never returns 0.
       
  1913 */
       
  1914 QScrollBar* Q3ScrollView::horizontalScrollBar() const
       
  1915 {
       
  1916     return d->hbar;
       
  1917 }
       
  1918 
       
  1919 /*!
       
  1920     Returns the component vertical scroll bar. It is made available to
       
  1921     allow accelerators, autoscrolling, etc.
       
  1922 
       
  1923     It should not be used for other purposes.
       
  1924 
       
  1925     This function never returns 0.
       
  1926 */
       
  1927 QScrollBar* Q3ScrollView::verticalScrollBar() const {
       
  1928     return d->vbar;
       
  1929 }
       
  1930 
       
  1931 
       
  1932 /*!
       
  1933     Scrolls the content so that the point (\a x, \a y) is visible with at
       
  1934     least 50-pixel margins (if possible, otherwise centered).
       
  1935 */
       
  1936 void Q3ScrollView::ensureVisible(int x, int y)
       
  1937 {
       
  1938     ensureVisible(x, y, 50, 50);
       
  1939 }
       
  1940 
       
  1941 /*!
       
  1942     \overload
       
  1943 
       
  1944     Scrolls the content so that the point (\a x, \a y) is visible with at
       
  1945     least the \a xmargin and \a ymargin margins (if possible,
       
  1946     otherwise centered).
       
  1947 */
       
  1948 void Q3ScrollView::ensureVisible(int x, int y, int xmargin, int ymargin)
       
  1949 {
       
  1950     int pw=visibleWidth();
       
  1951     int ph=visibleHeight();
       
  1952 
       
  1953     int cx=-d->contentsX();
       
  1954     int cy=-d->contentsY();
       
  1955     int cw=d->contentsWidth();
       
  1956     int ch=contentsHeight();
       
  1957 
       
  1958     if (pw < xmargin*2)
       
  1959         xmargin=pw/2;
       
  1960     if (ph < ymargin*2)
       
  1961         ymargin=ph/2;
       
  1962 
       
  1963     if (cw <= pw) {
       
  1964         xmargin=0;
       
  1965         cx=0;
       
  1966     }
       
  1967     if (ch <= ph) {
       
  1968         ymargin=0;
       
  1969         cy=0;
       
  1970     }
       
  1971 
       
  1972     if (x < -cx+xmargin)
       
  1973         cx = -x+xmargin;
       
  1974     else if (x >= -cx+pw-xmargin)
       
  1975         cx = -x+pw-xmargin;
       
  1976 
       
  1977     if (y < -cy+ymargin)
       
  1978         cy = -y+ymargin;
       
  1979     else if (y >= -cy+ph-ymargin)
       
  1980         cy = -y+ph-ymargin;
       
  1981 
       
  1982     if (cx > 0)
       
  1983         cx=0;
       
  1984     else if (cx < pw-cw && cw>pw)
       
  1985         cx=pw-cw;
       
  1986 
       
  1987     if (cy > 0)
       
  1988         cy=0;
       
  1989     else if (cy < ph-ch && ch>ph)
       
  1990         cy=ph-ch;
       
  1991 
       
  1992     setContentsPos(-cx, -cy);
       
  1993 }
       
  1994 
       
  1995 /*!
       
  1996     Scrolls the content so that the point (\a x, \a y) is in the top-left
       
  1997     corner.
       
  1998 */
       
  1999 void Q3ScrollView::setContentsPos(int x, int y)
       
  2000 {
       
  2001 #if 0
       
  2002     // bounds checking...
       
  2003     if (QApplication::reverseLayout())
       
  2004         if (x > d->contentsWidth() - visibleWidth()) x = d->contentsWidth() - visibleWidth();
       
  2005     else
       
  2006 #endif
       
  2007         if (x < 0) x = 0;
       
  2008     if (y < 0) y = 0;
       
  2009     // Choke signal handling while we update BOTH sliders.
       
  2010     d->signal_choke=true;
       
  2011     moveContents(-x, -y);
       
  2012     d->vbar->setValue(y);
       
  2013     d->hbar->setValue(x);
       
  2014     d->signal_choke=false;
       
  2015 }
       
  2016 
       
  2017 /*!
       
  2018     Scrolls the content by \a dx to the left and \a dy upwards.
       
  2019 */
       
  2020 void Q3ScrollView::scrollBy(int dx, int dy)
       
  2021 {
       
  2022     setContentsPos(QMAX(d->contentsX()+dx, 0), QMAX(d->contentsY()+dy, 0));
       
  2023 }
       
  2024 
       
  2025 /*!
       
  2026     Scrolls the content so that the point (\a x, \a y) is in the center
       
  2027     of visible area.
       
  2028 */
       
  2029 void Q3ScrollView::center(int x, int y)
       
  2030 {
       
  2031     ensureVisible(x, y, 32000, 32000);
       
  2032 }
       
  2033 
       
  2034 /*!
       
  2035     \overload
       
  2036 
       
  2037     Scrolls the content so that the point (\a x, \a y) is visible with
       
  2038     the \a xmargin and \a ymargin margins (as fractions of visible
       
  2039     the area).
       
  2040 
       
  2041     For example:
       
  2042     \list
       
  2043     \i Margin 0.0 allows (x, y) to be on the edge of the visible area.
       
  2044     \i Margin 0.5 ensures that (x, y) is in middle 50% of the visible area.
       
  2045     \i Margin 1.0 ensures that (x, y) is in the center of the visible area.
       
  2046     \endlist
       
  2047 */
       
  2048 void Q3ScrollView::center(int x, int y, float xmargin, float ymargin)
       
  2049 {
       
  2050     int pw=visibleWidth();
       
  2051     int ph=visibleHeight();
       
  2052     ensureVisible(x, y, int(xmargin/2.0*pw+0.5), int(ymargin/2.0*ph+0.5));
       
  2053 }
       
  2054 
       
  2055 
       
  2056 /*!
       
  2057     \fn void Q3ScrollView::contentsMoving(int x, int y)
       
  2058 
       
  2059     This signal is emitted just before the contents are moved to
       
  2060     position (\a x, \a y).
       
  2061 
       
  2062     \sa contentsX(), contentsY()
       
  2063 */
       
  2064 
       
  2065 /*!
       
  2066     Moves the contents by (\a x, \a y).
       
  2067 */
       
  2068 void Q3ScrollView::moveContents(int x, int y)
       
  2069 {
       
  2070     if (-x+visibleWidth() > d->contentsWidth())
       
  2071 #if 0
       
  2072         if(QApplication::reverseLayout())
       
  2073             x=QMAX(0,-d->contentsWidth()+visibleWidth());
       
  2074         else
       
  2075 #endif
       
  2076             x=QMIN(0,-d->contentsWidth()+visibleWidth());
       
  2077     if (-y+visibleHeight() > contentsHeight())
       
  2078         y=QMIN(0,-contentsHeight()+visibleHeight());
       
  2079 
       
  2080     int dx = x - d->vx;
       
  2081     int dy = y - d->vy;
       
  2082 
       
  2083     if (!dx && !dy)
       
  2084         return; // Nothing to do
       
  2085 
       
  2086     emit contentsMoving(-x, -y);
       
  2087 
       
  2088     d->vx = x;
       
  2089     d->vy = y;
       
  2090 
       
  2091     if (d->clipped_viewport || d->static_bg) {
       
  2092         // Cheap move (usually)
       
  2093         d->moveAllBy(dx,dy);
       
  2094     } else if (/*dx && dy ||*/
       
  2095          (QABS(dy) * 5 > visibleHeight() * 4) ||
       
  2096          (QABS(dx) * 5 > visibleWidth() * 4)
       
  2097        )
       
  2098     {
       
  2099         // Big move
       
  2100         if (viewport()->updatesEnabled())
       
  2101             viewport()->update();
       
  2102         d->moveAllBy(dx,dy);
       
  2103     } else if (!d->fake_scroll || d->contentsWidth() > visibleWidth()) {
       
  2104         // Small move
       
  2105         clipper()->scroll(dx,dy);
       
  2106     }
       
  2107     d->hideOrShowAll(this, true);
       
  2108 }
       
  2109 
       
  2110 /*!
       
  2111     \property Q3ScrollView::contentsX
       
  2112     \brief the X coordinate of the contents that are at the left edge of
       
  2113     the viewport.
       
  2114 */
       
  2115 int Q3ScrollView::contentsX() const
       
  2116 {
       
  2117     return d->contentsX();
       
  2118 }
       
  2119 
       
  2120 /*!
       
  2121     \property Q3ScrollView::contentsY
       
  2122     \brief the Y coordinate of the contents that are at the top edge of
       
  2123     the viewport.
       
  2124 */
       
  2125 int Q3ScrollView::contentsY() const
       
  2126 {
       
  2127     return d->contentsY();
       
  2128 }
       
  2129 
       
  2130 /*!
       
  2131     \property Q3ScrollView::contentsWidth
       
  2132     \brief the width of the contents area
       
  2133 */
       
  2134 int Q3ScrollView::contentsWidth() const
       
  2135 {
       
  2136     return d->contentsWidth();
       
  2137 }
       
  2138 
       
  2139 /*!
       
  2140     \property Q3ScrollView::contentsHeight
       
  2141     \brief the height of the contents area
       
  2142 */
       
  2143 int Q3ScrollView::contentsHeight() const
       
  2144 {
       
  2145     return d->vheight;
       
  2146 }
       
  2147 
       
  2148 /*!
       
  2149     Sets the size of the contents area to \a w pixels wide and \a h
       
  2150     pixels high and updates the viewport accordingly.
       
  2151 */
       
  2152 void Q3ScrollView::resizeContents(int w, int h)
       
  2153 {
       
  2154     int ow = d->vwidth;
       
  2155     int oh = d->vheight;
       
  2156     d->vwidth = w;
       
  2157     d->vheight = h;
       
  2158 
       
  2159     d->scrollbar_timer.start(0, true);
       
  2160 
       
  2161     if (d->children.isEmpty() && d->policy == Default)
       
  2162         setResizePolicy(Manual);
       
  2163 
       
  2164     if (ow > w) {
       
  2165         // Swap
       
  2166         int t=w;
       
  2167         w=ow;
       
  2168         ow=t;
       
  2169     }
       
  2170     // Refresh area ow..w
       
  2171     if (ow < visibleWidth() && w >= 0) {
       
  2172         if (ow < 0)
       
  2173             ow = 0;
       
  2174         if (w > visibleWidth())
       
  2175             w = visibleWidth();
       
  2176         clipper()->update(d->contentsX()+ow, 0, w-ow, visibleHeight());
       
  2177     }
       
  2178 
       
  2179     if (oh > h) {
       
  2180         // Swap
       
  2181         int t=h;
       
  2182         h=oh;
       
  2183         oh=t;
       
  2184     }
       
  2185     // Refresh area oh..h
       
  2186     if (oh < visibleHeight() && h >= 0) {
       
  2187         if (oh < 0)
       
  2188             oh = 0;
       
  2189         if (h > visibleHeight())
       
  2190             h = visibleHeight();
       
  2191         clipper()->update(0, d->contentsY()+oh, visibleWidth(), h-oh);
       
  2192     }
       
  2193 }
       
  2194 
       
  2195 /*!
       
  2196     Calls update() on a rectangle defined by \a x, \a y, \a w, \a h,
       
  2197     translated appropriately. If the rectangle is not visible, nothing
       
  2198     is repainted.
       
  2199 
       
  2200     \sa repaintContents()
       
  2201 */
       
  2202 void Q3ScrollView::updateContents(int x, int y, int w, int h)
       
  2203 {
       
  2204     if (!isVisible() || !updatesEnabled())
       
  2205         return;
       
  2206 
       
  2207     QWidget* vp = viewport();
       
  2208 
       
  2209     // Translate
       
  2210     x -= d->contentsX();
       
  2211     y -= d->contentsY();
       
  2212 
       
  2213     if (x < 0) {
       
  2214         w += x;
       
  2215         x = 0;
       
  2216     }
       
  2217     if (y < 0) {
       
  2218         h += y;
       
  2219         y = 0;
       
  2220     }
       
  2221 
       
  2222     if (w < 0 || h < 0)
       
  2223         return;
       
  2224     if (x > visibleWidth() || y > visibleHeight())
       
  2225         return;
       
  2226 
       
  2227     if (w > visibleWidth())
       
  2228         w = visibleWidth();
       
  2229     if (h > visibleHeight())
       
  2230         h = visibleHeight();
       
  2231 
       
  2232     if (d->clipped_viewport) {
       
  2233         // Translate clipper() to viewport()
       
  2234         x -= d->clipped_viewport->x();
       
  2235         y -= d->clipped_viewport->y();
       
  2236     }
       
  2237 
       
  2238     vp->update(x, y, w, h);
       
  2239 }
       
  2240 
       
  2241 /*!
       
  2242     \overload
       
  2243 
       
  2244     Updates the contents in rectangle \a r
       
  2245 */
       
  2246 void Q3ScrollView::updateContents(const QRect& r)
       
  2247 {
       
  2248     updateContents(r.x(), r.y(), r.width(), r.height());
       
  2249 }
       
  2250 
       
  2251 /*!
       
  2252     \overload
       
  2253 */
       
  2254 void Q3ScrollView::updateContents()
       
  2255 {
       
  2256     updateContents(d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight());
       
  2257 }
       
  2258 
       
  2259 /*!
       
  2260     \overload
       
  2261 
       
  2262     Repaints the contents of rectangle \a r. If \a erase is true the
       
  2263     background is cleared using the background color.
       
  2264 */
       
  2265 void Q3ScrollView::repaintContents(const QRect& r, bool erase)
       
  2266 {
       
  2267     repaintContents(r.x(), r.y(), r.width(), r.height(), erase);
       
  2268 }
       
  2269 
       
  2270 
       
  2271 /*!
       
  2272     \overload
       
  2273 
       
  2274     Repaints the contents. If \a erase is true the background is
       
  2275     cleared using the background color.
       
  2276 */
       
  2277 void Q3ScrollView::repaintContents(bool erase)
       
  2278 {
       
  2279     repaintContents(d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight(), erase);
       
  2280 }
       
  2281 
       
  2282 
       
  2283 /*!
       
  2284     Calls repaint() on a rectangle defined by \a x, \a y, \a w, \a h,
       
  2285     translated appropriately. If the rectangle is not visible, nothing
       
  2286     is repainted. If \a erase is true the background is cleared using
       
  2287     the background color.
       
  2288 
       
  2289     \sa updateContents()
       
  2290 */
       
  2291 void Q3ScrollView::repaintContents(int x, int y, int w, int h, bool /*erase*/)
       
  2292 {
       
  2293     if (!isVisible() || !updatesEnabled())
       
  2294         return;
       
  2295 
       
  2296     QWidget* vp = viewport();
       
  2297 
       
  2298     // Translate logical to clipper()
       
  2299     x -= d->contentsX();
       
  2300     y -= d->contentsY();
       
  2301 
       
  2302     if (x < 0) {
       
  2303         w += x;
       
  2304         x = 0;
       
  2305     }
       
  2306     if (y < 0) {
       
  2307         h += y;
       
  2308         y = 0;
       
  2309     }
       
  2310 
       
  2311     if (w < 0 || h < 0)
       
  2312         return;
       
  2313     if (w > visibleWidth())
       
  2314         w = visibleWidth();
       
  2315     if (h > visibleHeight())
       
  2316         h = visibleHeight();
       
  2317 
       
  2318     if (d->clipped_viewport) {
       
  2319         // Translate clipper() to viewport()
       
  2320         x -= d->clipped_viewport->x();
       
  2321         y -= d->clipped_viewport->y();
       
  2322     }
       
  2323 
       
  2324     vp->update(x, y, w, h);
       
  2325 }
       
  2326 
       
  2327 
       
  2328 /*!
       
  2329     For backward-compatibility only. It is easier to use
       
  2330     drawContents(QPainter*,int,int,int,int).
       
  2331 
       
  2332     The default implementation translates the painter appropriately
       
  2333     and calls drawContents(QPainter*,int,int,int,int). See
       
  2334     drawContents() for an explanation of the parameters \a p, \a
       
  2335     offsetx, \a offsety, \a clipx, \a clipy, \a clipw and \a cliph.
       
  2336 */
       
  2337 void Q3ScrollView::drawContentsOffset(QPainter* p, int offsetx, int offsety, int clipx, int clipy, int clipw, int cliph)
       
  2338 {
       
  2339     p->translate(-offsetx,-offsety);
       
  2340     drawContents(p, clipx, clipy, clipw, cliph);
       
  2341 }
       
  2342 
       
  2343 /*!
       
  2344     \fn void Q3ScrollView::drawContents(QPainter* p, int clipx, int clipy, int clipw, int cliph)
       
  2345 
       
  2346     Reimplement this function if you are viewing a drawing area rather
       
  2347     than a widget.
       
  2348 
       
  2349     The function should draw the rectangle (\a clipx, \a clipy, \a
       
  2350     clipw, \a cliph) of the contents using painter \a p. The clip
       
  2351     rectangle is in the scrollview's coordinates.
       
  2352 
       
  2353     For example:
       
  2354     \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 4
       
  2355 
       
  2356     The clip rectangle and translation of the painter \a p is already
       
  2357     set appropriately.
       
  2358 */
       
  2359 void Q3ScrollView::drawContents(QPainter*, int, int, int, int)
       
  2360 {
       
  2361 }
       
  2362 
       
  2363 
       
  2364 /*!
       
  2365     \reimp
       
  2366 */
       
  2367 void Q3ScrollView::frameChanged()
       
  2368 {
       
  2369     // slight ugle-hack - the listview header needs readjusting when
       
  2370     // changing the frame
       
  2371     if (Q3ListView *lv = qobject_cast<Q3ListView *>(this))
       
  2372         lv->triggerUpdate();
       
  2373     Q3Frame::frameChanged();
       
  2374     updateScrollBars();
       
  2375 }
       
  2376 
       
  2377 
       
  2378 /*!
       
  2379     Returns the viewport widget of the scrollview. This is the widget
       
  2380     containing the contents widget or which is the drawing area.
       
  2381 */
       
  2382 QWidget* Q3ScrollView::viewport() const
       
  2383 {
       
  2384     if (d->clipped_viewport)
       
  2385         return  d->clipped_viewport;
       
  2386     return d->viewport;
       
  2387 }
       
  2388 
       
  2389 /*!
       
  2390     Returns the clipper widget. Contents in the scrollview are
       
  2391     ultimately clipped to be inside the clipper widget.
       
  2392 
       
  2393     You should not need to use this function.
       
  2394 
       
  2395     \sa visibleWidth(), visibleHeight()
       
  2396 */
       
  2397 QWidget* Q3ScrollView::clipper() const
       
  2398 {
       
  2399     return d->viewport;
       
  2400 }
       
  2401 
       
  2402 /*!
       
  2403     \property Q3ScrollView::visibleWidth
       
  2404     \brief the horizontal amount of the content that is visible
       
  2405 */
       
  2406 int Q3ScrollView::visibleWidth() const
       
  2407 {
       
  2408     return clipper()->width();
       
  2409 }
       
  2410 
       
  2411 /*!
       
  2412     \property Q3ScrollView::visibleHeight
       
  2413     \brief the vertical amount of the content that is visible
       
  2414 */
       
  2415 int Q3ScrollView::visibleHeight() const
       
  2416 {
       
  2417     return clipper()->height();
       
  2418 }
       
  2419 
       
  2420 
       
  2421 void Q3ScrollView::changeFrameRect(const QRect& r)
       
  2422 {
       
  2423     QRect oldr = frameRect();
       
  2424     if (oldr != r) {
       
  2425         QRect cr = contentsRect();
       
  2426         QRegion fr(frameRect());
       
  2427         fr = fr.subtracted(contentsRect());
       
  2428         setFrameRect(r);
       
  2429         if (isVisible()) {
       
  2430             cr = cr.intersected(contentsRect());
       
  2431             fr = fr.united(frameRect());
       
  2432             fr = fr.subtracted(cr);
       
  2433             if (!fr.isEmpty())
       
  2434                 update(fr);
       
  2435         }
       
  2436     }
       
  2437 }
       
  2438 
       
  2439 
       
  2440 /*!
       
  2441     Sets the margins around the scrolling area to \a left, \a top, \a
       
  2442     right and \a bottom. This is useful for applications such as
       
  2443     spreadsheets with "locked" rows and columns. The marginal space is
       
  2444     \e inside the frameRect() and is left blank; reimplement
       
  2445     drawFrame() or put widgets in the unused area.
       
  2446 
       
  2447     By default all margins are zero.
       
  2448 
       
  2449     \sa frameChanged()
       
  2450 */
       
  2451 void Q3ScrollView::setMargins(int left, int top, int right, int bottom)
       
  2452 {
       
  2453     if (left == d->l_marg &&
       
  2454          top == d->t_marg &&
       
  2455          right == d->r_marg &&
       
  2456          bottom == d->b_marg)
       
  2457         return;
       
  2458 
       
  2459     d->l_marg = left;
       
  2460     d->t_marg = top;
       
  2461     d->r_marg = right;
       
  2462     d->b_marg = bottom;
       
  2463     updateScrollBars();
       
  2464 }
       
  2465 
       
  2466 
       
  2467 /*!
       
  2468     Returns the left margin.
       
  2469 
       
  2470     \sa setMargins()
       
  2471 */
       
  2472 int Q3ScrollView::leftMargin() const
       
  2473 {
       
  2474     return d->l_marg;
       
  2475 }
       
  2476 
       
  2477 
       
  2478 /*!
       
  2479     Returns the top margin.
       
  2480 
       
  2481     \sa setMargins()
       
  2482 */
       
  2483 int Q3ScrollView::topMargin() const
       
  2484 {
       
  2485     return d->t_marg;
       
  2486 }
       
  2487 
       
  2488 
       
  2489 /*!
       
  2490     Returns the right margin.
       
  2491 
       
  2492     \sa setMargins()
       
  2493 */
       
  2494 int Q3ScrollView::rightMargin() const
       
  2495 {
       
  2496     return d->r_marg;
       
  2497 }
       
  2498 
       
  2499 
       
  2500 /*!
       
  2501     Returns the bottom margin.
       
  2502 
       
  2503     \sa setMargins()
       
  2504 */
       
  2505 int Q3ScrollView::bottomMargin() const
       
  2506 {
       
  2507     return d->b_marg;
       
  2508 }
       
  2509 
       
  2510 /*!
       
  2511     \reimp
       
  2512 */
       
  2513 bool Q3ScrollView::focusNextPrevChild(bool next)
       
  2514 {
       
  2515     //  Makes sure that the new focus widget is on-screen, if
       
  2516     //  necessary by scrolling the scroll view.
       
  2517     bool retval = Q3Frame::focusNextPrevChild(next);
       
  2518     if (retval) {
       
  2519         QWidget *w = window()->focusWidget();
       
  2520         if (isAncestorOf(w)) {
       
  2521             QSVChildRec *r = d->ancestorRec(w);
       
  2522            if (r && (r->child == w || w->isVisibleTo(r->child))) {
       
  2523                 QPoint cp = r->child->mapToGlobal(QPoint(0, 0));
       
  2524                 QPoint cr = w->mapToGlobal(QPoint(0, 0)) - cp;
       
  2525                 ensureVisible(r->x + cr.x() + w->width()/2, r->y + cr.y() + w->height()/2,
       
  2526                               w->width()/2, w->height()/2);
       
  2527             }
       
  2528         }
       
  2529     }
       
  2530     return retval;
       
  2531 }
       
  2532 
       
  2533 
       
  2534 
       
  2535 /*!
       
  2536     When a large numbers of child widgets are in a scrollview,
       
  2537     especially if they are close together, the scrolling performance
       
  2538     can suffer greatly. If \a y is true the scrollview will use an
       
  2539     extra widget to group child widgets.
       
  2540 
       
  2541     Note that you may only call enableClipper() prior to adding
       
  2542     widgets.
       
  2543 */
       
  2544 void Q3ScrollView::enableClipper(bool y)
       
  2545 {
       
  2546     if (!d->clipped_viewport == !y)
       
  2547         return;
       
  2548     if (d->children.count())
       
  2549         qFatal("May only call Q3ScrollView::enableClipper() before adding widgets");
       
  2550     if (y) {
       
  2551         d->clipped_viewport = new QClipperWidget(clipper(), "qt_clipped_viewport", QFlag(d->flags));
       
  2552         d->clipped_viewport->setGeometry(-coord_limit/2,-coord_limit/2,
       
  2553                                          coord_limit,coord_limit);
       
  2554         d->clipped_viewport->setBackgroundMode(d->viewport->backgroundMode());
       
  2555         d->viewport->setBackgroundMode(NoBackground); // no exposures for this
       
  2556         d->viewport->removeEventFilter(this);
       
  2557         d->clipped_viewport->installEventFilter(this);
       
  2558         d->clipped_viewport->show();
       
  2559     } else {
       
  2560         delete d->clipped_viewport;
       
  2561         d->clipped_viewport = 0;
       
  2562     }
       
  2563 }
       
  2564 
       
  2565 /*!
       
  2566     Sets the scrollview to have a static background if \a y is true,
       
  2567     or a scrolling background if \a y is false. By default, the
       
  2568     background is scrolling.
       
  2569 
       
  2570     Be aware that this mode is quite slow, as a full repaint of the
       
  2571     visible area has to be triggered on every contents move.
       
  2572 
       
  2573     \sa hasStaticBackground()
       
  2574 */
       
  2575 void  Q3ScrollView::setStaticBackground(bool y)
       
  2576 {
       
  2577     d->static_bg = y;
       
  2578 }
       
  2579 
       
  2580 /*!
       
  2581     Returns true if Q3ScrollView uses a static background; otherwise
       
  2582     returns false.
       
  2583 
       
  2584     \sa setStaticBackground()
       
  2585 */
       
  2586 bool Q3ScrollView::hasStaticBackground() const
       
  2587 {
       
  2588     return d->static_bg;
       
  2589 }
       
  2590 
       
  2591 /*!
       
  2592     \overload
       
  2593 
       
  2594     Returns the point \a p translated to a point on the viewport()
       
  2595     widget.
       
  2596 */
       
  2597 QPoint Q3ScrollView::contentsToViewport(const QPoint& p) const
       
  2598 {
       
  2599     if (d->clipped_viewport) {
       
  2600         return QPoint(p.x() - d->contentsX() - d->clipped_viewport->x(),
       
  2601                        p.y() - d->contentsY() - d->clipped_viewport->y());
       
  2602     } else {
       
  2603         return QPoint(p.x() - d->contentsX(),
       
  2604                        p.y() - d->contentsY());
       
  2605     }
       
  2606 }
       
  2607 
       
  2608 /*!
       
  2609     \overload
       
  2610 
       
  2611     Returns the point on the viewport \a vp translated to a point in
       
  2612     the contents.
       
  2613 */
       
  2614 QPoint Q3ScrollView::viewportToContents(const QPoint& vp) const
       
  2615 {
       
  2616     if (d->clipped_viewport) {
       
  2617         return QPoint(vp.x() + d->contentsX() + d->clipped_viewport->x(),
       
  2618                        vp.y() + d->contentsY() + d->clipped_viewport->y());
       
  2619     } else {
       
  2620         return QPoint(vp.x() + d->contentsX(),
       
  2621                        vp.y() + d->contentsY());
       
  2622     }
       
  2623 }
       
  2624 
       
  2625 
       
  2626 /*!
       
  2627     Translates a point (\a x, \a y) in the contents to a point (\a vx,
       
  2628     \a vy) on the viewport() widget.
       
  2629 */
       
  2630 void Q3ScrollView::contentsToViewport(int x, int y, int& vx, int& vy) const
       
  2631 {
       
  2632     const QPoint v = contentsToViewport(QPoint(x,y));
       
  2633     vx = v.x();
       
  2634     vy = v.y();
       
  2635 }
       
  2636 
       
  2637 /*!
       
  2638     Translates a point (\a vx, \a vy) on the viewport() widget to a
       
  2639     point (\a x, \a y) in the contents.
       
  2640 */
       
  2641 void Q3ScrollView::viewportToContents(int vx, int vy, int& x, int& y) const
       
  2642 {
       
  2643     const QPoint c = viewportToContents(QPoint(vx,vy));
       
  2644     x = c.x();
       
  2645     y = c.y();
       
  2646 }
       
  2647 
       
  2648 /*!
       
  2649     \reimp
       
  2650 */
       
  2651 QSize Q3ScrollView::sizeHint() const
       
  2652 {
       
  2653     if (d->use_cached_size_hint && d->cachedSizeHint.isValid())
       
  2654         return d->cachedSizeHint;
       
  2655 
       
  2656     constPolish();
       
  2657     int f = 2 * frameWidth();
       
  2658     int h = fontMetrics().height();
       
  2659     QSize sz(f, f);
       
  2660     if (d->policy > Manual) {
       
  2661         QSVChildRec *r = d->children.first();
       
  2662         if (r) {
       
  2663             QSize cs = r->child->sizeHint();
       
  2664             if (cs.isValid())
       
  2665                 sz += cs.boundedTo(r->child->maximumSize());
       
  2666             else
       
  2667                 sz += r->child->size();
       
  2668         }
       
  2669     } else {
       
  2670         sz += QSize(d->contentsWidth(), contentsHeight());
       
  2671     }
       
  2672     if (d->vMode == AlwaysOn)
       
  2673         sz.setWidth(sz.width() + d->vbar->sizeHint().width());
       
  2674     if (d->hMode == AlwaysOn)
       
  2675         sz.setHeight(sz.height() + d->hbar->sizeHint().height());
       
  2676     return sz.expandedTo(QSize(12 * h, 8 * h))
       
  2677              .boundedTo(QSize(36 * h, 24 * h));
       
  2678 }
       
  2679 
       
  2680 
       
  2681 /*!
       
  2682     \reimp
       
  2683 */
       
  2684 QSize Q3ScrollView::minimumSizeHint() const
       
  2685 {
       
  2686     int h = fontMetrics().height();
       
  2687     if (h < 10)
       
  2688         h = 10;
       
  2689     int f = 2 * frameWidth();
       
  2690     return QSize((6 * h) + f, (4 * h) + f);
       
  2691 }
       
  2692 
       
  2693 
       
  2694 /*!
       
  2695     \reimp
       
  2696 
       
  2697     (Implemented to get rid of a compiler warning.)
       
  2698 */
       
  2699 void Q3ScrollView::drawContents(QPainter *)
       
  2700 {
       
  2701 }
       
  2702 
       
  2703 #ifndef QT_NO_DRAGANDDROP
       
  2704 
       
  2705 /*!
       
  2706   \internal
       
  2707 */
       
  2708 void Q3ScrollView::startDragAutoScroll()
       
  2709 {
       
  2710     if (!d->autoscroll_timer.isActive()) {
       
  2711         d->autoscroll_time = initialScrollTime;
       
  2712         d->autoscroll_accel = initialScrollAccel;
       
  2713         d->autoscroll_timer.start(d->autoscroll_time);
       
  2714     }
       
  2715 }
       
  2716 
       
  2717 
       
  2718 /*!
       
  2719   \internal
       
  2720 */
       
  2721 void Q3ScrollView::stopDragAutoScroll()
       
  2722 {
       
  2723     d->autoscroll_timer.stop();
       
  2724 }
       
  2725 
       
  2726 
       
  2727 /*!
       
  2728   \internal
       
  2729 */
       
  2730 void Q3ScrollView::doDragAutoScroll()
       
  2731 {
       
  2732     QPoint p = d->viewport->mapFromGlobal(QCursor::pos());
       
  2733 
       
  2734     if (d->autoscroll_accel-- <= 0 && d->autoscroll_time) {
       
  2735         d->autoscroll_accel = initialScrollAccel;
       
  2736         d->autoscroll_time--;
       
  2737         d->autoscroll_timer.start(d->autoscroll_time);
       
  2738     }
       
  2739     int l = QMAX(1, (initialScrollTime- d->autoscroll_time));
       
  2740 
       
  2741     int dx = 0, dy = 0;
       
  2742     if (p.y() < autoscroll_margin) {
       
  2743         dy = -l;
       
  2744     } else if (p.y() > visibleHeight() - autoscroll_margin) {
       
  2745         dy = +l;
       
  2746     }
       
  2747     if (p.x() < autoscroll_margin) {
       
  2748         dx = -l;
       
  2749     } else if (p.x() > visibleWidth() - autoscroll_margin) {
       
  2750         dx = +l;
       
  2751     }
       
  2752     if (dx || dy) {
       
  2753         scrollBy(dx,dy);
       
  2754     } else {
       
  2755         stopDragAutoScroll();
       
  2756     }
       
  2757 }
       
  2758 
       
  2759 
       
  2760 /*!
       
  2761     \property Q3ScrollView::dragAutoScroll
       
  2762     \brief whether autoscrolling in drag move events is enabled
       
  2763 
       
  2764     If this property is set to true (the default), the Q3ScrollView
       
  2765     automatically scrolls the contents in drag move events if the user
       
  2766     moves the cursor close to a border of the view. Of course this
       
  2767     works only if the viewport accepts drops. Specifying false
       
  2768     disables this autoscroll feature.
       
  2769 */
       
  2770 
       
  2771 void Q3ScrollView::setDragAutoScroll(bool b)
       
  2772 {
       
  2773     d->drag_autoscroll = b;
       
  2774 }
       
  2775 
       
  2776 bool Q3ScrollView::dragAutoScroll() const
       
  2777 {
       
  2778     return d->drag_autoscroll;
       
  2779 }
       
  2780 
       
  2781 #endif // QT_NO_DRAGANDDROP
       
  2782 
       
  2783 /*!\internal
       
  2784  */
       
  2785 void Q3ScrollView::setCachedSizeHint(const QSize &sh) const
       
  2786 {
       
  2787     if (isVisible() && !d->cachedSizeHint.isValid())
       
  2788         d->cachedSizeHint = sh;
       
  2789 }
       
  2790 
       
  2791 /*!\internal
       
  2792  */
       
  2793 void Q3ScrollView::disableSizeHintCaching()
       
  2794 {
       
  2795     d->use_cached_size_hint = false;
       
  2796 }
       
  2797 
       
  2798 /*!\internal
       
  2799  */
       
  2800 QSize Q3ScrollView::cachedSizeHint() const
       
  2801 {
       
  2802     return d->use_cached_size_hint ? d->cachedSizeHint : QSize();
       
  2803 }
       
  2804 
       
  2805 QT_END_NAMESPACE
       
  2806 
       
  2807 #endif // QT_NO_SCROLLVIEW