diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2010-02-20 07:42:16 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2010-02-20 07:42:16 (GMT) |
commit | f0eb658611f549470f0d90e141eda61ab9301838 (patch) | |
tree | e234b73e10490e297033d645b744a7cbd26da4b9 /src/declarative/util/qmlview.cpp | |
parent | ba9c21f7a1398ddcdeee6f010b1477d79f5bb8ce (diff) | |
parent | 8f10ca802dee1ed110f301191c4a56a85575033c (diff) | |
download | Qt-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.cpp | 393 |
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(); |