📄 q3scrollview.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the Qt3Support module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qwidget.h"#ifndef QT_NO_SCROLLVIEW#include "qscrollbar.h"#include "qpainter.h"#include "qpixmap.h"#include "qcursor.h"#include "q3scrollview.h"#include "q3ptrdict.h"#include "qapplication.h"#include "qtimer.h"#include "qstyle.h"#include "q3ptrlist.h"#include "qevent.h"#include "q3listview.h"#ifdef Q_WS_MAC# include "private/qt_mac_p.h"#endifusing namespace Qt;static const int coord_limit = 4000;static const int autoscroll_margin = 16;static const int initialScrollTime = 30;static const int initialScrollAccel = 5;struct QSVChildRec { QSVChildRec(QWidget* c, int xx, int yy) : child(c), x(xx), y(yy) { } void hideOrShow(Q3ScrollView* sv, QWidget* clipped_viewport); void moveTo(Q3ScrollView* sv, int xx, int yy, QWidget* clipped_viewport) { if (x != xx || y != yy) { x = xx; y = yy; hideOrShow(sv,clipped_viewport); } } QWidget* child; int x, y;};void QSVChildRec::hideOrShow(Q3ScrollView* sv, QWidget* clipped_viewport){ if (clipped_viewport) { if (x+child->width() < sv->contentsX()+clipped_viewport->x() || x > sv->contentsX()+clipped_viewport->width() || y+child->height() < sv->contentsY()+clipped_viewport->y() || y > sv->contentsY()+clipped_viewport->height()) { child->move(clipped_viewport->width(), clipped_viewport->height()); } else { child->move(x-sv->contentsX()-clipped_viewport->x(), y-sv->contentsY()-clipped_viewport->y()); } } else { child->move(x-sv->contentsX(), y-sv->contentsY()); }}class QAbstractScrollAreaWidget : public QWidget{ Q_OBJECTpublic: QAbstractScrollAreaWidget(Q3ScrollView* parent=0, const char* name=0, Qt::WindowFlags f = 0) : QWidget(parent, name, f) { setAutoFillBackground(true); }};class QClipperWidget : public QWidget{ Q_OBJECTpublic: QClipperWidget(QWidget * parent=0, const char * name=0, Qt::WindowFlags f=0) : QWidget (parent,name,f) {}};#include "q3scrollview.moc"class Q3ScrollViewData {public: Q3ScrollViewData(Q3ScrollView* parent, int vpwflags) : hbar(new QScrollBar(Qt::Horizontal, parent, "qt_hbar")), vbar(new QScrollBar(Qt::Vertical, parent, "qt_vbar")), viewport(new QAbstractScrollAreaWidget(parent, "qt_viewport", QFlag(vpwflags))), clipped_viewport(0), flags(vpwflags), vx(0), vy(0), vwidth(1), vheight(1),#ifndef QT_NO_DRAGANDDROP autoscroll_timer(parent, "scrollview autoscroll timer"), drag_autoscroll(true),#endif scrollbar_timer(parent, "scrollview scrollbar timer"), inresize(false), use_cached_size_hint(true) { l_marg = r_marg = t_marg = b_marg = 0; viewport->polish(); vMode = Q3ScrollView::Auto; hMode = Q3ScrollView::Auto; corner = 0; vbar->setSteps(20, 1/*set later*/); hbar->setSteps(20, 1/*set later*/); policy = Q3ScrollView::Default; signal_choke = false; static_bg = false; fake_scroll = false; hbarPressed = false; vbarPressed = false; hbar->setLayoutDirection(Qt::LeftToRight); } ~Q3ScrollViewData(); QSVChildRec* rec(QWidget* w) { return childDict.find(w); } QSVChildRec* ancestorRec(QWidget* w); QSVChildRec* addChildRec(QWidget* w, int x, int y) { QSVChildRec *r = new QSVChildRec(w,x,y); children.append(r); childDict.insert(w, r); return r; } void deleteChildRec(QSVChildRec* r) { childDict.remove(r->child); children.removeRef(r); delete r; } void hideOrShowAll(Q3ScrollView* sv, bool isScroll = false); void moveAllBy(int dx, int dy); bool anyVisibleChildren(); void autoMove(Q3ScrollView* sv); void autoResize(Q3ScrollView* sv); void autoResizeHint(Q3ScrollView* sv); void viewportResized(int w, int h); QScrollBar* hbar; QScrollBar* vbar; bool hbarPressed; bool vbarPressed; QAbstractScrollAreaWidget* viewport; QClipperWidget* clipped_viewport; int flags; Q3PtrList<QSVChildRec> children; Q3PtrDict<QSVChildRec> childDict; QWidget* corner; int vx, vy, vwidth, vheight; // for drawContents-style usage int l_marg, r_marg, t_marg, b_marg; Q3ScrollView::ResizePolicy policy; Q3ScrollView::ScrollBarMode vMode; Q3ScrollView::ScrollBarMode hMode;#ifndef QT_NO_DRAGANDDROP QPoint cpDragStart; QTimer autoscroll_timer; int autoscroll_time; int autoscroll_accel; bool drag_autoscroll;#endif QTimer scrollbar_timer; uint static_bg : 1; uint fake_scroll : 1; // This variable allows ensureVisible to move the contents then // update both the sliders. Otherwise, updating the sliders would // cause two image scrolls, creating ugly flashing. // uint signal_choke : 1; // This variables indicates in updateScrollBars() that we are // in a resizeEvent() and thus don't want to flash scroll bars uint inresize : 1; uint use_cached_size_hint : 1; QSize cachedSizeHint; inline int contentsX() const { return -vx; } inline int contentsY() const { return -vy; } inline int contentsWidth() const { return vwidth; }};inline Q3ScrollViewData::~Q3ScrollViewData(){ children.setAutoDelete(true);}QSVChildRec* Q3ScrollViewData::ancestorRec(QWidget* w){ if (clipped_viewport) { while (w->parentWidget() != clipped_viewport) { w = w->parentWidget(); if (!w) return 0; } } else { while (w->parentWidget() != viewport) { w = w->parentWidget(); if (!w) return 0; } } return rec(w);}void Q3ScrollViewData::hideOrShowAll(Q3ScrollView* sv, bool isScroll){ if (!clipped_viewport) return; 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()) { // clipped_viewport still covers viewport if(static_bg) clipped_viewport->repaint(true); else if ((!isScroll && !clipped_viewport->testAttribute(Qt::WA_StaticContents)) || static_bg) clipped_viewport->update(); } else { // Re-center int nx = (viewport->width() - clipped_viewport->width()) / 2; int ny = (viewport->height() - clipped_viewport->height()) / 2; clipped_viewport->move(nx,ny); clipped_viewport->update(); } for (QSVChildRec *r = children.first(); r; r=children.next()) { r->hideOrShow(sv, clipped_viewport); }}void Q3ScrollViewData::moveAllBy(int dx, int dy){ if (clipped_viewport && !static_bg) { clipped_viewport->move(clipped_viewport->x()+dx, clipped_viewport->y()+dy); } else { for (QSVChildRec *r = children.first(); r; r=children.next()) { r->child->move(r->child->x()+dx,r->child->y()+dy); } if (static_bg) viewport->repaint(true); }}bool Q3ScrollViewData::anyVisibleChildren(){ for (QSVChildRec *r = children.first(); r; r=children.next()) { if (r->child->isVisible()) return true; } return false;}void Q3ScrollViewData::autoMove(Q3ScrollView* sv){ if (policy == Q3ScrollView::AutoOne) { QSVChildRec* r = children.first(); if (r) sv->setContentsPos(-r->child->x(),-r->child->y()); }}void Q3ScrollViewData::autoResize(Q3ScrollView* sv){ if (policy == Q3ScrollView::AutoOne) { QSVChildRec* r = children.first(); if (r) sv->resizeContents(r->child->width(),r->child->height()); }}void Q3ScrollViewData::autoResizeHint(Q3ScrollView* sv){ if (policy == Q3ScrollView::AutoOne) { QSVChildRec* r = children.first(); if (r) { QSize s = r->child->sizeHint(); if (s.isValid()) r->child->resize(s); } } else if (policy == Q3ScrollView::AutoOneFit) { QSVChildRec* r = children.first(); if (r) { QSize sh = r->child->sizeHint(); sh = sh.boundedTo(r->child->maximumSize()); sv->resizeContents(sh.width(), sh.height()); } }}void Q3ScrollViewData::viewportResized(int w, int h){ if (policy == Q3ScrollView::AutoOneFit) { QSVChildRec* r = children.first(); if (r) { QSize sh = r->child->sizeHint(); sh = sh.boundedTo(r->child->maximumSize()); r->child->resize(QMAX(w,sh.width()), QMAX(h,sh.height())); } }}/*! \class Q3ScrollView qscrollview.h \brief The Q3ScrollView widget provides a scrolling area with on-demand scroll bars. \compat The Q3ScrollView is a large canvas - potentially larger than the coordinate system normally supported by the underlying window system. This is important because it is quite easy to go beyond these limitations (e.g. many web pages are more than 32000 pixels high). Additionally, the Q3ScrollView can have QWidgets positioned on it that scroll around with the drawn content. These sub-widgets can also have positions outside the normal coordinate range (but they are still limited in size). To provide content for the widget, inherit from Q3ScrollView, reimplement drawContents() and use resizeContents() to set the size of the viewed area. Use addChild() and moveChild() to position widgets on the view. To use Q3ScrollView effectively it is important to understand its widget structure in the three styles of use: a single large child widget, a large panning area with some widgets and a large panning area with many widgets. \section1 Using One Big Widget \img qscrollview-vp2.png The first, simplest usage of Q3ScrollView (depicted above), is appropriate for scrolling areas that are never more than about 4000 pixels in either dimension (this is about the maximum reliable size on X11 servers). In this usage, you just make one large child in the Q3ScrollView. The child should be a child of the viewport() of the scrollview and be added with addChild(): \code Q3ScrollView* sv = new Q3ScrollView(...); QWidget *widget = new QWidget(sv->viewport()); QVBoxLayout *layout = new QVBoxLayout(widget); addChild(widget); \endcode You can go on to add arbitrary child widgets to the single child in the scrollview as you would with any widget: \code QLabel* child1 = new QLabel("CHILD", widget); QLabel* child2 = new QLabel("CHILD", widget); QLabel* child3 = new QLabel("CHILD", widget); layout->addWidget(child1); layout->addWidget(child2); layout->addWidget(child3); ... \endcode Here the Q3ScrollView has four children: the viewport(), the verticalScrollBar(), the horizontalScrollBar() and a small cornerWidget(). The viewport() has one child: the QWidget. The QWidget has the three QLabel objects as child widgets. When the view is scrolled, the QWidget is moved; its children move with it as child widgets normally do. \section1 Using a Very Big View with Some Widgets \img qscrollview-vp.png The second usage of Q3ScrollView (depicted above) is appropriate when few, if any, widgets are on a very large scrolling area that is potentially larger than 4000 pixels in either dimension. In this usage you call resizeContents() to set the size of the area and reimplement drawContents() to paint the contents. You may also add some widgets by making them children of the viewport() and adding them with addChild() (this is the same as the process for the single large widget in the previous example): \code Q3ScrollView* sv = new Q3ScrollView(...); QLabel* child1 = new QLabel("CHILD", sv->viewport()); sv->addChild(child1); QLabel* child2 = new QLabel("CHILD", sv->viewport()); sv->addChild(child2); QLabel* child3 = new QLabel("CHILD", sv->viewport()); sv->addChild(child3); \endcode Here, the Q3ScrollView has the same four children: the viewport(), the verticalScrollBar(), the horizontalScrollBar() and a small cornerWidget(). The viewport() has the three QLabel objects as child widgets. When the view is scrolled, the scrollview moves the child widgets individually. \section1 Using a Very Big View with Many Widgets \img qscrollview-cl.png The final usage of Q3ScrollView (depicted above) is appropriate when many widgets are on a very large scrolling area that is potentially larger than 4000 pixels in either dimension. In this usage you call resizeContents() to set the size of the area and reimplement drawContents() to paint the contents. You then call enableClipper(true) and add widgets, again by making them children of the viewport(), and adding them with addChild(): \code Q3ScrollView* sv = new Q3ScrollView(...); sv->enableClipper(true); QLabel* child1 = new QLabel("CHILD", sv->viewport()); sv->addChild(child1); QLabel* child2 = new QLabel("CHILD", sv->viewport()); sv->addChild(child2); QLabel* child3 = new QLabel("CHILD", sv->viewport()); sv->addChild(child3); \endcode Here, the Q3ScrollView has four children: the clipper() (not the viewport() this time), the verticalScrollBar(), the horizontalScrollBar() and a small cornerWidget(). The clipper() has one child: the viewport(). The viewport() has the same three
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -