Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qscrollarea.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qscrollarea.h"
5#include "private/qscrollarea_p.h"
6
7#include "qscrollbar.h"
8#include "qlayout.h"
9#include "qstyle.h"
10#include "qapplication.h"
11#include "qvariant.h"
12#include "qdebug.h"
13#include "private/qapplication_p.h"
14#include "private/qlayoutengine_p.h"
15
17
104 : QAbstractScrollArea(*new QScrollAreaPrivate,parent)
105{
106 Q_D(QScrollArea);
107 d->viewport->setBackgroundRole(QPalette::NoRole);
108 d->vbar->setSingleStep(20);
109 d->hbar->setSingleStep(20);
110 d->layoutChildren();
111}
112
117 : QAbstractScrollArea(dd, parent)
118{
119 Q_D(QScrollArea);
120 d->viewport->setBackgroundRole(QPalette::NoRole);
121 d->vbar->setSingleStep(20);
122 d->hbar->setSingleStep(20);
123 d->layoutChildren();
124}
125
134
136{
137 Q_Q(QScrollArea);
138 Qt::LayoutDirection dir = q->layoutDirection();
139 QRect scrolled = QStyle::visualRect(dir, viewport->rect(), QRect(QPoint(-hbar->value(), -vbar->value()), widget->size()));
141 widget->move(widget->width() < viewport->width() ? aligned.x() : scrolled.x(),
142 widget->height() < viewport->height() ? aligned.y() : scrolled.y());
143}
144
146{
147 Q_Q(QScrollArea);
148 if (!widget)
149 return;
150 QSize p = viewport->size();
151 QSize m = q->maximumViewportSize();
152
155
156 if (resizable) {
158 QSize p_hfw = p.expandedTo(min).boundedTo(max);
159 int h = widget->heightForWidth(p_hfw.width());
160 // If the height we calculated requires a vertical scrollbar,
161 // then we need to constrain the width and calculate the height again,
162 // otherwise we end up flipping the scrollbar on and off all the time.
163 if (vbarpolicy == Qt::ScrollBarAsNeeded) {
164 int vbarWidth = vbar->sizeHint().width();
165 QSize m_hfw = m.expandedTo(min).boundedTo(max);
166 // is there any point in searching?
167 if (widget->heightForWidth(m_hfw.width() - vbarWidth) <= m.height()) {
168 while (h > m.height() && vbarWidth) {
169 --vbarWidth;
170 --m_hfw.rwidth();
171 h = widget->heightForWidth(m_hfw.width());
172 }
173 }
174 max = QSize(m_hfw.width(), qMax(m_hfw.height(), h));
175 }
176 min = QSize(p_hfw.width(), qMax(p_hfw.height(), h));
177 }
178 }
179
180 if ((resizable && m.expandedTo(min) == m && m.boundedTo(max) == m)
181 || (!resizable && m.expandedTo(widget->size()) == m))
182 p = m; // no scroll bars needed
183
184 if (resizable)
185 widget->resize(p.expandedTo(min).boundedTo(max));
186 QSize v = widget->size();
187
188 hbar->setRange(0, v.width() - p.width());
189 hbar->setPageStep(p.width());
190 vbar->setRange(0, v.height() - p.height());
191 vbar->setPageStep(p.height());
193
194}
195
203{
204 Q_D(const QScrollArea);
205 return d->widget;
206}
207
232{
233 Q_D(QScrollArea);
234 if (widget == d->widget || !widget)
235 return;
236
237 delete d->widget;
238 d->widget = nullptr;
239 d->hbar->setValue(0);
240 d->vbar->setValue(0);
241 if (widget->parentWidget() != d->viewport)
242 widget->setParent(d->viewport);
245 d->widget = widget;
246 d->widget->setAutoFillBackground(true);
248 d->widgetSize = QSize();
249 d->updateScrollBars();
250 d->widget->show();
251
252}
253
261{
262 Q_D(QScrollArea);
263 QWidget *w = d->widget;
264 d->widget = nullptr;
265 if (w)
266 w->setParent(nullptr);
267 return w;
268}
269
274{
275 Q_D(QScrollArea);
276 if (e->type() == QEvent::StyleChange || e->type() == QEvent::LayoutRequest) {
277 d->updateScrollBars();
278 }
279#ifdef QT_KEYPAD_NAVIGATION
280 else if (QApplicationPrivate::keypadNavigationEnabled()) {
281 if (e->type() == QEvent::Show)
282 QApplication::instance()->installEventFilter(this);
283 else if (e->type() == QEvent::Hide)
284 QApplication::instance()->removeEventFilter(this);
285 }
286#endif
287 return QAbstractScrollArea::event(e);
288}
289
290
295{
296 Q_D(QScrollArea);
297#ifdef QT_KEYPAD_NAVIGATION
298 if (d->widget && o != d->widget && e->type() == QEvent::FocusIn
299 && QApplicationPrivate::keypadNavigationEnabled()) {
300 if (o->isWidgetType())
301 ensureWidgetVisible(static_cast<QWidget *>(o));
302 }
303#endif
304 if (o == d->widget && e->type() == QEvent::Resize)
305 d->updateScrollBars();
306
307 return QAbstractScrollArea::eventFilter(o, e);
308}
309
314{
315 Q_D(QScrollArea);
316 d->updateScrollBars();
317
318}
319
320
324{
325 Q_D(QScrollArea);
326 if (!d->widget)
327 return;
328 d->updateWidgetPosition();
329}
330
331
347{
348 Q_D(const QScrollArea);
349 return d->resizable;
350}
351
353{
354 Q_D(QScrollArea);
355 d->resizable = resizable;
356 updateGeometry();
357 d->updateScrollBars();
358}
359
364{
365 Q_D(const QScrollArea);
366 int f = 2 * d->frameWidth;
367 QSize sz(f, f);
368 int h = fontMetrics().height();
369 if (d->widget) {
370 if (!d->widgetSize.isValid())
371 d->widgetSize = d->resizable ? d->widget->sizeHint() : d->widget->size();
372 sz += d->widgetSize;
373 } else {
374 sz += QSize(12 * h, 8 * h);
375 }
376 if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
377 sz.setWidth(sz.width() + d->vbar->sizeHint().width());
378 if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
379 sz.setHeight(sz.height() + d->hbar->sizeHint().height());
380 return sz.boundedTo(QSize(36 * h, 24 * h));
381}
382
387{
388 Q_D(const QScrollArea);
389 if (d->widget) {
390 return d->resizable ? d->widget->sizeHint() : d->widget->size();
391 }
392 const int h = fontMetrics().height();
393 return QSize(6 * h, 4 * h);
394}
395
396
401{
403 if (QWidget *fw = focusWidget())
405 return true;
406 }
407 return false;
408}
409
416void QScrollArea::ensureVisible(int x, int y, int xmargin, int ymargin)
417{
418 Q_D(QScrollArea);
419
420 int logicalX = QStyle::visualPos(layoutDirection(), d->viewport->rect(), QPoint(x, y)).x();
421
422 if (logicalX - xmargin < d->hbar->value()) {
423 d->hbar->setValue(qMax(0, logicalX - xmargin));
424 } else if (logicalX > d->hbar->value() + d->viewport->width() - xmargin) {
425 d->hbar->setValue(qMin(logicalX - d->viewport->width() + xmargin, d->hbar->maximum()));
426 }
427
428 if (y - ymargin < d->vbar->value()) {
429 d->vbar->setValue(qMax(0, y - ymargin));
430 } else if (y > d->vbar->value() + d->viewport->height() - ymargin) {
431 d->vbar->setValue(qMin(y - d->viewport->height() + ymargin, d->vbar->maximum()));
432 }
433}
434
446void QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin, int ymargin)
447{
448 Q_D(QScrollArea);
449
450 if (!d->widget->isAncestorOf(childWidget))
451 return;
452
453 const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
454 const QRect defaultMicroFocus =
455 childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
456 QRect focusRect = (microFocus != defaultMicroFocus)
457 ? QRect(childWidget->mapTo(d->widget, microFocus.topLeft()), microFocus.size())
458 : QRect(childWidget->mapTo(d->widget, QPoint(0,0)), childWidget->size());
459 const QRect visibleRect(-d->widget->pos(), d->viewport->size());
460
461 if (visibleRect.contains(focusRect))
462 return;
463
464 focusRect.adjust(-xmargin, -ymargin, xmargin, ymargin);
465
466 if (focusRect.width() > visibleRect.width())
467 d->hbar->setValue(focusRect.center().x() - d->viewport->width() / 2);
468 else if (focusRect.right() > visibleRect.right())
469 d->hbar->setValue(focusRect.right() - d->viewport->width() + 1);
470 else if (focusRect.left() < visibleRect.left())
471 d->hbar->setValue(focusRect.left());
472
473 if (focusRect.height() > visibleRect.height())
474 d->vbar->setValue(focusRect.center().y() - d->viewport->height() / 2);
475 else if (focusRect.bottom() > visibleRect.bottom())
476 d->vbar->setValue(focusRect.bottom() - d->viewport->height() + 1);
477 else if (focusRect.top() < visibleRect.top())
478 d->vbar->setValue(focusRect.top());
479}
480
481
501{
502 Q_D(QScrollArea);
503 d->alignment = alignment;
504 if (d->widget)
505 d->updateWidgetPosition();
506}
507
508Qt::Alignment QScrollArea::alignment() const
509{
510 Q_D(const QScrollArea);
511 return d->alignment;
512}
513
515
516#include "moc_qscrollarea.cpp"
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
\inmodule QtCore
Definition qcoreevent.h:45
@ StyleChange
Definition qcoreevent.h:136
@ LayoutRequest
Definition qcoreevent.h:112
@ FocusIn
Definition qcoreevent.h:66
Type type() const
Returns the event type.
Definition qcoreevent.h:304
virtual bool hasHeightForWidth() const
Returns true if this layout's preferred height depends on its width; otherwise returns false.
\inmodule QtCore
Definition qobject.h:103
void installEventFilter(QObject *filterObj)
Installs an event filter filterObj on this object.
Definition qobject.cpp:2339
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:548
QPointer< QWidget > widget
Qt::Alignment alignment
The QScrollArea class provides a scrolling view onto another widget.
Definition qscrollarea.h:17
bool event(QEvent *) override
\reimp
QSize sizeHint() const override
\reimp
~QScrollArea()
Destroys the scroll area and its child widget.
QWidget * widget() const
Returns the scroll area's widget, or \nullptr if there is none.
Qt::Alignment alignment
the alignment of the scroll area's widget
Definition qscrollarea.h:20
void resizeEvent(QResizeEvent *) override
\reimp
QScrollArea(QWidget *parent=nullptr)
Constructs an empty scroll area with the given parent.
void scrollContentsBy(int dx, int dy) override
\reimp
QSize viewportSizeHint() const override
\reimp
QWidget * takeWidget()
Removes the scroll area's widget, and passes ownership of the widget to the caller.
bool widgetResizable
whether the scroll area should resize the view widget
Definition qscrollarea.h:19
bool eventFilter(QObject *, QEvent *) override
\reimp
bool focusNextPrevChild(bool next) override
\reimp
void setWidget(QWidget *widget)
Sets the scroll area's widget.
void ensureVisible(int x, int y, int xmargin=50, int ymargin=50)
Scrolls the contents of the scroll area so that the point (x, y) is visible inside the region of the ...
void setAlignment(Qt::Alignment)
void setWidgetResizable(bool resizable)
void ensureWidgetVisible(QWidget *childWidget, int xmargin=50, int ymargin=50)
constexpr bool hasHeightForWidth() const noexcept
Returns true if the widget's preferred height depends on its width; otherwise returns false.
Definition qsizepolicy.h:81
\inmodule QtCore
Definition qsize.h:25
constexpr QSize boundedTo(const QSize &) const noexcept
Returns a size holding the minimum width and height of this size and the given otherSize.
Definition qsize.h:197
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition qsize.h:192
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
static QRect alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSize &size, const QRect &rectangle)
Returns a new rectangle of the specified size that is aligned to the given rectangle according to the...
Definition qstyle.cpp:2173
static QRect visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect)
Returns the given logicalRectangle converted to screen coordinates based on the specified direction.
Definition qstyle.cpp:2143
static QPoint visualPos(Qt::LayoutDirection direction, const QRect &boundingRect, const QPoint &logicalPos)
Returns the given logicalPosition converted to screen coordinates based on the specified direction.
Definition qstyle.cpp:2162
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setAutoFillBackground(bool enabled)
Definition qwidget.cpp:330
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
QLayout * layout() const
Returns the layout manager that is installed on this widget, or \nullptr if no layout manager is inst...
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
void move(int x, int y)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:880
QSizePolicy sizePolicy
the default layout behavior of the widget
Definition qwidget.h:119
virtual bool focusNextPrevChild(bool next)
Finds a new widget to give the keyboard focus to, as appropriate for Tab and Shift+Tab,...
Definition qwidget.cpp:6777
virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const
This method is only relevant for input widgets.
Definition qwidget.cpp:9913
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
QSize sizeHint
the recommended size for the widget
Definition qwidget.h:148
void resize(int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:883
QWidget * parentWidget() const
Returns the parent of this widget, or \nullptr if it does not have any parent widget.
Definition qwidget.h:904
QPointF mapTo(const QWidget *, const QPointF &) const
Translates the widget coordinate pos to the coordinate system of parent.
Definition qwidget.cpp:4197
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition qwidget.h:910
virtual int heightForWidth(int) const
Returns the preferred height for this widget, given the width w.
QOpenGLWidget * widget
[1]
uint alignment
fontMetrics
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
@ ImCursorRectangle
@ WA_Resized
Definition qnamespace.h:308
LayoutDirection
@ ScrollBarAlwaysOn
@ ScrollBarAsNeeded
Q_WIDGETS_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy)
Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QSize &sizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy, Qt::Alignment align)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLfloat GLfloat f
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
Int aligned(Int v, Int byteAlign)
QString dir
[11]
view viewport() -> scroll(dx, dy, deviceRect)