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 <QtTest/QtTestWidgets>
31#include <QtWidgets/qdesktopwidget.h>
32#include <QtWidgets/qgraphicseffect.h>
33#include <QtWidgets/qgraphicsview.h>
34#include <QtWidgets/qgraphicsscene.h>
35#include <QtWidgets/qgraphicsitem.h>
36#include <QtWidgets/qgraphicswidget.h>
37#include <QtWidgets/qstyleoption.h>
38
39#include <private/qgraphicseffect_p.h>
40
41class tst_QGraphicsEffect : public QObject
42{
43 Q_OBJECT
44public slots:
45 void initTestCase();
46
47private slots:
48 void setEnabled();
49 void source();
50 void boundingRectFor();
51 void boundingRect();
52 void boundingRect2();
53 void draw();
54 void opacity();
55 void grayscale();
56 void colorize();
57 void drawPixmapItem();
58 void deviceCoordinateTranslateCaching();
59 void inheritOpacity();
60 void dropShadowClipping();
61 void childrenVisibilityShouldInvalidateCache();
62 void prepareGeometryChangeInvalidateCache();
63 void itemHasNoContents();
64};
65
66void tst_QGraphicsEffect::initTestCase()
67{}
68
69class CustomItem : public QGraphicsRectItem
70{
71public:
72 CustomItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent = 0)
73 : QGraphicsRectItem(x, y, width, height, parent), numRepaints(0),
74 m_painter(0), m_styleOption(0)
75 {}
76
77 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
78 {
79 m_painter = painter;
80 m_styleOption = option;
81 ++numRepaints;
82 QGraphicsRectItem::paint(painter, option, widget);
83 }
84
85 void reset()
86 {
87 numRepaints = 0;
88 m_painter = 0;
89 m_styleOption = 0;
90 }
91
92 int numRepaints;
93 QPainter *m_painter;
94 const QStyleOption *m_styleOption;
95};
96
97class CustomEffect : public QGraphicsEffect
98{
99public:
100 CustomEffect()
101 : QGraphicsEffect(), numRepaints(0), m_margin(10),
102 doNothingInDraw(false), m_painter(0), m_styleOption(0), m_source(0), m_opacity(1.0)
103 {}
104
105 QRectF boundingRectFor(const QRectF &rect) const
106 { return rect.adjusted(xp1: -m_margin, yp1: -m_margin, xp2: m_margin, yp2: m_margin); }
107
108 void reset()
109 {
110 numRepaints = 0;
111 m_sourceChangedFlags = QGraphicsEffect::ChangeFlags();
112 m_painter = 0;
113 m_styleOption = 0;
114 m_source = 0;
115 m_opacity = 1.0;
116 }
117
118 void setMargin(int margin)
119 {
120 m_margin = margin;
121 updateBoundingRect();
122 }
123
124 int margin() const
125 { return m_margin; }
126
127 void draw(QPainter *painter)
128 {
129 ++numRepaints;
130 if (doNothingInDraw)
131 return;
132 m_source = source();
133 m_painter = painter;
134 m_styleOption = source()->styleOption();
135 m_opacity = painter->opacity();
136 drawSource(painter);
137 }
138
139 void sourceChanged(QGraphicsEffect::ChangeFlags flags)
140 { m_sourceChangedFlags |= flags; }
141
142 int numRepaints;
143 int m_margin;
144 QGraphicsEffect::ChangeFlags m_sourceChangedFlags;
145 bool doNothingInDraw;
146 QPainter *m_painter;
147 const QStyleOption *m_styleOption;
148 QGraphicsEffectSource *m_source;
149 qreal m_opacity;
150};
151
152void tst_QGraphicsEffect::setEnabled()
153{
154 CustomEffect effect;
155 QVERIFY(effect.isEnabled());
156
157 effect.setEnabled(false);
158 QVERIFY(!effect.isEnabled());
159}
160
161void tst_QGraphicsEffect::source()
162{
163 QPointer<CustomEffect> effect = new CustomEffect;
164 QVERIFY(!effect->source());
165 QVERIFY(!effect->m_sourceChangedFlags);
166
167 // Install effect on QGraphicsItem.
168 QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
169 item->setGraphicsEffect(effect);
170 QVERIFY(effect->source());
171 QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
172 QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceAttached);
173 effect->reset();
174
175 // Make sure disabling/enabling the effect doesn't change the source.
176 effect->setEnabled(false);
177 QVERIFY(effect->source());
178 QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
179 QVERIFY(!effect->m_sourceChangedFlags);
180 effect->reset();
181
182 effect->setEnabled(true);
183 QVERIFY(effect->source());
184 QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
185 QVERIFY(!effect->m_sourceChangedFlags);
186 effect->reset();
187
188 // Uninstall effect on QGraphicsItem.
189 effect->reset();
190 item->setGraphicsEffect(0);
191 QVERIFY(!effect);
192 effect = new CustomEffect;
193
194 // The item takes ownership and should delete the effect when destroyed.
195 item->setGraphicsEffect(effect);
196 QPointer<QGraphicsEffectSource> source = effect->source();
197 QVERIFY(source);
198 QCOMPARE(source->graphicsItem(), (const QGraphicsItem*)item);
199 delete item;
200 QVERIFY(!effect);
201 QVERIFY(!source);
202}
203
204void tst_QGraphicsEffect::boundingRectFor()
205{
206 CustomEffect effect;
207 int margin = effect.margin();
208 const QRectF source(0, 0, 100, 100);
209 QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin));
210
211 effect.setMargin(margin = 20);
212 QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin));
213}
214
215void tst_QGraphicsEffect::boundingRect()
216{
217 // No source; empty bounding rect.
218 CustomEffect *effect = new CustomEffect;
219 QCOMPARE(effect->boundingRect(), QRectF());
220
221 // Install effect on QGraphicsItem.
222 QRectF itemRect(0, 0, 100, 100);
223 QGraphicsRectItem *item = new QGraphicsRectItem;
224 item->setPen(QPen(Qt::black, 0));
225 item->setRect(itemRect);
226 item->setGraphicsEffect(effect);
227 int margin = effect->margin();
228 QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
229 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
230
231 // Make sure disabling/enabling the effect doesn't change the bounding rect.
232 effect->setEnabled(false);
233 QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
234 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
235 effect->setEnabled(true);
236 QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
237 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
238
239 // Change effect margins.
240 effect->setMargin(margin = 20);
241 QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin));
242 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect));
243
244 // Uninstall effect on QGraphicsItem.
245 QPointer<CustomEffect> ptr = effect;
246 item->setGraphicsEffect(0);
247 QVERIFY(!ptr);
248
249 delete item;
250}
251
252void tst_QGraphicsEffect::boundingRect2()
253{
254 CustomEffect *effect = new CustomEffect;
255 QGraphicsRectItem *root = new QGraphicsRectItem;
256 root->setPen(QPen(Qt::black, 0));
257 root->setGraphicsEffect(effect);
258
259 QGraphicsRectItem *child = new QGraphicsRectItem;
260 QRectF childRect(0, 0, 100, 100);
261 child->setPen(QPen(Qt::black, 0));
262 child->setFlag(flag: QGraphicsItem::ItemClipsChildrenToShape);
263 child->setRect(childRect);
264 child->setParentItem(root);
265
266 QGraphicsRectItem *grandChild = new QGraphicsRectItem;
267 QRectF grandChildRect(0, 0, 200, 200);
268 grandChild->setPen(QPen(Qt::black, 0));
269 grandChild->setRect(grandChildRect);
270 grandChild->setParentItem(child);
271
272 // Make sure the effect's bounding rect is clipped to the child's bounding rect.
273 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect));
274
275 // Disable ItemClipsChildrenToShape; effect's bounding rect is no longer clipped.
276 child->setFlag(flag: QGraphicsItem::ItemClipsChildrenToShape, enabled: false);
277 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
278
279 // Add root item to a scene, do the same tests as above. Results should be the same.
280 QGraphicsScene scene;
281 scene.addItem(item: root);
282
283 child->setFlag(flag: QGraphicsItem::ItemClipsChildrenToShape);
284 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect));
285
286 child->setFlag(flag: QGraphicsItem::ItemClipsChildrenToShape, enabled: false);
287 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
288
289 // Now add the scene to a view, results should be the same.
290 QGraphicsView view(&scene);
291
292 child->setFlag(flag: QGraphicsItem::ItemClipsChildrenToShape);
293 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect));
294
295 child->setFlag(flag: QGraphicsItem::ItemClipsChildrenToShape, enabled: false);
296 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
297
298 CustomEffect *childEffect = new CustomEffect;
299 child->setGraphicsEffect(childEffect);
300 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childEffect->boundingRectFor(childRect | grandChildRect)));
301
302 child->setGraphicsEffect(0);
303 QCOMPARE(effect->boundingRect(), effect->boundingRectFor(childRect | grandChildRect));
304}
305
306void tst_QGraphicsEffect::draw()
307{
308 QGraphicsScene scene;
309 CustomItem *item = new CustomItem(0, 0, 100, 100);
310 scene.addItem(item);
311
312 QGraphicsView view(&scene);
313 view.show();
314 QVERIFY(QTest::qWaitForWindowExposed(&view));
315 QTRY_VERIFY(item->numRepaints > 0);
316 QCoreApplication::processEvents(); // Process all queued paint events
317 item->reset();
318
319 // Make sure installing the effect triggers a repaint.
320 CustomEffect *effect = new CustomEffect;
321 item->setGraphicsEffect(effect);
322 QTRY_COMPARE(effect->numRepaints, 1);
323 QTRY_COMPARE(item->numRepaints, 1);
324
325 // Make sure QPainter* and QStyleOptionGraphicsItem* stays persistent
326 // during QGraphicsEffect::draw/QGraphicsItem::paint.
327 QVERIFY(effect->m_painter);
328 QCOMPARE(effect->m_painter, item->m_painter);
329 QCOMPARE(effect->m_styleOption, item->m_styleOption);
330 // Make sure QGraphicsEffect::source is persistent.
331 QCOMPARE(effect->m_source, effect->source());
332 effect->reset();
333 item->reset();
334
335 // Make sure updating the source triggers a repaint.
336 item->update();
337 QTRY_COMPARE(effect->numRepaints, 1);
338 QTRY_COMPARE(item->numRepaints, 1);
339 QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceInvalidated);
340 effect->reset();
341 item->reset();
342
343 // Make sure changing the effect's bounding rect triggers a repaint.
344 effect->setMargin(20);
345 QTRY_COMPARE(effect->numRepaints, 1);
346 QTRY_COMPARE(item->numRepaints, 1);
347 effect->reset();
348 item->reset();
349
350 // Make sure change the item's bounding rect triggers a repaint.
351 item->setRect(ax: 0, ay: 0, w: 50, h: 50);
352 QTRY_COMPARE(effect->numRepaints, 1);
353 QTRY_COMPARE(item->numRepaints, 1);
354 QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceBoundingRectChanged);
355 effect->reset();
356 item->reset();
357
358 // Make sure the effect is the one to issue a repaint of the item.
359 effect->doNothingInDraw = true;
360 item->update();
361 QTRY_COMPARE(effect->numRepaints, 1);
362 QCOMPARE(item->numRepaints, 0);
363 effect->doNothingInDraw = false;
364 effect->reset();
365 item->reset();
366
367 // Make sure we update the source when disabling/enabling the effect.
368 effect->setEnabled(false);
369 QTRY_COMPARE(item->numRepaints, 1);
370 QCOMPARE(effect->numRepaints, 0);
371 effect->reset();
372 item->reset();
373
374 effect->setEnabled(true);
375 QTRY_COMPARE(effect->numRepaints, 1);
376 QTRY_COMPARE(item->numRepaints, 1);
377 effect->reset();
378 item->reset();
379
380 // Effect is already enabled; nothing should happen.
381 effect->setEnabled(true);
382 QTest::qWait(ms: 50);
383 QCOMPARE(effect->numRepaints, 0);
384 QCOMPARE(item->numRepaints, 0);
385
386 // Make sure uninstalling an effect triggers a repaint.
387 QPointer<CustomEffect> ptr = effect;
388 item->setGraphicsEffect(0);
389 QVERIFY(!ptr);
390 QTRY_COMPARE(item->numRepaints, 1);
391}
392
393void tst_QGraphicsEffect::opacity()
394{
395 // Make sure the painter's opacity is correct in QGraphicsEffect::draw.
396 QGraphicsScene scene;
397 CustomItem *item = new CustomItem(0, 0, 100, 100);
398 item->setOpacity(0.5);
399 CustomEffect *effect = new CustomEffect;
400 item->setGraphicsEffect(effect);
401 scene.addItem(item);
402
403 QGraphicsView view(&scene);
404 view.show();
405 QVERIFY(QTest::qWaitForWindowExposed(&view));
406 QTRY_VERIFY(effect->numRepaints > 0);
407 QCOMPARE(effect->m_opacity, qreal(0.5));
408}
409
410void tst_QGraphicsEffect::grayscale()
411{
412 if (qApp->desktop()->depth() < 24)
413 QSKIP("Test only works on 32 bit displays");
414
415 QGraphicsScene scene(0, 0, 100, 100);
416
417 QGraphicsRectItem *item = scene.addRect(x: 0, y: 0, w: 50, h: 50);
418 item->setPen(Qt::NoPen);
419 item->setBrush(QColor(122, 193, 66)); // Qt light green
420
421 QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect;
422 effect->setColor(Qt::black);
423 item->setGraphicsEffect(effect);
424
425 QPainter painter;
426 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
427
428 image.fill(pixel: 0);
429 painter.begin(&image);
430 painter.setRenderHint(hint: QPainter::Antialiasing);
431 scene.render(painter: &painter);
432 painter.end();
433
434 QCOMPARE(image.pixel(10, 10), qRgb(148, 148, 148));
435
436 effect->setStrength(0.5);
437
438 image.fill(pixel: 0);
439 painter.begin(&image);
440 painter.setRenderHint(hint: QPainter::Antialiasing);
441 scene.render(painter: &painter);
442 painter.end();
443
444 QCOMPARE(image.pixel(10, 10), qRgb(135, 171, 107));
445
446 effect->setStrength(0.0);
447
448 image.fill(pixel: 0);
449 painter.begin(&image);
450 painter.setRenderHint(hint: QPainter::Antialiasing);
451 scene.render(painter: &painter);
452 painter.end();
453
454 QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66));
455}
456
457void tst_QGraphicsEffect::colorize()
458{
459 if (qApp->desktop()->depth() < 24)
460 QSKIP("Test only works on 32 bit displays");
461
462 QGraphicsScene scene(0, 0, 100, 100);
463
464 QGraphicsRectItem *item = scene.addRect(x: 0, y: 0, w: 50, h: 50);
465 item->setPen(Qt::NoPen);
466 item->setBrush(QColor(122, 193, 66)); // Qt light green
467
468 QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect;
469 effect->setColor(QColor(102, 153, 51)); // Qt dark green
470 item->setGraphicsEffect(effect);
471
472 QPainter painter;
473 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
474
475 image.fill(pixel: 0);
476 painter.begin(&image);
477 painter.setRenderHint(hint: QPainter::Antialiasing);
478 scene.render(painter: &painter);
479 painter.end();
480
481 QCOMPARE(image.pixel(10, 10), qRgb(191, 212, 169));
482
483 effect->setStrength(0.5);
484
485 image.fill(pixel: 0);
486 painter.begin(&image);
487 painter.setRenderHint(hint: QPainter::Antialiasing);
488 scene.render(painter: &painter);
489 painter.end();
490
491 QCOMPARE(image.pixel(10, 10), qRgb(156, 203, 117));
492
493 effect->setStrength(0.0);
494
495 image.fill(pixel: 0);
496 painter.begin(&image);
497 painter.setRenderHint(hint: QPainter::Antialiasing);
498 scene.render(painter: &painter);
499 painter.end();
500
501 QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66));
502}
503
504class PixmapItemEffect : public QGraphicsEffect
505{
506public:
507 PixmapItemEffect(const QPixmap &source)
508 : QGraphicsEffect()
509 , pixmap(source)
510 , repaints(0)
511 {}
512
513 QRectF boundingRectFor(const QRectF &rect) const
514 { return rect; }
515
516 void draw(QPainter *painter)
517 {
518 QCOMPARE(sourcePixmap(Qt::LogicalCoordinates).handle(), pixmap.handle());
519 QVERIFY((painter->worldTransform().type() <= QTransform::TxTranslate) == (sourcePixmap(Qt::DeviceCoordinates).handle() == pixmap.handle()));
520
521 ++repaints;
522 }
523 QPixmap pixmap;
524 int repaints;
525};
526
527void tst_QGraphicsEffect::drawPixmapItem()
528{
529 QImage image(32, 32, QImage::Format_RGB32);
530 QPainter p(&image);
531 p.fillRect(x: 0, y: 0, w: 32, h: 16, c: Qt::blue);
532 p.fillRect(x: 0, y: 16, w: 32, h: 16, c: Qt::red);
533 p.end();
534
535 QGraphicsScene scene;
536 QGraphicsPixmapItem *item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
537 scene.addItem(item);
538
539 PixmapItemEffect *effect = new PixmapItemEffect(item->pixmap());
540 item->setGraphicsEffect(effect);
541
542 QGraphicsView view(&scene);
543 view.show();
544 QVERIFY(QTest::qWaitForWindowExposed(&view));
545 QTRY_VERIFY(effect->repaints >= 1);
546
547 item->setTransform(matrix: QTransform().rotate(a: 180), combine: true);
548
549 QTRY_VERIFY(effect->repaints >= 2);
550}
551
552class DeviceEffect : public QGraphicsEffect
553{
554public:
555 QRectF boundingRectFor(const QRectF &rect) const
556 { return rect; }
557
558 void draw(QPainter *painter)
559 {
560 QPoint offset;
561 QPixmap pixmap = sourcePixmap(system: Qt::DeviceCoordinates, offset: &offset, mode: QGraphicsEffect::NoPad);
562
563 if (pixmap.isNull())
564 return;
565
566 painter->save();
567 painter->setWorldTransform(matrix: QTransform());
568 painter->drawPixmap(p: offset, pm: pixmap);
569 painter->restore();
570 }
571};
572
573void tst_QGraphicsEffect::deviceCoordinateTranslateCaching()
574{
575 QGraphicsScene scene;
576 CustomItem *item = new CustomItem(0, 0, 10, 10);
577 scene.addItem(item);
578 scene.setSceneRect(x: 0, y: 0, w: 50, h: 0);
579
580 item->setGraphicsEffect(new DeviceEffect);
581 item->setPen(Qt::NoPen);
582 item->setBrush(Qt::red);
583
584 QGraphicsView view(&scene);
585 view.show();
586 QVERIFY(QTest::qWaitForWindowExposed(&view));
587
588 QTRY_VERIFY(item->numRepaints >= 1);
589 int numRepaints = item->numRepaints;
590
591 item->setTransform(matrix: QTransform::fromTranslate(dx: 10, dy: 0), combine: true);
592
593 QTRY_COMPARE(item->numRepaints, numRepaints);
594}
595
596void tst_QGraphicsEffect::inheritOpacity()
597{
598 QGraphicsScene scene;
599 QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 10, 10);
600 CustomItem *item = new CustomItem(0, 0, 10, 10, rectItem);
601
602 scene.addItem(item: rectItem);
603
604 item->setGraphicsEffect(new DeviceEffect);
605 item->setPen(Qt::NoPen);
606 item->setBrush(Qt::red);
607
608 rectItem->setOpacity(0.5);
609
610 QGraphicsView view(&scene);
611 view.show();
612 QVERIFY(QTest::qWaitForWindowExposed(&view));
613
614 QTRY_VERIFY(item->numRepaints >= 1);
615
616 int numRepaints = item->numRepaints;
617
618 rectItem->setOpacity(1);
619
620 // item should have been rerendered due to opacity changing
621 QTRY_VERIFY(item->numRepaints > numRepaints);
622}
623
624void tst_QGraphicsEffect::dropShadowClipping()
625{
626 QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
627 img.fill(pixel: 0xffffffff);
628
629 QGraphicsScene scene;
630 QGraphicsRectItem *item = new QGraphicsRectItem(-5, -500, 10, 1000);
631 item->setGraphicsEffect(new QGraphicsDropShadowEffect);
632 item->setPen(Qt::NoPen);
633 item->setBrush(Qt::red);
634
635 scene.addItem(item);
636
637 QPainter p(&img);
638 scene.render(painter: &p, target: img.rect(), source: QRect(-64, -64, 128, 128));
639 p.end();
640
641 for (int y = 1; y < img.height(); ++y)
642 for (int x = 0; x < img.width(); ++x)
643 QCOMPARE(img.pixel(x, y), img.pixel(x, y-1));
644}
645
646class MyGraphicsItem : public QGraphicsWidget
647{
648public:
649 MyGraphicsItem(QGraphicsItem *parent = 0) :
650 QGraphicsWidget(parent), nbPaint(0)
651 {}
652 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
653 {
654 nbPaint++;
655 QGraphicsWidget::paint(painter, option, widget);
656 }
657 int nbPaint;
658};
659
660void tst_QGraphicsEffect::childrenVisibilityShouldInvalidateCache()
661{
662 QGraphicsScene scene;
663 MyGraphicsItem parent;
664 parent.resize(w: 200, h: 200);
665 QGraphicsWidget child(&parent);
666 child.resize(w: 200, h: 200);
667 child.setVisible(false);
668 scene.addItem(item: &parent);
669 QGraphicsView view(&scene);
670 view.show();
671 QVERIFY(QTest::qWaitForWindowExposed(&view));
672 QTRY_VERIFY(parent.nbPaint >= 1);
673 //we set an effect on the parent
674 parent.setGraphicsEffect(new QGraphicsDropShadowEffect(&parent));
675 //flush the events
676 QApplication::processEvents();
677 //new effect applied->repaint
678 QVERIFY(parent.nbPaint >= 2);
679 child.setVisible(true);
680 //flush the events
681 QApplication::processEvents();
682 //a new child appears we need to redraw the effect.
683 QVERIFY(parent.nbPaint >= 3);
684}
685
686void tst_QGraphicsEffect::prepareGeometryChangeInvalidateCache()
687{
688 MyGraphicsItem *item = new MyGraphicsItem;
689 item->resize(w: 200, h: 200);
690
691 QGraphicsScene scene;
692 scene.addItem(item);
693
694 QGraphicsView view(&scene);
695 view.show();
696 QVERIFY(QTest::qWaitForWindowExposed(&view));
697 QTRY_VERIFY(item->nbPaint >= 1);
698
699 item->nbPaint = 0;
700 item->setGraphicsEffect(new QGraphicsDropShadowEffect);
701 QTRY_COMPARE(item->nbPaint, 1);
702
703 item->nbPaint = 0;
704 item->resize(w: 300, h: 300);
705 QTRY_COMPARE(item->nbPaint, 1);
706
707 item->nbPaint = 0;
708 item->setPos(item->pos() + QPointF(10, 10));
709 QTest::qWait(ms: 50);
710 QCOMPARE(item->nbPaint, 0);
711}
712
713void tst_QGraphicsEffect::itemHasNoContents()
714{
715 QGraphicsRectItem *parent = new QGraphicsRectItem;
716 parent->setFlag(flag: QGraphicsItem::ItemHasNoContents);
717
718 MyGraphicsItem *child = new MyGraphicsItem;
719 child->setParentItem(parent);
720 child->resize(w: 200, h: 200);
721
722 QGraphicsScene scene;
723 scene.addItem(item: parent);
724
725 QGraphicsView view(&scene);
726 view.show();
727 QVERIFY(QTest::qWaitForWindowExposed(&view));
728 QTRY_VERIFY(child->nbPaint >= 1);
729
730 CustomEffect *effect = new CustomEffect;
731 parent->setGraphicsEffect(effect);
732 QTRY_VERIFY(effect->numRepaints >= 1);
733
734 for (int i = 0; i < 3; ++i) {
735 effect->reset();
736 effect->update();
737 QTRY_VERIFY(effect->numRepaints >= 1);
738 }
739}
740
741QTEST_MAIN(tst_QGraphicsEffect)
742#include "tst_qgraphicseffect.moc"
743
744

source code of qtbase/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp