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
qquickstacklayout.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
5
6#include <limits>
7
8#include <QtQml/qqmlinfo.h>
9
13
73
75{
76 return static_cast<QQuickStackLayoutAttached*>(
77 qmlAttachedPropertiesObject<QQuickStackLayout>(item, create));
78}
79
84
94{
95 Q_D(const QQuickStackLayout);
96 return d->count;
97}
98
109{
110 Q_D(const QQuickStackLayout);
111 return d->currentIndex;
112}
113
115{
117 if (index == d->currentIndex)
118 return;
119
120 QQuickItem *prev = itemAt(d->currentIndex);
122 d->currentIndex = index;
123 d->explicitCurrentIndex = true;
124 if (prev)
125 prev->setVisible(false);
126 if (next)
127 next->setVisible(true);
128
129 if (isComponentComplete()) {
132 }
133
134 // Update attached properties after emitting currentIndexChanged()
135 // to maintain a more sensible emission order.
136 if (prev) {
137 auto stackLayoutAttached = attachedStackLayoutObject(prev);
138 if (stackLayoutAttached)
139 stackLayoutAttached->setIsCurrentItem(false);
140 }
141 if (next) {
142 auto stackLayoutAttached = attachedStackLayoutObject(next);
143 if (stackLayoutAttached)
144 stackLayoutAttached->setIsCurrentItem(true);
145 }
146}
147
149{
150 QQuickLayout::componentComplete(); // will call our geometryChange(), (where isComponentComplete() == true)
151
152 childItemsChanged();
153 invalidate();
155
156 QQuickItem *par = parentItem();
157 if (qobject_cast<QQuickLayout*>(par))
158 return;
159
161}
162
164{
166 if (!isReady())
167 return;
168
169 if (change == ItemChildRemovedChange) {
170 QQuickItem *item = value.item;
171 auto stackLayoutAttached = attachedStackLayoutObject(item);
172 if (stackLayoutAttached) {
173 stackLayoutAttached->setLayout(nullptr);
174 stackLayoutAttached->setIndex(-1);
175 stackLayoutAttached->setIsCurrentItem(false);
176 }
177 m_cachedItemSizeHints.remove(item);
178 childItemsChanged(AdjustCurrentIndex); // removal; might have to adjust currentIndex
179 invalidate();
180 } else if (change == ItemChildAddedChange) {
181 childItemsChanged();
182 invalidate();
183 }
184}
185
187{
188 Q_D(const QQuickStackLayout);
189 QSizeF &askingFor = m_cachedSizeHints[whichSizeHint];
190 if (!askingFor.isValid()) {
191 QSizeF &minS = m_cachedSizeHints[Qt::MinimumSize];
192 QSizeF &prefS = m_cachedSizeHints[Qt::PreferredSize];
193 QSizeF &maxS = m_cachedSizeHints[Qt::MaximumSize];
194
195 minS = QSizeF(0,0);
196 prefS = QSizeF(0,0);
197 maxS = QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity());
198
199 const int count = itemCount();
200 for (int i = 0; i < count; ++i) {
201 SizeHints &hints = cachedItemSizeHints(i);
202 minS = minS.expandedTo(hints.min());
203 prefS = prefS.expandedTo(hints.pref());
204 //maxS = maxS.boundedTo(hints.max()); // Can be resized to be larger than any of its items.
205 // This is the same as QStackLayout does it.
206 // Not sure how descent makes sense here...
207 }
208 }
209 d->m_dirty = false;
210 return askingFor;
211}
212
214{
215 if (childItem) {
216 int indexOfItem = 0;
217 const auto items = childItems();
218 for (QQuickItem *item : items) {
219 if (shouldIgnoreItem(item))
220 continue;
221 if (childItem == item)
222 return indexOfItem;
223 ++indexOfItem;
224 }
225 }
226 return -1;
227}
228
233
235{
236 const auto items = childItems();
237 for (QQuickItem *item : items) {
238 if (shouldIgnoreItem(item))
239 continue;
240 if (index == 0)
241 return item;
242 --index;
243 }
244 return nullptr;
245}
246
248{
249 int count = 0;
250 const auto items = childItems();
251 for (QQuickItem *item : items) {
252 if (shouldIgnoreItem(item))
253 continue;
254 ++count;
255 }
256 return count;
257}
258
259void QQuickStackLayout::setAlignment(QQuickItem * /*item*/, Qt::Alignment /*align*/)
260{
261 // ### Do we have to respect alignment?
262}
263
265{
266 if (childItem) {
267 SizeHints &hints = m_cachedItemSizeHints[childItem];
268 hints.min() = QSizeF();
269 hints.pref() = QSizeF();
270 hints.max() = QSizeF();
271 }
272
273 for (int i = 0; i < Qt::NSizeHints; ++i)
274 m_cachedSizeHints[i] = QSizeF();
276
277 if (QQuickLayout *parentLayout = qobject_cast<QQuickLayout *>(parentItem()))
278 parentLayout->invalidate(this);
279}
280
281void QQuickStackLayout::childItemsChanged(AdjustCurrentIndexPolicy adjustCurrentIndexPolicy)
282{
284 const int count = itemCount();
285 const int oldIndex = d->currentIndex;
286 if (!d->explicitCurrentIndex)
287 d->currentIndex = (count > 0 ? 0 : -1);
288
289 if (adjustCurrentIndexPolicy == AdjustCurrentIndex) {
290 /*
291 * If an item is inserted or deleted at an index less than or equal to the current index it
292 * will affect the current index, but keep the current item. This is consistent with
293 * QStackedLayout, QStackedWidget and TabBar
294 *
295 * Unless the caller is componentComplete(), we can assume that only one of the children
296 * are visible, and we should keep that visible even if the stacking order has changed.
297 * This means that if the sibling order has changed (or an item stacked before the current
298 * item is added/removed), we must update the currentIndex so that it corresponds with the
299 * current visible item.
300 */
301 if (d->currentIndex < d->count) {
302 for (int i = 0; i < count; ++i) {
304 if (child->isVisible()) {
305 d->currentIndex = i;
306 break;
307 }
308 }
309 }
310 }
311 if (d->currentIndex != oldIndex)
313
314 if (count != d->count) {
315 d->count = count;
317 }
318 for (int i = 0; i < count; ++i) {
321 child->setVisible(d->currentIndex == i);
322
323 auto stackLayoutAttached = attachedStackLayoutObject(child);
324 if (stackLayoutAttached) {
325 stackLayoutAttached->setLayout(this);
326 stackLayoutAttached->setIndex(i);
327 stackLayoutAttached->setIsCurrentItem(d->currentIndex == i);
328 }
329 }
330}
331
332QQuickStackLayout::SizeHints &QQuickStackLayout::cachedItemSizeHints(int index) const
333{
335 Q_ASSERT(item);
336 SizeHints &hints = m_cachedItemSizeHints[item]; // will create an entry if it doesn't exist
337 if (!hints.min().isValid())
338 QQuickStackLayout::collectItemSizeHints(item, hints.array);
339 return hints;
340}
341
342
344{
346 if (newSize.isNull() || !newSize.isValid())
347 return;
348
349 qCDebug(lcQuickLayouts) << "QQuickStackLayout::rearrange";
350
351 if (d->currentIndex == -1 || d->currentIndex >= m_cachedItemSizeHints.size())
352 return;
353 QQuickStackLayout::SizeHints &hints = cachedItemSizeHints(d->currentIndex);
354 QQuickItem *item = itemAt(d->currentIndex);
355 Q_ASSERT(item);
356 item->setPosition(QPointF(0,0)); // ### respect alignment?
357 const QSizeF oldSize(item->width(), item->height());
358 const QSizeF effectiveNewSize = newSize.expandedTo(hints.min()).boundedTo(hints.max());
359 item->setSize(effectiveNewSize);
360 if (effectiveNewSize == oldSize)
361 item->polish();
363}
364
365void QQuickStackLayout::setStretchFactor(QQuickItem * /*item*/, int /*stretchFactor*/, Qt::Orientation /*orient*/)
366{
367}
368
369void QQuickStackLayout::collectItemSizeHints(QQuickItem *item, QSizeF *sizeHints)
370{
371 QQuickLayoutAttached *info = nullptr;
373 if (!info)
374 return;
375 if (info->isFillWidthSet() && !info->fillWidth()) {
376 const qreal pref = sizeHints[Qt::PreferredSize].width();
377 sizeHints[Qt::MinimumSize].setWidth(pref);
378 sizeHints[Qt::MaximumSize].setWidth(pref);
379 }
380
381 if (info->isFillHeightSet() && !info->fillHeight()) {
382 const qreal pref = sizeHints[Qt::PreferredSize].height();
383 sizeHints[Qt::MinimumSize].setHeight(pref);
384 sizeHints[Qt::MaximumSize].setHeight(pref);
385 }
386}
387
388bool QQuickStackLayout::shouldIgnoreItem(QQuickItem *item) const
389{
390 return QQuickItemPrivate::get(item)->isTransparentForPositioner();
391}
392
394{
395 if (!isReady())
396 return;
397 childItemsChanged(AdjustCurrentIndex);
398 invalidate();
399}
400
402{
403 auto item = qobject_cast<QQuickItem*>(object);
404 if (!item) {
405 qmlWarning(object) << "StackLayout must be attached to an Item";
406 return;
407 }
408
409 auto stackLayout = qobject_cast<QQuickStackLayout*>(item->parentItem());
410 if (!stackLayout) {
411 // It might not be a child of a StackLayout yet, and that's OK.
412 // The index will get set by updateLayoutItems() when it's reparented.
413 return;
414 }
415
416 if (!stackLayout->isComponentComplete()) {
417 // Don't try to get the index if the StackLayout itself hasn't loaded yet.
418 return;
419 }
420
421 // If we got this far, the item was added as a child to the StackLayout after it loaded.
422 const int index = stackLayout->indexOf(item);
423 setLayout(stackLayout);
425 setIsCurrentItem(stackLayout->currentIndex() == index);
426
427 // In case of lazy loading in loader, attachedProperties are created and updated for the
428 // object after adding the child object to the stack layout, which leads to entries with
429 // same index. Triggering childItemsChanged() resets to right index in the stack layout.
430 stackLayout->childItemsChanged();
431}
432
445{
446 return m_index;
447}
448
450{
451 if (index == m_index)
452 return;
453
454 m_index = index;
456}
457
470{
471 return m_isCurrentItem;
472}
473
475{
476 if (isCurrentItem == m_isCurrentItem)
477 return;
478
479 m_isCurrentItem = isCurrentItem;
481}
482
495{
496 return m_layout;
497}
498
500{
501 if (layout == m_layout)
502 return;
503
504 m_layout = layout;
506}
507
509
510#include "moc_qquickstacklayout_p.cpp"
QGraphicsItem * parentItem() const
Returns a pointer to this item's parent item.
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:958
qsizetype size() const noexcept
Returns the number of items in the hash.
Definition qhash.h:927
\inmodule QtCore
Definition qobject.h:103
\inmodule QtCore\reentrant
Definition qpoint.h:217
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
QList< QQuickItem * > childItems() const
Returns the children of this item.
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
QQuickItem * parentItem() const
void setVisible(bool)
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
ItemChange
Used in conjunction with QQuickItem::itemChange() to notify the item about certain types of changes.
Definition qquickitem.h:144
@ ItemChildAddedChange
Definition qquickitem.h:145
@ ItemChildRemovedChange
Definition qquickitem.h:146
bool isReady() const
void itemChange(ItemChange change, const ItemChangeData &value) override
Called when change occurs for this item.
static void effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **info, bool useFallbackToWidthOrHeight)
virtual void rearrange(const QSizeF &)
virtual void invalidate(QQuickItem *childItem=nullptr)
void checkAnchors(QQuickItem *item) const
void ensureLayoutItemsUpdated(EnsureLayoutItemsUpdatedOptions options={}) const
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
void setLayout(QQuickStackLayout *layout)
void setIsCurrentItem(bool isCurrentItem)
QQuickStackLayoutAttached(QObject *object)
void setAlignment(QQuickItem *item, Qt::Alignment align) override
Q_INVOKABLE QQuickItem * itemAt(int index) const override
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
int indexOf(QQuickItem *item) const
void currentIndexChanged()
void setStretchFactor(QQuickItem *item, int stretchFactor, Qt::Orientation orient) override
friend class QQuickStackLayoutAttached
void rearrange(const QSizeF &) override
void invalidate(QQuickItem *childItem=nullptr) override
static QQuickStackLayoutAttached * qmlAttachedProperties(QObject *object)
QQuickStackLayout(QQuickItem *parent=nullptr)
void setCurrentIndex(int index)
void itemSiblingOrderChanged(QQuickItem *item) override
int itemCount() const override
void itemChange(ItemChange change, const ItemChangeData &value) override
Called when change occurs for this item.
QSizeF sizeHint(Qt::SizeHint whichSizeHint) const override
\inmodule QtCore
Definition qsize.h:208
constexpr bool isValid() const noexcept
Returns true if both the width and height are equal to or greater than 0; otherwise returns false.
Definition qsize.h:329
bool isNull() const noexcept
Returns true if both the width and height are 0.0 (ignoring the sign); otherwise returns false.
Definition qsize.h:323
constexpr void setHeight(qreal h) noexcept
Sets the height to the given finite height.
Definition qsize.h:341
constexpr void setWidth(qreal w) noexcept
Sets the width to the given finite width.
Definition qsize.h:338
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:332
constexpr QSizeF expandedTo(const QSizeF &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition qsize.h:391
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:335
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
Orientation
Definition qnamespace.h:98
@ MaximumSize
@ PreferredSize
@ MinimumSize
@ NSizeHints
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCDebug(category,...)
GLuint index
[2]
GLenum GLenum GLsizei count
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
Definition qquickitem.h:492
static QT_BEGIN_NAMESPACE QQuickStackLayoutAttached * attachedStackLayoutObject(QQuickItem *item, bool create=false)
The StackLayout class provides a stack of items where only one item is visible at a time.
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
double qreal
Definition qtypes.h:187
QVBoxLayout * layout
QGraphicsItem * item
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
QHostInfo info
[0]
view create()
\inmodule QtQuick
Definition qquickitem.h:159