diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2017-10-23 15:19:09 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2017-10-23 19:43:32 +0000 |
commit | 4d452d5dff2d12a9a44277798f2a70902a3d1891 (patch) | |
tree | 3055096e4ac3268ca357f9b9407d9433ccc85f1a | |
parent | e04b7c4b7ba2808215825de23cd6d6606cb9102f (diff) |
QQuickIconImage: fix crash with image providers
QQuickImageBase::load() cannot call until the component creation is
completed, because it requires an associated QML engine. All calls to
updateIcon() are guarded with the appropriate isComponentComplete()
check, but the sourceSizeChanged() signal was connected directly to
updateIcon(). Establish the signal-slot connection at component
completion to avoid calling updateIcon() to soon.
Task-number: QTBUG-63959
Change-Id: I3c935291796dbae031d2728e1d51c55596a51cd0
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r-- | src/quickcontrols2/qquickiconimage.cpp | 3 | ||||
-rw-r--r-- | tests/auto/qquickiconimage/data/imageProvider.qml | 9 | ||||
-rw-r--r-- | tests/auto/qquickiconimage/tst_qquickiconimage.cpp | 39 |
3 files changed, 49 insertions, 2 deletions
diff --git a/src/quickcontrols2/qquickiconimage.cpp b/src/quickcontrols2/qquickiconimage.cpp index c628c7ae..885bc7f9 100644 --- a/src/quickcontrols2/qquickiconimage.cpp +++ b/src/quickcontrols2/qquickiconimage.cpp @@ -125,9 +125,7 @@ qreal QQuickIconImagePrivate::calculateDevicePixelRatio() const QQuickIconImage::QQuickIconImage(QQuickItem *parent) : QQuickImage(*(new QQuickIconImagePrivate), parent) { - Q_D(QQuickIconImage); setFillMode(Pad); - QObjectPrivate::connect(this, &QQuickImageBase::sourceSizeChanged, d, &QQuickIconImagePrivate::updateIcon); } QString QQuickIconImage::name() const @@ -183,6 +181,7 @@ void QQuickIconImage::componentComplete() Q_D(QQuickIconImage); QQuickImage::componentComplete(); d->updateIcon(); + QObjectPrivate::connect(this, &QQuickImageBase::sourceSizeChanged, d, &QQuickIconImagePrivate::updateIcon); } void QQuickIconImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) diff --git a/tests/auto/qquickiconimage/data/imageProvider.qml b/tests/auto/qquickiconimage/data/imageProvider.qml new file mode 100644 index 00000000..0d7d3033 --- /dev/null +++ b/tests/auto/qquickiconimage/data/imageProvider.qml @@ -0,0 +1,9 @@ +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T + +IconLabel { + icon.color: "transparent" + icon.source: "image://provider/red" +} diff --git a/tests/auto/qquickiconimage/tst_qquickiconimage.cpp b/tests/auto/qquickiconimage/tst_qquickiconimage.cpp index 4e4afb13..77b860a2 100644 --- a/tests/auto/qquickiconimage/tst_qquickiconimage.cpp +++ b/tests/auto/qquickiconimage/tst_qquickiconimage.cpp @@ -35,6 +35,7 @@ #include <QtQml/qqmlfileselector.h> #include <QtQuick/qquickitem.h> #include <QtQuick/qquickview.h> +#include <QtQuick/qquickimageprovider.h> #include <QtQuick/qquickitemgrabresult.h> #include <QtQuick/private/qquickimage_p.h> #include <QtQuickControls2/private/qquickiconimage_p.h> @@ -67,6 +68,7 @@ private slots: void svgSourceBindingSourceSize(); void color(); void fileSelectors(); + void imageProvider(); private: void setTheme(); @@ -480,6 +482,43 @@ void tst_qquickiconimage::fileSelectors() QCOMPARE(iconImageWindowGrab.pixelColor(iconImageWindowGrab.width() / 2, iconImageWindowGrab.height() / 2), QColor(Qt::blue)); } +class TestImageProvider : public QQuickImageProvider +{ +public: + TestImageProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) { } + + QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) + { + QSize defaultSize(32, 32); + if (size) + *size = defaultSize; + + QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : defaultSize.width(), + requestedSize.height() > 0 ? requestedSize.height() : defaultSize.height()); + pixmap.fill(QColor(id).rgba()); + return pixmap; + } +}; + +// don't crash (QTBUG-63959) +void tst_qquickiconimage::imageProvider() +{ + QQuickView view; + view.engine()->addImageProvider("provider", new TestImageProvider); + view.setSource(testFileUrl("imageProvider.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->findChild<QQuickIconImage *>()); + QVERIFY(iconImage); + + QImage image = grabItemToImage(iconImage); + QVERIFY(!image.isNull()); + QCOMPARE(image.pixelColor(image.width() / 2, image.height() / 2), QColor(Qt::red)); +} + int main(int argc, char *argv[]) { QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); |