From 742a7a0bd18d4ec23288b132a0e190235bff0547 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 18 Dec 2013 12:24:56 +0100 Subject: Introducing QQuickWidget Renders into an FBO, and provides a texture that is composed by the QPA/widget kernel compositor. Also introducing QQuickRenderControl, which is private API for now. Change-Id: I710c16e1506124a17f91e87344496471803a448b Reviewed-by: Gunnar Sletta --- src/quick/items/items.pri | 2 + src/quick/items/qquickrendercontrol.cpp | 224 +++++++++ src/quick/items/qquickrendercontrol_p.h | 94 ++++ src/quick/items/qquickwindow.cpp | 78 +++- src/quick/items/qquickwindow.h | 4 + src/quick/items/qquickwindow_p.h | 5 +- src/quickwidgets/qquickwidget.cpp | 785 ++++++++++++++++++++++++++++++++ src/quickwidgets/qquickwidget.h | 127 ++++++ src/quickwidgets/qquickwidget_p.h | 117 +++++ src/quickwidgets/qtquickwidgetsglobal.h | 61 +++ src/quickwidgets/quickwidgets.pro | 19 + src/src.pro | 2 + sync.profile | 1 + 13 files changed, 1504 insertions(+), 15 deletions(-) create mode 100644 src/quick/items/qquickrendercontrol.cpp create mode 100644 src/quick/items/qquickrendercontrol_p.h create mode 100644 src/quickwidgets/qquickwidget.cpp create mode 100644 src/quickwidgets/qquickwidget.h create mode 100644 src/quickwidgets/qquickwidget_p.h create mode 100644 src/quickwidgets/qtquickwidgetsglobal.h create mode 100644 src/quickwidgets/quickwidgets.pro 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 +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +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 +#include + +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 #include #include +#include #include #include @@ -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()); @@ -1039,6 +1067,18 @@ QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent) d->init(this); } +/*! + \internal +*/ +QQuickWindow::QQuickWindow(QQuickRenderControl *control) + : QWindow(*(new QQuickWindowPrivate), 0) +{ + Q_D(QQuickWindow); + d->init(this, control); +} + + + /*! Destroys the window. */ @@ -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 *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 +#include +#include + +#include +#include +#include + +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 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(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 QQuickWidget::errors() const +{ + Q_D(const QQuickWidget); + QList 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 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 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(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()); + + d->offscreenWindow->keyPressEvent(e); +} + +/*! \reimp */ +void QQuickWidget::keyReleaseEvent(QKeyEvent *e) +{ + Q_D(QQuickWidget); + Q_QUICK_PROFILE(addEvent()); + + d->offscreenWindow->keyReleaseEvent(e); +} + +/*! \reimp */ +void QQuickWidget::mouseMoveEvent(QMouseEvent *e) +{ + Q_D(QQuickWidget); + Q_QUICK_PROFILE(addEvent()); + + 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()); + + 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()); + + 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 +#include +#include +#include +#include + +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 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 + +#include +#include +#include +#include +#include + +#include + +#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 root; + + QUrl source; + + QPointer 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 + +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", -- cgit v1.2.3