QtBase  v6.3.1
tst_qgraphicslinearlayout.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 
30 #include <QTest>
31 #include <qgraphicslinearlayout.h>
32 #include <qgraphicsproxywidget.h>
33 #include <qgraphicswidget.h>
34 #include <qgraphicsscene.h>
35 #include <qgraphicsview.h>
36 #include <qapplication.h>
37 #include <QtWidgets/qstyle.h>
38 #include <QtWidgets/qproxystyle.h>
39 
42 
43 private slots:
44  void initTestCase();
45  void qgraphicslinearlayout_data();
46  void qgraphicslinearlayout();
47 
48  void alignment_data();
49  void alignment();
50  void count_data();
51  void count();
52  void dump_data();
53  void dump();
54  void geometry_data();
55  void geometry();
56  void insertItem_data();
57  void insertItem();
58  void insertStretch_data();
59  void insertStretch();
60  void invalidate_data();
61  void invalidate();
62  void itemAt_data();
63  void itemAt();
64  void itemAt_visualOrder();
65  void orientation_data();
66  void orientation();
67  void removeAt_data();
68  void removeAt();
69  void removeItem_data();
70  void removeItem();
71  void setGeometry_data();
72  void setGeometry();
73  void defaultSpacing();
74  void setSpacing_data();
75  void setSpacing();
76  void setItemSpacing_data();
77  void setItemSpacing();
78  void itemSpacing();
79  void setStretchFactor_data();
80  void setStretchFactor();
81  void testStretch();
82  void defaultStretchFactors_data();
83  void defaultStretchFactors();
84  void sizeHint_data();
85  void sizeHint();
86  void updateGeometry();
87  void layoutDirection();
88  void removeLayout();
89  void avoidRecursionInInsertItem();
90  void styleInfoLeak();
91  void testAlignmentInLargerLayout();
92  void testOffByOneInLargerLayout();
93  void testDefaultAlignment();
94  void combineSizePolicies();
95  void hiddenItems();
96 
97  // Task specific tests
98  void task218400_insertStretchCrash();
99 };
100 
101 // Subclass that exposes the protected functions.
103 public:
106  layoutRequest(0),
108  { }
109 
110  void widgetEvent(QEvent *e) override
111  {
112  switch (e->type()) {
115  break;
117  layoutRequest++;
118  break;
121  break;
122  default:
123  break;
124  }
125 
127  }
128 
132 };
133 
134 // This will be called before the first test function is executed.
135 // It is only called once.
136 void tst_QGraphicsLinearLayout::initTestCase()
137 {
138  // since the style will influence the results, we have to ensure
139  // that the tests are run using the same style on all platforms
140  QApplication::setStyle("windows");
141 }
142 
143 class RectWidget : public QGraphicsWidget
144 {
145 public:
147 
149  {
150  Q_UNUSED(option);
151  Q_UNUSED(widget);
154  }
155 
156  void setSizeHint(Qt::SizeHint which, const QSizeF &size) {
157  m_sizeHints[which] = size;
158  updateGeometry();
159  }
160 
161  virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override
162  {
163  if (m_sizeHints[which].isValid()) {
164  return m_sizeHints[which];
165  }
166  return QGraphicsWidget::sizeHint(which, constraint);
167  }
168 
169  // Initializer {} is a workaround for gcc bug 68949
172 };
173 
174 
176 void tst_QGraphicsLinearLayout::qgraphicslinearlayout_data()
177 {
178  QTest::addColumn<Qt::Orientation>("orientation");
179  QTest::newRow("vertical") << Qt::Vertical;
180  QTest::newRow("horizontal") << Qt::Horizontal;
181 }
182 
183 void tst_QGraphicsLinearLayout::qgraphicslinearlayout()
184 {
185  QFETCH(Qt::Orientation, orientation);
186  SubQGraphicsLinearLayout layout(orientation);
187  QVERIFY(layout.isLayout());
188 
189  qApp->processEvents();
190  QCOMPARE(layout.graphicsSceneResize, 0);
191  QCOMPARE(layout.layoutRequest, 0);
192  QCOMPARE(layout.layoutDirectionChange, 0);
193 
194  layout.setOrientation(Qt::Vertical);
195  layout.orientation();
196  QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert null item");
197  QCOMPARE(layout.count(), 0);
198  layout.addItem(0);
199  QCOMPARE(layout.count(), 0);
200  layout.addStretch(0);
201  QCOMPARE(layout.count(), 0);
202  QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert null item");
203  layout.insertItem(0, 0);
204  layout.insertStretch(0, 0);
205  layout.removeItem(0);
206  QCOMPARE(layout.count(), 0);
207  layout.setSpacing(0);
208  layout.spacing();
209  QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::setStretchFactor: cannot assign a stretch factor to a null item");
210  layout.setStretchFactor(0, 0);
211  QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::setStretchFactor: cannot return a stretch factor for a null item");
212  layout.stretchFactor(0);
214  QCOMPARE(layout.alignment(0), 0);
216  layout.geometry();
217  QCOMPARE(layout.count(), 0);
218  layout.invalidate();
220 }
221 
223 void tst_QGraphicsLinearLayout::alignment_data()
224 {
225  QTest::addColumn<Qt::Orientation>("orientation");
226  QTest::addColumn<QSize>("newSize");
227  QTest::newRow("h-defaultsize") << Qt::Horizontal << QSize();
228  QTest::newRow("v-defaultsize") << Qt::Vertical << QSize();
229  QTest::newRow("h-300") << Qt::Horizontal << QSize(300,100);
230  QTest::newRow("v-300") << Qt::Vertical << QSize(100, 300);
231 }
232 
233 void tst_QGraphicsLinearLayout::alignment()
234 {
235  QFETCH(Qt::Orientation, orientation);
236  QFETCH(QSize, newSize);
237 
238  //if (alignment == Qt::AlignAbsolute)
239  // QApplication::setLayoutDirection(Qt::RightToLeft);
242  view.setSceneRect(0, 0, 320, 240);
247 
248  static const Qt::Alignment alignmentsToTest[] = {
249  Qt::Alignment{},
253  Qt::AlignTop,
257  Qt::Alignment{},
261  Qt::AlignTop,
265  };
266 
267  int i;
268  bool addWidget = true;
269  for (size_t i = 0; i < sizeof(alignmentsToTest)/sizeof(Qt::Alignment); ++i) {
270  QGraphicsLayoutItem *loutItem;
271  Qt::Alignment align = alignmentsToTest[i];
272  if (!align && i > 0)
273  addWidget = false;
274  if (addWidget)
275  loutItem = new RectWidget(widget, QBrush(Qt::blue));
276  else {
279  lay->setContentsMargins(0,0,0,0);
281  if (align) {
282  w->setMinimumSize(QSizeF(10,10));
283  w->setMaximumSize(QSizeF(10,10));
284  } else {
285  w->setMinimumSize(QSizeF(50,50));
286  w->setMaximumSize(QSizeF(50,50));
287  }
288  lay->addItem(w);
289  loutItem = lay;
290  }
291  if (align) {
292  loutItem->setMinimumSize(QSizeF(10,10));
293  loutItem->setMaximumSize(QSizeF(10,10));
294  } else {
295  loutItem->setMinimumSize(QSizeF(50,50));
296  loutItem->setMaximumSize(QSizeF(50,50));
297  }
298  layout.addItem(loutItem);
299  layout.setAlignment(loutItem, align);
300 
301  }
302  layout.setContentsMargins(0,0,0,0);
303  int spacing = 1;
305  if (newSize.isValid())
306  widget->resize(newSize);
307  view.show();
308  widget->show();
311 
312  int x = 0;
313  int y = 0;
314  for (i = 0; i < layout.count(); ++i) {
317 
318  int w = 10;
319  int h = 10;
320  switch(align) {
321  case Qt::AlignLeft:
322  break;
323  case Qt::AlignRight:
324  if (orientation == Qt::Vertical)
325  x += 40;
326  break;
327  case Qt::AlignHCenter:
328  if (orientation == Qt::Vertical)
329  x += 20;
330  break;
331  case Qt::AlignTop:
332  break;
333  case Qt::AlignBottom:
334  if (orientation == Qt::Horizontal)
335  y += 40;
336  break;
337  case Qt::AlignVCenter:
338  if (orientation == Qt::Horizontal)
339  y += 20;
340  break;
341  case Qt::AlignCenter:
342  if (orientation == Qt::Horizontal)
343  y += 20;
344  else
345  x += 20;
346  break;
347  case 0:
348  w = 50;
349  h = 50;
350  break;
351  default:
352  break;
353  }
354  QRectF expectedGeometry(x, y, w, h);
355  QCOMPARE(item->geometry(), expectedGeometry);
356  if (orientation == Qt::Horizontal) {
357  x += w;
358  y = 0;
359  x += spacing;
360  } else {
361  x = 0;
362  y += h;
363  y += spacing;
364  }
365  }
366 }
367 
368 void tst_QGraphicsLinearLayout::count_data()
369 {
370  QTest::addColumn<int>("itemCount");
371  QTest::addColumn<int>("layoutCount");
372  QTest::newRow("0, 0") << 0 << 0;
373  QTest::newRow("0, 5") << 0 << 5;
374  QTest::newRow("5, 0") << 5 << 0;
375  QTest::newRow("5, 5") << 5 << 5;
376 }
377 
378 // int count() const public
379 void tst_QGraphicsLinearLayout::count()
380 {
381  QFETCH(int, itemCount);
382  QFETCH(int, layoutCount);
383 
385  QCOMPARE(layout.count(), 0);
386 
387  for (int i = 0; i < itemCount; ++i)
389  QCOMPARE(layout.count(), itemCount);
390 
391  for (int i = 0; i < layoutCount; ++i)
393  QCOMPARE(layout.count(), itemCount + layoutCount);
394 
395  // see also removeAt()
396 }
397 
398 void tst_QGraphicsLinearLayout::dump_data()
399 {
400  QTest::addColumn<int>("itemCount");
401  QTest::addColumn<int>("layoutCount");
402  for (int i = -1; i < 3; ++i) {
403  const QByteArray iB = QByteArray::number(i);
404  QTest::newRow((iB + ", 0, 0").constData()) << 0 << 0;
405  QTest::newRow((iB + ", 0, 5").constData()) << 5 << 5;
406  QTest::newRow((iB + ", 5, 0").constData()) << 5 << 5;
407  QTest::newRow((iB + ", 5, 5").constData()) << 5 << 5;
408  }
409 }
410 
411 // void dump(int indent = 0) const public
412 void tst_QGraphicsLinearLayout::dump()
413 {
414  QFETCH(int, itemCount);
415  QFETCH(int, layoutCount);
417  for (int i = 0; i < itemCount; ++i)
419  for (int i = 0; i < layoutCount; ++i)
421 }
422 
423 void tst_QGraphicsLinearLayout::geometry_data()
424 {
425  QTest::addColumn<int>("itemCount");
426  QTest::addColumn<int>("layoutCount");
427  QTest::addColumn<int>("itemSpacing");
428  QTest::addColumn<int>("spacing");
429  QTest::addColumn<Qt::Orientation>("orientation");
430  QTest::addColumn<QRectF>("rect");
431 
432  QTest::newRow("null") << 0 << 0 << 0 << 0 << Qt::Horizontal << QRectF();
433 
434  QTest::newRow("one item") << 1 << 0 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 10, 10);
435  QTest::newRow("one layout") << 0 << 1 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 10, 10);
436  QTest::newRow("two h") << 1 << 1 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 20, 10);
437  QTest::newRow("two v") << 1 << 1 << 0 << 0 << Qt::Vertical << QRectF(0, 0, 10, 20);
438 
439  QTest::newRow("two w/itemspacing") << 1 << 1 << 5 << 0 << Qt::Horizontal << QRectF(0, 0, 25, 10);
440  QTest::newRow("two w/spacing") << 1 << 1 << 8 << 0 << Qt::Horizontal << QRectF(0, 0, 28, 10);
441 
442  QTest::newRow("two w/itemspacing v") << 1 << 1 << 5 << 0 << Qt::Vertical << QRectF(0, 0, 10, 25);
443  QTest::newRow("two w/spacing v") << 1 << 1 << 8 << 0 << Qt::Vertical << QRectF(0, 0, 10, 28);
444 }
445 
446 // QRectF geometry() const public
447 void tst_QGraphicsLinearLayout::geometry()
448 {
449  QFETCH(int, itemCount);
450  QFETCH(int, layoutCount);
451  QFETCH(int, itemSpacing);
452  QFETCH(int, spacing);
453  QFETCH(Qt::Orientation, orientation);
454  QFETCH(QRectF, rect);
461  widget->setContentsMargins(0, 0, 0, 0);
462  for (int i = 0; i < itemCount; ++i)
464  for (int i = 0; i < layoutCount; ++i)
466 
467  for (int i = 0; i < layout.count(); ++i) {
469  item->setMaximumSize(10, 10);
470  item->setMinimumSize(10, 10);
471  }
472  layout.setItemSpacing(0, itemSpacing);
474  layout.setContentsMargins(0, 0, 0, 0);
475 
476  widget->show();
477  view.show();
480  delete widget;
481 }
482 
483 void tst_QGraphicsLinearLayout::insertItem_data()
484 {
485  QTest::addColumn<int>("itemCount");
486  QTest::addColumn<int>("layoutCount");
487  QTest::addColumn<int>("insertItemAt");
488  QTest::addColumn<bool>("isWidget");
489  for (int i = -1; i < 4; ++i) {
490  const QByteArray iB = QByteArray::number(i);
491  for (int j = 0; j < 2; ++j) {
492  const QByteArray postFix = iB + ' ' + QByteArray::number(j);
493  QTest::newRow(("0, 0, " + postFix).constData()) << 0 << 0 << i << (bool)j;
494  QTest::newRow(("1, 0, " + postFix).constData()) << 1 << 0 << i << (bool)j;
495  QTest::newRow(("0, 1, " + postFix).constData()) << 0 << 1 << i << (bool)j;
496  QTest::newRow(("2, 2, " + postFix).constData()) << 2 << 2 << i << (bool)j;
497  }
498  }
499 }
500 
501 // void insertItem(int index, QGraphicsLayoutItem* item) public
502 void tst_QGraphicsLinearLayout::insertItem()
503 {
504  QFETCH(int, itemCount);
505  QFETCH(int, layoutCount);
506  QFETCH(int, insertItemAt);
507  QFETCH(bool, isWidget);
508  if (insertItemAt > layoutCount + itemCount)
509  return;
510 
512  for (int i = 0; i < itemCount; ++i)
514  for (int i = 0; i < layoutCount; ++i)
516 
517  QGraphicsLayoutItem *item = nullptr;
518  if (isWidget)
519  item = new QGraphicsWidget;
520  else
522 
523  QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
524  layout.insertItem(insertItemAt, item);
525  QCOMPARE(layout.count(), itemCount + layoutCount + 1);
526 
527  if (insertItemAt >= 0 && (itemCount + layoutCount >= 0)) {
528  QCOMPARE(layout.itemAt(insertItemAt), item);
529  }
530 
531  layout.activate();
532  QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
533  if (!isWidget && layout.count() == 1)
534  QCOMPARE(oldSizeHint.width(), newSizeHint.width());
535  else if (itemCount + layoutCount > 0)
536  QVERIFY(oldSizeHint.width() < newSizeHint.width());
537 }
538 
539 void tst_QGraphicsLinearLayout::insertStretch_data()
540 {
541  QTest::addColumn<int>("itemCount");
542  QTest::addColumn<int>("layoutCount");
543  QTest::addColumn<int>("insertItemAt");
544  QTest::addColumn<int>("stretch");
545  for (int i = -1; i < 4; ++i) {
546  const QByteArray iB = QByteArray::number(i);
547  for (int j = 0; j < 2; ++j) {
548  const QByteArray postFix = iB + ' ' + QByteArray::number(j);
549  QTest::newRow(("0, 0, " + postFix).constData()) << 0 << 0 << i << j;
550  QTest::newRow(("1, 0, " + postFix).constData()) << 1 << 0 << i << j;
551  QTest::newRow(("0, 1, " + postFix).constData()) << 0 << 1 << i << j;
552  QTest::newRow(("2, 2, " + postFix).constData()) << 2 << 2 << i << j;
553  }
554  }
555 }
556 
557 // void insertStretch(int index, int stretch = 1) public
558 void tst_QGraphicsLinearLayout::insertStretch()
559 {
560  QFETCH(int, itemCount);
561  QFETCH(int, layoutCount);
562  QFETCH(int, insertItemAt);
563  QFETCH(int, stretch);
564  if (insertItemAt > layoutCount + itemCount)
565  return;
566 
572 
574  QGraphicsWidget *item = nullptr;
575  for (int i = 0; i < itemCount; ++i) {
576  item = new RectWidget;
577  item->setMinimumSize(10, 10);
578  item->setPreferredSize(25, 25);
579  item->setMaximumSize(50, 50);
580  layout->addItem(item);
581  }
582  for (int i = 0; i < layoutCount; ++i) {
583  item = new RectWidget;
584  item->setMinimumSize(10, 10);
585  item->setPreferredSize(25, 25);
586  item->setMaximumSize(50, 50);
588  sublayout->addItem(item);
589  layout->addItem(sublayout);
590  }
592  layout->insertStretch(insertItemAt, stretch);
593  QCOMPARE(layout->count(), itemCount + layoutCount);
594 
595  layout->activate();
596  view.show();
597  widget->show();
598 
599  int prevStretch = -2;
600  int prevWidth = -2;
601  widget->resize((layoutCount + itemCount) * 25 + 25, 25);
602  for (int i = 0; i < layout->count(); ++i) {
604  if (prevStretch != -2) {
605  if (layout->stretchFactor(item) >= prevStretch) {
606  QVERIFY(item->geometry().width() >= prevWidth);
607  } else {
608  QVERIFY(item->geometry().width() < prevWidth);
609  }
610  }
611  prevStretch = layout->stretchFactor(item);
612  prevWidth = (int)(item->geometry().width());
613  }
614  }
615 
616  delete widget;
617 }
618 
619 void tst_QGraphicsLinearLayout::invalidate_data()
620 {
621  QTest::addColumn<int>("count");
622  QTest::newRow("0") << 0;
623  QTest::newRow("1") << 1;
624  QTest::newRow("2") << 2;
625  QTest::newRow("3") << 3;
626 }
627 
628 // void invalidate() public
629 void tst_QGraphicsLinearLayout::invalidate()
630 {
631  QFETCH(int, count);
638  widget->setContentsMargins(0, 0, 0, 0);
639  layout.setContentsMargins(0, 0, 0, 0);
640  view.show();
641  widget->show();
643  qApp->processEvents();
644  layout.layoutRequest = 0;
645 
646  layout.setContentsMargins(1, 2, 3, 4);
648  QCOMPARE(layout.layoutRequest, 1);
649 
650  layout.setOrientation(Qt::Vertical);
652  QCOMPARE(layout.layoutRequest, 2);
653 
654  for (int i = 0; i < count; ++i)
655  layout.invalidate(); // Event is compressed, should only get one layoutrequest
657  QCOMPARE(layout.layoutRequest, count ? 3 : 2);
658  delete widget;
659 }
660 
661 void tst_QGraphicsLinearLayout::itemAt_data()
662 {
663  QTest::addColumn<int>("index");
664  QTest::newRow("0") << 0;
665  QTest::newRow("1") << 1;
666  QTest::newRow("2") << 2;
667 }
668 
669 // QGraphicsLayoutItem* itemAt(int index) const public
670 void tst_QGraphicsLinearLayout::itemAt()
671 {
672  // see also the insertItem() etc tests
673  QFETCH(int, index);
675  for (int i = 0; i < 3; ++i)
677 
678  QVERIFY(layout.itemAt(index) != 0);
679 }
680 
681 void tst_QGraphicsLinearLayout::itemAt_visualOrder()
682 {
684 
686  l->addItem(w1);
687 
689  l->addItem(w3);
690 
692  l->insertItem(0, w0);
693 
695  l->insertItem(2, w2);
696 
697  QCOMPARE(l->itemAt(0), static_cast<QGraphicsLayoutItem*>(w0));
698  QCOMPARE(l->itemAt(1), static_cast<QGraphicsLayoutItem*>(w1));
699  QCOMPARE(l->itemAt(2), static_cast<QGraphicsLayoutItem*>(w2));
700  QCOMPARE(l->itemAt(3), static_cast<QGraphicsLayoutItem*>(w3));
701 }
702 
703 void tst_QGraphicsLinearLayout::orientation_data()
704 {
705  QTest::addColumn<Qt::Orientation>("orientation");
706  QTest::newRow("vertical") << Qt::Vertical;
707  QTest::newRow("horizontal") << Qt::Horizontal;
708 }
709 
710 // Qt::Orientation orientation() const public
711 void tst_QGraphicsLinearLayout::orientation()
712 {
713  QFETCH(Qt::Orientation, orientation);
714 
718  Qt::Orientation initialOrientation = (orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical);
719  SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout(initialOrientation));
722  widget->setContentsMargins(0, 0, 0, 0);
723  layout.setContentsMargins(0, 0, 0, 0);
724  int i;
725  int itemCount = 3;
726  for (i = 0; i < itemCount; ++i)
728  QCOMPARE(layout.orientation(), initialOrientation);
729  QList<qreal> positions;
730 
731  view.show();
732  widget->show();
733  qApp->processEvents();
734 
735  for (i = 0; i < itemCount; ++i) {
736  QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
737  qreal pos;
738  if (initialOrientation == Qt::Horizontal)
739  pos = item->pos().x();
740  else
741  pos = item->pos().y();
742  positions.append(pos);
743 
744  }
745 
746  layout.setOrientation(orientation);
747  QCOMPARE(layout.orientation(), orientation);
748  // important to resize to preferredsize when orientation is switched
749  widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
750  qApp->processEvents();
751  for (i = 0; i < positions.count(); ++i) {
752  QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
753  if (initialOrientation == Qt::Horizontal)
754  QCOMPARE(item->pos().y(), positions.at(i));
755  else
756  QCOMPARE(item->pos().x(), positions.at(i));
757  }
758 }
759 
760 void tst_QGraphicsLinearLayout::removeAt_data()
761 {
762  QTest::addColumn<int>("itemCount");
763  QTest::addColumn<int>("layoutCount");
764  QTest::addColumn<int>("removeItemAt");
765  QTest::addColumn<Qt::Orientation>("orientation");
766  for (int i = -1; i < 4; ++i) {
767  const QByteArray iB = QByteArray::number(i);
768  for (int k = 0; k < 2; ++k) {
769  Qt::Orientation orientation = (k == 0) ? Qt::Vertical : Qt::Horizontal;
770  QTest::newRow(("0, 0, " + iB).constData()) << 0 << 0 << i << orientation;
771  QTest::newRow(("1, 0, " + iB).constData()) << 1 << 0 << i << orientation;
772  QTest::newRow(("0, 1, " + iB).constData()) << 0 << 1 << i << orientation;
773  QTest::newRow(("2, 2, " + iB).constData()) << 2 << 2 << i << orientation;
774  }
775  }
776 }
777 
778 // void removeAt(int index) public
779 void tst_QGraphicsLinearLayout::removeAt()
780 {
781  QFETCH(int, itemCount);
782  QFETCH(int, layoutCount);
783  QFETCH(int, removeItemAt);
784  QFETCH(Qt::Orientation, orientation);
785  if (removeItemAt >= layoutCount + itemCount)
786  return;
787 
788  SubQGraphicsLinearLayout layout(orientation);
789  for (int i = 0; i < itemCount; ++i)
791  for (int i = 0; i < layoutCount; ++i)
793  QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
794 
795  QGraphicsLayoutItem *w = nullptr;
796  if (removeItemAt >= 0 && removeItemAt < layout.count())
797  w = layout.itemAt(removeItemAt);
798  if (w) {
799  QGraphicsLayoutItem *wParent = w->parentLayoutItem();
800  QCOMPARE(wParent, static_cast<QGraphicsLayoutItem *>(&layout));
801  layout.removeAt(removeItemAt);
802  wParent = w->parentLayoutItem();
803  QCOMPARE(wParent, nullptr);
804  delete w;
805  }
806  QCOMPARE(layout.count(), itemCount + layoutCount - (w ? 1 : 0));
807 
808  layout.activate();
809  QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
810  if (orientation == Qt::Horizontal)
811  QVERIFY(oldSizeHint.width() >= newSizeHint.width());
812  else
813  QVERIFY(oldSizeHint.height() >= newSizeHint.height());
814 }
815 
816 void tst_QGraphicsLinearLayout::removeItem_data()
817 {
818  QTest::addColumn<int>("itemCount");
819  QTest::addColumn<int>("layoutCount");
820  QTest::addColumn<int>("removeItemAt");
821  for (int i = -1; i < 4; ++i) {
822  const QByteArray iB = QByteArray::number(i);
823  QTest::newRow(("0, 0, " + iB).constData()) << 0 << 0 << i;
824  QTest::newRow(("1, 0, " + iB).constData()) << 1 << 0 << i;
825  QTest::newRow(("0, 1, " + iB).constData()) << 0 << 1 << i;
826  QTest::newRow(("2, 2, " + iB).constData()) << 2 << 2 << i;
827  }
828 }
829 
830 // void removeItem(QGraphicsLayoutItem* item) public
831 void tst_QGraphicsLinearLayout::removeItem()
832 {
833  QFETCH(int, itemCount);
834  QFETCH(int, layoutCount);
835  QFETCH(int, removeItemAt);
836  if (removeItemAt >= layoutCount + itemCount)
837  return;
838 
840  for (int i = 0; i < itemCount; ++i)
842  for (int i = 0; i < layoutCount; ++i)
844 
845  QGraphicsLayoutItem *w = nullptr;
846  if (removeItemAt >= 0 && removeItemAt < layout.count())
847  w = layout.itemAt(removeItemAt);
848  QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
849  if (w) {
851  delete w;
852  }
853  QCOMPARE(layout.count(), itemCount + layoutCount - (w ? 1 : 0));
854 
855  layout.activate();
856  QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
857  QVERIFY(oldSizeHint.width() >= newSizeHint.width());
858 }
859 
860 void tst_QGraphicsLinearLayout::setGeometry_data()
861 {
862  QTest::addColumn<QRectF>("rect");
863  QTest::newRow("null") << QRectF();
864  QTest::newRow("small") << QRectF(0, 0, 10, 10);
865 }
866 
867 // void setGeometry(QRectF const& rect) public
868 void tst_QGraphicsLinearLayout::setGeometry()
869 {
870  QFETCH(QRectF, rect);
877  widget->setContentsMargins(0, 0, 0, 0);
878  layout.setContentsMargins(0, 0, 0, 0);
879  layout.setMaximumSize(100, 100);
880  view.show();
881  widget->show();
885  // see also geometry()
886  delete widget;
887 }
888 
889 class LayoutStyle : public QProxyStyle
890 {
891 public:
893  : QProxyStyle(key),
895 
896  virtual int pixelMetric(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0) const override
897  {
899  return horizontalSpacing;
900  } else if (pm == QStyle::PM_LayoutVerticalSpacing && verticalSpacing >= 0) {
901  return verticalSpacing;
902  }
904  }
905 
908 };
909 
910 void tst_QGraphicsLinearLayout::defaultSpacing()
911 {
914  LayoutStyle *style = new LayoutStyle(QLatin1String("windows"));
915  style->horizontalSpacing = 5;
916  style->verticalSpacing = 3;
917  LayoutStyle *style2 = new LayoutStyle(QLatin1String("windows"));
918  style2->horizontalSpacing = 25;
919  style2->verticalSpacing = 23;
920 
923 
924  // Horizontal layout
927  Q_ASSERT(widget->style());
929  layout->setContentsMargins(0, 0, 0, 0);
930  view.show();
931 
932  for (int i = 0; i < 2; ++i) {
934  layout->addItem(w);
935  }
936 
937  // Horizontal layout
938  qreal styleSpacing = (qreal)style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
939  QCOMPARE(styleSpacing, qreal(5));
940  QCOMPARE(styleSpacing, layout->spacing());
941  QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).width(), qreal(105));
942  style->horizontalSpacing = 15;
943  // If the style method changes return value, the layout must be invalidated by the application
944  layout->invalidate();
945  styleSpacing = (qreal)style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
946  QCOMPARE(styleSpacing, qreal(15));
947  QCOMPARE(styleSpacing, layout->spacing());
948  QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).width(), qreal(115));
949  widget->setStyle(style2);
950  // If the style itself changes, the layout will pick that up
951  QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).width(), qreal(125));
952  QCOMPARE(layout->spacing(), qreal(25));
953 
954  // Vertical layout
956  layout->setOrientation(Qt::Vertical);
957  styleSpacing = (qreal)style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
958  QCOMPARE(styleSpacing, qreal(3));
959  QCOMPARE(styleSpacing, layout->spacing());
960  QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).height(), qreal(103));
961  style->verticalSpacing = 13;
962  // If the style method changes return value, the layout must be invalidated by the application
963  layout->invalidate();
964  styleSpacing = (qreal)style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
965  QCOMPARE(styleSpacing, qreal(13));
966  QCOMPARE(styleSpacing, layout->spacing());
967  QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).height(), qreal(113));
968  widget->setStyle(style2);
969  // If the style itself changes, the layout will pick that up
970  QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).height(), qreal(123));
971  QCOMPARE(layout->spacing(), qreal(23));
972 
973 
974  delete widget;
975 }
976 
977 void tst_QGraphicsLinearLayout::setSpacing_data()
978 {
979  QTest::addColumn<qreal>("spacing");
980  QTest::newRow("0") << (qreal)0;
981  QTest::newRow("5") << (qreal)5;
982  QTest::newRow("3.3") << (qreal)3.3;
983  QTest::newRow("-4.3") << (qreal)4.3;
984 }
985 
986 // void setSpacing(qreal spacing) public
987 void tst_QGraphicsLinearLayout::setSpacing()
988 {
989  QFETCH(qreal, spacing);
990 
997  layout.setContentsMargins(0, 0, 0, 0);
998 
999  // The remainder of this test is only applicable if the style uses uniform spacing
1000  qreal oldSpacing = layout.spacing();
1001  if (oldSpacing != -1) {
1002  for (int i = 0; i < 3; ++i)
1004  QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize);
1005 
1008 
1009  view.show();
1010  widget->show();
1012  QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize);
1013 
1014  QCOMPARE(oldSizeHint.width() - oldSpacing * 2, newSizeHint.width() - spacing * 2);
1015  }
1016  delete widget;
1017 }
1018 
1019 void tst_QGraphicsLinearLayout::setItemSpacing_data()
1020 {
1021  QTest::addColumn<int>("index");
1022  QTest::addColumn<int>("spacing");
1023 
1024  QTest::newRow("0 at 0") << 0 << 0;
1025  QTest::newRow("10 at 0") << 0 << 10;
1026  QTest::newRow("10 at 1") << 1 << 10;
1027  QTest::newRow("10 at the end") << 4 << 10;
1028 }
1029 
1030 void tst_QGraphicsLinearLayout::setItemSpacing()
1031 {
1032  QFETCH(int, index);
1033  QFETCH(int, spacing);
1034 
1039  scene.addItem(widget);
1041  layout->setContentsMargins(0, 0, 0, 0);
1042  for (int i = 0; i < 5; ++i) {
1044  layout->addItem(w);
1045  }
1046  QSizeF oldSizeHint = layout->sizeHint(Qt::PreferredSize);
1047  qreal oldSpacing = 0;
1048  if (index < layout->count() - 1)
1049  oldSpacing = layout->spacing();
1050  else
1051  spacing = 0;
1052 
1053  layout->setItemSpacing(index, spacing);
1054  view.show();
1056  QSizeF newSizeHint = layout->sizeHint(Qt::PreferredSize);
1057 
1058  // The remainder of this test is only applicable if the style uses uniform spacing
1059  if (oldSpacing >= 0) {
1060  QCOMPARE(newSizeHint.width() - spacing, oldSizeHint.width() - oldSpacing);
1061  }
1062  delete widget;
1063 }
1064 
1065 void tst_QGraphicsLinearLayout::itemSpacing()
1066 {
1071  scene.addItem(widget);
1073  layout->setContentsMargins(0, 0, 0, 0);
1074  for (int i = 0; i < 5; ++i) {
1076  layout->addItem(w);
1077  }
1078 
1079  // Check defaults
1080  qreal defaultSpacing = layout->spacing();
1081  if (defaultSpacing >= 0) {
1082  QCOMPARE(layout->itemSpacing(0), defaultSpacing);
1083  } else {
1084  // all widgets are the same, so the spacing should be uniform
1085  QCOMPARE(layout->itemSpacing(0), layout->itemSpacing(1));
1086  }
1087 
1088  layout->setItemSpacing(1, 42);
1089  QCOMPARE(layout->itemSpacing(1), qreal(42));
1090 
1091  // try to unset
1092  layout->setItemSpacing(1, -1);
1093  QCOMPARE(layout->itemSpacing(1), defaultSpacing);
1094 
1095  delete widget;
1096 }
1097 
1121 
1122 void tst_QGraphicsLinearLayout::setStretchFactor_data()
1123 {
1124  QTest::addColumn<qreal>("totalSize");
1125  QTest::addColumn<IntList>("stretches");
1126 
1127  QTest::newRow(QString("60 [1,2]").toLatin1()) << qreal(60.0) << (IntList() << 1 << 2);
1128  QTest::newRow(QString("60 [1,2,3]").toLatin1()) << qreal(60.0) << (IntList() << 1 << 2 << 3);
1129  QTest::newRow(QString("120 [1,2,3,6]").toLatin1()) << qreal(120.0) << (IntList() << 1 << 2 << 3 << 6);
1130 }
1131 
1132 // void setStretchFactor(QGraphicsLayoutItem* item, int stretch) public
1133 void tst_QGraphicsLinearLayout::setStretchFactor()
1134 {
1135  QFETCH(qreal, totalSize);
1136  QFETCH(IntList, stretches);
1141  scene.addItem(widget);
1142  widget->setLayout(&layout);
1143  layout.setContentsMargins(0, 0, 0, 0);
1144  layout.setSpacing(0.0);
1145  widget->setContentsMargins(0, 0, 0, 0);
1146 
1147 
1148  int i;
1149  for (i = 0; i < stretches.count(); ++i) {
1151  item->setMinimumSize(5,5);
1152  item->setPreferredSize(10,5);
1153  item->setMaximumSize(50,5);
1154  layout.addItem(item);
1155  layout.setStretchFactor(item, stretches.at(i));
1156  }
1157 
1158  widget->resize(totalSize, 10);
1160 
1161  view.show();
1162  widget->show();
1163 
1164  qreal firstStretch = -1;
1165  qreal firstExtent = -1.;
1166  qreal sumExtent = 0;
1167  for (i = 0; i < stretches.count(); ++i) {
1168  QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
1169  qreal extent = item->size().width();
1170  qreal stretch = (qreal)stretches.at(i);
1171  if (firstStretch != -1 && firstExtent != -1) {
1172  // The resulting widths does not correspond linearly to the stretch factors.
1173  if (stretch == firstStretch)
1174  QCOMPARE(extent, firstExtent);
1175  else if (stretch > firstStretch)
1176  QVERIFY(extent > firstExtent);
1177  else
1178  QVERIFY(extent < firstExtent);
1179  } else {
1180  firstStretch = (qreal)stretch;
1181  firstExtent = extent;
1182  }
1183  sumExtent+= extent;
1184  }
1185  QCOMPARE(sumExtent, totalSize);
1186 
1187  delete widget;
1188 }
1189 
1190 void tst_QGraphicsLinearLayout::testStretch()
1191 {
1194  Q_UNUSED(view);
1196 
1197  scene.addItem(form);
1198  form->setMinimumSize(600, 600);
1199  form->setMaximumSize(600, 600);
1201  QGraphicsWidget *w1 = new RectWidget;
1202  w1->setPreferredSize(100,100);
1203  w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
1204  QGraphicsWidget *w2 = new RectWidget;
1205  w2->setPreferredSize(200,200);
1206  w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
1207  layout->setSpacing(0);
1208  layout->setContentsMargins(0, 0, 0, 0);
1209  layout->addItem(w1);
1210  layout->addStretch(2);
1211  layout->addItem(w2);
1212  QCOMPARE(layout->count(), 2);
1213  QCOMPARE(layout->itemAt(0), w1);
1214  QCOMPARE(layout->itemAt(1), w2);
1215  layout->activate();
1216 
1217  //view->setSceneRect(-50, -50, 800, 800);
1218  //view->show();
1219  //QVERIFY(QTest::qWaitForWindowExposed(view));
1220  QCOMPARE(form->geometry().size(), QSizeF(600,600));
1221  QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
1222  QCOMPARE(w2->geometry(), QRectF(400, 0, 200, 200));
1223 }
1224 
1225 void tst_QGraphicsLinearLayout::defaultStretchFactors_data()
1226 {
1227  QTest::addColumn<Qt::Orientation>("orientation");
1228  QTest::addColumn<int>("count");
1229  QTest::addColumn<IntList>("preferredSizeHints");
1230  QTest::addColumn<IntList>("stretches");
1231  QTest::addColumn<IntList>("ignoreFlag");
1232  QTest::addColumn<QSizeF>("newSize");
1233  QTest::addColumn<IntList>("expectedSizes");
1234 
1235  QTest::newRow("hor") << Qt::Horizontal << 3
1236  << (IntList() << 20 << 40 << 60)
1237  << (IntList())
1238  << (IntList())
1239  << QSizeF()
1240  << (IntList() << 20 << 40 << 60);
1241 
1242  QTest::newRow("ver") << Qt::Vertical << 3
1243  << (IntList() << 20 << 40 << 60)
1244  << (IntList())
1245  << (IntList())
1246  << QSizeF()
1247  << (IntList() << 20 << 40 << 60);
1248 
1249  QTest::newRow("hor,ignore123") << Qt::Horizontal << 3
1250  << (IntList() << 20 << 40 << 60)
1251  << (IntList())
1252  << (IntList() << 1 << 1 << 1)
1253  << QSizeF()
1254  << (IntList() << 0 << 0 << 0);
1255 
1256  QTest::newRow("hor,ignore23") << Qt::Horizontal << 3
1257  << (IntList() << 10 << 10 << 10)
1258  << (IntList())
1259  << (IntList() << 0 << 1 << 1)
1260  << QSizeF(200, 50)
1261  << (IntList()); //### stretches are not linear.
1262 
1263  QTest::newRow("hor,ignore2") << Qt::Horizontal << 3
1264  << (IntList() << 10 << 10 << 10)
1265  << (IntList())
1266  << (IntList() << 0 << 1 << 0)
1267  << QSizeF()
1268  << (IntList() << 10 << 0 << 10);
1269 
1270 }
1271 
1272 void tst_QGraphicsLinearLayout::defaultStretchFactors()
1273 {
1274  QFETCH(Qt::Orientation, orientation);
1275  QFETCH(int, count);
1276  QFETCH(IntList, preferredSizeHints);
1277  QFETCH(IntList, stretches);
1278  QFETCH(IntList, ignoreFlag);
1279  QFETCH(QSizeF, newSize);
1280  QFETCH(IntList, expectedSizes);
1281 
1286  scene.addItem(widget);
1288  layout->setContentsMargins(0, 0, 0, 0);
1289  layout->setSpacing(0.0);
1290  widget->setContentsMargins(0, 0, 0, 0);
1291 
1292  int i;
1293  for (i = 0; i < count; ++i) {
1294  RectWidget *item = new RectWidget(widget);
1295  layout->addItem(item);
1296  if (preferredSizeHints.value(i, -1) >= 0) {
1297  item->setSizeHint(Qt::PreferredSize, QSizeF(preferredSizeHints.at(i), preferredSizeHints.at(i)));
1298  }
1299  if (stretches.value(i, -1) >= 0) {
1300  layout->setStretchFactor(item, stretches.at(i));
1301  }
1302  if (ignoreFlag.value(i, 0) != 0) {
1303  QSizePolicy sp = item->sizePolicy();
1304  if (orientation == Qt::Horizontal)
1305  sp.setHorizontalPolicy(QSizePolicy::Policy(sp.horizontalPolicy() | QSizePolicy::IgnoreFlag));
1306  else
1307  sp.setVerticalPolicy(QSizePolicy::Policy(sp.verticalPolicy() | QSizePolicy::IgnoreFlag));
1308  item->setSizePolicy(sp);
1309  }
1310  }
1311 
1313 
1314  widget->show();
1315  view.show();
1316  view.resize(400,300);
1317  if (newSize.isValid())
1318  widget->resize(newSize);
1319 
1321  for (i = 0; i < count; ++i) {
1322  QSizeF itemSize = layout->itemAt(i)->geometry().size();
1323  if (orientation == Qt::Vertical)
1324  itemSize.transpose();
1325  if (i < expectedSizes.count())
1326  QCOMPARE(itemSize.width(), qreal(expectedSizes.at(i)));
1327  }
1328 
1329  delete widget;
1330 }
1331 
1333 void tst_QGraphicsLinearLayout::sizeHint_data()
1334 {
1335  QTest::addColumn<Qt::SizeHint>("which");
1336  QTest::addColumn<QSizeF>("constraint");
1337  QTest::addColumn<qreal>("spacing");
1338  QTest::addColumn<qreal>("layoutMargin");
1339  QTest::addColumn<QSizeF>("sizeHint");
1340 
1341  QTest::newRow("minimumSize") << Qt::MinimumSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(30, 10);
1342  QTest::newRow("preferredSize") << Qt::PreferredSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(75, 25);
1343  QTest::newRow("maximumSize") << Qt::MaximumSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(150, 50);
1344  QTest::newRow("minimumSize, spacing=3") << Qt::MinimumSize << QSizeF() << qreal(3.0) << qreal(0.0) << QSizeF(30 + 2*3, 10);
1345  QTest::newRow("minimumSize, spacing=3, layoutMargin=10") << Qt::MinimumSize << QSizeF() << qreal(3.0) << qreal(10.0) << QSizeF(30 + 2*3 + 2*10, 10 + 2*10);
1346  QTest::newRow("minimumSize, spacing=0, layoutMargin=7") << Qt::MinimumSize << QSizeF() << qreal(0.0) << qreal(7.0) << QSizeF(30 + 0 + 2*7, 10 + 2*7);
1347 }
1348 
1349 // QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint) const public
1350 void tst_QGraphicsLinearLayout::sizeHint()
1351 {
1352  QFETCH(Qt::SizeHint, which);
1353  QFETCH(QSizeF, constraint);
1354  QFETCH(qreal, spacing);
1355  QFETCH(qreal, layoutMargin);
1356  QFETCH(QSizeF, sizeHint);
1357 
1362  scene.addItem(widget);
1363  widget->setLayout(&layout);
1364  layout.setContentsMargins(layoutMargin, layoutMargin, layoutMargin, layoutMargin);
1366  for (int i = 0; i < 3; ++i) {
1368  item->setMinimumSize(10, 10);
1369  item->setPreferredSize(25, 25);
1370  item->setMaximumSize(50, 50);
1371  layout.addItem(item);
1372  }
1374  QCOMPARE(layout.sizeHint(which, constraint), sizeHint);
1375  delete widget;
1376 }
1377 
1378 void tst_QGraphicsLinearLayout::updateGeometry()
1379 {
1382 
1385  w1->setMinimumSize(100, 40);
1387  layout->addItem(w1);
1388  scene.addItem(window);
1389  window->setLayout(layout);
1390  layout->setContentsMargins(0, 0, 0, 0);
1391  QCOMPARE(w1->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout));
1392  QCOMPARE(layout->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(window));
1393 
1394  view.show();
1396  QCOMPARE(window->size().toSize(), QSize(100, 50));
1397  w1->setMinimumSize(110, 60);
1399  QCOMPARE(window->size().toSize(), QSize(110, 60));
1401 
1402  {
1403  delete window;
1404  window = new QGraphicsWidget(0, Qt::Window);
1407  w1->setMinimumSize(110, 50);
1408  layout2a->addItem(w1);
1410  layout2->addItem(layout2a);
1411  layout2->setContentsMargins(1, 1, 1, 1);
1412  layout2a->setContentsMargins(1, 1, 1, 1);
1413  window->setLayout(layout2);
1415  QCOMPARE(w1->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout2a));
1416  QCOMPARE(layout2a->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout2));
1417  QCOMPARE(layout2->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(window));
1418  QCOMPARE(window->size().toSize(), QSize(114, 54));
1420  w1->setMinimumSize(120, 60);
1422  QCOMPARE(window->size().toSize(), QSize(124, 64));
1423  }
1424 
1425  {
1426  delete window;
1427  window = new QGraphicsWidget(0, Qt::Window);
1428  scene.addItem(window);
1429  window->show();
1431  w1->setMinimumSize(100, 50);
1433  layout2a->addItem(w1);
1435  layout2->addItem(layout2a);
1436  layout2a->setContentsMargins(1, 1, 1, 1);
1437  window->setLayout(layout2);
1439  qreal left, top, right, bottom;
1440  layout2->getContentsMargins(&left, &top, &right, &bottom);
1441  QCOMPARE(window->size().toSize(), QSize(102 +left + right, 52 + top + bottom));
1442  }
1443 
1444  {
1445  delete window;
1446  window = new QGraphicsWidget(0, Qt::Window);
1447  scene.addItem(window);
1449  w1->setMinimumSize(100, 50);
1450  window->setLayout(0);
1452  layout2a->addItem(w1);
1454  layout2->addItem(layout2a);
1455  window->resize(200, 80);
1456  window->setLayout(layout2);
1457  window->show();
1459  QCOMPARE(window->size().toSize(), QSize(200, 80));
1460  }
1461 
1462 }
1463 
1464 void tst_QGraphicsLinearLayout::layoutDirection()
1465 {
1468 
1471  layout->setContentsMargins(1, 2, 3, 4);
1472  layout->setSpacing(6);
1473 
1474  RectWidget *w1 = new RectWidget;
1475  w1->setPreferredSize(20, 20);
1476  w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
1477  layout->addItem(w1);
1478  RectWidget *w2 = new RectWidget;
1479  w2->setPreferredSize(20, 20);
1480  w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
1481  layout->addItem(w2);
1482 
1483  scene.addItem(window);
1484  window->setLayout(layout);
1485  view.show();
1486  window->resize(50, 20);
1487  window->setLayoutDirection(Qt::LeftToRight);
1489  QCOMPARE(w1->geometry().left(), 1.0);
1490  QCOMPARE(w1->geometry().right(), 21.0);
1491  QCOMPARE(w2->geometry().left(), 27.0);
1492  QCOMPARE(w2->geometry().right(), 47.0);
1493 
1494  window->setLayoutDirection(Qt::RightToLeft);
1496  QCOMPARE(w1->geometry().right(), 49.0);
1497  QCOMPARE(w1->geometry().left(), 29.0);
1498  QCOMPARE(w2->geometry().right(), 23.0);
1499  QCOMPARE(w2->geometry().left(), 3.0);
1500 
1501  delete window;
1502 }
1503 
1504 void tst_QGraphicsLinearLayout::removeLayout()
1505 {
1511 
1515 
1517  form->setLayout(layout);
1518  scene.addItem(form);
1519 
1521  view.show();
1523 
1524  QRectF r1 = textEdit->geometry();
1526  form->setLayout(0);
1527  //documentation of QGraphicsWidget::setLayout:
1528  //If layout is 0, the widget is left without a layout. Existing subwidgets' geometries will remain unaffected.
1529  QCOMPARE(textEdit->geometry(), r1);
1530  QCOMPARE(pushButton->geometry(), r2);
1531 }
1532 
1533 void tst_QGraphicsLinearLayout::avoidRecursionInInsertItem()
1534 {
1537  QCOMPARE(layout->count(), 0);
1538  QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert itself");
1539  layout->insertItem(0, layout);
1540  QCOMPARE(layout->count(), 0);
1541 }
1542 
1543 void tst_QGraphicsLinearLayout::styleInfoLeak()
1544 {
1546  layout.spacing();
1547 }
1548 
1549 void tst_QGraphicsLinearLayout::task218400_insertStretchCrash()
1550 {
1554 
1556  layout->addItem(a);
1557  layout->addItem(b);
1558  layout->insertStretch(0); // inserts gap in item grid in the layout engine
1559 
1561  form->setLayout(layout); // crash
1562 }
1563 
1564 void tst_QGraphicsLinearLayout::testAlignmentInLargerLayout()
1565 {
1568  scene->addItem(form);
1570  layout->setSpacing(0);
1571  layout->setContentsMargins(0,0,0,0);
1572 
1574  a->setMaximumSize(100,100);
1575  layout->addItem(a);
1576 
1577  QCOMPARE(form->maximumSize(), QSizeF(100,100));
1578  QCOMPARE(layout->maximumSize(), QSizeF(100,100));
1579  layout->setMinimumSize(QSizeF(200,200));
1580  layout->setMaximumSize(QSizeF(200,200));
1581 
1583  layout->activate();
1584  QCOMPARE(a->geometry(), QRectF(50,50,100,100));
1585 
1587  layout->activate();
1588  QCOMPARE(a->geometry(), QRectF(100,100,100,100));
1589 
1591  layout->activate();
1592  QCOMPARE(a->geometry(), QRectF(50,0,100,100));
1593 
1595  b->setMaximumSize(100,100);
1596  layout->addItem(b);
1597 
1600  layout->activate();
1601  QCOMPARE(a->geometry(), QRectF(50,0,100,100));
1602  QCOMPARE(b->geometry(), QRectF(50,100,100,100));
1603 
1606  layout->activate();
1607  QCOMPARE(a->geometry(), QRectF(100,0,100,100));
1608  QCOMPARE(b->geometry(), QRectF(0,100,100,100));
1609 }
1610 
1611 void tst_QGraphicsLinearLayout::testOffByOneInLargerLayout() {
1614  scene->addItem(form);
1616  layout->setSpacing(0);
1617  layout->setContentsMargins(0,0,0,0);
1618 
1621  a->setMaximumSize(100,100);
1622  b->setMaximumSize(100,100);
1623  layout->addItem(a);
1624  layout->addItem(b);
1625 
1628  layout->setMinimumSize(QSizeF(101,201));
1629  layout->setMaximumSize(QSizeF(101,201));
1630  layout->activate();
1631  QCOMPARE(a->geometry(), QRectF(1,0.5,100,100));
1632  QCOMPARE(b->geometry(), QRectF(0,100.5,100,100));
1633 
1634  layout->setMinimumSize(QSizeF(100,200));
1635  layout->setMaximumSize(QSizeF(100,200));
1636  layout->activate();
1637  QCOMPARE(a->geometry(), QRectF(0,0,100,100));
1638  QCOMPARE(b->geometry(), QRectF(0,100,100,100));
1639 
1640  layout->setMinimumSize(QSizeF(99,199));
1641  layout->setMaximumSize(QSizeF(99,199));
1642  layout->activate();
1643  QCOMPARE(a->geometry(), QRectF(0,0,99,99.5));
1644  QCOMPARE(b->geometry(), QRectF(0,99.5,99,99.5));
1645 }
1646 void tst_QGraphicsLinearLayout::testDefaultAlignment()
1647 {
1650  layout->setContentsMargins(0, 0, 0, 0);
1651  layout->setSpacing(0);
1652 
1654  w->setMinimumSize(50,50);
1655  w->setMaximumSize(50,50);
1656  layout->addItem(w);
1657 
1658  //Default alignment should be to the top-left
1659  QCOMPARE(layout->alignment(w), 0);
1660 
1661  //First, check by forcing the layout to be bigger
1662  layout->setMinimumSize(100,100);
1663  layout->activate();
1664  QCOMPARE(layout->geometry(), QRectF(0,0,100,100));
1665  QCOMPARE(w->geometry(), QRectF(0,0,50,50));
1666  layout->setMinimumSize(-1,-1);
1667 
1668  //Second, check by adding a larger item in the column
1670  w2->setMinimumSize(100,100);
1671  w2->setMaximumSize(100,100);
1672  layout->addItem(w2);
1673  layout->activate();
1674  QCOMPARE(layout->geometry(), QRectF(0,0,100,150));
1675  QCOMPARE(w->geometry(), QRectF(0,0,50,50));
1676  QCOMPARE(w2->geometry(), QRectF(0,50,100,100));
1677 }
1678 
1679 void tst_QGraphicsLinearLayout::combineSizePolicies()
1680 {
1683  layout->setContentsMargins(0, 0, 0, 0);
1684  layout->setSpacing(0);
1685 
1687  w1->setMaximumSize(200,200);
1689  layout->addItem(w1);
1690 
1692  w2->setPreferredSize(50,50);
1693  w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
1694  layout->addItem(w2);
1695  QCOMPARE(layout->maximumHeight(), qreal(200));
1696 
1697  // now remove the fixed vertical size policy, and set instead the maximum height to 50
1698  // this should in effect give the same maximumHeight
1699  w2->setMaximumHeight(50);
1700  w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
1701  QCOMPARE(layout->maximumHeight(), qreal(200));
1702 }
1703 
1704 void tst_QGraphicsLinearLayout::hiddenItems()
1705 {
1708  layout->setContentsMargins(0, 0, 0, 0);
1709  layout->setSpacing(2);
1710 
1711  RectWidget *w1 = new RectWidget;
1712  w1->setPreferredSize(QSizeF(20, 20));
1713  layout->addItem(w1);
1714 
1715  RectWidget *w2 = new RectWidget;
1716  w2->setPreferredSize(QSizeF(20, 20));
1717  layout->addItem(w2);
1718 
1719  RectWidget *w3 = new RectWidget;
1720  w3->setPreferredSize(QSizeF(20, 20));
1721  layout->addItem(w3);
1722 
1723  QCOMPARE(layout->preferredWidth(), qreal(64));
1724  w2->hide();
1725  QCOMPARE(layout->preferredWidth(), qreal(42));
1726  w2->show();
1727  QCOMPARE(layout->preferredWidth(), qreal(64));
1728  QSizePolicy sp = w2->sizePolicy();
1729  sp.setRetainSizeWhenHidden(true);
1730  w2->setSizePolicy(sp);
1731  QCOMPARE(layout->preferredWidth(), qreal(64));
1732  w2->hide();
1733  QCOMPARE(layout->preferredWidth(), qreal(64));
1734  sp.setRetainSizeWhenHidden(false);
1735  w2->setSizePolicy(sp);
1736  QCOMPARE(layout->preferredWidth(), qreal(42));
1737 }
1738 
1740 #include "tst_qgraphicslinearlayout.moc"
1741 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
Arabic default style
Definition: afstyles.h:94
QList< int > IntList
virtual int pixelMetric(QStyle::PixelMetric pm, const QStyleOption *option=0, const QWidget *widget=0) const override
LayoutStyle(const QString &key)
static void setStyle(QStyle *)
void setGeometry(const QRect &) override
Definition: qboxlayout.cpp:760
void invalidate() override
Definition: qboxlayout.cpp:697
int count() const override
Definition: qboxlayout.cpp:707
void insertStretch(int index, int stretch=0)
Definition: qboxlayout.cpp:892
int spacing() const override
Definition: qboxlayout.cpp:587
QSize sizeHint() const override
Definition: qboxlayout.cpp:615
QSize maximumSize() const override
Definition: qboxlayout.cpp:637
bool setStretchFactor(QWidget *w, int stretch)
void addItem(QLayoutItem *) override
Definition: qboxlayout.cpp:832
void insertItem(int index, QLayoutItem *)
Definition: qboxlayout.cpp:847
void addStretch(int stretch=0)
QLayoutItem * itemAt(int) const override
Definition: qboxlayout.cpp:716
void setSpacing(int spacing) override
Definition: qboxlayout.cpp:605
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:66
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
static QByteArray number(int, int base=10)
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ LayoutDirectionChange
Definition: qcoreevent.h:137
@ LayoutRequest
Definition: qcoreevent.h:125
@ GraphicsSceneResize
Definition: qcoreevent.h:238
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
Definition: qgraphicsitem.h:83
QPointF pos() const
virtual void widgetEvent(QEvent *e)
void getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const override
void setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
The QGraphicsLayoutItem class can be inherited to allow your custom items to be managed by layouts.
void setMaximumSize(const QSizeF &size)
void setSizePolicy(const QSizePolicy &policy)
void setPreferredSize(const QSizeF &size)
QGraphicsLayoutItem * parentLayoutItem() const
void setMinimumSize(const QSizeF &size)
The QGraphicsLinearLayout class provides a horizontal or vertical layout for managing widgets in Grap...
void addItem(QGraphicsLayoutItem *item)
Qt::Orientation orientation() const
QGraphicsObject * parent
the parent of the item
The QGraphicsScene class provides a surface for managing a large number of 2D graphical items.
void addItem(QGraphicsItem *item)
QGraphicsProxyWidget * addWidget(QWidget *widget, Qt::WindowFlags wFlags=Qt::WindowFlags())
The QGraphicsView class provides a widget for displaying the contents of a QGraphicsScene.
Definition: qgraphicsview.h:60
The QGraphicsWidget class is the base class for all widget items in a QGraphicsScene.
void setLayout(QGraphicsLayout *layout)
QRectF geometry
the geometry of the widget
QRectF rect() const
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint=QSizeF()) const override
QSizeF size
the size of the widget
void updateGeometry() override
QSizeF maximumSize
the maximum size of the widget
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
QRect geometry() const override
Definition: qlayout.cpp:497
bool activate()
Definition: qlayout.cpp:1028
bool setAlignment(QWidget *w, Qt::Alignment alignment)
Definition: qlayout.cpp:236
void removeItem(QLayoutItem *)
Definition: qlayout.cpp:1384
void setContentsMargins(int left, int top, int right, int bottom)
Definition: qlayout.cpp:325
virtual QRect geometry() const =0
Qt::Alignment alignment() const
Definition: qlayoutitem.h:81
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
qsizetype count() const noexcept
Definition: qlist.h:415
void append(parameter_type t)
Definition: qlist.h:469
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:82
void setBrush(const QBrush &brush)
Definition: qpainter.cpp:3755
void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode=Qt::AbsoluteSize)
Definition: qpainter.cpp:3924
constexpr qreal x() const noexcept
Definition: qpoint.h:361
constexpr qreal y() const noexcept
Definition: qpoint.h:366
The QProxyStyle class is a convenience class that simplifies dynamically overriding QStyle elements.
Definition: qproxystyle.h:53
int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const override
The QRectF class defines a finite rectangle in the plane using floating point precision.
Definition: qrect.h:511
constexpr QSizeF size() const noexcept
Definition: qrect.h:744
constexpr QSize size() const noexcept
Definition: qrect.h:269
The QSizeF class defines the size of a two-dimensional object using floating point precision.
Definition: qsize.h:235
constexpr qreal width() const noexcept
Definition: qsize.h:349
constexpr qreal height() const noexcept
Definition: qsize.h:352
void transpose() noexcept
Definition: qsize.cpp:608
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
The QSizePolicy class is a layout attribute describing horizontal and vertical resizing policy.
Definition: qsizepolicy.h:54
The QString class provides a Unicode character string.
Definition: qstring.h:388
PixelMetric
Definition: qstyle.h:449
@ PM_LayoutVerticalSpacing
Definition: qstyle.h:551
@ PM_LayoutHorizontalSpacing
Definition: qstyle.h:550
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem.
Definition: qstyleoption.h:684
The QStyleOption class stores the parameters used by QStyle functions.
Definition: qstyleoption.h:75
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
void setLayout(QLayout *)
Definition: qwidget.cpp:10146
void setGeometry(int x, int y, int w, int h)
Definition: qwidget.h:919
void setContentsMargins(int left, int top, int right, int bottom)
Definition: qwidget.cpp:7545
void setStyle(QStyle *)
Definition: qwidget.cpp:2642
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition: qwidget.h:140
void show()
Definition: qwidget.cpp:7825
QStyle * style() const
Definition: qwidget.cpp:2612
void resize(int w, int h)
Definition: qwidget.h:916
QSizeF m_sizeHints[Qt::NSizeHints]
void setSizeHint(Qt::SizeHint which, const QSizeF &size)
RectWidget(QGraphicsItem *parent=nullptr, const QBrush &brush=QBrush())
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint=QSizeF()) const override
void widgetEvent(QEvent *e) override
SubQGraphicsLinearLayout(Qt::Orientation orientation=Qt::Horizontal)
QOpenGLWidget * widget
[1]
qreal spacing
double e
QCOMPARE(spy.count(), 1)
rect
[4]
union Alignment_ Alignment
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout=5000)
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message)
Definition: qtestcase.cpp:2292
AlignmentFlag
Definition: qnamespace.h:168
@ AlignRight
Definition: qnamespace.h:171
@ AlignBottom
Definition: qnamespace.h:179
@ AlignVCenter
Definition: qnamespace.h:180
@ AlignTop
Definition: qnamespace.h:178
@ AlignHCenter
Definition: qnamespace.h:173
@ AlignCenter
Definition: qnamespace.h:188
@ AlignLeft
Definition: qnamespace.h:169
@ RelativeSize
Definition: qnamespace.h:1163
@ LeftToRight
Definition: qnamespace.h:1463
@ RightToLeft
Definition: qnamespace.h:1464
Orientation
Definition: qnamespace.h:123
@ Horizontal
Definition: qnamespace.h:124
@ Vertical
Definition: qnamespace.h:125
@ blue
Definition: qnamespace.h:68
@ red
Definition: qnamespace.h:66
@ Window
Definition: qnamespace.h:232
SizeHint
Definition: qnamespace.h:1589
@ MaximumSize
Definition: qnamespace.h:1592
@ PreferredSize
Definition: qnamespace.h:1591
@ MinimumSize
Definition: qnamespace.h:1590
@ NSizeHints
Definition: qnamespace.h:1594
Definition: brush.cpp:52
#define QString()
Definition: parse-defines.h:51
#define qApp
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
@ QtWarningMsg
Definition: qlogging.h:62
#define Q_DECLARE_METATYPE(TYPE)
Definition: qmetatype.h:1417
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint left
GLint GLint bottom
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: qopenglext.h:12395
GLuint GLenum option
Definition: qopenglext.h:5929
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: qopenglext.h:12395
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
#define sp
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
Q_UNUSED(salary)
[21]
QPushButton * pushButton
QVBoxLayout * layout
QRect r1(100, 200, 11, 16)
[0]
QRect r2(QPoint(100, 200), QSize(11, 16))
QGraphicsWidget * form
QGraphicsScene scene
[0]
QGraphicsWidget * textEdit
QGraphicsItem * item
QList< QTreeWidgetItem * > items
gridLayout addWidget(nameLabel, 0, 0)
QPainter painter(this)
[7]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QQuickView * view
[0]