Fixes warnings about unused variables
[profile/ivi/qtbase.git] / src / gui / graphicsview / qgraphicsanchorlayout_p.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtGui/qwidget.h>
43 #include <QtGui/qapplication.h>
44 #include <QtCore/qlinkedlist.h>
45 #include <QtCore/qstack.h>
46
47 #ifdef QT_DEBUG
48 #include <QtCore/qfile.h>
49 #endif
50
51 #include "qgraphicsanchorlayout_p.h"
52
53 #ifndef QT_NO_GRAPHICSVIEW
54 QT_BEGIN_NAMESPACE
55
56 // To ensure that all variables inside the simplex solver are non-negative,
57 // we limit the size of anchors in the interval [-limit, limit]. Then before
58 // sending them to the simplex solver we add "limit" as an offset, so that
59 // they are actually calculated in the interval [0, 2 * limit]
60 // To avoid numerical errors in platforms where we use single precision,
61 // we use a tighter limit for the variables range.
62 const qreal g_offset = (sizeof(qreal) == sizeof(double)) ? QWIDGETSIZE_MAX : QWIDGETSIZE_MAX / 32;
63
64 QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version)
65     : QObjectPrivate(version), layoutPrivate(0), data(0),
66       sizePolicy(QSizePolicy::Fixed), preferredSize(0),
67       hasSize(true)
68 {
69 }
70
71 QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate()
72 {
73     if (data) {
74         // The QGraphicsAnchor was already deleted at this moment. We must clean
75         // the dangling pointer to avoid double deletion in the AnchorData dtor.
76         data->graphicsAnchor = 0;
77
78         layoutPrivate->removeAnchor(data->from, data->to);
79     }
80 }
81
82 void QGraphicsAnchorPrivate::setSizePolicy(QSizePolicy::Policy policy)
83 {
84     if (sizePolicy != policy) {
85         sizePolicy = policy;
86         layoutPrivate->q_func()->invalidate();
87     }
88 }
89
90 void QGraphicsAnchorPrivate::setSpacing(qreal value)
91 {
92     if (!data) {
93         qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist.");
94         return;
95     }
96
97     if (hasSize && (preferredSize == value))
98         return;
99
100     // The anchor has an user-defined size
101     hasSize = true;
102     preferredSize = value;
103
104     layoutPrivate->q_func()->invalidate();
105 }
106
107 void QGraphicsAnchorPrivate::unsetSpacing()
108 {
109     if (!data) {
110         qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist.");
111         return;
112     }
113
114     // Return to standard direction
115     hasSize = false;
116
117     layoutPrivate->q_func()->invalidate();
118 }
119
120 qreal QGraphicsAnchorPrivate::spacing() const
121 {
122     if (!data) {
123         qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist.");
124         return 0;
125     }
126
127     return preferredSize;
128 }
129
130
131 static void applySizePolicy(QSizePolicy::Policy policy,
132                             qreal minSizeHint, qreal prefSizeHint, qreal maxSizeHint,
133                             qreal *minSize, qreal *prefSize,
134                             qreal *maxSize)
135 {
136     // minSize, prefSize and maxSize are initialized
137     // with item's preferred Size: this is QSizePolicy::Fixed.
138     //
139     // Then we check each flag to find the resultant QSizePolicy,
140     // according to the following table:
141     //
142     //      constant               value
143     // QSizePolicy::Fixed            0
144     // QSizePolicy::Minimum       GrowFlag
145     // QSizePolicy::Maximum       ShrinkFlag
146     // QSizePolicy::Preferred     GrowFlag | ShrinkFlag
147     // QSizePolicy::Ignored       GrowFlag | ShrinkFlag | IgnoreFlag
148
149     if (policy & QSizePolicy::ShrinkFlag)
150         *minSize = minSizeHint;
151     else
152         *minSize = prefSizeHint;
153
154     if (policy & QSizePolicy::GrowFlag)
155         *maxSize = maxSizeHint;
156     else
157         *maxSize = prefSizeHint;
158
159     // Note that these two initializations are affected by the previous flags
160     if (policy & QSizePolicy::IgnoreFlag)
161         *prefSize = *minSize;
162     else
163         *prefSize = prefSizeHint;
164 }
165
166 AnchorData::~AnchorData()
167 {
168     if (graphicsAnchor) {
169         // Remove reference to ourself to avoid double removal in
170         // QGraphicsAnchorPrivate dtor.
171         graphicsAnchor->d_func()->data = 0;
172
173         delete graphicsAnchor;
174     }
175 }
176
177
178 void AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
179 {
180     QSizePolicy::Policy policy;
181     qreal minSizeHint;
182     qreal prefSizeHint;
183     qreal maxSizeHint;
184
185     if (item) {
186         // It is an internal anchor, fetch size information from the item
187         if (isLayoutAnchor) {
188             minSize = 0;
189             prefSize = 0;
190             maxSize = QWIDGETSIZE_MAX;
191             if (isCenterAnchor)
192                 maxSize /= 2;
193
194             minPrefSize = prefSize;
195             maxPrefSize = maxSize;
196             return;
197         } else {
198             if (orientation == QGraphicsAnchorLayoutPrivate::Horizontal) {
199                 policy = item->sizePolicy().horizontalPolicy();
200                 minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).width();
201                 prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).width();
202                 maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).width();
203             } else {
204                 policy = item->sizePolicy().verticalPolicy();
205                 minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).height();
206                 prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).height();
207                 maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).height();
208             }
209
210             if (isCenterAnchor) {
211                 minSizeHint /= 2;
212                 prefSizeHint /= 2;
213                 maxSizeHint /= 2;
214             }
215         }
216     } else {
217         // It is a user-created anchor, fetch size information from the associated QGraphicsAnchor
218         Q_ASSERT(graphicsAnchor);
219         QGraphicsAnchorPrivate *anchorPrivate = graphicsAnchor->d_func();
220
221         // Policy, min and max sizes are straightforward
222         policy = anchorPrivate->sizePolicy;
223         minSizeHint = 0;
224         maxSizeHint = QWIDGETSIZE_MAX;
225
226         // Preferred Size
227         if (anchorPrivate->hasSize) {
228             // Anchor has user-defined size
229             prefSizeHint = anchorPrivate->preferredSize;
230         } else {
231             // Fetch size information from style
232             const Qt::Orientation orient = Qt::Orientation(QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge) + 1);
233             qreal s = styleInfo->defaultSpacing(orient);
234             if (s < 0) {
235                 QSizePolicy::ControlType controlTypeFrom = from->m_item->sizePolicy().controlType();
236                 QSizePolicy::ControlType controlTypeTo = to->m_item->sizePolicy().controlType();
237                 s = styleInfo->perItemSpacing(controlTypeFrom, controlTypeTo, orient);
238
239                 // ### Currently we do not support negative anchors inside the graph.
240                 // To avoid those being created by a negative style spacing, we must
241                 // make this test.
242                 if (s < 0)
243                     s = 0;
244             }
245             prefSizeHint = s;
246         }
247     }
248
249     // Fill minSize, prefSize and maxSize based on policy and sizeHints
250     applySizePolicy(policy, minSizeHint, prefSizeHint, maxSizeHint,
251                     &minSize, &prefSize, &maxSize);
252
253     minPrefSize = prefSize;
254     maxPrefSize = maxSize;
255
256     // Set the anchor effective sizes to preferred.
257     //
258     // Note: The idea here is that all items should remain at their
259     // preferred size unless where that's impossible.  In cases where
260     // the item is subject to restrictions (anchored to the layout
261     // edges, for instance), the simplex solver will be run to
262     // recalculate and override the values we set here.
263     sizeAtMinimum = prefSize;
264     sizeAtPreferred = prefSize;
265     sizeAtMaximum = prefSize;
266 }
267
268 void ParallelAnchorData::updateChildrenSizes()
269 {
270     firstEdge->sizeAtMinimum = sizeAtMinimum;
271     firstEdge->sizeAtPreferred = sizeAtPreferred;
272     firstEdge->sizeAtMaximum = sizeAtMaximum;
273
274     if (secondForward()) {
275         secondEdge->sizeAtMinimum = sizeAtMinimum;
276         secondEdge->sizeAtPreferred = sizeAtPreferred;
277         secondEdge->sizeAtMaximum = sizeAtMaximum;
278     } else {
279         secondEdge->sizeAtMinimum = -sizeAtMinimum;
280         secondEdge->sizeAtPreferred = -sizeAtPreferred;
281         secondEdge->sizeAtMaximum = -sizeAtMaximum;
282     }
283
284     firstEdge->updateChildrenSizes();
285     secondEdge->updateChildrenSizes();
286 }
287
288 /*
289   \internal
290
291   Initialize the parallel anchor size hints using the sizeHint information from
292   its children.
293
294   Note that parallel groups can lead to unfeasibility, so during calculation, we can
295   find out one unfeasibility. Because of that this method return boolean. This can't
296   happen in sequential, so there the method is void.
297  */
298 bool ParallelAnchorData::calculateSizeHints()
299 {
300     // Normalize second child sizes.
301     // A negative anchor of sizes min, minPref, pref, maxPref and max, is equivalent
302     // to a forward anchor of sizes -max, -maxPref, -pref, -minPref, -min
303     qreal secondMin;
304     qreal secondMinPref;
305     qreal secondPref;
306     qreal secondMaxPref;
307     qreal secondMax;
308
309     if (secondForward()) {
310         secondMin = secondEdge->minSize;
311         secondMinPref = secondEdge->minPrefSize;
312         secondPref = secondEdge->prefSize;
313         secondMaxPref = secondEdge->maxPrefSize;
314         secondMax = secondEdge->maxSize;
315     } else {
316         secondMin = -secondEdge->maxSize;
317         secondMinPref = -secondEdge->maxPrefSize;
318         secondPref = -secondEdge->prefSize;
319         secondMaxPref = -secondEdge->minPrefSize;
320         secondMax = -secondEdge->minSize;
321     }
322
323     minSize = qMax(firstEdge->minSize, secondMin);
324     maxSize = qMin(firstEdge->maxSize, secondMax);
325
326     // This condition means that the maximum size of one anchor being simplified is smaller than
327     // the minimum size of the other anchor. The consequence is that there won't be a valid size
328     // for this parallel setup.
329     if (minSize > maxSize) {
330         return false;
331     }
332
333     // Preferred size calculation
334     // The calculation of preferred size is done as follows:
335     //
336     // 1) Check whether one of the child anchors is the layout structural anchor
337     //    If so, we can simply copy the preferred information from the other child,
338     //    after bounding it to our minimum and maximum sizes.
339     //    If not, then we proceed with the actual calculations.
340     //
341     // 2) The whole algorithm for preferred size calculation is based on the fact
342     //    that, if a given anchor cannot remain at its preferred size, it'd rather
343     //    grow than shrink.
344     //
345     //    What happens though is that while this affirmative is true for simple
346     //    anchors, it may not be true for sequential anchors that have one or more
347     //    reversed anchors inside it. That happens because when a sequential anchor
348     //    grows, any reversed anchors inside it may be required to shrink, something
349     //    we try to avoid, as said above.
350     //
351     //    To overcome this, besides their actual preferred size "prefSize", each anchor
352     //    exports what we call "minPrefSize" and "maxPrefSize". These two values define
353     //    a surrounding interval where, if required to move, the anchor would rather
354     //    remain inside.
355     //
356     //    For standard anchors, this area simply represents the region between
357     //    prefSize and maxSize, which makes sense since our first affirmation.
358     //    For composed anchors, these values are calculated as to reduce the global
359     //    "damage", that is, to reduce the total deviation and the total amount of
360     //    anchors that had to shrink.
361
362     if (firstEdge->isLayoutAnchor) {
363         prefSize = qBound(minSize, secondPref, maxSize);
364         minPrefSize = qBound(minSize, secondMinPref, maxSize);
365         maxPrefSize = qBound(minSize, secondMaxPref, maxSize);
366     } else if (secondEdge->isLayoutAnchor) {
367         prefSize = qBound(minSize, firstEdge->prefSize, maxSize);
368         minPrefSize = qBound(minSize, firstEdge->minPrefSize, maxSize);
369         maxPrefSize = qBound(minSize, firstEdge->maxPrefSize, maxSize);
370     } else {
371         // Calculate the intersection between the "preferred" regions of each child
372         const qreal lowerBoundary =
373             qBound(minSize, qMax(firstEdge->minPrefSize, secondMinPref), maxSize);
374         const qreal upperBoundary =
375             qBound(minSize, qMin(firstEdge->maxPrefSize, secondMaxPref), maxSize);
376         const qreal prefMean =
377             qBound(minSize, (firstEdge->prefSize + secondPref) / 2, maxSize);
378
379         if (lowerBoundary < upperBoundary) {
380             // If there is an intersection between the two regions, this intersection
381             // will be used as the preferred region of the parallel anchor itself.
382             // The preferred size will be the bounded average between the two preferred
383             // sizes.
384             prefSize = qBound(lowerBoundary, prefMean, upperBoundary);
385             minPrefSize = lowerBoundary;
386             maxPrefSize = upperBoundary;
387         } else {
388             // If there is no intersection, we have to attribute "damage" to at least
389             // one of the children. The minimum total damage is achieved in points
390             // inside the region that extends from (1) the upper boundary of the lower
391             // region to (2) the lower boundary of the upper region.
392             // Then, we expose this region as _our_ preferred region and once again,
393             // use the bounded average as our preferred size.
394             prefSize = qBound(upperBoundary, prefMean, lowerBoundary);
395             minPrefSize = upperBoundary;
396             maxPrefSize = lowerBoundary;
397         }
398     }
399
400     // See comment in AnchorData::refreshSizeHints() about sizeAt* values
401     sizeAtMinimum = prefSize;
402     sizeAtPreferred = prefSize;
403     sizeAtMaximum = prefSize;
404
405     return true;
406 }
407
408 /*!
409     \internal
410     returns the factor in the interval [-1, 1].
411     -1 is at Minimum
412      0 is at Preferred
413      1 is at Maximum
414 */
415 static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal value, qreal min,
416                                                                       qreal minPref, qreal pref,
417                                                                       qreal maxPref, qreal max)
418 {
419     QGraphicsAnchorLayoutPrivate::Interval interval;
420     qreal lower;
421     qreal upper;
422
423     if (value < minPref) {
424         interval = QGraphicsAnchorLayoutPrivate::MinimumToMinPreferred;
425         lower = min;
426         upper = minPref;
427     } else if (value < pref) {
428         interval = QGraphicsAnchorLayoutPrivate::MinPreferredToPreferred;
429         lower = minPref;
430         upper = pref;
431     } else if (value < maxPref) {
432         interval = QGraphicsAnchorLayoutPrivate::PreferredToMaxPreferred;
433         lower = pref;
434         upper = maxPref;
435     } else {
436         interval = QGraphicsAnchorLayoutPrivate::MaxPreferredToMaximum;
437         lower = maxPref;
438         upper = max;
439     }
440
441     qreal progress;
442     if (upper == lower) {
443         progress = 0;
444     } else {
445         progress = (value - lower) / (upper - lower);
446     }
447
448     return qMakePair(interval, progress);
449 }
450
451 static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> &factor,
452                          qreal min, qreal minPref, qreal pref, qreal maxPref, qreal max)
453 {
454     qreal lower = 0;
455     qreal upper = 0;
456
457     switch (factor.first) {
458     case QGraphicsAnchorLayoutPrivate::MinimumToMinPreferred:
459         lower = min;
460         upper = minPref;
461         break;
462     case QGraphicsAnchorLayoutPrivate::MinPreferredToPreferred:
463         lower = minPref;
464         upper = pref;
465         break;
466     case QGraphicsAnchorLayoutPrivate::PreferredToMaxPreferred:
467         lower = pref;
468         upper = maxPref;
469         break;
470     case QGraphicsAnchorLayoutPrivate::MaxPreferredToMaximum:
471         lower = maxPref;
472         upper = max;
473         break;
474     }
475
476     return lower + factor.second * (upper - lower);
477 }
478
479 void SequentialAnchorData::updateChildrenSizes()
480 {
481     // Band here refers if the value is in the Minimum To Preferred
482     // band (the lower band) or the Preferred To Maximum (the upper band).
483
484     const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> minFactor =
485         getFactor(sizeAtMinimum, minSize, minPrefSize, prefSize, maxPrefSize, maxSize);
486     const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> prefFactor =
487         getFactor(sizeAtPreferred, minSize, minPrefSize, prefSize, maxPrefSize, maxSize);
488     const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> maxFactor =
489         getFactor(sizeAtMaximum, minSize, minPrefSize, prefSize, maxPrefSize, maxSize);
490
491     // XXX This is not safe if Vertex simplification takes place after the sequential
492     // anchor is created. In that case, "prev" will be a group-vertex, different from
493     // "from" or "to", that _contains_ one of them.
494     AnchorVertex *prev = from;
495
496     for (int i = 0; i < m_edges.count(); ++i) {
497         AnchorData *e = m_edges.at(i);
498
499         const bool edgeIsForward = (e->from == prev);
500         if (edgeIsForward) {
501             e->sizeAtMinimum = interpolate(minFactor, e->minSize, e->minPrefSize,
502                                            e->prefSize, e->maxPrefSize, e->maxSize);
503             e->sizeAtPreferred = interpolate(prefFactor, e->minSize, e->minPrefSize,
504                                            e->prefSize, e->maxPrefSize, e->maxSize);
505             e->sizeAtMaximum = interpolate(maxFactor, e->minSize, e->minPrefSize,
506                                            e->prefSize, e->maxPrefSize, e->maxSize);
507             prev = e->to;
508         } else {
509             Q_ASSERT(prev == e->to);
510             e->sizeAtMinimum = interpolate(minFactor, e->maxSize, e->maxPrefSize,
511                                            e->prefSize, e->minPrefSize, e->minSize);
512             e->sizeAtPreferred = interpolate(prefFactor, e->maxSize, e->maxPrefSize,
513                                            e->prefSize, e->minPrefSize, e->minSize);
514             e->sizeAtMaximum = interpolate(maxFactor, e->maxSize, e->maxPrefSize,
515                                            e->prefSize, e->minPrefSize, e->minSize);
516             prev = e->from;
517         }
518
519         e->updateChildrenSizes();
520     }
521 }
522
523 void SequentialAnchorData::calculateSizeHints()
524 {
525     minSize = 0;
526     prefSize = 0;
527     maxSize = 0;
528     minPrefSize = 0;
529     maxPrefSize = 0;
530
531     AnchorVertex *prev = from;
532
533     for (int i = 0; i < m_edges.count(); ++i) {
534         AnchorData *edge = m_edges.at(i);
535
536         const bool edgeIsForward = (edge->from == prev);
537         if (edgeIsForward) {
538             minSize += edge->minSize;
539             prefSize += edge->prefSize;
540             maxSize += edge->maxSize;
541             minPrefSize += edge->minPrefSize;
542             maxPrefSize += edge->maxPrefSize;
543             prev = edge->to;
544         } else {
545             Q_ASSERT(prev == edge->to);
546             minSize -= edge->maxSize;
547             prefSize -= edge->prefSize;
548             maxSize -= edge->minSize;
549             minPrefSize -= edge->maxPrefSize;
550             maxPrefSize -= edge->minPrefSize;
551             prev = edge->from;
552         }
553     }
554
555     // See comment in AnchorData::refreshSizeHints() about sizeAt* values
556     sizeAtMinimum = prefSize;
557     sizeAtPreferred = prefSize;
558     sizeAtMaximum = prefSize;
559 }
560
561 #ifdef QT_DEBUG
562 void AnchorData::dump(int indent) {
563     if (type == Parallel) {
564         qDebug("%*s type: parallel:", indent, "");
565         ParallelAnchorData *p = static_cast<ParallelAnchorData *>(this);
566         p->firstEdge->dump(indent+2);
567         p->secondEdge->dump(indent+2);
568     } else if (type == Sequential) {
569         SequentialAnchorData *s = static_cast<SequentialAnchorData *>(this);
570         int kids = s->m_edges.count();
571         qDebug("%*s type: sequential(%d):", indent, "", kids);
572         for (int i = 0; i < kids; ++i) {
573             s->m_edges.at(i)->dump(indent+2);
574         }
575     } else {
576         qDebug("%*s type: Normal:", indent, "");
577     }
578 }
579
580 #endif
581
582 QSimplexConstraint *GraphPath::constraint(const GraphPath &path) const
583 {
584     // Calculate
585     QSet<AnchorData *> cPositives;
586     QSet<AnchorData *> cNegatives;
587     QSet<AnchorData *> intersection;
588
589     cPositives = positives + path.negatives;
590     cNegatives = negatives + path.positives;
591
592     intersection = cPositives & cNegatives;
593
594     cPositives -= intersection;
595     cNegatives -= intersection;
596
597     // Fill
598     QSimplexConstraint *c = new QSimplexConstraint;
599     QSet<AnchorData *>::iterator i;
600     for (i = cPositives.begin(); i != cPositives.end(); ++i)
601         c->variables.insert(*i, 1.0);
602
603     for (i = cNegatives.begin(); i != cNegatives.end(); ++i)
604         c->variables.insert(*i, -1.0);
605
606     return c;
607 }
608
609 #ifdef QT_DEBUG
610 QString GraphPath::toString() const
611 {
612     QString string(QLatin1String("Path: "));
613     foreach(AnchorData *edge, positives)
614         string += QString::fromAscii(" (+++) %1").arg(edge->toString());
615
616     foreach(AnchorData *edge, negatives)
617         string += QString::fromAscii(" (---) %1").arg(edge->toString());
618
619     return string;
620 }
621 #endif
622
623 QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate()
624     : calculateGraphCacheDirty(true), styleInfoDirty(true)
625 {
626     for (int i = 0; i < NOrientations; ++i) {
627         for (int j = 0; j < 3; ++j) {
628             sizeHints[i][j] = -1;
629         }
630         interpolationProgress[i] = -1;
631
632         spacings[i] = -1;
633         graphHasConflicts[i] = false;
634
635         layoutFirstVertex[i] = 0;
636         layoutCentralVertex[i] = 0;
637         layoutLastVertex[i] = 0;
638     }
639 }
640
641 Qt::AnchorPoint QGraphicsAnchorLayoutPrivate::oppositeEdge(Qt::AnchorPoint edge)
642 {
643     switch (edge) {
644     case Qt::AnchorLeft:
645         edge = Qt::AnchorRight;
646         break;
647     case Qt::AnchorRight:
648         edge = Qt::AnchorLeft;
649         break;
650     case Qt::AnchorTop:
651         edge = Qt::AnchorBottom;
652         break;
653     case Qt::AnchorBottom:
654         edge = Qt::AnchorTop;
655         break;
656     default:
657         break;
658     }
659     return edge;
660 }
661
662
663 /*!
664  * \internal
665  *
666  * helper function in order to avoid overflowing anchor sizes
667  * the returned size will never be larger than FLT_MAX
668  *
669  */
670 inline static qreal checkAdd(qreal a, qreal b)
671 {
672     if (FLT_MAX - b  < a)
673         return FLT_MAX;
674     return a + b;
675 }
676
677 /*!
678     \internal
679
680     Adds \a newAnchor to the graph.
681
682     Returns the newAnchor itself if it could be added without further changes to the graph. If a
683     new parallel anchor had to be created, then returns the new parallel anchor. If a parallel anchor
684     had to be created and it results in an unfeasible setup, \a feasible is set to false, otherwise
685     true.
686
687     Note that in the case a new parallel anchor is created, it might also take over some constraints
688     from its children anchors.
689 */
690 AnchorData *QGraphicsAnchorLayoutPrivate::addAnchorMaybeParallel(AnchorData *newAnchor, bool *feasible)
691 {
692     Orientation orientation = Orientation(newAnchor->orientation);
693     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
694     *feasible = true;
695
696     // If already exists one anchor where newAnchor is supposed to be, we create a parallel
697     // anchor.
698     if (AnchorData *oldAnchor = g.takeEdge(newAnchor->from, newAnchor->to)) {
699         ParallelAnchorData *parallel = new ParallelAnchorData(oldAnchor, newAnchor);
700
701         // The parallel anchor will "replace" its children anchors in
702         // every center constraint that they appear.
703
704         // ### If the dependent (center) anchors had reference(s) to their constraints, we
705         // could avoid traversing all the itemCenterConstraints.
706         QList<QSimplexConstraint *> &constraints = itemCenterConstraints[orientation];
707
708         AnchorData *children[2] = { oldAnchor, newAnchor };
709         QList<QSimplexConstraint *> *childrenConstraints[2] = { &parallel->m_firstConstraints,
710                                                                 &parallel->m_secondConstraints };
711
712         for (int i = 0; i < 2; ++i) {
713             AnchorData *child = children[i];
714             QList<QSimplexConstraint *> *childConstraints = childrenConstraints[i];
715
716             // We need to fix the second child constraints if the parallel group will have the
717             // opposite direction of the second child anchor. For the point of view of external
718             // entities, this anchor was reversed. So if at some point we say that the parallel
719             // has a value of 20, this mean that the second child (when reversed) will be
720             // assigned -20.
721             const bool needsReverse = i == 1 && !parallel->secondForward();
722
723             if (!child->isCenterAnchor)
724                 continue;
725
726             parallel->isCenterAnchor = true;
727
728             for (int j = 0; j < constraints.count(); ++j) {
729                 QSimplexConstraint *c = constraints[j];
730                 if (c->variables.contains(child)) {
731                     childConstraints->append(c);
732                     qreal v = c->variables.take(child);
733                     if (needsReverse)
734                         v *= -1;
735                     c->variables.insert(parallel, v);
736                 }
737             }
738         }
739
740         // At this point we can identify that the parallel anchor is not feasible, e.g. one
741         // anchor minimum size is bigger than the other anchor maximum size.
742         *feasible = parallel->calculateSizeHints();
743         newAnchor = parallel;
744     }
745
746     g.createEdge(newAnchor->from, newAnchor->to, newAnchor);
747     return newAnchor;
748 }
749
750 /*!
751     \internal
752
753     Takes the sequence of vertices described by (\a before, \a vertices, \a after) and removes
754     all anchors connected to the vertices in \a vertices, returning one simplified anchor between
755     \a before and \a after.
756
757     Note that this function doesn't add the created anchor to the graph. This should be done by
758     the caller.
759 */
760 static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *graph,
761                                   AnchorVertex *before,
762                                   const QVector<AnchorVertex*> &vertices,
763                                   AnchorVertex *after)
764 {
765 #if defined(QT_DEBUG) && 0
766     QString strVertices;
767     for (int i = 0; i < vertices.count(); ++i) {
768         strVertices += QString::fromAscii("%1 - ").arg(vertices.at(i)->toString());
769     }
770     QString strPath = QString::fromAscii("%1 - %2%3").arg(before->toString(), strVertices, after->toString());
771     qDebug("simplifying [%s] to [%s - %s]", qPrintable(strPath), qPrintable(before->toString()), qPrintable(after->toString()));
772 #endif
773
774     AnchorVertex *prev = before;
775     QVector<AnchorData *> edges;
776
777     // Take from the graph, the edges that will be simplificated
778     for (int i = 0; i < vertices.count(); ++i) {
779         AnchorVertex *next = vertices.at(i);
780         AnchorData *ad = graph->takeEdge(prev, next);
781         Q_ASSERT(ad);
782         edges.append(ad);
783         prev = next;
784     }
785
786     // Take the last edge (not covered in the loop above)
787     AnchorData *ad = graph->takeEdge(vertices.last(), after);
788     Q_ASSERT(ad);
789     edges.append(ad);
790
791     // Create sequence
792     SequentialAnchorData *sequence = new SequentialAnchorData(vertices, edges);
793     sequence->from = before;
794     sequence->to = after;
795
796     sequence->calculateSizeHints();
797
798     return sequence;
799 }
800
801 /*!
802    \internal
803
804    The purpose of this function is to simplify the graph.
805    Simplification serves two purposes:
806    1. Reduce the number of edges in the graph, (thus the number of variables to the equation
807       solver is reduced, and the solver performs better).
808    2. Be able to do distribution of sequences of edges more intelligently (esp. with sequential
809       anchors)
810
811    It is essential that it must be possible to restore simplified anchors back to their "original"
812    form. This is done by restoreSimplifiedAnchor().
813
814    There are two types of simplification that can be done:
815    1. Sequential simplification
816       Sequential simplification means that all sequences of anchors will be merged into one single
817       anchor. Only anhcors that points in the same direction will be merged.
818    2. Parallel simplification
819       If a simplified sequential anchor is about to be inserted between two vertices in the graph
820       and there already exist an anchor between those two vertices, a parallel anchor will be
821       created that serves as a placeholder for the sequential anchor and the anchor that was
822       already between the two vertices.
823
824    The process of simplification can be described as:
825
826    1. Simplify all sequences of anchors into one anchor.
827       If no further simplification was done, go to (3)
828       - If there already exist an anchor where the sequential anchor is supposed to be inserted,
829         take that anchor out of the graph
830       - Then create a parallel anchor that holds the sequential anchor and the anchor just taken
831         out of the graph.
832    2. Go to (1)
833    3. Done
834
835    When creating the parallel anchors, the algorithm might identify unfeasible situations. In this
836    case the simplification process stops and returns false. Otherwise returns true.
837 */
838 bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
839 {
840     if (items.isEmpty())
841         return true;
842
843 #if defined(QT_DEBUG) && 0
844     qDebug("Simplifying Graph for %s",
845            orientation == Horizontal ? "Horizontal" : "Vertical");
846
847     static int count = 0;
848     if (orientation == Horizontal) {
849         count++;
850         dumpGraph(QString::fromAscii("%1-full").arg(count));
851     }
852 #endif
853
854     // Vertex simplification
855     if (!simplifyVertices(orientation)) {
856         restoreVertices(orientation);
857         return false;
858     }
859
860     // Anchor simplification
861     bool dirty;
862     bool feasible = true;
863     do {
864         dirty = simplifyGraphIteration(orientation, &feasible);
865     } while (dirty && feasible);
866
867     // Note that if we are not feasible, we fallback and make sure that the graph is fully restored
868     if (!feasible) {
869         restoreSimplifiedGraph(orientation);
870         restoreVertices(orientation);
871         return false;
872     }
873
874 #if defined(QT_DEBUG) && 0
875     dumpGraph(QString::fromAscii("%1-simplified-%2").arg(count).arg(
876                   QString::fromAscii(orientation == Horizontal ? "Horizontal" : "Vertical")));
877 #endif
878
879     return true;
880 }
881
882 static AnchorVertex *replaceVertex_helper(AnchorData *data, AnchorVertex *oldV, AnchorVertex *newV)
883 {
884     AnchorVertex *other;
885     if (data->from == oldV) {
886         data->from = newV;
887         other = data->to;
888     } else {
889         data->to = newV;
890         other = data->from;
891     }
892     return other;
893 }
894
895 bool QGraphicsAnchorLayoutPrivate::replaceVertex(Orientation orientation, AnchorVertex *oldV,
896                                                  AnchorVertex *newV, const QList<AnchorData *> &edges)
897 {
898     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
899     bool feasible = true;
900
901     for (int i = 0; i < edges.count(); ++i) {
902         AnchorData *ad = edges[i];
903         AnchorVertex *otherV = replaceVertex_helper(ad, oldV, newV);
904
905 #if defined(QT_DEBUG)
906         ad->name = QString::fromAscii("%1 --to--> %2").arg(ad->from->toString()).arg(ad->to->toString());
907 #endif
908
909         bool newFeasible;
910         AnchorData *newAnchor = addAnchorMaybeParallel(ad, &newFeasible);
911         feasible &= newFeasible;
912
913         if (newAnchor != ad) {
914             // A parallel was created, we mark that in the list of anchors created by vertex
915             // simplification. This is needed because we want to restore them in a separate step
916             // from the restoration of anchor simplification.
917             anchorsFromSimplifiedVertices[orientation].append(newAnchor);
918         }
919
920         g.takeEdge(oldV, otherV);
921     }
922
923     return feasible;
924 }
925
926 /*!
927     \internal
928 */
929 bool QGraphicsAnchorLayoutPrivate::simplifyVertices(Orientation orientation)
930 {
931     Q_Q(QGraphicsAnchorLayout);
932     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
933
934     // We'll walk through vertices
935     QStack<AnchorVertex *> stack;
936     stack.push(layoutFirstVertex[orientation]);
937     QSet<AnchorVertex *> visited;
938
939     while (!stack.isEmpty()) {
940         AnchorVertex *v = stack.pop();
941         visited.insert(v);
942
943         // Each adjacent of 'v' is a possible vertex to be merged. So we traverse all of
944         // them. Since once a merge is made, we might add new adjacents, and we don't want to
945         // pass two times through one adjacent. The 'index' is used to track our position.
946         QList<AnchorVertex *> adjacents = g.adjacentVertices(v);
947         int index = 0;
948
949         while (index < adjacents.count()) {
950             AnchorVertex *next = adjacents.at(index);
951             index++;
952
953             AnchorData *data = g.edgeData(v, next);
954             const bool bothLayoutVertices = v->m_item == q && next->m_item == q;
955             const bool zeroSized = !data->minSize && !data->maxSize;
956
957             if (!bothLayoutVertices && zeroSized) {
958
959                 // Create a new vertex pair, note that we keep a list of those vertices so we can
960                 // easily process them when restoring the graph.
961                 AnchorVertexPair *newV = new AnchorVertexPair(v, next, data);
962                 simplifiedVertices[orientation].append(newV);
963
964                 // Collect the anchors of both vertices, the new vertex pair will take their place
965                 // in those anchors
966                 const QList<AnchorVertex *> &vAdjacents = g.adjacentVertices(v);
967                 const QList<AnchorVertex *> &nextAdjacents = g.adjacentVertices(next);
968
969                 for (int i = 0; i < vAdjacents.count(); ++i) {
970                     AnchorVertex *adjacent = vAdjacents.at(i);
971                     if (adjacent != next) {
972                         AnchorData *ad = g.edgeData(v, adjacent);
973                         newV->m_firstAnchors.append(ad);
974                     }
975                 }
976
977                 for (int i = 0; i < nextAdjacents.count(); ++i) {
978                     AnchorVertex *adjacent = nextAdjacents.at(i);
979                     if (adjacent != v) {
980                         AnchorData *ad = g.edgeData(next, adjacent);
981                         newV->m_secondAnchors.append(ad);
982
983                         // We'll also add new vertices to the adjacent list of the new 'v', to be
984                         // created as a vertex pair and replace the current one.
985                         if (!adjacents.contains(adjacent))
986                             adjacents.append(adjacent);
987                     }
988                 }
989
990                 // ### merge this loop into the ones that calculated m_firstAnchors/m_secondAnchors?
991                 // Make newV take the place of v and next
992                 bool feasible = replaceVertex(orientation, v, newV, newV->m_firstAnchors);
993                 feasible &= replaceVertex(orientation, next, newV, newV->m_secondAnchors);
994
995                 // Update the layout vertex information if one of the vertices is a layout vertex.
996                 AnchorVertex *layoutVertex = 0;
997                 if (v->m_item == q)
998                     layoutVertex = v;
999                 else if (next->m_item == q)
1000                     layoutVertex = next;
1001
1002                 if (layoutVertex) {
1003                     // Layout vertices always have m_item == q...
1004                     newV->m_item = q;
1005                     changeLayoutVertex(orientation, layoutVertex, newV);
1006                 }
1007
1008                 g.takeEdge(v, next);
1009
1010                 // If a non-feasibility is found, we leave early and cancel the simplification
1011                 if (!feasible)
1012                     return false;
1013
1014                 v = newV;
1015                 visited.insert(newV);
1016
1017             } else if (!visited.contains(next) && !stack.contains(next)) {
1018                 // If the adjacent is not fit for merge and it wasn't visited by the outermost
1019                 // loop, we add it to the stack.
1020                 stack.push(next);
1021             }
1022         }
1023     }
1024
1025     return true;
1026 }
1027
1028 /*!
1029     \internal
1030
1031     One iteration of the simplification algorithm. Returns true if another iteration is needed.
1032
1033     The algorithm walks the graph in depth-first order, and only collects vertices that has two
1034     edges connected to it.  If the vertex does not have two edges or if it is a layout edge, it
1035     will take all the previously collected vertices and try to create a simplified sequential
1036     anchor representing all the previously collected vertices.  Once the simplified anchor is
1037     inserted, the collected list is cleared in order to find the next sequence to simplify.
1038
1039     Note that there are some catches to this that are not covered by the above explanation, see
1040     the function comments for more details.
1041 */
1042 bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation,
1043                                                           bool *feasible)
1044 {
1045     Q_Q(QGraphicsAnchorLayout);
1046     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
1047
1048     QSet<AnchorVertex *> visited;
1049     QStack<QPair<AnchorVertex *, AnchorVertex *> > stack;
1050     stack.push(qMakePair(static_cast<AnchorVertex *>(0), layoutFirstVertex[orientation]));
1051     QVector<AnchorVertex*> candidates;
1052
1053     // Walk depth-first, in the stack we store start of the candidate sequence (beforeSequence)
1054     // and the vertex to be visited.
1055     while (!stack.isEmpty()) {
1056         QPair<AnchorVertex *, AnchorVertex *> pair = stack.pop();
1057         AnchorVertex *beforeSequence = pair.first;
1058         AnchorVertex *v = pair.second;
1059
1060         // The basic idea is to determine whether we found an end of sequence,
1061         // if that's the case, we stop adding vertices to the candidate list
1062         // and do a simplification step.
1063         //
1064         // A vertex can trigger an end of sequence if
1065         // (a) it is a layout vertex, we don't simplify away the layout vertices;
1066         // (b) it does not have exactly 2 adjacents;
1067         // (c) its next adjacent is already visited (a cycle in the graph).
1068         // (d) the next anchor is a center anchor.
1069
1070         const QList<AnchorVertex *> &adjacents = g.adjacentVertices(v);
1071         const bool isLayoutVertex = v->m_item == q;
1072         AnchorVertex *afterSequence = v;
1073         bool endOfSequence = false;
1074
1075         //
1076         // Identify the end cases.
1077         //
1078
1079         // Identifies cases (a) and (b)
1080         endOfSequence = isLayoutVertex || adjacents.count() != 2;
1081
1082         if (!endOfSequence) {
1083             // This is a tricky part. We peek at the next vertex to find out whether
1084             //
1085             // - we already visited the next vertex (c);
1086             // - the next anchor is a center (d).
1087             //
1088             // Those are needed to identify the remaining end of sequence cases. Note that unlike
1089             // (a) and (b), we preempt the end of sequence by looking into the next vertex.
1090
1091             // Peek at the next vertex
1092             AnchorVertex *after;
1093             if (candidates.isEmpty())
1094                 after = (beforeSequence == adjacents.last() ? adjacents.first() : adjacents.last());
1095             else
1096                 after = (candidates.last() == adjacents.last() ? adjacents.first() : adjacents.last());
1097
1098             // ### At this point we assumed that candidates will not contain 'after', this may not hold
1099             // when simplifying FLOATing anchors.
1100             Q_ASSERT(!candidates.contains(after));
1101
1102             const AnchorData *data = g.edgeData(v, after);
1103             Q_ASSERT(data);
1104             const bool cycleFound = visited.contains(after);
1105
1106             // Now cases (c) and (d)...
1107             endOfSequence = cycleFound || data->isCenterAnchor;
1108
1109             if (!endOfSequence) {
1110                 // If it's not an end of sequence, then the vertex didn't trigger neither of the
1111                 // previously three cases, so it can be added to the candidates list.
1112                 candidates.append(v);
1113             } else if (cycleFound && (beforeSequence != after)) {
1114                 afterSequence = after;
1115                 candidates.append(v);
1116             }
1117         }
1118
1119         //
1120         // Add next non-visited vertices to the stack.
1121         //
1122         for (int i = 0; i < adjacents.count(); ++i) {
1123             AnchorVertex *next = adjacents.at(i);
1124             if (visited.contains(next))
1125                 continue;
1126
1127             // If current vertex is an end of sequence, and it'll reset the candidates list. So
1128             // the next vertices will build candidates lists with the current vertex as 'before'
1129             // vertex. If it's not an end of sequence, we keep the original 'before' vertex,
1130             // since we are keeping the candidates list.
1131             if (endOfSequence)
1132                 stack.push(qMakePair(v, next));
1133             else
1134                 stack.push(qMakePair(beforeSequence, next));
1135         }
1136
1137         visited.insert(v);
1138
1139         if (!endOfSequence || candidates.isEmpty())
1140             continue;
1141
1142         //
1143         // Create a sequence for (beforeSequence, candidates, afterSequence).
1144         //
1145
1146         // One restriction we have is to not simplify half of an anchor and let the other half
1147         // unsimplified. So we remove center edges before and after the sequence.
1148         const AnchorData *firstAnchor = g.edgeData(beforeSequence, candidates.first());
1149         if (firstAnchor->isCenterAnchor) {
1150             beforeSequence = candidates.first();
1151             candidates.remove(0);
1152
1153             // If there's not candidates to be simplified, leave.
1154             if (candidates.isEmpty())
1155                 continue;
1156         }
1157
1158         const AnchorData *lastAnchor = g.edgeData(candidates.last(), afterSequence);
1159         if (lastAnchor->isCenterAnchor) {
1160             afterSequence = candidates.last();
1161             candidates.remove(candidates.count() - 1);
1162
1163             if (candidates.isEmpty())
1164                 continue;
1165         }
1166
1167         //
1168         // Add the sequence to the graph.
1169         //
1170
1171         AnchorData *sequence = createSequence(&g, beforeSequence, candidates, afterSequence);
1172
1173         // If 'beforeSequence' and 'afterSequence' already had an anchor between them, we'll
1174         // create a parallel anchor between the new sequence and the old anchor.
1175         bool newFeasible;
1176         AnchorData *newAnchor = addAnchorMaybeParallel(sequence, &newFeasible);
1177
1178         if (!newFeasible) {
1179             *feasible = false;
1180             return false;
1181         }
1182
1183         // When a new parallel anchor is create in the graph, we finish the iteration and return
1184         // true to indicate a new iteration is needed. This happens because a parallel anchor
1185         // changes the number of adjacents one vertex has, possibly opening up oportunities for
1186         // building candidate lists (when adjacents == 2).
1187         if (newAnchor != sequence)
1188             return true;
1189
1190         // If there was no parallel simplification, we'll keep walking the graph. So we clear the
1191         // candidates list to start again.
1192         candidates.clear();
1193     }
1194
1195     return false;
1196 }
1197
1198 void QGraphicsAnchorLayoutPrivate::restoreSimplifiedAnchor(AnchorData *edge)
1199 {
1200 #if 0
1201     static const char *anchortypes[] = {"Normal",
1202                                         "Sequential",
1203                                         "Parallel"};
1204     qDebug("Restoring %s edge.", anchortypes[int(edge->type)]);
1205 #endif
1206
1207     Graph<AnchorVertex, AnchorData> &g = graph[edge->orientation];
1208
1209     if (edge->type == AnchorData::Normal) {
1210         g.createEdge(edge->from, edge->to, edge);
1211
1212     } else if (edge->type == AnchorData::Sequential) {
1213         SequentialAnchorData *sequence = static_cast<SequentialAnchorData *>(edge);
1214
1215         for (int i = 0; i < sequence->m_edges.count(); ++i) {
1216             AnchorData *data = sequence->m_edges.at(i);
1217             restoreSimplifiedAnchor(data);
1218         }
1219
1220         delete sequence;
1221
1222     } else if (edge->type == AnchorData::Parallel) {
1223
1224         // Skip parallel anchors that were created by vertex simplification, they will be processed
1225         // later, when restoring vertex simplification.
1226         // ### we could improve this check bit having a bit inside 'edge'
1227         if (anchorsFromSimplifiedVertices[edge->orientation].contains(edge))
1228             return;
1229
1230         ParallelAnchorData* parallel = static_cast<ParallelAnchorData*>(edge);
1231         restoreSimplifiedConstraints(parallel);
1232
1233         // ### Because of the way parallel anchors are created in the anchor simplification
1234         // algorithm, we know that one of these will be a sequence, so it'll be safe if the other
1235         // anchor create an edge between the same vertices as the parallel.
1236         Q_ASSERT(parallel->firstEdge->type == AnchorData::Sequential
1237                  || parallel->secondEdge->type == AnchorData::Sequential);
1238         restoreSimplifiedAnchor(parallel->firstEdge);
1239         restoreSimplifiedAnchor(parallel->secondEdge);
1240
1241         delete parallel;
1242     }
1243 }
1244
1245 void QGraphicsAnchorLayoutPrivate::restoreSimplifiedConstraints(ParallelAnchorData *parallel)
1246 {
1247     if (!parallel->isCenterAnchor)
1248         return;
1249
1250     for (int i = 0; i < parallel->m_firstConstraints.count(); ++i) {
1251         QSimplexConstraint *c = parallel->m_firstConstraints.at(i);
1252         qreal v = c->variables[parallel];
1253         c->variables.remove(parallel);
1254         c->variables.insert(parallel->firstEdge, v);
1255     }
1256
1257     // When restoring, we might have to revert constraints back. See comments on
1258     // addAnchorMaybeParallel().
1259     const bool needsReverse = !parallel->secondForward();
1260
1261     for (int i = 0; i < parallel->m_secondConstraints.count(); ++i) {
1262         QSimplexConstraint *c = parallel->m_secondConstraints.at(i);
1263         qreal v = c->variables[parallel];
1264         if (needsReverse)
1265             v *= -1;
1266         c->variables.remove(parallel);
1267         c->variables.insert(parallel->secondEdge, v);
1268     }
1269 }
1270
1271 void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientation)
1272 {
1273 #if 0
1274     qDebug("Restoring Simplified Graph for %s",
1275            orientation == Horizontal ? "Horizontal" : "Vertical");
1276 #endif
1277
1278     // Restore anchor simplification
1279     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
1280     QList<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections();
1281     for (int i = 0; i < connections.count(); ++i) {
1282         AnchorVertex *v1 = connections.at(i).first;
1283         AnchorVertex *v2 = connections.at(i).second;
1284         AnchorData *edge = g.edgeData(v1, v2);
1285
1286         // We restore only sequential anchors and parallels that were not created by
1287         // vertex simplification.
1288         if (edge->type == AnchorData::Sequential
1289             || (edge->type == AnchorData::Parallel &&
1290                 !anchorsFromSimplifiedVertices[orientation].contains(edge))) {
1291
1292             g.takeEdge(v1, v2);
1293             restoreSimplifiedAnchor(edge);
1294         }
1295     }
1296
1297     restoreVertices(orientation);
1298 }
1299
1300 void QGraphicsAnchorLayoutPrivate::restoreVertices(Orientation orientation)
1301 {
1302     Q_Q(QGraphicsAnchorLayout);
1303
1304     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
1305     QList<AnchorVertexPair *> &toRestore = simplifiedVertices[orientation];
1306
1307     // Since we keep a list of parallel anchors and vertices that were created during vertex
1308     // simplification, we can now iterate on those lists instead of traversing the graph
1309     // recursively.
1310
1311     // First, restore the constraints changed when we created parallel anchors. Note that this
1312     // works at this point because the constraints doesn't depend on vertex information and at
1313     // this point it's always safe to identify whether the second child is forward or backwards.
1314     // In the next step, we'll change the anchors vertices so that would not be possible anymore.
1315     QList<AnchorData *> &parallelAnchors = anchorsFromSimplifiedVertices[orientation];
1316
1317     for (int i = parallelAnchors.count() - 1; i >= 0; --i) {
1318         ParallelAnchorData *parallel = static_cast<ParallelAnchorData *>(parallelAnchors.at(i));
1319         restoreSimplifiedConstraints(parallel);
1320     }
1321
1322     // Then, we will restore the vertices in the inverse order of creation, this way we ensure that
1323     // the vertex being restored was not wrapped by another simplification.
1324     for (int i = toRestore.count() - 1; i >= 0; --i) {
1325         AnchorVertexPair *pair = toRestore.at(i);
1326         QList<AnchorVertex *> adjacents = g.adjacentVertices(pair);
1327
1328         // Restore the removed edge, this will also restore both vertices 'first' and 'second' to
1329         // the graph structure.
1330         AnchorVertex *first = pair->m_first;
1331         AnchorVertex *second = pair->m_second;
1332         g.createEdge(first, second, pair->m_removedAnchor);
1333
1334         // Restore the anchors for the first child vertex
1335         for (int j = 0; j < pair->m_firstAnchors.count(); ++j) {
1336             AnchorData *ad = pair->m_firstAnchors.at(j);
1337             Q_ASSERT(ad->from == pair || ad->to == pair);
1338
1339             replaceVertex_helper(ad, pair, first);
1340             g.createEdge(ad->from, ad->to, ad);
1341         }
1342
1343         // Restore the anchors for the second child vertex
1344         for (int j = 0; j < pair->m_secondAnchors.count(); ++j) {
1345             AnchorData *ad = pair->m_secondAnchors.at(j);
1346             Q_ASSERT(ad->from == pair || ad->to == pair);
1347
1348             replaceVertex_helper(ad, pair, second);
1349             g.createEdge(ad->from, ad->to, ad);
1350         }
1351
1352         for (int j = 0; j < adjacents.count(); ++j) {
1353             g.takeEdge(pair, adjacents.at(j));
1354         }
1355
1356         // The pair simplified a layout vertex, so place back the correct vertex in the variable
1357         // that track layout vertices
1358         if (pair->m_item == q) {
1359             AnchorVertex *layoutVertex = first->m_item == q ? first : second;
1360             Q_ASSERT(layoutVertex->m_item == q);
1361             changeLayoutVertex(orientation, pair, layoutVertex);
1362         }
1363
1364         delete pair;
1365     }
1366     qDeleteAll(parallelAnchors);
1367     parallelAnchors.clear();
1368     toRestore.clear();
1369 }
1370
1371 QGraphicsAnchorLayoutPrivate::Orientation
1372 QGraphicsAnchorLayoutPrivate::edgeOrientation(Qt::AnchorPoint edge)
1373 {
1374     return edge > Qt::AnchorRight ? Vertical : Horizontal;
1375 }
1376
1377 /*!
1378   \internal
1379
1380   Create internal anchors to connect the layout edges (Left to Right and
1381   Top to Bottom).
1382
1383   These anchors doesn't have size restrictions, that will be enforced by
1384   other anchors and items in the layout.
1385 */
1386 void QGraphicsAnchorLayoutPrivate::createLayoutEdges()
1387 {
1388     Q_Q(QGraphicsAnchorLayout);
1389     QGraphicsLayoutItem *layout = q;
1390
1391     // Horizontal
1392     AnchorData *data = new AnchorData;
1393     addAnchor_helper(layout, Qt::AnchorLeft, layout,
1394                      Qt::AnchorRight, data);
1395     data->maxSize = QWIDGETSIZE_MAX;
1396
1397     // Save a reference to layout vertices
1398     layoutFirstVertex[Horizontal] = internalVertex(layout, Qt::AnchorLeft);
1399     layoutCentralVertex[Horizontal] = 0;
1400     layoutLastVertex[Horizontal] = internalVertex(layout, Qt::AnchorRight);
1401
1402     // Vertical
1403     data = new AnchorData;
1404     addAnchor_helper(layout, Qt::AnchorTop, layout,
1405                      Qt::AnchorBottom, data);
1406     data->maxSize = QWIDGETSIZE_MAX;
1407
1408     // Save a reference to layout vertices
1409     layoutFirstVertex[Vertical] = internalVertex(layout, Qt::AnchorTop);
1410     layoutCentralVertex[Vertical] = 0;
1411     layoutLastVertex[Vertical] = internalVertex(layout, Qt::AnchorBottom);
1412 }
1413
1414 void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges()
1415 {
1416     Q_Q(QGraphicsAnchorLayout);
1417
1418     Q_ASSERT(!internalVertex(q, Qt::AnchorHorizontalCenter));
1419     Q_ASSERT(!internalVertex(q, Qt::AnchorVerticalCenter));
1420
1421     removeAnchor_helper(internalVertex(q, Qt::AnchorLeft),
1422                         internalVertex(q, Qt::AnchorRight));
1423     removeAnchor_helper(internalVertex(q, Qt::AnchorTop),
1424                         internalVertex(q, Qt::AnchorBottom));
1425 }
1426
1427 void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item)
1428 {
1429     items.append(item);
1430
1431     // Create horizontal and vertical internal anchors for the item and
1432     // refresh its size hint / policy values.
1433     AnchorData *data = new AnchorData;
1434     addAnchor_helper(item, Qt::AnchorLeft, item, Qt::AnchorRight, data);
1435     data->refreshSizeHints();
1436
1437     data = new AnchorData;
1438     addAnchor_helper(item, Qt::AnchorTop, item, Qt::AnchorBottom, data);
1439     data->refreshSizeHints();
1440 }
1441
1442 /*!
1443   \internal
1444
1445   By default, each item in the layout is represented internally as
1446   a single anchor in each direction. For instance, from Left to Right.
1447
1448   However, to support anchorage of items to the center of items, we
1449   must split this internal anchor into two half-anchors. From Left
1450   to Center and then from Center to Right, with the restriction that
1451   these anchors must have the same time at all times.
1452 */
1453 void QGraphicsAnchorLayoutPrivate::createCenterAnchors(
1454     QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge)
1455 {
1456     Q_Q(QGraphicsAnchorLayout);
1457
1458     Orientation orientation;
1459     switch (centerEdge) {
1460     case Qt::AnchorHorizontalCenter:
1461         orientation = Horizontal;
1462         break;
1463     case Qt::AnchorVerticalCenter:
1464         orientation = Vertical;
1465         break;
1466     default:
1467         // Don't create center edges unless needed
1468         return;
1469     }
1470
1471     // Check if vertex already exists
1472     if (internalVertex(item, centerEdge))
1473         return;
1474
1475     // Orientation code
1476     Qt::AnchorPoint firstEdge;
1477     Qt::AnchorPoint lastEdge;
1478
1479     if (orientation == Horizontal) {
1480         firstEdge = Qt::AnchorLeft;
1481         lastEdge = Qt::AnchorRight;
1482     } else {
1483         firstEdge = Qt::AnchorTop;
1484         lastEdge = Qt::AnchorBottom;
1485     }
1486
1487     AnchorVertex *first = internalVertex(item, firstEdge);
1488     AnchorVertex *last = internalVertex(item, lastEdge);
1489     Q_ASSERT(first && last);
1490
1491     // Create new anchors
1492     QSimplexConstraint *c = new QSimplexConstraint;
1493
1494     AnchorData *data = new AnchorData;
1495     c->variables.insert(data, 1.0);
1496     addAnchor_helper(item, firstEdge, item, centerEdge, data);
1497     data->isCenterAnchor = true;
1498     data->dependency = AnchorData::Master;
1499     data->refreshSizeHints();
1500
1501     data = new AnchorData;
1502     c->variables.insert(data, -1.0);
1503     addAnchor_helper(item, centerEdge, item, lastEdge, data);
1504     data->isCenterAnchor = true;
1505     data->dependency = AnchorData::Slave;
1506     data->refreshSizeHints();
1507
1508     itemCenterConstraints[orientation].append(c);
1509
1510     // Remove old one
1511     removeAnchor_helper(first, last);
1512
1513     if (item == q) {
1514         layoutCentralVertex[orientation] = internalVertex(q, centerEdge);
1515     }
1516 }
1517
1518 void QGraphicsAnchorLayoutPrivate::removeCenterAnchors(
1519     QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge,
1520     bool substitute)
1521 {
1522     Q_Q(QGraphicsAnchorLayout);
1523
1524     Orientation orientation;
1525     switch (centerEdge) {
1526     case Qt::AnchorHorizontalCenter:
1527         orientation = Horizontal;
1528         break;
1529     case Qt::AnchorVerticalCenter:
1530         orientation = Vertical;
1531         break;
1532     default:
1533         // Don't remove edges that not the center ones
1534         return;
1535     }
1536
1537     // Orientation code
1538     Qt::AnchorPoint firstEdge;
1539     Qt::AnchorPoint lastEdge;
1540
1541     if (orientation == Horizontal) {
1542         firstEdge = Qt::AnchorLeft;
1543         lastEdge = Qt::AnchorRight;
1544     } else {
1545         firstEdge = Qt::AnchorTop;
1546         lastEdge = Qt::AnchorBottom;
1547     }
1548
1549     AnchorVertex *center = internalVertex(item, centerEdge);
1550     if (!center)
1551         return;
1552     AnchorVertex *first = internalVertex(item, firstEdge);
1553
1554     Q_ASSERT(first);
1555     Q_ASSERT(center);
1556
1557     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
1558
1559
1560     AnchorData *oldData = g.edgeData(first, center);
1561     // Remove center constraint
1562     for (int i = itemCenterConstraints[orientation].count() - 1; i >= 0; --i) {
1563         if (itemCenterConstraints[orientation].at(i)->variables.contains(oldData)) {
1564             delete itemCenterConstraints[orientation].takeAt(i);
1565             break;
1566         }
1567     }
1568
1569     if (substitute) {
1570         // Create the new anchor that should substitute the left-center-right anchors.
1571         AnchorData *data = new AnchorData;
1572         addAnchor_helper(item, firstEdge, item, lastEdge, data);
1573         data->refreshSizeHints();
1574
1575         // Remove old anchors
1576         removeAnchor_helper(first, center);
1577         removeAnchor_helper(center, internalVertex(item, lastEdge));
1578
1579     } else {
1580         // this is only called from removeAnchors()
1581         // first, remove all non-internal anchors
1582         QList<AnchorVertex*> adjacents = g.adjacentVertices(center);
1583         for (int i = 0; i < adjacents.count(); ++i) {
1584             AnchorVertex *v = adjacents.at(i);
1585             if (v->m_item != item) {
1586                 removeAnchor_helper(center, internalVertex(v->m_item, v->m_edge));
1587             }
1588         }
1589         // when all non-internal anchors is removed it will automatically merge the
1590         // center anchor into a left-right (or top-bottom) anchor. We must also delete that.
1591         // by this time, the center vertex is deleted and merged into a non-centered internal anchor
1592         removeAnchor_helper(first, internalVertex(item, lastEdge));
1593     }
1594
1595     if (item == q) {
1596         layoutCentralVertex[orientation] = 0;
1597     }
1598 }
1599
1600
1601 void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *item,
1602                                                            Orientation orientation)
1603 {
1604     // Remove the item center constraints associated to this item
1605     // ### This is a temporary solution. We should probably use a better
1606     // data structure to hold items and/or their associated constraints
1607     // so that we can remove those easily
1608
1609     AnchorVertex *first = internalVertex(item, orientation == Horizontal ?
1610                                        Qt::AnchorLeft :
1611                                        Qt::AnchorTop);
1612     AnchorVertex *center = internalVertex(item, orientation == Horizontal ?
1613                                         Qt::AnchorHorizontalCenter :
1614                                         Qt::AnchorVerticalCenter);
1615
1616     // Skip if no center constraints exist
1617     if (!center)
1618         return;
1619
1620     Q_ASSERT(first);
1621     AnchorData *internalAnchor = graph[orientation].edgeData(first, center);
1622
1623     // Look for our anchor in all item center constraints, then remove it
1624     for (int i = 0; i < itemCenterConstraints[orientation].size(); ++i) {
1625         if (itemCenterConstraints[orientation].at(i)->variables.contains(internalAnchor)) {
1626             delete itemCenterConstraints[orientation].takeAt(i);
1627             break;
1628         }
1629     }
1630 }
1631
1632 /*!
1633  * \internal
1634  * Implements the high level "addAnchor" feature. Called by the public API
1635  * addAnchor method.
1636  *
1637  * The optional \a spacing argument defines the size of the anchor. If not provided,
1638  * the anchor size is either 0 or not-set, depending on type of anchor created (see
1639  * matrix below).
1640  *
1641  * All anchors that remain with size not-set will assume the standard spacing,
1642  * set either by the layout style or through the "setSpacing" layout API.
1643  */
1644 QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem,
1645                                                          Qt::AnchorPoint firstEdge,
1646                                                          QGraphicsLayoutItem *secondItem,
1647                                                          Qt::AnchorPoint secondEdge,
1648                                                          qreal *spacing)
1649 {
1650     Q_Q(QGraphicsAnchorLayout);
1651     if ((firstItem == 0) || (secondItem == 0)) {
1652         qWarning("QGraphicsAnchorLayout::addAnchor(): "
1653                  "Cannot anchor NULL items");
1654         return 0;
1655     }
1656
1657     if (firstItem == secondItem) {
1658         qWarning("QGraphicsAnchorLayout::addAnchor(): "
1659                  "Cannot anchor the item to itself");
1660         return 0;
1661     }
1662
1663     if (edgeOrientation(secondEdge) != edgeOrientation(firstEdge)) {
1664         qWarning("QGraphicsAnchorLayout::addAnchor(): "
1665                  "Cannot anchor edges of different orientations");
1666         return 0;
1667     }
1668
1669     const QGraphicsLayoutItem *parentWidget = q->parentLayoutItem();
1670     if (firstItem == parentWidget || secondItem == parentWidget) {
1671         qWarning("QGraphicsAnchorLayout::addAnchor(): "
1672                  "You cannot add the parent of the layout to the layout.");
1673         return 0;
1674     }
1675
1676     // In QGraphicsAnchorLayout, items are represented in its internal
1677     // graph as four anchors that connect:
1678     //  - Left -> HCenter
1679     //  - HCenter-> Right
1680     //  - Top -> VCenter
1681     //  - VCenter -> Bottom
1682
1683     // Ensure that the internal anchors have been created for both items.
1684     if (firstItem != q && !items.contains(firstItem)) {
1685         createItemEdges(firstItem);
1686         addChildLayoutItem(firstItem);
1687     }
1688     if (secondItem != q && !items.contains(secondItem)) {
1689         createItemEdges(secondItem);
1690         addChildLayoutItem(secondItem);
1691     }
1692
1693     // Create center edges if needed
1694     createCenterAnchors(firstItem, firstEdge);
1695     createCenterAnchors(secondItem, secondEdge);
1696
1697     // Use heuristics to find out what the user meant with this anchor.
1698     correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge);
1699
1700     AnchorData *data = new AnchorData;
1701     QGraphicsAnchor *graphicsAnchor = acquireGraphicsAnchor(data);
1702
1703     addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data);
1704
1705     if (spacing) {
1706         graphicsAnchor->setSpacing(*spacing);
1707     } else {
1708         // If firstItem or secondItem is the layout itself, the spacing will default to 0.
1709         // Otherwise, the following matrix is used (questionmark means that the spacing
1710         // is queried from the style):
1711         //                from
1712         //  to      Left    HCenter Right
1713         //  Left    0       0       ?
1714         //  HCenter 0       0       0
1715         //  Right   ?       0       0
1716         if (firstItem == q
1717             || secondItem == q
1718             || pickEdge(firstEdge, Horizontal) == Qt::AnchorHorizontalCenter
1719             || oppositeEdge(firstEdge) != secondEdge) {
1720             graphicsAnchor->setSpacing(0);
1721         } else {
1722             graphicsAnchor->unsetSpacing();
1723         }
1724     }
1725
1726     return graphicsAnchor;
1727 }
1728
1729 /*
1730   \internal
1731
1732   This method adds an AnchorData to the internal graph. It is responsible for doing
1733   the boilerplate part of such task.
1734
1735   If another AnchorData exists between the mentioned vertices, it is deleted and
1736   the new one is inserted.
1737 */
1738 void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem,
1739                                                     Qt::AnchorPoint firstEdge,
1740                                                     QGraphicsLayoutItem *secondItem,
1741                                                     Qt::AnchorPoint secondEdge,
1742                                                     AnchorData *data)
1743 {
1744     Q_Q(QGraphicsAnchorLayout);
1745
1746     const Orientation orientation = edgeOrientation(firstEdge);
1747
1748     // Create or increase the reference count for the related vertices.
1749     AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge);
1750     AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge);
1751
1752     // Remove previous anchor
1753     if (graph[orientation].edgeData(v1, v2)) {
1754         removeAnchor_helper(v1, v2);
1755     }
1756
1757     // If its an internal anchor, set the associated item
1758     if (firstItem == secondItem)
1759         data->item = firstItem;
1760
1761     data->orientation = orientation;
1762
1763     // Create a bi-directional edge in the sense it can be transversed both
1764     // from v1 or v2. "data" however is shared between the two references
1765     // so we still know that the anchor direction is from 1 to 2.
1766     data->from = v1;
1767     data->to = v2;
1768 #ifdef QT_DEBUG
1769     data->name = QString::fromAscii("%1 --to--> %2").arg(v1->toString()).arg(v2->toString());
1770 #endif
1771     // ### bit to track internal anchors, since inside AnchorData methods
1772     // we don't have access to the 'q' pointer.
1773     data->isLayoutAnchor = (data->item == q);
1774
1775     graph[orientation].createEdge(v1, v2, data);
1776 }
1777
1778 QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *firstItem,
1779                                                          Qt::AnchorPoint firstEdge,
1780                                                          QGraphicsLayoutItem *secondItem,
1781                                                          Qt::AnchorPoint secondEdge)
1782 {
1783     // Do not expose internal anchors
1784     if (firstItem == secondItem)
1785         return 0;
1786
1787     const Orientation orientation = edgeOrientation(firstEdge);
1788     AnchorVertex *v1 = internalVertex(firstItem, firstEdge);
1789     AnchorVertex *v2 = internalVertex(secondItem, secondEdge);
1790
1791     QGraphicsAnchor *graphicsAnchor = 0;
1792
1793     AnchorData *data = graph[orientation].edgeData(v1, v2);
1794     if (data) {
1795         // We could use "acquireGraphicsAnchor" here, but to avoid a regression where
1796         // an internal anchor was wrongly exposed, I want to ensure no new
1797         // QGraphicsAnchor instances are created by this call.
1798         // This assumption must hold because anchors are either user-created (and already
1799         // have their public object created), or they are internal (and must not reach
1800         // this point).
1801         Q_ASSERT(data->graphicsAnchor);
1802         graphicsAnchor = data->graphicsAnchor;
1803     }
1804     return graphicsAnchor;
1805 }
1806
1807 /*!
1808  * \internal
1809  *
1810  * Implements the high level "removeAnchor" feature. Called by
1811  * the QAnchorData destructor.
1812  */
1813 void QGraphicsAnchorLayoutPrivate::removeAnchor(AnchorVertex *firstVertex,
1814                                                 AnchorVertex *secondVertex)
1815 {
1816     Q_Q(QGraphicsAnchorLayout);
1817
1818     // Save references to items while it's safe to assume the vertices exist
1819     QGraphicsLayoutItem *firstItem = firstVertex->m_item;
1820     QGraphicsLayoutItem *secondItem = secondVertex->m_item;
1821
1822     // Delete the anchor (may trigger deletion of center vertices)
1823     removeAnchor_helper(firstVertex, secondVertex);
1824
1825     // Ensure no dangling pointer is left behind
1826     firstVertex = secondVertex = 0;
1827
1828     // Checking if the item stays in the layout or not
1829     bool keepFirstItem = false;
1830     bool keepSecondItem = false;
1831
1832     QPair<AnchorVertex *, int> v;
1833     int refcount = -1;
1834
1835     if (firstItem != q) {
1836         for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) {
1837             v = m_vertexList.value(qMakePair(firstItem, static_cast<Qt::AnchorPoint>(i)));
1838             if (v.first) {
1839                 if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter)
1840                     refcount = 2;
1841                 else
1842                     refcount = 1;
1843
1844                 if (v.second > refcount) {
1845                     keepFirstItem = true;
1846                     break;
1847                 }
1848             }
1849         }
1850     } else
1851         keepFirstItem = true;
1852
1853     if (secondItem != q) {
1854         for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) {
1855             v = m_vertexList.value(qMakePair(secondItem, static_cast<Qt::AnchorPoint>(i)));
1856             if (v.first) {
1857                 if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter)
1858                     refcount = 2;
1859                 else
1860                     refcount = 1;
1861
1862                 if (v.second > refcount) {
1863                     keepSecondItem = true;
1864                     break;
1865                 }
1866             }
1867         }
1868     } else
1869         keepSecondItem = true;
1870
1871     if (!keepFirstItem)
1872         q->removeAt(items.indexOf(firstItem));
1873
1874     if (!keepSecondItem)
1875         q->removeAt(items.indexOf(secondItem));
1876
1877     // Removing anchors invalidates the layout
1878     q->invalidate();
1879 }
1880
1881 /*
1882   \internal
1883
1884   Implements the low level "removeAnchor" feature. Called by
1885   private methods.
1886 */
1887 void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2)
1888 {
1889     Q_ASSERT(v1 && v2);
1890
1891     // Remove edge from graph
1892     const Orientation o = edgeOrientation(v1->m_edge);
1893     graph[o].removeEdge(v1, v2);
1894
1895     // Decrease vertices reference count (may trigger a deletion)
1896     removeInternalVertex(v1->m_item, v1->m_edge);
1897     removeInternalVertex(v2->m_item, v2->m_edge);
1898 }
1899
1900 AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item,
1901                                                               Qt::AnchorPoint edge)
1902 {
1903     QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge);
1904     QPair<AnchorVertex *, int> v = m_vertexList.value(pair);
1905
1906     if (!v.first) {
1907         Q_ASSERT(v.second == 0);
1908         v.first = new AnchorVertex(item, edge);
1909     }
1910     v.second++;
1911     m_vertexList.insert(pair, v);
1912     return v.first;
1913 }
1914
1915 /**
1916  * \internal
1917  *
1918  * returns the AnchorVertex that was dereferenced, also when it was removed.
1919  * returns 0 if it did not exist.
1920  */
1921 void QGraphicsAnchorLayoutPrivate::removeInternalVertex(QGraphicsLayoutItem *item,
1922                                                         Qt::AnchorPoint edge)
1923 {
1924     QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge);
1925     QPair<AnchorVertex *, int> v = m_vertexList.value(pair);
1926
1927     if (!v.first) {
1928         qWarning("This item with this edge is not in the graph");
1929         return;
1930     }
1931
1932     v.second--;
1933     if (v.second == 0) {
1934         // Remove reference and delete vertex
1935         m_vertexList.remove(pair);
1936         delete v.first;
1937     } else {
1938         // Update reference count
1939         m_vertexList.insert(pair, v);
1940
1941         if ((v.second == 2) &&
1942             ((edge == Qt::AnchorHorizontalCenter) ||
1943              (edge == Qt::AnchorVerticalCenter))) {
1944             removeCenterAnchors(item, edge, true);
1945         }
1946     }
1947 }
1948
1949 void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge)
1950 {
1951     if (AnchorVertex *v = internalVertex(item, edge)) {
1952         Graph<AnchorVertex, AnchorData> &g = graph[edgeOrientation(edge)];
1953         const QList<AnchorVertex *> allVertices = graph[edgeOrientation(edge)].adjacentVertices(v);
1954         AnchorVertex *v2;
1955         foreach (v2, allVertices) {
1956             g.removeEdge(v, v2);
1957             removeInternalVertex(item, edge);
1958             removeInternalVertex(v2->m_item, v2->m_edge);
1959         }
1960     }
1961 }
1962
1963 void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item)
1964 {
1965     // remove the center anchor first!!
1966     removeCenterAnchors(item, Qt::AnchorHorizontalCenter, false);
1967     removeVertex(item, Qt::AnchorLeft);
1968     removeVertex(item, Qt::AnchorRight);
1969
1970     removeCenterAnchors(item, Qt::AnchorVerticalCenter, false);
1971     removeVertex(item, Qt::AnchorTop);
1972     removeVertex(item, Qt::AnchorBottom);
1973 }
1974
1975 /*!
1976   \internal
1977
1978   Use heuristics to determine the correct orientation of a given anchor.
1979
1980   After API discussions, we decided we would like expressions like
1981   anchor(A, Left, B, Right) to mean the same as anchor(B, Right, A, Left).
1982   The problem with this is that anchors could become ambiguous, for
1983   instance, what does the anchor A, B of size X mean?
1984
1985      "pos(B) = pos(A) + X"  or  "pos(A) = pos(B) + X" ?
1986
1987   To keep the API user friendly and at the same time, keep our algorithm
1988   deterministic, we use an heuristic to determine a direction for each
1989   added anchor and then keep it. The heuristic is based on the fact
1990   that people usually avoid overlapping items, therefore:
1991
1992      "A, RIGHT to B, LEFT" means that B is to the LEFT of A.
1993      "B, LEFT to A, RIGHT" is corrected to the above anchor.
1994
1995   Special correction is also applied when one of the items is the
1996   layout. We handle Layout Left as if it was another items's Right
1997   and Layout Right as another item's Left.
1998 */
1999 void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&firstItem,
2000                                                         Qt::AnchorPoint &firstEdge,
2001                                                         QGraphicsLayoutItem *&secondItem,
2002                                                         Qt::AnchorPoint &secondEdge)
2003 {
2004     Q_Q(QGraphicsAnchorLayout);
2005
2006     if ((firstItem != q) && (secondItem != q)) {
2007         // If connection is between widgets (not the layout itself)
2008         // Ensure that "right-edges" sit to the left of "left-edges".
2009         if (firstEdge < secondEdge) {
2010             qSwap(firstItem, secondItem);
2011             qSwap(firstEdge, secondEdge);
2012         }
2013     } else if (firstItem == q) {
2014         // If connection involves the right or bottom of a layout, ensure
2015         // the layout is the second item.
2016         if ((firstEdge == Qt::AnchorRight) || (firstEdge == Qt::AnchorBottom)) {
2017             qSwap(firstItem, secondItem);
2018             qSwap(firstEdge, secondEdge);
2019         }
2020     } else if ((secondEdge != Qt::AnchorRight) && (secondEdge != Qt::AnchorBottom)) {
2021         // If connection involves the left, center or top of layout, ensure
2022         // the layout is the first item.
2023         qSwap(firstItem, secondItem);
2024         qSwap(firstEdge, secondEdge);
2025     }
2026 }
2027
2028 QLayoutStyleInfo &QGraphicsAnchorLayoutPrivate::styleInfo() const
2029 {
2030     if (styleInfoDirty) {
2031         Q_Q(const QGraphicsAnchorLayout);
2032         //### Fix this if QGV ever gets support for Metal style or different Aqua sizes.
2033         QWidget *wid = 0;
2034
2035         QGraphicsLayoutItem *parent = q->parentLayoutItem();
2036         while (parent && parent->isLayout()) {
2037             parent = parent->parentLayoutItem();
2038         }
2039         QGraphicsWidget *w = 0;
2040         if (parent) {
2041             QGraphicsItem *parentItem = parent->graphicsItem();
2042             if (parentItem && parentItem->isWidget())
2043                 w = static_cast<QGraphicsWidget*>(parentItem);
2044         }
2045
2046         QStyle *style = w ? w->style() : QApplication::style();
2047         cachedStyleInfo = QLayoutStyleInfo(style, wid);
2048         cachedStyleInfo.setDefaultSpacing(Qt::Horizontal, spacings[0]);
2049         cachedStyleInfo.setDefaultSpacing(Qt::Vertical, spacings[1]);
2050
2051         styleInfoDirty = false;
2052     }
2053     return cachedStyleInfo;
2054 }
2055
2056 /*!
2057   \internal
2058
2059   Called on activation. Uses Linear Programming to define minimum, preferred
2060   and maximum sizes for the layout. Also calculates the sizes that each item
2061   should assume when the layout is in one of such situations.
2062 */
2063 void QGraphicsAnchorLayoutPrivate::calculateGraphs()
2064 {
2065     if (!calculateGraphCacheDirty)
2066         return;
2067     calculateGraphs(Horizontal);
2068     calculateGraphs(Vertical);
2069     calculateGraphCacheDirty = false;
2070 }
2071
2072 // ### Maybe getGraphParts could return the variables when traversing, at least
2073 // for trunk...
2074 QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints)
2075 {
2076     QSet<AnchorData *> variableSet;
2077     for (int i = 0; i < constraints.count(); ++i) {
2078         const QSimplexConstraint *c = constraints.at(i);
2079         foreach (QSimplexVariable *var, c->variables.keys()) {
2080             variableSet += static_cast<AnchorData *>(var);
2081         }
2082     }
2083     return variableSet.toList();
2084 }
2085
2086 /*!
2087     \internal
2088
2089     Calculate graphs is the method that puts together all the helper routines
2090     so that the AnchorLayout can calculate the sizes of each item.
2091
2092     In a nutshell it should do:
2093
2094     1) Refresh anchor nominal sizes, that is, the size that each anchor would
2095        have if no other restrictions applied. This is done by quering the
2096        layout style and the sizeHints of the items belonging to the layout.
2097
2098     2) Simplify the graph by grouping together parallel and sequential anchors
2099        into "group anchors". These have equivalent minimum, preferred and maximum
2100        sizeHints as the anchors they replace.
2101
2102     3) Check if we got to a trivial case. In some cases, the whole graph can be
2103        simplified into a single anchor. If so, use this information. If not,
2104        then call the Simplex solver to calculate the anchors sizes.
2105
2106     4) Once the root anchors had its sizes calculated, propagate that to the
2107        anchors they represent.
2108 */
2109 void QGraphicsAnchorLayoutPrivate::calculateGraphs(
2110     QGraphicsAnchorLayoutPrivate::Orientation orientation)
2111 {
2112 #if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT)
2113     lastCalculationUsedSimplex[orientation] = false;
2114 #endif
2115
2116     static bool simplificationEnabled = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty();
2117
2118     // Reset the nominal sizes of each anchor based on the current item sizes
2119     refreshAllSizeHints(orientation);
2120
2121     // Simplify the graph
2122     if (simplificationEnabled && !simplifyGraph(orientation)) {
2123         qWarning("QGraphicsAnchorLayout: anchor setup is not feasible.");
2124         graphHasConflicts[orientation] = true;
2125         return;
2126     }
2127
2128     // Traverse all graph edges and store the possible paths to each vertex
2129     findPaths(orientation);
2130
2131     // From the paths calculated above, extract the constraints that the current
2132     // anchor setup impose, to our Linear Programming problem.
2133     constraintsFromPaths(orientation);
2134
2135     // Split the constraints and anchors into groups that should be fed to the
2136     // simplex solver independently. Currently we find two groups:
2137     //
2138     //  1) The "trunk", that is, the set of anchors (items) that are connected
2139     //     to the two opposite sides of our layout, and thus need to stretch in
2140     //     order to fit in the current layout size.
2141     //
2142     //  2) The floating or semi-floating anchors (items) that are those which
2143     //     are connected to only one (or none) of the layout sides, thus are not
2144     //     influenced by the layout size.
2145     QList<QList<QSimplexConstraint *> > parts = getGraphParts(orientation);
2146
2147     // Now run the simplex solver to calculate Minimum, Preferred and Maximum sizes
2148     // of the "trunk" set of constraints and variables.
2149     // ### does trunk always exist? empty = trunk is the layout left->center->right
2150     QList<QSimplexConstraint *> trunkConstraints = parts.at(0);
2151     QList<AnchorData *> trunkVariables = getVariables(trunkConstraints);
2152
2153     // For minimum and maximum, use the path between the two layout sides as the
2154     // objective function.
2155     AnchorVertex *v = layoutLastVertex[orientation];
2156     GraphPath trunkPath = graphPaths[orientation].value(v);
2157
2158     bool feasible = calculateTrunk(orientation, trunkPath, trunkConstraints, trunkVariables);
2159
2160     // For the other parts that not the trunk, solve only for the preferred size
2161     // that is the size they will remain at, since they are not stretched by the
2162     // layout.
2163
2164     // Skipping the first (trunk)
2165     for (int i = 1; i < parts.count(); ++i) {
2166         if (!feasible)
2167             break;
2168
2169         QList<QSimplexConstraint *> partConstraints = parts.at(i);
2170         QList<AnchorData *> partVariables = getVariables(partConstraints);
2171         Q_ASSERT(!partVariables.isEmpty());
2172         feasible &= calculateNonTrunk(partConstraints, partVariables);
2173     }
2174
2175     // Propagate the new sizes down the simplified graph, ie. tell the
2176     // group anchors to set their children anchors sizes.
2177     updateAnchorSizes(orientation);
2178
2179     graphHasConflicts[orientation] = !feasible;
2180
2181     // Clean up our data structures. They are not needed anymore since
2182     // distribution uses just interpolation.
2183     qDeleteAll(constraints[orientation]);
2184     constraints[orientation].clear();
2185     graphPaths[orientation].clear(); // ###
2186
2187     if (simplificationEnabled)
2188         restoreSimplifiedGraph(orientation);
2189 }
2190
2191 /*!
2192     \internal
2193
2194     Shift all the constraints by a certain amount. This allows us to deal with negative values in
2195     the linear program if they are bounded by a certain limit. Functions should be careful to
2196     call it again with a negative amount, to shift the constraints back.
2197 */
2198 static void shiftConstraints(const QList<QSimplexConstraint *> &constraints, qreal amount)
2199 {
2200     for (int i = 0; i < constraints.count(); ++i) {
2201         QSimplexConstraint *c = constraints.at(i);
2202         qreal multiplier = 0;
2203         foreach (qreal v, c->variables.values()) {
2204             multiplier += v;
2205         }
2206         c->constant += multiplier * amount;
2207     }
2208 }
2209
2210 /*!
2211     \internal
2212
2213     Calculate the sizes for all anchors which are part of the trunk. This works
2214     on top of a (possibly) simplified graph.
2215 */
2216 bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const GraphPath &path,
2217                                                   const QList<QSimplexConstraint *> &constraints,
2218                                                   const QList<AnchorData *> &variables)
2219 {
2220     bool feasible = true;
2221     bool needsSimplex = !constraints.isEmpty();
2222
2223 #if 0
2224     qDebug("Simplex %s for trunk of %s", needsSimplex ? "used" : "NOT used",
2225            orientation == Horizontal ? "Horizontal" : "Vertical");
2226 #endif
2227
2228     if (needsSimplex) {
2229
2230         QList<QSimplexConstraint *> sizeHintConstraints = constraintsFromSizeHints(variables);
2231         QList<QSimplexConstraint *> allConstraints = constraints + sizeHintConstraints;
2232
2233         shiftConstraints(allConstraints, g_offset);
2234
2235         // Solve min and max size hints
2236         qreal min, max;
2237         feasible = solveMinMax(allConstraints, path, &min, &max);
2238
2239         if (feasible) {
2240             solvePreferred(constraints, variables);
2241
2242             // Calculate and set the preferred size for the layout,
2243             // from the edge sizes that were calculated above.
2244             qreal pref(0.0);
2245             foreach (const AnchorData *ad, path.positives) {
2246                 pref += ad->sizeAtPreferred;
2247             }
2248             foreach (const AnchorData *ad, path.negatives) {
2249                 pref -= ad->sizeAtPreferred;
2250             }
2251
2252             sizeHints[orientation][Qt::MinimumSize] = min;
2253             sizeHints[orientation][Qt::PreferredSize] = pref;
2254             sizeHints[orientation][Qt::MaximumSize] = max;
2255         }
2256
2257         qDeleteAll(sizeHintConstraints);
2258         shiftConstraints(constraints, -g_offset);
2259
2260     } else {
2261         // No Simplex is necessary because the path was simplified all the way to a single
2262         // anchor.
2263         Q_ASSERT(path.positives.count() == 1);
2264         Q_ASSERT(path.negatives.count() == 0);
2265
2266         AnchorData *ad = path.positives.toList()[0];
2267         ad->sizeAtMinimum = ad->minSize;
2268         ad->sizeAtPreferred = ad->prefSize;
2269         ad->sizeAtMaximum = ad->maxSize;
2270
2271         sizeHints[orientation][Qt::MinimumSize] = ad->sizeAtMinimum;
2272         sizeHints[orientation][Qt::PreferredSize] = ad->sizeAtPreferred;
2273         sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum;
2274     }
2275
2276 #if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT)
2277     lastCalculationUsedSimplex[orientation] = needsSimplex;
2278 #endif
2279
2280     return feasible;
2281 }
2282
2283 /*!
2284     \internal
2285 */
2286 bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstraint *> &constraints,
2287                                                      const QList<AnchorData *> &variables)
2288 {
2289     shiftConstraints(constraints, g_offset);
2290     bool feasible = solvePreferred(constraints, variables);
2291
2292     if (feasible) {
2293         // Propagate size at preferred to other sizes. Semi-floats always will be
2294         // in their sizeAtPreferred.
2295         for (int j = 0; j < variables.count(); ++j) {
2296             AnchorData *ad = variables.at(j);
2297             Q_ASSERT(ad);
2298             ad->sizeAtMinimum = ad->sizeAtPreferred;
2299             ad->sizeAtMaximum = ad->sizeAtPreferred;
2300         }
2301     }
2302
2303     shiftConstraints(constraints, -g_offset);
2304     return feasible;
2305 }
2306
2307 /*!
2308     \internal
2309
2310     Traverse the graph refreshing the size hints. Edges will query their associated
2311     item or graphicsAnchor for their size hints.
2312 */
2313 void QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation)
2314 {
2315     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
2316     QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections();
2317
2318     QLayoutStyleInfo styleInf = styleInfo();
2319     for (int i = 0; i < vertices.count(); ++i) {
2320         AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);
2321         data->refreshSizeHints(&styleInf);
2322     }
2323 }
2324
2325 /*!
2326   \internal
2327
2328   This method walks the graph using a breadth-first search to find paths
2329   between the root vertex and each vertex on the graph. The edges
2330   directions in each path are considered and they are stored as a
2331   positive edge (left-to-right) or negative edge (right-to-left).
2332
2333   The list of paths is used later to generate a list of constraints.
2334  */
2335 void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation)
2336 {
2337     QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue;
2338
2339     QSet<AnchorData *> visited;
2340
2341     AnchorVertex *root = layoutFirstVertex[orientation];
2342
2343     graphPaths[orientation].insert(root, GraphPath());
2344
2345     foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) {
2346         queue.enqueue(qMakePair(root, v));
2347     }
2348
2349     while(!queue.isEmpty()) {
2350         QPair<AnchorVertex *, AnchorVertex *>  pair = queue.dequeue();
2351         AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second);
2352
2353         if (visited.contains(edge))
2354             continue;
2355
2356         visited.insert(edge);
2357         GraphPath current = graphPaths[orientation].value(pair.first);
2358
2359         if (edge->from == pair.first)
2360             current.positives.insert(edge);
2361         else
2362             current.negatives.insert(edge);
2363
2364         graphPaths[orientation].insert(pair.second, current);
2365
2366         foreach (AnchorVertex *v,
2367                 graph[orientation].adjacentVertices(pair.second)) {
2368             queue.enqueue(qMakePair(pair.second, v));
2369         }
2370     }
2371
2372     // We will walk through every reachable items (non-float) store them in a temporary set.
2373     // We them create a set of all items and subtract the non-floating items from the set in
2374     // order to get the floating items. The floating items is then stored in m_floatItems
2375     identifyFloatItems(visited, orientation);
2376 }
2377
2378 /*!
2379   \internal
2380
2381   Each vertex on the graph that has more than one path to it
2382   represents a contra int to the sizes of the items in these paths.
2383
2384   This method walks the list of paths to each vertex, generate
2385   the constraints and store them in a list so they can be used later
2386   by the Simplex solver.
2387 */
2388 void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation)
2389 {
2390     foreach (AnchorVertex *vertex, graphPaths[orientation].uniqueKeys())
2391     {
2392         int valueCount = graphPaths[orientation].count(vertex);
2393         if (valueCount == 1)
2394             continue;
2395
2396         QList<GraphPath> pathsToVertex = graphPaths[orientation].values(vertex);
2397         for (int i = 1; i < valueCount; ++i) {
2398             constraints[orientation] += \
2399                 pathsToVertex[0].constraint(pathsToVertex.at(i));
2400         }
2401     }
2402 }
2403
2404 /*!
2405   \internal
2406 */
2407 void QGraphicsAnchorLayoutPrivate::updateAnchorSizes(Orientation orientation)
2408 {
2409     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
2410     const QList<QPair<AnchorVertex *, AnchorVertex *> > &vertices = g.connections();
2411
2412     for (int i = 0; i < vertices.count(); ++i) {
2413         AnchorData *ad = g.edgeData(vertices.at(i).first, vertices.at(i).second);
2414         ad->updateChildrenSizes();
2415     }
2416 }
2417
2418 /*!
2419   \internal
2420
2421   Create LP constraints for each anchor based on its minimum and maximum
2422   sizes, as specified in its size hints
2423 */
2424 QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints(
2425     const QList<AnchorData *> &anchors)
2426 {
2427     if (anchors.isEmpty())
2428         return QList<QSimplexConstraint *>();
2429
2430     // Look for the layout edge. That can be either the first half in case the
2431     // layout is split in two, or the whole layout anchor.
2432     Orientation orient = Orientation(anchors.first()->orientation);
2433     AnchorData *layoutEdge = 0;
2434     if (layoutCentralVertex[orient]) {
2435         layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutCentralVertex[orient]);
2436     } else {
2437         layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutLastVertex[orient]);
2438     }
2439
2440     // If maxSize is less then "infinite", that means there are other anchors
2441     // grouped together with this one. We can't ignore its maximum value so we
2442     // set back the variable to NULL to prevent the continue condition from being
2443     // satisfied in the loop below.
2444     const qreal expectedMax = layoutCentralVertex[orient] ? QWIDGETSIZE_MAX / 2 : QWIDGETSIZE_MAX;
2445     qreal actualMax;
2446     if (layoutEdge->from == layoutFirstVertex[orient]) {
2447         actualMax = layoutEdge->maxSize;
2448     } else {
2449         actualMax = -layoutEdge->minSize;
2450     }
2451     if (actualMax != expectedMax) {
2452         layoutEdge = 0;
2453     }
2454
2455     // For each variable, create constraints based on size hints
2456     QList<QSimplexConstraint *> anchorConstraints;
2457     bool unboundedProblem = true;
2458     for (int i = 0; i < anchors.size(); ++i) {
2459         AnchorData *ad = anchors.at(i);
2460
2461         // Anchors that have their size directly linked to another one don't need constraints
2462         // For exammple, the second half of an item has exactly the same size as the first half
2463         // thus constraining the latter is enough.
2464         if (ad->dependency == AnchorData::Slave)
2465             continue;
2466
2467         // To use negative variables inside simplex, we shift them so the minimum negative value is
2468         // mapped to zero before solving. To make sure that it works, we need to guarantee that the
2469         // variables are all inside a certain boundary.
2470         qreal boundedMin = qBound(-g_offset, ad->minSize, g_offset);
2471         qreal boundedMax = qBound(-g_offset, ad->maxSize, g_offset);
2472
2473         if ((boundedMin == boundedMax) || qFuzzyCompare(boundedMin, boundedMax)) {
2474             QSimplexConstraint *c = new QSimplexConstraint;
2475             c->variables.insert(ad, 1.0);
2476             c->constant = boundedMin;
2477             c->ratio = QSimplexConstraint::Equal;
2478             anchorConstraints += c;
2479             unboundedProblem = false;
2480         } else {
2481             QSimplexConstraint *c = new QSimplexConstraint;
2482             c->variables.insert(ad, 1.0);
2483             c->constant = boundedMin;
2484             c->ratio = QSimplexConstraint::MoreOrEqual;
2485             anchorConstraints += c;
2486
2487             // We avoid adding restrictions to the layout internal anchors. That's
2488             // to prevent unnecessary fair distribution from happening due to this
2489             // artificial restriction.
2490             if (ad == layoutEdge)
2491                 continue;
2492
2493             c = new QSimplexConstraint;
2494             c->variables.insert(ad, 1.0);
2495             c->constant = boundedMax;
2496             c->ratio = QSimplexConstraint::LessOrEqual;
2497             anchorConstraints += c;
2498             unboundedProblem = false;
2499         }
2500     }
2501
2502     // If no upper boundary restriction was added, add one to avoid unbounded problem
2503     if (unboundedProblem) {
2504         QSimplexConstraint *c = new QSimplexConstraint;
2505         c->variables.insert(layoutEdge, 1.0);
2506         // The maximum size that the layout can take
2507         c->constant = g_offset;
2508         c->ratio = QSimplexConstraint::LessOrEqual;
2509         anchorConstraints += c;
2510     }
2511
2512     return anchorConstraints;
2513 }
2514
2515 /*!
2516   \internal
2517 */
2518 QList< QList<QSimplexConstraint *> >
2519 QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation)
2520 {
2521     Q_ASSERT(layoutFirstVertex[orientation] && layoutLastVertex[orientation]);
2522
2523     AnchorData *edgeL1 = 0;
2524     AnchorData *edgeL2 = 0;
2525
2526     // The layout may have a single anchor between Left and Right or two half anchors
2527     // passing through the center
2528     if (layoutCentralVertex[orientation]) {
2529         edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutCentralVertex[orientation]);
2530         edgeL2 = graph[orientation].edgeData(layoutCentralVertex[orientation], layoutLastVertex[orientation]);
2531     } else {
2532         edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutLastVertex[orientation]);
2533     }
2534
2535     QLinkedList<QSimplexConstraint *> remainingConstraints;
2536     for (int i = 0; i < constraints[orientation].count(); ++i) {
2537         remainingConstraints += constraints[orientation].at(i);
2538     }
2539     for (int i = 0; i < itemCenterConstraints[orientation].count(); ++i) {
2540         remainingConstraints += itemCenterConstraints[orientation].at(i);
2541     }
2542
2543     QList<QSimplexConstraint *> trunkConstraints;
2544     QSet<QSimplexVariable *> trunkVariables;
2545
2546     trunkVariables += edgeL1;
2547     if (edgeL2)
2548         trunkVariables += edgeL2;
2549
2550     bool dirty;
2551     do {
2552         dirty = false;
2553
2554         QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin();
2555         while (it != remainingConstraints.end()) {
2556             QSimplexConstraint *c = *it;
2557             bool match = false;
2558
2559             // Check if this constraint have some overlap with current
2560             // trunk variables...
2561             foreach (QSimplexVariable *ad, trunkVariables) {
2562                 if (c->variables.contains(ad)) {
2563                     match = true;
2564                     break;
2565                 }
2566             }
2567
2568             // If so, we add it to trunk, and erase it from the
2569             // remaining constraints.
2570             if (match) {
2571                 trunkConstraints += c;
2572                 trunkVariables += QSet<QSimplexVariable *>::fromList(c->variables.keys());
2573                 it = remainingConstraints.erase(it);
2574                 dirty = true;
2575             } else {
2576                 // Note that we don't erase the constraint if it's not
2577                 // a match, since in a next iteration of a do-while we
2578                 // can pass on it again and it will be a match.
2579                 //
2580                 // For example: if trunk share a variable with
2581                 // remainingConstraints[1] and it shares with
2582                 // remainingConstraints[0], we need a second iteration
2583                 // of the do-while loop to match both.
2584                 ++it;
2585             }
2586         }
2587     } while (dirty);
2588
2589     QList< QList<QSimplexConstraint *> > result;
2590     result += trunkConstraints;
2591
2592     if (!remainingConstraints.isEmpty()) {
2593         QList<QSimplexConstraint *> nonTrunkConstraints;
2594         QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin();
2595         while (it != remainingConstraints.end()) {
2596             nonTrunkConstraints += *it;
2597             ++it;
2598         }
2599         result += nonTrunkConstraints;
2600     }
2601
2602     return result;
2603 }
2604
2605 /*!
2606  \internal
2607
2608   Use all visited Anchors on findPaths() so we can identify non-float Items.
2609 */
2610 void QGraphicsAnchorLayoutPrivate::identifyFloatItems(const QSet<AnchorData *> &visited, Orientation orientation)
2611 {
2612     QSet<QGraphicsLayoutItem *> nonFloating;
2613
2614     foreach (const AnchorData *ad, visited)
2615         identifyNonFloatItems_helper(ad, &nonFloating);
2616
2617     QSet<QGraphicsLayoutItem *> allItems;
2618     foreach (QGraphicsLayoutItem *item, items)
2619         allItems.insert(item);
2620     m_floatItems[orientation] = allItems - nonFloating;
2621 }
2622
2623
2624 /*!
2625  \internal
2626
2627   Given an anchor, if it is an internal anchor and Normal we must mark it's item as non-float.
2628   If the anchor is Sequential or Parallel, we must iterate on its children recursively until we reach
2629   internal anchors (items).
2630 */
2631 void QGraphicsAnchorLayoutPrivate::identifyNonFloatItems_helper(const AnchorData *ad, QSet<QGraphicsLayoutItem *> *nonFloatingItemsIdentifiedSoFar)
2632 {
2633     Q_Q(QGraphicsAnchorLayout);
2634
2635     switch(ad->type) {
2636     case AnchorData::Normal:
2637         if (ad->item && ad->item != q)
2638             nonFloatingItemsIdentifiedSoFar->insert(ad->item);
2639         break;
2640     case AnchorData::Sequential:
2641         foreach (const AnchorData *d, static_cast<const SequentialAnchorData *>(ad)->m_edges)
2642             identifyNonFloatItems_helper(d, nonFloatingItemsIdentifiedSoFar);
2643         break;
2644     case AnchorData::Parallel:
2645         identifyNonFloatItems_helper(static_cast<const ParallelAnchorData *>(ad)->firstEdge, nonFloatingItemsIdentifiedSoFar);
2646         identifyNonFloatItems_helper(static_cast<const ParallelAnchorData *>(ad)->secondEdge, nonFloatingItemsIdentifiedSoFar);
2647         break;
2648     }
2649 }
2650
2651 /*!
2652   \internal
2653
2654   Use the current vertices distance to calculate and set the geometry of
2655   each item.
2656 */
2657 void QGraphicsAnchorLayoutPrivate::setItemsGeometries(const QRectF &geom)
2658 {
2659     Q_Q(QGraphicsAnchorLayout);
2660     AnchorVertex *firstH, *secondH, *firstV, *secondV;
2661
2662     qreal top;
2663     qreal left;
2664     qreal right;
2665
2666     q->getContentsMargins(&left, &top, &right, 0);
2667     const Qt::LayoutDirection visualDir = visualDirection();
2668     if (visualDir == Qt::RightToLeft)
2669         qSwap(left, right);
2670
2671     left += geom.left();
2672     top += geom.top();
2673     right = geom.right() - right;
2674
2675     foreach (QGraphicsLayoutItem *item, items) {
2676         QRectF newGeom;
2677         QSizeF itemPreferredSize = item->effectiveSizeHint(Qt::PreferredSize);
2678         if (m_floatItems[Horizontal].contains(item)) {
2679             newGeom.setLeft(0);
2680             newGeom.setRight(itemPreferredSize.width());
2681         } else {
2682             firstH = internalVertex(item, Qt::AnchorLeft);
2683             secondH = internalVertex(item, Qt::AnchorRight);
2684
2685             if (visualDir == Qt::LeftToRight) {
2686                 newGeom.setLeft(left + firstH->distance);
2687                 newGeom.setRight(left + secondH->distance);
2688             } else {
2689                 newGeom.setLeft(right - secondH->distance);
2690                 newGeom.setRight(right - firstH->distance);
2691             }
2692         }
2693
2694         if (m_floatItems[Vertical].contains(item)) {
2695             newGeom.setTop(0);
2696             newGeom.setBottom(itemPreferredSize.height());
2697         } else {
2698             firstV = internalVertex(item, Qt::AnchorTop);
2699             secondV = internalVertex(item, Qt::AnchorBottom);
2700
2701             newGeom.setTop(top + firstV->distance);
2702             newGeom.setBottom(top + secondV->distance);
2703         }
2704
2705         item->setGeometry(newGeom);
2706     }
2707 }
2708
2709 /*!
2710   \internal
2711
2712   Calculate the position of each vertex based on the paths to each of
2713   them as well as the current edges sizes.
2714 */
2715 void QGraphicsAnchorLayoutPrivate::calculateVertexPositions(
2716     QGraphicsAnchorLayoutPrivate::Orientation orientation)
2717 {
2718     QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue;
2719     QSet<AnchorVertex *> visited;
2720
2721     // Get root vertex
2722     AnchorVertex *root = layoutFirstVertex[orientation];
2723
2724     root->distance = 0;
2725     visited.insert(root);
2726
2727     // Add initial edges to the queue
2728     foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) {
2729         queue.enqueue(qMakePair(root, v));
2730     }
2731
2732     // Do initial calculation required by "interpolateEdge()"
2733     setupEdgesInterpolation(orientation);
2734
2735     // Traverse the graph and calculate vertex positions
2736     while (!queue.isEmpty()) {
2737         QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue();
2738         AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second);
2739
2740         if (visited.contains(pair.second))
2741             continue;
2742
2743         visited.insert(pair.second);
2744         interpolateEdge(pair.first, edge);
2745
2746         QList<AnchorVertex *> adjacents = graph[orientation].adjacentVertices(pair.second);
2747         for (int i = 0; i < adjacents.count(); ++i) {
2748             if (!visited.contains(adjacents.at(i)))
2749                 queue.enqueue(qMakePair(pair.second, adjacents.at(i)));
2750         }
2751     }
2752 }
2753
2754 /*!
2755   \internal
2756
2757   Calculate interpolation parameters based on current Layout Size.
2758   Must be called once before calling "interpolateEdgeSize()" for
2759   the edges.
2760 */
2761 void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation(
2762     Orientation orientation)
2763 {
2764     Q_Q(QGraphicsAnchorLayout);
2765
2766     qreal current;
2767     current = (orientation == Horizontal) ? q->contentsRect().width() : q->contentsRect().height();
2768
2769     QPair<Interval, qreal> result;
2770     result = getFactor(current,
2771                        sizeHints[orientation][Qt::MinimumSize],
2772                        sizeHints[orientation][Qt::PreferredSize],
2773                        sizeHints[orientation][Qt::PreferredSize],
2774                        sizeHints[orientation][Qt::PreferredSize],
2775                        sizeHints[orientation][Qt::MaximumSize]);
2776
2777     interpolationInterval[orientation] = result.first;
2778     interpolationProgress[orientation] = result.second;
2779 }
2780
2781 /*!
2782     \internal
2783
2784     Calculate the current Edge size based on the current Layout size and the
2785     size the edge is supposed to have when the layout is at its:
2786
2787     - minimum size,
2788     - preferred size,
2789     - maximum size.
2790
2791     These three key values are calculated in advance using linear
2792     programming (more expensive) or the simplification algorithm, then
2793     subsequential resizes of the parent layout require a simple
2794     interpolation.
2795 */
2796 void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorData *edge)
2797 {
2798     const Orientation orientation = Orientation(edge->orientation);
2799     const QPair<Interval, qreal> factor(interpolationInterval[orientation],
2800                                         interpolationProgress[orientation]);
2801
2802     qreal edgeDistance = interpolate(factor, edge->sizeAtMinimum, edge->sizeAtPreferred,
2803                                      edge->sizeAtPreferred, edge->sizeAtPreferred,
2804                                      edge->sizeAtMaximum);
2805
2806     Q_ASSERT(edge->from == base || edge->to == base);
2807
2808     // Calculate the distance for the vertex opposite to the base
2809     if (edge->from == base) {
2810         edge->to->distance = base->distance + edgeDistance;
2811     } else {
2812         edge->from->distance = base->distance - edgeDistance;
2813     }
2814 }
2815
2816 bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> &constraints,
2817                                                GraphPath path, qreal *min, qreal *max)
2818 {
2819     QSimplex simplex;
2820     bool feasible = simplex.setConstraints(constraints);
2821     if (feasible) {
2822         // Obtain the objective constraint
2823         QSimplexConstraint objective;
2824         QSet<AnchorData *>::const_iterator iter;
2825         for (iter = path.positives.constBegin(); iter != path.positives.constEnd(); ++iter)
2826             objective.variables.insert(*iter, 1.0);
2827
2828         for (iter = path.negatives.constBegin(); iter != path.negatives.constEnd(); ++iter)
2829             objective.variables.insert(*iter, -1.0);
2830
2831         const qreal objectiveOffset = (path.positives.count() - path.negatives.count()) * g_offset;
2832         simplex.setObjective(&objective);
2833
2834         // Calculate minimum values
2835         *min = simplex.solveMin() - objectiveOffset;
2836
2837         // Save sizeAtMinimum results
2838         QList<AnchorData *> variables = getVariables(constraints);
2839         for (int i = 0; i < variables.size(); ++i) {
2840             AnchorData *ad = static_cast<AnchorData *>(variables.at(i));
2841             ad->sizeAtMinimum = ad->result - g_offset;
2842         }
2843
2844         // Calculate maximum values
2845         *max = simplex.solveMax() - objectiveOffset;
2846
2847         // Save sizeAtMaximum results
2848         for (int i = 0; i < variables.size(); ++i) {
2849             AnchorData *ad = static_cast<AnchorData *>(variables.at(i));
2850             ad->sizeAtMaximum = ad->result - g_offset;
2851         }
2852     }
2853     return feasible;
2854 }
2855
2856 enum slackType { Grower = -1, Shrinker = 1 };
2857 static QPair<QSimplexVariable *, QSimplexConstraint *> createSlack(QSimplexConstraint *sizeConstraint,
2858                                                                    qreal interval, slackType type)
2859 {
2860     QSimplexVariable *slack = new QSimplexVariable;
2861     sizeConstraint->variables.insert(slack, type);
2862
2863     QSimplexConstraint *limit = new QSimplexConstraint;
2864     limit->variables.insert(slack, 1.0);
2865     limit->ratio = QSimplexConstraint::LessOrEqual;
2866     limit->constant = interval;
2867
2868     return qMakePair(slack, limit);
2869 }
2870
2871 bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint *> &constraints,
2872                                                   const QList<AnchorData *> &variables)
2873 {
2874     QList<QSimplexConstraint *> preferredConstraints;
2875     QList<QSimplexVariable *> preferredVariables;
2876     QSimplexConstraint objective;
2877
2878     // Fill the objective coefficients for this variable. In the
2879     // end the objective function will be
2880     //
2881     //     z = n * (A_shrinker_hard + A_grower_hard + B_shrinker_hard + B_grower_hard + ...) +
2882     //             (A_shrinker_soft + A_grower_soft + B_shrinker_soft + B_grower_soft + ...)
2883     //
2884     // where n is the number of variables that have
2885     // slacks. Note that here we use the number of variables
2886     // as coefficient, this is to mark the "shrinker slack
2887     // variable" less likely to get value than the "grower
2888     // slack variable".
2889
2890     // This will fill the values for the structural constraints
2891     // and we now fill the values for the slack constraints (one per variable),
2892     // which have this form (the constant A_pref was set when creating the slacks):
2893     //
2894     //      A + A_shrinker_hard + A_shrinker_soft - A_grower_hard - A_grower_soft = A_pref
2895     //
2896     for (int i = 0; i < variables.size(); ++i) {
2897         AnchorData *ad = variables.at(i);
2898
2899         // The layout original structure anchors are not relevant in preferred size calculation
2900         if (ad->isLayoutAnchor)
2901             continue;
2902
2903         // By default, all variables are equal to their preferred size. If they have room to
2904         // grow or shrink, such flexibility will be added by the additional variables below.
2905         QSimplexConstraint *sizeConstraint = new QSimplexConstraint;
2906         preferredConstraints += sizeConstraint;
2907         sizeConstraint->variables.insert(ad, 1.0);
2908         sizeConstraint->constant = ad->prefSize + g_offset;
2909
2910         // Can easily shrink
2911         QPair<QSimplexVariable *, QSimplexConstraint *> slack;
2912         const qreal softShrinkInterval = ad->prefSize - ad->minPrefSize;
2913         if (softShrinkInterval) {
2914             slack = createSlack(sizeConstraint, softShrinkInterval, Shrinker);
2915             preferredVariables += slack.first;
2916             preferredConstraints += slack.second;
2917
2918             // Add to objective with ratio == 1 (soft)
2919             objective.variables.insert(slack.first, 1.0);
2920         }
2921
2922         // Can easily grow
2923         const qreal softGrowInterval = ad->maxPrefSize - ad->prefSize;
2924         if (softGrowInterval) {
2925             slack = createSlack(sizeConstraint, softGrowInterval, Grower);
2926             preferredVariables += slack.first;
2927             preferredConstraints += slack.second;
2928
2929             // Add to objective with ratio == 1 (soft)
2930             objective.variables.insert(slack.first, 1.0);
2931         }
2932
2933         // Can shrink if really necessary
2934         const qreal hardShrinkInterval = ad->minPrefSize - ad->minSize;
2935         if (hardShrinkInterval) {
2936             slack = createSlack(sizeConstraint, hardShrinkInterval, Shrinker);
2937             preferredVariables += slack.first;
2938             preferredConstraints += slack.second;
2939
2940             // Add to objective with ratio == N (hard)
2941             objective.variables.insert(slack.first, variables.size());
2942         }
2943
2944         // Can grow if really necessary
2945         const qreal hardGrowInterval = ad->maxSize - ad->maxPrefSize;
2946         if (hardGrowInterval) {
2947             slack = createSlack(sizeConstraint, hardGrowInterval, Grower);
2948             preferredVariables += slack.first;
2949             preferredConstraints += slack.second;
2950
2951             // Add to objective with ratio == N (hard)
2952             objective.variables.insert(slack.first, variables.size());
2953         }
2954     }
2955
2956     QSimplex *simplex = new QSimplex;
2957     bool feasible = simplex->setConstraints(constraints + preferredConstraints);
2958     if (feasible) {
2959         simplex->setObjective(&objective);
2960
2961         // Calculate minimum values
2962         simplex->solveMin();
2963
2964         // Save sizeAtPreferred results
2965         for (int i = 0; i < variables.size(); ++i) {
2966             AnchorData *ad = variables.at(i);
2967             ad->sizeAtPreferred = ad->result - g_offset;
2968         }
2969
2970         // Make sure we delete the simplex solver -before- we delete the
2971         // constraints used by it.
2972         delete simplex;
2973     }
2974     // Delete constraints and variables we created.
2975     qDeleteAll(preferredConstraints);
2976     qDeleteAll(preferredVariables);
2977
2978     return feasible;
2979 }
2980
2981 /*!
2982     \internal
2983     Returns true if there are no arrangement that satisfies all constraints.
2984     Otherwise returns false.
2985
2986     \sa addAnchor()
2987 */
2988 bool QGraphicsAnchorLayoutPrivate::hasConflicts() const
2989 {
2990     QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate*>(this);
2991     that->calculateGraphs();
2992
2993     bool floatConflict = !m_floatItems[0].isEmpty() || !m_floatItems[1].isEmpty();
2994
2995     return graphHasConflicts[0] || graphHasConflicts[1] || floatConflict;
2996 }
2997
2998 #ifdef QT_DEBUG
2999 void QGraphicsAnchorLayoutPrivate::dumpGraph(const QString &name)
3000 {
3001     QFile file(QString::fromAscii("anchorlayout.%1.dot").arg(name));
3002     if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
3003         qWarning("Could not write to %s", file.fileName().toLocal8Bit().constData());
3004
3005     QString str = QString::fromAscii("digraph anchorlayout {\nnode [shape=\"rect\"]\n%1}");
3006     QString dotContents = graph[0].serializeToDot();
3007     dotContents += graph[1].serializeToDot();
3008     file.write(str.arg(dotContents).toLocal8Bit());
3009
3010     file.close();
3011 }
3012 #endif
3013
3014 QT_END_NAMESPACE
3015 #endif //QT_NO_GRAPHICSVIEW