12#include <QtQml/qqmlengine.h>
13#include <QtQml/qqmlcomponent.h>
14#include <private/qqmlengine_p.h>
15#include <private/qv4qobjectwrapper_p.h>
16#include <QtCore/qbasictimer.h>
22void QQuickViewPrivate::init(QQmlEngine* e)
29 engine =
new QQmlEngine(q);
31 QQmlEngine::setContextForObject(contentItem, engine.data()->rootContext());
33 if (!engine.data()->incubationController())
34 engine.data()->setIncubationController(q->incubationController());
39 QV4::ExecutionEngine *v4 = engine.data()->handle();
40 QV4::QObjectWrapper::ensureWrapper(v4, contentItem);
44QQuickViewPrivate::QQuickViewPrivate()
45 : component(
nullptr), resizeMode(QQuickView::SizeViewToRootObject), initialSize(0,0)
49QQuickViewPrivate::~QQuickViewPrivate()
53QQuickViewPrivate::ExecuteState QQuickViewPrivate::executeHelper()
56 qWarning() <<
"QQuickView: invalid qml engine.";
66 return ExecuteState::Continue;
69void QQuickViewPrivate::execute()
71 if (executeHelper() == Stop)
74 if (!source.isEmpty()) {
75 component =
new QQmlComponent(engine.data(), source, q);
76 if (!component->isLoading()) {
79 QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
80 q, SLOT(continueExecute()));
85void QQuickViewPrivate::execute(QAnyStringView uri, QAnyStringView typeName)
87 if (executeHelper() == Stop)
91 component =
new QQmlComponent(engine.data(), uri, typeName, q);
92 if (!component->isLoading()) {
95 QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
96 q, SLOT(continueExecute()));
101void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change,
102 const QRectF &oldGeometry)
105 if (resizeItem == root && resizeMode == QQuickView::SizeViewToRootObject) {
107 resizetimer.start(0,q);
109 QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, oldGeometry);
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
141
142
145
146
147
148
149QQuickView::QQuickView(QWindow *parent)
150: QQuickWindow(*(
new QQuickViewPrivate), parent)
156
157
158
159
160QQuickView::QQuickView(
const QUrl &source, QWindow *parent)
167
168
169
170
171
172
173QQuickView::QQuickView(QAnyStringView uri, QAnyStringView typeName, QWindow *parent)
176 loadFromModule(uri, typeName);
180
181
182
183
184
185
186
187
188QQuickView::QQuickView(QQmlEngine* engine, QWindow *parent)
189 : QQuickWindow(*(
new QQuickViewPrivate), parent)
192 d_func()->init(engine);
196
197
198QQuickView::QQuickView(
const QUrl &source, QQuickRenderControl *control)
199 : QQuickWindow(*(
new QQuickViewPrivate), control)
206
207
208QQuickView::~QQuickView()
217
218
219
220
221
222
223
224
225
228
229
230
231
232
233
234
235
236void QQuickView::setSource(
const QUrl& url)
244
245
246
247
248
249
250
251
252
253
254
255
256void QQuickView::loadFromModule(QAnyStringView uri, QAnyStringView typeName)
260 d->execute(uri, typeName);
264
265
266
267
268
269
270
271
272
273
274
275
276void QQuickView::setInitialProperties(
const QVariantMap &initialProperties)
279 d->initialProperties = initialProperties;
283
284
285
286
287void QQuickView::setContent(
const QUrl& url, QQmlComponent *component, QObject* item)
291 d->component = component;
293 if (d->component && d->component->isError()) {
294 const QList<QQmlError> errorList = d->component->errors();
295 for (
const QQmlError &error : errorList) {
296 QMessageLogger(error.url().toString().toLatin1().constData(), error.line(),
nullptr).warning()
299 emit statusChanged(status());
303 if (!d->setRootObject(item))
305 emit statusChanged(status());
309
310
311
312
313QUrl QQuickView::source()
const
315 Q_D(
const QQuickView);
320
321
322
323QQmlEngine* QQuickView::engine()
const
325 Q_D(
const QQuickView);
326 return d->engine ?
const_cast<QQmlEngine *>(d->engine.data()) :
nullptr;
330
331
332
333
334
335
336QQmlContext* QQuickView::rootContext()
const
338 Q_D(
const QQuickView);
339 return d->engine ? d->engine.data()->rootContext() :
nullptr;
343
344
345
346
347
348
349
350
351
354
355
356
357
358
359
362
363
364
366QQuickView::Status QQuickView::status()
const
368 Q_D(
const QQuickView);
370 return QQuickView::Error;
373 return QQuickView::Null;
375 if (d->component->status() == QQmlComponent::Ready && !d->root)
376 return QQuickView::Error;
378 return QQuickView::Status(d->component->status());
382
383
384
385QList<QQmlError> QQuickView::errors()
const
387 Q_D(
const QQuickView);
388 QList<QQmlError> errs;
391 errs = d->component->errors();
395 error.setDescription(QLatin1String(
"QQuickView: invalid qml engine."));
397 }
else if (d->component && d->component->status() == QQmlComponent::Ready && !d->root) {
399 error.setDescription(QLatin1String(
"QQuickView: invalid root object."));
407
408
409
410
411
412
413
414
415
416
417
419void QQuickView::setResizeMode(ResizeMode mode)
422 if (d->resizeMode == mode)
426 if (d->resizeMode == SizeViewToRootObject) {
427 QQuickItemPrivate *p = QQuickItemPrivate::get(d->root);
428 p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
432 d->resizeMode = mode;
438void QQuickViewPrivate::initResize()
441 if (resizeMode == QQuickView::SizeViewToRootObject) {
442 QQuickItemPrivate *p = QQuickItemPrivate::get(root);
443 p->addItemChangeListener(
this, QQuickItemPrivate::Geometry);
449void QQuickViewPrivate::updateSize()
455 if (resizeMode == QQuickView::SizeViewToRootObject) {
456 QSize newSize = QSize(root->width(), root->height());
457 if (newSize.isValid() && newSize != q->size()) {
460 }
else if (resizeMode == QQuickView::SizeRootObjectToView) {
461 bool needToUpdateWidth = !qFuzzyCompare(q->width(), root->width());
462 bool needToUpdateHeight = !qFuzzyCompare(q->height(), root->height());
464 if (needToUpdateWidth && needToUpdateHeight)
465 root->setSize(QSizeF(q->width(), q->height()));
466 else if (needToUpdateWidth)
467 root->setWidth(q->width());
468 else if (needToUpdateHeight)
469 root->setHeight(q->height());
473QSize QQuickViewPrivate::rootObjectSize()
const
475 QSize rootObjectSize(0,0);
476 int widthCandidate = -1;
477 int heightCandidate = -1;
479 widthCandidate = root->width();
480 heightCandidate = root->height();
482 if (widthCandidate > 0) {
483 rootObjectSize.setWidth(widthCandidate);
485 if (heightCandidate > 0) {
486 rootObjectSize.setHeight(heightCandidate);
488 return rootObjectSize;
491QQuickView::ResizeMode QQuickView::resizeMode()
const
493 Q_D(
const QQuickView);
494 return d->resizeMode;
498
499
500void QQuickView::continueExecute()
503 disconnect(d->component, SIGNAL(statusChanged(QQmlComponent::Status)),
this, SLOT(continueExecute()));
505 if (d->component->isError()) {
506 const QList<QQmlError> errorList = d->component->errors();
507 for (
const QQmlError &error : errorList) {
508 QMessageLogger(error.url().toString().toLatin1().constData(), error.line(),
nullptr).warning()
511 emit statusChanged(status());
515 std::unique_ptr<QObject> obj(d->initialProperties.empty()
516 ? d->component->create()
517 : d->component->createWithInitialProperties(d->initialProperties));
519 if (d->component->isError()) {
520 const QList<QQmlError> errorList = d->component->errors();
521 for (
const QQmlError &error : errorList) {
522 QMessageLogger(error.url().toString().toLatin1().constData(), error.line(),
nullptr).warning()
525 emit statusChanged(status());
531 if (d->source.isEmpty())
532 d->source = d->component->url();
534 if (d->setRootObject(obj.get()))
535 Q_UNUSED(obj.release());
536 emit statusChanged(status());
541
542
543
544
545
546
547
548bool QQuickViewPrivate::setRootObject(QObject *obj)
558 if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
560 root->setFlag(QQuickItem::ItemIsViewport);
561 sgItem->setParentItem(q->QQuickWindow::contentItem());
562 QQml_setParent_noEvent(sgItem, q->QQuickWindow::contentItem());
563 initialSize = rootObjectSize();
564 if ((resizeMode == QQuickView::SizeViewToRootObject || q->width() <= 1 || q->height() <= 1) &&
565 initialSize != q->size()) {
566 q->resize(initialSize);
572 if (qobject_cast<QWindow *>(obj)) {
573 qWarning() <<
"QQuickView does not support using a window as a root item." << Qt::endl
575 <<
"If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << Qt::endl;
579 qWarning() <<
"QQuickView only supports loading of root objects that derive from QQuickItem." << Qt::endl
581 <<
"Ensure your QML code is written for QtQuick 2, and uses a root that is or" << Qt::endl
582 <<
"inherits from QtQuick's Item (not a Timer, QtObject, etc)." << Qt::endl;
587
588
589
590
591void QQuickView::timerEvent(QTimerEvent* e)
594 if (!e || e->timerId() == d->resizetimer.timerId()) {
596 d->resizetimer.stop();
601
602
603
604QSize QQuickView::sizeHint()
const
606 Q_D(
const QQuickView);
607 QSize rootObjectSize = d->rootObjectSize();
608 if (rootObjectSize.isEmpty()) {
611 return rootObjectSize;
616
617
618
619
620
621
622QSize QQuickView::initialSize()
const
624 Q_D(
const QQuickView);
625 return d->initialSize;
629
630
631QQuickItem *QQuickView::rootObject()
const
633 Q_D(
const QQuickView);
638
639
640
641
642void QQuickView::resizeEvent(QResizeEvent *e)
645 if (d->resizeMode == SizeRootObjectToView)
648 QQuickWindow::resizeEvent(e);
652void QQuickView::keyPressEvent(QKeyEvent *e)
654 QQuickWindow::keyPressEvent(e);
658void QQuickView::keyReleaseEvent(QKeyEvent *e)
660 QQuickWindow::keyReleaseEvent(e);
664void QQuickView::mouseMoveEvent(QMouseEvent *e)
666 QQuickWindow::mouseMoveEvent(e);
670void QQuickView::mousePressEvent(QMouseEvent *e)
672 QQuickWindow::mousePressEvent(e);
676void QQuickView::mouseReleaseEvent(QMouseEvent *e)
678 QQuickWindow::mouseReleaseEvent(e);
684#include "moc_qquickview.cpp"