diff options
Diffstat (limited to 'src/quick/items/qquickview.cpp')
-rw-r--r-- | src/quick/items/qquickview.cpp | 194 |
1 files changed, 125 insertions, 69 deletions
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index c411da9519..cb9fab654c 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qquickview.h" #include "qquickview_p.h" @@ -44,13 +8,13 @@ #include "qquickitem_p.h" #include "qquickitemchangelistener_p.h" -#include <private/qqmlmemoryprofiler_p.h> - #include <QtQml/qqmlengine.h> #include <private/qqmlengine_p.h> #include <private/qv4qobjectwrapper_p.h> #include <QtCore/qbasictimer.h> +#include <memory> + QT_BEGIN_NAMESPACE void QQuickViewPrivate::init(QQmlEngine* e) @@ -71,12 +35,12 @@ void QQuickViewPrivate::init(QQmlEngine* e) // The content item has CppOwnership policy (set in QQuickWindow). Ensure the presence of a JS // wrapper so that the garbage collector can see the policy. QV4::ExecutionEngine *v4 = engine.data()->handle(); - QV4::QObjectWrapper::wrap(v4, contentItem); + QV4::QObjectWrapper::ensureWrapper(v4, contentItem); } } QQuickViewPrivate::QQuickViewPrivate() - : root(nullptr), component(nullptr), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0) + : component(nullptr), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0) { } @@ -84,24 +48,28 @@ QQuickViewPrivate::~QQuickViewPrivate() { } -void QQuickViewPrivate::execute() +QQuickViewPrivate::ExecuteState QQuickViewPrivate::executeHelper() { - Q_Q(QQuickView); if (!engine) { qWarning() << "QQuickView: invalid qml engine."; - return; + return Stop; } - if (root) { + if (root) delete root; - root = nullptr; - } if (component) { delete component; component = nullptr; } + return ExecuteState::Continue; +} + +void QQuickViewPrivate::execute() +{ + if (executeHelper() == Stop) + return; + Q_Q(QQuickView); if (!source.isEmpty()) { - QML_MEMORY_SCOPE_URL(engine.data()->baseUrl().resolved(source)); component = new QQmlComponent(engine.data(), source, q); if (!component->isLoading()) { q->continueExecute(); @@ -112,6 +80,22 @@ void QQuickViewPrivate::execute() } } +void QQuickViewPrivate::execute(QAnyStringView uri, QAnyStringView typeName) +{ + if (executeHelper() == Stop) + return; + Q_Q(QQuickView); + + component = new QQmlComponent(engine.data(), uri, typeName, q); + if (!component->isLoading()) { + q->continueExecute(); + } else { + QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)), + q, SLOT(continueExecute())); + } + +} + void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change, const QRectF &oldGeometry) { @@ -168,7 +152,7 @@ QQuickView::QQuickView(QWindow *parent) /*! Constructs a QQuickView with the given QML \a source and \a parent. - The default value of \a parent is 0. + The default value of \a parent is \c{nullptr}. */ QQuickView::QQuickView(const QUrl &source, QWindow *parent) @@ -178,6 +162,19 @@ QQuickView::QQuickView(const QUrl &source, QWindow *parent) } /*! + \since 6.7 + Constructs a QQuickView with the element specified by \a uri and \a typeName + and parent \a parent. + The default value of \a parent is \c{nullptr}. + \sa loadFromModule + */ +QQuickView::QQuickView(QAnyStringView uri, QAnyStringView typeName, QWindow *parent) + : QQuickView(parent) +{ + loadFromModule(uri, typeName); +} + +/*! Constructs a QQuickView with the given QML \a engine and \a parent. Note: In this case, the QQuickView does not own the given \a engine object; @@ -212,7 +209,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; } /*! @@ -243,6 +239,45 @@ void QQuickView::setSource(const QUrl& url) } /*! + \since 6.7 + Loads the QML component identified by \a uri and \a typeName. If the component + is backed by a QML file, \l{source} will be set accordingly. For types defined + in \c{C++}, \c{source} will be empty. + + If any \l{source} was set before this method was called, it will be cleared. + + Calling this method multiple times with the same \a uri and \a typeName will result + in the QML component being reinstantiated. + + \sa setSource, QQmlComponent::loadFromModule, QQmlApplicationEngine::loadFromModule + */ +void QQuickView::loadFromModule(QAnyStringView uri, QAnyStringView typeName) +{ + Q_D(QQuickView); + d->source = {}; // clear URL + d->execute(uri, typeName); +} + +/*! + Sets the initial properties \a initialProperties with which the QML + component gets initialized after calling \l QQuickView::setSource(). + + \snippet qquickview-ex.cpp 1 + + \note You can only use this function to initialize top-level properties. + \note This function should always be called before setSource, as it has + no effect once the component has become \c Ready. + + \sa QQmlComponent::createWithInitialProperties() + \since 5.14 +*/ +void QQuickView::setInitialProperties(const QVariantMap &initialProperties) +{ + Q_D(QQuickView); + d->initialProperties = initialProperties; +} + +/*! \internal Set the source \a url, \a component and content \a item (root of the QML object hierarchy) directly. @@ -263,7 +298,8 @@ void QQuickView::setContent(const QUrl& url, QQmlComponent *component, QObject* return; } - d->setRootObject(item); + if (!d->setRootObject(item)) + delete item; emit statusChanged(status()); } @@ -474,7 +510,9 @@ void QQuickView::continueExecute() return; } - QObject *obj = d->component->create(); + std::unique_ptr<QObject> obj(d->initialProperties.empty() + ? d->component->create() + : d->component->createWithInitialProperties(d->initialProperties)); if (d->component->isError()) { const QList<QQmlError> errorList = d->component->errors(); @@ -486,43 +524,61 @@ void QQuickView::continueExecute() return; } - d->setRootObject(obj); + // If we used loadFromModule, we might not have a URL so far. + // Thus, query the component to retrieve the associated URL, if any + if (d->source.isEmpty()) + d->source = d->component->url(); + + if (d->setRootObject(obj.get())) + Q_UNUSED(obj.release()); 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; + root->setFlag(QQuickItem::ItemIsViewport); 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." << Qt::endl + << Qt::endl + << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << Qt::endl; + return false; + } + + qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << Qt::endl + << Qt::endl + << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << Qt::endl + << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << Qt::endl; + return false; } /*! |