diff options
Diffstat (limited to 'src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp')
-rw-r--r-- | src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp | 157 |
1 files changed, 68 insertions, 89 deletions
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp index dac8e61645..53db11d2d7 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp @@ -1,36 +1,44 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "qgraphicsanchorlayout_p.h" + #include <QtWidgets/qwidget.h> #include <QtWidgets/qapplication.h> #include <QtCore/qlinkedlist.h> @@ -40,7 +48,7 @@ #include <QtCore/qfile.h> #endif -#include "qgraphicsanchorlayout_p.h" +#include <numeric> #ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE @@ -602,10 +610,10 @@ QSimplexConstraint *GraphPath::constraint(const GraphPath &path) const QString GraphPath::toString() const { QString string(QLatin1String("Path: ")); - foreach(AnchorData *edge, positives) + for (AnchorData *edge : positives) string += QString::fromLatin1(" (+++) %1").arg(edge->toString()); - foreach(AnchorData *edge, negatives) + for (AnchorData *edge : negatives) string += QString::fromLatin1(" (---) %1").arg(edge->toString()); return string; @@ -1258,7 +1266,7 @@ void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientatio // Restore anchor simplification Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - QList<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections(); + QVector<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections(); for (int i = 0; i < connections.count(); ++i) { AnchorVertex *v1 = connections.at(i).first; AnchorVertex *v2 = connections.at(i).second; @@ -1932,8 +1940,7 @@ void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::A if (AnchorVertex *v = internalVertex(item, edge)) { Graph<AnchorVertex, AnchorData> &g = graph[edgeOrientation(edge)]; const QList<AnchorVertex *> allVertices = graph[edgeOrientation(edge)].adjacentVertices(v); - AnchorVertex *v2; - foreach (v2, allVertices) { + for (auto *v2 : allVertices) { g.removeEdge(v, v2); removeInternalVertex(item, edge); removeInternalVertex(v2->m_item, v2->m_edge); @@ -2057,9 +2064,8 @@ QList<AnchorData *> getVariables(const QList<QSimplexConstraint *> &constraints) QSet<AnchorData *> variableSet; for (int i = 0; i < constraints.count(); ++i) { const QSimplexConstraint *c = constraints.at(i); - foreach (QSimplexVariable *var, c->variables.keys()) { - variableSet += static_cast<AnchorData *>(var); - } + for (auto it = c->variables.cbegin(), end = c->variables.cend(); it != end; ++it) + variableSet.insert(static_cast<AnchorData *>(it.key())); } return variableSet.toList(); } @@ -2123,34 +2129,28 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( // 2) The floating or semi-floating anchors (items) that are those which // are connected to only one (or none) of the layout sides, thus are not // influenced by the layout size. - QList<QList<QSimplexConstraint *> > parts = getGraphParts(orientation); + const auto parts = getGraphParts(orientation); // Now run the simplex solver to calculate Minimum, Preferred and Maximum sizes // of the "trunk" set of constraints and variables. // ### does trunk always exist? empty = trunk is the layout left->center->right - QList<QSimplexConstraint *> trunkConstraints = parts.at(0); - QList<AnchorData *> trunkVariables = getVariables(trunkConstraints); + const QList<AnchorData *> trunkVariables = getVariables(parts.trunkConstraints); // For minimum and maximum, use the path between the two layout sides as the // objective function. AnchorVertex *v = layoutLastVertex[orientation]; GraphPath trunkPath = graphPaths[orientation].value(v); - bool feasible = calculateTrunk(orientation, trunkPath, trunkConstraints, trunkVariables); + bool feasible = calculateTrunk(orientation, trunkPath, parts.trunkConstraints, trunkVariables); // 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. - // Skipping the first (trunk) - for (int i = 1; i < parts.count(); ++i) { - if (!feasible) - break; - - QList<QSimplexConstraint *> partConstraints = parts.at(i); - QList<AnchorData *> partVariables = getVariables(partConstraints); + if (feasible && !parts.nonTrunkConstraints.isEmpty()) { + const QList<AnchorData *> partVariables = getVariables(parts.nonTrunkConstraints); Q_ASSERT(!partVariables.isEmpty()); - feasible &= calculateNonTrunk(partConstraints, partVariables); + feasible = calculateNonTrunk(parts.nonTrunkConstraints, partVariables); } // Propagate the new sizes down the simplified graph, ie. tell the @@ -2180,10 +2180,7 @@ static void shiftConstraints(const QList<QSimplexConstraint *> &constraints, qre { for (int i = 0; i < constraints.count(); ++i) { QSimplexConstraint *c = constraints.at(i); - qreal multiplier = 0; - foreach (qreal v, c->variables) { - multiplier += v; - } + const qreal multiplier = std::accumulate(c->variables.cbegin(), c->variables.cend(), qreal(0)); c->constant += multiplier * amount; } } @@ -2223,12 +2220,10 @@ bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const // Calculate and set the preferred size for the layout, // from the edge sizes that were calculated above. qreal pref(0.0); - foreach (const AnchorData *ad, path.positives) { + for (const AnchorData *ad : path.positives) pref += ad->sizeAtPreferred; - } - foreach (const AnchorData *ad, path.negatives) { + for (const AnchorData *ad : path.negatives) pref -= ad->sizeAtPreferred; - } sizeHints[orientation][Qt::MinimumSize] = min; sizeHints[orientation][Qt::PreferredSize] = pref; @@ -2244,7 +2239,7 @@ bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const Q_ASSERT(path.positives.count() == 1); Q_ASSERT(path.negatives.count() == 0); - AnchorData *ad = path.positives.toList()[0]; + AnchorData *ad = *path.positives.cbegin(); ad->sizeAtMinimum = ad->minSize; ad->sizeAtPreferred = ad->prefSize; ad->sizeAtMaximum = ad->maxSize; @@ -2294,7 +2289,7 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstra void QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation) { Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections(); + QVector<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections(); QLayoutStyleInfo styleInf = styleInfo(); for (int i = 0; i < vertices.count(); ++i) { @@ -2323,9 +2318,9 @@ void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation) graphPaths[orientation].insert(root, GraphPath()); - foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) { + const auto adjacentVertices = graph[orientation].adjacentVertices(root); + for (AnchorVertex *v : adjacentVertices) queue.enqueue(qMakePair(root, v)); - } while(!queue.isEmpty()) { QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue(); @@ -2344,10 +2339,9 @@ void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation) graphPaths[orientation].insert(pair.second, current); - foreach (AnchorVertex *v, - graph[orientation].adjacentVertices(pair.second)) { + const auto adjacentVertices = graph[orientation].adjacentVertices(pair.second); + for (AnchorVertex *v : adjacentVertices) queue.enqueue(qMakePair(pair.second, v)); - } } // We will walk through every reachable items (non-float) store them in a temporary set. @@ -2368,8 +2362,8 @@ void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation) */ void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation) { - foreach (AnchorVertex *vertex, graphPaths[orientation].uniqueKeys()) - { + const auto vertices = graphPaths[orientation].uniqueKeys(); + for (AnchorVertex *vertex : vertices) { int valueCount = graphPaths[orientation].count(vertex); if (valueCount == 1) continue; @@ -2388,7 +2382,7 @@ void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation) void QGraphicsAnchorLayoutPrivate::updateAnchorSizes(Orientation orientation) { Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - const QList<QPair<AnchorVertex *, AnchorVertex *> > &vertices = g.connections(); + const QVector<QPair<AnchorVertex *, AnchorVertex *> > &vertices = g.connections(); for (int i = 0; i < vertices.count(); ++i) { AnchorData *ad = g.edgeData(vertices.at(i).first, vertices.at(i).second); @@ -2496,9 +2490,11 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin /*! \internal */ -QList< QList<QSimplexConstraint *> > +QGraphicsAnchorLayoutPrivate::GraphParts QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) { + GraphParts result; + Q_ASSERT(layoutFirstVertex[orientation] && layoutLastVertex[orientation]); AnchorData *edgeL1 = 0; @@ -2513,15 +2509,8 @@ QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutLastVertex[orientation]); } - QLinkedList<QSimplexConstraint *> remainingConstraints; - for (int i = 0; i < constraints[orientation].count(); ++i) { - remainingConstraints += constraints[orientation].at(i); - } - for (int i = 0; i < itemCenterConstraints[orientation].count(); ++i) { - remainingConstraints += itemCenterConstraints[orientation].at(i); - } + result.nonTrunkConstraints = constraints[orientation] + itemCenterConstraints[orientation]; - QList<QSimplexConstraint *> trunkConstraints; QSet<QSimplexVariable *> trunkVariables; trunkVariables += edgeL1; @@ -2529,12 +2518,11 @@ QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) trunkVariables += edgeL2; bool dirty; + auto end = result.nonTrunkConstraints.end(); do { dirty = false; - QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin(); - while (it != remainingConstraints.end()) { - QSimplexConstraint *c = *it; + auto isMatch = [&result, &trunkVariables](QSimplexConstraint *c) -> bool { bool match = false; // Check if this constraint have some overlap with current @@ -2549,10 +2537,10 @@ QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) // If so, we add it to trunk, and erase it from the // remaining constraints. if (match) { - trunkConstraints += c; - trunkVariables += QSet<QSimplexVariable *>::fromList(c->variables.keys()); - it = remainingConstraints.erase(it); - dirty = true; + result.trunkConstraints += c; + for (auto jt = c->variables.cbegin(), end = c->variables.cend(); jt != end; ++jt) + trunkVariables.insert(jt.key()); + return true; } else { // Note that we don't erase the constraint if it's not // a match, since in a next iteration of a do-while we @@ -2562,24 +2550,15 @@ QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) // remainingConstraints[1] and it shares with // remainingConstraints[0], we need a second iteration // of the do-while loop to match both. - ++it; + return false; } - } + }; + const auto newEnd = std::remove_if(result.nonTrunkConstraints.begin(), end, isMatch); + dirty = newEnd != end; + end = newEnd; } while (dirty); - QList< QList<QSimplexConstraint *> > result; - result += trunkConstraints; - - if (!remainingConstraints.isEmpty()) { - QList<QSimplexConstraint *> nonTrunkConstraints; - nonTrunkConstraints.reserve(remainingConstraints.size()); - QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin(); - while (it != remainingConstraints.end()) { - nonTrunkConstraints += *it; - ++it; - } - result += nonTrunkConstraints; - } + result.nonTrunkConstraints.erase(end, result.nonTrunkConstraints.end()); return result; } @@ -2593,7 +2572,7 @@ void QGraphicsAnchorLayoutPrivate::identifyFloatItems(const QSet<AnchorData *> & { QSet<QGraphicsLayoutItem *> nonFloating; - foreach (const AnchorData *ad, visited) + for (const AnchorData *ad : visited) identifyNonFloatItems_helper(ad, &nonFloating); QSet<QGraphicsLayoutItem *> allItems; @@ -2707,9 +2686,9 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( visited.insert(root); // Add initial edges to the queue - foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) { + const auto adjacentVertices = graph[orientation].adjacentVertices(root); + for (AnchorVertex *v : adjacentVertices) queue.enqueue(qMakePair(root, v)); - } // Do initial calculation required by "interpolateEdge()" setupEdgesInterpolation(orientation); @@ -2796,7 +2775,7 @@ void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorDat } bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> &constraints, - GraphPath path, qreal *min, qreal *max) + const GraphPath &path, qreal *min, qreal *max) { QSimplex simplex; bool feasible = simplex.setConstraints(constraints); @@ -2983,7 +2962,7 @@ void QGraphicsAnchorLayoutPrivate::dumpGraph(const QString &name) { QFile file(QString::fromLatin1("anchorlayout.%1.dot").arg(name)); if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) - qWarning("Could not write to %s", file.fileName().toLocal8Bit().constData()); + qWarning("Could not write to %ls", qUtf16Printable(file.fileName())); QString str = QString::fromLatin1("digraph anchorlayout {\nnode [shape=\"rect\"]\n%1}"); QString dotContents = graph[0].serializeToDot(); |