File indexing completed on 2024-11-10 04:42:40
0001 /* 0002 * stackedwidgets.h - 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 #pragma once 0010 0011 #include <QList> 0012 #include <QScrollArea> 0013 #include <QStackedWidget> 0014 class QDialog; 0015 0016 /** 0017 * A QStackedWidget, whose size hint is that of the largest widget in the stack. 0018 * 0019 * @author David Jarvie <djarvie@kde.org> 0020 */ 0021 class StackedWidget : public QStackedWidget 0022 { 0023 public: 0024 /** Constructor. 0025 * @param parent The parent object of this widget. 0026 */ 0027 explicit StackedWidget(QWidget* parent = nullptr) 0028 : QStackedWidget(parent) {} 0029 QSize sizeHint() const override; 0030 QSize minimumSizeHint() const override; 0031 }; 0032 0033 template <class T> class StackedGroupT; 0034 0035 /** 0036 * A widget contained in a stack, whose minimum size hint is that of the largest 0037 * widget in the stack. This class works together with StackedGroup. 0038 * 0039 * Do not use this class for widgets contained in a QStackedWidget or 0040 * StackedWidget. 0041 * 0042 * @tparam T The base class for this widget. Must be derived from QWidget. 0043 0044 * @author David Jarvie <djarvie@kde.org> 0045 */ 0046 template <class T> 0047 class StackedGroupWidgetT : public T 0048 { 0049 public: 0050 /** Constructor. 0051 * @param group The stack group to insert this widget into. 0052 * @param parent The parent object of this widget. 0053 */ 0054 explicit StackedGroupWidgetT(StackedGroupT<T>* group, QWidget* parent = nullptr) 0055 : T(parent), 0056 mGroup(group) 0057 { 0058 mGroup->addWidget(this); 0059 } 0060 ~StackedGroupWidgetT() override { mGroup->removeWidget(this); } 0061 QSize sizeHint() const override { return minimumSizeHint(); } 0062 QSize minimumSizeHint() const override { return mGroup->minimumSizeHint(); } 0063 0064 private: 0065 StackedGroupT<T>* mGroup; 0066 }; 0067 0068 /** 0069 * A group of stacked widgets whose minimum size hints are all equal to the 0070 * largest widget's minimum size hint. Use this alongside the widgets' container, 0071 * e.g. QTabWidget. 0072 * 0073 * It is inherited from QObject solely to ensure automatic deletion when its 0074 * parent widget is deleted. 0075 * 0076 * @author David Jarvie <djarvie@kde.org> 0077 */ 0078 template <class T> 0079 class StackedGroupT : public QObject 0080 { 0081 public: 0082 /** Constructor. 0083 * @param container The parent widget. This should be set to the container 0084 * for the stacked widgets, which will ensure that this 0085 * object is deleted when the container is deleted. 0086 */ 0087 explicit StackedGroupT(QWidget* container) : QObject(container) {} 0088 0089 void addWidget(StackedGroupWidgetT<T>* w) { mWidgets += w; } 0090 void removeWidget(StackedGroupWidgetT<T>* w) { mWidgets.removeAll(w); } 0091 virtual QSize minimumSizeHint() const; 0092 0093 protected: 0094 QList<StackedGroupWidgetT<T>*> mWidgets; 0095 }; 0096 0097 template <class T> 0098 QSize StackedGroupT<T>::minimumSizeHint() const 0099 { 0100 QSize sz; 0101 for (const auto& w : mWidgets) 0102 sz = sz.expandedTo(w->T::minimumSizeHint()); 0103 return sz; 0104 } 0105 0106 /** A non-scrollable stacked QWidget. */ 0107 using StackedGroupWidget = StackedGroupWidgetT<QWidget>; 0108 /** A group of non-scrollable stacked widgets which are each derived from QWidget. */ 0109 using StackedGroup = StackedGroupT<QWidget>; 0110 0111 0112 class StackedScrollGroup; 0113 0114 /** 0115 * A stacked QScrollArea widget, which becomes scrollable when necessary to 0116 * fit the height of the screen. 0117 * 0118 * Do not use this class for widgets contained in a QStackedWidget or 0119 * StackedWidget. 0120 * 0121 * @author David Jarvie <djarvie@kde.org> 0122 */ 0123 class StackedScrollWidget : public StackedGroupWidgetT<QScrollArea> 0124 { 0125 public: 0126 explicit StackedScrollWidget(StackedScrollGroup* group, QWidget* parent = nullptr); 0127 QWidget* widget() const { return viewport()->findChild<QWidget*>(); } 0128 }; 0129 0130 /** 0131 * A group of stacked StackedScrollWidget widgets, which individually become 0132 * scrollable when necessary to fit the height of the screen. 0133 * 0134 * @author David Jarvie <djarvie@kde.org> 0135 */ 0136 class StackedScrollGroup : public StackedGroupT<QScrollArea> 0137 { 0138 public: 0139 /** Constructor. 0140 * @param dialog The dialog which contains the widgets. 0141 * @param container The parent widget. This should be set to the container 0142 * for the stacked widgets, which will ensure that this 0143 * object is deleted when the container is deleted. 0144 */ 0145 StackedScrollGroup(QDialog* dialog, QWidget* container); 0146 0147 /** Return the minimum size for the tabs, constrained if necessary to a height 0148 * that fits the dialog into the screen. The dialog height must have been 0149 * previously evaluated by calling adjustSize(). 0150 */ 0151 QSize minimumSizeHint() const override; 0152 0153 /** Return the reduction in dialog height which adjustSize() performed in 0154 * order to fit the dialog to the desktop. 0155 */ 0156 int heightReduction() const { return mHeightReduction; } 0157 0158 /** Set the minimum height for the dialog, so as to accommodate the tabs, 0159 * but constrained to fit the desktop. If necessary, the tab contents are 0160 * made scrollable. 0161 * @param force If false, this method will only evaluate and set the 0162 * minimum dialog height the first time it is called. Set 0163 * true to force re-evaluation. 0164 * @return The minimum size for the dialog, or null if the size was not evaluated. 0165 */ 0166 QSize adjustSize(bool force = false); 0167 0168 /** Prevent adjustSize(false) from evaluating or setting the dialog height. */ 0169 void setSized() { mSized = true; } 0170 0171 /** Return whether the dialog size has already been set, e.g. by adjustSize(). */ 0172 bool sized() const { return mSized; } 0173 0174 private: 0175 QSize maxMinimumSizeHint() const; 0176 0177 QDialog* mDialog; 0178 int mMinHeight {-1}; 0179 int mHeightReduction {0}; 0180 bool mSized {false}; 0181 }; 0182 0183 // vim: et sw=4: