diff options
author | John Tapsell <john.tapsell.ext@basyskom.de> | 2010-07-17 06:39:39 +0900 |
---|---|---|
committer | Mike FABIAN <mike.fabian@basyskom.de> | 2010-07-27 11:13:13 +0200 |
commit | a5834337f28f112ec7ff0a7a007cec536f2246ab (patch) | |
tree | 1213e89fd0eeca776e06ed193b07e1b6ba597872 /tests | |
parent | 4b4bc65362c99d062bbd60f34e23435e009d5a3d (diff) |
Changes: Add AllWidgets unit test, to check that all widgets paint inside of their bounding box
RevBy: TrustMe
Details:
* Check that all subitems are inside the geometry of the parent widget unless certain flags are set
* Check that we delete the view and model
* Check that all subitems are deleted
* Check that QObject::parent is not set, and QGraphicsItem::parentItem is correctly set
* Check that all painting happens inside the bounding rect
* Check that all painting happens within the view's bounding rect
* Check all of the above even when the widget is forced to size 1,1
* Check all of the above in right to left mode
Diffstat (limited to 'tests')
-rw-r--r-- | tests/ut_allwidgets/.gitignore | 1 | ||||
-rw-r--r-- | tests/ut_allwidgets/ut_allwidgets.cpp | 283 | ||||
-rw-r--r-- | tests/ut_allwidgets/ut_allwidgets.css | 6 | ||||
-rw-r--r-- | tests/ut_allwidgets/ut_allwidgets.h | 64 | ||||
-rw-r--r-- | tests/ut_allwidgets/ut_allwidgets.pro | 15 |
5 files changed, 369 insertions, 0 deletions
diff --git a/tests/ut_allwidgets/.gitignore b/tests/ut_allwidgets/.gitignore new file mode 100644 index 00000000..d2915314 --- /dev/null +++ b/tests/ut_allwidgets/.gitignore @@ -0,0 +1 @@ +ut_allwidgets diff --git a/tests/ut_allwidgets/ut_allwidgets.cpp b/tests/ut_allwidgets/ut_allwidgets.cpp new file mode 100644 index 00000000..3064b59d --- /dev/null +++ b/tests/ut_allwidgets/ut_allwidgets.cpp @@ -0,0 +1,283 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libmeegotouch. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#include "ut_allwidgets.h" +#include <QtGui/QPushButton> +#include <QtGui/QGraphicsScene> +#include <QtGui/QLabel> +#include <QtGui/QWindowsStyle> + +//Gain access to the view.. +#define protected public +#include <mwidgetcontroller.h> +#undef protected + +#include <mapplication.h> +#include <mlabel.h> +#include <mbutton.h> +#include <mtheme.h> +#include <mwidgetview.h> +#include <mbubbleitem.h> +#include <mslider.h> + +Q_DECLARE_METATYPE(MWidgetController*) +MApplication *app; + +Ut_AllWidgets::Ut_AllWidgets() +{ + static int argc = 1; + static char *argv[1] = { (char *) "./ut_allwidgets" }; + app = new MApplication(argc, argv); + m_scene = new QGraphicsScene; + MTheme::loadCSS(qApp->applicationDirPath() + "/ut_allwidgets.css"); + qRegisterMetaType<MWidgetController *>("MWidgetController *"); +} + +Ut_AllWidgets::~Ut_AllWidgets() +{ +} + +void Ut_AllWidgets::cleanupTestCase() +{ + delete m_scene; // Deletes the items in the scene, too! + m_scene = 0; + delete app; +} + +void Ut_AllWidgets::init() +{ +} + +void Ut_AllWidgets::cleanup() +{ +} + +void Ut_AllWidgets::debugDisplayImage(const QImage &image, int seconds) +{ + debugDisplayPixmap(QPixmap::fromImage(image), seconds); +} +void Ut_AllWidgets::debugDisplayPixmap(const QPixmap &pixmap, int seconds) +{ + QLabel *label = new QLabel; + label->setStyle(new QWindowsStyle); + label->setPixmap(pixmap); + label->show(); + QTest::qWait(seconds*1000); + delete label; +} + +bool Ut_AllWidgets::paintAndTestWidget(QGraphicsWidget *widget, bool strict) +{ + //Because of the async nature, make sure we've got the pixmaps + app->processEvents(); + //Create a pixmap big enough for the widget plus room to check if it paints outside of its bounding box + QRectF boundingRect = widget->mapToScene(widget->boundingRect()).boundingRect(); + if(!(widget->flags() & QGraphicsItem::ItemClipsChildrenToShape)) + boundingRect |= widget->mapToScene(widget->childrenBoundingRect()).boundingRect(); + QSize size = boundingRect.size().toSize(); + + QImage image(size + QSize(200,200), QImage::Format_ARGB32); + image.fill(Qt::transparent); + + QPointF offset = QPointF(100,100) - boundingRect.topLeft(); + QRectF pixmapBoundingRect = boundingRect.translated(offset); + QRectF pixmapGeometry = widget->geometry().translated(offset); + + { + QPainter painter(&image); + m_scene->render(&painter, QRectF(0,0,image.width(), image.height()), boundingRect.adjusted(-100,-100,100,100)); + //Draw in the bounding rect and geometry, for showing to the user + if(pixmapBoundingRect.adjusted(0,0,-1,-1).isValid()) { + painter.setPen(Qt::red); + painter.drawRect(pixmapBoundingRect.adjusted(0,0,-1,-1)); + } + if(pixmapGeometry.adjusted(0,0,-1,-1).isValid()) { + painter.setPen(Qt::blue); + painter.drawRect(pixmapGeometry.adjusted(0,0,-1,-1)); + } + } + + //Now check that we haven't painted outside of the bounding box + for(int y = 0; y < image.height(); ++y) + for(int x = 0; x < image.width(); ++x) { + if(pixmapBoundingRect.contains(x,y)) { + if(!pixmapGeometry.contains(x,y) && image.pixel(x,y) != Qt::transparent) { + //It's not wrong to paint outside of your geometry but inside the bounding rect, but it is unusual + qWarning() << "Pixel at" << x << y << "is not transparent but geometry is" << pixmapGeometry; + if(strict) { + debugDisplayImage(image, 10); + return false; + } + } + } else if(image.pixel(x,y) != Qt::transparent) { + qWarning() << "Pixel at" << x << y << "is not transparent (" << QColor(image.pixel(x,y)) << ") but bounding rect is" << pixmapBoundingRect; +/* { + QPainter painter(&image); + painter.setPen(Qt::red); + painter.drawEllipse(QPoint(x,y),5,5); + }*/ + debugDisplayImage(image, 10); + return false; + } + } + // Uncomment to see what the widget looks like: + // debugDisplayImage(image, 3); + return true; +} +bool Ut_AllWidgets::checkChildrenBoundingRect(const QGraphicsWidget *widget) const +{ + //Make sure the widget has a chance to relayout if it needs to + app->processEvents(); + // Although it is legal to have children outside the parent's geometry, I think we should + // have a policy to not allow it + QRectF childrenBoundingRect = widget->childrenBoundingRect(); + if(!childrenBoundingRect.isEmpty() && !widget->boundingRect().contains(childrenBoundingRect)) { + // If this flag has been set, then it's okay to have children outside + if(widget->flags() & QGraphicsItem::ItemClipsChildrenToShape) + return true; + qWarning() << "The widget's children are outside of the parent's bounding rect. Children:" << childrenBoundingRect << "Parent:" << widget->boundingRect(); + return false; + } + return true; +} +QList< QPointer<QGraphicsObject> > Ut_AllWidgets::getAllLayoutItemObjects(QGraphicsLayoutItem *item) +{ + QList< QPointer<QGraphicsObject> > children; + if(!item) + return children; + + QGraphicsObject* object = dynamic_cast<QGraphicsObject *>(item->graphicsItem()); + if(object) + children << object; + if(item->isLayout()) { + QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item); + for(int i = 0 ; i < layout->count(); i++) + children << getAllLayoutItemObjects(layout->itemAt(i)); + } + + return children; +} +QList< QPointer<QGraphicsObject> > Ut_AllWidgets::getAllSubWidgets(QGraphicsItem *item) +{ + QList< QPointer<QGraphicsObject> > children; + foreach(QGraphicsItem *child, item->childItems()) { + QGraphicsObject *object = child->toGraphicsObject(); + if(object) + children << object; + children << getAllSubWidgets(child); + } + + if(item->isWidget()) + children << getAllLayoutItemObjects( static_cast<QGraphicsWidget *>(item)->layout() ); + + return children; +} + +bool Ut_AllWidgets::checkSubWidgets(MWidgetController * parentWidget, QList< QPointer<QGraphicsObject> > subwidgets) { + foreach(const QPointer<QGraphicsObject> &widget, subwidgets) { + if(widget->parent()) { + qWarning() << "A subwidget has QObject::parent set - it is better to keep this NULL and let QGraphicsItem::parentItem() delete the object"; + return false; + } + QGraphicsItem *parent = widget; + while(parent != parentWidget) { + if(!parent) { + qDebug() << "A subwidget does not have parentItem pointing to the widget."; + return false; + } + parent = parent->parentWidget(); + }; + } + return true; +} +void Ut_AllWidgets::testAllWidgets_data() +{ + QTest::addColumn<MWidgetController*>("widget"); + QTest::addColumn<bool>("strict"); //Make warnings into errors. + QTest::addColumn<bool>("leftToRight"); + +#define TEST_WIDGET(description, widget, strict) \ + QTest::newRow(description "(LTR)") << static_cast<MWidgetController*>(widget) << (strict) << false; \ + QTest::newRow(description "(RTL)") << static_cast<MWidgetController*>(widget) << (strict) << true; + + TEST_WIDGET("MLabel - simple", new MLabel("Hello there"), true); + TEST_WIDGET("MLabel - simple multiline", new MLabel("Hello there\nHow are you?"), true); + TEST_WIDGET("MLabel - rich", new MLabel("<qt><b>Hello</b> there"), true); + TEST_WIDGET("MButton - simple", new MButton("Hello there"), true); + TEST_WIDGET("MButton - simple multiline", new MButton("Hello there\nHow are you?"), true); + TEST_WIDGET("MButton - rich", new MButton("<qt><b>Hello</b> there"), true); + TEST_WIDGET("MSlider", new MSlider, true); +} + + +void Ut_AllWidgets::testAllWidgets() +{ + QFETCH(MWidgetController *, widget); + QFETCH(bool, strict); + QFETCH(bool, leftToRight); + widget->setLayoutDirection(leftToRight?Qt::LeftToRight:Qt::RightToLeft); + + m_scene->addItem(widget); + widget->style(); + + widget->setMinimumSize(0,0); + widget->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + + static_cast<MWidget *>(widget)->setGeometry(100,100,100,100); + + QVERIFY(checkChildrenBoundingRect(widget) || !strict); + QVERIFY(paintAndTestWidget(widget, strict)); + + //Now resize to just 1,1 and make sure it paints at maximum only 1 pixel + static_cast<MWidget *>(widget)->setGeometry(100,100,1,1); + + QVERIFY(checkChildrenBoundingRect(widget) || !strict); + QVERIFY(paintAndTestWidget(widget, strict)); + + //Now resize to 0,0 and make sure it paints nothing at all + static_cast<MWidget *>(widget)->setGeometry(100,100,0,0); + + QVERIFY(checkChildrenBoundingRect(widget) || !strict); + QVERIFY(paintAndTestWidget(widget, strict)); + + // Check that the CSS values override + widget->setObjectName("cssWidth"); + QCOMPARE(widget->minimumSize(), QSizeF(0,0)); + QCOMPARE(widget->maximumSize(), QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); + widget->setMinimumSize(-1,-1); + widget->setMaximumSize(-1,-1); + QCOMPARE(widget->minimumSize().width() - widget->style()->marginLeft() - widget->style()->marginRight(), 9.0); //The values in CSS should now take precedence + QCOMPARE(widget->maximumSize().width() - widget->style()->marginLeft() - widget->style()->marginRight(), 11.0); + + // Test for memory leaks by checking that the view, model and all children are deleted + QList< QPointer<QGraphicsObject> > subwidgets = getAllSubWidgets(widget); + QVERIFY(checkSubWidgets(widget, subwidgets)); + QPointer<MWidgetView> view = const_cast<MWidgetView*>(widget->view()); + QPointer<MWidgetModel> model = widget->model(); + delete widget; + foreach(const QPointer<QGraphicsObject> subwidget, subwidgets) { + QVERIFY(!subwidget); + } + + QVERIFY(!view); + QVERIFY(!model); +} + + +QTEST_APPLESS_MAIN(Ut_AllWidgets) diff --git a/tests/ut_allwidgets/ut_allwidgets.css b/tests/ut_allwidgets/ut_allwidgets.css new file mode 100644 index 00000000..3a8f7b0a --- /dev/null +++ b/tests/ut_allwidgets/ut_allwidgets.css @@ -0,0 +1,6 @@ +MWidgetStyle#cssWidth { + minimum-size: 9 -1; + preferred-size: 10 -1; + maximum-size: 11 -1; +} + diff --git a/tests/ut_allwidgets/ut_allwidgets.h b/tests/ut_allwidgets/ut_allwidgets.h new file mode 100644 index 00000000..6b0cdc7f --- /dev/null +++ b/tests/ut_allwidgets/ut_allwidgets.h @@ -0,0 +1,64 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libmeegotouch. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#ifndef UT_MLAYOUT_H +#define UT_MLAYOUT_H + +#include <QtTest/QtTest> +#include <QObject> +#include <QPointer> +#include <QList> + +#include <mlayout.h> + +class QGraphicsScene; +class MWidgetController; +class QGraphicsProxyWidget; +class QPushButton; + +class Ut_AllWidgets : public QObject +{ + Q_OBJECT + +public: + Ut_AllWidgets(); + virtual ~Ut_AllWidgets(); + +private slots: + void cleanupTestCase(); + void init(); + void cleanup(); + + void testAllWidgets_data(); + void testAllWidgets(); + +private: + bool checkSubWidgets(MWidgetController * parentWidget, QList< QPointer<QGraphicsObject> > subwidgets); + void debugDisplayPixmap(const QPixmap &pixmap, int seconds); + void debugDisplayImage(const QImage &image, int seconds); + bool paintAndTestWidget(QGraphicsWidget *widget, bool strict); + bool checkChildrenBoundingRect(const QGraphicsWidget *widget) const; + QList< QPointer<QGraphicsObject> > getAllLayoutItemObjects(QGraphicsLayoutItem *item); + QList< QPointer<QGraphicsObject> > getAllSubWidgets(QGraphicsItem *widget); + QGraphicsWidget *m_form; + QGraphicsScene *m_scene; +}; + +#endif // Header guard + diff --git a/tests/ut_allwidgets/ut_allwidgets.pro b/tests/ut_allwidgets/ut_allwidgets.pro new file mode 100644 index 00000000..719bb3af --- /dev/null +++ b/tests/ut_allwidgets/ut_allwidgets.pro @@ -0,0 +1,15 @@ +include(../common_top.pri) +TARGET = ut_allwidgets + +# unit test and unit +SOURCES += \ + ut_allwidgets.cpp \ + +# unit test and unit +HEADERS += \ + ut_allwidgets.h + +support_files.files += \ + ut_allwidgets.css + +include(../common_bot.pri) |