File indexing completed on 2024-11-10 04:42:40
0001 /* 0002 * stackedwidgets.cpp - classes implementing stacked widgets 0003 * Program: kalarm 0004 * SPDX-FileCopyrightText: 2008-2022 David Jarvie <djarvie@kde.org> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "stackedwidgets.h" 0010 0011 #include "desktop.h" 0012 #include "kalarm_debug.h" 0013 0014 #include <QDialog> 0015 #include <QStyle> 0016 0017 0018 QSize StackedWidget::sizeHint() const 0019 { 0020 QSize sz; 0021 for (int i = count(); --i >= 0; ) 0022 sz = sz.expandedTo(widget(i)->sizeHint()); 0023 return sz; 0024 } 0025 0026 QSize StackedWidget::minimumSizeHint() const 0027 { 0028 QSize sz; 0029 for (int i = count(); --i >= 0; ) 0030 sz = sz.expandedTo(widget(i)->minimumSizeHint()); 0031 return sz; 0032 } 0033 0034 0035 /****************************************************************************** 0036 */ 0037 StackedScrollWidget::StackedScrollWidget(StackedScrollGroup* group, QWidget* parent) 0038 : StackedGroupWidgetT<QScrollArea>(group, parent) 0039 { 0040 setFrameStyle(QFrame::NoFrame); 0041 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0042 setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); 0043 setWidgetResizable(true); 0044 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); 0045 } 0046 0047 StackedScrollGroup::StackedScrollGroup(QDialog* dlg, QWidget* container) 0048 : StackedGroupT<QScrollArea>(container) 0049 , mDialog(dlg) 0050 { 0051 } 0052 0053 /****************************************************************************** 0054 * Return the minimum size for the tabs, constrained if necessary to a height 0055 * that fits the screen. 0056 * In order to make the widget containing the tabs take the correct size, the 0057 * value returned is actually the minimum size of the largest tab. 0058 * Otherwise, only the currently visible tab would be taken into account with 0059 * the result that the dialog would initially be displayed too small. 0060 */ 0061 QSize StackedScrollGroup::minimumSizeHint() const 0062 { 0063 const QSize s = maxMinimumSizeHint(); 0064 if (!s.isEmpty() && mMinHeight > 0 && mMinHeight < s.height()) 0065 return {s.width() + mWidgets[0]->style()->pixelMetric(QStyle::PM_ScrollBarExtent), mMinHeight}; 0066 return s; 0067 } 0068 0069 /****************************************************************************** 0070 * Return the maximum minimum size for any instance. 0071 */ 0072 QSize StackedScrollGroup::maxMinimumSizeHint() const 0073 { 0074 QSize sz; 0075 for (const auto& sw : mWidgets) 0076 { 0077 QWidget* w = static_cast<StackedScrollWidget*>(sw)->widget(); 0078 if (!w) 0079 return {}; 0080 const QSize s = w->minimumSizeHint(); 0081 if (!s.isValid()) 0082 return {}; 0083 sz = sz.expandedTo(s); 0084 } 0085 return sz; 0086 } 0087 0088 /****************************************************************************** 0089 * Return the minimum size for the dialog. 0090 * If the minimum size would be too high to fit the desktop, the tab contents 0091 * are made scrollable. 0092 */ 0093 QSize StackedScrollGroup::adjustSize(bool force) 0094 { 0095 if (force) 0096 mSized = false; 0097 if (mSized) 0098 return {}; 0099 0100 // Cancel any previous minimum height and set the height of the 0101 // scroll widget contents widgets. 0102 mMinHeight = -1; 0103 mHeightReduction = 0; 0104 const QSize s = maxMinimumSizeHint(); 0105 if (s.isEmpty()) 0106 return {}; 0107 const int maxTabHeight = s.height(); 0108 for (auto& sw : mWidgets) 0109 { 0110 sw->setMinimumHeight(maxTabHeight); 0111 QWidget* w = static_cast<StackedScrollWidget*>(sw)->widget(); 0112 if (w) 0113 w->resize(s); 0114 } 0115 for (QWidget* w = mWidgets.at(0)->parentWidget(); w && w != mDialog; w = w->parentWidget()) 0116 { 0117 w->setMinimumHeight(0); 0118 w->adjustSize(); 0119 } 0120 mDialog->setMinimumHeight(0); 0121 0122 int decoration = mDialog->frameGeometry().height() - mDialog->geometry().height(); 0123 if (!decoration) 0124 { 0125 // On X11 at least, the window decoration height may not be 0126 // available, so use a guess of 25 pixels. 0127 decoration = 25; 0128 } 0129 const int desk = Desktop::workArea().height(); 0130 // There is no stored size, or the deferral group is visible. 0131 // Allow the tab contents to be scrolled vertically if that is necessary 0132 // to avoid the dialog exceeding the screen height. 0133 QSize dlgsize = mDialog->QDialog::minimumSizeHint(); 0134 const int y = dlgsize.height() + decoration - desk; 0135 if (y > 0) 0136 { 0137 mHeightReduction = y; 0138 mMinHeight = maxTabHeight - y; 0139 qCDebug(KALARM_LOG) << "StackedScrollGroup::adjustSize: Scrolling: max tab height=" << maxTabHeight << ", reduction=" << mHeightReduction << "-> min tab height=" << mMinHeight; 0140 if (mMinHeight > 0) 0141 { 0142 for (auto& sw : mWidgets) 0143 { 0144 sw->setMinimumHeight(mMinHeight); 0145 sw->resize(QSize(sw->width(), mMinHeight)); 0146 } 0147 } 0148 mSized = true; 0149 QSize sz = mWidgets.at(0)->parentWidget()->sizeHint(); 0150 if (sz.height() < mMinHeight) 0151 sz.setHeight(mMinHeight); 0152 mWidgets.at(0)->parentWidget()->resize(sz); 0153 for (QWidget* w = mWidgets.at(0)->parentWidget(); w && w != mDialog; w = w->parentWidget()) 0154 w->setMinimumHeight(qMin(w->minimumSizeHint().height(), w->sizeHint().height())); 0155 dlgsize.setHeight(dlgsize.height() - mHeightReduction); 0156 sz = mDialog->QDialog::minimumSizeHint(); 0157 if (sz.height() > dlgsize.height()) 0158 dlgsize.setHeight(sz.height()); 0159 mDialog->setMinimumHeight(dlgsize.height()); 0160 } 0161 mSized = true; 0162 mDialog->resize(dlgsize); 0163 return s; 0164 } 0165 0166 // vim: et sw=4: