Changeset 846 for trunk/src/gui/graphicsview/qgridlayoutengine.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/gui/graphicsview/qgridlayoutengine.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 167 167 } 168 168 169 void QGridLayoutRowData::distributeMultiCells( )169 void QGridLayoutRowData::distributeMultiCells(const QGridLayoutRowInfo &rowInfo) 170 170 { 171 171 MultiCellMap::const_iterator i = multiCellMap.constBegin(); … … 186 186 if (extra > 0.0) { 187 187 calculateGeometries(start, end, box.q_sizes(j), dummy.data(), newSizes.data(), 188 0, totalBox );188 0, totalBox, rowInfo); 189 189 190 190 for (int k = 0; k < span; ++k) … … 195 195 for (int k = 0; k < span; ++k) { 196 196 boxes[start + k].combine(extras[k]); 197 stretches[start + k] = qMax(stretches[start + k], stretch); 197 if (stretch != 0) 198 stretches[start + k] = qMax(stretches[start + k], stretch); 198 199 } 199 200 } … … 203 204 void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSize, qreal *positions, 204 205 qreal *sizes, qreal *descents, 205 const QGridLayoutBox &totalBox) 206 const QGridLayoutBox &totalBox, 207 const QGridLayoutRowInfo &rowInfo) 206 208 { 207 209 Q_ASSERT(end > start); 208 210 209 targetSize = q Bound(totalBox.q_minimumSize, targetSize, totalBox.q_maximumSize);211 targetSize = qMax(totalBox.q_minimumSize, targetSize); 210 212 211 213 int n = end - start; … … 247 249 } 248 250 } else { 249 stealBox(start, end, PreferredSize, positions, sizes); 250 251 sumAvailable = targetSize - totalBox.q_preferredSize; 251 bool isLargerThanMaximum = (targetSize > totalBox.q_maximumSize); 252 if (isLargerThanMaximum) { 253 stealBox(start, end, MaximumSize, positions, sizes); 254 sumAvailable = targetSize - totalBox.q_maximumSize; 255 } else { 256 stealBox(start, end, PreferredSize, positions, sizes); 257 sumAvailable = targetSize - totalBox.q_preferredSize; 258 } 259 252 260 if (sumAvailable > 0.0) { 261 qreal sumCurrentAvailable = sumAvailable; 253 262 bool somethingHasAMaximumSize = false; 254 263 255 qreal sum PreferredSizes = 0.0;264 qreal sumSizes = 0.0; 256 265 for (int i = 0; i < n; ++i) 257 sum PreferredSizes += sizes[i];266 sumSizes += sizes[i]; 258 267 259 268 for (int i = 0; i < n; ++i) { … … 265 274 266 275 const QGridLayoutBox &box = boxes.at(start + i); 267 qreal desired = box.q_maximumSize - box.q_preferredSize; 276 qreal boxSize; 277 278 qreal desired; 279 if (isLargerThanMaximum) { 280 boxSize = box.q_maximumSize; 281 desired = rowInfo.boxes.value(start + i).q_maximumSize - boxSize; 282 } else { 283 boxSize = box.q_preferredSize; 284 desired = box.q_maximumSize - boxSize; 285 } 268 286 if (desired == 0.0) { 269 287 newSizes[i] = sizes[i]; … … 284 302 factors[i] = 0.0; 285 303 } else { 286 qreal ultimate PreferredSize;287 qreal ultimateSum PreferredSizes;288 qreal x = ((stretch * sum PreferredSizes)289 - (sumStretches * box .q_preferredSize))304 qreal ultimateSize; 305 qreal ultimateSumSizes; 306 qreal x = ((stretch * sumSizes) 307 - (sumStretches * boxSize)) 290 308 / (sumStretches - stretch); 291 309 if (x >= 0.0) { 292 ultimate PreferredSize = box.q_preferredSize + x;293 ultimateSum PreferredSizes = sumPreferredSizes + x;310 ultimateSize = boxSize + x; 311 ultimateSumSizes = sumSizes + x; 294 312 } else { 295 ultimate PreferredSize = box.q_preferredSize;296 ultimateSum PreferredSizes = (sumStretches * box.q_preferredSize)313 ultimateSize = boxSize; 314 ultimateSumSizes = (sumStretches * boxSize) 297 315 / stretch; 298 316 } … … 303 321 during the transition). 304 322 */ 305 ultimatePreferredSize = ultimatePreferredSize * 3 / 2; 306 ultimateSumPreferredSizes = ultimateSumPreferredSizes * 3 / 2; 307 308 qreal ultimateFactor = (stretch * ultimateSumPreferredSizes 309 / sumStretches) 310 - (box.q_preferredSize); 311 qreal transitionalFactor = sumAvailable 312 * (ultimatePreferredSize - box.q_preferredSize) 313 / (ultimateSumPreferredSizes 314 - sumPreferredSizes); 315 316 qreal alpha = qMin(sumAvailable, 317 ultimateSumPreferredSizes - sumPreferredSizes); 318 qreal beta = ultimateSumPreferredSizes - sumPreferredSizes; 319 320 factors[i] = ((alpha * ultimateFactor) 321 + ((beta - alpha) * transitionalFactor)) / beta; 323 ultimateSize = ultimateSize * 3 / 2; 324 ultimateSumSizes = ultimateSumSizes * 3 / 2; 325 326 qreal beta = ultimateSumSizes - sumSizes; 327 if (!beta) { 328 factors[i] = 1; 329 } else { 330 qreal alpha = qMin(sumCurrentAvailable, beta); 331 qreal ultimateFactor = (stretch * ultimateSumSizes / sumStretches) 332 - (boxSize); 333 qreal transitionalFactor = sumCurrentAvailable * (ultimateSize - boxSize) / beta; 334 335 factors[i] = ((alpha * ultimateFactor) 336 + ((beta - alpha) * transitionalFactor)) / beta; 337 } 338 322 339 } 323 340 sumFactors += factors[i]; 324 if (desired < sum Available)341 if (desired < sumCurrentAvailable) 325 342 somethingHasAMaximumSize = true; 326 343 … … 337 354 continue; 338 355 339 const QGridLayoutBox &box = boxes.at(start + i); 340 qreal avail = sumAvailable * factors[i] / sumFactors; 341 if (sizes[i] + avail >= box.q_maximumSize) { 342 newSizes[i] = box.q_maximumSize; 343 sumAvailable -= box.q_maximumSize - sizes[i]; 356 qreal maxBoxSize; 357 if (isLargerThanMaximum) 358 maxBoxSize = rowInfo.boxes.value(start + i).q_maximumSize; 359 else 360 maxBoxSize = boxes.at(start + i).q_maximumSize; 361 362 qreal avail = sumCurrentAvailable * factors[i] / sumFactors; 363 if (sizes[i] + avail >= maxBoxSize) { 364 newSizes[i] = maxBoxSize; 365 sumCurrentAvailable -= maxBoxSize - sizes[i]; 344 366 sumFactors -= factors[i]; 345 keepGoing = (sum Available > 0.0);367 keepGoing = (sumCurrentAvailable > 0.0); 346 368 if (!keepGoing) 347 369 break; … … 353 375 if (newSizes[i] < 0.0) { 354 376 qreal delta = (sumFactors == 0.0) ? 0.0 355 : sum Available * factors[i] / sumFactors;377 : sumCurrentAvailable * factors[i] / sumFactors; 356 378 newSizes[i] = sizes[i] + delta; 357 379 } … … 546 568 } 547 569 570 /* 571 returns true if the size policy returns true for either hasHeightForWidth() 572 or hasWidthForHeight() 573 */ 574 bool QGridLayoutItem::hasDynamicConstraint() const 575 { 576 return QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth() 577 || QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight(); 578 } 579 580 Qt::Orientation QGridLayoutItem::dynamicConstraintOrientation() const 581 { 582 if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth()) 583 return Qt::Vertical; 584 else //if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight()) 585 return Qt::Horizontal; 586 } 587 548 588 QSizePolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /* side */) const 549 589 { … … 614 654 qreal cellHeight = height; 615 655 616 QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight)); 656 657 QSizeF size = effectiveMaxSize(QSizeF(-1,-1)); 658 if (hasDynamicConstraint()) { 659 if (dynamicConstraintOrientation() == Qt::Vertical) { 660 if (size.width() > cellWidth) 661 size = effectiveMaxSize(QSizeF(cellWidth, -1)); 662 } else if (size.height() > cellHeight) { 663 size = effectiveMaxSize(QSizeF(-1, cellHeight)); 664 } 665 } 666 size = size.boundedTo(QSizeF(cellWidth, cellHeight)); 617 667 width = size.width(); 618 668 height = size.height(); … … 676 726 (since it only evaluates the hints, as the name implies) 677 727 */ 678 QSizeF QGridLayoutItem::effectiveMaxSize( ) const679 { 680 QSizeF size ;728 QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const 729 { 730 QSizeF size = constraint; 681 731 bool vGrow = (sizePolicy(Qt::Vertical) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; 682 732 bool hGrow = (sizePolicy(Qt::Horizontal) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; 683 733 if (!vGrow || !hGrow) { 684 QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize );734 QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize, constraint); 685 735 if (!vGrow) 686 736 size.setHeight(pref.height()); … … 690 740 691 741 if (!size.isValid()) { 692 QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize );742 QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, size); 693 743 if (size.width() == -1) 694 744 size.setWidth(maxSize.width()); … … 1011 1061 q_cachedDataForStyleInfo.invalidate(); 1012 1062 q_cachedSize = QSizeF(); 1063 q_cachedConstraintOrientation = UnknownConstraint; 1013 1064 } 1014 1065 … … 1075 1126 1076 1127 QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, 1077 const QSizeF & /* constraint */) const 1078 { 1079 ensureColumnAndRowData(styleInfo); 1128 const QSizeF &constraint) const 1129 { 1130 QGridLayoutBox sizehint_totalBoxes[NOrientations]; 1131 1132 bool sizeHintCalculated = false; 1133 1134 if (hasDynamicConstraint() && rowCount() > 0 && columnCount() > 0) { 1135 if (constraintOrientation() == Qt::Vertical) { 1136 //We have items whose height depends on their width 1137 if (constraint.width() >= 0) { 1138 if (q_cachedDataForStyleInfo != styleInfo) 1139 ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); 1140 else 1141 sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; 1142 QVector<qreal> sizehint_xx; 1143 QVector<qreal> sizehint_widths; 1144 1145 sizehint_xx.resize(columnCount()); 1146 sizehint_widths.resize(columnCount()); 1147 qreal width = constraint.width(); 1148 //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as 1149 //constraints to find the row heights 1150 q_columnData.calculateGeometries(0, columnCount(), width, sizehint_xx.data(), sizehint_widths.data(), 1151 0, sizehint_totalBoxes[Hor], q_infos[Hor]); 1152 ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, sizehint_xx.data(), sizehint_widths.data(), Qt::Vertical); 1153 sizeHintCalculated = true; 1154 } 1155 } else { 1156 if (constraint.height() >= 0) { 1157 //We have items whose width depends on their height 1158 ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); 1159 QVector<qreal> sizehint_yy; 1160 QVector<qreal> sizehint_heights; 1161 1162 sizehint_yy.resize(rowCount()); 1163 sizehint_heights.resize(rowCount()); 1164 qreal height = constraint.height(); 1165 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as 1166 //constraints to find the column widths 1167 q_rowData.calculateGeometries(0, rowCount(), height, sizehint_yy.data(), sizehint_heights.data(), 1168 0, sizehint_totalBoxes[Ver], q_infos[Ver]); 1169 ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, sizehint_yy.data(), sizehint_heights.data(), Qt::Vertical); 1170 sizeHintCalculated = true; 1171 } 1172 } 1173 } 1174 1175 if (!sizeHintCalculated) { 1176 //No items with height for width, so it doesn't matter which order we do these in 1177 if (q_cachedDataForStyleInfo != styleInfo) { 1178 ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); 1179 ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); 1180 } else { 1181 sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; 1182 sizehint_totalBoxes[Ver] = q_totalBoxes[Ver]; 1183 } 1184 } 1080 1185 1081 1186 switch (which) { 1082 1187 case Qt::MinimumSize: 1083 return QSizeF( q_totalBoxes[Hor].q_minimumSize, q_totalBoxes[Ver].q_minimumSize);1188 return QSizeF(sizehint_totalBoxes[Hor].q_minimumSize, sizehint_totalBoxes[Ver].q_minimumSize); 1084 1189 case Qt::PreferredSize: 1085 return QSizeF( q_totalBoxes[Hor].q_preferredSize, q_totalBoxes[Ver].q_preferredSize);1190 return QSizeF(sizehint_totalBoxes[Hor].q_preferredSize, sizehint_totalBoxes[Ver].q_preferredSize); 1086 1191 case Qt::MaximumSize: 1087 return QSizeF( q_totalBoxes[Hor].q_maximumSize, q_totalBoxes[Ver].q_maximumSize);1192 return QSizeF(sizehint_totalBoxes[Hor].q_maximumSize, sizehint_totalBoxes[Ver].q_maximumSize); 1088 1193 case Qt::MinimumDescent: 1089 return QSizeF(-1.0, q_totalBoxes[Hor].q_minimumDescent); // ### doesn't work1194 return QSizeF(-1.0, sizehint_totalBoxes[Hor].q_minimumDescent); // ### doesn't work 1090 1195 default: 1091 1196 break; … … 1263 1368 1264 1369 void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo, 1370 qreal *colPositions, qreal *colSizes, 1265 1371 Qt::Orientation orientation) const 1266 1372 { … … 1368 1474 if (effectiveRowSpan == 1) { 1369 1475 box = &rowBox; 1370 if (!userRowStretch )1476 if (!userRowStretch && itemStretch != 0) 1371 1477 rowStretch = qMax(rowStretch, itemStretch); 1372 1478 } else { … … 1376 1482 multiCell.q_stretch = itemStretch; 1377 1483 } 1378 box->combine(item->box(orientation)); 1484 // Items with constraints need to be passed the constraint 1485 if (colSizes && colPositions && item->hasDynamicConstraint() && orientation == item->dynamicConstraintOrientation()) { 1486 /* Get the width of the item by summing up the widths of the columns that it spans. 1487 * We need to have already calculated the widths of the columns by calling 1488 * q_columns->calculateGeometries() before hand and passing the value in the colSizes 1489 * and colPositions parameters. 1490 * The variable name is still colSizes even when it actually has the row sizes 1491 */ 1492 qreal length = colSizes[item->lastColumn(orientation)]; 1493 if (item->columnSpan(orientation) != 1) 1494 length += colPositions[item->lastColumn(orientation)] - colPositions[item->firstColumn(orientation)]; 1495 box->combine(item->box(orientation, length)); 1496 } else { 1497 box->combine(item->box(orientation)); 1498 } 1379 1499 1380 1500 if (effectiveRowSpan == 1) { … … 1513 1633 } 1514 1634 1515 void QGridLayoutEngine::ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo) const 1516 { 1517 if (q_cachedDataForStyleInfo == styleInfo) 1518 return; 1519 1520 q_columnData.reset(columnCount()); 1521 q_rowData.reset(rowCount()); 1522 1523 fillRowData(&q_columnData, styleInfo, Qt::Horizontal); 1524 fillRowData(&q_rowData, styleInfo, Qt::Vertical); 1525 1526 q_columnData.distributeMultiCells(); 1527 q_rowData.distributeMultiCells(); 1528 1529 q_totalBoxes[Hor] = q_columnData.totalBox(0, columnCount()); 1530 q_totalBoxes[Ver] = q_rowData.totalBox(0, rowCount()); 1531 1532 q_cachedDataForStyleInfo = styleInfo; 1635 void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox, 1636 const QLayoutStyleInfo &styleInfo, 1637 qreal *colPositions, qreal *colSizes, 1638 Qt::Orientation orientation) const 1639 { 1640 rowData->reset(rowCount(orientation)); 1641 fillRowData(rowData, styleInfo, colPositions, colSizes, orientation); 1642 const QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; 1643 rowData->distributeMultiCells(rowInfo); 1644 *totalBox = rowData->totalBox(0, rowCount(orientation)); 1645 //We have items whose width depends on their height 1646 } 1647 1648 /** 1649 returns false if the layout has contradicting constraints (i.e. some items with a horizontal 1650 constraint and other items with a vertical constraint) 1651 */ 1652 bool QGridLayoutEngine::ensureDynamicConstraint() const 1653 { 1654 if (q_cachedConstraintOrientation == UnknownConstraint) { 1655 for (int i = q_items.count() - 1; i >= 0; --i) { 1656 QGridLayoutItem *item = q_items.at(i); 1657 if (item->hasDynamicConstraint()) { 1658 Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation(); 1659 if (q_cachedConstraintOrientation == UnknownConstraint) { 1660 q_cachedConstraintOrientation = itemConstraintOrientation; 1661 } else if (q_cachedConstraintOrientation != itemConstraintOrientation) { 1662 q_cachedConstraintOrientation = UnfeasibleConstraint; 1663 qWarning("QGridLayoutEngine: Unfeasible, cannot mix horizontal and" 1664 " vertical constraint in the same layout"); 1665 return false; 1666 } 1667 } 1668 } 1669 if (q_cachedConstraintOrientation == UnknownConstraint) 1670 q_cachedConstraintOrientation = NoConstraint; 1671 } 1672 return true; 1673 } 1674 1675 bool QGridLayoutEngine::hasDynamicConstraint() const 1676 { 1677 if (!ensureDynamicConstraint()) 1678 return false; 1679 return q_cachedConstraintOrientation != NoConstraint; 1680 } 1681 1682 /* 1683 * return value is only valid if hasConstraint() returns true 1684 */ 1685 Qt::Orientation QGridLayoutEngine::constraintOrientation() const 1686 { 1687 (void)ensureDynamicConstraint(); 1688 return (Qt::Orientation)q_cachedConstraintOrientation; 1533 1689 } 1534 1690 … … 1536 1692 const QSizeF &size) const 1537 1693 { 1538 ensureColumnAndRowData(styleInfo); 1539 if (q_cachedSize == size) 1694 if (q_cachedDataForStyleInfo == styleInfo && q_cachedSize == size) 1540 1695 return; 1541 1696 1697 q_cachedDataForStyleInfo = styleInfo; 1698 q_cachedSize = size; 1699 1542 1700 q_xx.resize(columnCount()); 1701 q_widths.resize(columnCount()); 1543 1702 q_yy.resize(rowCount()); 1544 q_widths.resize(columnCount());1545 1703 q_heights.resize(rowCount()); 1546 1704 q_descents.resize(rowCount()); 1547 q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), 1548 0, q_totalBoxes[Hor]); 1549 q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), 1550 q_descents.data(), q_totalBoxes[Ver]); 1551 1552 q_cachedSize = size; 1705 1706 if (constraintOrientation() != Qt::Horizontal) { 1707 //We might have items whose width depends on their height 1708 ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); 1709 //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as 1710 //constraints to find the row heights 1711 q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), 1712 0, q_totalBoxes[Hor], q_infos[Hor] ); 1713 ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, q_xx.data(), q_widths.data(), Qt::Vertical); 1714 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() 1715 q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), 1716 q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]); 1717 } else { 1718 //We have items whose height depends on their width 1719 ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); 1720 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as 1721 //constraints to find the column widths 1722 q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), 1723 q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]); 1724 ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, q_yy.data(), q_heights.data(), Qt::Horizontal); 1725 //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() 1726 q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), 1727 0, q_totalBoxes[Hor], q_infos[Hor]); 1728 } 1553 1729 } 1554 1730
Note:
See TracChangeset
for help on using the changeset viewer.