116QScrollArea::QScrollArea(QScrollAreaPrivate &dd, QWidget *parent)
117 : QAbstractScrollArea(dd, parent)
120 d->viewport->setBackgroundRole(QPalette::NoRole);
121 const auto singleStep = d->defaultSingleStep();
122 d->vbar->setSingleStep(singleStep);
123 d->hbar->setSingleStep(singleStep);
136void QScrollAreaPrivate::updateWidgetPosition()
139 Qt::LayoutDirection dir = q->layoutDirection();
140 QRect scrolled = QStyle::visualRect(dir, viewport->rect(), QRect(QPoint(-hbar->value(), -vbar->value()), widget->size()));
141 QRect aligned = QStyle::alignedRect(dir, alignment, widget->size(), viewport->rect());
142 widget->move(widget->width() < viewport->width() ? aligned.x() : scrolled.x(),
143 widget->height() < viewport->height() ? aligned.y() : scrolled.y());
146void QScrollAreaPrivate::updateScrollBars()
151 QSize p = viewport->size();
152 QSize m = q->maximumViewportSize();
154 QSize min = qSmartMinSize(widget);
155 QSize max = qSmartMaxSize(widget);
158 if ((widget->layout() ? widget->layout()->hasHeightForWidth() : widget->sizePolicy().hasHeightForWidth())) {
159 QSize p_hfw = p.expandedTo(min).boundedTo(max);
160 int h = widget->heightForWidth(p_hfw.width());
164 if (vbarpolicy == Qt::ScrollBarAsNeeded) {
165 int vbarWidth = vbar->sizeHint().width();
166 QSize m_hfw = m.expandedTo(min).boundedTo(max);
168 if (widget->heightForWidth(m_hfw.width() - vbarWidth) <= m.height()) {
169 while (h > m.height() && vbarWidth) {
172 h = widget->heightForWidth(m_hfw.width());
175 max = QSize(m_hfw.width(), qMax(m_hfw.height(), h));
177 min = QSize(p_hfw.width(), qMax(p_hfw.height(), h));
181 if ((resizable && m.expandedTo(min) == m && m.boundedTo(max) == m)
182 || (!resizable && m.expandedTo(widget->size()) == m))
186 widget->resize(p.expandedTo(min).boundedTo(max));
187 QSize v = widget->size();
189 hbar->setRange(0, v.width() - p.width());
190 hbar->setPageStep(p.width());
191 vbar->setRange(0, v.height() - p.height());
192 vbar->setPageStep(p.height());
193 updateWidgetPosition();
232void QScrollArea::setWidget(QWidget *widget)
235 if (widget == d->widget || !widget)
240 d->hbar->setValue(0);
241 d->vbar->setValue(0);
242 if (widget->parentWidget() != d->viewport)
243 widget->setParent(d->viewport);
244 if (!widget->testAttribute(Qt::WA_Resized))
245 widget->resize(widget->sizeHint());
247 d->widget->setAutoFillBackground(
true);
248 widget->installEventFilter(
this);
249 d->widgetSize = QSize();
250 d->updateScrollBars();
274bool QScrollArea::event(QEvent *e)
277 if (e->type() == QEvent::StyleChange || e->type() == QEvent::LayoutRequest) {
278 d->updateScrollBars();
280#ifdef QT_KEYPAD_NAVIGATION
281 else if (QApplicationPrivate::keypadNavigationEnabled()) {
282 if (e->type() == QEvent::Show)
283 QApplication::instance()->installEventFilter(
this);
284 else if (e->type() == QEvent::Hide)
285 QApplication::instance()->removeEventFilter(
this);
288 return QAbstractScrollArea::event(e);
295bool QScrollArea::eventFilter(QObject *o, QEvent *e)
298#ifdef QT_KEYPAD_NAVIGATION
299 if (d->widget && o != d->widget && e->type() == QEvent::FocusIn
300 && QApplicationPrivate::keypadNavigationEnabled()) {
301 if (o->isWidgetType())
302 ensureWidgetVisible(
static_cast<QWidget *>(o));
305 if (o == d->widget && e->type() == QEvent::Resize)
306 d->updateScrollBars();
308 return QAbstractScrollArea::eventFilter(o, e);
364QSize QScrollArea::sizeHint()
const
366 Q_D(
const QScrollArea);
367 int f = 2 * d->frameWidth;
369 int h = fontMetrics().height();
371 if (!d->widgetSize.isValid())
372 d->widgetSize = d->resizable ? d->widget->sizeHint() : d->widget->size();
375 sz += QSize(12 * h, 8 * h);
377 if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
378 sz.setWidth(sz.width() + d->vbar->sizeHint().width());
379 if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
380 sz.setHeight(sz.height() + d->hbar->sizeHint().height());
381 return sz.boundedTo(QSize(36 * h, 24 * h));
417void QScrollArea::ensureVisible(
int x,
int y,
int xmargin,
int ymargin)
421 int logicalX = QStyle::visualPos(layoutDirection(), d->viewport->rect(), QPoint(x, y)).x();
423 if (logicalX - xmargin < d->hbar->value()) {
424 d->hbar->setValue(qMax(0, logicalX - xmargin));
425 }
else if (logicalX > d->hbar->value() + d->viewport->width() - xmargin) {
426 d->hbar->setValue(qMin(logicalX - d->viewport->width() + xmargin, d->hbar->maximum()));
429 if (y - ymargin < d->vbar->value()) {
430 d->vbar->setValue(qMax(0, y - ymargin));
431 }
else if (y > d->vbar->value() + d->viewport->height() - ymargin) {
432 d->vbar->setValue(qMin(y - d->viewport->height() + ymargin, d->vbar->maximum()));
447void QScrollArea::ensureWidgetVisible(QWidget *childWidget,
int xmargin,
int ymargin)
451 if (!d->widget->isAncestorOf(childWidget))
454 const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
455 const QRect defaultMicroFocus =
456 childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
457 QRect focusRect = (microFocus != defaultMicroFocus)
458 ? QRect(childWidget->mapTo(d->widget, microFocus.topLeft()), microFocus.size())
459 : QRect(childWidget->mapTo(d->widget, QPoint(0,0)), childWidget->size());
460 const QRect visibleRect(-d->widget->pos(), d->viewport->size());
462 if (visibleRect.contains(focusRect))
465 focusRect.adjust(-xmargin, -ymargin, xmargin, ymargin);
467 if (focusRect.width() > visibleRect.width())
468 d->hbar->setValue(focusRect.center().x() - d->viewport->width() / 2);
469 else if (focusRect.right() > visibleRect.right())
470 d->hbar->setValue(focusRect.right() - d->viewport->width() + 1);
471 else if (focusRect.left() < visibleRect.left())
472 d->hbar->setValue(focusRect.left());
474 if (focusRect.height() > visibleRect.height())
475 d->vbar->setValue(focusRect.center().y() - d->viewport->height() / 2);
476 else if (focusRect.bottom() > visibleRect.bottom())
477 d->vbar->setValue(focusRect.bottom() - d->viewport->height() + 1);
478 else if (focusRect.top() < visibleRect.top())
479 d->vbar->setValue(focusRect.top());