diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-05-20 14:37:12 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-05-25 10:21:38 +0200 |
commit | 5654d77ef667438ea13ed219e39d39080f769d66 (patch) | |
tree | fd262ee8948e5a27a3dcaa6d3e019c79e963943c | |
parent | ba047960a1af56249bd5f64883aaa70bddf48313 (diff) |
Fix handling of QQuickViewPrivate::root
QQuickView is supposed to own the root item and shall also track it for
external deletion. Therefore, when we assign a new root item we need to
delete the old one. There is no point in setting a QPointer to nullptr
after deleting it. It will do that by itself. When we fail to assign a
new item, we should _not_ automatically delete the new one. Calling code
typically does not expect the argument to a set* call to be deleted
right away. Rather, return a boolean indicating whether we have
successfully set the root object. This can then be used to get rid of
the object if necessary.
Coverity-Id: 218729
Change-Id: I79ed37d22d304bcc6d4e3c956b83a65fe157dfe0
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
(cherry picked from commit a64ee3a2481499f856d0f3fbc697399e0df1e8f8)
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r-- | src/quick/items/qquickview.cpp | 54 | ||||
-rw-r--r-- | src/quick/items/qquickview_p.h | 2 |
2 files changed, 33 insertions, 23 deletions
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index c411da9519..70d7f57b81 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -76,7 +76,7 @@ void QQuickViewPrivate::init(QQmlEngine* e) } QQuickViewPrivate::QQuickViewPrivate() - : root(nullptr), component(nullptr), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0) + : component(nullptr), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0) { } @@ -92,10 +92,8 @@ void QQuickViewPrivate::execute() return; } - if (root) { + if (root) delete root; - root = nullptr; - } if (component) { delete component; component = nullptr; @@ -212,7 +210,6 @@ QQuickView::~QQuickView() // be a child of the QQuickViewPrivate, and will be destroyed by its dtor Q_D(QQuickView); delete d->root; - d->root = nullptr; } /*! @@ -263,7 +260,8 @@ void QQuickView::setContent(const QUrl& url, QQmlComponent *component, QObject* return; } - d->setRootObject(item); + if (!d->setRootObject(item)) + delete item; emit statusChanged(status()); } @@ -486,43 +484,55 @@ void QQuickView::continueExecute() return; } - d->setRootObject(obj); + if (!d->setRootObject(obj)) + delete obj; emit statusChanged(status()); } /*! \internal + + Sets \a obj as root object and returns true if that operation succeeds. + Otherwise returns \c false. If \c false is returned, the root object is + \c nullptr afterwards. You can explicitly set the root object to nullptr, + and the return value will be \c true. */ -void QQuickViewPrivate::setRootObject(QObject *obj) +bool QQuickViewPrivate::setRootObject(QObject *obj) { Q_Q(QQuickView); if (root == obj) - return; + return true; + + delete root; + if (obj == nullptr) + return true; + if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) { root = sgItem; sgItem->setParentItem(q->QQuickWindow::contentItem()); QQml_setParent_noEvent(sgItem, q->QQuickWindow::contentItem()); - } else if (qobject_cast<QWindow *>(obj)) { - qWarning() << "QQuickView does not support using windows as a root item." << endl - << endl - << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl; - } else { - qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl - << endl - << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl - << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl; - delete obj; - root = nullptr; - } - if (root) { initialSize = rootObjectSize(); if ((resizeMode == QQuickView::SizeViewToRootObject || q->width() <= 1 || q->height() <= 1) && initialSize != q->size()) { q->resize(initialSize); } initResize(); + return true; + } + + if (qobject_cast<QWindow *>(obj)) { + qWarning() << "QQuickView does not support using a window as a root item." << endl + << endl + << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl; + return false; } + + qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl + << endl + << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl + << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl; + return false; } /*! diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index 3f284c0519..75e369411f 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -91,7 +91,7 @@ public: void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) override; void initResize(); void updateSize(); - void setRootObject(QObject *); + bool setRootObject(QObject *); void init(QQmlEngine* e = nullptr); |