File indexing completed on 2024-03-24 05:46:34
0001 /**************************************************************************** 0002 ** 0003 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 0004 ** Contact: http://www.qt-project.org/legal 0005 ** 0006 ** This file is part of the Qt3Support module of the Qt Toolkit. 0007 ** 0008 ** $QT_BEGIN_LICENSE:LGPL$ 0009 ** Commercial License Usage 0010 ** Licensees holding valid commercial Qt licenses may use this file in 0011 ** accordance with the commercial license agreement provided with the 0012 ** Software or, alternatively, in accordance with the terms contained in 0013 ** a written agreement between you and Digia. For licensing terms and 0014 ** conditions see http://qt.digia.com/licensing. For further information 0015 ** use the contact form at http://qt.digia.com/contact-us. 0016 ** 0017 ** GNU Lesser General Public License Usage 0018 ** Alternatively, this file may be used under the terms of the GNU Lesser 0019 ** General Public License version 2.1 as published by the Free Software 0020 ** Foundation and appearing in the file LICENSE.LGPL included in the 0021 ** packaging of this file. Please review the following information to 0022 ** ensure the GNU Lesser General Public License version 2.1 requirements 0023 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 0024 ** 0025 ** In addition, as a special exception, Digia gives you certain additional 0026 ** rights. These rights are described in the Digia Qt LGPL Exception 0027 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 0028 ** 0029 ** GNU General Public License Usage 0030 ** Alternatively, this file may be used under the terms of the GNU 0031 ** General Public License version 3.0 as published by the Free Software 0032 ** Foundation and appearing in the file LICENSE.GPL included in the 0033 ** packaging of this file. Please review the following information to 0034 ** ensure the GNU General Public License version 3.0 requirements will be 0035 ** met: http://www.gnu.org/copyleft/gpl.html. 0036 ** 0037 ** 0038 ** $QT_END_LICENSE$ 0039 ** 0040 ****************************************************************************/ 0041 0042 #include "ktlq3scrollview.h" 0043 0044 #include <QCursor> 0045 #include <QPainter> 0046 #include <QPixmap> 0047 #include <QScrollBar> 0048 #include <QWidget> 0049 // #include "q3ptrdict.h" 0050 #include <QApplication> 0051 #include <QHash> 0052 #include <QStyle> 0053 #include <QTimer> 0054 // #include "q3ptrlist.h" 0055 #include <QContextMenuEvent> 0056 #include <QDragEnterEvent> 0057 #include <QDragLeaveEvent> 0058 //#include "q3listview.h" 0059 // #ifdef Q_WS_MAC // 2018.10.18 - do not depend on internal headers 0060 // # include "private/qt_mac_p.h" 0061 // #endif 0062 0063 // QT_BEGIN_NAMESPACE 0064 0065 // using namespace Qt; 0066 0067 static const int coord_limit = 4000; 0068 static const int autoscroll_margin = 16; 0069 static const int initialScrollTime = 30; 0070 static const int initialScrollAccel = 5; 0071 0072 struct QSVChildRec { 0073 QSVChildRec(QWidget *c, int xx, int yy) 0074 : child(c) 0075 , x(xx) 0076 , y(yy) 0077 { 0078 } 0079 0080 void hideOrShow(KtlQ3ScrollView *sv, QWidget *clipped_viewport); 0081 void moveTo(KtlQ3ScrollView *sv, int xx, int yy, QWidget *clipped_viewport) 0082 { 0083 if (x != xx || y != yy) { 0084 x = xx; 0085 y = yy; 0086 hideOrShow(sv, clipped_viewport); 0087 } 0088 } 0089 QWidget *child; 0090 int x, y; 0091 }; 0092 0093 void QSVChildRec::hideOrShow(KtlQ3ScrollView *sv, QWidget *clipped_viewport) 0094 { 0095 if (clipped_viewport) { 0096 if (x + child->width() < sv->contentsX() + clipped_viewport->x() || x > sv->contentsX() + clipped_viewport->width() || y + child->height() < sv->contentsY() + clipped_viewport->y() || 0097 y > sv->contentsY() + clipped_viewport->height()) { 0098 child->move(clipped_viewport->width(), clipped_viewport->height()); 0099 } else { 0100 child->move(x - sv->contentsX() - clipped_viewport->x(), y - sv->contentsY() - clipped_viewport->y()); 0101 } 0102 } else { 0103 child->move(x - sv->contentsX(), y - sv->contentsY()); 0104 } 0105 } 0106 0107 // QT_BEGIN_INCLUDE_NAMESPACE 0108 0109 // QT_END_INCLUDE_NAMESPACE 0110 0111 class KtlQ3ScrollViewData 0112 { 0113 public: 0114 KtlQ3ScrollViewData(KtlQ3ScrollView *parent, int vpwflags) 0115 : hbar(new QScrollBar(Qt::Horizontal, parent /*, "qt_hbar"*/)) 0116 , vbar(new QScrollBar(Qt::Vertical, parent /*, "qt_vbar" */)) 0117 , viewport(new KtlQAbstractScrollAreaWidget(parent, "qt_viewport", QFlag(vpwflags))) 0118 , clipped_viewport(nullptr) 0119 , flags(vpwflags) 0120 , vx(0) 0121 , vy(0) 0122 , vwidth(1) 0123 , vheight(1) 0124 , 0125 #ifndef QT_NO_DRAGANDDROP 0126 autoscroll_timer(parent /* , "scrollview autoscroll timer" */) 0127 , drag_autoscroll(true) 0128 , 0129 #endif 0130 scrollbar_timer(parent /*, "scrollview scrollbar timer" */) 0131 , inresize(false) 0132 , use_cached_size_hint(true) 0133 { 0134 hbar->setObjectName("qt_hbar"); 0135 vbar->setObjectName("qt_vbar"); 0136 #ifndef QT_NO_DRAGANDDROP 0137 autoscroll_timer.setObjectName("scrollview autoscroll timer"); 0138 #endif 0139 scrollbar_timer.setObjectName("scrollview scrollbar timer"); 0140 l_marg = r_marg = t_marg = b_marg = 0; 0141 viewport->ensurePolished(); 0142 vMode = KtlQ3ScrollView::Auto; 0143 hMode = KtlQ3ScrollView::Auto; 0144 corner = nullptr; 0145 // vbar->setSteps(20, 1/*set later*/); 0146 vbar->setSingleStep(20); 0147 vbar->setPageStep(1); 0148 // hbar->setSteps(20, 1/*set later*/); 0149 hbar->setSingleStep(20); 0150 hbar->setPageStep(1); 0151 policy = KtlQ3ScrollView::Default; 0152 signal_choke = false; 0153 static_bg = false; 0154 fake_scroll = false; 0155 hbarPressed = false; 0156 vbarPressed = false; 0157 hbar->setLayoutDirection(Qt::LeftToRight); 0158 } 0159 ~KtlQ3ScrollViewData(); 0160 0161 QSVChildRec *rec(QWidget *w) 0162 { 0163 return /* childDict.find(w); */ childDict.value(w); 0164 } 0165 QSVChildRec *ancestorRec(QWidget *w); 0166 QSVChildRec *addChildRec(QWidget *w, int x, int y) 0167 { 0168 QSVChildRec *r = new QSVChildRec(w, x, y); 0169 children.append(r); 0170 childDict.insert(w, r); 0171 return r; 0172 } 0173 void deleteChildRec(QSVChildRec *r) 0174 { 0175 childDict.remove(r->child); 0176 // children.removeRef(r); 0177 children.removeAll(r); 0178 delete r; 0179 } 0180 0181 void hideOrShowAll(KtlQ3ScrollView *sv, bool isScroll = false); 0182 void moveAllBy(int dx, int dy); 0183 bool anyVisibleChildren(); 0184 void autoMove(KtlQ3ScrollView *sv); 0185 void autoResize(KtlQ3ScrollView *sv); 0186 void autoResizeHint(KtlQ3ScrollView *sv); 0187 void viewportResized(int w, int h); 0188 0189 QScrollBar *hbar; 0190 QScrollBar *vbar; 0191 bool hbarPressed; 0192 bool vbarPressed; 0193 KtlQAbstractScrollAreaWidget *viewport; 0194 KtlQClipperWidget *clipped_viewport; 0195 int flags; 0196 // Q3PtrList<QSVChildRec> children; 0197 QList<QSVChildRec *> children; 0198 // Q3PtrDict<QSVChildRec> childDict; // 2018.10.07 0199 QHash<QWidget *, QSVChildRec *> childDict; 0200 QWidget *corner; 0201 int vx, vy, vwidth, vheight; // for drawContents-style usage 0202 int l_marg, r_marg, t_marg, b_marg; 0203 KtlQ3ScrollView::ResizePolicy policy; 0204 KtlQ3ScrollView::ScrollBarMode vMode; 0205 KtlQ3ScrollView::ScrollBarMode hMode; 0206 #ifndef QT_NO_DRAGANDDROP 0207 QPoint cpDragStart; 0208 QTimer autoscroll_timer; 0209 int autoscroll_time; 0210 int autoscroll_accel; 0211 bool drag_autoscroll; 0212 #endif 0213 QTimer scrollbar_timer; 0214 0215 uint static_bg : 1; 0216 uint fake_scroll : 1; 0217 0218 // This variable allows ensureVisible to move the contents then 0219 // update both the sliders. Otherwise, updating the sliders would 0220 // cause two image scrolls, creating ugly flashing. 0221 // 0222 uint signal_choke : 1; 0223 0224 // This variables indicates in updateScrollBars() that we are 0225 // in a resizeEvent() and thus don't want to flash scroll bars 0226 uint inresize : 1; 0227 uint use_cached_size_hint : 1; 0228 QSize cachedSizeHint; 0229 0230 inline int contentsX() const 0231 { 0232 return -vx; 0233 } 0234 inline int contentsY() const 0235 { 0236 return -vy; 0237 } 0238 inline int contentsWidth() const 0239 { 0240 return vwidth; 0241 } 0242 }; 0243 0244 inline KtlQ3ScrollViewData::~KtlQ3ScrollViewData() 0245 { 0246 // children.setAutoDelete(true); // 2018.12.08 0247 for (QList<QSVChildRec *>::iterator it = children.begin(); it != children.end(); ++it) { 0248 QSVChildRec *r = *it; 0249 delete r; 0250 } 0251 children.removeAll(nullptr); 0252 } 0253 0254 QSVChildRec *KtlQ3ScrollViewData::ancestorRec(QWidget *w) 0255 { 0256 if (clipped_viewport) { 0257 while (w->parentWidget() != clipped_viewport) { 0258 w = w->parentWidget(); 0259 if (!w) 0260 return nullptr; 0261 } 0262 } else { 0263 while (w->parentWidget() != viewport) { 0264 w = w->parentWidget(); 0265 if (!w) 0266 return nullptr; 0267 } 0268 } 0269 return rec(w); 0270 } 0271 0272 void KtlQ3ScrollViewData::hideOrShowAll(KtlQ3ScrollView *sv, bool isScroll) 0273 { 0274 if (!clipped_viewport) 0275 return; 0276 if (clipped_viewport->x() <= 0 && clipped_viewport->y() <= 0 && clipped_viewport->width() + clipped_viewport->x() >= viewport->width() && clipped_viewport->height() + clipped_viewport->y() >= viewport->height()) { 0277 // clipped_viewport still covers viewport 0278 if (static_bg) { 0279 // clipped_viewport->repaint(true); // 2018.11.30 0280 clipped_viewport->repaint(); 0281 } else if ((!isScroll && !clipped_viewport->testAttribute(Qt::WA_StaticContents)) || static_bg) 0282 clipped_viewport->update(); 0283 } else { 0284 // Re-center 0285 int nx = (viewport->width() - clipped_viewport->width()) / 2; 0286 int ny = (viewport->height() - clipped_viewport->height()) / 2; 0287 clipped_viewport->move(nx, ny); 0288 clipped_viewport->update(); 0289 } 0290 // for (QSVChildRec *r = children.first(); r; r=children.next()) { // 2018.12.08 0291 // r->hideOrShow(sv, clipped_viewport); 0292 //} 0293 for (QList<QSVChildRec *>::iterator it = children.begin(); it != children.end(); ++it) { 0294 QSVChildRec *r = *it; 0295 r->hideOrShow(sv, clipped_viewport); 0296 } 0297 } 0298 0299 void KtlQ3ScrollViewData::moveAllBy(int dx, int dy) 0300 { 0301 if (clipped_viewport && !static_bg) { 0302 clipped_viewport->move(clipped_viewport->x() + dx, clipped_viewport->y() + dy); 0303 } else { 0304 // for (QSVChildRec *r = children.first(); r; r=children.next()) { // 2018.12.07 0305 // r->child->move(r->child->x()+dx,r->child->y()+dy); 0306 //} 0307 for (QList<QSVChildRec *>::iterator it = children.begin(); it != children.end(); ++it) { 0308 QSVChildRec *r = *it; 0309 r->child->move(r->child->x() + dx, r->child->y() + dy); 0310 } 0311 0312 if (static_bg) { 0313 // viewport->repaint(true); // 2018.11.30 0314 viewport->repaint(); 0315 } 0316 } 0317 } 0318 0319 bool KtlQ3ScrollViewData::anyVisibleChildren() 0320 { 0321 // for (QSVChildRec *r = children.first(); r; r=children.next()) { // 2018.12.08 0322 // if (r->child->isVisible()) return true; 0323 //} 0324 for (QList<QSVChildRec *>::iterator it = children.begin(); it != children.end(); ++it) { 0325 QSVChildRec *r = *it; 0326 if (r->child->isVisible()) 0327 return true; 0328 } 0329 return false; 0330 } 0331 0332 void KtlQ3ScrollViewData::autoMove(KtlQ3ScrollView *sv) 0333 { 0334 if (policy == KtlQ3ScrollView::AutoOne) { 0335 QSVChildRec *r = children.first(); 0336 if (r) 0337 sv->setContentsPos(-r->child->x(), -r->child->y()); 0338 } 0339 } 0340 0341 void KtlQ3ScrollViewData::autoResize(KtlQ3ScrollView *sv) 0342 { 0343 if (policy == KtlQ3ScrollView::AutoOne) { 0344 QSVChildRec *r = children.first(); 0345 if (r) 0346 sv->resizeContents(r->child->width(), r->child->height()); 0347 } 0348 } 0349 0350 void KtlQ3ScrollViewData::autoResizeHint(KtlQ3ScrollView *sv) 0351 { 0352 if (policy == KtlQ3ScrollView::AutoOne) { 0353 QSVChildRec *r = children.first(); 0354 if (r) { 0355 QSize s = r->child->sizeHint(); 0356 if (s.isValid()) 0357 r->child->resize(s); 0358 } 0359 } else if (policy == KtlQ3ScrollView::AutoOneFit) { 0360 QSVChildRec *r = children.first(); 0361 if (r) { 0362 QSize sh = r->child->sizeHint(); 0363 sh = sh.boundedTo(r->child->maximumSize()); 0364 sv->resizeContents(sh.width(), sh.height()); 0365 } 0366 } 0367 } 0368 0369 void KtlQ3ScrollViewData::viewportResized(int w, int h) 0370 { 0371 if (policy == KtlQ3ScrollView::AutoOneFit) { 0372 QSVChildRec *r = children.first(); 0373 if (r) { 0374 QSize sh = r->child->sizeHint(); 0375 sh = sh.boundedTo(r->child->maximumSize()); 0376 r->child->resize(qMax(w, sh.width()), qMax(h, sh.height())); 0377 } 0378 } 0379 } 0380 0381 /*! 0382 \class KtlQ3ScrollView 0383 \brief The KtlQ3ScrollView widget provides a scrolling area with on-demand scroll bars. 0384 0385 \compat 0386 0387 The KtlQ3ScrollView is a large canvas - potentially larger than the 0388 coordinate system normally supported by the underlying window 0389 system. This is important because it is quite easy to go beyond 0390 these limitations (e.g. many web pages are more than 32000 pixels 0391 high). Additionally, the KtlQ3ScrollView can have QWidgets positioned 0392 on it that scroll around with the drawn content. These sub-widgets 0393 can also have positions outside the normal coordinate range (but 0394 they are still limited in size). 0395 0396 To provide content for the widget, inherit from KtlQ3ScrollView, 0397 reimplement drawContents() and use resizeContents() to set the 0398 size of the viewed area. Use addChild() and moveChild() to 0399 position widgets on the view. 0400 0401 To use KtlQ3ScrollView effectively it is important to understand its 0402 widget structure in the three styles of use: a single large child 0403 widget, a large panning area with some widgets and a large panning 0404 area with many widgets. 0405 0406 \section1 Using One Big Widget 0407 0408 \img qscrollview-vp2.png 0409 0410 The first, simplest usage of KtlQ3ScrollView (depicted above), is 0411 appropriate for scrolling areas that are never more than about 0412 4000 pixels in either dimension (this is about the maximum 0413 reliable size on X11 servers). In this usage, you just make one 0414 large child in the KtlQ3ScrollView. The child should be a child of the 0415 viewport() of the scrollview and be added with addChild(): 0416 \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 0 0417 You can go on to add arbitrary child widgets to the single child 0418 in the scrollview as you would with any widget: 0419 \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 1 0420 0421 Here the KtlQ3ScrollView has four children: the viewport(), the 0422 verticalScrollBar(), the horizontalScrollBar() and a small 0423 cornerWidget(). The viewport() has one child: the QWidget. The 0424 QWidget has the three QLabel objects as child widgets. When the view 0425 is scrolled, the QWidget is moved; its children move with it as 0426 child widgets normally do. 0427 0428 \section1 Using a Very Big View with Some Widgets 0429 0430 \img qscrollview-vp.png 0431 0432 The second usage of KtlQ3ScrollView (depicted above) is appropriate 0433 when few, if any, widgets are on a very large scrolling area that 0434 is potentially larger than 4000 pixels in either dimension. In 0435 this usage you call resizeContents() to set the size of the area 0436 and reimplement drawContents() to paint the contents. You may also 0437 add some widgets by making them children of the viewport() and 0438 adding them with addChild() (this is the same as the process for 0439 the single large widget in the previous example): 0440 \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 2 0441 Here, the KtlQ3ScrollView has the same four children: the viewport(), 0442 the verticalScrollBar(), the horizontalScrollBar() and a small 0443 cornerWidget(). The viewport() has the three QLabel objects as 0444 child widgets. When the view is scrolled, the scrollview moves the 0445 child widgets individually. 0446 0447 \section1 Using a Very Big View with Many Widgets 0448 0449 \img qscrollview-cl.png 0450 0451 The final usage of KtlQ3ScrollView (depicted above) is appropriate 0452 when many widgets are on a very large scrolling area that is 0453 potentially larger than 4000 pixels in either dimension. In this 0454 usage you call resizeContents() to set the size of the area and 0455 reimplement drawContents() to paint the contents. You then call 0456 enableClipper(true) and add widgets, again by making them children 0457 of the viewport(), and adding them with addChild(): 0458 \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 3 0459 0460 Here, the KtlQ3ScrollView has four children: the clipper() (not the 0461 viewport() this time), the verticalScrollBar(), the 0462 horizontalScrollBar() and a small cornerWidget(). The clipper() 0463 has one child: the viewport(). The viewport() has the same three 0464 labels as child widgets. When the view is scrolled the viewport() 0465 is moved; its children move with it as child widgets normally do. 0466 0467 \target allviews 0468 \section1 Details Relevant for All Views 0469 0470 Normally you will use the first or third method if you want any 0471 child widgets in the view. 0472 0473 Note that the widget you see in the scrolled area is the 0474 viewport() widget, not the KtlQ3ScrollView itself. So to turn mouse 0475 tracking on, for example, use viewport()->setMouseTracking(true). 0476 0477 To enable drag-and-drop, you would setAcceptDrops(true) on the 0478 KtlQ3ScrollView (because drag-and-drop events propagate to the 0479 parent). But to work out the logical position in the view, you 0480 would need to map the drop co-ordinate from being relative to the 0481 KtlQ3ScrollView to being relative to the contents; use the function 0482 viewportToContents() for this. 0483 0484 To handle mouse events on the scrolling area, subclass scrollview 0485 as you would subclass other widgets, but rather than 0486 reimplementing mousePressEvent(), reimplement 0487 contentsMousePressEvent() instead. The contents specific event 0488 handlers provide translated events in the coordinate system of the 0489 scrollview. If you reimplement mousePressEvent(), you'll get 0490 called only when part of the KtlQ3ScrollView is clicked: and the only 0491 such part is the "corner" (if you don't set a cornerWidget()) and 0492 the frame; everything else is covered up by the viewport, clipper 0493 or scroll bars. 0494 0495 When you construct a KtlQ3ScrollView, some of the window flags apply 0496 to the viewport() instead of being sent to the QWidget constructor 0497 for the KtlQ3ScrollView. 0498 0499 \list 0500 0501 \i An image-manipulation widget would use \c 0502 WNoAutoErase|WStaticContents because the widget draws all pixels 0503 itself, and when its size increases, it only needs a paint event 0504 for the new part because the old part remains unchanged. 0505 0506 \i A scrolling game widget in which the background scrolls as the 0507 characters move might use \c WNoAutoErase (in addition to \c 0508 WStaticContents) so that the window system background does not 0509 flash in and out during scrolling. 0510 0511 \i A word processing widget might use \c WNoAutoErase and repaint 0512 itself line by line to get a less-flickery resizing. If the widget 0513 is in a mode in which no text justification can take place, it 0514 might use \c WStaticContents too, so that it would only get a 0515 repaint for the newly visible parts. 0516 0517 \endlist 0518 0519 Child widgets may be moved using addChild() or moveChild(). Use 0520 childX() and childY() to get the position of a child widget. 0521 0522 A widget may be placed in the corner between the vertical and 0523 horizontal scroll bars with setCornerWidget(). You can get access 0524 to the scroll bars using horizontalScrollBar() and 0525 verticalScrollBar(), and to the viewport with viewport(). The 0526 scroll view can be scrolled using scrollBy(), ensureVisible(), 0527 setContentsPos() or center(). 0528 0529 The visible area is given by visibleWidth() and visibleHeight(), 0530 and the contents area by contentsWidth() and contentsHeight(). The 0531 contents may be repainted using one of the repaintContents() or 0532 updateContents() functions. 0533 0534 Coordinate conversion is provided by contentsToViewport() and 0535 viewportToContents(). 0536 0537 The contentsMoving() signal is emitted just before the contents 0538 are moved to a new position. 0539 0540 \warning KtlQ3ScrollView currently does not erase the background when 0541 resized, i.e. you must always clear the background manually in 0542 scrollview subclasses. This will change in a future version of Qt 0543 and we recommend specifying the \c WNoAutoErase flag explicitly. 0544 */ 0545 0546 /*! 0547 \enum KtlQ3ScrollView::ResizePolicy 0548 0549 This enum type is used to control a KtlQ3ScrollView's reaction to 0550 resize events. 0551 0552 \value Default the KtlQ3ScrollView selects one of the other settings 0553 automatically when it has to. In this version of Qt, KtlQ3ScrollView 0554 changes to \c Manual if you resize the contents with 0555 resizeContents() and to \c AutoOne if a child is added. 0556 0557 \value Manual the contents stays the size set by resizeContents(). 0558 0559 \value AutoOne if there is only one child widget the contents stays 0560 the size of that widget. Otherwise the behavior is undefined. 0561 0562 \value AutoOneFit if there is only one child widget the contents stays 0563 the size of that widget's sizeHint(). If the scrollview is resized 0564 larger than the child's sizeHint(), the child will be resized to 0565 fit. If there is more than one child, the behavior is undefined. 0566 0567 */ 0568 //#### The widget will be resized to its sizeHint() when a LayoutHint event 0569 //#### is received 0570 0571 /*! 0572 Constructs a KtlQ3ScrollView called \a name with parent \a parent and 0573 widget flags \a f. 0574 0575 The widget flags \c WStaticContents, \c WNoAutoErase and \c 0576 WPaintClever are propagated to the viewport() widget. The other 0577 widget flags are propagated to the parent constructor as usual. 0578 */ 0579 0580 KtlQ3ScrollView::KtlQ3ScrollView(QWidget *parent, const char *name, Qt::WindowFlags f) 0581 : KtlQ3Frame(parent, name, f & (~Qt::WA_StaticContents) /*& (~Qt::WNoAutoErase) & (~Qt::WResizeNoErase) */) 0582 { 0583 Qt::WindowFlags flags = /* Qt::WResizeNoErase | (f&Qt::WPaintClever) 0584 | (f&Qt::WRepaintNoErase) | */ 0585 (f & Qt::WA_StaticContents); 0586 d = new KtlQ3ScrollViewData(this, flags); 0587 0588 #ifndef QT_NO_DRAGANDDROP 0589 connect(&d->autoscroll_timer, SIGNAL(timeout()), this, SLOT(doDragAutoScroll())); 0590 #endif 0591 0592 connect(d->hbar, SIGNAL(valueChanged(int)), this, SLOT(hslide(int))); 0593 connect(d->vbar, SIGNAL(valueChanged(int)), this, SLOT(vslide(int))); 0594 0595 connect(d->hbar, SIGNAL(sliderPressed()), this, SLOT(hbarIsPressed())); 0596 connect(d->hbar, SIGNAL(sliderReleased()), this, SLOT(hbarIsReleased())); 0597 connect(d->vbar, SIGNAL(sliderPressed()), this, SLOT(vbarIsPressed())); 0598 connect(d->vbar, SIGNAL(sliderReleased()), this, SLOT(vbarIsReleased())); 0599 0600 d->viewport->installEventFilter(this); 0601 0602 connect(&d->scrollbar_timer, SIGNAL(timeout()), this, SLOT(updateScrollBars())); 0603 0604 setFrameStyle(KtlQ3Frame::StyledPanel | KtlQ3Frame::Sunken); 0605 setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth)); 0606 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); 0607 } 0608 0609 /*! 0610 Destroys the KtlQ3ScrollView. Any children added with addChild() will 0611 be deleted. 0612 */ 0613 KtlQ3ScrollView::~KtlQ3ScrollView() 0614 { 0615 // Be careful not to get all those useless events... 0616 if (d->clipped_viewport) 0617 d->clipped_viewport->removeEventFilter(this); 0618 else 0619 d->viewport->removeEventFilter(this); 0620 0621 // order is important 0622 // ~QWidget may cause a WM_ERASEBKGND on Windows 0623 delete d->vbar; 0624 d->vbar = nullptr; 0625 delete d->hbar; 0626 d->hbar = nullptr; 0627 delete d->viewport; 0628 d->viewport = nullptr; 0629 delete d; 0630 d = nullptr; 0631 } 0632 0633 /*! 0634 \fn void KtlQ3ScrollView::horizontalSliderPressed() 0635 0636 This signal is emitted whenever the user presses the horizontal slider. 0637 */ 0638 /*! 0639 \fn void KtlQ3ScrollView::horizontalSliderReleased() 0640 0641 This signal is emitted whenever the user releases the horizontal slider. 0642 */ 0643 /*! 0644 \fn void KtlQ3ScrollView::verticalSliderPressed() 0645 0646 This signal is emitted whenever the user presses the vertical slider. 0647 */ 0648 /*! 0649 \fn void KtlQ3ScrollView::verticalSliderReleased() 0650 0651 This signal is emitted whenever the user releases the vertical slider. 0652 */ 0653 void KtlQ3ScrollView::hbarIsPressed() 0654 { 0655 d->hbarPressed = true; 0656 emit(horizontalSliderPressed()); 0657 } 0658 0659 void KtlQ3ScrollView::hbarIsReleased() 0660 { 0661 d->hbarPressed = false; 0662 emit(horizontalSliderReleased()); 0663 } 0664 0665 /*! 0666 Returns true if horizontal slider is pressed by user; otherwise returns false. 0667 */ 0668 bool KtlQ3ScrollView::isHorizontalSliderPressed() 0669 { 0670 return d->hbarPressed; 0671 } 0672 0673 void KtlQ3ScrollView::vbarIsPressed() 0674 { 0675 d->vbarPressed = true; 0676 emit(verticalSliderPressed()); 0677 } 0678 0679 void KtlQ3ScrollView::vbarIsReleased() 0680 { 0681 d->vbarPressed = false; 0682 emit(verticalSliderReleased()); 0683 } 0684 0685 /*! 0686 Returns true if vertical slider is pressed by user; otherwise returns false. 0687 */ 0688 bool KtlQ3ScrollView::isVerticalSliderPressed() 0689 { 0690 return d->vbarPressed; 0691 } 0692 0693 /*! 0694 \internal 0695 */ 0696 void KtlQ3ScrollView::styleChange(QStyle &/*old*/) 0697 { 0698 // QWidget::styleChange(old); // 2019.04.14 0699 updateScrollBars(); 0700 d->cachedSizeHint = QSize(); 0701 } 0702 0703 /*! 0704 \internal 0705 */ 0706 void KtlQ3ScrollView::fontChange(const QFont &/*old*/) 0707 { 0708 // QWidget::fontChange(old); // 2019.04.14 0709 updateScrollBars(); 0710 d->cachedSizeHint = QSize(); 0711 } 0712 0713 void KtlQ3ScrollView::hslide(int pos) 0714 { 0715 if (!d->signal_choke) { 0716 moveContents(-pos, -d->contentsY()); 0717 QGuiApplication::sync(); 0718 } 0719 } 0720 0721 void KtlQ3ScrollView::vslide(int pos) 0722 { 0723 if (!d->signal_choke) { 0724 moveContents(-d->contentsX(), -pos); 0725 QGuiApplication::sync(); 0726 } 0727 } 0728 0729 /*! 0730 Called when the horizontal scroll bar geometry changes. This is 0731 provided as a protected function so that subclasses can do 0732 interesting things such as providing extra buttons in some of the 0733 space normally used by the scroll bars. 0734 0735 The default implementation simply gives all the space to \a hbar. 0736 The new geometry is given by \a x, \a y, \a w and \a h. 0737 0738 \sa setVBarGeometry() 0739 */ 0740 void KtlQ3ScrollView::setHBarGeometry(QScrollBar &hbar, int x, int y, int w, int h) 0741 { 0742 hbar.setGeometry(x, y, w, h); 0743 } 0744 0745 /*! 0746 Called when the vertical scroll bar geometry changes. This is 0747 provided as a protected function so that subclasses can do 0748 interesting things such as providing extra buttons in some of the 0749 space normally used by the scroll bars. 0750 0751 The default implementation simply gives all the space to \a vbar. 0752 The new geometry is given by \a x, \a y, \a w and \a h. 0753 0754 \sa setHBarGeometry() 0755 */ 0756 void KtlQ3ScrollView::setVBarGeometry(QScrollBar &vbar, int x, int y, int w, int h) 0757 { 0758 vbar.setGeometry(x, y, w, h); 0759 } 0760 0761 /*! 0762 Returns the viewport size for size (\a x, \a y). 0763 0764 The viewport size depends on (\a x, \a y) (the size of the contents), 0765 the size of this widget and the modes of the horizontal and 0766 vertical scroll bars. 0767 0768 This function permits widgets that can trade vertical and 0769 horizontal space for each other to control scroll bar appearance 0770 better. For example, a word processor or web browser can control 0771 the width of the right margin accurately, whether or not there 0772 needs to be a vertical scroll bar. 0773 */ 0774 0775 QSize KtlQ3ScrollView::viewportSize(int x, int y) const 0776 { 0777 int fw = frameWidth(); 0778 int lmarg = fw + d->l_marg; 0779 int rmarg = fw + d->r_marg; 0780 int tmarg = fw + d->t_marg; 0781 int bmarg = fw + d->b_marg; 0782 0783 int w = width(); 0784 int h = height(); 0785 0786 bool needh, needv; 0787 bool showh, showv; 0788 int hsbExt = horizontalScrollBar()->sizeHint().height(); 0789 int vsbExt = verticalScrollBar()->sizeHint().width(); 0790 0791 if (d->policy != AutoOne || d->anyVisibleChildren()) { 0792 // Do we definitely need the scroll bar? 0793 needh = w - lmarg - rmarg < x; 0794 needv = h - tmarg - bmarg < y; 0795 0796 // Do we intend to show the scroll bar? 0797 if (d->hMode == AlwaysOn) 0798 showh = true; 0799 else if (d->hMode == AlwaysOff) 0800 showh = false; 0801 else 0802 showh = needh; 0803 0804 if (d->vMode == AlwaysOn) 0805 showv = true; 0806 else if (d->vMode == AlwaysOff) 0807 showv = false; 0808 else 0809 showv = needv; 0810 0811 // Given other scroll bar will be shown, NOW do we need one? 0812 if (showh && h - vsbExt - tmarg - bmarg < y) { 0813 if (d->vMode == Auto) 0814 showv = true; 0815 } 0816 if (showv && w - hsbExt - lmarg - rmarg < x) { 0817 if (d->hMode == Auto) 0818 showh = true; 0819 } 0820 } else { 0821 // Scroll bars not needed, only show scroll bar that are always on. 0822 showh = d->hMode == AlwaysOn; 0823 showv = d->vMode == AlwaysOn; 0824 } 0825 0826 return QSize(w - lmarg - rmarg - (showv ? vsbExt : 0), h - tmarg - bmarg - (showh ? hsbExt : 0)); 0827 } 0828 0829 /*! 0830 Updates scroll bars: all possibilities are considered. You should 0831 never need to call this in your code. 0832 */ 0833 void KtlQ3ScrollView::updateScrollBars() 0834 { 0835 if (!horizontalScrollBar() && !verticalScrollBar()) 0836 return; 0837 0838 // I support this should use viewportSize()... but it needs 0839 // so many of the temporary variables from viewportSize. hm. 0840 int fw = frameWidth(); 0841 int lmarg = fw + d->l_marg; 0842 int rmarg = fw + d->r_marg; 0843 int tmarg = fw + d->t_marg; 0844 int bmarg = fw + d->b_marg; 0845 0846 int w = width(); 0847 int h = height(); 0848 0849 int portw, porth; 0850 0851 bool needh; 0852 bool needv; 0853 bool showh; 0854 bool showv; 0855 bool showc = false; 0856 0857 int hsbExt = horizontalScrollBar()->sizeHint().height(); 0858 int vsbExt = verticalScrollBar()->sizeHint().width(); 0859 0860 QSize oldVisibleSize(visibleWidth(), visibleHeight()); 0861 0862 if (d->policy != AutoOne || d->anyVisibleChildren()) { 0863 // Do we definitely need the scroll bar? 0864 needh = w - lmarg - rmarg < d->contentsWidth(); 0865 if (d->inresize) 0866 needh = !horizontalScrollBar()->isHidden(); 0867 needv = h - tmarg - bmarg < contentsHeight(); 0868 0869 // Do we intend to show the scroll bar? 0870 if (d->hMode == AlwaysOn) 0871 showh = true; 0872 else if (d->hMode == AlwaysOff) 0873 showh = false; 0874 else 0875 showh = needh; 0876 0877 if (d->vMode == AlwaysOn) 0878 showv = true; 0879 else if (d->vMode == AlwaysOff) 0880 showv = false; 0881 else 0882 showv = needv; 0883 0884 #ifdef Q_WS_MAC 0885 bool mac_need_scroll = false; 0886 if (!parentWidget()) { 0887 mac_need_scroll = true; 0888 } else { 0889 QWidget *tlw = window(); 0890 // #ifndef QT_MAC_USE_COCOA // 2018.10.18 - do not depend on internal headers 0891 // QPoint tlw_br = QPoint(tlw->width(), tlw->height()), 0892 // my_br = qt_mac_posInWindow(this) + QPoint(w, h); 0893 // if(my_br.x() >= tlw_br.x() - 3 && my_br.y() >= tlw_br.y() - 3) 0894 // #endif 0895 mac_need_scroll = true; 0896 } 0897 if (mac_need_scroll) { 0898 // #ifndef QT_MAC_USE_COCOA // 2018.10.18 - do not depend on internal headers 0899 // WindowAttributes attr; 0900 // GetWindowAttributes((WindowPtr)handle(), &attr); 0901 // mac_need_scroll = (attr & kWindowResizableAttribute); 0902 // #endif 0903 } 0904 if (mac_need_scroll) { 0905 showc = true; 0906 if (d->vMode == Auto) 0907 showv = true; 0908 if (d->hMode == Auto) 0909 showh = true; 0910 } 0911 #endif 0912 0913 // Given other scroll bar will be shown, NOW do we need one? 0914 if (showh && h - vsbExt - tmarg - bmarg < contentsHeight()) { 0915 needv = true; 0916 if (d->vMode == Auto) 0917 showv = true; 0918 } 0919 if (showv && !d->inresize && w - hsbExt - lmarg - rmarg < d->contentsWidth()) { 0920 needh = true; 0921 if (d->hMode == Auto) 0922 showh = true; 0923 } 0924 } else { 0925 // Scrollbars not needed, only show scroll bar that are always on. 0926 needh = needv = false; 0927 showh = d->hMode == AlwaysOn; 0928 showv = d->vMode == AlwaysOn; 0929 } 0930 0931 bool sc = d->signal_choke; 0932 d->signal_choke = true; 0933 0934 // Hide unneeded scroll bar, calculate viewport size 0935 if (showh) { 0936 porth = h - hsbExt - tmarg - bmarg; 0937 } else { 0938 if (!needh) 0939 d->hbar->setValue(0); 0940 d->hbar->hide(); 0941 porth = h - tmarg - bmarg; 0942 } 0943 if (showv) { 0944 portw = w - vsbExt - lmarg - rmarg; 0945 } else { 0946 if (!needv) 0947 d->vbar->setValue(0); 0948 d->vbar->hide(); 0949 portw = w - lmarg - rmarg; 0950 } 0951 0952 // Configure scroll bars that we will show 0953 if (needv) { 0954 d->vbar->setRange(0, contentsHeight() - porth); 0955 // d->vbar->setSteps(KtlQ3ScrollView::d->vbar->lineStep(), porth); // 2018.11.30 0956 d->vbar->setSingleStep(KtlQ3ScrollView::d->vbar->singleStep()); 0957 d->vbar->setPageStep(porth); 0958 } else { 0959 d->vbar->setRange(0, 0); 0960 } 0961 if (needh) { 0962 d->hbar->setRange(0, qMax(0, d->contentsWidth() - portw)); 0963 // d->hbar->setSteps(KtlQ3ScrollView::d->hbar->lineStep(), portw); // 2018.11.30 0964 d->hbar->setSingleStep(KtlQ3ScrollView::d->hbar->singleStep()); 0965 d->hbar->setPageStep(portw); 0966 } else { 0967 d->hbar->setRange(0, 0); 0968 } 0969 0970 // Position the scroll bars, viewport and corner widget. 0971 int bottom; 0972 bool reverse = QApplication::layoutDirection() == Qt::RightToLeft; 0973 int xoffset = (reverse && (showv || cornerWidget())) ? vsbExt : 0; 0974 int xpos = reverse ? 0 : w - vsbExt; 0975 bool frameContentsOnly = style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents); 0976 0977 if (!frameContentsOnly) { 0978 if (reverse) 0979 xpos += fw; 0980 else 0981 xpos -= fw; 0982 } 0983 if (showh) { 0984 int right = (showc || showv || cornerWidget()) ? w - vsbExt : w; 0985 if (!frameContentsOnly) 0986 setHBarGeometry(*d->hbar, fw + xoffset, h - hsbExt - fw, right - fw - fw, hsbExt); 0987 else 0988 setHBarGeometry(*d->hbar, 0 + xoffset, h - hsbExt, right, hsbExt); 0989 bottom = h - hsbExt; 0990 } else { 0991 bottom = h; 0992 } 0993 if (showv) { 0994 clipper()->setGeometry(lmarg + xoffset, tmarg, w - vsbExt - lmarg - rmarg, bottom - tmarg - bmarg); 0995 d->viewportResized(w - vsbExt - lmarg - rmarg, bottom - tmarg - bmarg); 0996 if (!frameContentsOnly) 0997 changeFrameRect(QRect(0, 0, w, h)); 0998 else 0999 changeFrameRect(QRect(xoffset, 0, w - vsbExt, bottom)); 1000 if (showc || cornerWidget()) { 1001 if (!frameContentsOnly) 1002 setVBarGeometry(*d->vbar, xpos, fw, vsbExt, h - hsbExt - fw - fw); 1003 else 1004 setVBarGeometry(*d->vbar, xpos, 0, vsbExt, h - hsbExt); 1005 } else { 1006 if (!frameContentsOnly) 1007 setVBarGeometry(*d->vbar, xpos, fw, vsbExt, bottom - fw - fw); 1008 else 1009 setVBarGeometry(*d->vbar, xpos, 0, vsbExt, bottom); 1010 } 1011 } else { 1012 if (!frameContentsOnly) 1013 changeFrameRect(QRect(0, 0, w, h)); 1014 else 1015 changeFrameRect(QRect(0, 0, w, bottom)); 1016 clipper()->setGeometry(lmarg, tmarg, w - lmarg - rmarg, bottom - tmarg - bmarg); 1017 d->viewportResized(w - lmarg - rmarg, bottom - tmarg - bmarg); 1018 } 1019 1020 QWidget *corner = d->corner; 1021 if (d->corner) { 1022 if (!frameContentsOnly) 1023 corner->setGeometry(xpos, h - hsbExt - fw, vsbExt, hsbExt); 1024 else 1025 corner->setGeometry(xpos, h - hsbExt, vsbExt, hsbExt); 1026 } 1027 1028 d->signal_choke = sc; 1029 1030 if (d->contentsX() + visibleWidth() > d->contentsWidth()) { 1031 int x; 1032 #if 0 1033 if (reverse) 1034 x =qMin(0,d->contentsWidth()-visibleWidth()); 1035 else 1036 #endif 1037 x = qMax(0, d->contentsWidth() - visibleWidth()); 1038 d->hbar->setValue(x); 1039 // Do it even if it is recursive 1040 moveContents(-x, -d->contentsY()); 1041 } 1042 if (d->contentsY() + visibleHeight() > contentsHeight()) { 1043 int y = qMax(0, contentsHeight() - visibleHeight()); 1044 d->vbar->setValue(y); 1045 // Do it even if it is recursive 1046 moveContents(-d->contentsX(), -y); 1047 } 1048 1049 // Finally, show the scroll bars 1050 if (showh && (d->hbar->isHidden() || !d->hbar->isVisible())) 1051 d->hbar->show(); 1052 if (showv && (d->vbar->isHidden() || !d->vbar->isVisible())) 1053 d->vbar->show(); 1054 1055 d->signal_choke = true; 1056 d->vbar->setValue(d->contentsY()); 1057 d->hbar->setValue(d->contentsX()); 1058 d->signal_choke = false; 1059 1060 QSize newVisibleSize(visibleWidth(), visibleHeight()); 1061 if (d->clipped_viewport && oldVisibleSize != newVisibleSize) { 1062 QResizeEvent e(newVisibleSize, oldVisibleSize); 1063 viewportResizeEvent(&e); 1064 } 1065 } 1066 1067 /*! 1068 \reimp 1069 */ 1070 void KtlQ3ScrollView::setVisible(bool visible) 1071 { 1072 if (visible && !isVisible()) { 1073 QWidget::setVisible(visible); 1074 updateScrollBars(); 1075 d->hideOrShowAll(this); 1076 } else { 1077 QWidget::setVisible(visible); 1078 } 1079 } 1080 1081 /*! 1082 \internal 1083 */ 1084 void KtlQ3ScrollView::resize(int w, int h) 1085 { 1086 QWidget::resize(w, h); 1087 } 1088 1089 /*! 1090 \internal 1091 */ 1092 void KtlQ3ScrollView::resize(const QSize &s) 1093 { 1094 resize(s.width(), s.height()); 1095 } 1096 1097 /*! 1098 \reimp 1099 */ 1100 void KtlQ3ScrollView::resizeEvent(QResizeEvent */*event*/) 1101 { 1102 // KtlQ3Frame::resizeEvent(); 1103 1104 #if 0 1105 if (QApplication::reverseLayout()) { 1106 d->fake_scroll = true; 1107 scrollBy(-event->size().width() + event->oldSize().width(), 0); 1108 d->fake_scroll = false; 1109 } 1110 #endif 1111 1112 bool inresize = d->inresize; 1113 d->inresize = true; 1114 updateScrollBars(); 1115 d->inresize = inresize; 1116 // d->scrollbar_timer.start(0, true); // 2018.11.30 1117 d->scrollbar_timer.setSingleShot(true); 1118 d->scrollbar_timer.start(0); 1119 1120 d->hideOrShowAll(this); 1121 } 1122 1123 /*! 1124 \reimp 1125 */ 1126 void KtlQ3ScrollView::mousePressEvent(QMouseEvent *e) 1127 { 1128 e->ignore(); 1129 } 1130 1131 /*! 1132 \reimp 1133 */ 1134 void KtlQ3ScrollView::mouseReleaseEvent(QMouseEvent *e) 1135 { 1136 e->ignore(); 1137 } 1138 1139 /*! 1140 \reimp 1141 */ 1142 void KtlQ3ScrollView::mouseDoubleClickEvent(QMouseEvent *e) 1143 { 1144 e->ignore(); 1145 } 1146 1147 /*! 1148 \reimp 1149 */ 1150 void KtlQ3ScrollView::mouseMoveEvent(QMouseEvent *e) 1151 { 1152 e->ignore(); 1153 } 1154 1155 /*! 1156 \reimp 1157 */ 1158 #ifndef QT_NO_WHEELEVENT 1159 void KtlQ3ScrollView::wheelEvent(QWheelEvent *e) 1160 { 1161 /* QWheelEvent ce(viewport()->mapFromGlobal(e->globalPos()), 1162 e->globalPos(), e->delta(), e->state()); - 2018.11.30*/ 1163 /* QWheelEvent ce(viewport()->mapFromGlobal(e->globalPos()), e->globalPos(), e->delta(), e->buttons(), e->modifiers()); - 2023.04.10 */ 1164 QWheelEvent ce(viewport()->mapFromGlobal(e->globalPosition().toPoint()), 1165 e->globalPosition(), 1166 e->pixelDelta(), 1167 e->angleDelta(), 1168 e->buttons(), 1169 e->modifiers(), 1170 e->phase(), 1171 e->inverted()); 1172 viewportWheelEvent(&ce); 1173 if (!ce.isAccepted()) { 1174 if ((e->angleDelta().x() != 0) && horizontalScrollBar()) 1175 horizontalScrollBar()->event(e); 1176 else if ((e->angleDelta().y() != 0) && verticalScrollBar()) 1177 verticalScrollBar()->event(e); 1178 } else { 1179 e->accept(); 1180 } 1181 } 1182 #endif 1183 1184 /*! 1185 \reimp 1186 */ 1187 void KtlQ3ScrollView::contextMenuEvent(QContextMenuEvent *e) 1188 { 1189 if (e->reason() != QContextMenuEvent::Keyboard) { 1190 e->ignore(); 1191 return; 1192 } 1193 1194 /* QContextMenuEvent ce(e->reason(), viewport()->mapFromGlobal(e->globalPos()), 1195 e->globalPos(), e->state()); - 2018.11.30 */ 1196 QContextMenuEvent ce(e->reason(), viewport()->mapFromGlobal(e->globalPos()), e->globalPos(), e->modifiers()); 1197 viewportContextMenuEvent(&ce); 1198 if (ce.isAccepted()) 1199 e->accept(); 1200 else 1201 e->ignore(); 1202 } 1203 1204 KtlQ3ScrollView::ScrollBarMode KtlQ3ScrollView::vScrollBarMode() const 1205 { 1206 return d->vMode; 1207 } 1208 1209 /*! 1210 \enum KtlQ3ScrollView::ScrollBarMode 1211 1212 This enum type describes the various modes of KtlQ3ScrollView's scroll 1213 bars. 1214 1215 \value Auto KtlQ3ScrollView shows a scroll bar when the content is 1216 too large to fit and not otherwise. This is the default. 1217 1218 \value AlwaysOff KtlQ3ScrollView never shows a scroll bar. 1219 1220 \value AlwaysOn KtlQ3ScrollView always shows a scroll bar. 1221 1222 (The modes for the horizontal and vertical scroll bars are 1223 independent.) 1224 */ 1225 1226 /*! 1227 \property KtlQ3ScrollView::vScrollBarMode 1228 \brief the mode for the vertical scroll bar 1229 1230 The default mode is KtlQ3ScrollView::Auto. 1231 1232 \sa hScrollBarMode 1233 */ 1234 void KtlQ3ScrollView::setVScrollBarMode(ScrollBarMode mode) 1235 { 1236 if (d->vMode != mode) { 1237 d->vMode = mode; 1238 updateScrollBars(); 1239 } 1240 } 1241 1242 /*! 1243 \property KtlQ3ScrollView::hScrollBarMode 1244 \brief the mode for the horizontal scroll bar 1245 1246 The default mode is KtlQ3ScrollView::Auto. 1247 1248 \sa vScrollBarMode 1249 */ 1250 KtlQ3ScrollView::ScrollBarMode KtlQ3ScrollView::hScrollBarMode() const 1251 { 1252 return d->hMode; 1253 } 1254 1255 void KtlQ3ScrollView::setHScrollBarMode(ScrollBarMode mode) 1256 { 1257 if (d->hMode != mode) { 1258 d->hMode = mode; 1259 updateScrollBars(); 1260 } 1261 } 1262 1263 /*! 1264 Returns the widget in the corner between the two scroll bars. 1265 1266 By default, no corner widget is present. 1267 */ 1268 QWidget *KtlQ3ScrollView::cornerWidget() const 1269 { 1270 return d->corner; 1271 } 1272 1273 /*! 1274 Sets the widget in the \a corner between the two scroll bars. 1275 1276 You will probably also want to set at least one of the scroll bar 1277 modes to \c AlwaysOn. 1278 1279 Passing 0 shows no widget in the corner. 1280 1281 Any previous \a corner widget is hidden. 1282 1283 You may call setCornerWidget() with the same widget at different 1284 times. 1285 1286 All widgets set here will be deleted by the KtlQ3ScrollView when it is 1287 destroyed unless you separately reparent the widget after setting 1288 some other corner widget (or 0). 1289 1290 Any \e newly set widget should have no current parent. 1291 1292 By default, no corner widget is present. 1293 1294 \sa setVScrollBarMode(), setHScrollBarMode() 1295 */ 1296 void KtlQ3ScrollView::setCornerWidget(QWidget *corner) 1297 { 1298 QWidget *oldcorner = d->corner; 1299 if (oldcorner != corner) { 1300 if (oldcorner) 1301 oldcorner->hide(); 1302 d->corner = corner; 1303 if (corner) 1304 corner->setParent(this); 1305 updateScrollBars(); 1306 if (corner) 1307 corner->show(); 1308 } 1309 } 1310 1311 void KtlQ3ScrollView::setResizePolicy(ResizePolicy r) 1312 { 1313 d->policy = r; 1314 } 1315 1316 /*! 1317 \property KtlQ3ScrollView::resizePolicy 1318 \brief the resize policy 1319 1320 The default is \c Default. 1321 1322 \sa ResizePolicy 1323 */ 1324 KtlQ3ScrollView::ResizePolicy KtlQ3ScrollView::resizePolicy() const 1325 { 1326 return d->policy; 1327 } 1328 1329 /*! 1330 \internal 1331 */ 1332 void KtlQ3ScrollView::setEnabled(bool enable) 1333 { 1334 KtlQ3Frame::setEnabled(enable); 1335 } 1336 1337 /*! 1338 Removes the \a child widget from the scrolled area. Note that this 1339 happens automatically if the \a child is deleted. 1340 */ 1341 void KtlQ3ScrollView::removeChild(QWidget *child) 1342 { 1343 if (!d || !child) // First check in case we are destructing 1344 return; 1345 1346 QSVChildRec *r = d->rec(child); 1347 if (r) 1348 d->deleteChildRec(r); 1349 } 1350 1351 /*! 1352 \internal 1353 */ 1354 void KtlQ3ScrollView::removeChild(QObject *child) 1355 { 1356 // KtlQ3Frame::removeChild(child); // 2018.11.30 1357 if (child) { 1358 child->setParent(nullptr); 1359 } 1360 } 1361 1362 /*! 1363 Inserts the widget, \a child, into the scrolled area positioned at 1364 (\a x, \a y). The position defaults to (0, 0). If the child is 1365 already in the view, it is just moved. 1366 1367 You may want to call enableClipper(true) if you add a large number 1368 of widgets. 1369 */ 1370 void KtlQ3ScrollView::addChild(QWidget *child, int x, int y) 1371 { 1372 if (!child) { 1373 #if defined(QT_CHECK_NULL) 1374 qWarning("KtlQ3ScrollView::addChild(): Cannot add null child"); 1375 #endif 1376 return; 1377 } 1378 child->ensurePolished(); 1379 // child->setBackgroundOrigin(WidgetOrigin); // 2018.11.30 - does nothing in qt4 1380 1381 if (child->parentWidget() == viewport()) { 1382 // May already be there 1383 QSVChildRec *r = d->rec(child); 1384 if (r) { 1385 r->moveTo(this, x, y, d->clipped_viewport); 1386 if (d->policy > Manual) { 1387 d->autoResizeHint(this); 1388 d->autoResize(this); // #### better to just deal with this one widget! 1389 } 1390 return; 1391 } 1392 } 1393 1394 if (d->children.isEmpty() && d->policy != Manual) { 1395 if (d->policy == Default) 1396 setResizePolicy(AutoOne); 1397 child->installEventFilter(this); 1398 } else if (d->policy == AutoOne) { 1399 child->removeEventFilter(this); //#### ????? 1400 setResizePolicy(Manual); 1401 } 1402 if (child->parentWidget() != viewport()) { 1403 // child->reparent(viewport(), 0, QPoint(0,0), false); // 2018.11.30 1404 child->setParent(viewport()); 1405 child->setGeometry(0, 0, child->width(), child->height()); 1406 } 1407 d->addChildRec(child, x, y)->hideOrShow(this, d->clipped_viewport); 1408 1409 if (d->policy > Manual) { 1410 d->autoResizeHint(this); 1411 d->autoResize(this); // #### better to just deal with this one widget! 1412 } 1413 } 1414 1415 /*! 1416 Repositions the \a child widget to (\a x, \a y). This function is 1417 the same as addChild(). 1418 */ 1419 void KtlQ3ScrollView::moveChild(QWidget *child, int x, int y) 1420 { 1421 addChild(child, x, y); 1422 } 1423 1424 /*! 1425 Returns the X position of the given \a child widget. Use this 1426 rather than QWidget::x() for widgets added to the view. 1427 1428 This function returns 0 if \a child has not been added to the view. 1429 */ 1430 int KtlQ3ScrollView::childX(QWidget *child) 1431 { 1432 QSVChildRec *r = d->rec(child); 1433 return r ? r->x : 0; 1434 } 1435 1436 /*! 1437 Returns the Y position of the given \a child widget. Use this 1438 rather than QWidget::y() for widgets added to the view. 1439 1440 This function returns 0 if \a child has not been added to the view. 1441 */ 1442 int KtlQ3ScrollView::childY(QWidget *child) 1443 { 1444 QSVChildRec *r = d->rec(child); 1445 return r ? r->y : 0; 1446 } 1447 1448 /*! \fn bool KtlQ3ScrollView::childIsVisible(QWidget*) 1449 \obsolete 1450 1451 Returns true if \a child is visible. This is equivalent 1452 to child->isVisible(). 1453 */ 1454 1455 /*! \fn void KtlQ3ScrollView::showChild(QWidget* child, bool y) 1456 \obsolete 1457 1458 Sets the visibility of \a child. Equivalent to 1459 QWidget::show() or QWidget::hide(). 1460 */ 1461 1462 /*! 1463 This event filter ensures the scroll bars are updated when a 1464 single contents widget is resized, shown, hidden or destroyed; it 1465 passes mouse events to the KtlQ3ScrollView. The event is in \a e and 1466 the object is in \a obj. 1467 */ 1468 1469 bool KtlQ3ScrollView::eventFilter(QObject *obj, QEvent *e) 1470 { 1471 bool disabled = !(qobject_cast<QWidget *>(obj)->isEnabled()); 1472 if (!d) 1473 return false; // we are destructing 1474 if (obj == d->viewport || obj == d->clipped_viewport) { 1475 switch (e->type()) { 1476 /* Forward many events to viewport...() functions */ 1477 case QEvent::Paint: 1478 viewportPaintEvent(static_cast<QPaintEvent *>(e)); 1479 break; 1480 case QEvent::Resize: 1481 if (!d->clipped_viewport) 1482 viewportResizeEvent(static_cast<QResizeEvent *>(e)); 1483 break; 1484 case QEvent::MouseButtonPress: 1485 if (disabled) 1486 return false; 1487 viewportMousePressEvent(static_cast<QMouseEvent *>(e)); 1488 if ((static_cast<QMouseEvent *>(e))->isAccepted()) 1489 return true; 1490 break; 1491 case QEvent::MouseButtonRelease: 1492 if (disabled) 1493 return false; 1494 viewportMouseReleaseEvent(static_cast<QMouseEvent *>(e)); 1495 if ((static_cast<QMouseEvent *>(e))->isAccepted()) 1496 return true; 1497 break; 1498 case QEvent::MouseButtonDblClick: 1499 if (disabled) 1500 return false; 1501 viewportMouseDoubleClickEvent(static_cast<QMouseEvent *>(e)); 1502 if ((static_cast<QMouseEvent *>(e))->isAccepted()) 1503 return true; 1504 break; 1505 case QEvent::MouseMove: 1506 if (disabled) 1507 return false; 1508 viewportMouseMoveEvent(static_cast<QMouseEvent *>(e)); 1509 if ((static_cast<QMouseEvent *>(e))->isAccepted()) 1510 return true; 1511 break; 1512 #ifndef QT_NO_DRAGANDDROP 1513 case QEvent::DragEnter: 1514 if (disabled) 1515 return false; 1516 viewportDragEnterEvent(static_cast<QDragEnterEvent *>(e)); 1517 break; 1518 case QEvent::DragMove: { 1519 if (disabled) 1520 return false; 1521 if (d->drag_autoscroll) { 1522 QPoint vp = (static_cast<QDragMoveEvent *>(e))->pos(); 1523 QRect inside_margin(autoscroll_margin, autoscroll_margin, visibleWidth() - autoscroll_margin * 2, visibleHeight() - autoscroll_margin * 2); 1524 if (!inside_margin.contains(vp)) { 1525 startDragAutoScroll(); 1526 // Keep sending move events 1527 (static_cast<QDragMoveEvent *>(e))->accept(QRect(0, 0, 0, 0)); 1528 } 1529 } 1530 viewportDragMoveEvent(static_cast<QDragMoveEvent *>(e)); 1531 } break; 1532 case QEvent::DragLeave: 1533 if (disabled) 1534 return false; 1535 stopDragAutoScroll(); 1536 viewportDragLeaveEvent(static_cast<QDragLeaveEvent *>(e)); 1537 break; 1538 case QEvent::Drop: 1539 if (disabled) 1540 return false; 1541 stopDragAutoScroll(); 1542 viewportDropEvent(static_cast<QDropEvent *>(e)); 1543 break; 1544 #endif // QT_NO_DRAGANDDROP 1545 #ifndef QT_NO_WHEELEVENT 1546 case QEvent::Wheel: 1547 if (disabled) 1548 return false; 1549 break; 1550 #endif 1551 case QEvent::ContextMenu: 1552 if (disabled) 1553 return false; 1554 viewportContextMenuEvent(static_cast<QContextMenuEvent *>(e)); 1555 if ((static_cast<QContextMenuEvent *>(e))->isAccepted()) 1556 return true; 1557 break; 1558 case QEvent::ChildRemoved: 1559 removeChild(static_cast<QWidget *>((static_cast<QChildEvent *>(e))->child())); 1560 break; 1561 // case QEvent::LayoutHint: // 2018.12.08 - deprecated 1562 // d->autoResizeHint(this); 1563 // break; 1564 default: 1565 break; 1566 } 1567 } else if (d && d->rec(static_cast<QWidget *>(obj))) { // must be a child 1568 if (e->type() == QEvent::Resize) 1569 d->autoResize(this); 1570 else if (e->type() == QEvent::Move) 1571 d->autoMove(this); 1572 } 1573 return KtlQ3Frame::eventFilter(obj, e); // always continue with standard event processing 1574 } 1575 1576 /*! 1577 This event handler is called whenever the KtlQ3ScrollView receives a 1578 mousePressEvent(): the press position in \a e is translated to be a point 1579 on the contents. 1580 */ 1581 void KtlQ3ScrollView::contentsMousePressEvent(QMouseEvent *e) 1582 { 1583 e->ignore(); 1584 } 1585 1586 /*! 1587 This event handler is called whenever the KtlQ3ScrollView receives a 1588 mouseReleaseEvent(): the release position in \a e is translated to be a 1589 point on the contents. 1590 */ 1591 void KtlQ3ScrollView::contentsMouseReleaseEvent(QMouseEvent *e) 1592 { 1593 e->ignore(); 1594 } 1595 1596 /*! 1597 This event handler is called whenever the KtlQ3ScrollView receives a 1598 mouseDoubleClickEvent(): the click position in \a e is translated to be a 1599 point on the contents. 1600 1601 The default implementation generates a normal mouse press event. 1602 */ 1603 void KtlQ3ScrollView::contentsMouseDoubleClickEvent(QMouseEvent *e) 1604 { 1605 contentsMousePressEvent(e); // try mouse press event 1606 } 1607 1608 /*! 1609 This event handler is called whenever the KtlQ3ScrollView receives a 1610 mouseMoveEvent(): the mouse position in \a e is translated to be a point 1611 on the contents. 1612 */ 1613 void KtlQ3ScrollView::contentsMouseMoveEvent(QMouseEvent *e) 1614 { 1615 e->ignore(); 1616 } 1617 1618 #ifndef QT_NO_DRAGANDDROP 1619 1620 /*! 1621 This event handler is called whenever the KtlQ3ScrollView receives a 1622 dragEnterEvent(): the drag position is translated to be a point 1623 on the contents. 1624 1625 The default implementation does nothing. The \a event parameter is 1626 ignored. 1627 */ 1628 void KtlQ3ScrollView::contentsDragEnterEvent(QDragEnterEvent * /* event */) 1629 { 1630 } 1631 1632 /*! 1633 This event handler is called whenever the KtlQ3ScrollView receives a 1634 dragMoveEvent(): the drag position is translated to be a point on 1635 the contents. 1636 1637 The default implementation does nothing. The \a event parameter is 1638 ignored. 1639 */ 1640 void KtlQ3ScrollView::contentsDragMoveEvent(QDragMoveEvent * /* event */) 1641 { 1642 } 1643 1644 /*! 1645 This event handler is called whenever the KtlQ3ScrollView receives a 1646 dragLeaveEvent(): 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 */ 1652 void KtlQ3ScrollView::contentsDragLeaveEvent(QDragLeaveEvent * /* event */) 1653 { 1654 } 1655 1656 /*! 1657 This event handler is called whenever the KtlQ3ScrollView receives a 1658 dropEvent(): the drop position is translated to be a point on the 1659 contents. 1660 1661 The default implementation does nothing. The \a event parameter is 1662 ignored. 1663 */ 1664 1665 void KtlQ3ScrollView::contentsDropEvent(QDropEvent * /* event */) 1666 { 1667 } 1668 1669 #endif // QT_NO_DRAGANDDROP 1670 1671 /*! 1672 This event handler is called whenever the KtlQ3ScrollView receives a 1673 wheelEvent() in \a{e}: the mouse position is translated to be a 1674 point on the contents. 1675 */ 1676 #ifndef QT_NO_WHEELEVENT 1677 void KtlQ3ScrollView::contentsWheelEvent(QWheelEvent *e) 1678 { 1679 e->ignore(); 1680 } 1681 #endif 1682 /*! 1683 This event handler is called whenever the KtlQ3ScrollView receives a 1684 contextMenuEvent() in \a{e}: the mouse position is translated to 1685 be a point on the contents. 1686 */ 1687 void KtlQ3ScrollView::contentsContextMenuEvent(QContextMenuEvent *e) 1688 { 1689 e->ignore(); 1690 } 1691 1692 /*! 1693 This is a low-level painting routine that draws the viewport 1694 contents. Reimplement this if drawContents() is too high-level 1695 (for example, if you don't want to open a QPainter on the 1696 viewport). The paint event is passed in \a pe. 1697 */ 1698 void KtlQ3ScrollView::viewportPaintEvent(QPaintEvent *pe) 1699 { 1700 QWidget *vp = viewport(); 1701 1702 QPainter p(vp); 1703 QRect r = pe->rect(); 1704 1705 if (d->clipped_viewport) { 1706 QRect rr(-d->clipped_viewport->x(), -d->clipped_viewport->y(), d->viewport->width(), d->viewport->height()); 1707 r &= rr; 1708 if (r.isValid()) { 1709 int ex = r.x() + d->clipped_viewport->x() + d->contentsX(); 1710 int ey = r.y() + d->clipped_viewport->y() + d->contentsY(); 1711 int ew = r.width(); 1712 int eh = r.height(); 1713 drawContentsOffset(&p, d->contentsX() + d->clipped_viewport->x(), d->contentsY() + d->clipped_viewport->y(), ex, ey, ew, eh); 1714 } 1715 } else { 1716 r &= d->viewport->rect(); 1717 int ex = r.x() + d->contentsX(); 1718 int ey = r.y() + d->contentsY(); 1719 int ew = r.width(); 1720 int eh = r.height(); 1721 drawContentsOffset(&p, d->contentsX(), d->contentsY(), ex, ey, ew, eh); 1722 } 1723 } 1724 1725 /*! 1726 To provide simple processing of events on the contents, this 1727 function receives all resize events sent to the viewport. 1728 1729 The default implementation does nothing. The \a event parameter is 1730 ignored. 1731 1732 \sa QWidget::resizeEvent() 1733 */ 1734 void KtlQ3ScrollView::viewportResizeEvent(QResizeEvent * /* event */) 1735 { 1736 } 1737 1738 /*! \internal 1739 1740 To provide simple processing of events on the contents, this 1741 function receives all mouse press events sent to the viewport, 1742 translates the event and calls contentsMousePressEvent(). 1743 1744 \sa contentsMousePressEvent(), QWidget::mousePressEvent() 1745 */ 1746 void KtlQ3ScrollView::viewportMousePressEvent(QMouseEvent *e) 1747 { 1748 /* QMouseEvent ce(e->type(), viewportToContents(e->pos()), 1749 e->globalPos(), e->button(), e->state()); - 2018.11.30 */ 1750 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->buttons(), e->modifiers()); 1751 contentsMousePressEvent(&ce); 1752 if (!ce.isAccepted()) 1753 e->ignore(); 1754 } 1755 1756 /*!\internal 1757 1758 To provide simple processing of events on the contents, this function 1759 receives all mouse release events sent to the viewport, translates 1760 the event and calls contentsMouseReleaseEvent(). 1761 1762 \sa QWidget::mouseReleaseEvent() 1763 */ 1764 void KtlQ3ScrollView::viewportMouseReleaseEvent(QMouseEvent *e) 1765 { 1766 /* QMouseEvent ce(e->type(), viewportToContents(e->pos()), 1767 e->globalPos(), e->button(), e->state()); -- 2018.11.30 */ 1768 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->buttons(), e->modifiers()); 1769 contentsMouseReleaseEvent(&ce); 1770 if (!ce.isAccepted()) 1771 e->ignore(); 1772 } 1773 1774 /*!\internal 1775 1776 To provide simple processing of events on the contents, this function 1777 receives all mouse double click events sent to the viewport, 1778 translates the event and calls contentsMouseDoubleClickEvent(). 1779 1780 \sa QWidget::mouseDoubleClickEvent() 1781 */ 1782 void KtlQ3ScrollView::viewportMouseDoubleClickEvent(QMouseEvent *e) 1783 { 1784 /* QMouseEvent ce(e->type(), viewportToContents(e->pos()), 1785 e->globalPos(), e->button(), e->state()); - 2018.11.30 */ 1786 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->buttons(), e->modifiers()); 1787 contentsMouseDoubleClickEvent(&ce); 1788 if (!ce.isAccepted()) 1789 e->ignore(); 1790 } 1791 1792 /*!\internal 1793 1794 To provide simple processing of events on the contents, this function 1795 receives all mouse move events sent to the viewport, translates the 1796 event and calls contentsMouseMoveEvent(). 1797 1798 \sa QWidget::mouseMoveEvent() 1799 */ 1800 void KtlQ3ScrollView::viewportMouseMoveEvent(QMouseEvent *e) 1801 { 1802 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->buttons(), e->modifiers()); 1803 contentsMouseMoveEvent(&ce); 1804 if (!ce.isAccepted()) 1805 e->ignore(); 1806 } 1807 1808 #ifndef QT_NO_DRAGANDDROP 1809 1810 /*!\internal 1811 1812 To provide simple processing of events on the contents, this function 1813 receives all drag enter events sent to the viewport, translates the 1814 event and calls contentsDragEnterEvent(). 1815 1816 \sa QWidget::dragEnterEvent() 1817 */ 1818 void KtlQ3ScrollView::viewportDragEnterEvent(QDragEnterEvent *e) 1819 { 1820 // e->setPoint(viewportToContents(e->pos())); // 2018.11.30 1821 QDragEnterEvent ev(viewportToContents(e->pos()), e->possibleActions(), e->mimeData(), e->mouseButtons(), e->keyboardModifiers()); 1822 contentsDragEnterEvent(&ev); 1823 // e->setPoint(contentsToViewport(e->pos())); // 2018.11.30 1824 } 1825 1826 /*!\internal 1827 1828 To provide simple processing of events on the contents, this function 1829 receives all drag move events sent to the viewport, translates the 1830 event and calls contentsDragMoveEvent(). 1831 1832 \sa QWidget::dragMoveEvent() 1833 */ 1834 void KtlQ3ScrollView::viewportDragMoveEvent(QDragMoveEvent *e) 1835 { 1836 // e->setPoint(viewportToContents(e->pos())); // 2018.11.30 1837 QDragMoveEvent ev(viewportToContents(e->pos()), e->possibleActions(), e->mimeData(), e->mouseButtons(), e->keyboardModifiers()); 1838 contentsDragMoveEvent(&ev); 1839 // e->setPoint(contentsToViewport(e->pos())); // 2018.11.30 1840 } 1841 1842 /*!\internal 1843 1844 To provide simple processing of events on the contents, this function 1845 receives all drag leave events sent to the viewport and calls 1846 contentsDragLeaveEvent(). 1847 1848 \sa QWidget::dragLeaveEvent() 1849 */ 1850 void KtlQ3ScrollView::viewportDragLeaveEvent(QDragLeaveEvent *e) 1851 { 1852 contentsDragLeaveEvent(e); 1853 } 1854 1855 /*!\internal 1856 1857 To provide simple processing of events on the contents, this function 1858 receives all drop events sent to the viewport, translates the event 1859 and calls contentsDropEvent(). 1860 1861 \sa QWidget::dropEvent() 1862 */ 1863 void KtlQ3ScrollView::viewportDropEvent(QDropEvent *e) 1864 { 1865 // e->setPoint(viewportToContents(e->pos())); // 2018.11.30 1866 QDropEvent ev(viewportToContents(e->pos()), e->possibleActions(), e->mimeData(), e->mouseButtons(), e->keyboardModifiers()); 1867 contentsDropEvent(&ev); 1868 // e->setPoint(contentsToViewport(e->pos())); // 2018.11.30 1869 } 1870 1871 #endif // QT_NO_DRAGANDDROP 1872 1873 /*!\internal 1874 1875 To provide simple processing of events on the contents, this function 1876 receives all wheel events sent to the viewport, translates the 1877 event and calls contentsWheelEvent(). 1878 1879 \sa QWidget::wheelEvent() 1880 */ 1881 #ifndef QT_NO_WHEELEVENT 1882 void KtlQ3ScrollView::viewportWheelEvent(QWheelEvent *e) 1883 { 1884 /* 1885 Different than standard mouse events, because wheel events might 1886 be sent to the focus widget if the widget-under-mouse doesn't want 1887 the event itself. 1888 */ 1889 /* QWheelEvent ce(viewportToContents(e->pos()), 1890 e->globalPos(), e->delta(), e->state()); */ 1891 QWheelEvent ce(viewportToContents(e->position().toPoint()), e->globalPosition(), e->pixelDelta(), e->angleDelta(), 1892 e->buttons(), e->modifiers(), e->phase(), e->inverted()); 1893 contentsWheelEvent(&ce); 1894 if (ce.isAccepted()) 1895 e->accept(); 1896 else 1897 e->ignore(); 1898 } 1899 #endif 1900 1901 /*! \internal 1902 1903 To provide simple processing of events on the contents, this function 1904 receives all context menu events sent to the viewport, translates the 1905 event and calls contentsContextMenuEvent(). 1906 */ 1907 void KtlQ3ScrollView::viewportContextMenuEvent(QContextMenuEvent *e) 1908 { 1909 // QContextMenuEvent ce(e->reason(), viewportToContents(e->pos()), e->globalPos(), e->state()); 1910 QContextMenuEvent ce(e->reason(), viewportToContents(e->pos()), e->globalPos(), e->modifiers()); 1911 contentsContextMenuEvent(&ce); 1912 if (ce.isAccepted()) 1913 e->accept(); 1914 else 1915 e->ignore(); 1916 } 1917 1918 /*! 1919 Returns the component horizontal scroll bar. It is made available 1920 to allow accelerators, autoscrolling, etc. 1921 1922 It should not be used for other purposes. 1923 1924 This function never returns 0. 1925 */ 1926 QScrollBar *KtlQ3ScrollView::horizontalScrollBar() const 1927 { 1928 return d->hbar; 1929 } 1930 1931 /*! 1932 Returns the component vertical scroll bar. It is made available to 1933 allow accelerators, autoscrolling, etc. 1934 1935 It should not be used for other purposes. 1936 1937 This function never returns 0. 1938 */ 1939 QScrollBar *KtlQ3ScrollView::verticalScrollBar() const 1940 { 1941 return d->vbar; 1942 } 1943 1944 /*! 1945 Scrolls the content so that the point (\a x, \a y) is visible with at 1946 least 50-pixel margins (if possible, otherwise centered). 1947 */ 1948 void KtlQ3ScrollView::ensureVisible(int x, int y) 1949 { 1950 ensureVisible(x, y, 50, 50); 1951 } 1952 1953 /*! 1954 \overload 1955 1956 Scrolls the content so that the point (\a x, \a y) is visible with at 1957 least the \a xmargin and \a ymargin margins (if possible, 1958 otherwise centered). 1959 */ 1960 void KtlQ3ScrollView::ensureVisible(int x, int y, int xmargin, int ymargin) 1961 { 1962 int pw = visibleWidth(); 1963 int ph = visibleHeight(); 1964 1965 int cx = -d->contentsX(); 1966 int cy = -d->contentsY(); 1967 int cw = d->contentsWidth(); 1968 int ch = contentsHeight(); 1969 1970 if (pw < xmargin * 2) 1971 xmargin = pw / 2; 1972 if (ph < ymargin * 2) 1973 ymargin = ph / 2; 1974 1975 if (cw <= pw) { 1976 xmargin = 0; 1977 cx = 0; 1978 } 1979 if (ch <= ph) { 1980 ymargin = 0; 1981 cy = 0; 1982 } 1983 1984 if (x < -cx + xmargin) 1985 cx = -x + xmargin; 1986 else if (x >= -cx + pw - xmargin) 1987 cx = -x + pw - xmargin; 1988 1989 if (y < -cy + ymargin) 1990 cy = -y + ymargin; 1991 else if (y >= -cy + ph - ymargin) 1992 cy = -y + ph - ymargin; 1993 1994 if (cx > 0) 1995 cx = 0; 1996 else if (cx < pw - cw && cw > pw) 1997 cx = pw - cw; 1998 1999 if (cy > 0) 2000 cy = 0; 2001 else if (cy < ph - ch && ch > ph) 2002 cy = ph - ch; 2003 2004 setContentsPos(-cx, -cy); 2005 } 2006 2007 /*! 2008 Scrolls the content so that the point (\a x, \a y) is in the top-left 2009 corner. 2010 */ 2011 void KtlQ3ScrollView::setContentsPos(int x, int y) 2012 { 2013 #if 0 2014 // bounds checking... 2015 if (QApplication::reverseLayout()) 2016 if (x > d->contentsWidth() - visibleWidth()) x = d->contentsWidth() - visibleWidth(); 2017 else 2018 #endif 2019 if (x < 0) 2020 x = 0; 2021 if (y < 0) 2022 y = 0; 2023 // Choke signal handling while we update BOTH sliders. 2024 d->signal_choke = true; 2025 moveContents(-x, -y); 2026 d->vbar->setValue(y); 2027 d->hbar->setValue(x); 2028 d->signal_choke = false; 2029 } 2030 2031 /*! 2032 Scrolls the content by \a dx to the left and \a dy upwards. 2033 */ 2034 void KtlQ3ScrollView::scrollBy(int dx, int dy) 2035 { 2036 setContentsPos(qMax(d->contentsX() + dx, 0), qMax(d->contentsY() + dy, 0)); 2037 } 2038 2039 /*! 2040 Scrolls the content so that the point (\a x, \a y) is in the center 2041 of visible area. 2042 */ 2043 void KtlQ3ScrollView::center(int x, int y) 2044 { 2045 ensureVisible(x, y, 32000, 32000); 2046 } 2047 2048 /*! 2049 \overload 2050 2051 Scrolls the content so that the point (\a x, \a y) is visible with 2052 the \a xmargin and \a ymargin margins (as fractions of visible 2053 the area). 2054 2055 For example: 2056 \list 2057 \i Margin 0.0 allows (x, y) to be on the edge of the visible area. 2058 \i Margin 0.5 ensures that (x, y) is in middle 50% of the visible area. 2059 \i Margin 1.0 ensures that (x, y) is in the center of the visible area. 2060 \endlist 2061 */ 2062 void KtlQ3ScrollView::center(int x, int y, float xmargin, float ymargin) 2063 { 2064 int pw = visibleWidth(); 2065 int ph = visibleHeight(); 2066 ensureVisible(x, y, int(xmargin / 2.0 * pw + 0.5), int(ymargin / 2.0 * ph + 0.5)); 2067 } 2068 2069 /*! 2070 \fn void KtlQ3ScrollView::contentsMoving(int x, int y) 2071 2072 This signal is emitted just before the contents are moved to 2073 position (\a x, \a y). 2074 2075 \sa contentsX(), contentsY() 2076 */ 2077 2078 /*! 2079 Moves the contents by (\a x, \a y). 2080 */ 2081 void KtlQ3ScrollView::moveContents(int x, int y) 2082 { 2083 if (-x + visibleWidth() > d->contentsWidth()) 2084 #if 0 2085 if(QApplication::reverseLayout()) 2086 x=qMax(0,-d->contentsWidth()+visibleWidth()); 2087 else 2088 #endif 2089 x = qMin(0, -d->contentsWidth() + visibleWidth()); 2090 if (-y + visibleHeight() > contentsHeight()) 2091 y = qMin(0, -contentsHeight() + visibleHeight()); 2092 2093 int dx = x - d->vx; 2094 int dy = y - d->vy; 2095 2096 if (!dx && !dy) 2097 return; // Nothing to do 2098 2099 emit contentsMoving(-x, -y); 2100 2101 d->vx = x; 2102 d->vy = y; 2103 2104 if (d->clipped_viewport || d->static_bg) { 2105 // Cheap move (usually) 2106 d->moveAllBy(dx, dy); 2107 } else if (/*dx && dy ||*/ 2108 (qAbs(dy) * 5 > visibleHeight() * 4) || (qAbs(dx) * 5 > visibleWidth() * 4)) { 2109 // Big move 2110 if (viewport()->updatesEnabled()) 2111 viewport()->update(); 2112 d->moveAllBy(dx, dy); 2113 } else if (!d->fake_scroll || d->contentsWidth() > visibleWidth()) { 2114 // Small move 2115 clipper()->scroll(dx, dy); 2116 } 2117 d->hideOrShowAll(this, true); 2118 } 2119 2120 /*! 2121 \property KtlQ3ScrollView::contentsX 2122 \brief the X coordinate of the contents that are at the left edge of 2123 the viewport. 2124 */ 2125 int KtlQ3ScrollView::contentsX() const 2126 { 2127 return d->contentsX(); 2128 } 2129 2130 /*! 2131 \property KtlQ3ScrollView::contentsY 2132 \brief the Y coordinate of the contents that are at the top edge of 2133 the viewport. 2134 */ 2135 int KtlQ3ScrollView::contentsY() const 2136 { 2137 return d->contentsY(); 2138 } 2139 2140 /*! 2141 \property KtlQ3ScrollView::contentsWidth 2142 \brief the width of the contents area 2143 */ 2144 int KtlQ3ScrollView::contentsWidth() const 2145 { 2146 return d->contentsWidth(); 2147 } 2148 2149 /*! 2150 \property KtlQ3ScrollView::contentsHeight 2151 \brief the height of the contents area 2152 */ 2153 int KtlQ3ScrollView::contentsHeight() const 2154 { 2155 return d->vheight; 2156 } 2157 2158 /*! 2159 Sets the size of the contents area to \a w pixels wide and \a h 2160 pixels high and updates the viewport accordingly. 2161 */ 2162 void KtlQ3ScrollView::resizeContents(int w, int h) 2163 { 2164 int ow = d->vwidth; 2165 int oh = d->vheight; 2166 d->vwidth = w; 2167 d->vheight = h; 2168 2169 d->scrollbar_timer.setSingleShot(true); 2170 d->scrollbar_timer.start(0 /*, true */); 2171 2172 if (d->children.isEmpty() && d->policy == Default) 2173 setResizePolicy(Manual); 2174 2175 if (ow > w) { 2176 // Swap 2177 int t = w; 2178 w = ow; 2179 ow = t; 2180 } 2181 // Refresh area ow..w 2182 if (ow < visibleWidth() && w >= 0) { 2183 if (ow < 0) 2184 ow = 0; 2185 if (w > visibleWidth()) 2186 w = visibleWidth(); 2187 clipper()->update(d->contentsX() + ow, 0, w - ow, visibleHeight()); 2188 } 2189 2190 if (oh > h) { 2191 // Swap 2192 int t = h; 2193 h = oh; 2194 oh = t; 2195 } 2196 // Refresh area oh..h 2197 if (oh < visibleHeight() && h >= 0) { 2198 if (oh < 0) 2199 oh = 0; 2200 if (h > visibleHeight()) 2201 h = visibleHeight(); 2202 clipper()->update(0, d->contentsY() + oh, visibleWidth(), h - oh); 2203 } 2204 } 2205 2206 /*! 2207 Calls update() on a rectangle defined by \a x, \a y, \a w, \a h, 2208 translated appropriately. If the rectangle is not visible, nothing 2209 is repainted. 2210 2211 \sa repaintContents() 2212 */ 2213 void KtlQ3ScrollView::updateContents(int x, int y, int w, int h) 2214 { 2215 if (!isVisible() || !updatesEnabled()) 2216 return; 2217 2218 QWidget *vp = viewport(); 2219 2220 // Translate 2221 x -= d->contentsX(); 2222 y -= d->contentsY(); 2223 2224 if (x < 0) { 2225 w += x; 2226 x = 0; 2227 } 2228 if (y < 0) { 2229 h += y; 2230 y = 0; 2231 } 2232 2233 if (w < 0 || h < 0) 2234 return; 2235 if (x > visibleWidth() || y > visibleHeight()) 2236 return; 2237 2238 if (w > visibleWidth()) 2239 w = visibleWidth(); 2240 if (h > visibleHeight()) 2241 h = visibleHeight(); 2242 2243 if (d->clipped_viewport) { 2244 // Translate clipper() to viewport() 2245 x -= d->clipped_viewport->x(); 2246 y -= d->clipped_viewport->y(); 2247 } 2248 2249 vp->update(x, y, w, h); 2250 } 2251 2252 /*! 2253 \overload 2254 2255 Updates the contents in rectangle \a r 2256 */ 2257 void KtlQ3ScrollView::updateContents(const QRect &r) 2258 { 2259 updateContents(r.x(), r.y(), r.width(), r.height()); 2260 } 2261 2262 /*! 2263 \overload 2264 */ 2265 void KtlQ3ScrollView::updateContents() 2266 { 2267 updateContents(d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight()); 2268 } 2269 2270 /*! 2271 \overload 2272 2273 Repaints the contents of rectangle \a r. If \a erase is true the 2274 background is cleared using the background color. 2275 */ 2276 void KtlQ3ScrollView::repaintContents(const QRect &r, bool erase) 2277 { 2278 repaintContents(r.x(), r.y(), r.width(), r.height(), erase); 2279 } 2280 2281 /*! 2282 \overload 2283 2284 Repaints the contents. If \a erase is true the background is 2285 cleared using the background color. 2286 */ 2287 void KtlQ3ScrollView::repaintContents(bool erase) 2288 { 2289 repaintContents(d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight(), erase); 2290 } 2291 2292 /*! 2293 Calls repaint() on a rectangle defined by \a x, \a y, \a w, \a h, 2294 translated appropriately. If the rectangle is not visible, nothing 2295 is repainted. If \a erase is true the background is cleared using 2296 the background color. 2297 2298 \sa updateContents() 2299 */ 2300 void KtlQ3ScrollView::repaintContents(int x, int y, int w, int h, bool /*erase*/) 2301 { 2302 if (!isVisible() || !updatesEnabled()) 2303 return; 2304 2305 QWidget *vp = viewport(); 2306 2307 // Translate logical to clipper() 2308 x -= d->contentsX(); 2309 y -= d->contentsY(); 2310 2311 if (x < 0) { 2312 w += x; 2313 x = 0; 2314 } 2315 if (y < 0) { 2316 h += y; 2317 y = 0; 2318 } 2319 2320 if (w < 0 || h < 0) 2321 return; 2322 if (w > visibleWidth()) 2323 w = visibleWidth(); 2324 if (h > visibleHeight()) 2325 h = visibleHeight(); 2326 2327 if (d->clipped_viewport) { 2328 // Translate clipper() to viewport() 2329 x -= d->clipped_viewport->x(); 2330 y -= d->clipped_viewport->y(); 2331 } 2332 2333 vp->update(x, y, w, h); 2334 } 2335 2336 /*! 2337 For backward-compatibility only. It is easier to use 2338 drawContents(QPainter*,int,int,int,int). 2339 2340 The default implementation translates the painter appropriately 2341 and calls drawContents(QPainter*,int,int,int,int). See 2342 drawContents() for an explanation of the parameters \a p, \a 2343 offsetx, \a offsety, \a clipx, \a clipy, \a clipw and \a cliph. 2344 */ 2345 void KtlQ3ScrollView::drawContentsOffset(QPainter *p, int offsetx, int offsety, int clipx, int clipy, int clipw, int cliph) 2346 { 2347 p->translate(-offsetx, -offsety); 2348 drawContents(p, clipx, clipy, clipw, cliph); 2349 } 2350 2351 /*! 2352 \fn void KtlQ3ScrollView::drawContents(QPainter* p, int clipx, int clipy, int clipw, int cliph) 2353 2354 Reimplement this function if you are viewing a drawing area rather 2355 than a widget. 2356 2357 The function should draw the rectangle (\a clipx, \a clipy, \a 2358 clipw, \a cliph) of the contents using painter \a p. The clip 2359 rectangle is in the scrollview's coordinates. 2360 2361 For example: 2362 \snippet doc/src/snippets/code/src_qt3support_widgets_q3scrollview.cpp 4 2363 2364 The clip rectangle and translation of the painter \a p is already 2365 set appropriately. 2366 */ 2367 void KtlQ3ScrollView::drawContents(QPainter *, int, int, int, int) 2368 { 2369 } 2370 2371 /*! 2372 \reimp 2373 */ 2374 void KtlQ3ScrollView::frameChanged() 2375 { 2376 // // slight ugle-hack - the listview header needs readjusting when 2377 // // changing the frame 2378 // if (Q3ListView *lv = qobject_cast<Q3ListView *>(this)) 2379 // lv->triggerUpdate(); 2380 KtlQ3Frame::frameChanged(); 2381 updateScrollBars(); 2382 } 2383 2384 /*! 2385 Returns the viewport widget of the scrollview. This is the widget 2386 containing the contents widget or which is the drawing area. 2387 */ 2388 QWidget *KtlQ3ScrollView::viewport() const 2389 { 2390 if (d->clipped_viewport) 2391 return d->clipped_viewport; 2392 return d->viewport; 2393 } 2394 2395 /*! 2396 Returns the clipper widget. Contents in the scrollview are 2397 ultimately clipped to be inside the clipper widget. 2398 2399 You should not need to use this function. 2400 2401 \sa visibleWidth(), visibleHeight() 2402 */ 2403 QWidget *KtlQ3ScrollView::clipper() const 2404 { 2405 return d->viewport; 2406 } 2407 2408 /*! 2409 \property KtlQ3ScrollView::visibleWidth 2410 \brief the horizontal amount of the content that is visible 2411 */ 2412 int KtlQ3ScrollView::visibleWidth() const 2413 { 2414 return clipper()->width(); 2415 } 2416 2417 /*! 2418 \property KtlQ3ScrollView::visibleHeight 2419 \brief the vertical amount of the content that is visible 2420 */ 2421 int KtlQ3ScrollView::visibleHeight() const 2422 { 2423 return clipper()->height(); 2424 } 2425 2426 void KtlQ3ScrollView::changeFrameRect(const QRect &r) 2427 { 2428 QRect oldr = frameRect(); 2429 if (oldr != r) { 2430 QRect cr = contentsRect(); 2431 QRegion fr(frameRect()); 2432 fr = fr.subtracted(contentsRect()); 2433 setFrameRect(r); 2434 if (isVisible()) { 2435 cr = cr.intersected(contentsRect()); 2436 fr = fr.united(frameRect()); 2437 fr = fr.subtracted(cr); 2438 if (!fr.isEmpty()) 2439 update(fr); 2440 } 2441 } 2442 } 2443 2444 /*! 2445 Sets the margins around the scrolling area to \a left, \a top, \a 2446 right and \a bottom. This is useful for applications such as 2447 spreadsheets with "locked" rows and columns. The marginal space is 2448 \e inside the frameRect() and is left blank; reimplement 2449 drawFrame() or put widgets in the unused area. 2450 2451 By default all margins are zero. 2452 2453 \sa frameChanged() 2454 */ 2455 void KtlQ3ScrollView::setMargins(int left, int top, int right, int bottom) 2456 { 2457 if (left == d->l_marg && top == d->t_marg && right == d->r_marg && bottom == d->b_marg) 2458 return; 2459 2460 d->l_marg = left; 2461 d->t_marg = top; 2462 d->r_marg = right; 2463 d->b_marg = bottom; 2464 updateScrollBars(); 2465 } 2466 2467 /*! 2468 Returns the left margin. 2469 2470 \sa setMargins() 2471 */ 2472 int KtlQ3ScrollView::leftMargin() const 2473 { 2474 return d->l_marg; 2475 } 2476 2477 /*! 2478 Returns the top margin. 2479 2480 \sa setMargins() 2481 */ 2482 int KtlQ3ScrollView::topMargin() const 2483 { 2484 return d->t_marg; 2485 } 2486 2487 /*! 2488 Returns the right margin. 2489 2490 \sa setMargins() 2491 */ 2492 int KtlQ3ScrollView::rightMargin() const 2493 { 2494 return d->r_marg; 2495 } 2496 2497 /*! 2498 Returns the bottom margin. 2499 2500 \sa setMargins() 2501 */ 2502 int KtlQ3ScrollView::bottomMargin() const 2503 { 2504 return d->b_marg; 2505 } 2506 2507 /*! 2508 \reimp 2509 */ 2510 bool KtlQ3ScrollView::focusNextPrevChild(bool next) 2511 { 2512 // Makes sure that the new focus widget is on-screen, if 2513 // necessary by scrolling the scroll view. 2514 bool retval = KtlQ3Frame::focusNextPrevChild(next); 2515 if (retval) { 2516 QWidget *w = window()->focusWidget(); 2517 if (isAncestorOf(w)) { 2518 QSVChildRec *r = d->ancestorRec(w); 2519 if (r && (r->child == w || w->isVisibleTo(r->child))) { 2520 QPoint cp = r->child->mapToGlobal(QPoint(0, 0)); 2521 QPoint cr = w->mapToGlobal(QPoint(0, 0)) - cp; 2522 ensureVisible(r->x + cr.x() + w->width() / 2, r->y + cr.y() + w->height() / 2, w->width() / 2, w->height() / 2); 2523 } 2524 } 2525 } 2526 return retval; 2527 } 2528 2529 /*! 2530 When a large numbers of child widgets are in a scrollview, 2531 especially if they are close together, the scrolling performance 2532 can suffer greatly. If \a y is true the scrollview will use an 2533 extra widget to group child widgets. 2534 2535 Note that you may only call enableClipper() prior to adding 2536 widgets. 2537 */ 2538 void KtlQ3ScrollView::enableClipper(bool y) // note: this method as of 2018.11.30 is unused 2539 { 2540 if (!d->clipped_viewport == !y) 2541 return; 2542 if (d->children.count()) 2543 qFatal("May only call KtlQ3ScrollView::enableClipper() before adding widgets"); 2544 if (y) { 2545 d->clipped_viewport = new KtlQClipperWidget(clipper(), "qt_clipped_viewport", QFlag(d->flags)); 2546 d->clipped_viewport->setGeometry(-coord_limit / 2, -coord_limit / 2, coord_limit, coord_limit); 2547 // d->clipped_viewport->setBackgroundMode(d->viewport->backgroundMode()); 2548 d->clipped_viewport->setBackgroundRole(d->viewport->backgroundRole()); 2549 // d->viewport->setBackgroundMode(NoBackground); // no exposures for this // 2018.11.30 2550 d->viewport->setAttribute(Qt::WA_NoSystemBackground); // hope this is the correct replacement for above 2551 d->viewport->removeEventFilter(this); 2552 d->clipped_viewport->installEventFilter(this); 2553 d->clipped_viewport->show(); 2554 } else { 2555 delete d->clipped_viewport; 2556 d->clipped_viewport = nullptr; 2557 } 2558 } 2559 2560 /*! 2561 Sets the scrollview to have a static background if \a y is true, 2562 or a scrolling background if \a y is false. By default, the 2563 background is scrolling. 2564 2565 Be aware that this mode is quite slow, as a full repaint of the 2566 visible area has to be triggered on every contents move. 2567 2568 \sa hasStaticBackground() 2569 */ 2570 void KtlQ3ScrollView::setStaticBackground(bool y) 2571 { 2572 d->static_bg = y; 2573 } 2574 2575 /*! 2576 Returns true if KtlQ3ScrollView uses a static background; otherwise 2577 returns false. 2578 2579 \sa setStaticBackground() 2580 */ 2581 bool KtlQ3ScrollView::hasStaticBackground() const 2582 { 2583 return d->static_bg; 2584 } 2585 2586 /*! 2587 \overload 2588 2589 Returns the point \a p translated to a point on the viewport() 2590 widget. 2591 */ 2592 QPoint KtlQ3ScrollView::contentsToViewport(const QPoint &p) const 2593 { 2594 if (d->clipped_viewport) { 2595 return QPoint(p.x() - d->contentsX() - d->clipped_viewport->x(), p.y() - d->contentsY() - d->clipped_viewport->y()); 2596 } else { 2597 return QPoint(p.x() - d->contentsX(), p.y() - d->contentsY()); 2598 } 2599 } 2600 2601 /*! 2602 \overload 2603 2604 Returns the point on the viewport \a vp translated to a point in 2605 the contents. 2606 */ 2607 QPoint KtlQ3ScrollView::viewportToContents(const QPoint &vp) const 2608 { 2609 if (d->clipped_viewport) { 2610 return QPoint(vp.x() + d->contentsX() + d->clipped_viewport->x(), vp.y() + d->contentsY() + d->clipped_viewport->y()); 2611 } else { 2612 return QPoint(vp.x() + d->contentsX(), vp.y() + d->contentsY()); 2613 } 2614 } 2615 2616 /*! 2617 Translates a point (\a x, \a y) in the contents to a point (\a vx, 2618 \a vy) on the viewport() widget. 2619 */ 2620 void KtlQ3ScrollView::contentsToViewport(int x, int y, int &vx, int &vy) const 2621 { 2622 const QPoint v = contentsToViewport(QPoint(x, y)); 2623 vx = v.x(); 2624 vy = v.y(); 2625 } 2626 2627 /*! 2628 Translates a point (\a vx, \a vy) on the viewport() widget to a 2629 point (\a x, \a y) in the contents. 2630 */ 2631 void KtlQ3ScrollView::viewportToContents(int vx, int vy, int &x, int &y) const 2632 { 2633 const QPoint c = viewportToContents(QPoint(vx, vy)); 2634 x = c.x(); 2635 y = c.y(); 2636 } 2637 2638 /*! 2639 \reimp 2640 */ 2641 QSize KtlQ3ScrollView::sizeHint() const 2642 { 2643 if (d->use_cached_size_hint && d->cachedSizeHint.isValid()) 2644 return d->cachedSizeHint; 2645 2646 // constPolish(); // 2018.11.30 2647 ensurePolished(); 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->vMode == AlwaysOn) 2664 sz.setWidth(sz.width() + d->vbar->sizeHint().width()); 2665 if (d->hMode == AlwaysOn) 2666 sz.setHeight(sz.height() + d->hbar->sizeHint().height()); 2667 return sz.expandedTo(QSize(12 * h, 8 * h)).boundedTo(QSize(36 * h, 24 * h)); 2668 } 2669 2670 /*! 2671 \reimp 2672 */ 2673 QSize KtlQ3ScrollView::minimumSizeHint() const 2674 { 2675 int h = fontMetrics().height(); 2676 if (h < 10) 2677 h = 10; 2678 int f = 2 * frameWidth(); 2679 return QSize((6 * h) + f, (4 * h) + f); 2680 } 2681 2682 /*! 2683 \reimp 2684 2685 (Implemented to get rid of a compiler warning.) 2686 */ 2687 void KtlQ3ScrollView::drawContents(QPainter *) 2688 { 2689 } 2690 2691 #ifndef QT_NO_DRAGANDDROP 2692 2693 /*! 2694 \internal 2695 */ 2696 void KtlQ3ScrollView::startDragAutoScroll() 2697 { 2698 if (!d->autoscroll_timer.isActive()) { 2699 d->autoscroll_time = initialScrollTime; 2700 d->autoscroll_accel = initialScrollAccel; 2701 d->autoscroll_timer.start(d->autoscroll_time); 2702 } 2703 } 2704 2705 /*! 2706 \internal 2707 */ 2708 void KtlQ3ScrollView::stopDragAutoScroll() 2709 { 2710 d->autoscroll_timer.stop(); 2711 } 2712 2713 /*! 2714 \internal 2715 */ 2716 void KtlQ3ScrollView::doDragAutoScroll() 2717 { 2718 QPoint p = d->viewport->mapFromGlobal(QCursor::pos()); 2719 2720 if (d->autoscroll_accel-- <= 0 && d->autoscroll_time) { 2721 d->autoscroll_accel = initialScrollAccel; 2722 d->autoscroll_time--; 2723 d->autoscroll_timer.start(d->autoscroll_time); 2724 } 2725 int l = qMax(1, (initialScrollTime - d->autoscroll_time)); 2726 2727 int dx = 0, dy = 0; 2728 if (p.y() < autoscroll_margin) { 2729 dy = -l; 2730 } else if (p.y() > visibleHeight() - autoscroll_margin) { 2731 dy = +l; 2732 } 2733 if (p.x() < autoscroll_margin) { 2734 dx = -l; 2735 } else if (p.x() > visibleWidth() - autoscroll_margin) { 2736 dx = +l; 2737 } 2738 if (dx || dy) { 2739 scrollBy(dx, dy); 2740 } else { 2741 stopDragAutoScroll(); 2742 } 2743 } 2744 2745 /*! 2746 \property KtlQ3ScrollView::dragAutoScroll 2747 \brief whether autoscrolling in drag move events is enabled 2748 2749 If this property is set to true (the default), the KtlQ3ScrollView 2750 automatically scrolls the contents in drag move events if the user 2751 moves the cursor close to a border of the view. Of course this 2752 works only if the viewport accepts drops. Specifying false 2753 disables this autoscroll feature. 2754 */ 2755 2756 void KtlQ3ScrollView::setDragAutoScroll(bool b) 2757 { 2758 d->drag_autoscroll = b; 2759 } 2760 2761 bool KtlQ3ScrollView::dragAutoScroll() const 2762 { 2763 return d->drag_autoscroll; 2764 } 2765 2766 #endif // QT_NO_DRAGANDDROP 2767 2768 /*!\internal 2769 */ 2770 void KtlQ3ScrollView::setCachedSizeHint(const QSize &sh) const 2771 { 2772 if (isVisible() && !d->cachedSizeHint.isValid()) 2773 d->cachedSizeHint = sh; 2774 } 2775 2776 /*!\internal 2777 */ 2778 void KtlQ3ScrollView::disableSizeHintCaching() 2779 { 2780 d->use_cached_size_hint = false; 2781 } 2782 2783 /*!\internal 2784 */ 2785 QSize KtlQ3ScrollView::cachedSizeHint() const 2786 { 2787 return d->use_cached_size_hint ? d->cachedSizeHint : QSize(); 2788 } 2789 2790 // QT_END_NAMESPACE 2791 2792 #include "moc_ktlq3scrollview.cpp"