1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickview.h"
43 #include "qquickview_p.h"
45 #include "qquickcanvas_p.h"
46 #include "qquickitem_p.h"
47 #include "qquickitemchangelistener_p.h"
49 #include <private/qqmlprofilerservice_p.h>
50 #include <private/qqmlinspectorservice_p.h>
52 #include <QtQml/qqmlengine.h>
53 #include <private/qqmlengine_p.h>
54 #include <QtCore/qbasictimer.h>
59 void QQuickViewPrivate::init()
63 engine.setIncubationController(q->incubationController());
65 if (QQmlDebugService::isDebuggingEnabled())
66 QQmlInspectorService::instance()->addView(q);
69 QQuickViewPrivate::QQuickViewPrivate()
70 : root(0), component(0), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0)
74 QQuickViewPrivate::~QQuickViewPrivate()
76 if (QQmlDebugService::isDebuggingEnabled())
77 QQmlInspectorService::instance()->removeView(q_func());
82 void QQuickViewPrivate::execute()
93 if (!source.isEmpty()) {
94 component = new QQmlComponent(&engine, source, q);
95 if (!component->isLoading()) {
98 QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
99 q, SLOT(continueExecute()));
104 void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
107 if (resizeItem == root && resizeMode == QQuickView::SizeViewToRootObject) {
108 // wait for both width and height to be changed
109 resizetimer.start(0,q);
111 QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
117 \brief The QQuickView class provides a window for displaying a Qt Quick user interface.
121 This is a convenience subclass of QQuickCanvas which
122 will automatically load and display a QML scene when given the URL of the main source file. Alternatively,
123 you can instantiate your own objects using QQmlComponent and place them in a manually setup QQuickCanvas.
128 QQuickView *view = new QQuickView;
129 view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
133 To receive errors related to loading and executing QML with QQuickView,
134 you can connect to the statusChanged() signal and monitor for QQuickView::Error.
135 The errors are available via QQuickView::errors().
137 \sa {Using QML Bindings in C++ Applications}
141 /*! \fn void QQuickView::sceneResized(QSize size)
142 This signal is emitted when the view is resized to \a size.
145 /*! \fn void QQuickView::statusChanged(QQuickView::Status status)
146 This signal is emitted when the component's current \a status changes.
149 /*! \fn void QQuickView::initialSizeChanged(QSize size)
154 \fn QQuickView::QQuickView(QWindow *parent)
156 Constructs a QQuickView with the given \a parent.
158 QQuickView::QQuickView(QWindow *parent, Qt::WindowFlags f)
159 : QQuickCanvas(*(new QQuickViewPrivate), parent)
166 \fn QQuickView::QQuickView(const QUrl &source, QWidget *parent)
168 Constructs a QQuickView with the given QML \a source and \a parent.
170 QQuickView::QQuickView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
171 : QQuickCanvas(*(new QQuickViewPrivate), parent)
178 QQuickView::~QQuickView()
182 /*! \property QQuickView::source
183 \brief The URL of the source of the QML component.
185 Changing this property causes the QML component to be reloaded.
187 Ensure that the URL provided is full and correct, in particular, use
188 \l QUrl::fromLocalFile() when loading a file from the local filesystem.
192 Sets the source to the \a url, loads the QML component and instantiates it.
194 Ensure that the URL provided is full and correct, in particular, use
195 \l QUrl::fromLocalFile() when loading a file from the local filesystem.
197 Calling this methods multiple times with the same url will result
198 in the QML being reloaded.
200 void QQuickView::setSource(const QUrl& url)
208 Returns the source URL, if set.
212 QUrl QQuickView::source() const
214 Q_D(const QQuickView);
219 Returns a pointer to the QQmlEngine used for instantiating
222 QQmlEngine* QQuickView::engine() const
224 Q_D(const QQuickView);
225 return const_cast<QQmlEngine *>(&d->engine);
229 This function returns the root of the context hierarchy. Each QML
230 component is instantiated in a QQmlContext. QQmlContext's are
231 essential for passing data to QML components. In QML, contexts are
232 arranged hierarchically and this hierarchy is managed by the
235 QQmlContext* QQuickView::rootContext() const
237 Q_D(const QQuickView);
238 return d->engine.rootContext();
242 \enum QQuickView::Status
243 Specifies the loading status of the QQuickView.
245 \value Null This QQuickView has no source set.
246 \value Ready This QQuickView has loaded and created the QML component.
247 \value Loading This QQuickView is loading network data.
248 \value Error One or more errors has occurred. Call errors() to retrieve a list
252 /*! \enum QQuickView::ResizeMode
254 This enum specifies how to resize the view.
256 \value SizeViewToRootObject The view resizes with the root item in the QML.
257 \value SizeRootObjectToView The view will automatically resize the root item to the size of the view.
261 \property QQuickView::status
262 The component's current \l{QQuickView::Status} {status}.
265 QQuickView::Status QQuickView::status() const
267 Q_D(const QQuickView);
269 return QQuickView::Null;
271 return QQuickView::Status(d->component->status());
275 Return the list of errors that occurred during the last compile or create
276 operation. When the status is not Error, an empty list is returned.
278 QList<QQmlError> QQuickView::errors() const
280 Q_D(const QQuickView);
282 return d->component->errors();
283 return QList<QQmlError>();
287 \property QQuickView::resizeMode
288 \brief whether the view should resize the canvas contents
290 If this property is set to SizeViewToRootObject (the default), the view
291 resizes with the root item in the QML.
293 If this property is set to SizeRootObjectToView, the view will
294 automatically resize the root item.
296 Regardless of this property, the sizeHint of the view
297 is the initial size of the root item. Note though that
298 since QML may load dynamically, that size may change.
301 void QQuickView::setResizeMode(ResizeMode mode)
304 if (d->resizeMode == mode)
308 if (d->resizeMode == SizeViewToRootObject) {
309 QQuickItemPrivate *p = QQuickItemPrivate::get(d->root);
310 p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
314 d->resizeMode = mode;
320 void QQuickViewPrivate::initResize()
323 if (resizeMode == QQuickView::SizeViewToRootObject) {
324 QQuickItemPrivate *p = QQuickItemPrivate::get(root);
325 p->addItemChangeListener(this, QQuickItemPrivate::Geometry);
331 void QQuickViewPrivate::updateSize()
337 if (resizeMode == QQuickView::SizeViewToRootObject) {
338 QSize newSize = QSize(root->width(), root->height());
339 if (newSize.isValid() && newSize != q->size()) {
342 } else if (resizeMode == QQuickView::SizeRootObjectToView) {
343 if (!qFuzzyCompare(q->width(), root->width()))
344 root->setWidth(q->width());
345 if (!qFuzzyCompare(q->height(), root->height()))
346 root->setHeight(q->height());
350 QSize QQuickViewPrivate::rootObjectSize() const
352 QSize rootObjectSize(0,0);
353 int widthCandidate = -1;
354 int heightCandidate = -1;
356 widthCandidate = root->width();
357 heightCandidate = root->height();
359 if (widthCandidate > 0) {
360 rootObjectSize.setWidth(widthCandidate);
362 if (heightCandidate > 0) {
363 rootObjectSize.setHeight(heightCandidate);
365 return rootObjectSize;
368 QQuickView::ResizeMode QQuickView::resizeMode() const
370 Q_D(const QQuickView);
371 return d->resizeMode;
377 void QQuickView::continueExecute()
380 disconnect(d->component, SIGNAL(statusChanged(QQmlComponent::Status)), this, SLOT(continueExecute()));
382 if (d->component->isError()) {
383 QList<QQmlError> errorList = d->component->errors();
384 foreach (const QQmlError &error, errorList) {
387 emit statusChanged(status());
391 QObject *obj = d->component->create();
393 if (d->component->isError()) {
394 QList<QQmlError> errorList = d->component->errors();
395 foreach (const QQmlError &error, errorList) {
398 emit statusChanged(status());
402 d->setRootObject(obj);
403 emit statusChanged(status());
410 void QQuickViewPrivate::setRootObject(QObject *obj)
415 if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
417 sgItem->setParentItem(q->QQuickCanvas::rootItem());
419 qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl
421 << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
422 << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
424 << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
425 << "QQuickView class in the qtquick1 module." << endl;
430 initialSize = rootObjectSize();
431 if ((resizeMode == QQuickView::SizeViewToRootObject || !q->width() || !q->height())
432 && initialSize != q->size()) {
433 q->resize(initialSize);
441 If the \l {QTimerEvent} {timer event} \a e is this
442 view's resize timer, sceneResized() is emitted.
444 void QQuickView::timerEvent(QTimerEvent* e)
447 if (!e || e->timerId() == d->resizetimer.timerId()) {
449 d->resizetimer.stop();
455 Preferred size follows the root object geometry.
457 QSize QQuickView::sizeHint() const
459 Q_D(const QQuickView);
460 QSize rootObjectSize = d->rootObjectSize();
461 if (rootObjectSize.isEmpty()) {
464 return rootObjectSize;
469 Returns the initial size of the root object
471 QSize QQuickView::initialSize() const
473 Q_D(const QQuickView);
474 return d->initialSize;
478 Returns the view's root \l {QQuickItem} {item}.
480 QQuickItem *QQuickView::rootObject() const
482 Q_D(const QQuickView);
488 This function handles the \l {QResizeEvent} {resize event}
491 void QQuickView::resizeEvent(QResizeEvent *e)
494 if (d->resizeMode == SizeRootObjectToView)
497 QQuickCanvas::resizeEvent(e);
501 void QQuickView::keyPressEvent(QKeyEvent *e)
503 QQmlProfilerService::addEvent(QQmlProfilerService::Key);
505 QQuickCanvas::keyPressEvent(e);
509 void QQuickView::keyReleaseEvent(QKeyEvent *e)
511 QQmlProfilerService::addEvent(QQmlProfilerService::Key);
513 QQuickCanvas::keyReleaseEvent(e);
517 void QQuickView::mouseMoveEvent(QMouseEvent *e)
519 QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
521 QQuickCanvas::mouseMoveEvent(e);
525 void QQuickView::mousePressEvent(QMouseEvent *e)
527 QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
529 QQuickCanvas::mousePressEvent(e);
533 void QQuickView::mouseReleaseEvent(QMouseEvent *e)
535 QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
537 QQuickCanvas::mouseReleaseEvent(e);