1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #include "qsgcanvas_p.h"
45 #include "qsgitem_p.h"
46 #include "qsgitemchangelistener_p.h"
48 #include <private/qdeclarativedebugtrace_p.h>
49 #include <private/qdeclarativeinspectorservice_p.h>
51 #include <QtDeclarative/qdeclarativeengine.h>
52 #include <private/qdeclarativeengine_p.h>
53 #include <QtCore/qbasictimer.h>
55 // XXX todo - This whole class should probably be merged with QDeclarativeView for
56 // maximum seamlessness
59 DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE)
61 class QSGViewPrivate : public QSGCanvasPrivate,
62 public QSGItemChangeListener
64 Q_DECLARE_PUBLIC(QSGView)
70 void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
73 void setRootObject(QObject *);
77 QSize rootObjectSize() const;
79 QPointer<QSGItem> root;
83 QDeclarativeEngine engine;
84 QDeclarativeComponent *component;
85 QBasicTimer resizetimer;
87 QSGView::ResizeMode resizeMode;
89 QElapsedTimer frameTimer;
94 void QSGViewPrivate::init()
96 QDeclarativeEnginePrivate::get(&engine)->sgContext = QSGCanvasPrivate::context;
98 QDeclarativeInspectorService::instance()->addView(q_func());
101 QSGViewPrivate::QSGViewPrivate()
102 : root(0), component(0), resizeMode(QSGView::SizeViewToRootObject), initialSize(0,0), resized(false)
106 QSGViewPrivate::~QSGViewPrivate()
108 QDeclarativeInspectorService::instance()->removeView(q_func());
113 void QSGViewPrivate::execute()
124 if (!source.isEmpty()) {
125 component = new QDeclarativeComponent(&engine, source, q);
126 if (!component->isLoading()) {
127 q->continueExecute();
129 QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
130 q, SLOT(continueExecute()));
135 void QSGViewPrivate::itemGeometryChanged(QSGItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
138 if (resizeItem == root && resizeMode == QSGView::SizeViewToRootObject) {
139 // wait for both width and height to be changed
140 resizetimer.start(0,q);
142 QSGItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
145 QSGView::QSGView(QWindow *parent, Qt::WindowFlags f)
146 : QSGCanvas(*(new QSGViewPrivate), parent)
152 QSGView::QSGView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
153 : QSGCanvas(*(new QSGViewPrivate), parent)
164 void QSGView::setSource(const QUrl& url)
171 QUrl QSGView::source() const
177 QDeclarativeEngine* QSGView::engine() const
180 return const_cast<QDeclarativeEngine *>(&d->engine);
183 QDeclarativeContext* QSGView::rootContext() const
186 return d->engine.rootContext();
189 QSGView::Status QSGView::status() const
193 return QSGView::Null;
195 return QSGView::Status(d->component->status());
198 QList<QDeclarativeError> QSGView::errors() const
202 return d->component->errors();
203 return QList<QDeclarativeError>();
206 void QSGView::setResizeMode(ResizeMode mode)
209 if (d->resizeMode == mode)
213 if (d->resizeMode == SizeViewToRootObject) {
214 QSGItemPrivate *p = QSGItemPrivate::get(d->root);
215 p->removeItemChangeListener(d, QSGItemPrivate::Geometry);
219 d->resizeMode = mode;
225 void QSGViewPrivate::initResize()
228 if (resizeMode == QSGView::SizeViewToRootObject) {
229 QSGItemPrivate *p = QSGItemPrivate::get(root);
230 p->addItemChangeListener(this, QSGItemPrivate::Geometry);
236 void QSGViewPrivate::updateSize()
242 if (resizeMode == QSGView::SizeViewToRootObject) {
243 QSize newSize = QSize(root->width(), root->height());
244 if (newSize.isValid() && newSize != q->size()) {
247 } else if (resizeMode == QSGView::SizeRootObjectToView) {
248 if (!qFuzzyCompare(q->width(), root->width()))
249 root->setWidth(q->width());
250 if (!qFuzzyCompare(q->height(), root->height()))
251 root->setHeight(q->height());
255 QSize QSGViewPrivate::rootObjectSize() const
257 QSize rootObjectSize(0,0);
258 int widthCandidate = -1;
259 int heightCandidate = -1;
261 widthCandidate = root->width();
262 heightCandidate = root->height();
264 if (widthCandidate > 0) {
265 rootObjectSize.setWidth(widthCandidate);
267 if (heightCandidate > 0) {
268 rootObjectSize.setHeight(heightCandidate);
270 return rootObjectSize;
273 QSGView::ResizeMode QSGView::resizeMode() const
276 return d->resizeMode;
282 void QSGView::continueExecute()
285 disconnect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueExecute()));
287 if (d->component->isError()) {
288 QList<QDeclarativeError> errorList = d->component->errors();
289 foreach (const QDeclarativeError &error, errorList) {
292 emit statusChanged(status());
296 QObject *obj = d->component->create();
298 if(d->component->isError()) {
299 QList<QDeclarativeError> errorList = d->component->errors();
300 foreach (const QDeclarativeError &error, errorList) {
303 emit statusChanged(status());
307 d->setRootObject(obj);
308 emit statusChanged(status());
315 void QSGViewPrivate::setRootObject(QObject *obj)
320 if (QSGItem *sgItem = qobject_cast<QSGItem *>(obj)) {
322 sgItem->setParentItem(q->QSGCanvas::rootItem());
324 qWarning() << "QSGView only supports loading of root objects that derive from QSGItem." << endl
326 << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
327 << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
329 << "To load files with 'import QtQuick 1.0' with QML 2, specify:" << endl
330 << " QMLSCENE_IMPORT_NAME=quick1" << endl
331 << "on as an environment variable prior to launching the application." << endl
333 << "To load files with 'import Qt 4.7' with QML 2, specify:" << endl
334 << " QMLSCENE_IMPORT_NAME=qt" << endl
335 << "on as an environment variable prior to launching the application." << endl;
340 initialSize = rootObjectSize();
341 if ((resizeMode == QSGView::SizeViewToRootObject || !resized) // ### refactor: || !q->testAttribute(Qt::WA_Resized)
342 && initialSize != q->size()) {
344 q->resize(initialSize);
353 If the \l {QTimerEvent} {timer event} \a e is this
354 view's resize timer, sceneResized() is emitted.
356 void QSGView::timerEvent(QTimerEvent* e)
359 if (!e || e->timerId() == d->resizetimer.timerId()) {
361 d->resizetimer.stop();
367 Preferred size follows the root object geometry.
369 QSize QSGView::sizeHint() const
372 QSize rootObjectSize = d->rootObjectSize();
373 if (rootObjectSize.isEmpty()) {
376 return rootObjectSize;
380 QSize QSGView::initialSize() const
383 return d->initialSize;
386 QSGItem *QSGView::rootObject() const
394 This function handles the \l {QResizeEvent} {resize event}
397 void QSGView::resizeEvent(QResizeEvent *e)
400 if (d->resizeMode == SizeRootObjectToView)
403 QSGCanvas::resizeEvent(e);
406 void QSGView::keyPressEvent(QKeyEvent *e)
408 QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
410 QSGCanvas::keyPressEvent(e);
413 void QSGView::keyReleaseEvent(QKeyEvent *e)
415 QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
417 QSGCanvas::keyReleaseEvent(e);
420 void QSGView::mouseMoveEvent(QMouseEvent *e)
422 QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
424 QSGCanvas::mouseMoveEvent(e);
427 void QSGView::mousePressEvent(QMouseEvent *e)
429 QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
431 QSGCanvas::mousePressEvent(e);
434 void QSGView::mouseReleaseEvent(QMouseEvent *e)
436 QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
438 QSGCanvas::mouseReleaseEvent(e);