1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtWidgets module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QGRAPHICSANCHORLAYOUT_P_H |
41 | #define QGRAPHICSANCHORLAYOUT_P_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include <QtWidgets/private/qtwidgetsglobal_p.h> |
55 | #include <QGraphicsWidget> |
56 | #include <private/qobject_p.h> |
57 | |
58 | #include "qgraphicslayout_p.h" |
59 | #include "qgraphicsanchorlayout.h" |
60 | #include "qgraph_p.h" |
61 | #include "qsimplex_p.h" |
62 | |
63 | QT_REQUIRE_CONFIG(graphicsview); |
64 | |
65 | QT_BEGIN_NAMESPACE |
66 | |
67 | /* |
68 | The public QGraphicsAnchorLayout interface represents an anchorage point |
69 | as a pair of a <QGraphicsLayoutItem *> and a <Qt::AnchorPoint>. |
70 | |
71 | Internally though, it has a graph of anchorage points (vertices) and |
72 | anchors (edges), represented by the AnchorVertex and AnchorData structs |
73 | respectively. |
74 | */ |
75 | |
76 | namespace QtGraphicsAnchorLayout { |
77 | /*! |
78 | \internal |
79 | |
80 | Represents a vertex (anchorage point) in the internal graph |
81 | */ |
82 | struct AnchorVertex |
83 | { |
84 | AnchorVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge) |
85 | : m_item(item), m_edge(edge) {} |
86 | |
87 | AnchorVertex() |
88 | : m_item(nullptr), m_edge(Qt::AnchorPoint(0)) {} |
89 | |
90 | virtual ~AnchorVertex() = default; |
91 | |
92 | #ifdef QT_DEBUG |
93 | virtual inline QString toString() const; |
94 | #endif |
95 | |
96 | QGraphicsLayoutItem *m_item; |
97 | Qt::AnchorPoint m_edge; |
98 | |
99 | // Current distance from this vertex to the layout edge (Left or Top) |
100 | // Value is calculated from the current anchors sizes. |
101 | qreal distance; |
102 | }; |
103 | |
104 | /*! |
105 | \internal |
106 | |
107 | Represents an edge (anchor) in the internal graph. |
108 | */ |
109 | struct AnchorData : public QSimplexVariable { |
110 | enum Type { |
111 | Normal = 0, |
112 | Sequential, |
113 | Parallel |
114 | }; |
115 | |
116 | enum Dependency { |
117 | Independent = 0, |
118 | Master, |
119 | Slave |
120 | }; |
121 | |
122 | AnchorData() |
123 | : QSimplexVariable(), from(nullptr), to(nullptr), |
124 | minSize(0), prefSize(0), maxSize(0), |
125 | minPrefSize(0), maxPrefSize(0), |
126 | sizeAtMinimum(0), sizeAtPreferred(0), |
127 | sizeAtMaximum(0), item(nullptr), graphicsAnchor(nullptr), |
128 | type(Normal), isLayoutAnchor(false), |
129 | isCenterAnchor(false), orientation(0), |
130 | dependency(Independent) {} |
131 | virtual ~AnchorData(); |
132 | |
133 | virtual void updateChildrenSizes() {} |
134 | void refreshSizeHints(const QLayoutStyleInfo *styleInfo = nullptr); |
135 | |
136 | #ifdef QT_DEBUG |
137 | void dump(int indent = 2); |
138 | inline QString toString() const; |
139 | QString name; |
140 | #endif |
141 | |
142 | // Anchor is semantically directed |
143 | AnchorVertex *from; |
144 | AnchorVertex *to; |
145 | |
146 | // Nominal sizes |
147 | // These are the intrinsic size restrictions for a given item. They are |
148 | // used as input for the calculation of the actual sizes. |
149 | // These values are filled by the refreshSizeHints method, based on the |
150 | // anchor size policy, the size hints of the item it (possibly) represents |
151 | // and the layout spacing information. |
152 | qreal minSize; |
153 | qreal prefSize; |
154 | qreal maxSize; |
155 | |
156 | qreal minPrefSize; |
157 | qreal maxPrefSize; |
158 | |
159 | // Calculated sizes |
160 | // These attributes define which sizes should that anchor be in when the |
161 | // layout is at its minimum, preferred or maximum sizes. Values are |
162 | // calculated by the Simplex solver based on the current layout setup. |
163 | qreal sizeAtMinimum; |
164 | qreal sizeAtPreferred; |
165 | qreal sizeAtMaximum; |
166 | |
167 | // References to the classes that represent this anchor in the public world |
168 | // An anchor may represent a LayoutItem, it may also be acessible externally |
169 | // through a GraphicsAnchor "handler". |
170 | QGraphicsLayoutItem *item; |
171 | QGraphicsAnchor *graphicsAnchor; |
172 | |
173 | uint type : 2; // either Normal, Sequential or Parallel |
174 | uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor |
175 | uint isCenterAnchor : 1; |
176 | uint orientation : 1; |
177 | uint dependency : 2; // either Independent, Master or Slave |
178 | }; |
179 | |
180 | #ifdef QT_DEBUG |
181 | inline QString AnchorData::toString() const |
182 | { |
183 | return QString::fromLatin1(str: "Anchor(%1)" ).arg(a: name); |
184 | } |
185 | #endif |
186 | |
187 | struct SequentialAnchorData : public AnchorData |
188 | { |
189 | SequentialAnchorData(const QVector<AnchorVertex *> &vertices, const QVector<AnchorData *> &edges) |
190 | : AnchorData(), m_children(vertices), m_edges(edges) |
191 | { |
192 | type = AnchorData::Sequential; |
193 | orientation = m_edges.at(i: 0)->orientation; |
194 | #ifdef QT_DEBUG |
195 | name = QString::fromLatin1(str: "%1 -- %2" ).arg(args: vertices.first()->toString(), args: vertices.last()->toString()); |
196 | #endif |
197 | } |
198 | |
199 | virtual void updateChildrenSizes() override; |
200 | void calculateSizeHints(); |
201 | |
202 | QVector<AnchorVertex*> m_children; // list of vertices in the sequence |
203 | QVector<AnchorData*> m_edges; // keep the list of edges too. |
204 | }; |
205 | |
206 | struct ParallelAnchorData : public AnchorData |
207 | { |
208 | ParallelAnchorData(AnchorData *first, AnchorData *second) |
209 | : AnchorData(), firstEdge(first), secondEdge(second) |
210 | { |
211 | type = AnchorData::Parallel; |
212 | orientation = first->orientation; |
213 | |
214 | // This assert whether the child anchors share their vertices |
215 | Q_ASSERT(((first->from == second->from) && (first->to == second->to)) || |
216 | ((first->from == second->to) && (first->to == second->from))); |
217 | |
218 | // Our convention will be that the parallel group anchor will have the same |
219 | // direction as the first anchor. |
220 | from = first->from; |
221 | to = first->to; |
222 | #ifdef QT_DEBUG |
223 | name = QString::fromLatin1(str: "%1 | %2" ).arg(args: first->toString(), args: second->toString()); |
224 | #endif |
225 | } |
226 | |
227 | virtual void updateChildrenSizes() override; |
228 | bool calculateSizeHints(); |
229 | |
230 | bool secondForward() const { |
231 | // We have the convention that the first children will define the direction of the |
232 | // pararell group. Note that we can't rely on 'this->from' or 'this->to' because they |
233 | // might be changed by vertex simplification. |
234 | return firstEdge->from == secondEdge->from; |
235 | } |
236 | |
237 | AnchorData* firstEdge; |
238 | AnchorData* secondEdge; |
239 | |
240 | QList<QSimplexConstraint *> m_firstConstraints; |
241 | QList<QSimplexConstraint *> m_secondConstraints; |
242 | }; |
243 | |
244 | struct AnchorVertexPair : public AnchorVertex { |
245 | AnchorVertexPair(AnchorVertex *v1, AnchorVertex *v2, AnchorData *data) |
246 | : AnchorVertex(), m_first(v1), m_second(v2), m_removedAnchor(data) |
247 | { |
248 | } |
249 | |
250 | AnchorVertex *m_first; |
251 | AnchorVertex *m_second; |
252 | |
253 | AnchorData *m_removedAnchor; |
254 | QList<AnchorData *> m_firstAnchors; |
255 | QList<AnchorData *> m_secondAnchors; |
256 | |
257 | #ifdef QT_DEBUG |
258 | inline QString toString() const override |
259 | { |
260 | return QString::fromLatin1(str: "(%1, %2)" ).arg(args: m_first->toString(), args: m_second->toString()); |
261 | } |
262 | #endif |
263 | }; |
264 | |
265 | #ifdef QT_DEBUG |
266 | inline QString AnchorVertex::toString() const |
267 | { |
268 | if (!m_item) |
269 | return QString::fromLatin1(str: "NULL_%1" ).arg(a: quintptr(this)); |
270 | |
271 | QString edge; |
272 | switch (m_edge) { |
273 | case Qt::AnchorLeft: |
274 | edge = QLatin1String("Left" ); |
275 | break; |
276 | case Qt::AnchorHorizontalCenter: |
277 | edge = QLatin1String("HorizontalCenter" ); |
278 | break; |
279 | case Qt::AnchorRight: |
280 | edge = QLatin1String("Right" ); |
281 | break; |
282 | case Qt::AnchorTop: |
283 | edge = QLatin1String("Top" ); |
284 | break; |
285 | case Qt::AnchorVerticalCenter: |
286 | edge = QLatin1String("VerticalCenter" ); |
287 | break; |
288 | case Qt::AnchorBottom: |
289 | edge = QLatin1String("Bottom" ); |
290 | break; |
291 | default: |
292 | edge = QLatin1String("None" ); |
293 | break; |
294 | } |
295 | QString itemName; |
296 | if (m_item->isLayout()) { |
297 | itemName = QLatin1String("layout" ); |
298 | } else { |
299 | if (QGraphicsItem *item = m_item->graphicsItem()) { |
300 | itemName = item->data(key: 0).toString(); |
301 | } |
302 | } |
303 | edge.insert(i: 0, s: QLatin1String("%1_" )); |
304 | return edge.arg(a: itemName); |
305 | } |
306 | #endif |
307 | |
308 | /*! |
309 | \internal |
310 | |
311 | Representation of a valid path for a given vertex in the graph. |
312 | In this struct, "positives" is the set of anchors that have been |
313 | traversed in the forward direction, while "negatives" is the set |
314 | with the ones walked backwards. |
315 | |
316 | This paths are compared against each other to produce LP Constraints, |
317 | the exact order in which the anchors were traversed is not relevant. |
318 | */ |
319 | class GraphPath |
320 | { |
321 | public: |
322 | GraphPath() {} |
323 | |
324 | QSimplexConstraint *constraint(const GraphPath &path) const; |
325 | #ifdef QT_DEBUG |
326 | QString toString() const; |
327 | #endif |
328 | QSet<AnchorData *> positives; |
329 | QSet<AnchorData *> negatives; |
330 | }; |
331 | } // namespace QtGraphicsAnchorLayout |
332 | using namespace QtGraphicsAnchorLayout; |
333 | |
334 | Q_DECLARE_TYPEINFO(GraphPath, Q_MOVABLE_TYPE); |
335 | |
336 | class QGraphicsAnchorLayoutPrivate; |
337 | /*! |
338 | \internal |
339 | */ |
340 | class QGraphicsAnchorPrivate : public QObjectPrivate |
341 | { |
342 | Q_DECLARE_PUBLIC(QGraphicsAnchor) |
343 | |
344 | public: |
345 | explicit QGraphicsAnchorPrivate(int version = QObjectPrivateVersion); |
346 | ~QGraphicsAnchorPrivate(); |
347 | |
348 | void setSpacing(qreal value); |
349 | void unsetSpacing(); |
350 | qreal spacing() const; |
351 | |
352 | void setSizePolicy(QSizePolicy::Policy policy); |
353 | |
354 | static QGraphicsAnchorPrivate *get(QGraphicsAnchor *q) |
355 | { return q->d_func(); } |
356 | |
357 | QGraphicsAnchorLayoutPrivate *layoutPrivate; |
358 | AnchorData *data; |
359 | |
360 | // Size information for user controlled anchor |
361 | QSizePolicy::Policy sizePolicy; |
362 | qreal preferredSize; |
363 | |
364 | uint hasSize : 1; // if false, get size from style. |
365 | }; |
366 | |
367 | |
368 | |
369 | |
370 | /*! |
371 | \internal |
372 | |
373 | QGraphicsAnchorLayout private methods and attributes. |
374 | */ |
375 | class Q_AUTOTEST_EXPORT QGraphicsAnchorLayoutPrivate : public QGraphicsLayoutPrivate |
376 | { |
377 | Q_DECLARE_PUBLIC(QGraphicsAnchorLayout) |
378 | |
379 | public: |
380 | // When the layout geometry is different from its Minimum, Preferred |
381 | // or Maximum values, interpolation is used to calculate the geometries |
382 | // of the items. |
383 | // |
384 | // Interval represents which interpolation interval are we operating in. |
385 | enum Interval { |
386 | MinimumToMinPreferred = 0, |
387 | MinPreferredToPreferred, |
388 | PreferredToMaxPreferred, |
389 | MaxPreferredToMaximum |
390 | }; |
391 | |
392 | // Several structures internal to the layout are duplicated to handle |
393 | // both Horizontal and Vertical restrictions. |
394 | // |
395 | // Orientation is used to reference the right structure in each context |
396 | enum Orientation { |
397 | Horizontal = 0, |
398 | Vertical, |
399 | NOrientations |
400 | }; |
401 | |
402 | QGraphicsAnchorLayoutPrivate(); |
403 | |
404 | static QGraphicsAnchorLayoutPrivate *get(QGraphicsAnchorLayout *q) |
405 | { |
406 | return q ? q->d_func() : nullptr; |
407 | } |
408 | |
409 | static Qt::AnchorPoint oppositeEdge( |
410 | Qt::AnchorPoint edge); |
411 | |
412 | static Orientation edgeOrientation(Qt::AnchorPoint edge); |
413 | |
414 | static Qt::AnchorPoint pickEdge(Qt::AnchorPoint edge, Orientation orientation) |
415 | { |
416 | if (orientation == Vertical && int(edge) <= 2) |
417 | return (Qt::AnchorPoint)(edge + 3); |
418 | else if (orientation == Horizontal && int(edge) >= 3) { |
419 | return (Qt::AnchorPoint)(edge - 3); |
420 | } |
421 | return edge; |
422 | } |
423 | |
424 | // Init methods |
425 | void createLayoutEdges(); |
426 | void deleteLayoutEdges(); |
427 | void createItemEdges(QGraphicsLayoutItem *item); |
428 | void createCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge); |
429 | void removeCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, bool substitute = true); |
430 | void removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation); |
431 | |
432 | QGraphicsAnchor *acquireGraphicsAnchor(AnchorData *data) |
433 | { |
434 | Q_Q(QGraphicsAnchorLayout); |
435 | if (!data->graphicsAnchor) { |
436 | data->graphicsAnchor = new QGraphicsAnchor(q); |
437 | data->graphicsAnchor->d_func()->data = data; |
438 | } |
439 | return data->graphicsAnchor; |
440 | } |
441 | |
442 | // function used by the 4 API functions |
443 | QGraphicsAnchor *addAnchor(QGraphicsLayoutItem *firstItem, |
444 | Qt::AnchorPoint firstEdge, |
445 | QGraphicsLayoutItem *secondItem, |
446 | Qt::AnchorPoint secondEdge, |
447 | qreal *spacing = nullptr); |
448 | |
449 | // Helper for Anchor Manipulation methods |
450 | void addAnchor_helper(QGraphicsLayoutItem *firstItem, |
451 | Qt::AnchorPoint firstEdge, |
452 | QGraphicsLayoutItem *secondItem, |
453 | Qt::AnchorPoint secondEdge, |
454 | AnchorData *data); |
455 | |
456 | QGraphicsAnchor *getAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, |
457 | QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); |
458 | |
459 | void removeAnchor(AnchorVertex *firstVertex, AnchorVertex *secondVertex); |
460 | void removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2); |
461 | |
462 | void removeAnchors(QGraphicsLayoutItem *item); |
463 | |
464 | void removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); |
465 | |
466 | void correctEdgeDirection(QGraphicsLayoutItem *&firstItem, |
467 | Qt::AnchorPoint &firstEdge, |
468 | QGraphicsLayoutItem *&secondItem, |
469 | Qt::AnchorPoint &secondEdge); |
470 | |
471 | QLayoutStyleInfo &styleInfo() const; |
472 | |
473 | AnchorData *addAnchorMaybeParallel(AnchorData *newAnchor, bool *feasible); |
474 | |
475 | // Activation |
476 | void calculateGraphs(); |
477 | void calculateGraphs(Orientation orientation); |
478 | |
479 | // Simplification |
480 | bool simplifyGraph(Orientation orientation); |
481 | bool simplifyVertices(Orientation orientation); |
482 | bool simplifyGraphIteration(Orientation orientation, bool *feasible); |
483 | |
484 | bool replaceVertex(Orientation orientation, AnchorVertex *oldV, |
485 | AnchorVertex *newV, const QList<AnchorData *> &edges); |
486 | |
487 | |
488 | void restoreSimplifiedGraph(Orientation orientation); |
489 | void restoreSimplifiedAnchor(AnchorData *edge); |
490 | void restoreSimplifiedConstraints(ParallelAnchorData *parallel); |
491 | void restoreVertices(Orientation orientation); |
492 | |
493 | bool calculateTrunk(Orientation orientation, const GraphPath &trunkPath, |
494 | const QList<QSimplexConstraint *> &constraints, |
495 | const QList<AnchorData *> &variables); |
496 | bool calculateNonTrunk(const QList<QSimplexConstraint *> &constraints, |
497 | const QList<AnchorData *> &variables); |
498 | |
499 | // Support functions for calculateGraph() |
500 | void refreshAllSizeHints(Orientation orientation); |
501 | void findPaths(Orientation orientation); |
502 | void constraintsFromPaths(Orientation orientation); |
503 | void updateAnchorSizes(Orientation orientation); |
504 | QList<QSimplexConstraint *> constraintsFromSizeHints(const QList<AnchorData *> &anchors); |
505 | struct GraphParts { |
506 | QList<QSimplexConstraint *> trunkConstraints; |
507 | QList<QSimplexConstraint *> nonTrunkConstraints; |
508 | }; |
509 | GraphParts getGraphParts(Orientation orientation); |
510 | void identifyFloatItems(const QSet<AnchorData *> &visited, Orientation orientation); |
511 | void identifyNonFloatItems_helper(const AnchorData *ad, QSet<QGraphicsLayoutItem *> *nonFloatingItemsIdentifiedSoFar); |
512 | |
513 | inline AnchorVertex *internalVertex(const QPair<QGraphicsLayoutItem*, Qt::AnchorPoint> &itemEdge) const |
514 | { |
515 | return m_vertexList.value(key: itemEdge).first; |
516 | } |
517 | |
518 | inline AnchorVertex *internalVertex(const QGraphicsLayoutItem *item, Qt::AnchorPoint edge) const |
519 | { |
520 | return internalVertex(itemEdge: qMakePair(x: const_cast<QGraphicsLayoutItem *>(item), y: edge)); |
521 | } |
522 | |
523 | inline void changeLayoutVertex(Orientation orientation, AnchorVertex *oldV, AnchorVertex *newV) |
524 | { |
525 | if (layoutFirstVertex[orientation] == oldV) |
526 | layoutFirstVertex[orientation] = newV; |
527 | else if (layoutCentralVertex[orientation] == oldV) |
528 | layoutCentralVertex[orientation] = newV; |
529 | else if (layoutLastVertex[orientation] == oldV) |
530 | layoutLastVertex[orientation] = newV; |
531 | } |
532 | |
533 | |
534 | AnchorVertex *addInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); |
535 | void removeInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); |
536 | |
537 | // Geometry interpolation methods |
538 | void setItemsGeometries(const QRectF &geom); |
539 | |
540 | void calculateVertexPositions(Orientation orientation); |
541 | void setupEdgesInterpolation(Orientation orientation); |
542 | void interpolateEdge(AnchorVertex *base, AnchorData *edge); |
543 | |
544 | // Linear Programming solver methods |
545 | bool solveMinMax(const QList<QSimplexConstraint *> &constraints, |
546 | const GraphPath &path, qreal *min, qreal *max); |
547 | bool solvePreferred(const QList<QSimplexConstraint *> &constraints, |
548 | const QList<AnchorData *> &variables); |
549 | bool hasConflicts() const; |
550 | |
551 | #ifdef QT_DEBUG |
552 | void dumpGraph(const QString &name = QString()); |
553 | #endif |
554 | |
555 | |
556 | qreal spacings[NOrientations]; |
557 | // Size hints from simplex engine |
558 | qreal sizeHints[2][3]; |
559 | |
560 | // Items |
561 | QVector<QGraphicsLayoutItem *> items; |
562 | |
563 | // Mapping between high level anchorage points (Item, Edge) to low level |
564 | // ones (Graph Vertices) |
565 | |
566 | QHash<QPair<QGraphicsLayoutItem*, Qt::AnchorPoint>, QPair<AnchorVertex *, int> > m_vertexList; |
567 | |
568 | // Internal graph of anchorage points and anchors, for both orientations |
569 | Graph<AnchorVertex, AnchorData> graph[2]; |
570 | |
571 | AnchorVertex *layoutFirstVertex[2]; |
572 | AnchorVertex *layoutCentralVertex[2]; |
573 | AnchorVertex *layoutLastVertex[2]; |
574 | |
575 | // Combined anchors in order of creation |
576 | QList<AnchorVertexPair *> simplifiedVertices[2]; |
577 | QList<AnchorData *> anchorsFromSimplifiedVertices[2]; |
578 | |
579 | // Graph paths and constraints, for both orientations |
580 | QMultiHash<AnchorVertex *, GraphPath> graphPaths[2]; |
581 | QList<QSimplexConstraint *> constraints[2]; |
582 | QList<QSimplexConstraint *> itemCenterConstraints[2]; |
583 | |
584 | // The interpolation interval and progress based on the current size |
585 | // as well as the key values (minimum, preferred and maximum) |
586 | Interval interpolationInterval[2]; |
587 | qreal interpolationProgress[2]; |
588 | |
589 | bool graphHasConflicts[2]; |
590 | QSet<QGraphicsLayoutItem *> m_floatItems[2]; |
591 | |
592 | #if defined(QT_DEBUG) || defined(QT_BUILD_INTERNAL) |
593 | bool lastCalculationUsedSimplex[2]; |
594 | #endif |
595 | |
596 | uint calculateGraphCacheDirty : 1; |
597 | mutable uint styleInfoDirty : 1; |
598 | mutable QLayoutStyleInfo cachedStyleInfo; |
599 | |
600 | friend class QGraphicsAnchorPrivate; |
601 | }; |
602 | |
603 | QT_END_NAMESPACE |
604 | |
605 | #endif |
606 | |