Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qstackedlayout.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qstackedlayout.h"
5#include "qlayout_p.h"
6
7#include <qlist.h>
8#include "private/qwidget_p.h"
9#include "private/qlayoutengine_p.h"
10
11#include <QtCore/qpointer.h>
12
13#include <memory>
14
16
18{
19 Q_DECLARE_PUBLIC(QStackedLayout)
20public:
22 QLayoutItem* replaceAt(int index, QLayoutItem *newitem) override;
23 QList<QLayoutItem *> list;
24 int index;
26};
27
29{
30 Q_Q(QStackedLayout);
31 if (idx < 0 || idx >= list.size() || !newitem)
32 return nullptr;
33 QWidget *wdg = newitem->widget();
34 if (Q_UNLIKELY(!wdg)) {
35 qWarning("QStackedLayout::replaceAt: Only widgets can be added");
36 return nullptr;
37 }
38 QLayoutItem *orgitem = list.at(idx);
39 list.replace(idx, newitem);
40 if (idx == index)
41 q->setCurrentIndex(index);
42 return orgitem;
43}
44
128
139
145 : QLayout(*new QStackedLayoutPrivate, parentLayout, nullptr)
146{
147}
148
158
169{
170 Q_D(QStackedLayout);
171 return insertWidget(d->list.size(), widget);
172}
173
189{
190 Q_D(QStackedLayout);
192 index = qMin(index, d->list.size());
193 if (index < 0)
194 index = d->list.size();
196 d->list.insert(index, wi);
197 invalidate();
198 if (d->index < 0) {
200 } else {
201 if (index <= d->index)
202 ++d->index;
203 if (d->stackingMode == StackOne)
204 widget->hide();
205 widget->lower();
206 }
207 return index;
208}
209
214{
215 Q_D(const QStackedLayout);
216 return d->list.value(index);
217}
218
219// Code that enables proper handling of the case that takeAt() is
220// called somewhere inside QObject destructor (can't call hide()
221// on the object then)
222static bool qt_wasDeleted(const QWidget *w)
223{
224 return QObjectPrivate::get(w)->wasDeleted;
225}
226
227
232{
233 Q_D(QStackedLayout);
234 if (index <0 || index >= d->list.size())
235 return nullptr;
236 QLayoutItem *item = d->list.takeAt(index);
237 if (index == d->index) {
238 d->index = -1;
239 if ( d->list.size() > 0 ) {
240 int newIndex = (index == d->list.size()) ? index-1 : index;
241 setCurrentIndex(newIndex);
242 } else {
244 }
245 } else if (index < d->index) {
246 --d->index;
247 }
249 if (item->widget() && !qt_wasDeleted(item->widget()))
250 item->widget()->hide();
251 return item;
252}
253
263{
264 Q_D(QStackedLayout);
265 QWidget *prev = currentWidget();
267 if (!next || next == prev)
268 return;
269
270 bool reenableUpdates = false;
272
273 if (parent && parent->updatesEnabled()) {
274 reenableUpdates = true;
275 parent->setUpdatesEnabled(false);
276 }
277
278 QPointer<QWidget> fw = parent ? parent->window()->focusWidget() : nullptr;
279 const bool focusWasOnOldPage = fw && (prev && prev->isAncestorOf(fw));
280
281 if (prev) {
282 prev->clearFocus();
283 if (d->stackingMode == StackOne)
284 prev->hide();
285 }
286
287 d->index = index;
288 next->raise();
289 next->show();
290
291 // try to move focus onto the incoming widget if focus
292 // was somewhere on the outgoing widget.
293
294 if (parent) {
295 if (focusWasOnOldPage) {
296 // look for the best focus widget we can find
297 if (QWidget *nfw = next->focusWidget())
298 nfw->setFocus();
299 else {
300 // second best: first child widget in the focus chain
301 if (QWidget *i = fw) {
302 while ((i = i->nextInFocusChain()) != fw) {
303 if (((i->focusPolicy() & Qt::TabFocus) == Qt::TabFocus)
304 && !i->focusProxy() && i->isVisibleTo(next) && i->isEnabled()
305 && next->isAncestorOf(i)) {
306 i->setFocus();
307 break;
308 }
309 }
310 // third best: incoming widget
311 if (i == fw )
312 next->setFocus();
313 }
314 }
315 }
316 }
317 if (reenableUpdates)
318 parent->setUpdatesEnabled(true);
320}
321
323{
324 Q_D(const QStackedLayout);
325 return d->index;
326}
327
328
338{
339 int index = indexOf(widget);
340 if (Q_UNLIKELY(index == -1)) {
341 qWarning("QStackedLayout::setCurrentWidget: Widget %p not contained in stack", widget);
342 return;
343 }
345}
346
347
355{
356 Q_D(const QStackedLayout);
357 return d->index >= 0 ? d->list.at(d->index)->widget() : nullptr;
358}
359
367{
368 Q_D(const QStackedLayout);
369 if (index < 0 || index >= d->list.size())
370 return nullptr;
371 return d->list.at(index)->widget();
372}
373
381{
382 Q_D(const QStackedLayout);
383 return d->list.size();
384}
385
386
391{
392 std::unique_ptr<QLayoutItem> guard(item);
393 QWidget *widget = item->widget();
394 if (Q_UNLIKELY(!widget)) {
395 qWarning("QStackedLayout::addItem: Only widgets can be added");
396 return;
397 }
399}
400
405{
406 Q_D(const QStackedLayout);
407 QSize s(0, 0);
408 int n = d->list.size();
409
410 for (int i = 0; i < n; ++i)
411 if (QWidget *widget = d->list.at(i)->widget()) {
412 QSize ws(widget->sizeHint());
413 if (widget->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
414 ws.setWidth(0);
415 if (widget->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
416 ws.setHeight(0);
417 s = s.expandedTo(ws);
418 }
419 return s;
420}
421
426{
427 Q_D(const QStackedLayout);
428 QSize s(0, 0);
429 int n = d->list.size();
430
431 for (int i = 0; i < n; ++i)
432 if (QWidget *widget = d->list.at(i)->widget())
433 s = s.expandedTo(qSmartMinSize(widget));
434 return s;
435}
436
441{
442 Q_D(QStackedLayout);
443 switch (d->stackingMode) {
444 case StackOne:
446 widget->setGeometry(rect);
447 break;
448 case StackAll:
449 if (const int n = d->list.size())
450 for (int i = 0; i < n; ++i)
451 if (QWidget *widget = d->list.at(i)->widget())
452 widget->setGeometry(rect);
453 break;
454 }
455}
456
461{
462 const int n = count();
463
464 for (int i = 0; i < n; ++i) {
465 if (QLayoutItem *item = itemAt(i)) {
466 if (item->hasHeightForWidth())
467 return true;
468 }
469 }
470 return false;
471}
472
477{
478 const int n = count();
479
480 int hfw = 0;
481 for (int i = 0; i < n; ++i) {
482 if (QLayoutItem *item = itemAt(i)) {
483 if (QWidget *w = item->widget())
484 /*
485 Note: Does not query the layout item, but bypasses it and asks the widget
486 directly. This is consistent with how QStackedLayout::sizeHint() is
487 implemented. This also avoids an issue where QWidgetItem::heightForWidth()
488 returns -1 if the widget is hidden.
489 */
490 hfw = qMax(hfw, w->heightForWidth(width));
491 }
492 }
493 hfw = qMax(hfw, minimumSize().height());
494 return hfw;
495}
496
524{
525 Q_D(const QStackedLayout);
526 return d->stackingMode;
527}
528
530{
531 Q_D(QStackedLayout);
532 if (d->stackingMode == stackingMode)
533 return;
534 d->stackingMode = stackingMode;
535
536 const int n = d->list.size();
537 if (n == 0)
538 return;
539
540 switch (d->stackingMode) {
541 case StackOne:
542 if (const int idx = currentIndex())
543 for (int i = 0; i < n; ++i)
544 if (QWidget *widget = d->list.at(i)->widget())
545 widget->setVisible(i == idx);
546 break;
547 case StackAll: { // Turn overlay on: Make sure all widgets are the same size
549 if (const QWidget *widget = currentWidget())
550 geometry = widget->geometry();
551 for (int i = 0; i < n; ++i)
552 if (QWidget *widget = d->list.at(i)->widget()) {
553 if (!geometry.isNull())
554 widget->setGeometry(geometry);
555 widget->setVisible(true);
556 }
557 }
558 break;
559 }
560}
561
563
564#include "moc_qstackedlayout.cpp"
void hide()
Hides the item (items are visible by default).
The QLayoutItem class provides an abstract item that a QLayout manipulates.
Definition qlayoutitem.h:25
virtual QWidget * widget() const
If this item manages a QWidget, returns that widget.
static QWidgetItem * createWidgetItem(const QLayout *layout, QWidget *widget)
Definition qlayout.cpp:148
The QLayout class is the base class of geometry managers.
Definition qlayout.h:26
QRect geometry() const override
\reimp
Definition qlayout.cpp:460
void addChildWidget(QWidget *w)
This function is called from addWidget() functions in subclasses to add w as a managed widget of a la...
Definition qlayout.cpp:837
void invalidate() override
\reimp
Definition qlayout.cpp:469
QWidget * parentWidget() const
Returns the parent widget of this layout, or \nullptr if this layout is not installed on any widget.
Definition qlayout.cpp:399
virtual int indexOf(const QWidget *) const
Searches for widget widget in this layout (not including child layouts).
Definition qlayout.cpp:1177
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void replace(qsizetype i, parameter_type t)
Definition qlist.h:543
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:164
\inmodule QtCore
Definition qsize.h:25
QLayoutItem * replaceAt(int index, QLayoutItem *newitem) override
QList< QLayoutItem * > list
QStackedLayout::StackingMode stackingMode
The QStackedLayout class provides a stack of widgets where only one widget is visible at a time.
void widgetRemoved(int index)
This signal is emitted whenever a widget is removed from the layout.
StackingMode stackingMode
determines the way visibility of child widgets are handled.
void setCurrentIndex(int index)
int heightForWidth(int width) const override
\reimp
QSize minimumSize() const override
\reimp
void setStackingMode(StackingMode stackingMode)
QLayoutItem * itemAt(int) const override
\reimp
int insertWidget(int index, QWidget *w)
Inserts the given widget at the given index in this QStackedLayout.
bool hasHeightForWidth() const override
\reimp
void currentChanged(int index)
This signal is emitted whenever the current widget in the layout changes.
int currentIndex
the index position of the widget that is visible
int addWidget(QWidget *w)
Adds the given widget to the end of this layout and returns the index position of the widget.
void setGeometry(const QRect &rect) override
\reimp
void setCurrentWidget(QWidget *w)
Sets the current widget to be the specified widget.
QWidget * currentWidget() const
Returns the current widget, or \nullptr if there are no widgets in this layout.
~QStackedLayout()
Destroys this QStackedLayout.
QStackedLayout()
Constructs a QStackedLayout with no parent.
void addItem(QLayoutItem *item) override
\reimp
QLayoutItem * takeAt(int) override
\reimp
QSize sizeHint() const override
\reimp
int count() const override
the number of widgets contained in the layout
The QWidgetItem class is a layout item that represents a widget.
Definition qlayoutitem.h:86
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void clearFocus()
Takes keyboard input focus from the widget.
Definition qwidget.cpp:6683
void hide()
Hides the widget.
Definition qwidget.cpp:8135
bool isAncestorOf(const QWidget *child) const
Returns true if this widget is a parent, (or grandparent and so on to any level), of the given child,...
Definition qwidget.cpp:8822
QOpenGLWidget * widget
[1]
qDeleteAll(list.begin(), list.end())
rect
[4]
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
@ TabFocus
Definition qnamespace.h:108
#define Q_UNLIKELY(x)
Q_WIDGETS_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy)
#define qWarning
Definition qlogging.h:166
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLuint index
[2]
GLint GLsizei width
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
static bool qt_wasDeleted(const QWidget *w)
#define emit
QObject::connect nullptr
QGraphicsItem * item