File indexing completed on 2025-01-05 04:55:46
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 ui/adjustingscrollarea.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB 0006 SPDX-FileCopyrightText: 2022 g10 Code GmbH 0007 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include "adjustingscrollarea.h" 0013 0014 #include <QApplication> 0015 #include <QResizeEvent> 0016 #include <QScreen> 0017 #include <QScrollBar> 0018 #include <QVBoxLayout> 0019 0020 using namespace Kleo; 0021 0022 AdjustingScrollArea::AdjustingScrollArea(QWidget *parent) 0023 : QScrollArea{parent} 0024 { 0025 auto w = new QWidget; 0026 w->setObjectName(QLatin1StringView("scrollarea_widget")); 0027 new QVBoxLayout{w}; 0028 setWidget(w); 0029 setWidgetResizable(true); 0030 w->installEventFilter(this); 0031 0032 connect(qApp, &QApplication::focusChanged, this, [this](QWidget *old, QWidget *now) { 0033 Q_UNUSED(old); 0034 ensureWidgetVisible(now); 0035 }); 0036 } 0037 0038 AdjustingScrollArea::~AdjustingScrollArea() 0039 { 0040 widget()->removeEventFilter(this); 0041 } 0042 0043 QSize AdjustingScrollArea::minimumSizeHint() const 0044 { 0045 const int fw = frameWidth(); 0046 QSize sz{2 * fw, 2 * fw}; 0047 sz += {widget()->minimumSizeHint().width(), 0}; 0048 if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0049 sz.setWidth(sz.width() + verticalScrollBar()->sizeHint().width()); 0050 } 0051 if (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0052 sz.setHeight(sz.height() + horizontalScrollBar()->sizeHint().height()); 0053 } 0054 return QScrollArea::minimumSizeHint().expandedTo(sz); 0055 } 0056 0057 QSize AdjustingScrollArea::sizeHint() const 0058 { 0059 const int fw = frameWidth(); 0060 QSize sz{2 * fw, 2 * fw}; 0061 sz += viewportSizeHint(); 0062 if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0063 sz.setWidth(sz.width() + verticalScrollBar()->sizeHint().width()); 0064 } 0065 if (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0066 sz.setHeight(sz.height() + horizontalScrollBar()->sizeHint().height()); 0067 } 0068 sz = QScrollArea::sizeHint().expandedTo(sz); 0069 return sz; 0070 } 0071 0072 void AdjustingScrollArea::adjustSizeOfWindowBy(const QSize &extent) 0073 { 0074 if (auto w = window()) { 0075 const auto currentSize = w->size(); 0076 // we limit the automatic size adjustment to 2/3 of the screen's size 0077 const auto maxWindowSize = screen()->geometry().size() * 2 / 3; 0078 const auto newWindowSize = currentSize.expandedTo((currentSize + extent).boundedTo(maxWindowSize)); 0079 if (newWindowSize != currentSize) { 0080 w->resize(newWindowSize); 0081 } 0082 } 0083 } 0084 0085 bool AdjustingScrollArea::eventFilter(QObject *obj, QEvent *ev) 0086 { 0087 if (ev->type() == QEvent::Resize && obj == widget() && sizeAdjustPolicy() == AdjustToContents) { 0088 const auto *const event = static_cast<QResizeEvent *>(ev); 0089 if (event->size().height() > event->oldSize().height()) { 0090 const auto currentViewportHeight = viewport()->height(); 0091 const auto wantedViewportHeight = event->size().height(); 0092 const auto wantedAdditionalHeight = wantedViewportHeight - currentViewportHeight; 0093 if (wantedAdditionalHeight > 0) { 0094 adjustSizeOfWindowBy(QSize{0, wantedAdditionalHeight}); 0095 } 0096 } 0097 } 0098 return QScrollArea::eventFilter(obj, ev); 0099 }