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) {
385 QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
388 emit statusChanged(status());
392 QObject *obj = d->component->create();
394 if (d->component->isError()) {
395 QList<QQmlError> errorList = d->component->errors();
396 foreach (const QQmlError &error, errorList) {
397 QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
400 emit statusChanged(status());
404 d->setRootObject(obj);
405 emit statusChanged(status());
412 void QQuickViewPrivate::setRootObject(QObject *obj)
417 if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
419 sgItem->setParentItem(q->QQuickCanvas::rootItem());
421 qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl
423 << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
424 << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
426 << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
427 << "QQuickView class in the qtquick1 module." << endl;
432 initialSize = rootObjectSize();
433 if ((resizeMode == QQuickView::SizeViewToRootObject || !q->width() || !q->height())
434 && initialSize != q->size()) {
435 q->resize(initialSize);
443 If the \l {QTimerEvent} {timer event} \a e is this
444 view's resize timer, sceneResized() is emitted.
446 void QQuickView::timerEvent(QTimerEvent* e)
449 if (!e || e->timerId() == d->resizetimer.timerId()) {
451 d->resizetimer.stop();
457 Preferred size follows the root object geometry.
459 QSize QQuickView::sizeHint() const
461 Q_D(const QQuickView);
462 QSize rootObjectSize = d->rootObjectSize();
463 if (rootObjectSize.isEmpty()) {
466 return rootObjectSize;
471 Returns the initial size of the root object
473 QSize QQuickView::initialSize() const
475 Q_D(const QQuickView);
476 return d->initialSize;
480 Returns the view's root \l {QQuickItem} {item}.
482 QQuickItem *QQuickView::rootObject() const
484 Q_D(const QQuickView);
490 This function handles the \l {QResizeEvent} {resize event}
493 void QQuickView::resizeEvent(QResizeEvent *e)
496 if (d->resizeMode == SizeRootObjectToView)
499 QQuickCanvas::resizeEvent(e);
503 void QQuickView::keyPressEvent(QKeyEvent *e)
505 QQmlProfilerService::addEvent(QQmlProfilerService::Key);
507 QQuickCanvas::keyPressEvent(e);
511 void QQuickView::keyReleaseEvent(QKeyEvent *e)
513 QQmlProfilerService::addEvent(QQmlProfilerService::Key);
515 QQuickCanvas::keyReleaseEvent(e);
519 void QQuickView::mouseMoveEvent(QMouseEvent *e)
521 QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
523 QQuickCanvas::mouseMoveEvent(e);
527 void QQuickView::mousePressEvent(QMouseEvent *e)
529 QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
531 QQuickCanvas::mousePressEvent(e);
535 void QQuickView::mouseReleaseEvent(QMouseEvent *e)
537 QQmlProfilerService::addEvent(QQmlProfilerService::Mouse);
539 QQuickCanvas::mouseReleaseEvent(e);