cd20f6c9734500c93b55203da3964aef9fc89bab
[profile/ivi/qtdeclarative.git] / src / declarative / items / qsgview.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qsgview.h"
43 #include "qsgview_p.h"
44
45 #include "qsgcanvas_p.h"
46 #include "qsgitem_p.h"
47 #include "qsgitemchangelistener_p.h"
48
49 #include <private/qdeclarativedebugtrace_p.h>
50 #include <private/qdeclarativeinspectorservice_p.h>
51
52 #include <QtDeclarative/qdeclarativeengine.h>
53 #include <private/qdeclarativeengine_p.h>
54 #include <QtCore/qbasictimer.h>
55
56
57 // XXX todo - This whole class should probably be merged with QDeclarativeView for
58 // maximum seamlessness
59 QT_BEGIN_NAMESPACE
60
61 DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE)
62
63 void QSGViewPrivate::init()
64 {
65     Q_Q(QSGView);
66
67     QDeclarativeEnginePrivate::get(&engine)->sgContext = QSGCanvasPrivate::context;
68
69     engine.setIncubationController(q->incubationController());
70
71     QDeclarativeInspectorService::instance()->addView(q);
72 }
73
74 QSGViewPrivate::QSGViewPrivate()
75     : root(0), component(0), resizeMode(QSGView::SizeViewToRootObject), initialSize(0,0), resized(false)
76 {
77 }
78
79 QSGViewPrivate::~QSGViewPrivate()
80 {
81     QDeclarativeInspectorService::instance()->removeView(q_func());
82
83     delete root;
84 }
85
86 void QSGViewPrivate::execute()
87 {
88     Q_Q(QSGView);
89     if (root) {
90         delete root;
91         root = 0;
92     }
93     if (component) {
94         delete component;
95         component = 0;
96     }
97     if (!source.isEmpty()) {
98         component = new QDeclarativeComponent(&engine, source, q);
99         if (!component->isLoading()) {
100             q->continueExecute();
101         } else {
102             QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
103                              q, SLOT(continueExecute()));
104         }
105     }
106 }
107
108 void QSGViewPrivate::itemGeometryChanged(QSGItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
109 {
110     Q_Q(QSGView);
111     if (resizeItem == root && resizeMode == QSGView::SizeViewToRootObject) {
112         // wait for both width and height to be changed
113         resizetimer.start(0,q);
114     }
115     QSGItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
116 }
117
118 QSGView::QSGView(QWindow *parent, Qt::WindowFlags f)
119 : QSGCanvas(*(new QSGViewPrivate), parent)
120 {
121     setWindowFlags(f);
122     d_func()->init();
123 }
124
125 QSGView::QSGView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
126 : QSGCanvas(*(new QSGViewPrivate), parent)
127 {
128     setWindowFlags(f);
129     d_func()->init();
130     setSource(source);
131 }
132
133 QSGView::~QSGView()
134 {
135 }
136
137 void QSGView::setSource(const QUrl& url)
138 {
139     Q_D(QSGView);
140     d->source = url;
141     d->execute();
142 }
143
144 QUrl QSGView::source() const
145 {
146     Q_D(const QSGView);
147     return d->source;
148 }
149
150 QDeclarativeEngine* QSGView::engine() const
151 {
152     Q_D(const QSGView);
153     return const_cast<QDeclarativeEngine *>(&d->engine);
154 }
155
156 QDeclarativeContext* QSGView::rootContext() const
157 {
158     Q_D(const QSGView);
159     return d->engine.rootContext();
160 }
161
162 QSGView::Status QSGView::status() const
163 {
164     Q_D(const QSGView);
165     if (!d->component)
166         return QSGView::Null;
167
168     return QSGView::Status(d->component->status());
169 }
170
171 QList<QDeclarativeError> QSGView::errors() const
172 {
173     Q_D(const QSGView);
174     if (d->component)
175         return d->component->errors();
176     return QList<QDeclarativeError>();
177 }
178
179 void QSGView::setResizeMode(ResizeMode mode)
180 {
181     Q_D(QSGView);
182     if (d->resizeMode == mode)
183         return;
184
185     if (d->root) {
186         if (d->resizeMode == SizeViewToRootObject) {
187             QSGItemPrivate *p = QSGItemPrivate::get(d->root);
188             p->removeItemChangeListener(d, QSGItemPrivate::Geometry);
189         }
190     }
191
192     d->resizeMode = mode;
193     if (d->root) {
194         d->initResize();
195     }
196 }
197
198 void QSGViewPrivate::initResize()
199 {
200     if (root) {
201         if (resizeMode == QSGView::SizeViewToRootObject) {
202             QSGItemPrivate *p = QSGItemPrivate::get(root);
203             p->addItemChangeListener(this, QSGItemPrivate::Geometry);
204         }
205     }
206     updateSize();
207 }
208
209 void QSGViewPrivate::updateSize()
210 {
211     Q_Q(QSGView);
212     if (!root)
213         return;
214
215     if (resizeMode == QSGView::SizeViewToRootObject) {
216         QSize newSize = QSize(root->width(), root->height());
217         if (newSize.isValid() && newSize != q->size()) {
218             q->resize(newSize);
219         }
220     } else if (resizeMode == QSGView::SizeRootObjectToView) {
221         if (!qFuzzyCompare(q->width(), root->width()))
222             root->setWidth(q->width());
223         if (!qFuzzyCompare(q->height(), root->height()))
224             root->setHeight(q->height());
225     }
226 }
227
228 QSize QSGViewPrivate::rootObjectSize() const
229 {
230     QSize rootObjectSize(0,0);
231     int widthCandidate = -1;
232     int heightCandidate = -1;
233     if (root) {
234         widthCandidate = root->width();
235         heightCandidate = root->height();
236     }
237     if (widthCandidate > 0) {
238         rootObjectSize.setWidth(widthCandidate);
239     }
240     if (heightCandidate > 0) {
241         rootObjectSize.setHeight(heightCandidate);
242     }
243     return rootObjectSize;
244 }
245
246 QSGView::ResizeMode QSGView::resizeMode() const
247 {
248     Q_D(const QSGView);
249     return d->resizeMode;
250 }
251
252 /*!
253   \internal
254  */
255 void QSGView::continueExecute()
256 {
257     Q_D(QSGView);
258     disconnect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueExecute()));
259
260     if (d->component->isError()) {
261         QList<QDeclarativeError> errorList = d->component->errors();
262         foreach (const QDeclarativeError &error, errorList) {
263             qWarning() << error;
264         }
265         emit statusChanged(status());
266         return;
267     }
268
269     QObject *obj = d->component->create();
270
271     if (d->component->isError()) {
272         QList<QDeclarativeError> errorList = d->component->errors();
273         foreach (const QDeclarativeError &error, errorList) {
274             qWarning() << error;
275         }
276         emit statusChanged(status());
277         return;
278     }
279
280     d->setRootObject(obj);
281     emit statusChanged(status());
282 }
283
284
285 /*!
286   \internal
287 */
288 void QSGViewPrivate::setRootObject(QObject *obj)
289 {
290     Q_Q(QSGView);
291     if (root == obj)
292         return;
293     if (QSGItem *sgItem = qobject_cast<QSGItem *>(obj)) {
294         root = sgItem;
295         sgItem->setParentItem(q->QSGCanvas::rootItem());
296     } else {
297         qWarning() << "QSGView only supports loading of root objects that derive from QSGItem." << endl
298                    << endl
299                    << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
300                    << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
301                    << endl
302                    << "To load files with 'import QtQuick 1.0' with QML 2, specify:" << endl
303                    << "  QMLSCENE_IMPORT_NAME=quick1" << endl
304                    << "on as an environment variable prior to launching the application." << endl
305                    << endl
306                    << "To load files with 'import Qt 4.7' with QML 2, specify:" << endl
307                    << "  QMLSCENE_IMPORT_NAME=qt" << endl
308                    << "on as an environment variable prior to launching the application." << endl;
309         delete obj;
310         root = 0;
311     }
312     if (root) {
313         initialSize = rootObjectSize();
314         if ((resizeMode == QSGView::SizeViewToRootObject || !resized) // ### refactor:  || !q->testAttribute(Qt::WA_Resized)
315              && initialSize != q->size()) {
316
317             q->resize(initialSize);
318             resized = true;
319         }
320         initResize();
321     }
322 }
323
324 /*!
325   \internal
326   If the \l {QTimerEvent} {timer event} \a e is this
327   view's resize timer, sceneResized() is emitted.
328  */
329 void QSGView::timerEvent(QTimerEvent* e)
330 {
331     Q_D(QSGView);
332     if (!e || e->timerId() == d->resizetimer.timerId()) {
333         d->updateSize();
334         d->resizetimer.stop();
335     }
336 }
337
338 /*!
339     \internal
340     Preferred size follows the root object geometry.
341 */
342 QSize QSGView::sizeHint() const
343 {
344     Q_D(const QSGView);
345     QSize rootObjectSize = d->rootObjectSize();
346     if (rootObjectSize.isEmpty()) {
347         return size();
348     } else {
349         return rootObjectSize;
350     }
351 }
352
353 QSize QSGView::initialSize() const
354 {
355     Q_D(const QSGView);
356     return d->initialSize;
357 }
358
359 QSGItem *QSGView::rootObject() const
360 {
361     Q_D(const QSGView);
362     return d->root;
363 }
364
365 /*!
366   \internal
367   This function handles the \l {QResizeEvent} {resize event}
368   \a e.
369  */
370 void QSGView::resizeEvent(QResizeEvent *e)
371 {
372     Q_D(QSGView);
373     if (d->resizeMode == SizeRootObjectToView)
374         d->updateSize();
375
376     QSGCanvas::resizeEvent(e);
377 }
378
379 void QSGView::keyPressEvent(QKeyEvent *e)
380 {
381     QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
382
383     QSGCanvas::keyPressEvent(e);
384 }
385
386 void QSGView::keyReleaseEvent(QKeyEvent *e)
387 {
388     QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
389
390     QSGCanvas::keyReleaseEvent(e);
391 }
392
393 void QSGView::mouseMoveEvent(QMouseEvent *e)
394 {
395     QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
396
397     QSGCanvas::mouseMoveEvent(e);
398 }
399
400 void QSGView::mousePressEvent(QMouseEvent *e)
401 {
402     QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
403
404     QSGCanvas::mousePressEvent(e);
405 }
406
407 void QSGView::mouseReleaseEvent(QMouseEvent *e)
408 {
409     QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
410
411     QSGCanvas::mouseReleaseEvent(e);
412 }
413
414
415 QT_END_NAMESPACE