|
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 documentation 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 <QtTest/QtTest> |
|
43 #include <QtGui/qgraphicsanchorlayout.h> |
|
44 #include <QtGui/qgraphicslinearlayout.h> |
|
45 #include <QtGui/qgraphicswidget.h> |
|
46 #include <QtGui/qgraphicsview.h> |
|
47 |
|
48 class tst_QGraphicsAnchorLayout : public QObject |
|
49 { |
|
50 Q_OBJECT |
|
51 public: |
|
52 tst_QGraphicsAnchorLayout() {} |
|
53 ~tst_QGraphicsAnchorLayout() {} |
|
54 |
|
55 private slots: |
|
56 void s60_hard_complex_data(); |
|
57 void s60_hard_complex(); |
|
58 void linearVsAnchorSizeHints_data(); |
|
59 void linearVsAnchorSizeHints(); |
|
60 void linearVsAnchorSetGeometry_data(); |
|
61 void linearVsAnchorSetGeometry(); |
|
62 void linearVsAnchorNested_data(); |
|
63 void linearVsAnchorNested(); |
|
64 }; |
|
65 |
|
66 |
|
67 class RectWidget : public QGraphicsWidget |
|
68 { |
|
69 public: |
|
70 RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent){} |
|
71 |
|
72 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
|
73 { |
|
74 Q_UNUSED(option); |
|
75 Q_UNUSED(widget); |
|
76 painter->drawRoundRect(rect()); |
|
77 painter->drawLine(rect().topLeft(), rect().bottomRight()); |
|
78 painter->drawLine(rect().bottomLeft(), rect().topRight()); |
|
79 } |
|
80 }; |
|
81 |
|
82 static QGraphicsWidget *createItem(const QSizeF &minimum = QSizeF(100.0, 100.0), |
|
83 const QSizeF &preferred = QSize(150.0, 100.0), |
|
84 const QSizeF &maximum = QSizeF(200.0, 100.0), |
|
85 const QString &name = QString()) |
|
86 { |
|
87 QGraphicsWidget *w = new RectWidget; |
|
88 w->setMinimumSize(minimum); |
|
89 w->setPreferredSize(preferred); |
|
90 w->setMaximumSize(maximum); |
|
91 w->setData(0, name); |
|
92 return w; |
|
93 } |
|
94 |
|
95 static void setAnchor(QGraphicsAnchorLayout *l, |
|
96 QGraphicsLayoutItem *firstItem, |
|
97 Qt::AnchorPoint firstEdge, |
|
98 QGraphicsLayoutItem *secondItem, |
|
99 Qt::AnchorPoint secondEdge, |
|
100 qreal spacing) |
|
101 { |
|
102 QGraphicsAnchor *anchor = l->addAnchor(firstItem, firstEdge, secondItem, secondEdge); |
|
103 anchor->setSpacing(spacing); |
|
104 } |
|
105 |
|
106 void tst_QGraphicsAnchorLayout::s60_hard_complex_data() |
|
107 { |
|
108 QTest::addColumn<int>("whichSizeHint"); |
|
109 QTest::newRow("minimumSizeHint") |
|
110 << int(Qt::MinimumSize); |
|
111 QTest::newRow("preferredSizeHint") |
|
112 << int(Qt::PreferredSize); |
|
113 QTest::newRow("maximumSizeHint") |
|
114 << int(Qt::MaximumSize); |
|
115 // Add it as a reference to see how much overhead the body of effectiveSizeHint takes. |
|
116 QTest::newRow("noSizeHint") |
|
117 << -1; |
|
118 } |
|
119 |
|
120 void tst_QGraphicsAnchorLayout::s60_hard_complex() |
|
121 { |
|
122 QFETCH(int, whichSizeHint); |
|
123 |
|
124 // Test for "hard" complex case, taken from wiki |
|
125 // https://cwiki.nokia.com/S60QTUI/AnchorLayoutComplexCases |
|
126 QSizeF min(0, 10); |
|
127 QSizeF pref(50, 10); |
|
128 QSizeF max(100, 10); |
|
129 |
|
130 QGraphicsWidget *a = createItem(min, pref, max, "a"); |
|
131 QGraphicsWidget *b = createItem(min, pref, max, "b"); |
|
132 QGraphicsWidget *c = createItem(min, pref, max, "c"); |
|
133 QGraphicsWidget *d = createItem(min, pref, max, "d"); |
|
134 QGraphicsWidget *e = createItem(min, pref, max, "e"); |
|
135 QGraphicsWidget *f = createItem(min, pref, max, "f"); |
|
136 QGraphicsWidget *g = createItem(min, pref, max, "g"); |
|
137 |
|
138 QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; |
|
139 l->setContentsMargins(0, 0, 0, 0); |
|
140 |
|
141 //<!-- Trunk --> |
|
142 setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 10); |
|
143 setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 10); |
|
144 setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft, 10); |
|
145 setAnchor(l, c, Qt::AnchorRight, d, Qt::AnchorLeft, 10); |
|
146 setAnchor(l, d, Qt::AnchorRight, l, Qt::AnchorRight, 10); |
|
147 |
|
148 //<!-- Above trunk --> |
|
149 setAnchor(l, b, Qt::AnchorLeft, e, Qt::AnchorLeft, 10); |
|
150 setAnchor(l, e, Qt::AnchorRight, d, Qt::AnchorLeft, 10); |
|
151 |
|
152 //<!-- Below trunk --> |
|
153 setAnchor(l, a, Qt::AnchorHorizontalCenter, g, Qt::AnchorLeft, 10); |
|
154 setAnchor(l, g, Qt::AnchorRight, f, Qt::AnchorHorizontalCenter, 10); |
|
155 setAnchor(l, c, Qt::AnchorLeft, f, Qt::AnchorLeft, 10); |
|
156 setAnchor(l, f, Qt::AnchorRight, d, Qt::AnchorRight, 10); |
|
157 |
|
158 //<!-- vertical is simpler --> |
|
159 setAnchor(l, l, Qt::AnchorTop, e, Qt::AnchorTop, 0); |
|
160 setAnchor(l, e, Qt::AnchorBottom, a, Qt::AnchorTop, 0); |
|
161 setAnchor(l, e, Qt::AnchorBottom, b, Qt::AnchorTop, 0); |
|
162 setAnchor(l, e, Qt::AnchorBottom, c, Qt::AnchorTop, 0); |
|
163 setAnchor(l, e, Qt::AnchorBottom, d, Qt::AnchorTop, 0); |
|
164 setAnchor(l, a, Qt::AnchorBottom, f, Qt::AnchorTop, 0); |
|
165 setAnchor(l, a, Qt::AnchorBottom, b, Qt::AnchorBottom, 0); |
|
166 setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorBottom, 0); |
|
167 setAnchor(l, a, Qt::AnchorBottom, d, Qt::AnchorBottom, 0); |
|
168 setAnchor(l, f, Qt::AnchorBottom, g, Qt::AnchorTop, 0); |
|
169 setAnchor(l, g, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); |
|
170 |
|
171 // It won't query the size hint if it already has a size set. |
|
172 // If only one of the sizes is unset it will query sizeHint only of for that hint type. |
|
173 l->setMinimumSize(60,40); |
|
174 l->setPreferredSize(220,40); |
|
175 l->setMaximumSize(240,40); |
|
176 |
|
177 switch (whichSizeHint) { |
|
178 case Qt::MinimumSize: |
|
179 l->setMinimumSize(-1, -1); |
|
180 break; |
|
181 case Qt::PreferredSize: |
|
182 l->setPreferredSize(-1, -1); |
|
183 break; |
|
184 case Qt::MaximumSize: |
|
185 l->setMaximumSize(-1, -1); |
|
186 break; |
|
187 default: |
|
188 break; |
|
189 } |
|
190 |
|
191 QSizeF sizeHint; |
|
192 // warm up instruction cache |
|
193 l->invalidate(); |
|
194 sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint); |
|
195 // ...then measure... |
|
196 QBENCHMARK { |
|
197 l->invalidate(); |
|
198 sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint); |
|
199 } |
|
200 } |
|
201 |
|
202 static QGraphicsLayout* createLayouts(int whichLayout) |
|
203 { |
|
204 QSizeF min(0, 10); |
|
205 QSizeF pref(50, 10); |
|
206 QSizeF max(100, 10); |
|
207 |
|
208 QGraphicsWidget *a = createItem(min, pref, max, "a"); |
|
209 QGraphicsWidget *b = createItem(min, pref, max, "b"); |
|
210 QGraphicsWidget *c = createItem(min, pref, max, "c"); |
|
211 QGraphicsWidget *d = createItem(min, pref, max, "d"); |
|
212 |
|
213 QGraphicsLayout *l; |
|
214 if (whichLayout == 0) { |
|
215 l = new QGraphicsLinearLayout; |
|
216 QGraphicsLinearLayout *linear = static_cast<QGraphicsLinearLayout *>(l); |
|
217 linear->setContentsMargins(0, 0, 0, 0); |
|
218 |
|
219 linear->addItem(a); |
|
220 linear->addItem(b); |
|
221 linear->addItem(c); |
|
222 linear->addItem(d); |
|
223 } else { |
|
224 l = new QGraphicsAnchorLayout; |
|
225 QGraphicsAnchorLayout *anchor = static_cast<QGraphicsAnchorLayout *>(l); |
|
226 anchor->setContentsMargins(0, 0, 0, 0); |
|
227 |
|
228 // Horizontal |
|
229 setAnchor(anchor, anchor, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); |
|
230 setAnchor(anchor, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0); |
|
231 setAnchor(anchor, b, Qt::AnchorRight, c, Qt::AnchorLeft, 0); |
|
232 setAnchor(anchor, c, Qt::AnchorRight, d, Qt::AnchorLeft, 0); |
|
233 setAnchor(anchor, d, Qt::AnchorRight, anchor, Qt::AnchorRight, 0); |
|
234 |
|
235 // Vertical |
|
236 anchor->addAnchors(anchor, a, Qt::Vertical); |
|
237 anchor->addAnchors(anchor, b, Qt::Vertical); |
|
238 anchor->addAnchors(anchor, c, Qt::Vertical); |
|
239 anchor->addAnchors(anchor, d, Qt::Vertical); |
|
240 } |
|
241 |
|
242 return l; |
|
243 } |
|
244 |
|
245 void tst_QGraphicsAnchorLayout::linearVsAnchorSizeHints_data() |
|
246 { |
|
247 QTest::addColumn<int>("whichLayout"); |
|
248 QTest::addColumn<int>("whichSizeHint"); |
|
249 |
|
250 QTest::newRow("QGraphicsLinearLayout::minimum") |
|
251 << 0 << int(Qt::MinimumSize); |
|
252 QTest::newRow("QGraphicsLinearLayout::preferred") |
|
253 << 0 << int(Qt::PreferredSize); |
|
254 QTest::newRow("QGraphicsLinearLayout::maximum") |
|
255 << 0 << int(Qt::MaximumSize); |
|
256 QTest::newRow("QGraphicsLinearLayout::noSizeHint") |
|
257 << 0 << -1; |
|
258 |
|
259 QTest::newRow("QGraphicsAnchorLayout::minimum") |
|
260 << 1 << int(Qt::MinimumSize); |
|
261 QTest::newRow("QGraphicsAnchorLayout::preferred") |
|
262 << 1 << int(Qt::PreferredSize); |
|
263 QTest::newRow("QGraphicsAnchorLayout::maximum") |
|
264 << 1 << int(Qt::MaximumSize); |
|
265 QTest::newRow("QGraphicsAnchorLayout::noSizeHint") |
|
266 << 1 << -1; |
|
267 } |
|
268 |
|
269 void tst_QGraphicsAnchorLayout::linearVsAnchorSizeHints() |
|
270 { |
|
271 QFETCH(int, whichSizeHint); |
|
272 QFETCH(int, whichLayout); |
|
273 |
|
274 QGraphicsLayout *l = createLayouts(whichLayout); |
|
275 |
|
276 QSizeF sizeHint; |
|
277 // warm up instruction cache |
|
278 l->invalidate(); |
|
279 sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint); |
|
280 // ...then measure... |
|
281 |
|
282 QBENCHMARK { |
|
283 l->invalidate(); |
|
284 sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint); |
|
285 } |
|
286 } |
|
287 |
|
288 void tst_QGraphicsAnchorLayout::linearVsAnchorSetGeometry_data() |
|
289 { |
|
290 QTest::addColumn<int>("whichLayout"); |
|
291 |
|
292 QTest::newRow("QGraphicsLinearLayout") |
|
293 << 0; |
|
294 QTest::newRow("QGraphicsAnchorLayout") |
|
295 << 1; |
|
296 } |
|
297 |
|
298 void tst_QGraphicsAnchorLayout::linearVsAnchorSetGeometry() |
|
299 { |
|
300 QFETCH(int, whichLayout); |
|
301 |
|
302 QGraphicsLayout *l = createLayouts(whichLayout); |
|
303 |
|
304 QRectF sizeHint; |
|
305 qreal maxWidth; |
|
306 qreal increment; |
|
307 // warm up instruction cache |
|
308 l->invalidate(); |
|
309 sizeHint.setSize(l->effectiveSizeHint(Qt::MinimumSize)); |
|
310 maxWidth = l->effectiveSizeHint(Qt::MaximumSize).width(); |
|
311 increment = (maxWidth - sizeHint.width()) / 100; |
|
312 l->setGeometry(sizeHint); |
|
313 // ...then measure... |
|
314 |
|
315 QBENCHMARK { |
|
316 l->invalidate(); |
|
317 for (qreal width = sizeHint.width(); width <= maxWidth; width += increment) { |
|
318 sizeHint.setWidth(width); |
|
319 l->setGeometry(sizeHint); |
|
320 } |
|
321 } |
|
322 } |
|
323 |
|
324 void tst_QGraphicsAnchorLayout::linearVsAnchorNested_data() |
|
325 { |
|
326 QTest::addColumn<int>("whichLayout"); |
|
327 QTest::newRow("LinearLayout") |
|
328 << 0; |
|
329 QTest::newRow("AnchorLayout setup with null-anchors knot") |
|
330 << 1; |
|
331 QTest::newRow("AnchorLayout setup easy to simplificate") |
|
332 << 2; |
|
333 } |
|
334 |
|
335 void tst_QGraphicsAnchorLayout::linearVsAnchorNested() |
|
336 { |
|
337 QFETCH(int, whichLayout); |
|
338 |
|
339 QSizeF min(10, 10); |
|
340 QSizeF pref(80, 80); |
|
341 QSizeF max(150, 150); |
|
342 |
|
343 QGraphicsWidget *a = createItem(min, pref, max, "a"); |
|
344 QGraphicsWidget *b = createItem(min, pref, max, "b"); |
|
345 QGraphicsWidget *c = createItem(min, pref, max, "c"); |
|
346 QGraphicsWidget *d = createItem(min, pref, max, "d"); |
|
347 |
|
348 QGraphicsLayout *layout; |
|
349 |
|
350 if (whichLayout == 0) { |
|
351 QGraphicsLinearLayout *linear1 = new QGraphicsLinearLayout; |
|
352 QGraphicsLinearLayout *linear2 = new QGraphicsLinearLayout(Qt::Vertical); |
|
353 QGraphicsLinearLayout *linear3 = new QGraphicsLinearLayout; |
|
354 |
|
355 linear1->addItem(a); |
|
356 linear1->addItem(linear2); |
|
357 linear2->addItem(b); |
|
358 linear2->addItem(linear3); |
|
359 linear3->addItem(c); |
|
360 linear3->addItem(d); |
|
361 |
|
362 layout = linear1; |
|
363 } else if (whichLayout == 1) { |
|
364 QGraphicsAnchorLayout *anchor = new QGraphicsAnchorLayout; |
|
365 |
|
366 // A |
|
367 anchor->addCornerAnchors(a, Qt::TopLeftCorner, anchor, Qt::TopLeftCorner); |
|
368 anchor->addCornerAnchors(a, Qt::TopRightCorner, b, Qt::TopLeftCorner); |
|
369 anchor->addCornerAnchors(a, Qt::BottomLeftCorner, anchor, Qt::BottomLeftCorner); |
|
370 anchor->addCornerAnchors(a, Qt::BottomRightCorner, c, Qt::BottomLeftCorner); |
|
371 |
|
372 // B |
|
373 anchor->addCornerAnchors(b, Qt::TopRightCorner, anchor, Qt::TopRightCorner); |
|
374 anchor->addCornerAnchors(b, Qt::BottomLeftCorner, c, Qt::TopLeftCorner); |
|
375 anchor->addCornerAnchors(b, Qt::BottomRightCorner, d, Qt::TopRightCorner); |
|
376 |
|
377 // C |
|
378 anchor->addCornerAnchors(c, Qt::TopRightCorner, d, Qt::TopLeftCorner); |
|
379 anchor->addCornerAnchors(c, Qt::BottomRightCorner, d, Qt::BottomLeftCorner); |
|
380 |
|
381 // D |
|
382 anchor->addCornerAnchors(d, Qt::BottomRightCorner, anchor, Qt::BottomRightCorner); |
|
383 |
|
384 layout = anchor; |
|
385 } else { |
|
386 QGraphicsAnchorLayout *anchor = new QGraphicsAnchorLayout; |
|
387 |
|
388 // A |
|
389 anchor->addAnchor(a, Qt::AnchorLeft, anchor, Qt::AnchorLeft); |
|
390 anchor->addAnchors(a, anchor, Qt::Vertical); |
|
391 anchor->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); |
|
392 anchor->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft); |
|
393 |
|
394 // B |
|
395 anchor->addAnchor(b, Qt::AnchorTop, anchor, Qt::AnchorTop); |
|
396 anchor->addAnchor(b, Qt::AnchorRight, anchor, Qt::AnchorRight); |
|
397 anchor->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop); |
|
398 anchor->addAnchor(b, Qt::AnchorBottom, d, Qt::AnchorTop); |
|
399 |
|
400 // C |
|
401 anchor->addAnchor(c, Qt::AnchorRight, d, Qt::AnchorLeft); |
|
402 anchor->addAnchor(c, Qt::AnchorBottom, anchor, Qt::AnchorBottom); |
|
403 |
|
404 // D |
|
405 anchor->addAnchor(d, Qt::AnchorRight, anchor, Qt::AnchorRight); |
|
406 anchor->addAnchor(d, Qt::AnchorBottom, anchor, Qt::AnchorBottom); |
|
407 |
|
408 layout = anchor; |
|
409 } |
|
410 |
|
411 QSizeF sizeHint; |
|
412 // warm up instruction cache |
|
413 layout->invalidate(); |
|
414 sizeHint = layout->effectiveSizeHint(Qt::PreferredSize); |
|
415 |
|
416 // ...then measure... |
|
417 QBENCHMARK { |
|
418 // To ensure that all sizeHints caches are invalidated in |
|
419 // the LinearLayout setup, we must call updateGeometry on the |
|
420 // children. If we didn't, only the top level layout would be |
|
421 // re-calculated. |
|
422 static_cast<QGraphicsLayoutItem *>(a)->updateGeometry(); |
|
423 static_cast<QGraphicsLayoutItem *>(b)->updateGeometry(); |
|
424 static_cast<QGraphicsLayoutItem *>(c)->updateGeometry(); |
|
425 static_cast<QGraphicsLayoutItem *>(d)->updateGeometry(); |
|
426 layout->invalidate(); |
|
427 sizeHint = layout->effectiveSizeHint(Qt::PreferredSize); |
|
428 } |
|
429 } |
|
430 |
|
431 QTEST_MAIN(tst_QGraphicsAnchorLayout) |
|
432 |
|
433 #include "tst_qgraphicsanchorlayout.moc" |