From 3dd45840c881e90904781169bfd546e1f58eac30 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 22 Feb 2012 12:16:50 +1000 Subject: Positioners cleanup Use qreal for positions and spacing instead of ints, and make the positionedItems list take care of filtering out invisible items. Change-Id: Icad93ad89c848e40a70bd7a9539bd810e27020df Reviewed-by: Bea Lam --- src/quick/items/qquickpositioners.cpp | 155 +++++++++++++++++--------------- src/quick/items/qquickpositioners_p.h | 31 ++++--- src/quick/items/qquickpositioners_p_p.h | 2 +- 3 files changed, 100 insertions(+), 88 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index fc77cf7938..77d2a360b8 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -121,13 +121,13 @@ void QQuickBasePositioner::updatePolish() prePositioning(); } -int QQuickBasePositioner::spacing() const +qreal QQuickBasePositioner::spacing() const { Q_D(const QQuickBasePositioner); return d->spacing; } -void QQuickBasePositioner::setSpacing(int s) +void QQuickBasePositioner::setSpacing(qreal s) { Q_D(QQuickBasePositioner); if (s == d->spacing) @@ -210,32 +210,39 @@ void QQuickBasePositioner::prePositioning() QPODVector oldItems; positionedItems.copyAndClear(oldItems); + for (int ii = 0; ii < unpositionedItems.count(); ii++) + oldItems.append(unpositionedItems[ii]); + unpositionedItems.clear(); + for (int ii = 0; ii < children.count(); ++ii) { QQuickItem *child = children.at(ii); QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); - PositionedItem *item = 0; PositionedItem posItem(child); int wIdx = oldItems.find(posItem); if (wIdx < 0) { d->watchChanges(child); - positionedItems.append(posItem); - item = &positionedItems[positionedItems.count()-1]; - item->isNew = true; - if (!childPrivate->explicitVisible || !child->width() || !child->height()) - item->isVisible = false; + posItem.isNew = true; + if (!childPrivate->explicitVisible || !child->width() || !child->height()) { + posItem.isVisible = false; + unpositionedItems.append(posItem); + } else { + positionedItems.append(posItem); + } } else { - item = &oldItems[wIdx]; + PositionedItem *item = &oldItems[wIdx]; // Items are only omitted from positioning if they are explicitly hidden // i.e. their positioning is not affected if an ancestor is hidden. if (!childPrivate->explicitVisible || !child->width() || !child->height()) { item->isVisible = false; + unpositionedItems.append(*item); } else if (!item->isVisible) { item->isVisible = true; item->isNew = true; + positionedItems.append(*item); } else { item->isNew = false; + positionedItems.append(*item); } - positionedItems.append(*item); } } QSizeF contentSize(0,0); @@ -251,7 +258,7 @@ void QQuickBasePositioner::prePositioning() setImplicitSize(contentSize.width(), contentSize.height()); } -void QQuickBasePositioner::positionX(int x, const PositionedItem &target) +void QQuickBasePositioner::positionX(qreal x, const PositionedItem &target) { Q_D(QQuickBasePositioner); if (d->type == Horizontal || d->type == Both) { @@ -269,7 +276,7 @@ void QQuickBasePositioner::positionX(int x, const PositionedItem &target) } } -void QQuickBasePositioner::positionY(int y, const PositionedItem &target) +void QQuickBasePositioner::positionY(qreal y, const PositionedItem &target) { Q_D(QQuickBasePositioner); if (d->type == Vertical || d->type == Both) { @@ -515,7 +522,7 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem) \sa add, {declarative/positioners}{Positioners example} */ /*! - \qmlproperty int QtQuick2::Column::spacing + \qmlproperty real QtQuick2::Column::spacing The spacing is the amount in pixels left empty between adjacent items. The default spacing is 0. @@ -529,12 +536,11 @@ QQuickColumn::QQuickColumn(QQuickItem *parent) void QQuickColumn::doPositioning(QSizeF *contentSize) { - int voffset = 0; + //Precondition: All items in the positioned list have a valid item pointer and should be positioned + qreal voffset = 0; for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); - if (!child.item || !child.isVisible) - continue; if (child.item->y() != voffset) positionY(voffset, child); @@ -652,7 +658,7 @@ void QQuickColumn::reportConflictingAnchors() \sa add, {declarative/positioners}{Positioners example} */ /*! - \qmlproperty int QtQuick2::Row::spacing + \qmlproperty real QtQuick2::Row::spacing The spacing is the amount in pixels left empty between adjacent items. The default spacing is 0. @@ -719,14 +725,13 @@ Qt::LayoutDirection QQuickRow::effectiveLayoutDirection() const void QQuickRow::doPositioning(QSizeF *contentSize) { + //Precondition: All items in the positioned list have a valid item pointer and should be positioned QQuickBasePositionerPrivate *d = static_cast(QQuickBasePositionerPrivate::get(this)); - int hoffset = 0; + qreal hoffset = 0; - QList hoffsets; + QList hoffsets; for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); - if (!child.item || !child.isVisible) - continue; if (d->isLeftToRight()) { if (child.item->x() != hoffset) @@ -749,7 +754,7 @@ void QQuickRow::doPositioning(QSizeF *contentSize) return; //Right to Left layout - int end = 0; + qreal end = 0; if (!widthValid()) end = contentSize->width(); else @@ -758,8 +763,6 @@ void QQuickRow::doPositioning(QSizeF *contentSize) int acc = 0; for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); - if (!child.item || !child.isVisible) - continue; hoffset = end - hoffsets[acc++] - child.item->width(); if (child.item->x() != hoffset) positionX(hoffset, child); @@ -868,7 +871,7 @@ void QQuickRow::reportConflictingAnchors() \sa add, {declarative/positioners}{Positioners example} */ /*! - \qmlproperty int QtQuick2::Grid::spacing + \qmlproperty qreal QtQuick2::Grid::spacing The spacing is the amount in pixels left empty between adjacent items. The amount of spacing applied will be the same in the @@ -885,8 +888,15 @@ void QQuickRow::reportConflictingAnchors() \sa rows, columns */ -QQuickGrid::QQuickGrid(QQuickItem *parent) : - QQuickBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_rowSpacing(-1), m_columnSpacing(-1), m_flow(LeftToRight) +QQuickGrid::QQuickGrid(QQuickItem *parent) + : QQuickBasePositioner(Both, parent) + , m_rows(-1) + , m_columns(-1) + , m_rowSpacing(-1) + , m_columnSpacing(-1) + , m_useRowSpacing(false) + , m_useColumnSpacing(false) + , m_flow(LeftToRight) { } @@ -954,35 +964,45 @@ void QQuickGrid::setFlow(Flow flow) } /*! - \qmlproperty int QtQuick2::Grid::rowSpacing + \qmlproperty qreal QtQuick2::Grid::rowSpacing This property holds the spacing in pixels between rows. + If this property is not set, then spacing is used for the row spacing. + + By default this property is not set. + \sa columnSpacing \since QtQuick2.0 */ -void QQuickGrid::setRowSpacing(const int rowSpacing) +void QQuickGrid::setRowSpacing(const qreal rowSpacing) { if (rowSpacing == m_rowSpacing) return; m_rowSpacing = rowSpacing; + m_useRowSpacing = true; prePositioning(); emit rowSpacingChanged(); } /*! - \qmlproperty int QtQuick2::Grid::columnSpacing + \qmlproperty qreal QtQuick2::Grid::columnSpacing This property holds the spacing in pixels between columns. + If this property is not set, then spacing is used for the column spacing. + + By default this property is not set. + \sa rowSpacing \since QtQuick2.0 */ -void QQuickGrid::setColumnSpacing(const int columnSpacing) +void QQuickGrid::setColumnSpacing(const qreal columnSpacing) { if (columnSpacing == m_columnSpacing) return; m_columnSpacing = columnSpacing; + m_useColumnSpacing = true; prePositioning(); emit columnSpacingChanged(); } @@ -1043,18 +1063,13 @@ Qt::LayoutDirection QQuickGrid::effectiveLayoutDirection() const void QQuickGrid::doPositioning(QSizeF *contentSize) { + //Precondition: All items in the positioned list have a valid item pointer and should be positioned QQuickBasePositionerPrivate *d = static_cast(QQuickBasePositionerPrivate::get(this)); int c = m_columns; int r = m_rows; - //Is allocating the extra QPODVector too much overhead? - QPODVector visibleItems;//we aren't concerned with invisible items - visibleItems.reserve(positionedItems.count()); - for (int i=0; i maxColWidth; - QList maxRowHeight; + QList maxColWidth; + QList maxRowHeight; int childIndex =0; if (m_flow == LeftToRight) { for (int i = 0; i < r; i++) { @@ -1077,10 +1092,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) if (i == 0) maxColWidth << 0; - if (childIndex == visibleItems.count()) + if (childIndex == numVisible) break; - const PositionedItem &child = visibleItems.at(childIndex++); + const PositionedItem &child = positionedItems.at(childIndex++); if (child.item->width() > maxColWidth[j]) maxColWidth[j] = child.item->width(); if (child.item->height() > maxRowHeight[i]) @@ -1095,10 +1110,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) if (i == 0) maxColWidth << 0; - if (childIndex == visibleItems.count()) + if (childIndex == numVisible) break; - const PositionedItem &child = visibleItems.at(childIndex++); + const PositionedItem &child = positionedItems.at(childIndex++); if (child.item->width() > maxColWidth[j]) maxColWidth[j] = child.item->width(); if (child.item->height() > maxRowHeight[i]) @@ -1107,23 +1122,18 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) } } - int columnSpacing = m_columnSpacing; - if (columnSpacing == -1) - columnSpacing = spacing(); - - int rowSpacing = m_rowSpacing; - if (rowSpacing == -1) - rowSpacing = spacing(); + qreal columnSpacing = m_useColumnSpacing ? m_columnSpacing : spacing(); + qreal rowSpacing = m_useRowSpacing ? m_rowSpacing : spacing(); - int widthSum = 0; - for (int j=0; j < maxColWidth.size(); j++){ + qreal widthSum = 0; + for (int j = 0; j < maxColWidth.size(); j++) { if (j) widthSum += columnSpacing; widthSum += maxColWidth[j]; } - int heightSum = 0; - for (int i=0; i < maxRowHeight.size(); i++){ + qreal heightSum = 0; + for (int i = 0; i < maxRowHeight.size(); i++) { if (i) heightSum += rowSpacing; heightSum += maxRowHeight[i]; @@ -1138,15 +1148,15 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) else end = widthSum; - int xoffset=0; + qreal xoffset = 0; if (!d->isLeftToRight()) xoffset = end; - int yoffset=0; + qreal yoffset = 0; int curRow =0; int curCol =0; - for (int i = 0; i < visibleItems.count(); ++i) { - const PositionedItem &child = visibleItems.at(i); - int childXOffset = xoffset; + for (int i = 0; i < positionedItems.count(); ++i) { + const PositionedItem &child = positionedItems.at(i); + qreal childXOffset = xoffset; if (!d->isLeftToRight()) childXOffset -= child.item->width(); if ((child.item->x() != childXOffset) || (child.item->y() != yoffset)) { @@ -1277,7 +1287,7 @@ void QQuickGrid::reportConflictingAnchors() \sa add, {declarative/positioners}{Positioners example} */ /*! - \qmlproperty int QtQuick2::Flow::spacing + \qmlproperty real QtQuick2::Flow::spacing spacing is the amount in pixels left empty between each adjacent item, and defaults to 0. @@ -1390,17 +1400,16 @@ Qt::LayoutDirection QQuickFlow::effectiveLayoutDirection() const void QQuickFlow::doPositioning(QSizeF *contentSize) { + //Precondition: All items in the positioned list have a valid item pointer and should be positioned Q_D(QQuickFlow); - int hoffset = 0; - int voffset = 0; - int linemax = 0; - QList hoffsets; + qreal hoffset = 0; + qreal voffset = 0; + qreal linemax = 0; + QList hoffsets; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); - if (!child.item || !child.isVisible) - continue; if (d->flow == LeftToRight) { if (widthValid() && hoffset && hoffset + child.item->width() > width()) { @@ -1431,17 +1440,17 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) if (d->flow == LeftToRight) { hoffset += child.item->width(); hoffset += spacing(); - linemax = qMax(linemax, qCeil(child.item->height())); + linemax = qMax(linemax, child.item->height()); } else { voffset += child.item->height(); voffset += spacing(); - linemax = qMax(linemax, qCeil(child.item->width())); + linemax = qMax(linemax, child.item->width()); } } if (d->isLeftToRight()) return; - int end; + qreal end; if (widthValid()) end = width(); else @@ -1449,8 +1458,6 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) int acc = 0; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); - if (!child.item || !child.isVisible) - continue; hoffset = end - hoffsets[acc++] - child.item->width(); if (child.item->x() != hoffset) positionX(hoffset, child); diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index 305aae6340..a4f18cfc21 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -91,7 +91,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte { Q_OBJECT - Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) + Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) Q_PROPERTY(QDeclarativeTransition *move READ move WRITE setMove NOTIFY moveChanged) Q_PROPERTY(QDeclarativeTransition *add READ add WRITE setAdd NOTIFY addChanged) public: @@ -99,8 +99,8 @@ public: QQuickBasePositioner(PositionerType, QQuickItem *parent); ~QQuickBasePositioner(); - int spacing() const; - void setSpacing(int); + qreal spacing() const; + void setSpacing(qreal); QDeclarativeTransition *move() const; void setMove(QDeclarativeTransition *); @@ -141,8 +141,9 @@ protected: }; QPODVector positionedItems; - void positionX(int,const PositionedItem &target); - void positionY(int,const PositionedItem &target); + QPODVector unpositionedItems;//Still 'in' the positioner, just not positioned + void positionX(qreal,const PositionedItem &target); + void positionY(qreal,const PositionedItem &target); private: Q_DISABLE_COPY(QQuickBasePositioner) @@ -190,8 +191,8 @@ class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner Q_OBJECT Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged) - Q_PROPERTY(int rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged) - Q_PROPERTY(int columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged) + Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged RESET resetRowSpacing) + Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged RESET resetColumnSpacing) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) @@ -205,11 +206,13 @@ public: int columns() const { return m_columns; } void setColumns(const int columns); - int rowSpacing() const { return m_rowSpacing; } - void setRowSpacing(int); + qreal rowSpacing() const { return m_rowSpacing; } + void setRowSpacing(qreal); + void resetRowSpacing() { m_useRowSpacing = false; } - int columnSpacing() const { return m_columnSpacing; } - void setColumnSpacing(int); + qreal columnSpacing() const { return m_columnSpacing; } + void setColumnSpacing(qreal); + void resetColumnSpacing() { m_useColumnSpacing = false; } Q_ENUMS(Flow) enum Flow { LeftToRight, TopToBottom }; @@ -236,8 +239,10 @@ protected: private: int m_rows; int m_columns; - int m_rowSpacing; - int m_columnSpacing; + qreal m_rowSpacing; + qreal m_columnSpacing; + bool m_useRowSpacing; + bool m_useColumnSpacing; Flow m_flow; Q_DISABLE_COPY(QQuickGrid) }; diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h index da55a1e79d..d281f1a372 100644 --- a/src/quick/items/qquickpositioners_p_p.h +++ b/src/quick/items/qquickpositioners_p_p.h @@ -84,7 +84,7 @@ public: childrenDoNotOverlap = true; } - int spacing; + qreal spacing; QQuickBasePositioner::PositionerType type; QDeclarativeTransition *moveTransition; -- cgit v1.2.3