summaryrefslogtreecommitdiffstats
path: root/src/declarative/util/qmlview.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2010-02-20 07:42:16 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2010-02-20 07:42:16 (GMT)
commitf0eb658611f549470f0d90e141eda61ab9301838 (patch)
treee234b73e10490e297033d645b744a7cbd26da4b9 /src/declarative/util/qmlview.cpp
parentba9c21f7a1398ddcdeee6f010b1477d79f5bb8ce (diff)
parent8f10ca802dee1ed110f301191c4a56a85575033c (diff)
downloadQt-f0eb658611f549470f0d90e141eda61ab9301838.zip
Qt-f0eb658611f549470f0d90e141eda61ab9301838.tar.gz
Qt-f0eb658611f549470f0d90e141eda61ab9301838.tar.bz2
Merge remote branch 'origin/master'
Conflicts: doc/src/declarative/advtutorial1.qdoc
Diffstat (limited to 'src/declarative/util/qmlview.cpp')
-rw-r--r--src/declarative/util/qmlview.cpp393
1 files changed, 188 insertions, 205 deletions
diff --git a/src/declarative/util/qmlview.cpp b/src/declarative/util/qmlview.cpp
index 7518118..05b6016 100644
--- a/src/declarative/util/qmlview.cpp
+++ b/src/declarative/util/qmlview.cpp
@@ -64,6 +64,7 @@
#include <qboxlayout.h>
#include <qbasictimer.h>
#include <QtCore/qabstractanimation.h>
+#include <private/qgraphicsview_p.h>
QT_BEGIN_NAMESPACE
@@ -125,24 +126,24 @@ void FrameBreakAnimation::updateCurrentTime(int msecs)
server->frameBreak();
}
-class QmlViewPrivate
+class QmlViewPrivate : public QGraphicsViewPrivate
{
+ Q_DECLARE_PUBLIC(QmlView)
public:
- QmlViewPrivate(QmlView *w)
- : q(w), root(0), component(0), resizable(false) {}
+ QmlViewPrivate()
+ : root(0), component(0), resizeMode(QmlView::SizeViewToRootObject) {}
- QmlView *q;
- QmlGraphicsItem *root;
+ QGuard<QGraphicsObject> root;
+ QGuard<QmlGraphicsItem> qmlRoot;
QUrl source;
- QString qml;
QmlEngine engine;
QmlComponent *component;
QBasicTimer resizetimer;
- QSize initialSize;
- bool resizable;
+ mutable QSize initialSize;
+ QmlView::ResizeMode resizeMode;
QTime frameTimer;
void init();
@@ -155,9 +156,30 @@ public:
\since 4.7
\brief The QmlView class provides a widget for displaying a Qt Declarative user interface.
- QmlView currently provides a minimal interface for displaying QML
+ Any QGraphicsObject or QmlGraphicsItem
+ created via QML can be placed on a standard QGraphicsScene and viewed with a standard
+ QGraphicsView.
+
+ QmlView is a QGraphicsView subclass provided as a convenience for displaying QML
files, and connecting between QML and C++ Qt objects.
+ QmlView performs the following functions:
+
+ \list
+ \o Manages QmlComponent loading and object creation.
+ \o Initializes QGraphicsView for optimal performance with QML:
+ \list
+ \o QGraphicsView::setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ \o QGraphicsView::setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ \o QGraphicsScene::setItemIndexMethod(QGraphicsScene::NoIndex);
+ \endlist
+ \o Initializes QGraphicsView for QML key handling:
+ \list
+ \o QGraphicsView::viewport()->setFocusPolicy(Qt::NoFocus);
+ \o QGraphicsScene::setStickyFocus(true);
+ \endlist
+ \endlist
+
Typical usage:
\code
...
@@ -165,7 +187,7 @@ public:
vbox->addWidget(view);
QUrl url(fileName);
- view->setUrl(url);
+ view->setSource(url);
...
view->execute();
...
@@ -173,7 +195,17 @@ public:
\endcode
To receive errors related to loading and executing QML with QmlView,
- you can connect to the errors() signal.
+ you can connect to the statusChanged() signal and monitor for QmlView::Error.
+ The errors are available via QmlView::errors().
+*/
+
+
+/*! \fn void QmlView::sceneResized(QSize size)
+ This signal is emitted when the view is resized to \a size.
+*/
+
+/*! \fn void QmlView::statusChanged(QmlView::Status status)
+ This signal is emitted when the component's current \l{QmlView::Status} {status} changes.
*/
/*!
@@ -182,14 +214,16 @@ public:
Constructs a QmlView with the given \a parent.
*/
QmlView::QmlView(QWidget *parent)
-: QGraphicsView(parent), d(new QmlViewPrivate(this))
+: QGraphicsView(*(new QmlViewPrivate), parent)
{
+ Q_D(QmlView);
setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
d->init();
}
void QmlViewPrivate::init()
{
+ Q_Q(QmlView);
#ifdef Q_ENABLE_PERFORMANCE_LOG
{
QmlPerfTimer<QmlPerf::FontDatabase> perf;
@@ -213,61 +247,46 @@ void QmlViewPrivate::init()
}
/*!
- The destructor clears the view's \l {QmlGraphicsItem} {items} and
+ The destructor clears the view's \l {QGraphicsObject} {items} and
deletes the internal representation.
-
- \sa clearItems()
*/
QmlView::~QmlView()
{
- clearItems();
- delete d; d = 0;
+ Q_D(QmlView);
+ delete d->root;
}
/*!
- Sets the source to the \a url. The QML string is set to
- empty.
+ Sets the source to the \a url.
+
+ Call \l execute() to load the QML and instantiate the component.
+
+ \sa execute()
*/
-void QmlView::setUrl(const QUrl& url)
+void QmlView::setSource(const QUrl& url)
{
+ Q_D(QmlView);
d->source = url;
- d->qml = QString();
}
/*!
Returns the source URL, if set.
- \sa setUrl()
+ \sa setSource()
*/
-QUrl QmlView::url() const
+QUrl QmlView::source() const
{
+ Q_D(const QmlView);
return d->source;
}
/*!
- Sets the source to the URL from the \a filename, and sets
- the QML string to \a qml.
- */
-void QmlView::setQml(const QString &qml, const QString &filename)
-{
- d->source = QUrl::fromLocalFile(filename);
- d->qml = qml;
-}
-
-/*!
- Returns the QML string.
- */
-QString QmlView::qml() const
-{
- return d->qml;
-}
-
-/*!
Returns a pointer to the QmlEngine used for instantiating
QML Components.
*/
QmlEngine* QmlView::engine()
{
+ Q_D(QmlView);
return &d->engine;
}
@@ -280,21 +299,21 @@ QmlEngine* QmlView::engine()
*/
QmlContext* QmlView::rootContext()
{
+ Q_D(QmlView);
return d->engine.rootContext();
}
/*!
- Displays the Qt Declarative user interface.
+ Loads and instantiates the QML component set by the \l setSource() method.
+
+ \sa setSource()
*/
void QmlView::execute()
{
- if (d->qml.isEmpty()) {
- d->component = new QmlComponent(&d->engine, d->source, this);
- } else {
- d->component = new QmlComponent(&d->engine, this);
- d->component->setData(d->qml.toUtf8(), d->source);
- }
- connect (&d->engine, SIGNAL (quit ()), this, SIGNAL (quit ()));
+ Q_D(QmlView);
+ delete d->root;
+ delete d->component;
+ d->component = new QmlComponent(&d->engine, d->source, this);
if (!d->component->isLoading()) {
continueExecute();
@@ -303,26 +322,100 @@ void QmlView::execute()
}
}
+/*!
+ \enum QmlView::Status
+
+ Specifies the loading status of the QmlView.
+
+ \value Null This QmlView has no source set.
+ \value Ready This QmlView has loaded and created the QML component.
+ \value Loading This QmlView is loading network data.
+ \value Error An error has occured. Calling errorDescription() to retrieve a description.
+*/
+
+/*!
+ \property QmlView::status
+ The component's current \l{QmlView::Status} {status}.
+*/
+
+QmlView::Status QmlView::status() const
+{
+ Q_D(const QmlView);
+ if (!d->component)
+ return QmlView::Null;
+
+ return QmlView::Status(d->component->status());
+}
+
+/*!
+ Return the list of errors that occured during the last compile or create
+ operation. An empty list is returned if isError() is not set.
+*/
+QList<QmlError> QmlView::errors() const
+{
+ Q_D(const QmlView);
+ if (d->component)
+ return d->component->errors();
+ return QList<QmlError>();
+}
+
+
+/*!
+ \property QmlView::resizeMode
+ \brief whether the view should resize the canvas contents
+
+ If this property is set to SizeViewToRootObject (the default), the view
+ resizes with the root item in the QML.
+
+ If this property is set to SizeRootObjectToView, the view will
+ automatically resize the root item.
+
+ 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 QmlView::setResizeMode(ResizeMode mode)
+{
+ Q_D(QmlView);
+ if (d->resizeMode == mode)
+ return;
+
+ d->resizeMode = mode;
+ if (d->qmlRoot) {
+ if (d->resizeMode == SizeRootObjectToView) {
+ d->qmlRoot->setWidth(width());
+ d->qmlRoot->setHeight(height());
+ } else {
+ d->qmlRoot->setWidth(d->initialSize.width());
+ d->qmlRoot->setHeight(d->initialSize.height());
+ }
+ }
+}
+
+QmlView::ResizeMode QmlView::resizeMode() const
+{
+ Q_D(const QmlView);
+ return d->resizeMode;
+}
/*!
\internal
*/
void QmlView::continueExecute()
{
- disconnect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
+ Q_D(QmlView);
- if (!d->component) {
- qWarning() << "Error in loading" << d->source;
- return;
- }
+ disconnect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
- if(d->component->isError()) {
+ if (d->component->isError()) {
QList<QmlError> errorList = d->component->errors();
foreach (const QmlError &error, errorList) {
qWarning() << error;
}
- emit errors(errorList);
-
+ emit statusChanged(status());
return;
}
@@ -333,8 +426,7 @@ void QmlView::continueExecute()
foreach (const QmlError &error, errorList) {
qWarning() << error;
}
- emit errors(errorList);
-
+ emit statusChanged(status());
return;
}
@@ -346,24 +438,27 @@ void QmlView::continueExecute()
QPerformanceLog::displayData();
QPerformanceLog::clear();
d->root = item;
+ d->qmlRoot = item;
connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged()));
connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged()));
- if (d->initialSize.height() <= 0 && d->root->width() > 0)
- d->initialSize.setWidth(d->root->width());
- if (d->initialSize.height() <= 0 && d->root->height() > 0)
- d->initialSize.setHeight(d->root->height());
+ if (d->initialSize.height() <= 0 && d->qmlRoot->width() > 0)
+ d->initialSize.setWidth(d->qmlRoot->width());
+ if (d->initialSize.height() <= 0 && d->qmlRoot->height() > 0)
+ d->initialSize.setHeight(d->qmlRoot->height());
resize(d->initialSize);
- if (d->resizable) {
- d->root->setWidth(width());
- d->root->setHeight(height());
+ if (d->resizeMode == SizeRootObjectToView) {
+ d->qmlRoot->setWidth(width());
+ d->qmlRoot->setHeight(height());
} else {
- QSize sz(d->root->width(),d->root->height());
+ QSize sz(d->qmlRoot->width(),d->qmlRoot->height());
emit sceneResized(sz);
resize(sz);
}
updateGeometry();
- emit initialSize(d->initialSize);
+ } else if (QGraphicsObject *item = qobject_cast<QGraphicsObject *>(obj)) {
+ d->scene.addItem(item);
+ qWarning() << "QmlView::resizeMode is not honored for components of type QGraphicsObject";
} else if (QWidget *wid = qobject_cast<QWidget *>(obj)) {
window()->setAttribute(Qt::WA_OpaquePaintEvent, false);
window()->setAttribute(Qt::WA_NoSystemBackground, false);
@@ -378,45 +473,32 @@ void QmlView::continueExecute()
}
layout()->addWidget(wid);
emit sceneResized(wid->size());
- emit initialSize(wid->size());
}
}
+ emit statusChanged(status());
}
-/*! \fn void QmlView::sceneResized(QSize size)
- This signal is emitted when the view is resized to \a size.
- */
-
-/*! \fn void QmlView::initialSize(QSize size)
- This signal is emitted when the initial \a size of the root item is known.
- */
-
-/*! \fn void QmlView::errors(const QList<QmlError> &errors)
- This signal is emitted when the qml loaded contains \a errors.
- */
-
-/*! \fn void QmlView::quit()
- \internal
- */
-
/*!
\internal
*/
void QmlView::sizeChanged()
{
+ Q_D(QmlView);
// delay, so we catch both width and height changing.
d->resizetimer.start(0,this);
}
/*!
+ \internal
If the \l {QTimerEvent} {timer event} \a e is this
view's resize timer, sceneResized() is emitted.
*/
void QmlView::timerEvent(QTimerEvent* e)
{
+ Q_D(QmlView);
if (!e || e->timerId() == d->resizetimer.timerId()) {
- if (d->root) {
- QSize sz(d->root->width(),d->root->height());
+ if (d->qmlRoot) {
+ QSize sz(d->qmlRoot->width(),d->qmlRoot->height());
emit sceneResized(sz);
//if (!d->resizable)
//resize(sz);
@@ -426,147 +508,47 @@ void QmlView::timerEvent(QTimerEvent* e)
}
}
-// modelled on QScrollArea::widgetResizable
-/*!
- \property QmlView::contentResizable
- \brief whether the view should resize the canvas contents
-
- If this property is set to false (the default), the view
- resizes with the root item in the QML.
-
- If this property is set to true, the view will
- automatically resize the root item.
-
- 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 QmlView::setContentResizable(bool on)
-{
- if (d->resizable != on) {
- d->resizable = on;
- if (d->root) {
- if (on) {
- d->root->setWidth(width());
- d->root->setHeight(height());
- } else {
- d->root->setWidth(d->initialSize.width());
- d->root->setHeight(d->initialSize.height());
- }
- }
- }
-}
-
-bool QmlView::contentResizable() const
-{
- return d->resizable;
-}
-
-
/*!
+ \internal
The size hint is the size of the root item.
*/
QSize QmlView::sizeHint() const
{
- if (d->root) {
+ Q_D(const QmlView);
+ if (d->qmlRoot) {
if (d->initialSize.width() <= 0)
- d->initialSize.setWidth(d->root->width());
+ d->initialSize.setWidth(d->qmlRoot->width());
if (d->initialSize.height() <= 0)
- d->initialSize.setHeight(d->root->height());
+ d->initialSize.setHeight(d->qmlRoot->height());
}
return d->initialSize;
}
/*!
- Creates a \l{QmlComponent} {component} from the \a qml
- string, and returns it as an \l {QmlGraphicsItem} {item}. If the
- \a parent item is provided, it becomes the new item's
- parent. \a parent should be in this view's item hierarchy.
+ Returns the view's root \l {QGraphicsObject} {item}.
*/
-QmlGraphicsItem* QmlView::addItem(const QString &qml, QmlGraphicsItem* parent)
-{
- if (!d->root)
- return 0;
-
- QmlComponent component(&d->engine);
- component.setData(qml.toUtf8(), QUrl());
- if(d->component->isError()) {
- QList<QmlError> errorList = d->component->errors();
- foreach (const QmlError &error, errorList) {
- qWarning() << error;
- }
- emit errors(errorList);
-
- return 0;
- }
-
- QObject *obj = component.create();
- if(d->component->isError()) {
- QList<QmlError> errorList = d->component->errors();
- foreach (const QmlError &error, errorList) {
- qWarning() << error;
- }
- emit errors(errorList);
-
- return 0;
- }
-
- if (obj){
- QmlGraphicsItem *item = static_cast<QmlGraphicsItem *>(obj);
- if (!parent)
- parent = d->root;
-
- item->setParentItem(parent);
- return item;
- }
- return 0;
-}
-
-/*!
- Deletes the view's \l {QmlGraphicsItem} {items} and clears the \l {QmlEngine}
- {QML engine's} Component cache.
- */
-void QmlView::reset()
-{
- clearItems();
- d->engine.clearComponentCache();
- d->initialSize = QSize();
-}
-
-/*!
- Deletes the view's \l {QmlGraphicsItem} {items}.
- */
-void QmlView::clearItems()
-{
- if (!d->root)
- return;
- delete d->root;
- d->root = 0;
-}
-
-/*!
- Returns the view's root \l {QmlGraphicsItem} {item}.
- */
-QmlGraphicsItem *QmlView::root() const
+QGraphicsObject *QmlView::rootObject() const
{
+ Q_D(const QmlView);
return d->root;
}
/*!
+ \internal
This function handles the \l {QResizeEvent} {resize event}
\a e.
*/
void QmlView::resizeEvent(QResizeEvent *e)
{
- if (d->resizable && d->root) {
- d->root->setWidth(width());
- d->root->setHeight(height());
+ Q_D(QmlView);
+ if (d->resizeMode == SizeRootObjectToView && d->qmlRoot) {
+ d->qmlRoot->setWidth(width());
+ d->qmlRoot->setHeight(height());
}
- if (d->root) {
- setSceneRect(QRectF(0, 0, d->root->width(), d->root->height()));
+ if (d->qmlRoot) {
+ setSceneRect(QRectF(0, 0, d->qmlRoot->width(), d->qmlRoot->height()));
+ } else if (d->root) {
+ setSceneRect(d->root->boundingRect());
} else {
setSceneRect(rect());
}
@@ -574,10 +556,11 @@ void QmlView::resizeEvent(QResizeEvent *e)
}
/*!
- \reimp
+ \internal
*/
void QmlView::paintEvent(QPaintEvent *event)
{
+ Q_D(QmlView);
int time = 0;
if (frameRateDebug() || QmlViewDebugServer::isDebuggingEnabled())
time = d->frameTimer.restart();