Don't loose precision by converting the sizes (qreals) to ints.
[qt:qt-palm-pre.git] / src / gui / graphicsview / qgraphicsanchorlayout_p.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 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 <QtCore/qlinkedlist.h>
44 #include <QtCore/qstack.h>
45
46 #ifdef QT_DEBUG
47 #include <QtCore/qfile.h>
48 #endif
49
50 #include "qgraphicsanchorlayout_p.h"
51
52 QT_BEGIN_NAMESPACE
53
54
55 QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version)
56     : QObjectPrivate(version), layoutPrivate(0), data(0)
57 {
58 }
59
60 QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate()
61 {
62     layoutPrivate->removeAnchor(data->from, data->to);
63 }
64
65 void QGraphicsAnchorPrivate::setSpacing(qreal value)
66 {
67     if (data) {
68         layoutPrivate->setAnchorSize(data, &value);
69     } else {
70         qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist.");
71     }
72 }
73
74 void QGraphicsAnchorPrivate::unsetSpacing()
75 {
76     if (data) {
77         layoutPrivate->setAnchorSize(data, 0);
78     } else {
79         qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist.");
80     }
81 }
82
83 qreal QGraphicsAnchorPrivate::spacing() const
84 {
85     qreal size = 0;
86     if (data) {
87         layoutPrivate->anchorSize(data, 0, &size, 0);
88     } else {
89         qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist.");
90     }
91     return size;
92 }
93
94
95 void AnchorData::refreshSizeHints(qreal effectiveSpacing)
96 {
97     if (!isLayoutAnchor && from->m_item == to->m_item) {
98         QGraphicsLayoutItem *item = from->m_item;
99
100         const QGraphicsAnchorLayoutPrivate::Orientation orient = QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge);
101         const Qt::AnchorPoint centerEdge = QGraphicsAnchorLayoutPrivate::pickEdge(Qt::AnchorHorizontalCenter, orient);
102
103         QSizePolicy::Policy policy;
104         qreal minSizeHint, prefSizeHint, maxSizeHint;
105         if (orient == QGraphicsAnchorLayoutPrivate::Horizontal) {
106             policy = item->sizePolicy().horizontalPolicy();
107             minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).width();
108             prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).width();
109             maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).width();
110         } else {
111             policy = item->sizePolicy().verticalPolicy();
112             minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).height();
113             prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).height();
114             maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).height();
115         }
116         // minSize, prefSize and maxSize are initialized
117         // with item's preferred Size: this is QSizePolicy::Fixed.
118         //
119         // Then we check each flag to find the resultant QSizePolicy,
120         // according to the following table:
121         //
122         //      constant               value
123         // QSizePolicy::Fixed            0
124         // QSizePolicy::Minimum       GrowFlag
125         // QSizePolicy::Maximum       ShrinkFlag
126         // QSizePolicy::Preferred     GrowFlag | ShrinkFlag
127         // QSizePolicy::Ignored       GrowFlag | ShrinkFlag | IgnoreFlag
128         prefSize = prefSizeHint;
129         minSize = prefSize;
130         maxSize = prefSize;
131
132         if (policy & QSizePolicy::GrowFlag)
133             maxSize = maxSizeHint;
134
135         if (policy & QSizePolicy::ShrinkFlag)
136             minSize = minSizeHint;
137
138         if (policy & QSizePolicy::IgnoreFlag)
139             prefSize = minSize;
140
141         bool hasCenter = (from->m_edge == centerEdge || to->m_edge == centerEdge);
142
143         if (hasCenter) {
144             minSize /= 2;
145             prefSize /= 2;
146             maxSize /= 2;
147         }
148
149         // Set the anchor effective sizes to preferred.
150         //
151         // Note: The idea here is that all items should remain at their
152         // preferred size unless where that's impossible.  In cases where
153         // the item is subject to restrictions (anchored to the layout
154         // edges, for instance), the simplex solver will be run to
155         // recalculate and override the values we set here.
156         sizeAtMinimum = prefSize;
157         sizeAtPreferred = prefSize;
158         sizeAtMaximum = prefSize;
159
160     } else if (!hasSize) {
161         // Anchor has no size defined, use given default information
162         minSize = effectiveSpacing;
163         prefSize = effectiveSpacing;
164         maxSize = effectiveSpacing;
165
166         sizeAtMinimum = prefSize;
167         sizeAtPreferred = prefSize;
168         sizeAtMaximum = prefSize;
169     }
170 }
171
172 void ParallelAnchorData::updateChildrenSizes()
173 {
174     firstEdge->sizeAtMinimum = secondEdge->sizeAtMinimum = sizeAtMinimum;
175     firstEdge->sizeAtPreferred = secondEdge->sizeAtPreferred = sizeAtPreferred;
176     firstEdge->sizeAtMaximum = secondEdge->sizeAtMaximum = sizeAtMaximum;
177
178     firstEdge->updateChildrenSizes();
179     secondEdge->updateChildrenSizes();
180 }
181
182 void ParallelAnchorData::refreshSizeHints(qreal effectiveSpacing)
183 {
184     // First refresh children information
185     firstEdge->refreshSizeHints(effectiveSpacing);
186     secondEdge->refreshSizeHints(effectiveSpacing);
187
188     // ### should we warn if the parallel connection is invalid?
189     // e.g. 1-2-3 with 10-20-30, the minimum of the latter is
190     // bigger than the maximum of the former.
191
192     minSize = qMax(firstEdge->minSize, secondEdge->minSize);
193     maxSize = qMin(firstEdge->maxSize, secondEdge->maxSize);
194
195     prefSize = qMax(firstEdge->prefSize, secondEdge->prefSize);
196     prefSize = qMin(prefSize, maxSize);
197
198     // See comment in AnchorData::refreshSizeHints() about sizeAt* values
199     sizeAtMinimum = prefSize;
200     sizeAtPreferred = prefSize;
201     sizeAtMaximum = prefSize;
202 }
203
204 /*!
205     \internal
206     returns the factor in the interval [-1, 1].
207     -1 is at Minimum
208      0 is at Preferred
209      1 is at Maximum
210 */
211 static qreal getFactor(qreal value, qreal min, qreal pref, qreal max)
212 {
213     // ### Maybe remove some of the assertions? (since outside is asserting us)
214     Q_ASSERT(value > min || qFuzzyCompare(value, min));
215     Q_ASSERT(value < max || qFuzzyCompare(value, max));
216
217     if (qFuzzyCompare(value, min)) {
218         return -1.0;
219     } else if (qFuzzyCompare(value, pref)) {
220         return 0.0;
221     } else if (qFuzzyCompare(value, max)) {
222         return 1.0;
223     } else if (value < pref) {
224         // Since value < pref and value != pref and min <= value,
225         // we can assert that min < pref.
226         Q_ASSERT(min < pref);
227         return (value - min) / (pref - min) - 1;
228     } else {
229         // Since value > pref and value != pref and max >= value,
230         // we can assert that max > pref.
231         Q_ASSERT(max > pref);
232         return (value - pref) / (max - pref);
233     }
234 }
235
236 void SequentialAnchorData::updateChildrenSizes()
237 {
238     // ### REMOVE ME
239     // ### check whether we are guarantee to get those or we need to warn stuff at this
240     // point.
241     Q_ASSERT(sizeAtMinimum > minSize || qFuzzyCompare(sizeAtMinimum, minSize));
242     Q_ASSERT(sizeAtMinimum < maxSize || qFuzzyCompare(sizeAtMinimum, maxSize));
243     Q_ASSERT(sizeAtPreferred > minSize || qFuzzyCompare(sizeAtPreferred, minSize));
244     Q_ASSERT(sizeAtPreferred < maxSize || qFuzzyCompare(sizeAtPreferred, maxSize));
245     Q_ASSERT(sizeAtMaximum > minSize || qFuzzyCompare(sizeAtMaximum, minSize));
246     Q_ASSERT(sizeAtMaximum < maxSize || qFuzzyCompare(sizeAtMaximum, maxSize));
247
248     // Band here refers if the value is in the Minimum To Preferred
249     // band (the lower band) or the Preferred To Maximum (the upper band).
250
251     qreal minFactor = getFactor(sizeAtMinimum, minSize, prefSize, maxSize);
252     qreal prefFactor = getFactor(sizeAtPreferred, minSize, prefSize, maxSize);
253     qreal maxFactor = getFactor(sizeAtMaximum, minSize, prefSize, maxSize);
254
255     for (int i = 0; i < m_edges.count(); ++i) {
256         AnchorData *e = m_edges.at(i);
257
258         qreal bandSize = minFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize;
259         e->sizeAtMinimum = e->prefSize + bandSize * minFactor;
260
261         bandSize = prefFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize;
262         e->sizeAtPreferred = e->prefSize + bandSize * prefFactor;
263
264         bandSize = maxFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize;
265         e->sizeAtMaximum = e->prefSize + bandSize * maxFactor;
266
267         e->updateChildrenSizes();
268     }
269 }
270
271 void SequentialAnchorData::refreshSizeHints(qreal effectiveSpacing)
272 {
273     minSize = 0;
274     prefSize = 0;
275     maxSize = 0;
276
277     for (int i = 0; i < m_edges.count(); ++i) {
278         AnchorData *edge = m_edges.at(i);
279
280         // First refresh children information
281         edge->refreshSizeHints(effectiveSpacing);
282
283         minSize += edge->minSize;
284         prefSize += edge->prefSize;
285         maxSize += edge->maxSize;
286     }
287
288     // See comment in AnchorData::refreshSizeHints() about sizeAt* values
289     sizeAtMinimum = prefSize;
290     sizeAtPreferred = prefSize;
291     sizeAtMaximum = prefSize;
292 }
293
294 #ifdef QT_DEBUG
295 void AnchorData::dump(int indent) {
296     if (type == Parallel) {
297         qDebug("%*s type: parallel:", indent, "");
298         ParallelAnchorData *p = static_cast<ParallelAnchorData *>(this);
299         p->firstEdge->dump(indent+2);
300         p->secondEdge->dump(indent+2);
301     } else if (type == Sequential) {
302         SequentialAnchorData *s = static_cast<SequentialAnchorData *>(this);
303         int kids = s->m_edges.count();
304         qDebug("%*s type: sequential(%d):", indent, "", kids);
305         for (int i = 0; i < kids; ++i) {
306             s->m_edges.at(i)->dump(indent+2);
307         }
308     } else {
309         qDebug("%*s type: Normal:", indent, "");
310     }
311 }
312
313 #endif
314
315 QSimplexConstraint *GraphPath::constraint(const GraphPath &path) const
316 {
317     // Calculate
318     QSet<AnchorData *> cPositives;
319     QSet<AnchorData *> cNegatives;
320     QSet<AnchorData *> intersection;
321
322     cPositives = positives + path.negatives;
323     cNegatives = negatives + path.positives;
324
325     intersection = cPositives & cNegatives;
326
327     cPositives -= intersection;
328     cNegatives -= intersection;
329
330     // Fill
331     QSimplexConstraint *c = new QSimplexConstraint;
332     QSet<AnchorData *>::iterator i;
333     for (i = cPositives.begin(); i != cPositives.end(); ++i)
334         c->variables.insert(*i, 1.0);
335
336     for (i = cNegatives.begin(); i != cNegatives.end(); ++i)
337         c->variables.insert(*i, -1.0);
338
339     return c;
340 }
341
342 #ifdef QT_DEBUG
343 QString GraphPath::toString() const
344 {
345     QString string(QLatin1String("Path: "));
346     foreach(AnchorData *edge, positives)
347         string += QString::fromAscii(" (+++) %1").arg(edge->toString());
348
349     foreach(AnchorData *edge, negatives)
350         string += QString::fromAscii(" (---) %1").arg(edge->toString());
351
352     return string;
353 }
354 #endif
355
356 QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate()
357     : calculateGraphCacheDirty(1)
358 {
359     for (int i = 0; i < NOrientations; ++i) {
360         spacings[i] = -1;
361         graphSimplified[i] = false;
362         graphHasConflicts[i] = false;
363     }
364 }
365
366 Qt::AnchorPoint QGraphicsAnchorLayoutPrivate::oppositeEdge(Qt::AnchorPoint edge)
367 {
368     switch (edge) {
369     case Qt::AnchorLeft:
370         edge = Qt::AnchorRight;
371         break;
372     case Qt::AnchorRight:
373         edge = Qt::AnchorLeft;
374         break;
375     case Qt::AnchorTop:
376         edge = Qt::AnchorBottom;
377         break;
378     case Qt::AnchorBottom:
379         edge = Qt::AnchorTop;
380         break;
381     default:
382         break;
383     }
384     return edge;
385 }
386
387
388 /*!
389  * \internal
390  *
391  * helper function in order to avoid overflowing anchor sizes
392  * the returned size will never be larger than FLT_MAX
393  *
394  */
395 inline static qreal checkAdd(qreal a, qreal b)
396 {
397     if (FLT_MAX - b  < a)
398         return FLT_MAX;
399     return a + b;
400 }
401
402 /*!
403  * \internal
404  *
405  * Takes the sequence of vertices described by (\a before, \a vertices, \a after) and replaces
406  * all anchors connected to the vertices in \a vertices with one simplified anchor between
407  * \a before and \a after. The simplified anchor will be a placeholder for all the previous
408  * anchors between \a before and \a after, and can be restored back to the anchors it is a
409  * placeholder for.
410  */
411 static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph,
412                                     AnchorVertex *before,
413                                     const QVector<AnchorVertex*> &vertices,
414                                     AnchorVertex *after)
415 {
416     int i;
417 #if defined(QT_DEBUG) && 0
418     QString strVertices;
419     for (i = 0; i < vertices.count(); ++i)
420         strVertices += QString::fromAscii("%1 - ").arg(vertices.at(i)->toString());
421     QString strPath = QString::fromAscii("%1 - %2%3").arg(before->toString(), strVertices, after->toString());
422     qDebug("simplifying [%s] to [%s - %s]", qPrintable(strPath), qPrintable(before->toString()), qPrintable(after->toString()));
423 #endif
424
425     qreal min = 0;
426     qreal pref = 0;
427     qreal max = 0;
428
429     SequentialAnchorData *sequence = new SequentialAnchorData;
430     AnchorVertex *prev = before;
431     AnchorData *data;
432     for (i = 0; i <= vertices.count(); ++i) {
433         AnchorVertex *next = (i < vertices.count()) ? vertices.at(i) : after;
434         data = graph->takeEdge(prev, next);
435         min += data->minSize;
436         pref += data->prefSize;
437         max = checkAdd(max, data->maxSize);
438         sequence->m_edges.append(data);
439         prev = next;
440     }
441
442     // insert new
443     sequence->minSize = min;
444     sequence->prefSize = pref;
445     sequence->maxSize = max;
446
447     // Unless these values are overhidden by the simplex solver later-on,
448     // anchors will keep their own preferred size.
449     sequence->sizeAtMinimum = pref;
450     sequence->sizeAtPreferred = pref;
451     sequence->sizeAtMaximum = pref;
452
453     sequence->setVertices(vertices);
454
455     sequence->from = before;
456     sequence->to = after;
457
458     // data here is the last edge in the sequence
459     // ### this seems to be here for supporting reverse order sequences,
460     // but doesnt seem to be used right now
461     if (data->from != vertices.last())
462         qSwap(sequence->from, sequence->to);
463
464     // Note that since layout 'edges' can't be simplified away from
465     // the graph, it's safe to assume that if there's a layout
466     // 'edge', it'll be in the boundaries of the sequence.
467     sequence->isLayoutAnchor = (sequence->m_edges.first()->isLayoutAnchor
468                                 || sequence->m_edges.last()->isLayoutAnchor);
469
470     AnchorData *newAnchor = sequence;
471     if (AnchorData *oldAnchor = graph->takeEdge(before, after)) {
472         newAnchor = new ParallelAnchorData(oldAnchor, sequence);
473
474         newAnchor->isLayoutAnchor = (oldAnchor->isLayoutAnchor
475                                      || sequence->isLayoutAnchor);
476
477         min = qMax(oldAnchor->minSize, sequence->minSize);
478         max = qMin(oldAnchor->maxSize, sequence->maxSize);
479
480         pref = qMax(oldAnchor->prefSize, sequence->prefSize);
481         pref = qMin(pref, max);
482
483         newAnchor->minSize = min;
484         newAnchor->prefSize = pref;
485         newAnchor->maxSize = max;
486
487         // Same as above, by default, keep preferred size.
488         newAnchor->sizeAtMinimum = pref;
489         newAnchor->sizeAtPreferred = pref;
490         newAnchor->sizeAtMaximum = pref;
491     }
492     graph->createEdge(before, after, newAnchor);
493
494     // True if we created a parallel anchor
495     return newAnchor != sequence;
496 }
497
498 /*!
499    \internal
500
501    The purpose of this function is to simplify the graph.
502    Simplification serves two purposes:
503    1. Reduce the number of edges in the graph, (thus the number of variables to the equation
504       solver is reduced, and the solver performs better).
505    2. Be able to do distribution of sequences of edges more intelligently (esp. with sequential
506       anchors)
507
508    It is essential that it must be possible to restore simplified anchors back to their "original"
509    form. This is done by restoreSimplifiedAnchor().
510
511    There are two types of simplification that can be done:
512    1. Sequential simplification
513       Sequential simplification means that all sequences of anchors will be merged into one single
514       anchor. Only anhcors that points in the same direction will be merged.
515    2. Parallel simplification
516       If a simplified sequential anchor is about to be inserted between two vertices in the graph
517       and there already exist an anchor between those two vertices, a parallel anchor will be
518       created that serves as a placeholder for the sequential anchor and the anchor that was
519       already between the two vertices.
520
521    The process of simplification can be described as:
522
523    1. Simplify all sequences of anchors into one anchor.
524       If no further simplification was done, go to (3)
525       - If there already exist an anchor where the sequential anchor is supposed to be inserted,
526         take that anchor out of the graph
527       - Then create a parallel anchor that holds the sequential anchor and the anchor just taken
528         out of the graph.
529    2. Go to (1)
530    3. Done
531
532
533    * Gathering sequential anchors *
534    The algorithm walks the graph in depth-first order, and only collects vertices that has two
535    edges connected to it. If the vertex does not have two edges or if it is a layout edge,
536    it will take all the previously collected vertices and try to create a simplified sequential
537    anchor representing all the previously collected vertices.
538    Once the simplified anchor is inserted, the collected list is cleared in order to find the next
539    sequence to simplify.
540    Note that there are some catches to this that are not covered by the above explanation.
541 */
542 void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
543 {
544     static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty();
545     if (noSimplification)
546         return;
547
548     if (graphSimplified[orientation])
549         return;
550     graphSimplified[orientation] = true;
551
552 #if 0
553     qDebug("Simplifying Graph for %s",
554            orientation == Horizontal ? "Horizontal" : "Vertical");
555 #endif
556
557     AnchorVertex *rootVertex = graph[orientation].rootVertex();
558
559     if (!rootVertex)
560         return;
561
562     bool dirty;
563     do {
564         dirty = simplifyGraphIteration(orientation);
565     } while (dirty);
566 }
567
568 bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation)
569 {
570     Q_Q(QGraphicsAnchorLayout);
571     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
572     AnchorVertex *v = g.rootVertex();
573
574     QSet<AnchorVertex *> visited;
575     QStack<AnchorVertex *> stack;
576     stack.push(v);
577     QVector<AnchorVertex*> candidates;
578
579     const Qt::AnchorPoint centerEdge = pickEdge(Qt::AnchorHorizontalCenter, orientation);
580     const Qt::AnchorPoint layoutEdge = oppositeEdge(v->m_edge);
581
582     bool dirty = false;
583
584     // walk depth-first.
585     while (!stack.isEmpty()) {
586         v = stack.pop();
587         QList<AnchorVertex *> vertices = g.adjacentVertices(v);
588         const int count = vertices.count();
589         bool endOfSequence = (v->m_item == q && v->m_edge == layoutEdge) || count != 2;
590         if (count == 2 && v->m_item != q) {
591             candidates.append(v);
592             if (visited.contains(vertices.first()) && visited.contains(vertices.last())) {
593                 // in case of a cycle
594                 endOfSequence = true;
595             }
596         }
597         if (endOfSequence && candidates.count() >= 1) {
598             int i;
599             AnchorVertex *afterSequence= 0;
600             AnchorVertex *beforeSequence = 0;
601             // find the items before and after the valid sequence
602             if (candidates.count() == 1) {
603                 QList<AnchorVertex *> beforeAndAfterVertices = g.adjacentVertices(candidates.at(0));
604                 Q_ASSERT(beforeAndAfterVertices.count() == 2);
605                 // Since we only have one vertex, we can pick
606                 // any of the two vertices to become before/after.
607                 afterSequence = beforeAndAfterVertices.last();
608                 beforeSequence = beforeAndAfterVertices.first();
609             } else {
610                 QList<AnchorVertex *> adjacentOfSecondLastVertex = g.adjacentVertices(candidates.last());
611                 Q_ASSERT(adjacentOfSecondLastVertex.count() == 2);
612                 if (adjacentOfSecondLastVertex.first() == candidates.at(candidates.count() - 2))
613                     afterSequence = adjacentOfSecondLastVertex.last();
614                 else
615                     afterSequence = adjacentOfSecondLastVertex.first();
616
617                 QList<AnchorVertex *> adjacentOfSecondVertex = g.adjacentVertices(candidates.first());
618                 Q_ASSERT(adjacentOfSecondVertex.count() == 2);
619                 if (adjacentOfSecondVertex.first() == candidates.at(1))
620                     beforeSequence = adjacentOfSecondVertex.last();
621                 else
622                     beforeSequence = adjacentOfSecondVertex.first();
623             }
624             // The complete path of the sequence to simplify is: beforeSequence, <candidates>, afterSequence
625             // where beforeSequence and afterSequence are the endpoints where the anchor is inserted
626             // between.
627 #if defined(QT_DEBUG) && 0
628             // ### DEBUG
629             QString strCandidates;
630             for (i = 0; i < candidates.count(); ++i)
631                 strCandidates += QString::fromAscii("%1 - ").arg(candidates.at(i)->toString());
632             QString strPath = QString::fromAscii("%1 - %2%3").arg(beforeSequence->toString(), strCandidates, afterSequence->toString());
633             qDebug("candidate list for sequential simplification:\n[%s]", qPrintable(strPath));
634 #endif
635
636             bool forward = true;
637             AnchorVertex *prev = beforeSequence;
638             int intervalFrom = 0;
639
640             // Check for directionality (from). We don't want to destroy that information,
641             // thus we only combine anchors with the same direction.
642
643             // "i" is the index *including* the beforeSequence and afterSequence vertices.
644             for (i = 1; i <= candidates.count() + 1; ++i) {
645                 bool atVertexAfter = i > candidates.count();
646                 AnchorVertex *v1 = atVertexAfter ? afterSequence : candidates.at(i - 1);
647                 AnchorData *data = g.edgeData(prev, v1);
648                 Q_ASSERT(data);
649                 if (i == 1) {
650                     forward = (prev == data->from ? true : false);
651                 } else if (forward != (prev == data->from) || atVertexAfter) {
652                     int intervalTo = i;
653                     if (forward != (prev == data->from))
654                         --intervalTo;
655
656                     // intervalFrom and intervalTo should now be indices to the vertex before and
657                     // after the sequential anchor.
658                     if (intervalTo - intervalFrom >= 2) {
659                         // simplify in the range [intervalFrom, intervalTo]
660
661                         // Trim off internal center anchors (Left-Center/Center-Right) from the
662                         // start and the end of the sequence. We never want to simplify internal
663                         // center anchors where there is an external anchor connected to the center.
664                         AnchorVertex *intervalVertexFrom = intervalFrom == 0 ? beforeSequence : candidates.at(intervalFrom - 1);
665                         int effectiveIntervalFrom = intervalFrom;
666                         if (intervalVertexFrom->m_edge == centerEdge
667                             && intervalVertexFrom->m_item == candidates.at(effectiveIntervalFrom)->m_item) {
668                             ++effectiveIntervalFrom;
669                             intervalVertexFrom = candidates.at(effectiveIntervalFrom - 1);
670                         }
671                         AnchorVertex *intervalVertexTo = intervalTo <= candidates.count() ? candidates.at(intervalTo - 1) : afterSequence;
672                         int effectiveIntervalTo = intervalTo;
673                         if (intervalVertexTo->m_edge == centerEdge
674                             && intervalVertexTo->m_item == candidates.at(effectiveIntervalTo - 2)->m_item) {
675                             --effectiveIntervalTo;
676                             intervalVertexTo = candidates.at(effectiveIntervalTo - 1);
677                         }
678                         if (effectiveIntervalTo - effectiveIntervalFrom >= 2) {
679                             QVector<AnchorVertex*> subCandidates;
680                             if (forward) {
681                                subCandidates = candidates.mid(effectiveIntervalFrom, effectiveIntervalTo - effectiveIntervalFrom - 1);
682                             } else {
683                                 // reverse the order of the candidates.
684                                 qSwap(intervalVertexFrom, intervalVertexTo);
685                                 do {
686                                     ++effectiveIntervalFrom;
687                                     subCandidates.prepend(candidates.at(effectiveIntervalFrom - 1));
688                                 } while (effectiveIntervalFrom < effectiveIntervalTo - 1);
689                             }
690                             if (simplifySequentialChunk(&g, intervalVertexFrom, subCandidates, intervalVertexTo)) {
691                                 dirty = true;
692                                 break;
693                             }
694                             // finished simplification of chunk with same direction
695                         }
696                     }
697                     if (forward == (prev == data->from))
698                         --intervalTo;
699                     intervalFrom = intervalTo;
700
701                     forward = !forward;
702                 }
703                 prev = v1;
704             }
705
706             if (dirty)
707                 break;
708         }
709
710         if (endOfSequence)
711             candidates.clear();
712
713         for (int i = 0; i < count; ++i) {
714             AnchorVertex *next = vertices.at(i);
715             if (next->m_item == q && next->m_edge == centerEdge)
716                 continue;
717             if (visited.contains(next))
718                 continue;
719             stack.push(next);
720         }
721
722         visited.insert(v);
723     }
724
725     return dirty;
726 }
727
728 static void restoreSimplifiedAnchor(Graph<AnchorVertex, AnchorData> &g,
729                                     AnchorData *edge,
730                                     AnchorVertex *before,
731                                     AnchorVertex *after)
732 {
733     Q_ASSERT(edge->type != AnchorData::Normal);
734 #if 0
735     static const char *anchortypes[] = {"Normal",
736                                         "Sequential",
737                                         "Parallel"};
738     qDebug("Restoring %s edge.", anchortypes[int(edge->type)]);
739 #endif
740     if (edge->type == AnchorData::Sequential) {
741         SequentialAnchorData* seqEdge = static_cast<SequentialAnchorData*>(edge);
742         // restore the sequential anchor
743         AnchorVertex *prev = before;
744         AnchorVertex *last = after;
745         if (edge->from != prev)
746             qSwap(last, prev);
747
748         for (int i = 0; i < seqEdge->m_edges.count(); ++i) {
749             AnchorVertex *v1 = (i < seqEdge->m_children.count()) ? seqEdge->m_children.at(i) : last;
750             AnchorData *data = seqEdge->m_edges.at(i);
751             if (data->type != AnchorData::Normal) {
752                 restoreSimplifiedAnchor(g, data, prev, v1);
753             } else {
754                 g.createEdge(prev, v1, data);
755             }
756             prev = v1;
757         }
758     } else if (edge->type == AnchorData::Parallel) {
759         ParallelAnchorData* parallelEdge = static_cast<ParallelAnchorData*>(edge);
760         AnchorData *parallelEdges[2] = {parallelEdge->firstEdge,
761                                         parallelEdge->secondEdge};
762         for (int i = 0; i < 2; ++i) {
763             AnchorData *data = parallelEdges[i];
764             if (data->type == AnchorData::Normal) {
765                 g.createEdge(before, after, data);
766             } else {
767                 restoreSimplifiedAnchor(g, data, before, after);
768             }
769         }
770     }
771 }
772
773 void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientation)
774 {
775     if (!graphSimplified[orientation])
776         return;
777     graphSimplified[orientation] = false;
778
779 #if 0
780     qDebug("Restoring Simplified Graph for %s",
781            orientation == Horizontal ? "Horizontal" : "Vertical");
782 #endif
783
784     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
785
786     QList<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections();
787     for (int i = 0; i < connections.count(); ++i) {
788         AnchorVertex *v1 = connections.at(i).first;
789         AnchorVertex *v2 = connections.at(i).second;
790         AnchorData *edge = g.edgeData(v1, v2);
791         if (edge->type != AnchorData::Normal) {
792             AnchorData *oldEdge = g.takeEdge(v1, v2);
793             restoreSimplifiedAnchor(g, edge, v1, v2);
794             delete oldEdge;
795         }
796     }
797 }
798
799 QGraphicsAnchorLayoutPrivate::Orientation
800 QGraphicsAnchorLayoutPrivate::edgeOrientation(Qt::AnchorPoint edge)
801 {
802     return edge > Qt::AnchorRight ? Vertical : Horizontal;
803 }
804
805 /*!
806   \internal
807
808   Create internal anchors to connect the layout edges (Left to Right and
809   Top to Bottom).
810
811   These anchors doesn't have size restrictions, that will be enforced by
812   other anchors and items in the layout.
813 */
814 void QGraphicsAnchorLayoutPrivate::createLayoutEdges()
815 {
816     Q_Q(QGraphicsAnchorLayout);
817     QGraphicsLayoutItem *layout = q;
818
819     // Horizontal
820     AnchorData *data = new AnchorData(0, 0, QWIDGETSIZE_MAX);
821     addAnchor_helper(layout, Qt::AnchorLeft, layout,
822               Qt::AnchorRight, data);
823     data->skipInPreferred = 1;
824
825     // Set the Layout Left edge as the root of the horizontal graph.
826     AnchorVertex *v = internalVertex(layout, Qt::AnchorLeft);
827     graph[Horizontal].setRootVertex(v);
828
829     // Vertical
830     data = new AnchorData(0, 0, QWIDGETSIZE_MAX);
831     addAnchor_helper(layout, Qt::AnchorTop, layout,
832               Qt::AnchorBottom, data);
833     data->skipInPreferred = 1;
834
835     // Set the Layout Top edge as the root of the vertical graph.
836     v = internalVertex(layout, Qt::AnchorTop);
837     graph[Vertical].setRootVertex(v);
838 }
839
840 void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges()
841 {
842     Q_Q(QGraphicsAnchorLayout);
843
844     Q_ASSERT(internalVertex(q, Qt::AnchorHorizontalCenter) == NULL);
845     Q_ASSERT(internalVertex(q, Qt::AnchorVerticalCenter) == NULL);
846
847     removeAnchor_helper(internalVertex(q, Qt::AnchorLeft),
848                         internalVertex(q, Qt::AnchorRight));
849     removeAnchor_helper(internalVertex(q, Qt::AnchorTop),
850                         internalVertex(q, Qt::AnchorBottom));
851 }
852
853 void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item)
854 {
855     Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]);
856
857     items.append(item);
858
859     QSizeF minSize = item->effectiveSizeHint(Qt::MinimumSize);
860     QSizeF prefSize = item->effectiveSizeHint(Qt::PreferredSize);
861     QSizeF maxSize = item->effectiveSizeHint(Qt::MaximumSize);
862
863     // Horizontal
864     AnchorData *data = new AnchorData(minSize.width(), prefSize.width(), maxSize.width());
865     addAnchor_helper(item, Qt::AnchorLeft, item,
866               Qt::AnchorRight, data);
867
868     // Vertical
869     data = new AnchorData(minSize.height(), prefSize.height(), maxSize.height());
870     addAnchor_helper(item, Qt::AnchorTop, item,
871               Qt::AnchorBottom, data);
872 }
873
874 /*!
875   \internal
876
877   By default, each item in the layout is represented internally as
878   a single anchor in each direction. For instance, from Left to Right.
879
880   However, to support anchorage of items to the center of items, we
881   must split this internal anchor into two half-anchors. From Left
882   to Center and then from Center to Right, with the restriction that
883   these anchors must have the same time at all times.
884 */
885 void QGraphicsAnchorLayoutPrivate::createCenterAnchors(
886     QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge)
887 {
888     Orientation orientation;
889     switch (centerEdge) {
890     case Qt::AnchorHorizontalCenter:
891         orientation = Horizontal;
892         break;
893     case Qt::AnchorVerticalCenter:
894         orientation = Vertical;
895         break;
896     default:
897         // Don't create center edges unless needed
898         return;
899     }
900
901     Q_ASSERT(!graphSimplified[orientation]);
902
903     // Check if vertex already exists
904     if (internalVertex(item, centerEdge))
905         return;
906
907     // Orientation code
908     Qt::AnchorPoint firstEdge;
909     Qt::AnchorPoint lastEdge;
910
911     if (orientation == Horizontal) {
912         firstEdge = Qt::AnchorLeft;
913         lastEdge = Qt::AnchorRight;
914     } else {
915         firstEdge = Qt::AnchorTop;
916         lastEdge = Qt::AnchorBottom;
917     }
918
919     AnchorVertex *first = internalVertex(item, firstEdge);
920     AnchorVertex *last = internalVertex(item, lastEdge);
921     Q_ASSERT(first && last);
922
923     // Create new anchors
924     AnchorData *oldData = graph[orientation].edgeData(first, last);
925
926     qreal minimumSize = oldData->minSize / 2;
927     qreal preferredSize = oldData->prefSize / 2;
928     qreal maximumSize = oldData->maxSize / 2;
929
930     QSimplexConstraint *c = new QSimplexConstraint;
931     AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize);
932     c->variables.insert(data, 1.0);
933     addAnchor_helper(item, firstEdge, item, centerEdge, data);
934
935     data = new AnchorData(minimumSize, preferredSize, maximumSize);
936     c->variables.insert(data, -1.0);
937     addAnchor_helper(item, centerEdge, item, lastEdge, data);
938
939     itemCenterConstraints[orientation].append(c);
940
941     // Remove old one
942     removeAnchor_helper(first, last);
943 }
944
945 void QGraphicsAnchorLayoutPrivate::removeCenterAnchors(
946     QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge,
947     bool substitute)
948 {
949     Orientation orientation;
950     switch (centerEdge) {
951     case Qt::AnchorHorizontalCenter:
952         orientation = Horizontal;
953         break;
954     case Qt::AnchorVerticalCenter:
955         orientation = Vertical;
956         break;
957     default:
958         // Don't remove edges that not the center ones
959         return;
960     }
961
962     Q_ASSERT(!graphSimplified[orientation]);
963
964     // Orientation code
965     Qt::AnchorPoint firstEdge;
966     Qt::AnchorPoint lastEdge;
967
968     if (orientation == Horizontal) {
969         firstEdge = Qt::AnchorLeft;
970         lastEdge = Qt::AnchorRight;
971     } else {
972         firstEdge = Qt::AnchorTop;
973         lastEdge = Qt::AnchorBottom;
974     }
975
976     AnchorVertex *center = internalVertex(item, centerEdge);
977     if (!center)
978         return;
979     AnchorVertex *first = internalVertex(item, firstEdge);
980
981     Q_ASSERT(first);
982     Q_ASSERT(center);
983
984     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
985
986
987     AnchorData *oldData = g.edgeData(first, center);
988     // Remove center constraint
989     for (int i = itemCenterConstraints[orientation].count() - 1; i >= 0; --i) {
990         if (itemCenterConstraints[orientation][i]->variables.contains(oldData)) {
991             delete itemCenterConstraints[orientation].takeAt(i);
992             break;
993         }
994     }
995
996     if (substitute) {
997         // Create the new anchor that should substitute the left-center-right anchors.
998         AnchorData *oldData = g.edgeData(first, center);
999
1000         qreal minimumSize = oldData->minSize * 2;
1001         qreal preferredSize = oldData->prefSize * 2;
1002         qreal maximumSize = oldData->maxSize * 2;
1003
1004         AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize);
1005         addAnchor_helper(item, firstEdge, item, lastEdge, data);
1006
1007         // Remove old anchors
1008         removeAnchor_helper(first, center);
1009         removeAnchor_helper(center, internalVertex(item, lastEdge));
1010
1011     } else {
1012         // this is only called from removeAnchors()
1013         // first, remove all non-internal anchors
1014         QList<AnchorVertex*> adjacents = g.adjacentVertices(center);
1015         for (int i = 0; i < adjacents.count(); ++i) {
1016             AnchorVertex *v = adjacents.at(i);
1017             if (v->m_item != item) {
1018                 removeAnchor_helper(center, internalVertex(v->m_item, v->m_edge));
1019             }
1020         }
1021         // when all non-internal anchors is removed it will automatically merge the
1022         // center anchor into a left-right (or top-bottom) anchor. We must also delete that.
1023         // by this time, the center vertex is deleted and merged into a non-centered internal anchor
1024         removeAnchor_helper(first, internalVertex(item, lastEdge));
1025     }
1026 }
1027
1028
1029 void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *item,
1030                                                            Orientation orientation)
1031 {
1032     Q_ASSERT(!graphSimplified[orientation]);
1033
1034     // Remove the item center constraints associated to this item
1035     // ### This is a temporary solution. We should probably use a better
1036     // data structure to hold items and/or their associated constraints
1037     // so that we can remove those easily
1038
1039     AnchorVertex *first = internalVertex(item, orientation == Horizontal ?
1040                                        Qt::AnchorLeft :
1041                                        Qt::AnchorTop);
1042     AnchorVertex *center = internalVertex(item, orientation == Horizontal ?
1043                                         Qt::AnchorHorizontalCenter :
1044                                         Qt::AnchorVerticalCenter);
1045
1046     // Skip if no center constraints exist
1047     if (!center)
1048         return;
1049
1050     Q_ASSERT(first);
1051     AnchorData *internalAnchor = graph[orientation].edgeData(first, center);
1052
1053     // Look for our anchor in all item center constraints, then remove it
1054     for (int i = 0; i < itemCenterConstraints[orientation].size(); ++i) {
1055         if (itemCenterConstraints[orientation][i]->variables.contains(internalAnchor)) {
1056             delete itemCenterConstraints[orientation].takeAt(i);
1057             break;
1058         }
1059     }
1060 }
1061
1062 /*!
1063  * \internal
1064  *
1065  * Helper function that is called from the anchor functions in the public API.
1066  * If \a spacing is 0, it will pick up the spacing defined by the style.
1067  */
1068 QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem,
1069                                                       Qt::AnchorPoint firstEdge,
1070                                                       QGraphicsLayoutItem *secondItem,
1071                                                       Qt::AnchorPoint secondEdge,
1072                                                       qreal *spacing)
1073 {
1074     Q_Q(QGraphicsAnchorLayout);
1075     if ((firstItem == 0) || (secondItem == 0)) {
1076         qWarning("QGraphicsAnchorLayout::addAnchor(): "
1077                  "Cannot anchor NULL items");
1078         return 0;
1079     }
1080
1081     if (firstItem == secondItem) {
1082         qWarning("QGraphicsAnchorLayout::addAnchor(): "
1083                  "Cannot anchor the item to itself");
1084         return 0;
1085     }
1086
1087     if (edgeOrientation(secondEdge) != edgeOrientation(firstEdge)) {
1088         qWarning("QGraphicsAnchorLayout::addAnchor(): "
1089                  "Cannot anchor edges of different orientations");
1090         return 0;
1091     }
1092
1093     // Guarantee that the graph is no simplified when adding this anchor,
1094     // anchor manipulation always happen in the full graph
1095     restoreSimplifiedGraph(edgeOrientation(firstEdge));
1096
1097     // In QGraphicsAnchorLayout, items are represented in its internal
1098     // graph as four anchors that connect:
1099     //  - Left -> HCenter
1100     //  - HCenter-> Right
1101     //  - Top -> VCenter
1102     //  - VCenter -> Bottom
1103
1104     // Ensure that the internal anchors have been created for both items.
1105     if (firstItem != q && !items.contains(firstItem)) {
1106         restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal);
1107         createItemEdges(firstItem);
1108         addChildLayoutItem(firstItem);
1109     }
1110     if (secondItem != q && !items.contains(secondItem)) {
1111         restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal);
1112         createItemEdges(secondItem);
1113         addChildLayoutItem(secondItem);
1114     }
1115
1116     // Create center edges if needed
1117     createCenterAnchors(firstItem, firstEdge);
1118     createCenterAnchors(secondItem, secondEdge);
1119
1120     // Use heuristics to find out what the user meant with this anchor.
1121     correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge);
1122
1123     AnchorData *data;
1124     if (!spacing) {
1125         // If firstItem or secondItem is the layout itself, the spacing will default to 0.
1126         // Otherwise, the following matrix is used (questionmark means that the spacing
1127         // is queried from the style):
1128         //                from
1129         //  to      Left    HCenter Right
1130         //  Left    0       0       ?
1131         //  HCenter 0       0       0
1132         //  Right   ?       0       0
1133         if (firstItem != q
1134             && secondItem != q
1135             && pickEdge(firstEdge, Horizontal) != Qt::AnchorHorizontalCenter
1136             && oppositeEdge(firstEdge) == secondEdge) {
1137             data = new AnchorData;      // ask the style later
1138         } else {
1139             data = new AnchorData(0);   // spacing should be 0
1140         }
1141         addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data);
1142     } else if (*spacing >= 0) {
1143         data = new AnchorData(*spacing);
1144         addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data);
1145     } else {
1146         data = new AnchorData(-*spacing);
1147         addAnchor_helper(secondItem, secondEdge, firstItem, firstEdge, data);
1148     }
1149     return acquireGraphicsAnchor(data);
1150 }
1151
1152 void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem,
1153                                              Qt::AnchorPoint firstEdge,
1154                                              QGraphicsLayoutItem *secondItem,
1155                                              Qt::AnchorPoint secondEdge,
1156                                              AnchorData *data)
1157 {
1158     Q_Q(QGraphicsAnchorLayout);
1159
1160     // Guarantee that the graph is no simplified when adding this anchor,
1161     // anchor manipulation always happen in the full graph
1162     restoreSimplifiedGraph(edgeOrientation(firstEdge));
1163
1164     // Is the Vertex (firstItem, firstEdge) already represented in our
1165     // internal structure?
1166     AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge);
1167     AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge);
1168
1169     // Remove previous anchor
1170     // ### Could we update the existing edgeData rather than creating a new one?
1171     if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) {
1172         removeAnchor_helper(v1, v2);
1173     }
1174
1175     // Create a bi-directional edge in the sense it can be transversed both
1176     // from v1 or v2. "data" however is shared between the two references
1177     // so we still know that the anchor direction is from 1 to 2.
1178     data->from = v1;
1179     data->to = v2;
1180 #ifdef QT_DEBUG
1181     data->name = QString::fromAscii("%1 --to--> %2").arg(v1->toString()).arg(v2->toString());
1182 #endif
1183     // Keep track of anchors that are connected to the layout 'edges'
1184     data->isLayoutAnchor = (v1->m_item == q || v2->m_item == q);
1185
1186     graph[edgeOrientation(firstEdge)].createEdge(v1, v2, data);
1187 }
1188
1189 QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *firstItem,
1190                                                          Qt::AnchorPoint firstEdge,
1191                                                          QGraphicsLayoutItem *secondItem,
1192                                                          Qt::AnchorPoint secondEdge)
1193 {
1194     Orientation orient = edgeOrientation(firstEdge);
1195     restoreSimplifiedGraph(orient);
1196
1197     AnchorVertex *v1 = internalVertex(firstItem, firstEdge);
1198     AnchorVertex *v2 = internalVertex(secondItem, secondEdge);
1199
1200     QGraphicsAnchor *graphicsAnchor = 0;
1201
1202     AnchorData *data = graph[orient].edgeData(v1, v2);
1203     if (data)
1204         graphicsAnchor = acquireGraphicsAnchor(data);
1205     return graphicsAnchor;
1206 }
1207
1208 /*!
1209  * \internal
1210  *
1211  * Implements the high level "removeAnchor" feature. Called by
1212  * the QAnchorData destructor.
1213  */
1214 void QGraphicsAnchorLayoutPrivate::removeAnchor(AnchorVertex *firstVertex,
1215                                                 AnchorVertex *secondVertex)
1216 {
1217     Q_Q(QGraphicsAnchorLayout);
1218
1219     // Actually delete the anchor
1220     removeAnchor_helper(firstVertex, secondVertex);
1221
1222     QGraphicsLayoutItem *firstItem = firstVertex->m_item;
1223     QGraphicsLayoutItem *secondItem = secondVertex->m_item;
1224
1225     // Checking if the item stays in the layout or not
1226     bool keepFirstItem = false;
1227     bool keepSecondItem = false;
1228
1229     QPair<AnchorVertex *, int> v;
1230     int refcount = -1;
1231
1232     if (firstItem != q) {
1233         for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) {
1234             v = m_vertexList.value(qMakePair(firstItem, static_cast<Qt::AnchorPoint>(i)));
1235             if (v.first) {
1236                 if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter)
1237                     refcount = 2;
1238                 else
1239                     refcount = 1;
1240
1241                 if (v.second > refcount) {
1242                     keepFirstItem = true;
1243                     break;
1244                 }
1245             }
1246         }
1247     } else
1248         keepFirstItem = true;
1249
1250     if (secondItem != q) {
1251         for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) {
1252             v = m_vertexList.value(qMakePair(secondItem, static_cast<Qt::AnchorPoint>(i)));
1253             if (v.first) {
1254                 if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter)
1255                     refcount = 2;
1256                 else
1257                     refcount = 1;
1258
1259                 if (v.second > refcount) {
1260                     keepSecondItem = true;
1261                     break;
1262                 }
1263             }
1264         }
1265     } else
1266         keepSecondItem = true;
1267
1268     if (!keepFirstItem)
1269         q->removeAt(items.indexOf(firstItem));
1270
1271     if (!keepSecondItem)
1272         q->removeAt(items.indexOf(secondItem));
1273
1274     // Removing anchors invalidates the layout
1275     q->invalidate();
1276 }
1277
1278 /*
1279   \internal
1280
1281   Implements the low level "removeAnchor" feature. Called by
1282   private methods.
1283 */
1284 void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2)
1285 {
1286     Q_ASSERT(v1 && v2);
1287     // Guarantee that the graph is no simplified when removing this anchor,
1288     // anchor manipulation always happen in the full graph
1289     Orientation o = edgeOrientation(v1->m_edge);
1290     restoreSimplifiedGraph(o);
1291
1292     // Remove edge from graph
1293     graph[o].removeEdge(v1, v2);
1294
1295     // Decrease vertices reference count (may trigger a deletion)
1296     removeInternalVertex(v1->m_item, v1->m_edge);
1297     removeInternalVertex(v2->m_item, v2->m_edge);
1298 }
1299
1300 /*!
1301     \internal
1302     Only called from outside. (calls invalidate())
1303 */
1304 void QGraphicsAnchorLayoutPrivate::setAnchorSize(AnchorData *data, const qreal *anchorSize)
1305 {
1306     Q_Q(QGraphicsAnchorLayout);
1307     // ### we can avoid restoration if we really want to, but we would have to
1308     // search recursively through all composite anchors
1309     Q_ASSERT(data);
1310     restoreSimplifiedGraph(edgeOrientation(data->from->m_edge));
1311
1312     QGraphicsLayoutItem *firstItem = data->from->m_item;
1313     QGraphicsLayoutItem *secondItem = data->to->m_item;
1314     Qt::AnchorPoint firstEdge = data->from->m_edge;
1315     Qt::AnchorPoint secondEdge = data->to->m_edge;
1316
1317     // Use heuristics to find out what the user meant with this anchor.
1318     correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge);
1319     if (data->from->m_item != firstItem)
1320         qSwap(data->from, data->to);
1321
1322     if (anchorSize) {
1323         // ### The current implementation makes "setAnchorSize" behavior
1324         //     dependent on the argument order for cases where we have
1325         //     no heuristic. Ie. two widgets, same anchor point.
1326
1327         // We cannot have negative sizes inside the graph. This would cause
1328         // the simplex solver to fail because all simplex variables are
1329         // positive by definition.
1330         // "negative spacing" is handled by inverting the standard item order.
1331         if (*anchorSize >= 0) {
1332             data->setFixedSize(*anchorSize);
1333         } else {
1334             data->setFixedSize(-*anchorSize);
1335             qSwap(data->from, data->to);
1336         }
1337     } else {
1338         data->unsetSize();
1339     }
1340     q->invalidate();
1341 }
1342
1343 void QGraphicsAnchorLayoutPrivate::anchorSize(const AnchorData *data,
1344                                               qreal *minSize,
1345                                               qreal *prefSize,
1346                                               qreal *maxSize) const
1347 {
1348     Q_ASSERT(minSize || prefSize || maxSize);
1349     Q_ASSERT(data);
1350     QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate *>(this);
1351     that->restoreSimplifiedGraph(edgeOrientation(data->from->m_edge));
1352
1353     if (minSize)
1354         *minSize = data->minSize;
1355     if (prefSize)
1356         *prefSize = data->prefSize;
1357     if (maxSize)
1358         *maxSize = data->maxSize;
1359 }
1360
1361 AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item,
1362                                                               Qt::AnchorPoint edge)
1363 {
1364     QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge);
1365     QPair<AnchorVertex *, int> v = m_vertexList.value(pair);
1366
1367     if (!v.first) {
1368         Q_ASSERT(v.second == 0);
1369         v.first = new AnchorVertex(item, edge);
1370     }
1371     v.second++;
1372     m_vertexList.insert(pair, v);
1373     return v.first;
1374 }
1375
1376 /**
1377  * \internal
1378  *
1379  * returns the AnchorVertex that was dereferenced, also when it was removed.
1380  * returns 0 if it did not exist.
1381  */
1382 void QGraphicsAnchorLayoutPrivate::removeInternalVertex(QGraphicsLayoutItem *item,
1383                                                         Qt::AnchorPoint edge)
1384 {
1385     QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge);
1386     QPair<AnchorVertex *, int> v = m_vertexList.value(pair);
1387
1388     if (!v.first) {
1389         qWarning("This item with this edge is not in the graph");
1390         return;
1391     }
1392
1393     v.second--;
1394     if (v.second == 0) {
1395         // Remove reference and delete vertex
1396         m_vertexList.remove(pair);
1397         delete v.first;
1398     } else {
1399         // Update reference count
1400         m_vertexList.insert(pair, v);
1401
1402         if ((v.second == 2) &&
1403             ((edge == Qt::AnchorHorizontalCenter) ||
1404              (edge == Qt::AnchorVerticalCenter))) {
1405             removeCenterAnchors(item, edge, true);
1406         }
1407     }
1408 }
1409
1410 void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge)
1411 {
1412     if (AnchorVertex *v = internalVertex(item, edge)) {
1413         Graph<AnchorVertex, AnchorData> &g = graph[edgeOrientation(edge)];
1414         const QList<AnchorVertex *> allVertices = graph[edgeOrientation(edge)].adjacentVertices(v);
1415         AnchorVertex *v2;
1416         foreach (v2, allVertices) {
1417             g.removeEdge(v, v2);
1418             removeInternalVertex(item, edge);
1419             removeInternalVertex(v2->m_item, v2->m_edge);
1420         }
1421     }
1422 }
1423
1424 void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item)
1425 {
1426     Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]);
1427
1428     // remove the center anchor first!!
1429     removeCenterAnchors(item, Qt::AnchorHorizontalCenter, false);
1430     removeVertex(item, Qt::AnchorLeft);
1431     removeVertex(item, Qt::AnchorRight);
1432
1433     removeCenterAnchors(item, Qt::AnchorVerticalCenter, false);
1434     removeVertex(item, Qt::AnchorTop);
1435     removeVertex(item, Qt::AnchorBottom);
1436 }
1437
1438 /*!
1439   \internal
1440
1441   Use heuristics to determine the correct orientation of a given anchor.
1442
1443   After API discussions, we decided we would like expressions like
1444   anchor(A, Left, B, Right) to mean the same as anchor(B, Right, A, Left).
1445   The problem with this is that anchors could become ambiguous, for
1446   instance, what does the anchor A, B of size X mean?
1447
1448      "pos(B) = pos(A) + X"  or  "pos(A) = pos(B) + X" ?
1449
1450   To keep the API user friendly and at the same time, keep our algorithm
1451   deterministic, we use an heuristic to determine a direction for each
1452   added anchor and then keep it. The heuristic is based on the fact
1453   that people usually avoid overlapping items, therefore:
1454
1455      "A, RIGHT to B, LEFT" means that B is to the LEFT of A.
1456      "B, LEFT to A, RIGHT" is corrected to the above anchor.
1457
1458   Special correction is also applied when one of the items is the
1459   layout. We handle Layout Left as if it was another items's Right
1460   and Layout Right as another item's Left.
1461 */
1462 void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&firstItem,
1463                                                         Qt::AnchorPoint &firstEdge,
1464                                                         QGraphicsLayoutItem *&secondItem,
1465                                                         Qt::AnchorPoint &secondEdge)
1466 {
1467     Q_Q(QGraphicsAnchorLayout);
1468
1469     if ((firstItem != q) && (secondItem != q)) {
1470         // If connection is between widgets (not the layout itself)
1471         // Ensure that "right-edges" sit to the left of "left-edges".
1472         if (firstEdge < secondEdge) {
1473             qSwap(firstItem, secondItem);
1474             qSwap(firstEdge, secondEdge);
1475         }
1476     } else if (firstItem == q) {
1477         // If connection involves the right or bottom of a layout, ensure
1478         // the layout is the second item.
1479         if ((firstEdge == Qt::AnchorRight) || (firstEdge == Qt::AnchorBottom)) {
1480             qSwap(firstItem, secondItem);
1481             qSwap(firstEdge, secondEdge);
1482         }
1483     } else if ((secondEdge != Qt::AnchorRight) && (secondEdge != Qt::AnchorBottom)) {
1484         // If connection involves the left, center or top of layout, ensure
1485         // the layout is the first item.
1486         qSwap(firstItem, secondItem);
1487         qSwap(firstEdge, secondEdge);
1488     }
1489 }
1490
1491 qreal QGraphicsAnchorLayoutPrivate::effectiveSpacing(Orientation orientation) const
1492 {
1493     Q_Q(const QGraphicsAnchorLayout);
1494     qreal s = spacings[orientation];
1495     if (s < 0) {
1496         // ### make sure behaviour is the same as in QGraphicsGridLayout
1497         QGraphicsLayoutItem *parent = q->parentLayoutItem();
1498         while (parent && parent->isLayout()) {
1499             parent = parent->parentLayoutItem();
1500         }
1501         if (parent) {
1502             QGraphicsItem *parentItem = parent->graphicsItem();
1503             if (parentItem && parentItem->isWidget()) {
1504                 QGraphicsWidget *w = static_cast<QGraphicsWidget*>(parentItem);
1505                 s = w->style()->pixelMetric(orientation == Horizontal
1506                                             ? QStyle::PM_LayoutHorizontalSpacing
1507                                             : QStyle::PM_LayoutVerticalSpacing);
1508             }
1509         }
1510     }
1511     return s;
1512 }
1513
1514 /*!
1515   \internal
1516
1517   Called on activation. Uses Linear Programming to define minimum, preferred
1518   and maximum sizes for the layout. Also calculates the sizes that each item
1519   should assume when the layout is in one of such situations.
1520 */
1521 void QGraphicsAnchorLayoutPrivate::calculateGraphs()
1522 {
1523     if (!calculateGraphCacheDirty)
1524         return;
1525
1526     calculateGraphs(Horizontal);
1527     calculateGraphs(Vertical);
1528
1529     calculateGraphCacheDirty = 0;
1530 }
1531
1532 // ### remove me:
1533 QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints)
1534 {
1535     QSet<AnchorData *> variableSet;
1536     for (int i = 0; i < constraints.count(); ++i) {
1537         const QSimplexConstraint *c = constraints[i];
1538         foreach (QSimplexVariable *var, c->variables.keys()) {
1539             variableSet += static_cast<AnchorData *>(var);
1540         }
1541     }
1542     return variableSet.toList();
1543 }
1544
1545 /*!
1546   \internal
1547
1548   Calculate graphs is the method that puts together all the helper routines
1549   so that the AnchorLayout can calculate the sizes of each item.
1550
1551   In a nutshell it should do:
1552
1553   1) Update anchor nominal sizes, that is, the size that each anchor would
1554      have if no other restrictions applied. This is done by quering the
1555      layout style and the sizeHints of the items belonging to the layout.
1556
1557   2) Simplify the graph by grouping together parallel and sequential anchors
1558      into "group anchors". These have equivalent minimum, preferred and maximum
1559      sizeHints as the anchors they replace.
1560
1561   3) Check if we got to a trivial case. In some cases, the whole graph can be
1562      simplified into a single anchor. If so, use this information. If not,
1563      then call the Simplex solver to calculate the anchors sizes.
1564
1565   4) Once the root anchors had its sizes calculated, propagate that to the
1566      anchors they represent.
1567 */
1568 void QGraphicsAnchorLayoutPrivate::calculateGraphs(
1569     QGraphicsAnchorLayoutPrivate::Orientation orientation)
1570 {
1571     Q_Q(QGraphicsAnchorLayout);
1572
1573     // Simplify the graph
1574     simplifyGraph(orientation);
1575
1576     // Reset the nominal sizes of each anchor based on the current item sizes
1577     setAnchorSizeHintsFromItems(orientation);
1578
1579     // Traverse all graph edges and store the possible paths to each vertex
1580     findPaths(orientation);
1581
1582     // From the paths calculated above, extract the constraints that the current
1583     // anchor setup impose, to our Linear Programming problem.
1584     constraintsFromPaths(orientation);
1585
1586     // Split the constraints and anchors into groups that should be fed to the
1587     // simplex solver independently. Currently we find two groups:
1588     //
1589     //  1) The "trunk", that is, the set of anchors (items) that are connected
1590     //     to the two opposite sides of our layout, and thus need to stretch in
1591     //     order to fit in the current layout size.
1592     //
1593     //  2) The floating or semi-floating anchors (items) that are those which
1594     //     are connected to only one (or none) of the layout sides, thus are not
1595     //     influenced by the layout size.
1596     QList<QList<QSimplexConstraint *> > parts;
1597     parts = getGraphParts(orientation);
1598
1599     // Now run the simplex solver to calculate Minimum, Preferred and Maximum sizes
1600     // of the "trunk" set of constraints and variables.
1601     // ### does trunk always exist? empty = trunk is the layout left->center->right
1602     QList<QSimplexConstraint *> trunkConstraints = parts[0];
1603     QList<QSimplexConstraint *> sizeHintConstraints;
1604     sizeHintConstraints = constraintsFromSizeHints(getVariables(trunkConstraints));
1605     trunkConstraints += sizeHintConstraints;
1606
1607     // For minimum and maximum, use the path between the two layout sides as the
1608     // objective function.
1609
1610     // Retrieve that path
1611     AnchorVertex *v = internalVertex(q, pickEdge(Qt::AnchorRight, orientation));
1612     GraphPath trunkPath = graphPaths[orientation].value(v);
1613
1614     bool feasible = true;
1615     if (!trunkConstraints.isEmpty()) {
1616 #if 0
1617         qDebug("Simplex used for trunk of %s",
1618                orientation == Horizontal ? "Horizontal" : "Vertical");
1619 #endif
1620
1621         // Solve min and max size hints for trunk
1622         qreal min, max;
1623         feasible = solveMinMax(trunkConstraints, trunkPath, &min, &max);
1624
1625         // Solve for preferred. The objective function is calculated from the constraints
1626         // and variables internally.
1627         feasible &= solvePreferred(trunkConstraints);
1628
1629         if (feasible) {
1630             // Propagate the new sizes down the simplified graph, ie. tell the
1631             // group anchors to set their children anchors sizes.
1632
1633             // ### we calculated variables already a few times, can't we reuse that?
1634             QList<AnchorData *> trunkVariables = getVariables(trunkConstraints);
1635
1636             for (int i = 0; i < trunkVariables.count(); ++i)
1637                 trunkVariables.at(i)->updateChildrenSizes();
1638
1639             // Calculate and set the preferred size for the layout from the edge sizes that
1640             // were calculated above.
1641             qreal pref(0.0);
1642             foreach (const AnchorData *ad, trunkPath.positives) {
1643                 pref += ad->sizeAtPreferred;
1644             }
1645             foreach (const AnchorData *ad, trunkPath.negatives) {
1646                 pref -= ad->sizeAtPreferred;
1647             }
1648             sizeHints[orientation][Qt::MinimumSize] = min;
1649             sizeHints[orientation][Qt::PreferredSize] = pref;
1650             sizeHints[orientation][Qt::MaximumSize] = max;
1651
1652         }
1653     } else {
1654 #if 0
1655         qDebug("Simplex NOT used for trunk of %s",
1656                orientation == Horizontal ? "Horizontal" : "Vertical");
1657 #endif
1658
1659         // No Simplex is necessary because the path was simplified all the way to a single
1660         // anchor.
1661         Q_ASSERT(trunkPath.positives.count() == 1);
1662         Q_ASSERT(trunkPath.negatives.count() == 0);
1663
1664         AnchorData *ad = trunkPath.positives.toList()[0];
1665         ad->sizeAtMinimum = ad->minSize;
1666         ad->sizeAtPreferred = ad->prefSize;
1667         ad->sizeAtMaximum = ad->maxSize;
1668
1669         // Propagate
1670         ad->updateChildrenSizes();
1671
1672         sizeHints[orientation][Qt::MinimumSize] = ad->sizeAtMinimum;
1673         sizeHints[orientation][Qt::PreferredSize] = ad->sizeAtPreferred;
1674         sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum;
1675     }
1676
1677     // Delete the constraints, we won't use them anymore.
1678     qDeleteAll(sizeHintConstraints);
1679     sizeHintConstraints.clear();
1680
1681     // For the other parts that not the trunk, solve only for the preferred size
1682     // that is the size they will remain at, since they are not stretched by the
1683     // layout.
1684
1685     // Solve the other only for preferred, skip trunk
1686     if (feasible) {
1687         for (int i = 1; i < parts.count(); ++i) {
1688             QList<QSimplexConstraint *> partConstraints = parts[i];
1689             QList<AnchorData *> partVariables = getVariables(partConstraints);
1690             Q_ASSERT(!partVariables.isEmpty());
1691
1692             sizeHintConstraints = constraintsFromSizeHints(partVariables);
1693             partConstraints += sizeHintConstraints;
1694             feasible &= solvePreferred(partConstraints);
1695             if (!feasible)
1696                 break;
1697
1698             // Propagate size at preferred to other sizes. Semi-floats
1699             // always will be in their sizeAtPreferred.
1700             for (int j = 0; j < partVariables.count(); ++j) {
1701                 AnchorData *ad = partVariables[j];
1702                 Q_ASSERT(ad);
1703                 ad->sizeAtMinimum = ad->sizeAtPreferred;
1704                 ad->sizeAtMaximum = ad->sizeAtPreferred;
1705                 ad->updateChildrenSizes();
1706             }
1707
1708             // Delete the constraints, we won't use them anymore.
1709             qDeleteAll(sizeHintConstraints);
1710             sizeHintConstraints.clear();
1711         }
1712     }
1713     graphHasConflicts[orientation] = !feasible;
1714
1715     // Clean up our data structures. They are not needed anymore since
1716     // distribution uses just interpolation.
1717     qDeleteAll(constraints[orientation]);
1718     constraints[orientation].clear();
1719     graphPaths[orientation].clear(); // ###
1720 }
1721
1722 /*!
1723   \internal
1724
1725   For graph edges ("anchors") that represent items, this method updates their
1726   intrinsic size restrictions, based on the item size hints.
1727 */
1728 void QGraphicsAnchorLayoutPrivate::setAnchorSizeHintsFromItems(Orientation orientation)
1729 {
1730     Graph<AnchorVertex, AnchorData> &g = graph[orientation];
1731     QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections();
1732
1733     qreal spacing = effectiveSpacing(orientation);
1734
1735     for (int i = 0; i < vertices.count(); ++i) {
1736         AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);;
1737         Q_ASSERT(data->from && data->to);
1738         data->refreshSizeHints(spacing);
1739     }
1740 }
1741
1742 /*!
1743   \internal
1744
1745   This method walks the graph using a breadth-first search to find paths
1746   between the root vertex and each vertex on the graph. The edges
1747   directions in each path are considered and they are stored as a
1748   positive edge (left-to-right) or negative edge (right-to-left).
1749
1750   The list of paths is used later to generate a list of constraints.
1751  */
1752 void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation)
1753 {
1754     QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue;
1755
1756     QSet<AnchorData *> visited;
1757
1758     AnchorVertex *root = graph[orientation].rootVertex();
1759
1760     graphPaths[orientation].insert(root, GraphPath());
1761
1762     foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) {
1763         queue.enqueue(qMakePair(root, v));
1764     }
1765
1766     while(!queue.isEmpty()) {
1767         QPair<AnchorVertex *, AnchorVertex *>  pair = queue.dequeue();
1768         AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second);
1769
1770         if (visited.contains(edge))
1771             continue;
1772
1773         visited.insert(edge);
1774         GraphPath current = graphPaths[orientation].value(pair.first);
1775
1776         if (edge->from == pair.first)
1777             current.positives.insert(edge);
1778         else
1779             current.negatives.insert(edge);
1780
1781         graphPaths[orientation].insert(pair.second, current);
1782
1783         foreach (AnchorVertex *v,
1784                 graph[orientation].adjacentVertices(pair.second)) {
1785             queue.enqueue(qMakePair(pair.second, v));
1786         }
1787     }
1788 }
1789
1790 /*!
1791   \internal
1792
1793   Each vertex on the graph that has more than one path to it
1794   represents a contra int to the sizes of the items in these paths.
1795
1796   This method walks the list of paths to each vertex, generate
1797   the constraints and store them in a list so they can be used later
1798   by the Simplex solver.
1799 */
1800 void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation)
1801 {
1802     foreach (AnchorVertex *vertex, graphPaths[orientation].uniqueKeys())
1803     {
1804         int valueCount = graphPaths[orientation].count(vertex);
1805         if (valueCount == 1)
1806             continue;
1807
1808         QList<GraphPath> pathsToVertex = graphPaths[orientation].values(vertex);
1809         for (int i = 1; i < valueCount; ++i) {
1810             constraints[orientation] += \
1811                 pathsToVertex[0].constraint(pathsToVertex[i]);
1812         }
1813     }
1814 }
1815
1816 /*!
1817   \internal
1818
1819   Create LP constraints for each anchor based on its minimum and maximum
1820   sizes, as specified in its size hints
1821 */
1822 QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints(
1823     const QList<AnchorData *> &anchors)
1824 {
1825     QList<QSimplexConstraint *> anchorConstraints;
1826     for (int i = 0; i < anchors.size(); ++i) {
1827         QSimplexConstraint *c = new QSimplexConstraint;
1828         c->variables.insert(anchors[i], 1.0);
1829         c->constant = anchors[i]->minSize;
1830         c->ratio = QSimplexConstraint::MoreOrEqual;
1831         anchorConstraints += c;
1832
1833         c = new QSimplexConstraint;
1834         c->variables.insert(anchors[i], 1.0);
1835         c->constant = anchors[i]->maxSize;
1836         c->ratio = QSimplexConstraint::LessOrEqual;
1837         anchorConstraints += c;
1838     }
1839
1840     return anchorConstraints;
1841 }
1842
1843 /*!
1844   \internal
1845 */
1846 QList< QList<QSimplexConstraint *> >
1847 QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation)
1848 {
1849     Q_Q(QGraphicsAnchorLayout);
1850
1851     // Find layout vertices and edges for the current orientation.
1852     AnchorVertex *layoutFirstVertex = \
1853         internalVertex(q, pickEdge(Qt::AnchorLeft, orientation));
1854
1855     AnchorVertex *layoutCentralVertex = \
1856         internalVertex(q, pickEdge(Qt::AnchorHorizontalCenter, orientation));
1857
1858     AnchorVertex *layoutLastVertex = \
1859         internalVertex(q, pickEdge(Qt::AnchorRight, orientation));
1860
1861     Q_ASSERT(layoutFirstVertex && layoutLastVertex);
1862
1863     AnchorData *edgeL1 = NULL;
1864     AnchorData *edgeL2 = NULL;
1865
1866     // The layout may have a single anchor between Left and Right or two half anchors
1867     // passing through the center
1868     if (layoutCentralVertex) {
1869         edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutCentralVertex);
1870         edgeL2 = graph[orientation].edgeData(layoutCentralVertex, layoutLastVertex);
1871     } else {
1872         edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutLastVertex);
1873     }
1874
1875     QLinkedList<QSimplexConstraint *> remainingConstraints;
1876     for (int i = 0; i < constraints[orientation].count(); ++i) {
1877         remainingConstraints += constraints[orientation][i];
1878     }
1879     for (int i = 0; i < itemCenterConstraints[orientation].count(); ++i) {
1880         remainingConstraints += itemCenterConstraints[orientation][i];
1881     }
1882
1883     QList<QSimplexConstraint *> trunkConstraints;
1884     QSet<QSimplexVariable *> trunkVariables;
1885
1886     trunkVariables += edgeL1;
1887     if (edgeL2)
1888         trunkVariables += edgeL2;
1889
1890     bool dirty;
1891     do {
1892         dirty = false;
1893
1894         QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin();
1895         while (it != remainingConstraints.end()) {
1896             QSimplexConstraint *c = *it;
1897             bool match = false;
1898
1899             // Check if this constraint have some overlap with current
1900             // trunk variables...
1901             foreach (QSimplexVariable *ad, trunkVariables) {
1902                 if (c->variables.contains(ad)) {
1903                     match = true;
1904                     break;
1905                 }
1906             }
1907
1908             // If so, we add it to trunk, and erase it from the
1909             // remaining constraints.
1910             if (match) {
1911                 trunkConstraints += c;
1912                 trunkVariables += QSet<QSimplexVariable *>::fromList(c->variables.keys());
1913                 it = remainingConstraints.erase(it);
1914                 dirty = true;
1915             } else {
1916                 // Note that we don't erase the constraint if it's not
1917                 // a match, since in a next iteration of a do-while we
1918                 // can pass on it again and it will be a match.
1919                 //
1920                 // For example: if trunk share a variable with
1921                 // remainingConstraints[1] and it shares with
1922                 // remainingConstraints[0], we need a second iteration
1923                 // of the do-while loop to match both.
1924                 ++it;
1925             }
1926         }
1927     } while (dirty);
1928
1929     QList< QList<QSimplexConstraint *> > result;
1930     result += trunkConstraints;
1931
1932     if (!remainingConstraints.isEmpty()) {
1933         QList<QSimplexConstraint *> nonTrunkConstraints;
1934         QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin();
1935         while (it != remainingConstraints.end()) {
1936             nonTrunkConstraints += *it;
1937             ++it;
1938         }
1939         result += nonTrunkConstraints;
1940     }
1941
1942     return result;
1943 }
1944
1945 /*!
1946   \internal
1947
1948   Use the current vertices distance to calculate and set the geometry of
1949   each item.
1950 */
1951 void QGraphicsAnchorLayoutPrivate::setItemsGeometries(const QRectF &geom)
1952 {
1953     Q_Q(QGraphicsAnchorLayout);
1954     AnchorVertex *firstH, *secondH, *firstV, *secondV;
1955
1956     qreal top;
1957     qreal left;
1958     qreal right;
1959
1960     q->getContentsMargins(&left, &top, &right, 0);
1961     const Qt::LayoutDirection visualDir = visualDirection();
1962     if (visualDir == Qt::RightToLeft)
1963         qSwap(left, right);
1964
1965     left += geom.left();
1966     top += geom.top();
1967     right = geom.right() - right;
1968
1969     foreach (QGraphicsLayoutItem *item, items) {
1970         firstH = internalVertex(item, Qt::AnchorLeft);
1971         secondH = internalVertex(item, Qt::AnchorRight);
1972         firstV = internalVertex(item, Qt::AnchorTop);
1973         secondV = internalVertex(item, Qt::AnchorBottom);
1974
1975         QRectF newGeom;
1976         newGeom.setTop(top + firstV->distance);
1977         newGeom.setBottom(top + secondV->distance);
1978
1979         if (visualDir == Qt::LeftToRight) {
1980             newGeom.setLeft(left + firstH->distance);
1981             newGeom.setRight(left + secondH->distance);
1982         } else {
1983             newGeom.setLeft(right - secondH->distance);
1984             newGeom.setRight(right - firstH->distance);
1985         }
1986         item->setGeometry(newGeom);
1987     }
1988 }
1989
1990 /*!
1991   \internal
1992
1993   Calculate the position of each vertex based on the paths to each of
1994   them as well as the current edges sizes.
1995 */
1996 void QGraphicsAnchorLayoutPrivate::calculateVertexPositions(
1997     QGraphicsAnchorLayoutPrivate::Orientation orientation)
1998 {
1999     QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue;
2000     QSet<AnchorVertex *> visited;
2001
2002     // Get root vertex
2003     AnchorVertex *root = graph[orientation].rootVertex();
2004
2005     root->distance = 0;
2006     visited.insert(root);
2007
2008     // Add initial edges to the queue
2009     foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) {
2010         queue.enqueue(qMakePair(root, v));
2011     }
2012
2013     // Do initial calculation required by "interpolateEdge()"
2014     setupEdgesInterpolation(orientation);
2015
2016     // Traverse the graph and calculate vertex positions, we need to
2017     // visit all pairs since each of them could have a sequential
2018     // anchor inside, which hides more vertices.
2019     while (!queue.isEmpty()) {
2020         QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue();
2021         AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second);
2022
2023         // Both vertices were interpolated, and the anchor itself can't have other
2024         // anchors inside (it's not a complex anchor).
2025         if (edge->type == AnchorData::Normal && visited.contains(pair.second))
2026             continue;
2027
2028         visited.insert(pair.second);
2029         interpolateEdge(pair.first, edge, orientation);
2030
2031         QList<AnchorVertex *> adjacents = graph[orientation].adjacentVertices(pair.second);
2032         for (int i = 0; i < adjacents.count(); ++i) {
2033             if (!visited.contains(adjacents.at(i)))
2034                 queue.enqueue(qMakePair(pair.second, adjacents.at(i)));
2035         }
2036     }
2037 }
2038
2039 /*!
2040   \internal
2041
2042   Calculate interpolation parameters based on current Layout Size.
2043   Must once before calling "interpolateEdgeSize()" for each edge.
2044 */
2045 void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation(
2046     Orientation orientation)
2047 {
2048     Q_Q(QGraphicsAnchorLayout);
2049     qreal lower, upper, current;
2050
2051     if (orientation == Horizontal) {
2052         current = q->contentsRect().width();
2053     } else {
2054         current = q->contentsRect().height();
2055     }
2056
2057     if (current < sizeHints[orientation][Qt::PreferredSize]) {
2058         interpolationInterval[orientation] = MinToPreferred;
2059         lower = sizeHints[orientation][Qt::MinimumSize];
2060         upper = sizeHints[orientation][Qt::PreferredSize];
2061     } else {
2062         interpolationInterval[orientation] = PreferredToMax;
2063         lower = sizeHints[orientation][Qt::PreferredSize];
2064         upper = sizeHints[orientation][Qt::MaximumSize];
2065     }
2066
2067     if (upper == lower) {
2068         interpolationProgress[orientation] = 0;
2069     } else {
2070         interpolationProgress[orientation] = (current - lower) / (upper - lower);
2071     }
2072 }
2073
2074 /*!
2075   \internal
2076
2077   Calculate the current Edge size based on the current Layout size and the
2078   size the edge is supposed to have when:
2079
2080    - the layout is at its minimum size.
2081    - the layout is at its preferred size.
2082    - the layout is at its maximum size.
2083
2084    These three key values are calculated in advance using linear
2085    programming (more expensive) or the simplification algorithm, then
2086    subsequential resizes of the parent layout require a simple
2087    interpolation.
2088
2089    If the edge is sequential or parallel, it's possible to have more
2090    vertices to be initalized, so it calls specialized functions that
2091    will recurse back to interpolateEdge().
2092  */
2093 void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base,
2094                                                    AnchorData *edge,
2095                                                    Orientation orientation)
2096 {
2097     qreal lower, upper;
2098
2099     if (interpolationInterval[orientation] == MinToPreferred) {
2100         lower = edge->sizeAtMinimum;
2101         upper = edge->sizeAtPreferred;
2102     } else {
2103         lower = edge->sizeAtPreferred;
2104         upper = edge->sizeAtMaximum;
2105     }
2106
2107     qreal edgeDistance = (interpolationProgress[orientation] * (upper - lower)) + lower;
2108
2109     Q_ASSERT(edge->from == base || edge->to == base);
2110
2111     if (edge->from == base)
2112         edge->to->distance = base->distance + edgeDistance;
2113     else
2114         edge->from->distance = base->distance - edgeDistance;
2115
2116     // Process child anchors
2117     if (edge->type == AnchorData::Sequential)
2118         interpolateSequentialEdges(edge->from,
2119                                    static_cast<SequentialAnchorData *>(edge),
2120                                    orientation);
2121     else if (edge->type == AnchorData::Parallel)
2122         interpolateParallelEdges(edge->from,
2123                                  static_cast<ParallelAnchorData *>(edge),
2124                                  orientation);
2125 }
2126
2127 void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges(
2128     AnchorVertex *base, ParallelAnchorData *data, Orientation orientation)
2129 {
2130     // In parallels the boundary vertices are already calculate, we
2131     // just need to look for sequential groups inside, because only
2132     // them may have new vertices associated.
2133
2134     // First edge
2135     if (data->firstEdge->type == AnchorData::Sequential)
2136         interpolateSequentialEdges(base,
2137                                    static_cast<SequentialAnchorData *>(data->firstEdge),
2138                                    orientation);
2139     else if (data->firstEdge->type == AnchorData::Parallel)
2140         interpolateParallelEdges(base,
2141                                  static_cast<ParallelAnchorData *>(data->firstEdge),
2142                                  orientation);
2143
2144     // Second edge
2145     if (data->secondEdge->type == AnchorData::Sequential)
2146         interpolateSequentialEdges(base,
2147                                    static_cast<SequentialAnchorData *>(data->secondEdge),
2148                                    orientation);
2149     else if (data->secondEdge->type == AnchorData::Parallel)
2150         interpolateParallelEdges(base,
2151                                  static_cast<ParallelAnchorData *>(data->secondEdge),
2152                                  orientation);
2153 }
2154
2155 void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges(
2156     AnchorVertex *base, SequentialAnchorData *data, Orientation orientation)
2157 {
2158     AnchorVertex *prev = base;
2159
2160     // ### I'm not sure whether this assumption is safe. If not,
2161     // consider that m_edges.last() could be used instead (so
2162     // at(0) would be the one to be treated specially).
2163     Q_ASSERT(base == data->m_edges.at(0)->to || base == data->m_edges.at(0)->from);
2164
2165     // Skip the last
2166     for (int i = 0; i < data->m_edges.count() - 1; ++i) {
2167         AnchorData *child = data->m_edges.at(i);
2168         interpolateEdge(prev, child, orientation);
2169         prev = child->to;
2170     }
2171
2172     // Treat the last specially, since we already calculated it's end
2173     // vertex, so it's only interesting if it's a complex one
2174     if (data->m_edges.last()->type != AnchorData::Normal)
2175         interpolateEdge(prev, data->m_edges.last(), orientation);
2176 }
2177
2178 bool QGraphicsAnchorLayoutPrivate::solveMinMax(QList<QSimplexConstraint *> constraints,
2179                                                GraphPath path, qreal *min, qreal *max)
2180 {
2181     QSimplex simplex;
2182     bool feasible = simplex.setConstraints(constraints);
2183     if (feasible) {
2184         // Obtain the objective constraint
2185         QSimplexConstraint objective;
2186         QSet<AnchorData *>::const_iterator iter;
2187         for (iter = path.positives.constBegin(); iter != path.positives.constEnd(); ++iter)
2188             objective.variables.insert(*iter, 1.0);
2189
2190         for (iter = path.negatives.constBegin(); iter != path.negatives.constEnd(); ++iter)
2191             objective.variables.insert(*iter, -1.0);
2192
2193         simplex.setObjective(&objective);
2194
2195         // Calculate minimum values
2196         *min = simplex.solveMin();
2197
2198         // Save sizeAtMinimum results
2199         QList<QSimplexVariable *> variables = simplex.constraintsVariables();
2200         for (int i = 0; i < variables.size(); ++i) {
2201             AnchorData *ad = static_cast<AnchorData *>(variables[i]);
2202             Q_ASSERT(ad->result >= ad->minSize || qFuzzyCompare(ad->result, ad->minSize));
2203             ad->sizeAtMinimum = ad->result;
2204         }
2205
2206         // Calculate maximum values
2207         *max = simplex.solveMax();
2208
2209         // Save sizeAtMaximum results
2210         for (int i = 0; i < variables.size(); ++i) {
2211             AnchorData *ad = static_cast<AnchorData *>(variables[i]);
2212             Q_ASSERT(ad->result <= ad->maxSize || qFuzzyCompare(ad->result, ad->maxSize));
2213             ad->sizeAtMaximum = ad->result;
2214         }
2215     }
2216     return feasible;
2217 }
2218
2219 bool QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> constraints)
2220 {
2221     QList<AnchorData *> variables = getVariables(constraints);
2222     QList<QSimplexConstraint *> preferredConstraints;
2223     QList<QSimplexVariable *> preferredVariables;
2224     QSimplexConstraint objective;
2225
2226     // Fill the objective coefficients for this variable. In the
2227     // end the objective function will be
2228     //
2229     //     z = n * (A_shrink + B_shrink + ...) + (A_grower + B_grower + ...)
2230     //
2231     // where n is the number of variables that have
2232     // slacks. Note that here we use the number of variables
2233     // as coefficient, this is to mark the "shrinker slack
2234     // variable" less likely to get value than the "grower
2235     // slack variable".
2236
2237     // This will fill the values for the structural constraints
2238     // and we now fill the values for the slack constraints (one per variable),
2239     // which have this form (the constant A_pref was set when creating the slacks):
2240     //
2241     //      A + A_shrinker - A_grower = A_pref
2242     //
2243     for (int i = 0; i < variables.size(); ++i) {
2244         AnchorData *ad = static_cast<AnchorData *>(variables[i]);
2245         if (ad->skipInPreferred)
2246             continue;
2247
2248         QSimplexVariable *grower = new QSimplexVariable;
2249         QSimplexVariable *shrinker = new QSimplexVariable;
2250         QSimplexConstraint *c = new QSimplexConstraint;
2251         c->variables.insert(ad, 1.0);
2252         c->variables.insert(shrinker, 1.0);
2253         c->variables.insert(grower, -1.0);
2254         c->constant = ad->prefSize;
2255
2256         preferredConstraints += c;
2257         preferredVariables += grower;
2258         preferredVariables += shrinker;
2259
2260         objective.variables.insert(grower, 1.0);
2261         objective.variables.insert(shrinker, variables.size());
2262     }
2263
2264
2265     QSimplex *simplex = new QSimplex;
2266     bool feasible = simplex->setConstraints(constraints + preferredConstraints);
2267     if (feasible) {
2268         simplex->setObjective(&objective);
2269
2270         // Calculate minimum values
2271         simplex->solveMin();
2272
2273         // Save sizeAtPreferred results
2274         for (int i = 0; i < variables.size(); ++i) {
2275             AnchorData *ad = static_cast<AnchorData *>(variables[i]);
2276             ad->sizeAtPreferred = ad->result;
2277         }
2278
2279         // Make sure we delete the simplex solver -before- we delete the
2280         // constraints used by it.
2281         delete simplex;
2282     }
2283     // Delete constraints and variables we created.
2284     qDeleteAll(preferredConstraints);
2285     qDeleteAll(preferredVariables);
2286
2287     return feasible;
2288 }
2289
2290 bool QGraphicsAnchorLayoutPrivate::hasConflicts() const
2291 {
2292     QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate*>(this);
2293     that->calculateGraphs();
2294     return graphHasConflicts[0] || graphHasConflicts[1];
2295 }
2296
2297 #ifdef QT_DEBUG
2298 void QGraphicsAnchorLayoutPrivate::dumpGraph()
2299 {
2300     QFile file(QString::fromAscii("anchorlayout.dot"));
2301     if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
2302         qWarning("Could not write to %s", file.fileName().toLocal8Bit().constData());
2303
2304     QString str = QString::fromAscii("digraph anchorlayout {\nnode [shape=\"rect\"]\n%1}");
2305     QString dotContents = graph[0].serializeToDot();
2306     dotContents += graph[1].serializeToDot();
2307     file.write(str.arg(dotContents).toLocal8Bit());
2308
2309     file.close();
2310 }
2311 #endif
2312
2313 QT_END_NAMESPACE