maxLibQt
OverlayStackLayout.cpp
Go to the documentation of this file.
1 /*
2  OverlayStackLayout
3  https://github.com/mpaperno/maxLibQt
4 
5  COPYRIGHT: (c)2019 Maxim Paperno; All Rights Reserved.
6  Contact: http://www.WorldDesign.com/contact
7 
8  LICENSE:
9 
10  Commercial License Usage
11  Licensees holding valid commercial licenses may use this file in
12  accordance with the terms contained in a written agreement between
13  you and the copyright holder.
14 
15  GNU General Public License Usage
16  Alternatively, this file may be used under the terms of the GNU
17  General Public License as published by the Free Software Foundation,
18  either version 3 of the License, or (at your option) any later version.
19 
20  This program is distributed in the hope that it will be useful,
21  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  GNU General Public License for more details.
24 
25  A copy of the GNU General Public License is available at <http://www.gnu.org/licenses/>.
26 */
27 
28 #include "OverlayStackLayout.h"
29 #include <QVariant>
30 #include <QWidget>
31 
32 namespace {
33 static const char offsetProperty[15] {"positionOffset"};
34 }
35 
37  QStackedLayout(parent)
38 {
40 }
41 
43  QStackedLayout(parentLayout)
44 {
46 }
47 
48 int OverlayStackLayout::insertWidget(int index, QWidget *widget, Qt::Alignment alignment)
49 {
50  const int ret = insertWidget(index, widget);
51  if (ret > -1)
53  return ret;
54 }
55 
56 int OverlayStackLayout::insertWidget(int index, QWidget *widget, Qt::Alignment alignment, const QPoint &offset)
57 {
58  const int ret = insertWidget(index, widget, alignment);
59  if (ret > -1)
60  setOffset(widget, offset);
61  return ret;
62 }
63 
64 void OverlayStackLayout::setOffset(QWidget *widget, const QPoint &offset) const
65 {
66  if (widget->property(offsetProperty).isValid() && widget->property(offsetProperty).toPoint() == offset)
67  return;
68  widget->setProperty(offsetProperty, offset);
69  doLayout();
70 }
71 
73 {
74  if (QWidget *w = qobject_cast<QWidget*>(sender()))
75  setOffset(w, offset);
76 }
77 
79 {
80  if (QWidget *w = qobject_cast<QWidget*>(sender()))
81  setAlignment(w, align);
82 }
83 
85 {
86  if (mode == stackingMode())
87  return;
89  // resetting the mode to StackAll messes with our layout
90  if (mode == StackAll)
91  doLayout();
92 }
93 
95 {
96  if (geo == geometry())
97  return;
99  doLayout();
100 }
101 
102 void OverlayStackLayout::doLayout() const
103 {
104  const int n = count();
105  if (!n)
106  return;
107  for (int i=0; i < n; ++i) {
108  QWidget *w = nullptr;
109  if (QLayoutItem *item = itemAt(i))
110  w = item->widget();
111  if (!w)
112  continue;
113 
114  // available geometry for widgets, use size based on layout attribute
116  // widget's desired size
117  const QSize wSize = w->sizeHint().expandedTo(w->minimumSize()).boundedTo(w->maximumSize());
118  QRect wRect(rect.topLeft(), wSize); // default widget position and size
119  QPoint offset(0, 0); // position offset
120  if (w->property(offsetProperty).isValid())
121  offset = w->property(offsetProperty).toPoint();
122 
123  // expand or constrain to full width?
124  if ((w->sizePolicy().expandingDirections() & Qt::Horizontal) || wRect.width() > rect.width() - offset.x())
125  wRect.setWidth(rect.width() - offset.x());
126 
127  // expand or constrain to full height?
128  if ((w->sizePolicy().expandingDirections() & Qt::Vertical) || wRect.height() > rect.height() - offset.y())
129  wRect.setHeight(rect.height() - offset.y());
130 
131  // Adjust position for alignment
132  const Qt::Alignment align = itemAt(i)->alignment();
133  if (rect.width() > wRect.width() - offset.x()) {
134  switch (align & Qt::AlignHorizontal_Mask) {
135  case Qt::AlignHCenter:
136  wRect.moveLeft(rect.x() + (rect.width() - wRect.width()) / 2);
137  break;
138  case Qt::AlignRight:
139  wRect.moveRight(rect.right());
140  break;
141  case Qt::AlignLeft:
142  default:
143  wRect.moveLeft(rect.left());
144  break;
145  }
146  }
147  if (rect.height() > wRect.height() - offset.y()) {
148  switch (align & Qt::AlignVertical_Mask) {
149  case Qt::AlignVCenter:
150  wRect.moveTop(rect.y() + (rect.height() - wRect.height()) / 2);
151  break;
152  case Qt::AlignBottom:
153  wRect.moveBottom(rect.bottom());
154  break;
155  case Qt::AlignTop:
156  default:
157  wRect.moveTop(rect.top());
158  break;
159  }
160  }
161  // adjust for user-defined offset
162  if (!offset.isNull())
163  wRect.moveTopLeft(wRect.topLeft() + offset);
164 
165  // Set position and size of the widget.
166  w->setGeometry(wRect);
167  // Honor the stacking attribute
169  w->raise();
170  }
171 }
172 
173 #include "moc_OverlayStackLayout.cpp"
int right() const const
QObject * sender() const const
virtual QWidget * widget()
int height() const const
int x() const const
int y() const const
void setSenderAlignment(Qt::Alignment align)
Convenience slot to set the layout alignment on a signal from a QWidget::sender().
void setOffset(QWidget *widget, const QPoint &offset) const
Set the layout position offset coordinates for given widget.
typedef Alignment
virtual QRect geometry() const const override
bool testAttribute(Qt::WidgetAttribute attribute) const const
QVariant property(const char *name) const const
int top() const const
int left() const const
QRect contentsRect() const const
void raise()
void setStackingMode(StackingMode mode)
Re-implemented (shadowing) QStackedLayout::setStackingMode() to ensure proper child visibility.
void setSenderOffset(const QPoint &offset) const
Convenience slot to set the layout position offset on a signal from a QWidget::sender().
int insertWidget(int index, QWidget *widget, Qt::Alignment alignment)
Insert widget into the stack at index position with specified alignment.
QStackedLayout::StackingMode stackingMode() const const
WA_LayoutOnEntireRect
bool setAlignment(QWidget *w, Qt::Alignment alignment)
void setGeometry(const QRect &geo) override
int width() const const
int bottom() const const
QPoint topLeft() const const
virtual QLayoutItem * itemAt(int index) const const override
Qt::Alignment alignment() const const
bool isValid() const const
QPoint toPoint() const const
bool setProperty(const char *name, const QVariant &value)
Horizontal
OverlayStackLayout(QWidget *parent=nullptr)
Constructs a new OverlayStackLayout with the optional parent widget.
virtual void setGeometry(const QRect &r) override
void setGeometry(int x, int y, int w, int h)
virtual int count() const const override