~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/qt3support/widgets/q3scrollview.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

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