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();
940void QQuickColumn::doPositioning(QSizeF *contentSize)
943 qreal voffset = topPadding();
944 const qreal padding = leftPadding() + rightPadding();
945 contentSize->setWidth(qMax(contentSize->width(), padding));
947 for (PositionedItem &child : positionedItems) {
948 positionItem(child.itemX() + leftPadding() - child.leftPadding, voffset, &child);
949 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
950 contentSize->setWidth(qMax(contentSize->width(), child.item->width() + padding));
952 voffset += child.item->height();
953 voffset += spacing();
956 if (voffset - topPadding() != 0)
957 voffset -= spacing();
958 contentSize->setHeight(voffset + bottomPadding());
961void QQuickColumn::reportConflictingAnchors()
963 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(
this));
964 for (
const PositionedItem &child : positionedItems) {
966 QQuickAnchors *anchors = QQuickItemPrivate::get(
static_cast<QQuickItem *>(child.item))->_anchors;
968 QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
969 if (usedAnchors & QQuickAnchors::TopAnchor ||
970 usedAnchors & QQuickAnchors::BottomAnchor ||
971 usedAnchors & QQuickAnchors::VCenterAnchor ||
972 anchors->fill() || anchors->centerIn()) {
973 d->anchorConflict =
true;
979 if (d->anchorConflict) {
980 qmlWarning(
this) <<
"Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column."
981 <<
" Column will not function.";
1189void QQuickRow::doPositioning(QSizeF *contentSize)
1192 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(
this));
1193 qreal hoffset1 = leftPadding();
1194 qreal hoffset2 = rightPadding();
1195 if (!d->isLeftToRight())
1196 qSwap(hoffset1, hoffset2);
1197 qreal hoffset = hoffset1;
1198 const qreal padding = topPadding() + bottomPadding();
1199 contentSize->setHeight(qMax(contentSize->height(), padding));
1201 QList<qreal> hoffsets;
1202 for (PositionedItem &child : positionedItems) {
1203 if (d->isLeftToRight()) {
1204 positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
1205 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
1207 hoffsets << hoffset;
1210 contentSize->setHeight(qMax(contentSize->height(), child.item->height() + padding));
1212 hoffset += child.item->width();
1213 hoffset += spacing();
1216 if (hoffset - hoffset1 != 0)
1217 hoffset -= spacing();
1218 contentSize->setWidth(hoffset + hoffset2);
1220 if (d->isLeftToRight())
1226 end = contentSize->width();
1231 for (PositionedItem &child : positionedItems) {
1232 hoffset = end - hoffsets[acc++] - child.item->width();
1233 positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child);
1234 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
1238void QQuickRow::reportConflictingAnchors()
1240 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(
this));
1241 for (
const PositionedItem &child : positionedItems) {
1243 QQuickAnchors *anchors = QQuickItemPrivate::get(
static_cast<QQuickItem *>(child.item))->_anchors;
1245 QQuickAnchors::Anchors usedAnchors = anchors->usedAnchors();
1246 if (usedAnchors & QQuickAnchors::LeftAnchor ||
1247 usedAnchors & QQuickAnchors::RightAnchor ||
1248 usedAnchors & QQuickAnchors::HCenterAnchor ||
1249 anchors->fill() || anchors->centerIn()) {
1250 d->anchorConflict =
true;
1256 if (d->anchorConflict)
1257 qmlWarning(
this) <<
"Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row."
1258 <<
" Row will not function.";
1695void QQuickGrid::doPositioning(QSizeF *contentSize)
1698 QQuickBasePositionerPrivate *d =
static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(
this));
1701 const int numVisible =
int(positionedItems.size());
1703 if (m_columns <= 0 && m_rows <= 0) {
1705 r = (numVisible+3)/4;
1706 }
else if (m_rows <= 0) {
1707 r = (numVisible+(m_columns-1))/m_columns;
1708 }
else if (m_columns <= 0) {
1709 c = (numVisible+(m_rows-1))/m_rows;
1712 if (r == 0 || c == 0) {
1713 contentSize->setHeight(topPadding() + bottomPadding());
1714 contentSize->setWidth(leftPadding() + rightPadding());
1718 if (numVisible > r * c) {
1719 qmlWarning(
this) <<
"Grid contains more visible items (" << numVisible <<
") than rows*columns (" << r * c <<
")";
1722 QList<qreal> maxColWidth;
1723 QList<qreal> maxRowHeight;
1725 if (m_flow == LeftToRight) {
1726 for (
int i = 0; i < r; i++) {
1727 for (
int j = 0; j < c; j++) {
1733 if (childIndex == numVisible)
1736 const PositionedItem &child = positionedItems[childIndex++];
1737 if (child.item->width() > maxColWidth[j])
1738 maxColWidth[j] = child.item->width();
1739 if (child.item->height() > maxRowHeight[i])
1740 maxRowHeight[i] = child.item->height();
1744 for (
int j = 0; j < c; j++) {
1745 for (
int i = 0; i < r; i++) {
1751 if (childIndex == numVisible)
1754 const PositionedItem &child = positionedItems[childIndex++];
1755 if (child.item->width() > maxColWidth[j])
1756 maxColWidth[j] = child.item->width();
1757 if (child.item->height() > maxRowHeight[i])
1758 maxRowHeight[i] = child.item->height();
1763 qreal columnSpacing = m_useColumnSpacing ? m_columnSpacing : spacing();
1764 qreal rowSpacing = m_useRowSpacing ? m_rowSpacing : spacing();
1767 for (
int j = 0; j < maxColWidth.size(); j++) {
1769 widthSum += columnSpacing;
1770 widthSum += maxColWidth[j];
1772 widthSum += leftPadding() + rightPadding();
1774 qreal heightSum = 0;
1775 for (
int i = 0; i < maxRowHeight.size(); i++) {
1777 heightSum += rowSpacing;
1778 heightSum += maxRowHeight[i];
1780 heightSum += topPadding() + bottomPadding();
1782 contentSize->setHeight(heightSum);
1783 contentSize->setWidth(widthSum);
1791 qreal xoffset = leftPadding();
1792 if (!d->isLeftToRight())
1793 xoffset = end - rightPadding();
1794 qreal yoffset = topPadding();
1797 for (PositionedItem &child : positionedItems) {
1798 qreal childXOffset = xoffset;
1800 if (effectiveHAlign() == AlignRight)
1801 childXOffset += maxColWidth[curCol] - child.item->width();
1802 else if (hItemAlign() == AlignHCenter)
1803 childXOffset += (maxColWidth[curCol] - child.item->width())/2.0;
1805 if (!d->isLeftToRight())
1806 childXOffset -= maxColWidth[curCol];
1808 qreal alignYOffset = yoffset;
1809 if (m_vItemAlign == AlignVCenter)
1810 alignYOffset += (maxRowHeight[curRow] - child.item->height())/2.0;
1811 else if (m_vItemAlign == AlignBottom)
1812 alignYOffset += maxRowHeight[curRow] - child.item->height();
1814 positionItem(childXOffset, alignYOffset, &child);
1815 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
1817 if (m_flow == LeftToRight) {
1818 if (d->isLeftToRight())
1819 xoffset += maxColWidth[curCol]+columnSpacing;
1821 xoffset -= maxColWidth[curCol]+columnSpacing;
1825 yoffset += maxRowHeight[curRow]+rowSpacing;
1826 if (d->isLeftToRight())
1827 xoffset = leftPadding();
1829 xoffset = end - rightPadding();
1835 yoffset += maxRowHeight[curRow]+rowSpacing;
1839 if (d->isLeftToRight())
1840 xoffset += maxColWidth[curCol]+columnSpacing;
1842 xoffset -= maxColWidth[curCol]+columnSpacing;
1843 yoffset = topPadding();
2105void QQuickFlow::doPositioning(QSizeF *contentSize)
2110 qreal hoffset1 = leftPadding();
2111 qreal hoffset2 = rightPadding();
2112 if (!d->isLeftToRight())
2113 qSwap(hoffset1, hoffset2);
2114 qreal hoffset = hoffset1;
2115 const qreal voffset1 = topPadding();
2116 qreal voffset = voffset1;
2118 QList<qreal> hoffsets;
2119 contentSize->setWidth(qMax(contentSize->width(), hoffset1 + hoffset2));
2120 contentSize->setHeight(qMax(contentSize->height(), voffset + bottomPadding()));
2122 for (PositionedItem &child : positionedItems) {
2123 if (d->flow == LeftToRight) {
2124 if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) {
2126 voffset += linemax + spacing();
2130 if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) {
2132 hoffset += linemax + spacing();
2137 if (d->isLeftToRight()) {
2138 positionItem(hoffset, voffset, &child);
2139 child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding());
2141 hoffsets << hoffset;
2142 positionItemY(voffset, &child);
2143 child.topPadding = topPadding();
2144 child.bottomPadding = bottomPadding();
2147 contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2));
2148 contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding()));
2150 if (d->flow == LeftToRight) {
2151 hoffset += child.item->width();
2152 hoffset += spacing();
2153 linemax = qMax(linemax, child.item->height());
2155 voffset += child.item->height();
2156 voffset += spacing();
2157 linemax = qMax(linemax, child.item->width());
2161 if (d->isLeftToRight())
2168 end = contentSize->width();
2170 for (PositionedItem &child : positionedItems) {
2171 hoffset = end - hoffsets[acc++] - child.item->width();
2172 positionItemX(hoffset, &child);
2173 child.leftPadding = leftPadding();
2174 child.rightPadding = rightPadding();