254void QQuickBasePositioner::itemChange(ItemChange change,
const ItemChangeData &value)
256 Q_D(QQuickBasePositioner);
257 if (change == ItemChildAddedChange) {
258 d->setPositioningDirty();
259 }
else if (change == ItemChildRemovedChange) {
260 QQuickItem *child = value.item;
261 auto it = std::find(positionedItems.begin(), positionedItems.end(), child);
262 if (it != positionedItems.end()) {
263 d->unwatchChanges(child);
264 positionedItems.erase(it);
266 it = std::find(unpositionedItems.begin(), unpositionedItems.end(), child);
267 if (it != unpositionedItems.end()) {
268 d->unwatchChanges(child);
269 unpositionedItems.erase(it);
272 d->setPositioningDirty();
275 QQuickItem::itemChange(change, value);
283void QQuickBasePositioner::prePositioning()
285 Q_D(QQuickBasePositioner);
286 if (!isComponentComplete())
289 if (d->doingPositioning)
292 d->positioningDirty =
false;
293 d->doingPositioning =
true;
295 QList<QQuickItem *> children = childItems();
297 std::vector<PositionedItem> oldItems;
298 oldItems.reserve(positionedItems.size() + unpositionedItems.size());
300 std::move(positionedItems.begin(), positionedItems.end(),
301 std::back_inserter(oldItems));
302 positionedItems.clear();
304 std::move(unpositionedItems.begin(), unpositionedItems.end(),
305 std::back_inserter(oldItems));
306 unpositionedItems.clear();
308#if QT_CONFIG(quick_viewtransitions)
312 for (
int ii = 0; ii < children.size(); ++ii) {
313 QQuickItem *child = children.at(ii);
314 if (QQuickItemPrivate::get(child)->isTransparentForPositioner())
316 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
317 PositionedItem posItem(child);
318 auto it = std::find(oldItems.begin(), oldItems.end(), posItem);
319 if (it == oldItems.end()) {
321 d->watchChanges(child);
322 posItem.isNew =
true;
323 if (!childPrivate->explicitVisible || !child->width() || !child->height()) {
324 posItem.isVisible =
false;
331 childPrivate->setCulled(
true);
332 unpositionedItems.push_back(std::move(posItem));
334 const int posIndex =
int(positionedItems.size());
335 posItem.index = posIndex;
336 positionedItems.push_back(std::move(posItem));
338#if QT_CONFIG(quick_viewtransitions)
339 if (d->transitioner) {
341 addedIndex = posIndex;
342 PositionedItem *theItem = &positionedItems.back();
343 if (d->transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true))
344 theItem->transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::PopulateTransition,
true);
345 else if (!d->transitioner->populateTransitionEnabled())
346 theItem->transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition,
true);
352 PositionedItem *item = &*it;
355 if (!childPrivate->explicitVisible || !child->width() || !child->height()) {
356 item->isVisible =
false;
358 childPrivate->setCulled(
true);
359 unpositionedItems.push_back(std::move(*item));
360 }
else if (!item->isVisible) {
362 item->isVisible =
true;
364 const int itemIndex =
int(positionedItems.size());
365 item->index = itemIndex;
366 childPrivate->setCulled(
false);
367 positionedItems.push_back(std::move(*item));
369#if QT_CONFIG(quick_viewtransitions)
370 if (d->transitioner) {
372 addedIndex = itemIndex;
373 positionedItems.back().transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition,
true);
378 const int itemIndex =
int(positionedItems.size());
379 item->index = itemIndex;
380 positionedItems.push_back(std::move(*item));
385#if QT_CONFIG(quick_viewtransitions)
386 if (d->transitioner) {
387 for (PositionedItem &item : positionedItems) {
389 if (addedIndex >= 0) {
390 item.transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition,
false);
394 item.transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::MoveTransition,
false);
401 QSizeF contentSize(0,0);
402 reportConflictingAnchors();
403 if (!d->anchorConflict) {
404 doPositioning(&contentSize);
405 updateAttachedProperties();
408#if QT_CONFIG(quick_viewtransitions)
409 if (d->transitioner) {
410 QRectF viewBounds(QPointF(), contentSize);
411 for (PositionedItem &item : positionedItems)
412 item.prepareTransition(d->transitioner, viewBounds);
413 for (PositionedItem &item : positionedItems)
414 item.startTransition(d->transitioner);
415 d->transitioner->resetTargetLists();
419 d->doingPositioning =
false;
422 setImplicitSize(contentSize.width(), contentSize.height());
424 emit positioningComplete();
456void QQuickBasePositioner::updateAttachedProperties(QQuickPositionerAttached *specificProperty, QQuickItem *specificPropertyOwner)
const
462 QQuickPositionerAttached *prevLastProperty =
nullptr;
463 QQuickPositionerAttached *lastProperty =
nullptr;
465 const int positionedItemsSize =
int(positionedItems.size());
466 for (
int ii = 0; ii < positionedItemsSize; ++ii) {
467 const PositionedItem &child = positionedItems[ii];
471 QQuickPositionerAttached *property =
nullptr;
473 if (specificProperty) {
474 if (specificPropertyOwner == child.item) {
475 property = specificProperty;
478 property =
static_cast<QQuickPositionerAttached *>(qmlAttachedPropertiesObject<QQuickBasePositioner>(child.item,
false));
482 property->setIndex(ii);
483 property->setIsFirstItem(ii == 0);
485 if (property->isLastItem()) {
486 if (prevLastProperty)
487 prevLastProperty->setIsLastItem(
false);
488 prevLastProperty = property;
492 lastProperty = property;
495 if (prevLastProperty && prevLastProperty != lastProperty)
496 prevLastProperty->setIsLastItem(
false);
498 lastProperty->setIsLastItem(
true);
501 for (
const PositionedItem &child : unpositionedItems) {
505 QQuickPositionerAttached *property =
nullptr;
507 if (specificProperty) {
508 if (specificPropertyOwner == child.item) {
509 property = specificProperty;
512 property =
static_cast<QQuickPositionerAttached *>(qmlAttachedPropertiesObject<QQuickBasePositioner>(child.item,
false));
516 property->setIndex(-1);
517 property->setIsFirstItem(
false);
518 property->setIsLastItem(
false);
529void QQuickBasePositioner::setPadding(qreal padding)
531 Q_D(QQuickBasePositioner);
532 if (qFuzzyCompare(d->padding(), padding))
535 d->extra.value().padding = padding;
536 d->setPositioningDirty();
537 emit paddingChanged();
538 if (!d->extra.isAllocated() || !d->extra->explicitTopPadding)
539 emit topPaddingChanged();
540 if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding)
541 emit leftPaddingChanged();
542 if (!d->extra.isAllocated() || !d->extra->explicitRightPadding)
543 emit rightPaddingChanged();
544 if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding)
545 emit bottomPaddingChanged();
937void QQuickColumn::doPositioning(QSizeF *contentSize)
940 qreal voffset = topPadding();
941 const qreal padding = leftPadding() + rightPadding();
942 contentSize->setWidth(qMax(contentSize->width(), padding));
944 for (PositionedItem &child : positionedItems) {
945 positionItem(child.itemX() + leftPadding() - child.leftPadding, voffset, &child);
946 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
947 contentSize->setWidth(qMax(contentSize->width(), child.item->width() + padding));
949 voffset += child.item->height();
950 voffset += spacing();
953 if (voffset - topPadding() != 0)
954 voffset -= spacing();
955 contentSize->setHeight(voffset + bottomPadding());
958void QQuickColumn::reportConflictingAnchors()
960 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(
this));
961 for (
const PositionedItem &child : positionedItems) {
963 QQuickAnchors *anchors = QQuickItemPrivate::get(
static_cast<QQuickItem *>(child.item))->_anchors;
965 QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
966 if (usedAnchors & QQuickAnchors::TopAnchor ||
967 usedAnchors & QQuickAnchors::BottomAnchor ||
968 usedAnchors & QQuickAnchors::VCenterAnchor ||
969 anchors->fill() || anchors->centerIn()) {
970 d->anchorConflict =
true;
976 if (d->anchorConflict) {
977 qmlWarning(
this) <<
"Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column."
978 <<
" Column will not function.";
1185void QQuickRow::doPositioning(QSizeF *contentSize)
1188 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(
this));
1189 qreal hoffset1 = leftPadding();
1190 qreal hoffset2 = rightPadding();
1191 if (!d->isLeftToRight())
1192 qSwap(hoffset1, hoffset2);
1193 qreal hoffset = hoffset1;
1194 const qreal padding = topPadding() + bottomPadding();
1195 contentSize->setHeight(qMax(contentSize->height(), padding));
1197 QList<qreal> hoffsets;
1198 for (PositionedItem &child : positionedItems) {
1199 if (d->isLeftToRight()) {
1200 positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
1201 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
1203 hoffsets << hoffset;
1206 contentSize->setHeight(qMax(contentSize->height(), child.item->height() + padding));
1208 hoffset += child.item->width();
1209 hoffset += spacing();
1212 if (hoffset - hoffset1 != 0)
1213 hoffset -= spacing();
1214 contentSize->setWidth(hoffset + hoffset2);
1216 if (d->isLeftToRight())
1222 end = contentSize->width();
1227 for (PositionedItem &child : positionedItems) {
1228 hoffset = end - hoffsets[acc++] - child.item->width();
1229 positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
1230 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
1234void QQuickRow::reportConflictingAnchors()
1236 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(
this));
1237 for (
const PositionedItem &child : positionedItems) {
1239 QQuickAnchors *anchors = QQuickItemPrivate::get(
static_cast<QQuickItem *>(child.item))->_anchors;
1241 QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
1242 if (usedAnchors & QQuickAnchors::LeftAnchor ||
1243 usedAnchors & QQuickAnchors::RightAnchor ||
1244 usedAnchors & QQuickAnchors::HCenterAnchor ||
1245 anchors->fill() || anchors->centerIn()) {
1246 d->anchorConflict =
true;
1252 if (d->anchorConflict)
1253 qmlWarning(
this) <<
"Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row."
1254 <<
" Row will not function.";
1685void QQuickGrid::doPositioning(QSizeF *contentSize)
1688 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(
this));
1691 const int numVisible =
int(positionedItems.size());
1693 if (m_columns <= 0 && m_rows <= 0) {
1695 r = (numVisible+3)/4;
1696 }
else if (m_rows <= 0) {
1697 r = (numVisible+(m_columns-1))/m_columns;
1698 }
else if (m_columns <= 0) {
1699 c = (numVisible+(m_rows-1))/m_rows;
1702 if (r == 0 || c == 0) {
1703 contentSize->setHeight(topPadding() + bottomPadding());
1704 contentSize->setWidth(leftPadding() + rightPadding());
1708 if (numVisible > r * c) {
1709 qmlWarning(
this) <<
"Grid contains more visible items (" << numVisible <<
") than rows*columns (" << r * c <<
")";
1712 QList<qreal> maxColWidth;
1713 QList<qreal> maxRowHeight;
1715 if (m_flow == LeftToRight) {
1716 for (
int i = 0; i < r; i++) {
1717 for (
int j = 0; j < c; j++) {
1723 if (childIndex == numVisible)
1726 const PositionedItem &child = positionedItems[childIndex++];
1727 if (child.item->width() > maxColWidth[j])
1728 maxColWidth[j] = child.item->width();
1729 if (child.item->height() > maxRowHeight[i])
1730 maxRowHeight[i] = child.item->height();
1734 for (
int j = 0; j < c; j++) {
1735 for (
int i = 0; i < r; i++) {
1741 if (childIndex == numVisible)
1744 const PositionedItem &child = positionedItems[childIndex++];
1745 if (child.item->width() > maxColWidth[j])
1746 maxColWidth[j] = child.item->width();
1747 if (child.item->height() > maxRowHeight[i])
1748 maxRowHeight[i] = child.item->height();
1753 qreal columnSpacing = m_useColumnSpacing ? m_columnSpacing : spacing();
1754 qreal rowSpacing = m_useRowSpacing ? m_rowSpacing : spacing();
1757 for (
int j = 0; j < maxColWidth.size(); j++) {
1759 widthSum += columnSpacing;
1760 widthSum += maxColWidth[j];
1762 widthSum += leftPadding() + rightPadding();
1764 qreal heightSum = 0;
1765 for (
int i = 0; i < maxRowHeight.size(); i++) {
1767 heightSum += rowSpacing;
1768 heightSum += maxRowHeight[i];
1770 heightSum += topPadding() + bottomPadding();
1772 contentSize->setHeight(heightSum);
1773 contentSize->setWidth(widthSum);
1781 qreal xoffset = leftPadding();
1782 if (!d->isLeftToRight())
1783 xoffset = end - rightPadding();
1784 qreal yoffset = topPadding();
1787 for (PositionedItem &child : positionedItems) {
1788 qreal childXOffset = xoffset;
1790 if (effectiveHAlign() == AlignRight)
1791 childXOffset += maxColWidth[curCol] - child.item->width();
1792 else if (hItemAlign() == AlignHCenter)
1793 childXOffset += (maxColWidth[curCol] - child.item->width())/2.0;
1795 if (!d->isLeftToRight())
1796 childXOffset -= maxColWidth[curCol];
1798 qreal alignYOffset = yoffset;
1799 if (m_vItemAlign == AlignVCenter)
1800 alignYOffset += (maxRowHeight[curRow] - child.item->height())/2.0;
1801 else if (m_vItemAlign == AlignBottom)
1802 alignYOffset += maxRowHeight[curRow] - child.item->height();
1804 positionItem(childXOffset, alignYOffset, &child);
1805 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
1807 if (m_flow == LeftToRight) {
1808 if (d->isLeftToRight())
1809 xoffset += maxColWidth[curCol]+columnSpacing;
1811 xoffset -= maxColWidth[curCol]+columnSpacing;
1815 yoffset += maxRowHeight[curRow]+rowSpacing;
1816 if (d->isLeftToRight())
1817 xoffset = leftPadding();
1819 xoffset = end - rightPadding();
1825 yoffset += maxRowHeight[curRow]+rowSpacing;
1829 if (d->isLeftToRight())
1830 xoffset += maxColWidth[curCol]+columnSpacing;
1832 xoffset -= maxColWidth[curCol]+columnSpacing;
1833 yoffset = topPadding();
2094void QQuickFlow::doPositioning(QSizeF *contentSize)
2099 qreal hoffset1 = leftPadding();
2100 qreal hoffset2 = rightPadding();
2101 if (!d->isLeftToRight())
2102 qSwap(hoffset1, hoffset2);
2103 qreal hoffset = hoffset1;
2104 const qreal voffset1 = topPadding();
2105 qreal voffset = voffset1;
2107 QList<qreal> hoffsets;
2108 contentSize->setWidth(qMax(contentSize->width(), hoffset1 + hoffset2));
2109 contentSize->setHeight(qMax(contentSize->height(), voffset + bottomPadding()));
2111 for (PositionedItem &child : positionedItems) {
2112 if (d->flow == LeftToRight) {
2113 if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) {
2115 voffset += linemax + spacing();
2119 if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) {
2121 hoffset += linemax + spacing();
2126 if (d->isLeftToRight()) {
2127 positionItem(hoffset, voffset, &child);
2128 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
2130 hoffsets << hoffset;
2131 positionItemY(voffset, &child);
2132 child.topPadding = topPadding();
2133 child.bottomPadding = bottomPadding();
2136 contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2));
2137 contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding()));
2139 if (d->flow == LeftToRight) {
2140 hoffset += child.item->width();
2141 hoffset += spacing();
2142 linemax = qMax(linemax, child.item->height());
2144 voffset += child.item->height();
2145 voffset += spacing();
2146 linemax = qMax(linemax, child.item->width());
2150 if (d->isLeftToRight())
2157 end = contentSize->width();
2159 for (PositionedItem &child : positionedItems) {
2160 hoffset = end - hoffsets[acc++] - child.item->width();
2161 positionItemX(hoffset, &child);
2162 child.leftPadding = leftPadding();
2163 child.rightPadding = rightPadding();