aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/items.pri2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp224
-rw-r--r--src/quick/items/qquickrendercontrol_p.h94
-rw-r--r--src/quick/items/qquickwindow.cpp78
-rw-r--r--src/quick/items/qquickwindow.h4
-rw-r--r--src/quick/items/qquickwindow_p.h5
-rw-r--r--src/quickwidgets/qquickwidget.cpp785
-rw-r--r--src/quickwidgets/qquickwidget.h127
-rw-r--r--src/quickwidgets/qquickwidget_p.h117
-rw-r--r--src/quickwidgets/qtquickwidgetsglobal.h61
-rw-r--r--src/quickwidgets/quickwidgets.pro19
-rw-r--r--src/src.pro2
-rw-r--r--sync.profile1
13 files changed, 1504 insertions, 15 deletions
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index 41cdb3526b..cb378b424b 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -10,6 +10,7 @@ HEADERS += \
$$PWD/qquickrectangle_p_p.h \
$$PWD/qquickwindow.h \
$$PWD/qquickwindow_p.h \
+ $$PWD/qquickrendercontrol_p.h \
$$PWD/qquickfocusscope_p.h \
$$PWD/qquickitemsmodule_p.h \
$$PWD/qquickpainteditem.h \
@@ -82,6 +83,7 @@ SOURCES += \
$$PWD/qquickitem.cpp \
$$PWD/qquickrectangle.cpp \
$$PWD/qquickwindow.cpp \
+ $$PWD/qquickrendercontrol.cpp \
$$PWD/qquickfocusscope.cpp \
$$PWD/qquickitemsmodule.cpp \
$$PWD/qquickpainteditem.cpp \
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
new file mode 100644
index 0000000000..7e4335ba63
--- /dev/null
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickrendercontrol_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QTime>
+#include <QtCore/private/qabstractanimation_p.h>
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
+#include <QtQml/private/qqmlglobal_p.h>
+
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qqmlprofilerservice_p.h>
+#include <QtCore/private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+class QQuickRenderControlPrivate : public QObjectPrivate
+{
+public:
+ QQuickRenderControlPrivate()
+ : window(0)
+ {
+ sg = QSGContext::createDefaultContext();
+ rc = new QSGRenderContext(sg);
+ }
+
+ ~QQuickRenderControlPrivate()
+ {
+ delete rc;
+ delete sg;
+ }
+
+ QQuickWindow *window;
+ QSGContext *sg;
+ QSGRenderContext *rc;
+};
+
+/*!
+ \class QQuickRenderControl
+ \brief The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph.
+
+ \internal
+
+ \inmodule QtQuick
+*/
+
+QQuickRenderControl::QQuickRenderControl()
+ : QObject(*(new QQuickRenderControlPrivate), 0)
+{
+}
+
+QQuickRenderControl::~QQuickRenderControl()
+{
+}
+
+void QQuickRenderControl::windowDestroyed()
+{
+ Q_D(QQuickRenderControl);
+ if (d->window == 0) {
+ d->rc->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+}
+
+void QQuickRenderControl::initialize(QOpenGLContext *gl)
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window)
+ return;
+ bool current = gl->makeCurrent(d->window);
+ if (current)
+ QQuickWindowPrivate::get(d->window)->context->initialize(gl);
+}
+
+void QQuickRenderControl::invalidate()
+{
+ Q_D(QQuickRenderControl);
+ QQuickWindowPrivate::get(d->window)->context->invalidate();
+}
+
+/*!
+ This function should be called as late as possible before
+ sync(). In a threaded scenario, rendering can happen in parallel with this function.
+ */
+void QQuickRenderControl::polishItems()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window || !QQuickWindowPrivate::get(d->window)->isRenderable())
+ return;
+
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
+ cd->polishItems();
+}
+
+/*!
+ Synchronize GUI and scenegraph. Returns true if the scene graph was changed.
+
+ This function is a synchronization point. Rendering can not happen in parallel.
+ */
+bool QQuickRenderControl::sync()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window || !QQuickWindowPrivate::get(d->window)->isRenderable())
+ return false;
+
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
+ cd->syncSceneGraph();
+
+ // TODO: find out if the sync actually caused a scenegraph update.
+ return true;
+}
+
+/*!
+ Render the scenegraph using the current context.
+ */
+void QQuickRenderControl::render()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window || !QQuickWindowPrivate::get(d->window)->isRenderable())
+ return;
+
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
+ cd->renderSceneGraph(d->window->size());
+}
+
+
+/*!
+ \fn void QQuickRenderControl::renderRequested()
+
+ This signal is emitted when the scene graph needs to be rendered. It is not necessary to call sync().
+*/
+
+/*!
+ \fn void QQuickRenderControl::sceneChanged()
+
+ This signal is emitted when the scene graph is updated, meaning that
+ polishItems() and sync() needs to be called. If sync() returns
+ true, then render() needs to be called.
+*/
+
+
+QImage QQuickRenderControl::grab()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window)
+ return QImage();
+
+ render();
+ QImage grabContent = qt_gl_read_framebuffer(d->window->size(), false, false);
+ return grabContent;
+}
+
+QSGContext *QQuickRenderControl::sceneGraphContext() const
+{
+ Q_D(const QQuickRenderControl);
+ return d->sg;
+}
+
+QSGRenderContext *QQuickRenderControl::renderContext(QSGContext *) const
+{
+ Q_D(const QQuickRenderControl);
+ return d->rc;
+}
+
+void QQuickRenderControl::setWindow(QQuickWindow *window)
+{
+ Q_D(QQuickRenderControl);
+ d->window = window;
+}
+
+QQuickWindow *QQuickRenderControl::window() const
+{
+ Q_D(const QQuickRenderControl);
+ return d->window;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h
new file mode 100644
index 0000000000..7255a9ae0b
--- /dev/null
+++ b/src/quick/items/qquickrendercontrol_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKRENDERCONTROL_P_H
+#define QQUICKRENDERCONTROL_P_H
+
+#include <QtGui/QImage>
+#include <private/qtquickglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWindow;
+class QSGContext;
+class QSGRenderContext;
+class QAnimationDriver;
+class QOpenGLContext;
+class QQuickRenderControlPrivate;
+
+class Q_QUICK_PRIVATE_EXPORT QQuickRenderControl : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickRenderControl)
+public:
+ QQuickRenderControl();
+ ~QQuickRenderControl();
+
+ QQuickWindow *window() const;
+
+ void windowDestroyed();
+
+ void initialize(QOpenGLContext *gl);
+ void invalidate();
+ void polishItems();
+ void render();
+ bool sync();
+
+ QImage grab();
+
+Q_SIGNALS:
+ void renderRequested();
+ void sceneChanged();
+
+private:
+ friend class QQuickWindowPrivate;
+ friend class QQuickWindow;
+ void setWindow(QQuickWindow *window);
+ inline void update() { /*emit*/ renderRequested(); }
+ inline void maybeUpdate() { /*emit*/ sceneChanged(); }
+
+ QSGContext *sceneGraphContext() const;
+ QSGRenderContext *renderContext(QSGContext *) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKRENDERCONTROL_P_H
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 2e74c59c20..f035e87d99 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -51,6 +51,7 @@
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <private/qsgrenderloop_p.h>
+#include <private/qquickrendercontrol_p.h>
#include <private/qquickanimatorcontroller_p.h>
#include <private/qguiapplication_p.h>
@@ -210,25 +211,32 @@ QQuickRootItem::QQuickRootItem()
void QQuickWindow::exposeEvent(QExposeEvent *)
{
Q_D(QQuickWindow);
- d->windowManager->exposureChanged(this);
+ if (d->windowManager)
+ d->windowManager->exposureChanged(this);
}
/*! \reimp */
void QQuickWindow::resizeEvent(QResizeEvent *)
{
- d_func()->windowManager->resize(this);
+ Q_D(QQuickWindow);
+ if (d->windowManager)
+ d->windowManager->resize(this);
}
/*! \reimp */
void QQuickWindow::showEvent(QShowEvent *)
{
- d_func()->windowManager->show(this);
+ Q_D(QQuickWindow);
+ if (d->windowManager)
+ d->windowManager->show(this);
}
/*! \reimp */
void QQuickWindow::hideEvent(QHideEvent *)
{
- d_func()->windowManager->hide(this);
+ Q_D(QQuickWindow);
+ if (d->windowManager)
+ d->windowManager->hide(this);
}
/*! \reimp */
@@ -284,7 +292,10 @@ void QQuickWindowPrivate::polishItems()
void QQuickWindow::update()
{
Q_D(QQuickWindow);
- d->windowManager->update(this);
+ if (d->windowManager)
+ d->windowManager->update(this);
+ else
+ d->renderControl->update();
}
void forcePolishHelper(QQuickItem *item)
@@ -391,12 +402,14 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, context(0)
, renderer(0)
, windowManager(0)
+ , renderControl(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
, persistentGLContext(true)
, persistentSceneGraph(true)
, lastWheelEventAccepted(false)
, componentCompleted(true)
+ , forceRendering(false)
, renderTarget(0)
, renderTargetId(0)
, incubationController(0)
@@ -410,7 +423,7 @@ QQuickWindowPrivate::~QQuickWindowPrivate()
{
}
-void QQuickWindowPrivate::init(QQuickWindow *c)
+void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
{
q_ptr = c;
@@ -424,9 +437,24 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
customRenderMode = qgetenv("QSG_VISUALIZE");
- windowManager = QSGRenderLoop::instance();
- QSGContext *sg = windowManager->sceneGraphContext();
- context = windowManager->createRenderContext(sg);
+ renderControl = control;
+ if (renderControl)
+ renderControl->setWindow(q);
+
+ if (!renderControl)
+ windowManager = QSGRenderLoop::instance();
+
+ Q_ASSERT(windowManager || renderControl);
+
+ QSGContext *sg;
+ if (renderControl) {
+ sg = renderControl->sceneGraphContext();
+ context = renderControl->renderContext(sg);
+ } else {
+ sg = windowManager->sceneGraphContext();
+ context = windowManager->createRenderContext(sg);
+ }
+
q->setSurfaceType(QWindow::OpenGLSurface);
q->setFormat(sg->defaultSurfaceFormat());
@@ -1040,6 +1068,18 @@ QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
}
/*!
+ \internal
+*/
+QQuickWindow::QQuickWindow(QQuickRenderControl *control)
+ : QWindow(*(new QQuickWindowPrivate), 0)
+{
+ Q_D(QQuickWindow);
+ d->init(this, control);
+}
+
+
+
+/*!
Destroys the window.
*/
QQuickWindow::~QQuickWindow()
@@ -1047,7 +1087,10 @@ QQuickWindow::~QQuickWindow()
Q_D(QQuickWindow);
d->animationController->deleteLater();
- d->windowManager->windowDestroyed(this);
+ if (d->renderControl)
+ d->renderControl->windowDestroyed();
+ else
+ d->windowManager->windowDestroyed(this);
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete d->incubationController; d->incubationController = 0;
@@ -1075,7 +1118,8 @@ QQuickWindow::~QQuickWindow()
void QQuickWindow::releaseResources()
{
Q_D(QQuickWindow);
- d->windowManager->releaseResources(this);
+ if (d->windowManager)
+ d->windowManager->releaseResources(this);
QQuickPixmap::purgeCache();
}
@@ -2267,7 +2311,7 @@ void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
bool QQuickWindowPrivate::isRenderable() const
{
Q_Q(const QQuickWindow);
- return q->isExposed() && q->isVisible() && q->geometry().isValid();
+ return (forceRendering || (q->isExposed() && q->isVisible())) && q->geometry().isValid();
}
/*!
@@ -2638,7 +2682,10 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
void QQuickWindow::maybeUpdate()
{
Q_D(QQuickWindow);
- d->windowManager->maybeUpdate(this);
+ if (d->renderControl)
+ d->renderControl->maybeUpdate();
+ else
+ d->windowManager->maybeUpdate(this);
}
void QQuickWindow::cleanupSceneGraph()
@@ -2897,7 +2944,7 @@ QImage QQuickWindow::grabWindow()
return image;
}
- return d->windowManager->grab(this);
+ return d->renderControl ? d->renderControl->grab() : d->windowManager->grab(this);
}
/*!
@@ -2912,6 +2959,9 @@ QQmlIncubationController *QQuickWindow::incubationController() const
{
Q_D(const QQuickWindow);
+ if (!d->windowManager)
+ return 0; // TODO: make sure that this is safe
+
if (!d->incubationController)
d->incubationController = new QQuickWindowIncubationController(d->windowManager);
return d->incubationController;
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 5063b3b5db..233340d6fa 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -58,6 +58,7 @@ class QOpenGLFramebufferObject;
class QQmlIncubationController;
class QInputMethodEvent;
class QQuickCloseEvent;
+class QQuickRenderControl;
class Q_QUICK_EXPORT QQuickWindow : public QWindow
{
@@ -177,7 +178,10 @@ private Q_SLOTS:
private:
friend class QQuickItem;
+ friend class QQuickWidget;
+ friend class QQuickWidgetPrivate;
friend class QQuickAnimatorController;
+ explicit QQuickWindow(QQuickRenderControl*);
Q_DISABLE_COPY(QQuickWindow)
};
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 944a320dce..5f61403a40 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -74,6 +74,7 @@ QT_BEGIN_NAMESPACE
class QQuickAnimatorController;
class QSGRenderLoop;
+class QQuickRenderControl;
class QQuickDragGrabber;
class QQuickRootItem : public QQuickItem
@@ -103,7 +104,7 @@ public:
QQuickWindowPrivate();
virtual ~QQuickWindowPrivate();
- void init(QQuickWindow *);
+ void init(QQuickWindow *, QQuickRenderControl *control = 0);
void initContentItem();//Currently only used if items added in QML
QQuickRootItem *contentItem;
@@ -204,6 +205,7 @@ public:
QByteArray customRenderMode; // Default renderer supports "clip", "overdraw", "changes", "batches" and blank.
QSGRenderLoop *windowManager;
+ QQuickRenderControl *renderControl;
QQuickAnimatorController *animationController;
QColor clearColor;
@@ -217,6 +219,7 @@ public:
uint lastWheelEventAccepted : 1;
bool componentCompleted : 1;
+ bool forceRendering : 1;
QOpenGLFramebufferObject *renderTarget;
uint renderTargetId;
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
new file mode 100644
index 0000000000..0b1b101a88
--- /dev/null
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -0,0 +1,785 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickwidget.h"
+#include "qquickwidget_p.h"
+
+#include "private/qquickwindow_p.h"
+#include "private/qquickitem_p.h"
+#include "private/qquickitemchangelistener_p.h"
+#include "private/qquickrendercontrol_p.h"
+
+#include <private/qquickprofiler_p.h>
+#include <private/qqmlinspectorservice_p.h>
+#include <private/qqmlmemoryprofiler_p.h>
+
+#include <QtQml/qqmlengine.h>
+#include <private/qqmlengine_p.h>
+#include <QtCore/qbasictimer.h>
+
+QT_BEGIN_NAMESPACE
+
+//### profiler is broken: it no longer exports symbols
+#undef Q_QUICK_PROFILE
+#define Q_QUICK_PROFILE(x)
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+void QQuickWidgetPrivate::init(QQmlEngine* e)
+{
+ Q_Q(QQuickWidget);
+
+ setRenderToTexture();
+ engine = e;
+
+ if (engine.isNull())
+ engine = new QQmlEngine(q);
+
+ if (!engine.data()->incubationController())
+ engine.data()->setIncubationController(offscreenWindow->incubationController());
+
+ if (QQmlDebugService::isDebuggingEnabled())
+ QQmlInspectorService::instance()->addView(q);
+
+ QWidget::connect(offscreenWindow, SIGNAL(sceneGraphInitialized()), q, SLOT(createFramebufferObject()));
+ QWidget::connect(offscreenWindow, SIGNAL(sceneGraphInvalidated()), q, SLOT(destroyFramebufferObject()));
+ QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate()));
+ QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
+}
+
+QQuickWidgetPrivate::QQuickWidgetPrivate()
+ : root(0)
+ , component(0)
+ , fbo(0)
+ , context(0)
+ , resizeMode(QQuickWidget::SizeViewToRootObject)
+ , initialSize(0,0)
+ , updateTimer(0)
+ , eventPending(false)
+ , updatePending(false)
+{
+ renderControl = new QQuickRenderControl;
+ offscreenWindow = new QQuickWindow(renderControl);
+ offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
+ offscreenWindow->create();
+}
+
+QQuickWidgetPrivate::~QQuickWidgetPrivate()
+{
+ if (QQmlDebugService::isDebuggingEnabled())
+ QQmlInspectorService::instance()->removeView(q_func());
+ delete offscreenWindow;
+ delete renderControl;
+ delete fbo;
+}
+
+void QQuickWidgetPrivate::execute()
+{
+ Q_Q(QQuickWidget);
+ if (!engine) {
+ qWarning() << "QQuickWidget: invalid qml engine.";
+ return;
+ }
+
+ if (root) {
+ delete root;
+ root = 0;
+ }
+ if (component) {
+ delete component;
+ component = 0;
+ }
+ if (!source.isEmpty()) {
+ QML_MEMORY_SCOPE_URL(engine.data()->baseUrl().resolved(source));
+ component = new QQmlComponent(engine.data(), source, q);
+ if (!component->isLoading()) {
+ q->continueExecute();
+ } else {
+ QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
+ q, SLOT(continueExecute()));
+ }
+ }
+}
+
+void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QQuickWidget);
+ if (resizeItem == root && resizeMode == QQuickWidget::SizeViewToRootObject) {
+ // wait for both width and height to be changed
+ resizetimer.start(0,q);
+ }
+ QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
+}
+
+void QQuickWidgetPrivate::renderSceneGraph()
+{
+ Q_Q(QQuickWidget);
+ updatePending = false;
+
+ QOpenGLContext *context = offscreenWindow->openglContext();
+ if (!context) {
+ qWarning("QQuickWidget: render scenegraph with no context");
+ return;
+ }
+ context->makeCurrent(offscreenWindow);
+ renderControl->polishItems();
+ renderControl->sync();
+ renderControl->render();
+ glFlush();
+ context->doneCurrent();
+ q->update();
+}
+
+/*!
+ \class QQuickWidget
+ \since 5.0
+ \brief The QQuickWidget class provides a window for displaying a Qt Quick user interface.
+
+ \inmodule QtQuick
+
+ This is a convenience subclass of QQuickWindow which
+ will automatically load and display a QML scene when given the URL of the main source file. Alternatively,
+ you can instantiate your own objects using QQmlComponent and place them in a manually setup QQuickWindow.
+
+ Typical usage:
+
+ \code
+ QQuickWidget *view = new QQuickWidget;
+ view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
+ view->show();
+ \endcode
+
+ To receive errors related to loading and executing QML with QQuickWidget,
+ you can connect to the statusChanged() signal and monitor for QQuickWidget::Error.
+ The errors are available via QQuickWidget::errors().
+
+ QQuickWidget also manages sizing of the view and root object. By default, the \l resizeMode
+ is SizeViewToRootObject, which will load the component and resize it to the
+ size of the view. Alternatively the resizeMode may be set to SizeRootObjectToView which
+ will resize the view to the size of the root object.
+
+ \sa {qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++ Types to QML}
+*/
+
+
+/*! \fn void QQuickWidget::statusChanged(QQuickWidget::Status status)
+ This signal is emitted when the component's current \a status changes.
+*/
+
+/*!
+ Constructs a QQuickWidget with the given \a parent.
+ The default value of \a parent is 0.
+
+*/
+QQuickWidget::QQuickWidget(QWidget *parent)
+: QWidget(*(new QQuickWidgetPrivate), parent, 0)
+{
+ setMouseTracking(true);
+ d_func()->init();
+}
+
+/*!
+ Constructs a QQuickWidget with the given QML \a source and \a parent.
+ The default value of \a parent is 0.
+
+*/
+QQuickWidget::QQuickWidget(const QUrl &source, QWidget *parent)
+: QWidget(*(new QQuickWidgetPrivate), parent, 0)
+{
+ setMouseTracking(true);
+ d_func()->init();
+ setSource(source);
+}
+
+/*!
+ Constructs a QQuickWidget with the given QML \a engine and \a parent.
+
+ Note: In this case, the QQuickWidget does not own the given \a engine object;
+ it is the caller's responsibility to destroy the engine. If the \a engine is deleted
+ before the view, status() will return QQuickWidget::Error.
+
+ \sa Status, status(), errors()
+*/
+QQuickWidget::QQuickWidget(QQmlEngine* engine, QWidget *parent)
+ : QWidget(*(new QQuickWidgetPrivate), parent, 0)
+{
+ setMouseTracking(true);
+ Q_ASSERT(engine);
+ d_func()->init(engine);
+}
+
+/*!
+ Destroys the QQuickWidget.
+*/
+QQuickWidget::~QQuickWidget()
+{
+ // Ensure that the component is destroyed before the engine; the engine may
+ // be a child of the QQuickWidgetPrivate, and will be destroyed by its dtor
+ Q_D(QQuickWidget);
+ delete d->root;
+ d->root = 0;
+}
+
+/*!
+ \property QQuickWidget::source
+ \brief The URL of the source of the QML component.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+
+ Note that setting a source URL will result in the QML component being
+ instantiated, even if the URL is unchanged from the current value.
+*/
+
+/*!
+ Sets the source to the \a url, loads the QML component and instantiates it.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+
+ Calling this method multiple times with the same url will result
+ in the QML component being reinstantiated.
+ */
+void QQuickWidget::setSource(const QUrl& url)
+{
+ Q_D(QQuickWidget);
+ d->source = url;
+ d->execute();
+}
+
+/*!
+ \internal
+
+ Set the source \a url, \a component and content \a item (root of the QML object hierarchy) directly.
+ */
+void QQuickWidget::setContent(const QUrl& url, QQmlComponent *component, QObject* item)
+{
+ Q_D(QQuickWidget);
+ d->source = url;
+ d->component = component;
+
+ if (d->component && d->component->isError()) {
+ QList<QQmlError> errorList = d->component->errors();
+ foreach (const QQmlError &error, errorList) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ d->setRootObject(item);
+ emit statusChanged(status());
+}
+
+/*!
+ Returns the source URL, if set.
+
+ \sa setSource()
+ */
+QUrl QQuickWidget::source() const
+{
+ Q_D(const QQuickWidget);
+ return d->source;
+}
+
+/*!
+ Returns a pointer to the QQmlEngine used for instantiating
+ QML Components.
+ */
+QQmlEngine* QQuickWidget::engine() const
+{
+ Q_D(const QQuickWidget);
+ return d->engine ? const_cast<QQmlEngine *>(d->engine.data()) : 0;
+}
+
+/*!
+ This function returns the root of the context hierarchy. Each QML
+ component is instantiated in a QQmlContext. QQmlContext's are
+ essential for passing data to QML components. In QML, contexts are
+ arranged hierarchically and this hierarchy is managed by the
+ QQmlEngine.
+ */
+QQmlContext* QQuickWidget::rootContext() const
+{
+ Q_D(const QQuickWidget);
+ return d->engine ? d->engine.data()->rootContext() : 0;
+}
+
+/*!
+ \enum QQuickWidget::Status
+ Specifies the loading status of the QQuickWidget.
+
+ \value Null This QQuickWidget has no source set.
+ \value Ready This QQuickWidget has loaded and created the QML component.
+ \value Loading This QQuickWidget is loading network data.
+ \value Error One or more errors has occurred. Call errors() to retrieve a list
+ of errors.
+*/
+
+/*! \enum QQuickWidget::ResizeMode
+
+ This enum specifies how to resize the view.
+
+ \value SizeViewToRootObject The view resizes with the root item in the QML.
+ \value SizeRootObjectToView The view will automatically resize the root item to the size of the view.
+*/
+
+/*!
+ \property QQuickWidget::status
+ The component's current \l{QQuickWidget::Status} {status}.
+*/
+
+QQuickWidget::Status QQuickWidget::status() const
+{
+ Q_D(const QQuickWidget);
+ if (!d->engine)
+ return QQuickWidget::Error;
+
+ if (!d->component)
+ return QQuickWidget::Null;
+
+ return QQuickWidget::Status(d->component->status());
+}
+
+/*!
+ Return the list of errors that occurred during the last compile or create
+ operation. When the status is not Error, an empty list is returned.
+*/
+QList<QQmlError> QQuickWidget::errors() const
+{
+ Q_D(const QQuickWidget);
+ QList<QQmlError> errs;
+
+ if (d->component)
+ errs = d->component->errors();
+
+ if (!d->engine) {
+ QQmlError error;
+ error.setDescription(QLatin1String("QQuickWidget: invalid qml engine."));
+ errs << error;
+ }
+
+ return errs;
+}
+
+/*!
+ \property QQuickWidget::resizeMode
+ \brief whether the view should resize the window contents
+
+ If this property is set to SizeViewToRootObject (the default), the view
+ resizes to the size of the root item in the QML.
+
+ If this property is set to SizeRootObjectToView, the view will
+ automatically resize the root item to the size of the view.
+
+ Regardless of this property, the sizeHint of the view
+ is the initial size of the root item. Note though that
+ since QML may load dynamically, that size may change.
+
+ \sa initialSize()
+*/
+
+void QQuickWidget::setResizeMode(ResizeMode mode)
+{
+ Q_D(QQuickWidget);
+ if (d->resizeMode == mode)
+ return;
+
+ if (d->root) {
+ if (d->resizeMode == SizeViewToRootObject) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(d->root);
+ p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ }
+ }
+
+ d->resizeMode = mode;
+ if (d->root) {
+ d->initResize();
+ }
+}
+
+void QQuickWidgetPrivate::initResize()
+{
+ if (root) {
+ if (resizeMode == QQuickWidget::SizeViewToRootObject) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(root);
+ p->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+ }
+ updateSize();
+}
+
+void QQuickWidgetPrivate::updateSize()
+{
+ Q_Q(QQuickWidget);
+ if (!root)
+ return;
+
+ if (resizeMode == QQuickWidget::SizeViewToRootObject) {
+ QSize newSize = QSize(root->width(), root->height());
+ if (newSize.isValid() && newSize != q->size()) {
+ q->resize(newSize);
+ }
+ } else if (resizeMode == QQuickWidget::SizeRootObjectToView) {
+ if (!qFuzzyCompare(q->width(), root->width()))
+ root->setWidth(q->width());
+ if (!qFuzzyCompare(q->height(), root->height()))
+ root->setHeight(q->height());
+ }
+}
+
+QSize QQuickWidgetPrivate::rootObjectSize() const
+{
+ QSize rootObjectSize(0,0);
+ int widthCandidate = -1;
+ int heightCandidate = -1;
+ if (root) {
+ widthCandidate = root->width();
+ heightCandidate = root->height();
+ }
+ if (widthCandidate > 0) {
+ rootObjectSize.setWidth(widthCandidate);
+ }
+ if (heightCandidate > 0) {
+ rootObjectSize.setHeight(heightCandidate);
+ }
+ return rootObjectSize;
+}
+
+void QQuickWidgetPrivate::createContext()
+{
+ if (context)
+ return;
+
+ context = new QOpenGLContext();
+ context->setFormat(offscreenWindow->requestedFormat());
+ if (QSGContext::sharedOpenGLContext())
+ context->setShareContext(QSGContext::sharedOpenGLContext()); // ??? is this correct
+ if (!context->create()) {
+ qWarning("QtQuick: failed to create OpenGL context");
+ delete context;
+ context = 0;
+ }
+
+ renderControl->initialize(context);
+}
+
+void QQuickWidget::createFramebufferObject()
+{
+ Q_D(QQuickWidget);
+
+ if (d->fbo)
+ delete d->fbo;
+ QOpenGLContext *context = d->offscreenWindow->openglContext();
+
+ if (!context) {
+ qWarning("createFBO with no context");
+ return;
+ }
+
+ if (context->shareContext() != QWidgetPrivate::get(window())->shareContext()) {
+ context->setShareContext(QWidgetPrivate::get(window())->shareContext());
+ context->create();
+ }
+ context->makeCurrent(d->offscreenWindow);
+ d->fbo = new QOpenGLFramebufferObject(size());
+ d->fbo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ d->offscreenWindow->setRenderTarget(d->fbo);
+}
+
+void QQuickWidget::destroyFramebufferObject()
+{
+ Q_D(QQuickWidget);
+ if (d->fbo)
+ delete d->fbo;
+ d->fbo = 0;
+}
+
+QQuickWidget::ResizeMode QQuickWidget::resizeMode() const
+{
+ Q_D(const QQuickWidget);
+ return d->resizeMode;
+}
+
+/*!
+ \internal
+ */
+void QQuickWidget::continueExecute()
+{
+ Q_D(QQuickWidget);
+ disconnect(d->component, SIGNAL(statusChanged(QQmlComponent::Status)), this, SLOT(continueExecute()));
+
+ if (d->component->isError()) {
+ QList<QQmlError> errorList = d->component->errors();
+ foreach (const QQmlError &error, errorList) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ QObject *obj = d->component->create();
+
+ if (d->component->isError()) {
+ QList<QQmlError> errorList = d->component->errors();
+ foreach (const QQmlError &error, errorList) {
+ QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
+ << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ d->setRootObject(obj);
+ emit statusChanged(status());
+}
+
+
+/*!
+ \internal
+*/
+void QQuickWidgetPrivate::setRootObject(QObject *obj)
+{
+ Q_Q(QQuickWidget);
+ if (root == obj)
+ return;
+ if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) {
+ root = sgItem;
+ sgItem->setParentItem(offscreenWindow->contentItem());
+ } else {
+ qWarning() << "QQuickWidget only supports loading of root objects that derive from QQuickItem." << endl
+ << endl
+ << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl
+ << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl
+ << endl
+ << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl
+ << "QDeclarativeView class in the Qt Quick 1 module." << endl;
+ delete obj;
+ root = 0;
+ }
+ if (root) {
+ initialSize = rootObjectSize();
+ if ((resizeMode == QQuickWidget::SizeViewToRootObject || q->width() <= 1 || q->height() <= 1) &&
+ initialSize != q->size()) {
+ q->resize(initialSize);
+ }
+ initResize();
+ }
+}
+
+GLuint QQuickWidgetPrivate::textureId() const
+{
+ return fbo ? fbo->texture() : 0;
+}
+
+/*!
+ \internal
+ If the \l {QTimerEvent} {timer event} \a e is this
+ view's resize timer, sceneResized() is emitted.
+ */
+void QQuickWidget::timerEvent(QTimerEvent* e)
+{
+ Q_D(QQuickWidget);
+ if (!e || e->timerId() == d->resizetimer.timerId()) {
+ d->updateSize();
+ d->resizetimer.stop();
+ }
+}
+
+/*!
+ \internal
+ Preferred size follows the root object geometry.
+*/
+QSize QQuickWidget::sizeHint() const
+{
+ Q_D(const QQuickWidget);
+ QSize rootObjectSize = d->rootObjectSize();
+ if (rootObjectSize.isEmpty()) {
+ return size();
+ } else {
+ return rootObjectSize;
+ }
+}
+
+/*!
+ Returns the initial size of the root object.
+
+ If \l resizeMode is QQuickItem::SizeRootObjectToView the root object will be
+ resized to the size of the view. initialSize contains the size of the
+ root object before it was resized.
+*/
+QSize QQuickWidget::initialSize() const
+{
+ Q_D(const QQuickWidget);
+ return d->initialSize;
+}
+
+/*!
+ Returns the view's root \l {QQuickItem} {item}.
+ */
+QQuickItem *QQuickWidget::rootObject() const
+{
+ Q_D(const QQuickWidget);
+ return d->root;
+}
+
+/*!
+ \internal
+ This function handles the \l {QResizeEvent} {resize event}
+ \a e.
+ */
+void QQuickWidget::resizeEvent(QResizeEvent *e)
+{
+ Q_D(QQuickWidget);
+ if (d->resizeMode == SizeRootObjectToView)
+ d->updateSize();
+
+ d->createContext();
+ createFramebufferObject();
+ d->offscreenWindow->resizeEvent(e);
+ d->offscreenWindow->setGeometry(0, 0, e->size().width(), e->size().height());
+
+ QOpenGLContext *context = d->offscreenWindow->openglContext();
+ if (!context) {
+ qWarning("QQuickWidget::resizeEvent() no OpenGL context");
+ return;
+ }
+ context->makeCurrent(d->offscreenWindow);
+ d->renderControl->render();
+ glFlush();
+ context->doneCurrent();
+}
+
+/*! \reimp */
+void QQuickWidget::keyPressEvent(QKeyEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+
+ d->offscreenWindow->keyPressEvent(e);
+}
+
+/*! \reimp */
+void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+
+ d->offscreenWindow->keyReleaseEvent(e);
+}
+
+/*! \reimp */
+void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ d->offscreenWindow->mouseMoveEvent(&mappedEvent);
+}
+
+void QQuickWidget::showEvent(QShowEvent *e)
+{
+ Q_D(QQuickWidget);
+ QQuickWindowPrivate::get(d->offscreenWindow)->forceRendering = true;
+ d->offscreenWindow->showEvent(e);
+}
+
+void QQuickWidget::hideEvent(QHideEvent *e)
+{
+ Q_D(QQuickWidget);
+ QQuickWindowPrivate::get(d->offscreenWindow)->forceRendering = false;
+ d->offscreenWindow->hideEvent(e);
+}
+
+/*! \reimp */
+void QQuickWidget::mousePressEvent(QMouseEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ d->offscreenWindow->mousePressEvent(&mappedEvent);
+}
+
+/*! \reimp */
+void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_D(QQuickWidget);
+ Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
+ d->offscreenWindow->mouseReleaseEvent(&mappedEvent);
+}
+
+/*! \reimp */
+bool QQuickWidget::event(QEvent *e)
+{
+ Q_D(QQuickWidget);
+ if (e->type() == QEvent::Timer) {
+ d->eventPending = false;
+ killTimer(d->updateTimer);
+ d->updateTimer = 0;
+ if (d->updatePending)
+ d->renderSceneGraph();
+ return true;
+ }
+ return QWidget::event(e);
+}
+
+
+// TODO: try to separate the two cases of
+// 1. render() unconditionally without sync
+// 2. sync() and then render if necessary
+void QQuickWidget::triggerUpdate()
+{
+ Q_D(QQuickWidget);
+ d->updatePending = true;
+ if (!d->eventPending) {
+ const int exhaustDelay = 5;
+ d->updateTimer = startTimer(exhaustDelay, Qt::PreciseTimer);
+ d->eventPending = true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickwidgets/qquickwidget.h b/src/quickwidgets/qquickwidget.h
new file mode 100644
index 0000000000..f191a2d253
--- /dev/null
+++ b/src/quickwidgets/qquickwidget.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWIDGET_H
+#define QQUICKWIDGET_H
+
+#include <QtWidgets/qwidget.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtCore/qurl.h>
+#include <QtQml/qqmldebug.h>
+#include <QtQuickWidgets/qtquickwidgetsglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngine;
+class QQmlContext;
+class QQmlError;
+class QQuickItem;
+class QQmlComponent;
+
+class QQuickWidgetPrivate;
+class Q_QUICKWIDGETS_EXPORT QQuickWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
+ Q_ENUMS(ResizeMode Status)
+public:
+ explicit QQuickWidget(QWidget *parent = 0);
+ QQuickWidget(QQmlEngine* engine, QWidget *parent);
+ QQuickWidget(const QUrl &source, QWidget *parent = 0);
+ virtual ~QQuickWidget();
+
+ QUrl source() const;
+
+ QQmlEngine* engine() const;
+ QQmlContext* rootContext() const;
+
+ QQuickItem *rootObject() const;
+
+ enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ ResizeMode resizeMode() const;
+ void setResizeMode(ResizeMode);
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ QList<QQmlError> errors() const;
+
+ QSize sizeHint() const;
+ QSize initialSize() const;
+
+public Q_SLOTS:
+ void setSource(const QUrl&);
+ void setContent(const QUrl& url, QQmlComponent *component, QObject *item);
+
+Q_SIGNALS:
+ void statusChanged(QQuickWidget::Status);
+
+private Q_SLOTS:
+ void continueExecute();
+ void createFramebufferObject();
+ void destroyFramebufferObject();
+ void triggerUpdate();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void timerEvent(QTimerEvent*);
+
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+
+ virtual void showEvent(QShowEvent *);
+ virtual void hideEvent(QHideEvent *);
+
+ bool event(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QQuickWidget)
+ Q_DECLARE_PRIVATE(QQuickWidget)
+};
+
+QT_END_NAMESPACE
+
+#endif // QQuickWidget_H
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
new file mode 100644
index 0000000000..01f7c3ac91
--- /dev/null
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWIDGET_P_H
+#define QQUICKWIDGET_P_H
+
+#include "qquickwidget.h"
+#include <private/qwidget_p.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/QWeakPointer>
+
+#include <QtQml/qqmlengine.h>
+
+#include "private/qquickitemchangelistener_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQmlContext;
+class QQmlError;
+class QQuickItem;
+class QQmlComponent;
+class QQuickRenderControl;
+class QOpenGLContext;
+
+class QQuickWidgetPrivate
+ : public QWidgetPrivate,
+ public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickWidget)
+public:
+ static QQuickWidgetPrivate* get(QQuickWidget *view) { return view->d_func(); }
+ static const QQuickWidgetPrivate* get(const QQuickWidget *view) { return view->d_func(); }
+
+ QQuickWidgetPrivate();
+ ~QQuickWidgetPrivate();
+
+ void execute();
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void initResize();
+ void updateSize();
+ void updateFrambufferObjectSize();
+ void setRootObject(QObject *);
+ void renderSceneGraph();
+ void createContext();
+
+ GLuint textureId() const;
+
+ void init(QQmlEngine* e = 0);
+
+ QSize rootObjectSize() const;
+
+ QPointer<QQuickItem> root;
+
+ QUrl source;
+
+ QPointer<QQmlEngine> engine;
+ QQmlComponent *component;
+ QBasicTimer resizetimer;
+ QQuickWindow *offscreenWindow;
+ QQuickRenderControl *renderControl;
+ QOpenGLFramebufferObject *fbo;
+ QOpenGLContext *context;
+
+ QQuickWidget::ResizeMode resizeMode;
+ QSize initialSize;
+ QElapsedTimer frameTimer;
+
+ int updateTimer;
+ bool eventPending;
+ bool updatePending;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQuickWidget_P_H
diff --git a/src/quickwidgets/qtquickwidgetsglobal.h b/src/quickwidgets/qtquickwidgetsglobal.h
new file mode 100644
index 0000000000..2524150ed1
--- /dev/null
+++ b/src/quickwidgets/qtquickwidgetsglobal.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTQUICKWIDGETSGLOBAL_H
+#define QTQUICKWIDGETSGLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_STATIC
+# if defined(QT_BUILD_QUICKWIDGETS_LIB)
+# define Q_QUICKWIDGETS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_QUICKWIDGETS_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define Q_QUICKWIDGETS_EXPORT
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QTQUICKWIDGETSGLOBAL_H
diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro
new file mode 100644
index 0000000000..ab388ff9d3
--- /dev/null
+++ b/src/quickwidgets/quickwidgets.pro
@@ -0,0 +1,19 @@
+TARGET = QtQuickWidgets
+
+QT = core-private gui-private qml-private quick-private widgets-private
+
+DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
+
+
+load(qt_module)
+
+HEADERS += \
+ qquickwidget.h \
+ qquickwidget_p.h \
+ qtquickwidgetsglobal.h
+
+SOURCES += \
+ qquickwidget.cpp
+
+
+
diff --git a/src/src.pro b/src/src.pro
index fb61d49ed9..0cffc9abc0 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -15,4 +15,6 @@ SUBDIRS += \
imports \
qmldevtools
+qtHaveModule(widgets):SUBDIRS += quickwidgets
+
qmldevtools.CONFIG = host_build
diff --git a/sync.profile b/sync.profile
index 961c85b6ce..43364046f0 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,6 +1,7 @@
%modules = ( # path to module name map
"QtQml" => "$basedir/src/qml",
"QtQuick" => "$basedir/src/quick",
+ "QtQuickWidgets" => "$basedir/src/quickwidgets",
"QtQuickParticles" => "$basedir/src/particles",
"QtQuickTest" => "$basedir/src/qmltest",
"QtQmlDevTools" => "$basedir/src/qmldevtools",