summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgridlayoutengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview/qgridlayoutengine.cpp')
-rw-r--r--src/gui/graphicsview/qgridlayoutengine.cpp226
1 files changed, 192 insertions, 34 deletions
diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp
index ae5bf90..e486b4d 100644
--- a/src/gui/graphicsview/qgridlayoutengine.cpp
+++ b/src/gui/graphicsview/qgridlayoutengine.cpp
@@ -545,6 +545,24 @@ QSizePolicy::Policy QGridLayoutItem::sizePolicy(Qt::Orientation orientation) con
: sizePolicy.verticalPolicy();
}
+/*
+ returns true if the size policy returns true for either hasHeightForWidth()
+ or hasWidthForHeight()
+ */
+bool QGridLayoutItem::hasDynamicConstraint() const
+{
+ return QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth()
+ || QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight();
+}
+
+Qt::Orientation QGridLayoutItem::dynamicConstraintOrientation() const
+{
+ if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth())
+ return Qt::Vertical;
+ else //if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight())
+ return Qt::Horizontal;
+}
+
QSizePolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /* side */) const
{
return q_layoutItem->sizePolicy().controlType();
@@ -613,7 +631,17 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig
qreal cellWidth = width;
qreal cellHeight = height;
- QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight));
+
+ QSizeF size = effectiveMaxSize(QSizeF(-1,-1));
+ if (hasDynamicConstraint()) {
+ if (dynamicConstraintOrientation() == Qt::Vertical) {
+ if (size.width() > cellWidth)
+ size = effectiveMaxSize(QSizeF(cellWidth, -1));
+ } else if(size.height() > cellHeight) {
+ size = effectiveMaxSize(QSizeF(-1, cellHeight));
+ }
+ }
+ size = size.boundedTo(QSizeF(cellWidth, cellHeight));
width = size.width();
height = size.height();
@@ -675,13 +703,13 @@ void QGridLayoutItem::insertOrRemoveRows(int row, int delta, Qt::Orientation ori
Note that effectiveSizeHint does not take sizePolicy into consideration,
(since it only evaluates the hints, as the name implies)
*/
-QSizeF QGridLayoutItem::effectiveMaxSize() const
+QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const
{
- QSizeF size;
+ QSizeF size = constraint;
bool vGrow = (sizePolicy(Qt::Vertical) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag;
bool hGrow = (sizePolicy(Qt::Horizontal) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag;
if (!vGrow || !hGrow) {
- QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize);
+ QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize, constraint);
if (!vGrow)
size.setHeight(pref.height());
if (!hGrow)
@@ -689,7 +717,7 @@ QSizeF QGridLayoutItem::effectiveMaxSize() const
}
if (!size.isValid()) {
- QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, size);
if (size.width() == -1)
size.setWidth(maxSize.width());
if (size.height() == -1)
@@ -1010,6 +1038,7 @@ void QGridLayoutEngine::invalidate()
q_cachedEffectiveLastRows[Ver] = -1;
q_cachedDataForStyleInfo.invalidate();
q_cachedSize = QSizeF();
+ q_cachedConstraintOrientation = UnknownConstraint;
}
static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect)
@@ -1074,19 +1103,78 @@ QRectF QGridLayoutEngine::cellRect(const QLayoutStyleInfo &styleInfo,
}
QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which,
- const QSizeF & /* constraint */) const
+ const QSizeF &constraint) const
{
- ensureColumnAndRowData(styleInfo);
+ QGridLayoutBox sizehint_totalBoxes[NOrientations];
+
+ if(rowCount() < 1 || columnCount() < 1 || !hasDynamicConstraint()) {
+ //No items with height for width, so it doesn't matter which order we do these in
+ if(q_cachedDataForStyleInfo != styleInfo) {
+ ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal);
+ ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical);
+ } else {
+ sizehint_totalBoxes[Hor] = q_totalBoxes[Hor];
+ sizehint_totalBoxes[Ver] = q_totalBoxes[Ver];
+ }
+ } else if(constraintOrientation() == Qt::Vertical) {
+ //We have items whose width depends on their height
+ if(q_cachedDataForStyleInfo != styleInfo)
+ ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal);
+ else
+ sizehint_totalBoxes[Hor] = q_totalBoxes[Hor];
+ QVector<qreal> sizehint_xx;
+ QVector<qreal> sizehint_widths;
+
+ sizehint_xx.resize(columnCount());
+ sizehint_widths.resize(columnCount());
+ qreal width = constraint.width();
+ if(width < 0) {
+ /* It's not obvious what the behaviour should be. */
+/* if(which == Qt::MaximumSize)
+ width = sizehint_totalBoxes[Hor].q_maximumSize;
+ else if(which == Qt::MinimumSize)
+ width = sizehint_totalBoxes[Hor].q_minimumSize;
+ else*/
+ width = sizehint_totalBoxes[Hor].q_preferredSize;
+ }
+ //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
+ //constraints to find the row heights
+ q_columnData.calculateGeometries(0, columnCount(), width, sizehint_xx.data(), sizehint_widths.data(),
+ 0, sizehint_totalBoxes[Hor]);
+ ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, sizehint_xx.data(), sizehint_widths.data(), Qt::Vertical);
+ } else {
+ //We have items whose height depends on their width
+ ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical);
+ QVector<qreal> sizehint_yy;
+ QVector<qreal> sizehint_heights;
+
+ sizehint_yy.resize(rowCount());
+ sizehint_heights.resize(rowCount());
+ qreal height = constraint.height();
+ if(height < 0) {
+/* if(which == Qt::MaximumSize)
+ height = sizehint_totalBoxes[Ver].q_maximumSize;
+ else if(which == Qt::MinimumSize)
+ height = sizehint_totalBoxes[Ver].q_minimumSize;
+ else*/
+ height = sizehint_totalBoxes[Ver].q_preferredSize;
+ }
+ //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
+ //constraints to find the column widths
+ q_rowData.calculateGeometries(0, rowCount(), height, sizehint_yy.data(), sizehint_heights.data(),
+ 0, sizehint_totalBoxes[Ver]);
+ ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, sizehint_yy.data(), sizehint_heights.data(), Qt::Vertical);
+ }
switch (which) {
case Qt::MinimumSize:
- return QSizeF(q_totalBoxes[Hor].q_minimumSize, q_totalBoxes[Ver].q_minimumSize);
+ return QSizeF(sizehint_totalBoxes[Hor].q_minimumSize, sizehint_totalBoxes[Ver].q_minimumSize);
case Qt::PreferredSize:
- return QSizeF(q_totalBoxes[Hor].q_preferredSize, q_totalBoxes[Ver].q_preferredSize);
+ return QSizeF(sizehint_totalBoxes[Hor].q_preferredSize, sizehint_totalBoxes[Ver].q_preferredSize);
case Qt::MaximumSize:
- return QSizeF(q_totalBoxes[Hor].q_maximumSize, q_totalBoxes[Ver].q_maximumSize);
+ return QSizeF(sizehint_totalBoxes[Hor].q_maximumSize, sizehint_totalBoxes[Ver].q_maximumSize);
case Qt::MinimumDescent:
- return QSizeF(-1.0, q_totalBoxes[Hor].q_minimumDescent); // ### doesn't work
+ return QSizeF(-1.0, sizehint_totalBoxes[Hor].q_minimumDescent); // ### doesn't work
default:
break;
}
@@ -1262,6 +1350,7 @@ void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation o
}
void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo,
+ qreal *colPositions, qreal *colSizes,
Qt::Orientation orientation) const
{
const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton;
@@ -1375,7 +1464,21 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt
box = &multiCell.q_box;
multiCell.q_stretch = itemStretch;
}
- box->combine(item->box(orientation));
+ // Items with constraints need to be passed the constraint
+ if (colSizes && colPositions && item->hasDynamicConstraint() && orientation == item->dynamicConstraintOrientation()) {
+ /* Get the width of the item by summing up the widths of the columns that it spans.
+ * We need to have already calculated the widths of the columns by calling
+ * q_columns->calculateGeometries() before hand and passing the value in the colSizes
+ * and colPositions parameters.
+ * The variable name is still colSizes even when it actually has the row sizes
+ */
+ qreal length = colSizes[item->lastColumn(orientation)];
+ if (item->columnSpan(orientation) != 1)
+ length += colPositions[item->lastColumn(orientation)] - colPositions[item->firstColumn(orientation)];
+ box->combine(item->box(orientation, length));
+ } else {
+ box->combine(item->box(orientation));
+ }
if (effectiveRowSpan == 1) {
QSizePolicy::ControlTypes controls = item->controlTypes(top);
@@ -1512,44 +1615,99 @@ void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const
}
}
-void QGridLayoutEngine::ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo) const
+void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox,
+ const QLayoutStyleInfo &styleInfo,
+ qreal *colPositions, qreal *colSizes,
+ Qt::Orientation orientation) const
{
- if (q_cachedDataForStyleInfo == styleInfo)
- return;
-
- q_columnData.reset(columnCount());
- q_rowData.reset(rowCount());
-
- fillRowData(&q_columnData, styleInfo, Qt::Horizontal);
- fillRowData(&q_rowData, styleInfo, Qt::Vertical);
+ rowData->reset(rowCount(orientation));
+ fillRowData(rowData, styleInfo, colPositions, colSizes, orientation);
+ rowData->distributeMultiCells();
+ *totalBox = rowData->totalBox(0, rowCount(orientation));
+ //We have items whose width depends on their height
+}
- q_columnData.distributeMultiCells();
- q_rowData.distributeMultiCells();
+/**
+ returns false if the layout has contradicting constraints (i.e. some items with a horizontal
+ constraint and other items with a vertical constraint)
+ */
+bool QGridLayoutEngine::ensureDynamicConstraint() const
+{
+ if (q_cachedConstraintOrientation == UnknownConstraint) {
+ for (int i = q_items.count() - 1; i >= 0; --i) {
+ QGridLayoutItem *item = q_items.at(i);
+ if (item->hasDynamicConstraint()) {
+ Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation();
+ if (q_cachedConstraintOrientation == UnknownConstraint) {
+ q_cachedConstraintOrientation = itemConstraintOrientation;
+ } else if (q_cachedConstraintOrientation != itemConstraintOrientation) {
+ q_cachedConstraintOrientation = UnfeasibleConstraint;
+ qWarning("QGridLayoutEngine: Unfeasible, cannot mix horizontal and"
+ " vertical constraint in the same layout");
+ return false;
+ }
+ }
+ }
+ if (q_cachedConstraintOrientation == UnknownConstraint)
+ q_cachedConstraintOrientation = NoConstraint;
+ }
+ return true;
+}
- q_totalBoxes[Hor] = q_columnData.totalBox(0, columnCount());
- q_totalBoxes[Ver] = q_rowData.totalBox(0, rowCount());
+bool QGridLayoutEngine::hasDynamicConstraint() const
+{
+ if (!ensureDynamicConstraint())
+ return false;
+ return q_cachedConstraintOrientation != NoConstraint;
+}
- q_cachedDataForStyleInfo = styleInfo;
+/*
+ * return value is only valid if hasConstraint() returns true
+ */
+Qt::Orientation QGridLayoutEngine::constraintOrientation() const
+{
+ (void)ensureDynamicConstraint();
+ return (Qt::Orientation)q_cachedConstraintOrientation;
}
void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo,
const QSizeF &size) const
{
- ensureColumnAndRowData(styleInfo);
- if (q_cachedSize == size)
+ if (q_cachedDataForStyleInfo == styleInfo && q_cachedSize == size)
return;
+ q_cachedDataForStyleInfo = styleInfo;
+ q_cachedSize = size;
+
q_xx.resize(columnCount());
- q_yy.resize(rowCount());
q_widths.resize(columnCount());
+ q_yy.resize(rowCount());
q_heights.resize(rowCount());
q_descents.resize(rowCount());
- q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
- 0, q_totalBoxes[Hor]);
- q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
- q_descents.data(), q_totalBoxes[Ver]);
- q_cachedSize = size;
+ if(constraintOrientation() != Qt::Horizontal) {
+ //We might have items whose width depends on their height
+ ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal);
+ //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
+ //constraints to find the row heights
+ q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
+ 0, q_totalBoxes[Hor]);
+ ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, q_xx.data(), q_widths.data(), Qt::Vertical);
+ //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data()
+ q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
+ q_descents.data(), q_totalBoxes[Ver]);
+ } else {
+ //We have items whose height depends on their width
+ ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical);
+ //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
+ //constraints to find the column widths
+ q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
+ q_descents.data(), q_totalBoxes[Ver]);
+ ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, q_yy.data(), q_heights.data(), Qt::Horizontal);
+ //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data()
+ q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
+ 0, q_totalBoxes[Hor]);
+ }
}
QT_END_NAMESPACE