9#include <QtQml/qqmlinfo.h>
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
75static QQuickStackLayoutAttached *attachedStackLayoutObject(QQuickItem *item,
bool create =
false)
77 return static_cast<QQuickStackLayoutAttached*>(
78 qmlAttachedPropertiesObject<QQuickStackLayout>(item, create));
81QQuickStackLayout::QQuickStackLayout(QQuickItem *parent) :
82 QQuickLayout(*
new QQuickStackLayoutPrivate, parent)
87
88
89
90
91
92
93
94int QQuickStackLayout::count()
const
96 Q_D(
const QQuickStackLayout);
101
102
103
104
105
106
107
108
109int QQuickStackLayout::currentIndex()
const
111 Q_D(
const QQuickStackLayout);
112 return d->currentIndex;
115void QQuickStackLayout::setCurrentIndex(
int index)
117 Q_D(QQuickStackLayout);
118 if (index == d->currentIndex)
121 QQuickItem *prev = itemAt(d->currentIndex);
122 QQuickItem *next = itemAt(index);
123 d->currentIndex = index;
124 d->explicitCurrentIndex =
true;
126 prev->setVisible(
false);
128 next->setVisible(
true);
130 if (isComponentComplete()) {
131 rearrange(QSizeF(width(), height()));
132 emit currentIndexChanged();
138 auto stackLayoutAttached = attachedStackLayoutObject(prev);
139 if (stackLayoutAttached)
140 stackLayoutAttached->setIsCurrentItem(
false);
143 auto stackLayoutAttached = attachedStackLayoutObject(next);
144 if (stackLayoutAttached)
145 stackLayoutAttached->setIsCurrentItem(
true);
149void QQuickStackLayout::componentComplete()
151 QQuickLayout::componentComplete();
155 ensureLayoutItemsUpdated(ApplySizeHints);
157 QQuickItem *par = parentItem();
158 if (qobject_cast<QQuickLayout*>(par))
161 rearrange(QSizeF(width(), height()));
164void QQuickStackLayout::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &value)
166 QQuickLayout::itemChange(change, value);
170 if (change == ItemChildRemovedChange) {
171 QQuickItem *item = value.item;
172 auto stackLayoutAttached = attachedStackLayoutObject(item);
173 if (stackLayoutAttached) {
174 stackLayoutAttached->setLayout(
nullptr);
175 stackLayoutAttached->setIndex(-1);
176 stackLayoutAttached->setIsCurrentItem(
false);
178 m_cachedItemSizeHints.remove(item);
179 childItemsChanged(AdjustCurrentIndex);
181 }
else if (change == ItemChildAddedChange) {
187QSizeF QQuickStackLayout::sizeHint(Qt::SizeHint whichSizeHint)
const
189 Q_D(
const QQuickStackLayout);
190 QSizeF &askingFor = m_cachedSizeHints[whichSizeHint];
191 if (!askingFor.isValid()) {
192 QSizeF &minS = m_cachedSizeHints[Qt::MinimumSize];
193 QSizeF &prefS = m_cachedSizeHints[Qt::PreferredSize];
194 QSizeF &maxS = m_cachedSizeHints[Qt::MaximumSize];
198 maxS = QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity());
200 const int count = itemCount();
201 for (
int i = 0; i < count; ++i) {
202 SizeHints &hints = cachedItemSizeHints(i);
203 minS = minS.expandedTo(hints.min());
204 prefS = prefS.expandedTo(hints.pref());
214int QQuickStackLayout::indexOf(QQuickItem *childItem)
const
218 const auto items = childItems();
219 for (QQuickItem *item : items) {
220 if (shouldIgnoreItem(item))
222 if (childItem == item)
230QQuickStackLayoutAttached *QQuickStackLayout::qmlAttachedProperties(QObject *object)
232 return new QQuickStackLayoutAttached(object);
235QQuickItem *QQuickStackLayout::itemAt(
int index)
const
237 const auto items = childItems();
238 for (QQuickItem *item : items) {
239 if (shouldIgnoreItem(item))
248int QQuickStackLayout::itemCount()
const
251 const auto items = childItems();
252 for (QQuickItem *item : items) {
253 if (shouldIgnoreItem(item))
260void QQuickStackLayout::setAlignment(QQuickItem * , Qt::Alignment )
265void QQuickStackLayout::invalidate(QQuickItem *childItem)
268 SizeHints &hints = m_cachedItemSizeHints[childItem];
269 hints.min() = QSizeF();
270 hints.pref() = QSizeF();
271 hints.max() = QSizeF();
274 for (
int i = 0; i < Qt::NSizeHints; ++i)
275 m_cachedSizeHints[i] = QSizeF();
276 QQuickLayout::invalidate(
this);
278 if (QQuickLayout *parentLayout = qobject_cast<QQuickLayout *>(parentItem()))
279 parentLayout->invalidate(
this);
282void QQuickStackLayout::childItemsChanged(AdjustCurrentIndexPolicy adjustCurrentIndexPolicy)
284 Q_D(QQuickStackLayout);
285 const int count = itemCount();
286 const int oldIndex = d->currentIndex;
287 if (!d->explicitCurrentIndex)
288 d->currentIndex = (count > 0 ? 0 : -1);
290 if (adjustCurrentIndexPolicy == AdjustCurrentIndex) {
292
293
294
295
296
297
298
299
300
301
302 if (d->currentIndex < d->count) {
303 for (
int i = 0; i < count; ++i) {
304 QQuickItem *child = itemAt(i);
305 if (child->isVisible()) {
312 if (d->currentIndex != oldIndex)
313 emit currentIndexChanged();
315 if (count != d->count) {
319 for (
int i = 0; i < count; ++i) {
320 QQuickItem *child = itemAt(i);
322 child->setVisible(d->currentIndex == i);
324 auto stackLayoutAttached = attachedStackLayoutObject(child);
325 if (stackLayoutAttached) {
326 stackLayoutAttached->setLayout(
this);
327 stackLayoutAttached->setIndex(i);
328 stackLayoutAttached->setIsCurrentItem(d->currentIndex == i);
333QQuickStackLayout::SizeHints &QQuickStackLayout::cachedItemSizeHints(
int index)
const
335 QQuickItem *item = itemAt(index);
337 SizeHints &hints = m_cachedItemSizeHints[item];
338 if (!hints.min().isValid())
339 QQuickStackLayout::collectItemSizeHints(item, hints.array);
344void QQuickStackLayout::rearrange(
const QSizeF &newSize)
346 Q_D(QQuickStackLayout);
347 if (newSize.isNull() || !newSize.isValid())
350 qCDebug(lcQuickLayouts) <<
"QQuickStackLayout::rearrange";
352 if (d->currentIndex == -1 || d->currentIndex >= m_cachedItemSizeHints.size())
354 QQuickStackLayout::SizeHints &hints = cachedItemSizeHints(d->currentIndex);
355 QQuickItem *item = itemAt(d->currentIndex);
357 item->setPosition(QPointF(0,0));
358 const QSizeF oldSize(item->width(), item->height());
359 const QSizeF effectiveNewSize = newSize.expandedTo(hints.min()).boundedTo(hints.max());
360 item->setSize(effectiveNewSize);
361 if (effectiveNewSize == oldSize)
363 QQuickLayout::rearrange(newSize);
366void QQuickStackLayout::setStretchFactor(QQuickItem * ,
int , Qt::Orientation )
370void QQuickStackLayout::collectItemSizeHints(QQuickItem *item, QSizeF *sizeHints)
372 QQuickLayoutAttached *info =
nullptr;
373 QQuickLayout::effectiveSizeHints_helper(item, sizeHints, &info,
true);
376 if (info->isFillWidthSet() && !info->fillWidth()) {
377 const qreal pref = sizeHints[Qt::PreferredSize].width();
378 sizeHints[Qt::MinimumSize].setWidth(pref);
379 sizeHints[Qt::MaximumSize].setWidth(pref);
382 if (info->isFillHeightSet() && !info->fillHeight()) {
383 const qreal pref = sizeHints[Qt::PreferredSize].height();
384 sizeHints[Qt::MinimumSize].setHeight(pref);
385 sizeHints[Qt::MaximumSize].setHeight(pref);
389bool QQuickStackLayout::shouldIgnoreItem(QQuickItem *item)
const
391 return QQuickItemPrivate::get(item)->isTransparentForPositioner();
394void QQuickStackLayout::itemSiblingOrderChanged(QQuickItem *)
398 childItemsChanged(AdjustCurrentIndex);
402QQuickStackLayoutAttached::QQuickStackLayoutAttached(QObject *object)
404 auto item = qobject_cast<QQuickItem*>(object);
406 qmlWarning(object) <<
"StackLayout attached property must be attached to an object deriving from Item";
410 auto stackLayout = qobject_cast<QQuickStackLayout*>(item->parentItem());
417 if (!stackLayout->isComponentComplete()) {
423 const int index = stackLayout->indexOf(item);
424 setLayout(stackLayout);
426 setIsCurrentItem(stackLayout->currentIndex() == index);
431 stackLayout->childItemsChanged();
435
436
437
438
439
440
441
442
443
444
445int QQuickStackLayoutAttached::index()
const
450void QQuickStackLayoutAttached::setIndex(
int index)
452 if (index == m_index)
460
461
462
463
464
465
466
467
468
469
470bool QQuickStackLayoutAttached::isCurrentItem()
const
472 return m_isCurrentItem;
475void QQuickStackLayoutAttached::setIsCurrentItem(
bool isCurrentItem)
477 if (isCurrentItem == m_isCurrentItem)
480 m_isCurrentItem = isCurrentItem;
481 emit isCurrentItemChanged();
485
486
487
488
489
490
491
492
493
494
495QQuickStackLayout *QQuickStackLayoutAttached::layout()
const
500void QQuickStackLayoutAttached::setLayout(QQuickStackLayout *layout)
502 if (layout == m_layout)
506 emit layoutChanged();
511#include "moc_qquickstacklayout_p.cpp"