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