File indexing completed on 2024-06-23 05:14:18
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 utils/scrollarea.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 <config-kleopatra.h> 0013 0014 #include "scrollarea.h" 0015 0016 #include <QApplication> 0017 #include <QResizeEvent> 0018 #include <QScreen> 0019 #include <QScrollBar> 0020 #include <QVBoxLayout> 0021 0022 using namespace Kleo; 0023 0024 ScrollArea::ScrollArea(QWidget *parent) 0025 : QScrollArea{parent} 0026 { 0027 auto w = new QWidget; 0028 w->setObjectName(QLatin1StringView("scrollarea_widget")); 0029 new QVBoxLayout{w}; 0030 setWidget(w); 0031 setWidgetResizable(true); 0032 w->installEventFilter(this); 0033 0034 connect(qApp, &QApplication::focusChanged, this, [this](QWidget *old, QWidget *now) { 0035 Q_UNUSED(old); 0036 ensureWidgetVisible(now); 0037 }); 0038 } 0039 0040 ScrollArea::~ScrollArea() 0041 { 0042 widget()->removeEventFilter(this); 0043 } 0044 0045 QSize ScrollArea::minimumSizeHint() const 0046 { 0047 const int fw = frameWidth(); 0048 QSize sz{2 * fw, 2 * fw}; 0049 sz += {widget()->minimumSizeHint().width(), 0}; 0050 if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0051 sz.setWidth(sz.width() + verticalScrollBar()->sizeHint().width()); 0052 } 0053 if (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0054 sz.setHeight(sz.height() + horizontalScrollBar()->sizeHint().height()); 0055 } 0056 return QScrollArea::minimumSizeHint().expandedTo(sz); 0057 } 0058 0059 QSize ScrollArea::sizeHint() const 0060 { 0061 const int fw = frameWidth(); 0062 QSize sz{2 * fw, 2 * fw}; 0063 sz += viewportSizeHint(); 0064 if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0065 sz.setWidth(sz.width() + verticalScrollBar()->sizeHint().width()); 0066 } 0067 if (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { 0068 sz.setHeight(sz.height() + horizontalScrollBar()->sizeHint().height()); 0069 } 0070 sz = QScrollArea::sizeHint().expandedTo(sz); 0071 return sz; 0072 } 0073 0074 void ScrollArea::adjustSizeOfWindowBy(const QSize &extent) 0075 { 0076 if (auto w = window()) { 0077 const auto currentSize = w->size(); 0078 // we limit the automatic size adjustment to 2/3 of the screen's size 0079 const auto maxWindowSize = screen()->geometry().size() * 2 / 3; 0080 const auto newWindowSize = currentSize.expandedTo((currentSize + extent).boundedTo(maxWindowSize)); 0081 if (newWindowSize != currentSize) { 0082 w->resize(newWindowSize); 0083 } 0084 } 0085 } 0086 0087 bool ScrollArea::eventFilter(QObject *obj, QEvent *ev) 0088 { 0089 if (ev->type() == QEvent::Resize && obj == widget() && sizeAdjustPolicy() == AdjustToContents) { 0090 const auto *const event = static_cast<QResizeEvent *>(ev); 0091 if (event->size().height() > event->oldSize().height()) { 0092 const auto currentViewportHeight = viewport()->height(); 0093 const auto wantedViewportHeight = event->size().height(); 0094 const auto wantedAdditionalHeight = wantedViewportHeight - currentViewportHeight; 0095 if (wantedAdditionalHeight > 0) { 0096 adjustSizeOfWindowBy(QSize{0, wantedAdditionalHeight}); 0097 } 0098 } 0099 } 0100 return QScrollArea::eventFilter(obj, ev); 0101 } 0102 0103 #include "moc_scrollarea.cpp"