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