1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 
43 #include <QtTest/QtTest>
44 #include <qgraphicslayoutitem.h>
45 #include <float.h>
46 #include <limits.h>
47 #include <QtGui/qgraphicswidget.h>
48 
49 class tst_QGraphicsLayoutItem : public QObject {
50 Q_OBJECT
51 
52 public slots:
53     void initTestCase();
54     void cleanupTestCase();
55     void init();
56     void cleanup();
57 
58 private slots:
59     void qgraphicslayoutitem();
60 
61     void contentsRect();
62     void effectiveSizeHint_data();
63     void effectiveSizeHint();
64     void effectiveSizeHint2_data();
65     void effectiveSizeHint2();
66     void getContentsMargins();
67     void isLayout_data();
68     void isLayout();
69     void maximumSize();
70     void minimumSize();
71     void parentLayoutItem_data();
72     void parentLayoutItem();
73     void preferredSize();
74     void setMaximumSize_data();
75     void setMaximumSize();
76     void setMinimumSize_data();
77     void setMinimumSize();
78     void setPreferredSize_data();
79     void setPreferredSize();
80     void setSizePolicy_data();
81     void setPreferredSize2();
82     void setSizePolicy();
83 };
84 
85 // Subclass that exposes the protected functions.
86 class SubQGraphicsLayoutItem : public QGraphicsLayoutItem {
87 public:
SubQGraphicsLayoutItem(QGraphicsLayoutItem * par=0,bool layout=false)88     SubQGraphicsLayoutItem(QGraphicsLayoutItem *par = 0, bool layout = false)
89             : QGraphicsLayoutItem(par, layout), updateGeometryCalled(0)
90         {}
91 
92     // QGraphicsLayoutItem::geometry is a pure virtual function
geometry() const93     QRectF geometry() const
94         { return QRectF(); }
95 
96     // QGraphicsLayoutItem::setGeometry is a pure virtual function
setGeometry(QRectF const & rect)97     void setGeometry(QRectF const& rect)
98         { Q_UNUSED(rect); }
99 
100     // QGraphicsLayoutItem::sizeHint is a pure virtual function
sizeHint(Qt::SizeHint which,QSizeF const & constraint=QSizeF ()) const101     QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
102         { Q_UNUSED(which); Q_UNUSED(constraint); return QSizeF(); }
103 
updateGeometry()104     void updateGeometry()
105         { updateGeometryCalled++; QGraphicsLayoutItem::updateGeometry(); }
106     int updateGeometryCalled;
107 
108 };
109 
110 class RectWidget : public QGraphicsWidget
111 {
112 public:
RectWidget(QGraphicsItem * parent=0)113     RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent), m_fnConstraint(fn2000_div_w) {}
114 
115 
sizeHint(Qt::SizeHint which,const QSizeF & constraint=QSizeF ()) const116     QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
117     {
118         if (constraint.width() < 0 && constraint.height() < 0 && m_sizeHints[which].isValid()) {
119             return m_sizeHints[which];
120         }
121         if (m_fnConstraint) {
122             return m_fnConstraint(which, constraint);
123         }
124         return QGraphicsWidget::sizeHint(which, constraint);
125     }
126 
setSizeHint(Qt::SizeHint which,const QSizeF & size)127     void setSizeHint(Qt::SizeHint which, const QSizeF &size) {
128         m_sizeHints[which] = size;
129         updateGeometry();
130     }
131 
setConstraintFunction(QSizeF (* fnConstraint)(Qt::SizeHint,const QSizeF &))132     void setConstraintFunction(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &)) {
133         m_fnConstraint = fnConstraint;
134     }
135 
136     QSizeF m_sizeHints[Qt::NSizeHints];
137     QSizeF (*m_fnConstraint)(Qt::SizeHint, const QSizeF &);
138 
fn2000_div_w(Qt::SizeHint,const QSizeF & constraint=QSizeF ())139     static QSizeF fn2000_div_w(Qt::SizeHint /*which*/, const QSizeF &constraint = QSizeF()) {
140         return QSizeF(constraint.width(), 2000.0/constraint.width());
141     }
142 };
143 
144 // This will be called before the first test function is executed.
145 // It is only called once.
initTestCase()146 void tst_QGraphicsLayoutItem::initTestCase()
147 {
148 }
149 
150 // This will be called after the last test function is executed.
151 // It is only called once.
cleanupTestCase()152 void tst_QGraphicsLayoutItem::cleanupTestCase()
153 {
154 }
155 
156 // This will be called before each test function is executed.
init()157 void tst_QGraphicsLayoutItem::init()
158 {
159 }
160 
161 // This will be called after every test function.
cleanup()162 void tst_QGraphicsLayoutItem::cleanup()
163 {
164 }
165 
qgraphicslayoutitem()166 void tst_QGraphicsLayoutItem::qgraphicslayoutitem()
167 {
168     SubQGraphicsLayoutItem layoutItem;
169     layoutItem.contentsRect();
170     layoutItem.effectiveSizeHint(Qt::MinimumSize);
171     layoutItem.geometry();
172     QCOMPARE(layoutItem.isLayout(), false);
173     layoutItem.maximumSize();
174     layoutItem.minimumSize();
175     QCOMPARE(layoutItem.parentLayoutItem(), (QGraphicsLayoutItem*)0);
176     layoutItem.preferredSize();
177     layoutItem.sizePolicy();
178     layoutItem.sizeHint(Qt::MinimumSize);
179 }
180 
181 // QRectF contentsRect() const public
contentsRect()182 void tst_QGraphicsLayoutItem::contentsRect()
183 {
184     SubQGraphicsLayoutItem layoutItem;
185     QRectF f = layoutItem.contentsRect();
186     QCOMPARE(f, QRectF(QPoint(), QSizeF(0, 0)));
187 }
Q_DECLARE_METATYPE(Qt::SizeHint)188 Q_DECLARE_METATYPE(Qt::SizeHint)
189 void tst_QGraphicsLayoutItem::effectiveSizeHint_data()
190 {
191     QTest::addColumn<Qt::SizeHint>("sizeHint");
192     QTest::addColumn<QSizeF>("constraint");
193     for (int i = 0; i < 15; ++i) {
194         QTestData &data = QTest::newRow(QString("%1").arg(i).toLatin1());
195         switch(i % 5) {
196         case 0: data << Qt::MinimumSize; break;
197         case 1: data << Qt::PreferredSize; break;
198         case 2: data << Qt::MaximumSize; break;
199         case 3: data << Qt::MinimumDescent; break;
200         case 4: data << Qt::NSizeHints; break;
201         }
202         switch(i % 3) {
203         case 0: data << QSizeF(-1, -1); break;
204         case 1: data << QSizeF(0, 0); break;
205         case 2: data << QSizeF(10, 10); break;
206         }
207     }
208 }
209 
210 // QSizeF effectiveSizeHint(Qt::SizeHint which, QSizeF const& constraint = QSize()) const public
effectiveSizeHint()211 void tst_QGraphicsLayoutItem::effectiveSizeHint()
212 {
213     QFETCH(Qt::SizeHint, sizeHint);
214     QFETCH(QSizeF, constraint);
215     SubQGraphicsLayoutItem layoutItem;
216     QSizeF r = layoutItem.effectiveSizeHint(sizeHint, constraint);
217     if (constraint.width() != -1)
218         QCOMPARE(r.width(), constraint.width());
219     if (constraint.height() != -1)
220         QCOMPARE(r.height(), constraint.height());
221 }
222 
223 
effectiveSizeHint2_data()224 void tst_QGraphicsLayoutItem::effectiveSizeHint2_data()
225 {
226     QTest::addColumn<QSizeF>("minimumSize");
227     QTest::addColumn<QSizeF>("preferredSize");
228     QTest::addColumn<QSizeF>("maximumSize");
229     QTest::addColumn<QSizeF>("minimumSizeHint");
230     QTest::addColumn<QSizeF>("preferredSizeHint");
231     QTest::addColumn<QSizeF>("maximumSizeHint");
232 
233     QTest::addColumn<QSizeF>("inputConstraint");
234     QTest::addColumn<QSizeF>("expectedMinimumESH");
235     QTest::addColumn<QSizeF>("expectedPreferredESH");
236     QTest::addColumn<QSizeF>("expectedMaximumESH");
237 
238     QTest::newRow("P1-a")
239             << QSizeF(  6,   4) << QSizeF( 60,  40) << QSizeF( 600, 400)
240             << QSizeF( -1,  -1) << QSizeF( -1,  -1) << QSizeF( -1,  -1)
241             << QSizeF(-1, -1)
242             << QSizeF(6, 4)     << QSizeF( 60,  40) << QSizeF(600, 400);
243 
244     QTest::newRow("P1-hfw-1")
245             << QSizeF( -1,  -1) << QSizeF( -1,  -1) << QSizeF( -1,  -1)
246             << QSizeF(  6,   4) << QSizeF( 60,  40) << QSizeF(600, 400)
247             << QSizeF(200, -1)
248             << QSizeF(200, 10)  << QSizeF(200,  10) << QSizeF(200,  10);
249 
250     QTest::newRow("P1-hfw-2")
251             << QSizeF(  6,  -1) << QSizeF( 60,  -1) << QSizeF(600,  -1)
252             << QSizeF( -1,  -1) << QSizeF( -1,  -1) << QSizeF( -1,  -1)
253             << QSizeF(200, -1)
254             << QSizeF(200, 10)  << QSizeF(200,  10) << QSizeF(200,  10);
255 
256     // constraint is bigger than max width
257     QTest::newRow("P1-hfw-3")
258             << QSizeF(  5,  -1) << QSizeF( 50,  -1) << QSizeF(500,  -1)
259             << QSizeF( -1,  -1) << QSizeF( -1,  -1) << QSizeF( -1,  -1)
260             << QSizeF(600,  -1)
261             << QSizeF(500,   4)  << QSizeF(500,   4) << QSizeF(500,   4);
262 
263 }
264 
effectiveSizeHint2()265 void tst_QGraphicsLayoutItem::effectiveSizeHint2()
266 {
267     QFETCH(QSizeF, minimumSize);
268     QFETCH(QSizeF, preferredSize);
269     QFETCH(QSizeF, maximumSize);
270     QFETCH(QSizeF, minimumSizeHint);
271     QFETCH(QSizeF, preferredSizeHint);
272     QFETCH(QSizeF, maximumSizeHint);
273 
274     QFETCH(QSizeF, inputConstraint);
275     QFETCH(QSizeF, expectedMinimumESH);
276     QFETCH(QSizeF, expectedPreferredESH);
277     QFETCH(QSizeF, expectedMaximumESH);
278 
279     RectWidget *item = new RectWidget;
280     item->setMinimumSize(minimumSize);
281     item->setPreferredSize(preferredSize);
282     item->setMaximumSize(maximumSize);
283     item->setSizeHint(Qt::MinimumSize, minimumSizeHint);
284     item->setSizeHint(Qt::PreferredSize, preferredSizeHint);
285     item->setSizeHint(Qt::MaximumSize, maximumSizeHint);
286 
287     QCOMPARE(item->effectiveSizeHint(Qt::MinimumSize, inputConstraint), expectedMinimumESH);
288     QCOMPARE(item->effectiveSizeHint(Qt::PreferredSize, inputConstraint), expectedPreferredESH);
289     QCOMPARE(item->effectiveSizeHint(Qt::MaximumSize, inputConstraint), expectedMaximumESH);
290 
291 }
292 
293 
294 // void getContentsMargins(qreal* left, qreal* top, qreal* right, qreal* bottom) const public
getContentsMargins()295 void tst_QGraphicsLayoutItem::getContentsMargins()
296 {
297     SubQGraphicsLayoutItem layoutItem;
298     qreal left;
299     qreal top;
300     qreal right;
301     qreal bottom;
302     layoutItem.getContentsMargins(&left, &top, &right, &bottom);
303     QCOMPARE(left, (qreal)0);
304     QCOMPARE(top, (qreal)0);
305     QCOMPARE(right, (qreal)0);
306     QCOMPARE(bottom, (qreal)0);
307 }
308 
isLayout_data()309 void tst_QGraphicsLayoutItem::isLayout_data()
310 {
311     QTest::addColumn<bool>("isLayout");
312     QTest::newRow("no") << false;
313     QTest::newRow("yes") << true;
314 }
315 
316 // bool isLayout() const public
isLayout()317 void tst_QGraphicsLayoutItem::isLayout()
318 {
319     QFETCH(bool, isLayout);
320     SubQGraphicsLayoutItem layoutItem(0, isLayout);
321     QCOMPARE(layoutItem.isLayout(), isLayout);
322 }
323 
324 // QSizeF maximumSize() const public
maximumSize()325 void tst_QGraphicsLayoutItem::maximumSize()
326 {
327     SubQGraphicsLayoutItem layoutItem;
328     QCOMPARE(layoutItem.maximumSize(), QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
329     // layoutItem.effectiveSizeHint(Qt::MaximumSize);
330 }
331 
332 // QSizeF minimumSize() const public
minimumSize()333 void tst_QGraphicsLayoutItem::minimumSize()
334 {
335     SubQGraphicsLayoutItem layoutItem;
336     QCOMPARE(layoutItem.minimumSize(), QSizeF(0, 0));
337     // layoutItem.effectiveSizeHint(Qt::MinimumSize);
338 }
339 
parentLayoutItem_data()340 void tst_QGraphicsLayoutItem::parentLayoutItem_data()
341 {
342     QTest::addColumn<bool>("parent");
343     QTest::newRow("no") << false;
344     QTest::newRow("yes") << true;
345 }
346 
347 // QGraphicsLayoutItem* parentLayoutItem() const public
parentLayoutItem()348 void tst_QGraphicsLayoutItem::parentLayoutItem()
349 {
350     QFETCH(bool, parent);
351     SubQGraphicsLayoutItem parentLayout;
352     SubQGraphicsLayoutItem layoutItem(parent ? &parentLayout : 0);
353     QCOMPARE(layoutItem.parentLayoutItem(), static_cast<QGraphicsLayoutItem*>( parent ? &parentLayout : 0));
354 }
355 
356 // QSizeF preferredSize() const public
preferredSize()357 void tst_QGraphicsLayoutItem::preferredSize()
358 {
359     SubQGraphicsLayoutItem layoutItem;
360     QCOMPARE(layoutItem.preferredSize(), QSizeF(0, 0));
361     // layoutItem.effectiveSizeHint(Qt::PreferredSize));
362 }
363 
setMaximumSize_data()364 void tst_QGraphicsLayoutItem::setMaximumSize_data()
365 {
366     QTest::addColumn<QSizeF>("size");
367     QTest::addColumn<QSizeF>("outputSize");
368     QTest::newRow("-1") << QSizeF(-1, -1) << QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
369     QTest::newRow("0") << QSizeF(0, 0) << QSizeF(0, 0);
370     QTest::newRow("10") << QSizeF(10, 10) << QSizeF(10, 10);
371 }
372 
373 // void setMaximumSize(QSizeF const& size) public
setMaximumSize()374 void tst_QGraphicsLayoutItem::setMaximumSize()
375 {
376     QFETCH(QSizeF, size);
377     QFETCH(QSizeF, outputSize);
378     SubQGraphicsLayoutItem layoutItem;
379     QSizeF oldSize = layoutItem.maximumSize();
380     layoutItem.setMaximumSize(size);
381     if (size.isValid())
382         QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
383     else
384         QVERIFY(!layoutItem.updateGeometryCalled);
385     layoutItem.setMinimumSize(1, 1);
386 
387     QVERIFY(layoutItem.maximumSize().width() <= outputSize.width());
388     QVERIFY(layoutItem.maximumSize().height() <= outputSize.height());
389     QVERIFY(layoutItem.minimumSize().width() <= outputSize.width());
390     QVERIFY(layoutItem.minimumSize().height() <= outputSize.height());
391     QVERIFY(layoutItem.preferredSize().width() <= outputSize.width());
392     QVERIFY(layoutItem.preferredSize().height() <= outputSize.height());
393 }
394 
setMinimumSize_data()395 void tst_QGraphicsLayoutItem::setMinimumSize_data()
396 {
397     QTest::addColumn<QSizeF>("size");
398     QTest::addColumn<QSizeF>("outputSize");
399     QTest::newRow("-1") << QSizeF(-1, -1) << QSizeF(0, 0);
400     QTest::newRow("0") << QSizeF(0, 0) << QSizeF(0, 0);
401     QTest::newRow("10") << QSizeF(10, 10) << QSizeF(10, 10);
402 }
403 
404 // void setMinimumSize(QSizeF const& size) public
setMinimumSize()405 void tst_QGraphicsLayoutItem::setMinimumSize()
406 {
407     QFETCH(QSizeF, size);
408     QFETCH(QSizeF, outputSize);
409     SubQGraphicsLayoutItem layoutItem;
410     QSizeF oldSize = layoutItem.minimumSize();
411 
412     layoutItem.setMinimumSize(size);
413     if (size.isValid()) {
414         QEXPECT_FAIL("0", "updateGeometry() is called when it doesn't have to be.", Continue);
415         QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
416     } else {
417         QVERIFY(!layoutItem.updateGeometryCalled);
418     }
419     layoutItem.setMaximumSize(5, 5);
420     QEXPECT_FAIL("10", "layoutItem.maximumSize().width() < size.width()", Abort);
421     QVERIFY(layoutItem.maximumSize().width() >= size.width());
422     QVERIFY(layoutItem.maximumSize().height() >= size.height());
423     QVERIFY(layoutItem.minimumSize().width() >= size.width());
424     QVERIFY(layoutItem.minimumSize().height() >= size.height());
425     QVERIFY(layoutItem.preferredSize().width() >= size.width());
426     QVERIFY(layoutItem.preferredSize().height() >= size.height());
427 }
428 
setPreferredSize_data()429 void tst_QGraphicsLayoutItem::setPreferredSize_data()
430 {
431     QTest::addColumn<QSizeF>("size");
432     QTest::newRow("-1") << QSizeF(-1, -1);
433     QTest::newRow("0") << QSizeF(0, 0);
434     QTest::newRow("10") << QSizeF(10, 10);
435 }
436 
437 // void setPreferredSize(QSizeF const& size) public
setPreferredSize()438 void tst_QGraphicsLayoutItem::setPreferredSize()
439 {
440     QFETCH(QSizeF, size);
441     SubQGraphicsLayoutItem layoutItem;
442     QSizeF oldSize = layoutItem.preferredSize();
443     layoutItem.setPreferredSize(size);
444     if (size.isValid())
445        QCOMPARE(layoutItem.preferredSize(), size);
446 
447     if (size.isValid()) {
448         QEXPECT_FAIL("0", "updateGeometry() is called when it doesn't have to be.", Continue);
449         QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
450     } else {
451         QVERIFY(!layoutItem.updateGeometryCalled);
452     }
453 }
454 
setPreferredSize2()455 void tst_QGraphicsLayoutItem::setPreferredSize2()
456 {
457     SubQGraphicsLayoutItem layoutItem;
458     layoutItem.setPreferredSize(QSizeF(30, -1));
459     QCOMPARE(layoutItem.preferredWidth(), qreal(30));
460 }
461 
setSizePolicy_data()462 void tst_QGraphicsLayoutItem::setSizePolicy_data()
463 {
464     QTest::addColumn<QSizePolicy>("policy");
465     QTest::newRow("default") << QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, QSizePolicy::DefaultType);
466     QTest::newRow("rand") << QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
467 }
468 
469 // void setSizePolicy(QSizePolicy const& policy) public
setSizePolicy()470 void tst_QGraphicsLayoutItem::setSizePolicy()
471 {
472     QFETCH(QSizePolicy, policy);
473     SubQGraphicsLayoutItem layoutItem;
474     QSizePolicy defaultPolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType);
475     QCOMPARE(layoutItem.sizePolicy(), defaultPolicy);
476 
477     layoutItem.setSizePolicy(policy);
478     QCOMPARE(layoutItem.sizePolicy(), policy);
479     QCOMPARE(layoutItem.updateGeometryCalled, (defaultPolicy == policy) ? 0 : 1);
480 }
481 
482 QTEST_MAIN(tst_QGraphicsLayoutItem)
483 #include "tst_qgraphicslayoutitem.moc"
484 
485