QtBase  v6.3.1
tst_qgraphicsanchorlayout.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 #include <QTest>
30 #include <QtWidgets/qgraphicsanchorlayout.h>
31 #include <QtWidgets/qgraphicslinearlayout.h>
32 #include <QtWidgets/qgraphicswidget.h>
33 #include <QtWidgets/qgraphicsview.h>
34 
36 {
37  Q_OBJECT
38 public:
41 
42 private slots:
43  void hard_complex_data();
44  void hard_complex();
45  void linearVsAnchorSizeHints_data();
46  void linearVsAnchorSizeHints();
47  void linearVsAnchorSetGeometry_data();
48  void linearVsAnchorSetGeometry();
49  void linearVsAnchorNested_data();
50  void linearVsAnchorNested();
51 };
52 
53 
54 class RectWidget : public QGraphicsWidget
55 {
56 public:
58 
60  {
64  painter->drawLine(rect().topLeft(), rect().bottomRight());
65  painter->drawLine(rect().bottomLeft(), rect().topRight());
66  }
67 };
68 
69 static QGraphicsWidget *createItem(const QSizeF &minimum = QSizeF(100.0, 100.0),
70  const QSizeF &preferred = QSize(150.0, 100.0),
71  const QSizeF &maximum = QSizeF(200.0, 100.0),
72  const QString &name = QString())
73 {
75  w->setMinimumSize(minimum);
76  w->setPreferredSize(preferred);
77  w->setMaximumSize(maximum);
78  w->setData(0, name);
79  return w;
80 }
81 
82 static void setAnchor(QGraphicsAnchorLayout *l,
83  QGraphicsLayoutItem *firstItem,
84  Qt::AnchorPoint firstEdge,
85  QGraphicsLayoutItem *secondItem,
86  Qt::AnchorPoint secondEdge,
87  qreal spacing)
88 {
89  QGraphicsAnchor *anchor = l->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
90  anchor->setSpacing(spacing);
91 }
92 
93 void tst_QGraphicsAnchorLayout::hard_complex_data()
94 {
95  QTest::addColumn<int>("whichSizeHint");
96  QTest::newRow("minimumSizeHint")
97  << int(Qt::MinimumSize);
98  QTest::newRow("preferredSizeHint")
99  << int(Qt::PreferredSize);
100  QTest::newRow("maximumSizeHint")
101  << int(Qt::MaximumSize);
102  // Add it as a reference to see how much overhead the body of effectiveSizeHint takes.
103  QTest::newRow("noSizeHint")
104  << -1;
105 }
106 
107 void tst_QGraphicsAnchorLayout::hard_complex()
108 {
109  QFETCH(int, whichSizeHint);
110 
111  // Test for "hard" complex case, taken from wiki
112  // https://cwiki.nokia.com/S60QTUI/AnchorLayoutComplexCases
113  QSizeF min(0, 10);
114  QSizeF pref(50, 10);
115  QSizeF max(100, 10);
116 
117  QGraphicsWidget *a = createItem(min, pref, max, "a");
118  QGraphicsWidget *b = createItem(min, pref, max, "b");
119  QGraphicsWidget *c = createItem(min, pref, max, "c");
120  QGraphicsWidget *d = createItem(min, pref, max, "d");
121  QGraphicsWidget *e = createItem(min, pref, max, "e");
122  QGraphicsWidget *f = createItem(min, pref, max, "f");
123  QGraphicsWidget *g = createItem(min, pref, max, "g");
124 
126  l->setContentsMargins(0, 0, 0, 0);
127 
128  //<!-- Trunk -->
129  setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 10);
130  setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 10);
131  setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft, 10);
132  setAnchor(l, c, Qt::AnchorRight, d, Qt::AnchorLeft, 10);
133  setAnchor(l, d, Qt::AnchorRight, l, Qt::AnchorRight, 10);
134 
135  //<!-- Above trunk -->
136  setAnchor(l, b, Qt::AnchorLeft, e, Qt::AnchorLeft, 10);
137  setAnchor(l, e, Qt::AnchorRight, d, Qt::AnchorLeft, 10);
138 
139  //<!-- Below trunk -->
140  setAnchor(l, a, Qt::AnchorHorizontalCenter, g, Qt::AnchorLeft, 10);
141  setAnchor(l, g, Qt::AnchorRight, f, Qt::AnchorHorizontalCenter, 10);
142  setAnchor(l, c, Qt::AnchorLeft, f, Qt::AnchorLeft, 10);
143  setAnchor(l, f, Qt::AnchorRight, d, Qt::AnchorRight, 10);
144 
145  //<!-- vertical is simpler -->
146  setAnchor(l, l, Qt::AnchorTop, e, Qt::AnchorTop, 0);
147  setAnchor(l, e, Qt::AnchorBottom, a, Qt::AnchorTop, 0);
148  setAnchor(l, e, Qt::AnchorBottom, b, Qt::AnchorTop, 0);
149  setAnchor(l, e, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
150  setAnchor(l, e, Qt::AnchorBottom, d, Qt::AnchorTop, 0);
151  setAnchor(l, a, Qt::AnchorBottom, f, Qt::AnchorTop, 0);
152  setAnchor(l, a, Qt::AnchorBottom, b, Qt::AnchorBottom, 0);
153  setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorBottom, 0);
154  setAnchor(l, a, Qt::AnchorBottom, d, Qt::AnchorBottom, 0);
155  setAnchor(l, f, Qt::AnchorBottom, g, Qt::AnchorTop, 0);
156  setAnchor(l, g, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
157 
158  // It won't query the size hint if it already has a size set.
159  // If only one of the sizes is unset it will query sizeHint only of for that hint type.
160  l->setMinimumSize(60,40);
161  l->setPreferredSize(220,40);
162  l->setMaximumSize(240,40);
163 
164  switch (whichSizeHint) {
165  case Qt::MinimumSize:
166  l->setMinimumSize(-1, -1);
167  break;
168  case Qt::PreferredSize:
169  l->setPreferredSize(-1, -1);
170  break;
171  case Qt::MaximumSize:
172  l->setMaximumSize(-1, -1);
173  break;
174  default:
175  break;
176  }
177 
178  QSizeF sizeHint;
179  // warm up instruction cache
180  l->invalidate();
181  sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint);
182  // ...then measure...
183  QBENCHMARK {
184  l->invalidate();
185  sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint);
186  }
187 }
188 
189 static QGraphicsLayout* createLayouts(int whichLayout)
190 {
191  QSizeF min(0, 10);
192  QSizeF pref(50, 10);
193  QSizeF max(100, 10);
194 
195  QGraphicsWidget *a = createItem(min, pref, max, "a");
196  QGraphicsWidget *b = createItem(min, pref, max, "b");
197  QGraphicsWidget *c = createItem(min, pref, max, "c");
198  QGraphicsWidget *d = createItem(min, pref, max, "d");
199 
201  if (whichLayout == 0) {
202  l = new QGraphicsLinearLayout;
203  QGraphicsLinearLayout *linear = static_cast<QGraphicsLinearLayout *>(l);
204  linear->setContentsMargins(0, 0, 0, 0);
205 
206  linear->addItem(a);
207  linear->addItem(b);
208  linear->addItem(c);
209  linear->addItem(d);
210  } else {
211  l = new QGraphicsAnchorLayout;
212  QGraphicsAnchorLayout *anchor = static_cast<QGraphicsAnchorLayout *>(l);
213  anchor->setContentsMargins(0, 0, 0, 0);
214 
215  // Horizontal
216  setAnchor(anchor, anchor, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
217  setAnchor(anchor, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0);
218  setAnchor(anchor, b, Qt::AnchorRight, c, Qt::AnchorLeft, 0);
219  setAnchor(anchor, c, Qt::AnchorRight, d, Qt::AnchorLeft, 0);
220  setAnchor(anchor, d, Qt::AnchorRight, anchor, Qt::AnchorRight, 0);
221 
222  // Vertical
223  anchor->addAnchors(anchor, a, Qt::Vertical);
224  anchor->addAnchors(anchor, b, Qt::Vertical);
225  anchor->addAnchors(anchor, c, Qt::Vertical);
226  anchor->addAnchors(anchor, d, Qt::Vertical);
227  }
228 
229  return l;
230 }
231 
232 void tst_QGraphicsAnchorLayout::linearVsAnchorSizeHints_data()
233 {
234  QTest::addColumn<int>("whichLayout");
235  QTest::addColumn<int>("whichSizeHint");
236 
237  QTest::newRow("QGraphicsLinearLayout::minimum")
238  << 0 << int(Qt::MinimumSize);
239  QTest::newRow("QGraphicsLinearLayout::preferred")
240  << 0 << int(Qt::PreferredSize);
241  QTest::newRow("QGraphicsLinearLayout::maximum")
242  << 0 << int(Qt::MaximumSize);
243  QTest::newRow("QGraphicsLinearLayout::noSizeHint")
244  << 0 << -1;
245 
246  QTest::newRow("QGraphicsAnchorLayout::minimum")
247  << 1 << int(Qt::MinimumSize);
248  QTest::newRow("QGraphicsAnchorLayout::preferred")
249  << 1 << int(Qt::PreferredSize);
250  QTest::newRow("QGraphicsAnchorLayout::maximum")
251  << 1 << int(Qt::MaximumSize);
252  QTest::newRow("QGraphicsAnchorLayout::noSizeHint")
253  << 1 << -1;
254 }
255 
256 void tst_QGraphicsAnchorLayout::linearVsAnchorSizeHints()
257 {
258  QFETCH(int, whichSizeHint);
259  QFETCH(int, whichLayout);
260 
261  QGraphicsLayout *l = createLayouts(whichLayout);
262 
263  QSizeF sizeHint;
264  // warm up instruction cache
265  l->invalidate();
266  sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint);
267  // ...then measure...
268 
269  QBENCHMARK {
270  l->invalidate();
271  sizeHint = l->effectiveSizeHint((Qt::SizeHint)whichSizeHint);
272  }
273 }
274 
275 void tst_QGraphicsAnchorLayout::linearVsAnchorSetGeometry_data()
276 {
277  QTest::addColumn<int>("whichLayout");
278 
279  QTest::newRow("QGraphicsLinearLayout")
280  << 0;
281  QTest::newRow("QGraphicsAnchorLayout")
282  << 1;
283 }
284 
285 void tst_QGraphicsAnchorLayout::linearVsAnchorSetGeometry()
286 {
287  QFETCH(int, whichLayout);
288 
289  QGraphicsLayout *l = createLayouts(whichLayout);
290 
291  QRectF sizeHint;
292  qreal maxWidth;
294  // warm up instruction cache
295  l->invalidate();
296  sizeHint.setSize(l->effectiveSizeHint(Qt::MinimumSize));
297  maxWidth = l->effectiveSizeHint(Qt::MaximumSize).width();
298  increment = (maxWidth - sizeHint.width()) / 100;
299  l->setGeometry(sizeHint);
300  // ...then measure...
301 
302  QBENCHMARK {
303  l->invalidate();
304  for (qreal width = sizeHint.width(); width <= maxWidth; width += increment) {
305  sizeHint.setWidth(width);
306  l->setGeometry(sizeHint);
307  }
308  }
309 }
310 
311 void tst_QGraphicsAnchorLayout::linearVsAnchorNested_data()
312 {
313  QTest::addColumn<int>("whichLayout");
314  QTest::newRow("LinearLayout")
315  << 0;
316  QTest::newRow("AnchorLayout setup with null-anchors knot")
317  << 1;
318  QTest::newRow("AnchorLayout setup easy to simplificate")
319  << 2;
320 }
321 
322 void tst_QGraphicsAnchorLayout::linearVsAnchorNested()
323 {
324  QFETCH(int, whichLayout);
325 
326  QSizeF min(10, 10);
327  QSizeF pref(80, 80);
328  QSizeF max(150, 150);
329 
330  QGraphicsWidget *a = createItem(min, pref, max, "a");
331  QGraphicsWidget *b = createItem(min, pref, max, "b");
332  QGraphicsWidget *c = createItem(min, pref, max, "c");
333  QGraphicsWidget *d = createItem(min, pref, max, "d");
334 
336 
337  if (whichLayout == 0) {
341 
342  linear1->addItem(a);
343  linear1->addItem(linear2);
344  linear2->addItem(b);
345  linear2->addItem(linear3);
346  linear3->addItem(c);
347  linear3->addItem(d);
348 
349  layout = linear1;
350  } else if (whichLayout == 1) {
352 
353  // A
358 
359  // B
363 
364  // C
367 
368  // D
370 
371  layout = anchor;
372  } else {
374 
375  // A
376  anchor->addAnchor(a, Qt::AnchorLeft, anchor, Qt::AnchorLeft);
377  anchor->addAnchors(a, anchor, Qt::Vertical);
380 
381  // B
382  anchor->addAnchor(b, Qt::AnchorTop, anchor, Qt::AnchorTop);
383  anchor->addAnchor(b, Qt::AnchorRight, anchor, Qt::AnchorRight);
386 
387  // C
389  anchor->addAnchor(c, Qt::AnchorBottom, anchor, Qt::AnchorBottom);
390 
391  // D
392  anchor->addAnchor(d, Qt::AnchorRight, anchor, Qt::AnchorRight);
393  anchor->addAnchor(d, Qt::AnchorBottom, anchor, Qt::AnchorBottom);
394 
395  layout = anchor;
396  }
397 
398  QSizeF sizeHint;
399  // warm up instruction cache
400  layout->invalidate();
401  sizeHint = layout->effectiveSizeHint(Qt::PreferredSize);
402 
403  // ...then measure...
404  QBENCHMARK {
405  // To ensure that all sizeHints caches are invalidated in
406  // the LinearLayout setup, we must call updateGeometry on the
407  // children. If we didn't, only the top level layout would be
408  // re-calculated.
409  static_cast<QGraphicsLayoutItem *>(a)->updateGeometry();
410  static_cast<QGraphicsLayoutItem *>(b)->updateGeometry();
411  static_cast<QGraphicsLayoutItem *>(c)->updateGeometry();
412  static_cast<QGraphicsLayoutItem *>(d)->updateGeometry();
413  layout->invalidate();
414  sizeHint = layout->effectiveSizeHint(Qt::PreferredSize);
415  }
416 }
417 
419 
420 #include "tst_qgraphicsanchorlayout.moc"
void invalidate() override
Definition: qboxlayout.cpp:697
The QGraphicsAnchor class represents an anchor between two items in a QGraphicsAnchorLayout.
void setSpacing(qreal spacing)
The QGraphicsAnchorLayout class provides a layout where one can anchor widgets together in Graphics V...
QGraphicsAnchor * addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge)
void addCornerAnchors(QGraphicsLayoutItem *firstItem, Qt::Corner firstCorner, QGraphicsLayoutItem *secondItem, Qt::Corner secondCorner)
void addAnchors(QGraphicsLayoutItem *firstItem, QGraphicsLayoutItem *secondItem, Qt::Orientations orientations=Qt::Horizontal|Qt::Vertical)
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
Definition: qgraphicsitem.h:83
The QGraphicsLayout class provides the base class for all layouts in Graphics View.
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 setMinimumSize(const QSizeF &size)
The QGraphicsLinearLayout class provides a horizontal or vertical layout for managing widgets in Grap...
void addItem(QGraphicsLayoutItem *item)
QGraphicsObject * parent
the parent of the item
The QGraphicsWidget class is the base class for all widget items in a QGraphicsScene.
QRectF rect() const
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 drawLine(const QLineF &line)
Definition: qpainter.h:477
void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode=Qt::AbsoluteSize)
Definition: qpainter.cpp:3924
The QRectF class defines a finite rectangle in the plane using floating point precision.
Definition: qrect.h:511
constexpr qreal width() const noexcept
Definition: qrect.h:738
constexpr void setWidth(qreal w) noexcept
Definition: qrect.h:827
constexpr void setSize(const QSizeF &s) noexcept
Definition: qrect.h:833
The QSizeF class defines the size of a two-dimensional object using floating point precision.
Definition: qsize.h:235
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
The QString class provides a Unicode character string.
Definition: qstring.h:388
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem.
Definition: qstyleoption.h:684
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
RectWidget(QGraphicsItem *parent=nullptr)
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
QOpenGLWidget * widget
[1]
qreal spacing
double e
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
@ BottomLeftCorner
Definition: qnamespace.h:1290
@ TopRightCorner
Definition: qnamespace.h:1289
@ TopLeftCorner
Definition: qnamespace.h:1288
@ BottomRightCorner
Definition: qnamespace.h:1291
@ RelativeSize
Definition: qnamespace.h:1163
@ Vertical
Definition: qnamespace.h:125
AnchorPoint
Definition: qnamespace.h:1469
@ AnchorRight
Definition: qnamespace.h:1472
@ AnchorBottom
Definition: qnamespace.h:1475
@ AnchorTop
Definition: qnamespace.h:1473
@ AnchorHorizontalCenter
Definition: qnamespace.h:1471
@ AnchorLeft
Definition: qnamespace.h:1470
SizeHint
Definition: qnamespace.h:1589
@ MaximumSize
Definition: qnamespace.h:1592
@ PreferredSize
Definition: qnamespace.h:1591
@ MinimumSize
Definition: qnamespace.h:1590
#define QString()
Definition: parse-defines.h:51
#define QBENCHMARK
Definition: qbenchmark.h:76
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
GLboolean GLboolean GLboolean b
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLfloat GLfloat f
GLint GLsizei width
GLboolean GLboolean g
GLuint name
const GLubyte * c
Definition: qopenglext.h:12701
GLuint GLenum option
Definition: qopenglext.h:5929
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
Q_UNUSED(salary)
[21]
QtConcurrent::task([]{ qDebug("Hello, world!");}).spawn(FutureResult void increment(QPromise< int > &promise, int i)
[10]
QVBoxLayout * layout
QPainter painter(this)
[7]