From efb7495717b7fd84996a59ee99c9632aa4f43467 Mon Sep 17 00:00:00 2001 From: "Eduardo M. Fleury" Date: Fri, 29 May 2009 13:44:24 -0300 Subject: QGraphicsAnchorLayout: Fix memory management issue in QSimplex solver Both QGraphicsAnchorLayoutPrivate::solveMinMax() and solvePreferred() were deleting the linear programming contraints while QSimplex still had them. For solveMinMax(), move the creation of constraints out of that method. For solvePreferred(), create the simplex solver in the heap so it can be deleted before the constraints are. Signed-off-by: Eduardo M. Fleury Reviewed-by: Anselmo Lacerda S. de Melo --- src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 101 ++++++++++++----------- src/gui/graphicsview/qgraphicsanchorlayout_p.h | 1 + src/gui/graphicsview/qsimplex_p.cpp | 2 +- 3 files changed, 54 insertions(+), 50 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 8158f48..644ed6b 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -506,6 +506,9 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( // of the "trunk" set of constraints and variables. // ### does trunk always exist? empty = trunk is the layout left->center->right QList trunkConstraints = parts[0]; + QList sizeHintConstraints; + sizeHintConstraints = constraintsFromSizeHints(getVariables(trunkConstraints)); + trunkConstraints += sizeHintConstraints; // For minimum and maximum, use the path between the two layout sides as the // objective function. @@ -540,6 +543,10 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( } sizeHints[orientation][Qt::PreferredSize] = pref; + // Delete the constraints, we won't use them anymore. + qDeleteAll(sizeHintConstraints); + sizeHintConstraints.clear(); + // For the other parts that not the trunk, solve only for the preferred size // that is the size they will remain at, since they are not stretched by the // layout. @@ -548,11 +555,10 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( for (int i = 1; i < parts.count(); ++i) { QList partConstraints = parts[i]; QList partVariables = getVariables(partConstraints); + Q_ASSERT(!partVariables.isEmpty()); - // ### - if (partVariables.isEmpty()) - continue; - + sizeHintConstraints = constraintsFromSizeHints(partVariables); + partConstraints += sizeHintConstraints; solvePreferred(partConstraints); // Propagate size at preferred to other sizes. Semi-floats @@ -563,6 +569,10 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( ad->sizeAtMinimum = ad->sizeAtPreferred; ad->sizeAtMaximum = ad->sizeAtPreferred; } + + // Delete the constraints, we won't use them anymore. + qDeleteAll(sizeHintConstraints); + sizeHintConstraints.clear(); } // Clean up our data structures. They are not needed anymore since @@ -731,6 +741,33 @@ void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation) } /*! + \internal + + Create LP constraints for each anchor based on its minimum and maximum + sizes, as specified in its size hints +*/ +QList QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints( + const QList &anchors) +{ + QList anchorConstraints; + for (int i = 0; i < anchors.size(); ++i) { + QSimplexConstraint *c = new QSimplexConstraint; + c->variables.insert(anchors[i], 1.0); + c->constant = anchors[i]->minSize; + c->ratio = QSimplexConstraint::MoreOrEqual; + anchorConstraints += c; + + c = new QSimplexConstraint; + c->variables.insert(anchors[i], 1.0); + c->constant = anchors[i]->maxSize; + c->ratio = QSimplexConstraint::LessOrEqual; + anchorConstraints += c; + } + + return anchorConstraints; +} + +/*! \Internal */ QList< QList > @@ -976,25 +1013,8 @@ QPair QGraphicsAnchorLayoutPrivate::solveMinMax(QList constraints, GraphPath path) { - QList variables = getVariables(constraints); - QList itemConstraints; - - for (int i = 0; i < variables.size(); ++i) { - QSimplexConstraint *c = new QSimplexConstraint; - c->variables.insert(variables[i], 1.0); - c->constant = variables[i]->minSize; - c->ratio = QSimplexConstraint::MoreOrEqual; - itemConstraints += c; - - c = new QSimplexConstraint; - c->variables.insert(variables[i], 1.0); - c->constant = variables[i]->maxSize; - c->ratio = QSimplexConstraint::LessOrEqual; - itemConstraints += c; - } - QSimplex simplex; - simplex.setConstraints(constraints + itemConstraints); + simplex.setConstraints(constraints); // Obtain the objective constraint QSimplexConstraint objective; @@ -1011,6 +1031,7 @@ QGraphicsAnchorLayoutPrivate::solveMinMax(QList constraint qreal min = simplex.solveMin(); // Save sizeAtMinimum results + QList variables = simplex.constraintsVariables(); for (int i = 0; i < variables.size(); ++i) { AnchorData *ad = static_cast(variables[i]); ad->sizeAtMinimum = ad->result; @@ -1025,32 +1046,12 @@ QGraphicsAnchorLayoutPrivate::solveMinMax(QList constraint ad->sizeAtMaximum = ad->result; } - qDeleteAll(itemConstraints); - return qMakePair(min, max); } void QGraphicsAnchorLayoutPrivate::solvePreferred(QList constraints) { QList variables = getVariables(constraints); - - // ### - QList itemConstraints; - - for (int i = 0; i < variables.size(); ++i) { - QSimplexConstraint *c = new QSimplexConstraint; - c->variables.insert(variables[i], 1.0); - c->constant = variables[i]->minSize; - c->ratio = QSimplexConstraint::MoreOrEqual; - itemConstraints += c; - - c = new QSimplexConstraint; - c->variables.insert(variables[i], 1.0); - c->constant = variables[i]->maxSize; - c->ratio = QSimplexConstraint::LessOrEqual; - itemConstraints += c; - } - QList preferredConstraints; QList preferredVariables; QSimplexConstraint objective; @@ -1094,13 +1095,12 @@ void QGraphicsAnchorLayoutPrivate::solvePreferred(QList co } - QSimplex simplex; - simplex.setConstraints(constraints + itemConstraints + preferredConstraints); - - simplex.setObjective(&objective); + QSimplex *simplex = new QSimplex; + simplex->setConstraints(constraints + preferredConstraints); + simplex->setObjective(&objective); // Calculate minimum values - simplex.solveMin(); + simplex->solveMin(); // Save sizeAtPreferred results for (int i = 0; i < variables.size(); ++i) { @@ -1108,8 +1108,11 @@ void QGraphicsAnchorLayoutPrivate::solvePreferred(QList co ad->sizeAtPreferred = ad->result; } - qDeleteAll(itemConstraints); + // Make sure we delete the simplex solver -before- we delete the + // constraints used by it. + delete simplex; + + // Delete constraints and variables we created. qDeleteAll(preferredConstraints); qDeleteAll(preferredVariables); - } diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 6370f4a..f2dd796 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -264,6 +264,7 @@ public: void setAnchorSizeHintsFromItems(Orientation orientation); void findPaths(Orientation orientation); void constraintsFromPaths(Orientation orientation); + QList constraintsFromSizeHints(const QList &anchors); QList > getGraphParts(Orientation orientation); inline AnchorVertex *internalVertex(const QPair &itemEdge) diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp index 4ed11c4..774af8c 100644 --- a/src/gui/graphicsview/qsimplex_p.cpp +++ b/src/gui/graphicsview/qsimplex_p.cpp @@ -5,7 +5,7 @@ #include -QSimplex::QSimplex() : rows(0), columns(0), firstArtificial(0), matrix(0) +QSimplex::QSimplex() : objective(0), rows(0), columns(0), firstArtificial(0), matrix(0) { } -- cgit v0.12