1 /*
2  *  stackedwidgets.h  -  classes implementing stacked widgets
3  *  Program:  kalarm
4  *  SPDX-FileCopyrightText: 2008-2021 David Jarvie <djarvie@kde.org>
5  *
6  *  SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #pragma once
10 
11 #include <QStackedWidget>
12 #include <QVector>
13 #include <QScrollArea>
14 class QDialog;
15 
16 /**
17  *  A QStackedWidget, whose size hint is that of the largest widget in the stack.
18  *
19  *  @author David Jarvie <djarvie@kde.org>
20  */
21 class StackedWidget : public QStackedWidget
22 {
23 public:
24     /** Constructor.
25      *  @param parent The parent object of this widget.
26      */
27     explicit StackedWidget(QWidget* parent = nullptr)
QStackedWidget(parent)28           : QStackedWidget(parent)  {}
29     QSize sizeHint() const override;
30     QSize minimumSizeHint() const override;
31 };
32 
33 template <class T> class StackedGroupT;
34 
35 /**
36  *  A widget contained in a stack, whose minimum size hint is that of the largest
37  *  widget in the stack. This class works together with StackedGroup.
38  *
39  *  @author David Jarvie <djarvie@kde.org>
40  */
41 template <class T>
42 class StackedGroupWidgetT : public T
43 {
44 public:
45     /** Constructor.
46      *  @param parent The parent object of this widget.
47      *  @param group The stack group to insert this widget into.
48      */
49     explicit StackedGroupWidgetT(StackedGroupT<T>* group, QWidget* parent = nullptr)
T(parent)50           : T(parent),
51             mGroup(group)
52     {
53         mGroup->addWidget(this);
54     }
~StackedGroupWidgetT()55     ~StackedGroupWidgetT() override  { mGroup->removeWidget(this); }
sizeHint()56     QSize sizeHint() const         override { return minimumSizeHint(); }
minimumSizeHint()57     QSize minimumSizeHint() const  override { return mGroup->minimumSizeHint(); }
58 
59 private:
60     StackedGroupT<T>* mGroup;
61 };
62 
63 /**
64  *  A group of stacked widgets whose minimum size hints are all equal to the
65  *  largest widget's minimum size hint.
66  *
67  *  It is inherited from QObject solely to ensure automatic deletion when its
68  *  parent widget is deleted.
69  *
70  *  @author David Jarvie <djarvie@kde.org>
71  */
72 template <class T>
73 class StackedGroupT : public QObject
74 {
75 public:
QObject(parent)76     explicit StackedGroupT(QObject* parent = nullptr) : QObject(parent) {}
addWidget(StackedGroupWidgetT<T> * w)77     void  addWidget(StackedGroupWidgetT<T>* w)     { mWidgets += w; }
removeWidget(StackedGroupWidgetT<T> * w)78     void  removeWidget(StackedGroupWidgetT<T>* w)  { mWidgets.removeAll(w); }
79     virtual QSize minimumSizeHint() const;
80 
81 protected:
82     QVector<StackedGroupWidgetT<T>*> mWidgets;
83 };
84 
85 template <class T>
minimumSizeHint()86 QSize StackedGroupT<T>::minimumSizeHint() const
87 {
88     QSize sz;
89     for (const auto& w : mWidgets)
90         sz = sz.expandedTo(w->T::minimumSizeHint());
91     return sz;
92 }
93 
94 /** A non-scrollable stacked widget. */
95 using StackedGroupWidget = StackedGroupWidgetT<QWidget>;
96 /** A group of non-scrollable stacked widgets. */
97 using StackedGroup = StackedGroupT<QWidget>;
98 
99 
100 class StackedScrollGroup;
101 
102 /**
103  *  A stacked widget which becomes scrollable when necessary to fit the height
104  *  of the screen.
105  *
106  *  @author David Jarvie <djarvie@kde.org>
107  */
108 class StackedScrollWidget : public StackedGroupWidgetT<QScrollArea>
109 {
110 public:
111     explicit StackedScrollWidget(StackedScrollGroup* group, QWidget* parent = nullptr);
widget()112     QWidget* widget() const  { return viewport()->findChild<QWidget*>(); }
113 };
114 
115 /**
116  *  A group of stacked widgets which individually become scrollable when necessary
117  *  to fit the height of the screen.
118  *
119  *  @author David Jarvie <djarvie@kde.org>
120  */
121 class StackedScrollGroup : public StackedGroupT<QScrollArea>
122 {
123 public:
124     StackedScrollGroup(QDialog*, QObject* tabParent);
125     QSize    minimumSizeHint() const override;
heightReduction()126     int      heightReduction() const { return mHeightReduction; }
127     QSize    adjustSize(bool force = false);
setSized()128     void     setSized()              { mSized = true; }
sized()129     bool     sized() const           { return mSized; }
130 
131 private:
132     QSize    maxMinimumSizeHint() const;
133 
134     QDialog* mDialog;
135     int      mMinHeight {-1};
136     int      mHeightReduction {0};
137     bool     mSized {false};
138 };
139 
140 
141 // vim: et sw=4:
142