diff options
author | Alan Alpert <alan.alpert@nokia.com> | 2010-04-12 07:38:46 (GMT) |
---|---|---|
committer | Alan Alpert <alan.alpert@nokia.com> | 2010-04-12 07:38:46 (GMT) |
commit | ee958684bd1273a5140e1f6d1264bf8bb7d62ef1 (patch) | |
tree | c3b95bb906483b14dd9a58098b18b82b9d9010c2 /src/declarative | |
parent | efc80209fb5e6ac9d0343b3c9f6d5a1548cf5556 (diff) | |
parent | 9753f6098e0e5b3d80ac748559aecc2e66dcfc7a (diff) | |
download | Qt-ee958684bd1273a5140e1f6d1264bf8bb7d62ef1.zip Qt-ee958684bd1273a5140e1f6d1264bf8bb7d62ef1.tar.gz Qt-ee958684bd1273a5140e1f6d1264bf8bb7d62ef1.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7
Conflicts:
src/declarative/graphicsitems/qdeclarativetextinput.cpp
src/declarative/graphicsitems/qdeclarativetextinput_p.h
Diffstat (limited to 'src/declarative')
87 files changed, 2107 insertions, 1161 deletions
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index c86bdc6..d5910e3 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -1,6 +1,8 @@ ============================================================================= The changes below are pre Qt 4.7.0 beta +TextEdit: wrap property is replaced by wrapMode enumeration. +Text: wrap property is replaced by wrapMode enumeration. Removed Q-prefix from validators (IntValidator, DoubleValidator, and RegExpValidator) PathView: offset property now uses range 0-1.0 rather than 0-100 ListView, GridView::positionViewAtIndex() gained a 'mode' parameter @@ -32,12 +34,20 @@ syntax has been introduced: Item { Behavior on x {}; NumberAnimation on y {} } Only the syntax has changed, the behavior is identical. +EaseFollow renamed to SmoothedFollow +--------------------------------------- +This element shares the internal implementation with SmoothedAnimation, +both providing the same easing function, but with SmoothedFollow it's +easier to set a start value to animate intially and then start to follow, +while SmoothedAnimation is still convenient for using inside Behaviors +and Transitions. + -EaseFollow changed to SmoothedAnimation +Add SmoothedAnimation element --------------------------------------- -EaseFollow was renamed to SmoothedAnimation and now it inherits from -NumberAnimaton and as a consequence SmoothedAnimation can be used inside -Behaviors, as PropertySourceValues or in state transitions, like any other animation. +SmoothedAnimation inherits from NumberAnimaton and as a +consequence SmoothedAnimation can be used inside Behaviors, +as PropertySourceValues or in state transitions, like any other animation. The old EaseFollow properties changed to comply with the other declarative animations ('source' changed to 'to'), so now 'to' changes are not diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri index af76a67..eab41e3 100644 --- a/src/declarative/graphicsitems/graphicsitems.pri +++ b/src/declarative/graphicsitems/graphicsitems.pri @@ -48,7 +48,6 @@ HEADERS += \ $$PWD/qdeclarativetext_p_p.h \ $$PWD/qdeclarativevisualitemmodel_p.h \ $$PWD/qdeclarativelistview_p.h \ - $$PWD/qdeclarativegraphicsobjectcontainer_p.h \ $$PWD/qdeclarativelayoutitem_p.h \ $$PWD/qdeclarativeitemchangelistener_p.h \ $$PWD/qdeclarativeeffects.cpp @@ -82,5 +81,4 @@ SOURCES += \ $$PWD/qdeclarativetextedit.cpp \ $$PWD/qdeclarativevisualitemmodel.cpp \ $$PWD/qdeclarativelistview.cpp \ - $$PWD/qdeclarativegraphicsobjectcontainer.cpp \ $$PWD/qdeclarativelayoutitem.cpp diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp index f14f773..cc062f0 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp @@ -312,7 +312,7 @@ void QDeclarativeAnimatedImage::playingStatusChanged() void QDeclarativeAnimatedImage::componentComplete() { Q_D(QDeclarativeAnimatedImage); - QDeclarativeImage::componentComplete(); + QDeclarativeItem::componentComplete(); // NOT QDeclarativeImage if (!d->reply) { setCurrentFrame(d->preset_currentframe); d->preset_currentframe = 0; diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h index 6ab66b3..9d8087c 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h @@ -61,6 +61,10 @@ class Q_DECLARATIVE_EXPORT QDeclarativeAnimatedImage : public QDeclarativeImage Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged) Q_PROPERTY(int frameCount READ frameCount) + + // read-only for AnimatedImage + Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged) + public: QDeclarativeAnimatedImage(QDeclarativeItem *parent=0); ~QDeclarativeAnimatedImage(); @@ -83,6 +87,7 @@ Q_SIGNALS: void playingChanged(); void pausedChanged(); void frameChanged(); + void sourceSizeChanged(); private Q_SLOTS: void movieUpdate(); diff --git a/src/declarative/graphicsitems/qdeclarativeevents.cpp b/src/declarative/graphicsitems/qdeclarativeevents.cpp index 6118ea8..a181071 100644 --- a/src/declarative/graphicsitems/qdeclarativeevents.cpp +++ b/src/declarative/graphicsitems/qdeclarativeevents.cpp @@ -133,6 +133,17 @@ Item { These properties hold the position of the mouse event. */ + +/*! + \qmlproperty bool MouseEvent::accepted + + Setting \a accepted to true prevents the mouse event from being + propagated to items below this item. + + Generally, if the item acts on the mouse event then it should be accepted + so that items lower in the stacking order do not also respond to the same event. +*/ + /*! \qmlproperty enum MouseEvent::button diff --git a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp b/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp deleted file mode 100644 index c846431..0000000 --- a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qdeclarativegraphicsobjectcontainer_p.h" - -#include "private/qdeclarativeitem_p.h" - -#include <QGraphicsObject> -#include <QGraphicsWidget> -#include <QGraphicsSceneResizeEvent> - -QT_BEGIN_NAMESPACE - -class QDeclarativeGraphicsObjectContainerPrivate : public QDeclarativeItemPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeGraphicsObjectContainer) - -public: - QDeclarativeGraphicsObjectContainerPrivate() : QDeclarativeItemPrivate(), graphicsObject(0), syncedResize(false) - { } - - void _q_updateSize(); - - void setFiltering(bool on) - { - Q_Q(QDeclarativeGraphicsObjectContainer); - if (graphicsObject && graphicsObject->isWidget()) { - if (!on) { - graphicsObject->removeEventFilter(q); - QObject::disconnect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize())); - QObject::disconnect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize())); - } else { - graphicsObject->installEventFilter(q); - QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize())); - QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize())); - } - } - } - - - QGraphicsObject *graphicsObject; - bool syncedResize; -}; - - -/*! - \qmlclass GraphicsObjectContainer QDeclarativeGraphicsObjectContainer - \since 4.7 - \brief The GraphicsObjectContainer element allows you to add QGraphicsObjects into Fluid UI elements. - - While any QObject based class can be exposed to QML, QDeclarativeItem - provides a lot of important functionality, including anchors and proper - management of child items. GraphicsObjectContainer helps provide these - functions to other QGraphicsObjects, so that they can be used unaltered in - a QML scene. QGraphicsObjects, which are not QDeclarativeItems, and which are - placed in a QML scene outside of a GraphicsObjectContainer, will not appear - on screen at all. - - A GraphicsObjectContainer can have one element inside it, and it must be a - QGraphicsObject or subclass which has been exposed to the QML engine. - The graphics object inside the GraphicsObjectContainer can then be used - like any other item in QML with the exception of not being reparentable - and not having the standard properties of QML items (such as anchors). - - As the contained object is positioned relative to the container, anchors - affecting the container item will affect the onscreen position of the - contained item. If synchronizedResizing is set to true, then anchors - affecting the container item's size will also affect the contained item's - size. - - Example: - \code - import Qt 4.6 - import MyApp 2.1 as Widgets - Rectangle{ - id: rect - property alias widgetPropertyThree: widget.myThirdProperty; - GraphicsObjectContainer{ - synchronizedResizing: true - anchors.margins: 10 - anchors.fill: parent - Widgets.MyWidget{ - myProperty: "A Value" - myOtherProperty: rect.color - } - } - } - \endcode -*/ - -/*! - \internal - \class QDeclarativeGraphicsObjectContainer - \brief The QDeclarativeGraphicsObjectContainer class allows you to add QGraphicsObjects into Fluid UI applications. -*/ - -QDeclarativeGraphicsObjectContainer::QDeclarativeGraphicsObjectContainer(QDeclarativeItem *parent) -: QDeclarativeItem(*new QDeclarativeGraphicsObjectContainerPrivate, parent) -{ -} - -QDeclarativeGraphicsObjectContainer::~QDeclarativeGraphicsObjectContainer() -{ -} - -QGraphicsObject *QDeclarativeGraphicsObjectContainer::graphicsObject() const -{ - Q_D(const QDeclarativeGraphicsObjectContainer); - return d->graphicsObject; -} - -/*! - \qmlproperty QGraphicsObject GraphicsObjectContainer::graphicsObject - The QGraphicsObject associated with this element. -*/ -void QDeclarativeGraphicsObjectContainer::setGraphicsObject(QGraphicsObject *object) -{ - Q_D(QDeclarativeGraphicsObjectContainer); - if (object == d->graphicsObject) - return; - - //### remove previously set item? - - d->setFiltering(false); - - d->graphicsObject = object; - - if (d->graphicsObject) { - d->graphicsObject->setParentItem(this); - - if (d->syncedResize && d->graphicsObject->isWidget()) { - QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(d->graphicsObject); - QSizeF gwSize = gw->size(); //### should we use sizeHint? - QSizeF newSize = gwSize; - if (heightValid()) - newSize.setHeight(height()); - if (widthValid()) - newSize.setWidth(width()); - if (gwSize != newSize) - gw->resize(newSize); - - gwSize = gw->size(); - setImplicitWidth(gwSize.width()); - setImplicitHeight(gwSize.height()); - - d->setFiltering(true); - } - } -} - -QVariant QDeclarativeGraphicsObjectContainer::itemChange(GraphicsItemChange change, const QVariant &value) -{ - Q_D(QDeclarativeGraphicsObjectContainer); - if (change == ItemSceneHasChanged) { - QGraphicsObject *o = d->graphicsObject; - d->graphicsObject = 0; - setGraphicsObject(o); - } - return QDeclarativeItem::itemChange(change, value); -} - -bool QDeclarativeGraphicsObjectContainer::eventFilter(QObject *watched, QEvent *e) -{ - Q_D(QDeclarativeGraphicsObjectContainer); - if (watched == d->graphicsObject && e->type() == QEvent::GraphicsSceneResize) { - if (d->graphicsObject && d->graphicsObject->isWidget() && d->syncedResize) { - QSizeF newSize = static_cast<QGraphicsWidget*>(d->graphicsObject)->size(); - setImplicitWidth(newSize.width()); - setImplicitHeight(newSize.height()); - } - } - return QDeclarativeItem::eventFilter(watched, e); -} - -/*! - \qmlproperty bool GraphicsObjectContainer::synchronizedResizing - - This property determines whether or not the container and graphics object will synchronize their - sizes. - - \note This property only applies when wrapping a QGraphicsWidget. - - If synchronizedResizing is enabled, the container and widget will - synchronize their sizes as follows. - \list - \o If a size has been set on the container, the widget will be resized to the container. - Any changes in the container's size will be reflected in the widget. - - \o \e Otherwise, the container will initially be sized to the preferred size of the widget. - Any changes to the container's size will be reflected in the widget, and any changes to the - widget's size will be reflected in the container. - \endlist -*/ -bool QDeclarativeGraphicsObjectContainer::synchronizedResizing() const -{ - Q_D(const QDeclarativeGraphicsObjectContainer); - return d->syncedResize; -} - -void QDeclarativeGraphicsObjectContainer::setSynchronizedResizing(bool on) -{ - Q_D(QDeclarativeGraphicsObjectContainer); - if (on == d->syncedResize) - return; - - d->syncedResize = on; - d->setFiltering(on); -} - -void QDeclarativeGraphicsObjectContainerPrivate::_q_updateSize() -{ - if (!graphicsObject || !graphicsObject->isWidget() || !syncedResize) - return; - - QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(graphicsObject); - const QSizeF newSize(width(), height()); - gw->resize(newSize); - - //### will respecting the widgets min/max ever get us in trouble? (all other items always - // size to exactly what you tell them) - /*QSizeF constrainedSize = newSize.expandedTo(gw->minimumSize()).boundedTo(gw->maximumSize()); - gw->resize(constrainedSize); - if (constrainedSize != newSize) { - setImplicitWidth(constrainedSize.width()); - setImplicitHeight(constrainedSize.height()); - }*/ -} - -#include <moc_qdeclarativegraphicsobjectcontainer_p.cpp> - -QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h b/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h deleted file mode 100644 index 20c5bcf..0000000 --- a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVEGRAPHICSOBJECTCONTAINER_H -#define QDECLARATIVEGRAPHICSOBJECTCONTAINER_H - -#include "qdeclarativeitem.h" - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QGraphicsObject; -class QDeclarativeGraphicsObjectContainerPrivate; - -class Q_DECLARATIVE_EXPORT QDeclarativeGraphicsObjectContainer : public QDeclarativeItem -{ - Q_OBJECT - - Q_CLASSINFO("DefaultProperty", "graphicsObject") - Q_PROPERTY(QGraphicsObject *graphicsObject READ graphicsObject WRITE setGraphicsObject) - Q_PROPERTY(bool synchronizedResizing READ synchronizedResizing WRITE setSynchronizedResizing) - -public: - QDeclarativeGraphicsObjectContainer(QDeclarativeItem *parent = 0); - ~QDeclarativeGraphicsObjectContainer(); - - QGraphicsObject *graphicsObject() const; - void setGraphicsObject(QGraphicsObject *); - - bool synchronizedResizing() const; - void setSynchronizedResizing(bool on); - -protected: - QVariant itemChange(GraphicsItemChange change, const QVariant &value); - bool eventFilter(QObject *watched, QEvent *e); - -private: - Q_PRIVATE_SLOT(d_func(), void _q_updateSize()) - Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeGraphicsObjectContainer) -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QDeclarativeGraphicsObjectContainer) - -QT_END_HEADER - -#endif // QDECLARATIVEGRAPHICSOBJECTCONTAINER_H diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 8247f17..9be025a 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -102,10 +102,11 @@ public: QDeclarativeGridViewPrivate() : currentItem(0), flow(QDeclarativeGridView::LeftToRight) , visibleIndex(0) , currentIndex(-1) - , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1) + , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0) , highlightRangeStart(0), highlightRangeEnd(0), highlightRange(QDeclarativeGridView::NoHighlightRange) , highlightComponent(0), highlight(0), trackedItem(0) , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0) + , highlightMoveDuration(150) , bufferMode(NoBuffer), snapMode(QDeclarativeGridView::NoSnap) , ownModel(false), wrap(false), autoHighlight(true) , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false) @@ -315,6 +316,7 @@ public: int cellHeight; int columns; int requestedIndex; + int itemCount; qreal highlightRangeStart; qreal highlightRangeEnd; QDeclarativeGridView::HighlightRangeMode highlightRange; @@ -326,6 +328,7 @@ public: int buffer; QSmoothedAnimation *highlightXAnimator; QSmoothedAnimation *highlightYAnimator; + int highlightMoveDuration; enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 }; BufferMode bufferMode; QDeclarativeGridView::SnapMode snapMode; @@ -358,6 +361,7 @@ void QDeclarativeGridViewPrivate::clear() currentItem = 0; createHighlight(); trackedItem = 0; + itemCount = 0; } FxGridItem *QDeclarativeGridViewPrivate::createItem(int modelIndex) @@ -403,6 +407,7 @@ void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer) if (!isValid() || !q->isComponentComplete()) return; + itemCount = model->count(); qreal bufferFrom = from - buffer; qreal bufferTo = to + buffer; qreal fillFrom = from; @@ -546,6 +551,10 @@ void QDeclarativeGridViewPrivate::layout() { Q_Q(QDeclarativeGridView); layoutScheduled = false; + if (!isValid()) { + clear(); + return; + } if (visibleItems.count()) { qreal rowPos = visibleItems.first()->rowPos(); qreal colPos = visibleItems.first()->colPos(); @@ -662,10 +671,10 @@ void QDeclarativeGridViewPrivate::createHighlight() highlight = new FxGridItem(item, q); highlightXAnimator = new QSmoothedAnimation(q); highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x")); - highlightXAnimator->userDuration = 150; + highlightXAnimator->userDuration = highlightMoveDuration; highlightYAnimator = new QSmoothedAnimation(q); highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y")); - highlightYAnimator->userDuration = 150; + highlightYAnimator->userDuration = highlightMoveDuration; highlightXAnimator->restart(); highlightYAnimator->restart(); changed = true; @@ -1197,6 +1206,37 @@ void QDeclarativeGridView::setHighlightFollowsCurrentItem(bool autoHighlight) } /*! + \qmlproperty int GridView::highlightMoveDuration + This property holds the move animation duration of the highlight delegate. + + highlightFollowsCurrentItem must be true for this property + to have effect. + + The default value for the duration is 150ms. + + \sa highlightFollowsCurrentItem +*/ +int QDeclarativeGridView::highlightMoveDuration() const +{ + Q_D(const QDeclarativeGridView); + return d->highlightMoveDuration; +} + +void QDeclarativeGridView::setHighlightMoveDuration(int duration) +{ + Q_D(QDeclarativeGridView); + if (d->highlightMoveDuration != duration) { + d->highlightMoveDuration = duration; + if (d->highlightYAnimator) { + d->highlightXAnimator->userDuration = d->highlightMoveDuration; + d->highlightYAnimator->userDuration = d->highlightMoveDuration; + } + emit highlightMoveDurationChanged(); + } +} + + +/*! \qmlproperty real GridView::preferredHighlightBegin \qmlproperty real GridView::preferredHighlightEnd \qmlproperty enumeration GridView::highlightRangeMode @@ -1781,12 +1821,14 @@ void QDeclarativeGridView::componentComplete() Q_D(QDeclarativeGridView); QDeclarativeFlickable::componentComplete(); d->updateGrid(); - refill(); - if (d->currentIndex < 0) - d->updateCurrent(0); - else - d->updateCurrent(d->currentIndex); - d->fixupPosition(); + if (d->isValid()) { + refill(); + if (d->currentIndex < 0) + d->updateCurrent(0); + else + d->updateCurrent(d->currentIndex); + d->fixupPosition(); + } } void QDeclarativeGridView::trackedPositionChanged() @@ -1859,6 +1901,7 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) } else if (d->currentIndex < 0) { d->updateCurrent(0); } + d->itemCount += count; emit countChanged(); return; } @@ -1889,6 +1932,7 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) emit currentIndexChanged(); } d->scheduleLayout(); + d->itemCount += count; emit countChanged(); return; } @@ -1976,6 +2020,7 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) for (int j = 0; j < added.count(); ++j) added.at(j)->attached->emitAdd(); + d->itemCount += count; emit countChanged(); } @@ -1984,6 +2029,8 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) Q_D(QDeclarativeGridView); if (!isComponentComplete()) return; + + d->itemCount -= count; bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count; bool removedVisible = false; @@ -2031,7 +2078,8 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) d->releaseItem(d->currentItem); d->currentItem = 0; d->currentIndex = -1; - d->updateCurrent(qMin(modelIndex, d->model->count()-1)); + if (d->itemCount) + d->updateCurrent(qMin(modelIndex, d->itemCount-1)); } // update visibleIndex @@ -2046,7 +2094,7 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) if (removedVisible && d->visibleItems.isEmpty()) { d->timeline.clear(); d->setPosition(0); - if (d->model->count() == 0) + if (d->itemCount == 0) update(); } @@ -2118,6 +2166,8 @@ void QDeclarativeGridView::itemsMoved(int from, int to, int count) if (!movedItem) movedItem = d->createItem(item->index); it = d->visibleItems.insert(it, movedItem); + if (it == d->visibleItems.begin() && firstItem) + movedItem->setPosition(firstItem->colPos(), firstItem->rowPos()); ++it; --remaining; } else { diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index f73f632..5baa1dd 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -66,6 +66,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeGridView : public QDeclarativeFlickable Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged) Q_PROPERTY(QDeclarativeItem *highlightItem READ highlightItem NOTIFY highlightItemChanged) Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem) + Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged) Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged) Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged) @@ -106,6 +107,9 @@ public: bool highlightFollowsCurrentItem() const; void setHighlightFollowsCurrentItem(bool); + int highlightMoveDuration() const; + void setHighlightMoveDuration(int); + enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange }; HighlightRangeMode highlightRangeMode() const; void setHighlightRangeMode(HighlightRangeMode mode); @@ -161,6 +165,7 @@ Q_SIGNALS: void preferredHighlightBeginChanged(); void preferredHighlightEndChanged(); void highlightRangeModeChanged(); + void highlightMoveDurationChanged(); void modelChanged(); void delegateChanged(); void flowChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index 6c84456..49b1c58 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -73,7 +73,7 @@ public: bool asynchronous() const; void setAsynchronous(bool); - void setSourceSize(const QSize&); + virtual void setSourceSize(const QSize&); QSize sourceSize() const; Q_SIGNALS: diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 7989a27..8e5b863 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -57,7 +57,6 @@ #include "private/qdeclarativeflipable_p.h" #include "private/qdeclarativefocuspanel_p.h" #include "private/qdeclarativefocusscope_p.h" -#include "private/qdeclarativegraphicsobjectcontainer_p.h" #include "private/qdeclarativegridview_p.h" #include "private/qdeclarativeimage_p.h" #include "private/qdeclarativeitem_p.h" @@ -96,13 +95,10 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType<QDeclarativeFocusScope>("Qt",4,6,"FocusScope"); qmlRegisterType<QDeclarativeGradient>("Qt",4,6,"Gradient"); qmlRegisterType<QDeclarativeGradientStop>("Qt",4,6,"GradientStop"); - qmlRegisterType<QDeclarativeGraphicsObjectContainer>("Qt",4,6,"GraphicsObjectContainer"); qmlRegisterType<QDeclarativeGrid>("Qt",4,6,"Grid"); qmlRegisterType<QDeclarativeGridView>("Qt",4,6,"GridView"); qmlRegisterType<QDeclarativeImage>("Qt",4,6,"Image"); qmlRegisterType<QDeclarativeItem>("Qt",4,6,"Item"); - qmlRegisterType<QDeclarativeKeyNavigationAttached>("Qt",4,6,"KeyNavigation"); - qmlRegisterType<QDeclarativeKeysAttached>("Qt",4,6,"Keys"); qmlRegisterType<QDeclarativeLayoutItem>("Qt",4,6,"LayoutItem"); qmlRegisterType<QDeclarativeListView>("Qt",4,6,"ListView"); qmlRegisterType<QDeclarativeLoader>("Qt",4,6,"Loader"); @@ -116,10 +112,8 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType<QDeclarativePathQuad>("Qt",4,6,"PathQuad"); qmlRegisterType<QDeclarativePathView>("Qt",4,6,"PathView"); qmlRegisterType<QIntValidator>("Qt",4,6,"IntValidator"); -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) qmlRegisterType<QDoubleValidator>("Qt",4,7,"DoubleValidator"); qmlRegisterType<QRegExpValidator>("Qt",4,7,"RegExpValidator"); -#endif qmlRegisterType<QDeclarativeRectangle>("Qt",4,6,"Rectangle"); qmlRegisterType<QDeclarativeRepeater>("Qt",4,6,"Repeater"); qmlRegisterType<QGraphicsRotation>("Qt",4,6,"Rotation"); @@ -151,4 +145,7 @@ void QDeclarativeItemModule::defineModule() #ifdef QT_WEBKIT_LIB qmlRegisterType<QDeclarativeWebSettings>(); #endif + + qmlRegisterUncreatableType<QDeclarativeKeyNavigationAttached>("Qt",4,6,"KeyNavigation"); + qmlRegisterUncreatableType<QDeclarativeKeysAttached>("Qt",4,6,"Keys"); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index e85d60f..b4506ef 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -152,11 +152,12 @@ public: : currentItem(0), orient(QDeclarativeListView::Vertical) , visiblePos(0), visibleIndex(0) , averageSize(100.0), currentIndex(-1), requestedIndex(-1) - , highlightRangeStart(0), highlightRangeEnd(0) + , itemCount(0), highlightRangeStart(0), highlightRangeEnd(0) , highlightComponent(0), highlight(0), trackedItem(0) , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0) , sectionCriteria(0), spacing(0.0) - , highlightMoveSpeed(400), highlightResizeSpeed(400), highlightRange(QDeclarativeListView::NoHighlightRange) + , highlightMoveSpeed(400), highlightMoveDuration(-1) + , highlightResizeSpeed(400), highlightResizeDuration(-1), highlightRange(QDeclarativeListView::NoHighlightRange) , snapMode(QDeclarativeListView::NoSnap), overshootDist(0.0) , footerComponent(0), footer(0), headerComponent(0), header(0) , bufferMode(NoBuffer) @@ -447,6 +448,7 @@ public: qreal averageSize; int currentIndex; int requestedIndex; + int itemCount; qreal highlightRangeStart; qreal highlightRangeEnd; QDeclarativeComponent *highlightComponent; @@ -463,7 +465,9 @@ public: QDeclarativeItem *sectionCache[sectionCacheSize]; qreal spacing; qreal highlightMoveSpeed; + int highlightMoveDuration; qreal highlightResizeSpeed; + int highlightResizeDuration; QDeclarativeListView::HighlightRangeMode highlightRange; QDeclarativeListView::SnapMode snapMode; qreal overshootDist; @@ -501,6 +505,7 @@ void QDeclarativeListViewPrivate::init() void QDeclarativeListViewPrivate::clear() { + timeline.clear(); for (int i = 0; i < visibleItems.count(); ++i) releaseItem(visibleItems.at(i)); visibleItems.clear(); @@ -516,6 +521,8 @@ void QDeclarativeListViewPrivate::clear() trackedItem = 0; minExtentDirty = true; maxExtentDirty = true; + setPosition(0); + itemCount = 0; } FxListItem *QDeclarativeListViewPrivate::createItem(int modelIndex) @@ -594,6 +601,7 @@ void QDeclarativeListViewPrivate::refill(qreal from, qreal to, bool doBuffer) Q_Q(QDeclarativeListView); if (!isValid() || !q->isComponentComplete()) return; + itemCount = model->count(); qreal bufferFrom = from - buffer; qreal bufferTo = to + buffer; qreal fillFrom = from; @@ -698,6 +706,10 @@ void QDeclarativeListViewPrivate::layout() { Q_Q(QDeclarativeListView); layoutScheduled = false; + if (!isValid()) { + clear(); + return; + } updateSections(); if (!visibleItems.isEmpty()) { int oldEnd = visibleItems.last()->endPosition(); @@ -711,8 +723,6 @@ void QDeclarativeListViewPrivate::layout() if (currentItem && currentIndex > lastVisibleIndex()) currentItem->setPosition(currentItem->position() + (visibleItems.last()->endPosition() - oldEnd)); } - if (!isValid()) - return; q->refill(); minExtentDirty = true; maxExtentDirty = true; @@ -828,10 +838,12 @@ void QDeclarativeListViewPrivate::createHighlight() highlightPosAnimator = new QSmoothedAnimation(q); highlightPosAnimator->target = QDeclarativeProperty(highlight->item, posProp); highlightPosAnimator->velocity = highlightMoveSpeed; + highlightPosAnimator->userDuration = highlightMoveDuration; highlightPosAnimator->restart(); const QLatin1String sizeProp(orient == QDeclarativeListView::Vertical ? "height" : "width"); highlightSizeAnimator = new QSmoothedAnimation(q); highlightSizeAnimator->velocity = highlightResizeSpeed; + highlightSizeAnimator->userDuration = highlightResizeDuration; highlightSizeAnimator->target = QDeclarativeProperty(highlight->item, sizeProp); highlightSizeAnimator->restart(); changed = true; @@ -1860,13 +1872,19 @@ QString QDeclarativeListView::currentSection() const /*! \qmlproperty real ListView::highlightMoveSpeed + \qmlproperty int ListView::highlightMoveDuration \qmlproperty real ListView::highlightResizeSpeed + \qmlproperty int ListView::highlightResizeDuration These properties hold the move and resize animation speed of the highlight delegate. highlightFollowsCurrentItem must be true for these properties to have effect. - The default value for these properties is 400 pixels/second. + The default value for the speed properties is 400 pixels/second. + The default value for the duration properties is -1, i.e. the + highlight will take as much time as necessary to move at the set speed. + + These properties have the same characteristics as a SmoothedAnimation. \sa highlightFollowsCurrentItem */ @@ -1887,6 +1905,23 @@ void QDeclarativeListView::setHighlightMoveSpeed(qreal speed) } } +int QDeclarativeListView::highlightMoveDuration() const +{ + Q_D(const QDeclarativeListView); + return d->highlightMoveDuration; +} + +void QDeclarativeListView::setHighlightMoveDuration(int duration) +{ + Q_D(QDeclarativeListView);\ + if (d->highlightMoveDuration != duration) { + d->highlightMoveDuration = duration; + if (d->highlightPosAnimator) + d->highlightPosAnimator->userDuration = d->highlightMoveDuration; + emit highlightMoveDurationChanged(); + } +} + qreal QDeclarativeListView::highlightResizeSpeed() const { Q_D(const QDeclarativeListView);\ @@ -1904,6 +1939,23 @@ void QDeclarativeListView::setHighlightResizeSpeed(qreal speed) } } +int QDeclarativeListView::highlightResizeDuration() const +{ + Q_D(const QDeclarativeListView); + return d->highlightResizeDuration; +} + +void QDeclarativeListView::setHighlightResizeDuration(int duration) +{ + Q_D(QDeclarativeListView);\ + if (d->highlightResizeDuration != duration) { + d->highlightResizeDuration = duration; + if (d->highlightSizeAnimator) + d->highlightSizeAnimator->userDuration = d->highlightResizeDuration; + emit highlightResizeDurationChanged(); + } +} + /*! \qmlproperty enumeration ListView::snapMode @@ -2314,13 +2366,15 @@ void QDeclarativeListView::componentComplete() { Q_D(QDeclarativeListView); QDeclarativeFlickable::componentComplete(); - refill(); - d->moveReason = QDeclarativeListViewPrivate::SetIndex; - if (d->currentIndex < 0) - d->updateCurrent(0); - else - d->updateCurrent(d->currentIndex); - d->fixupPosition(); + if (d->isValid()) { + refill(); + d->moveReason = QDeclarativeListViewPrivate::SetIndex; + if (d->currentIndex < 0) + d->updateCurrent(0); + else + d->updateCurrent(d->currentIndex); + d->fixupPosition(); + } } void QDeclarativeListView::refill() @@ -2401,6 +2455,7 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) } else if (d->currentIndex < 0) { d->updateCurrent(0); } + d->itemCount += count; emit countChanged(); return; } @@ -2432,6 +2487,7 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) emit currentIndexChanged(); } d->scheduleLayout(); + d->itemCount += count; emit countChanged(); return; } @@ -2524,6 +2580,7 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) for (int j = 0; j < added.count(); ++j) added.at(j)->attached->emitAdd(); + d->itemCount += count; emit countChanged(); } @@ -2534,6 +2591,7 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) return; d->moveReason = QDeclarativeListViewPrivate::Other; d->updateUnrequestedIndexes(); + d->itemCount -= count; FxListItem *firstVisible = d->firstVisibleItem(); int preRemovedSize = 0; @@ -2586,7 +2644,8 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) d->releaseItem(d->currentItem); d->currentItem = 0; d->currentIndex = -1; - d->updateCurrent(qMin(modelIndex, d->model->count()-1)); + if (d->itemCount) + d->updateCurrent(qMin(modelIndex, d->itemCount-1)); } // update visibleIndex @@ -2602,7 +2661,7 @@ void QDeclarativeListView::itemsRemoved(int modelIndex, int count) d->visiblePos = d->header ? d->header->size() : 0; d->timeline.clear(); d->setPosition(0); - if (d->model->count() == 0) + if (d->itemCount == 0) update(); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 5810979..9c0b7dd 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -101,7 +101,9 @@ class Q_DECLARATIVE_EXPORT QDeclarativeListView : public QDeclarativeFlickable Q_PROPERTY(QDeclarativeItem *highlightItem READ highlightItem NOTIFY highlightItemChanged) Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged) Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged) + Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged) Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged) + Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged) Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged) Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged) @@ -176,9 +178,15 @@ public: qreal highlightMoveSpeed() const; void setHighlightMoveSpeed(qreal); + int highlightMoveDuration() const; + void setHighlightMoveDuration(int); + qreal highlightResizeSpeed() const; void setHighlightResizeSpeed(qreal); + int highlightResizeDuration() const; + void setHighlightResizeDuration(int); + enum SnapMode { NoSnap, SnapToItem, SnapOneItem }; SnapMode snapMode() const; void setSnapMode(SnapMode mode); @@ -208,7 +216,9 @@ Q_SIGNALS: void currentIndexChanged(); void currentSectionChanged(); void highlightMoveSpeedChanged(); + void highlightMoveDurationChanged(); void highlightResizeSpeedChanged(); + void highlightResizeDurationChanged(); void highlightChanged(); void highlightItemChanged(); void modelChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 2aab36f..409c228 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -276,9 +276,6 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded() Q_Q(QDeclarativeLoader); if (component) { - QDeclarativeContext *ctxt = new QDeclarativeContext(qmlContext(q)); - ctxt->setContextObject(q); - if (!component->errors().isEmpty()) { qWarning() << component->errors(); emit q->sourceChanged(); @@ -287,6 +284,9 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded() return; } + QDeclarativeContext *ctxt = new QDeclarativeContext(qmlContext(q)); + ctxt->setContextObject(q); + QDeclarativeComponent *c = component; QObject *obj = component->create(ctxt); if (component != c) { diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index 816aa78..a6cc75e 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -71,6 +71,14 @@ void QDeclarativeDrag::setTarget(QGraphicsObject *t) emit targetChanged(); } +void QDeclarativeDrag::resetTarget() +{ + if (!_target) + return; + _target = 0; + emit targetChanged(); +} + QDeclarativeDrag::Axis QDeclarativeDrag::axis() const { return _axis; @@ -412,8 +420,8 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) if (d->drag && d->drag->target()) { if (!d->moved) { - if (d->dragX) d->startX = drag()->target()->x(); - if (d->dragY) d->startY = drag()->target()->y(); + d->startX = drag()->target()->x(); + d->startY = drag()->target()->y(); } QPointF startLocalPos; @@ -439,7 +447,7 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) } } - if (d->dragX) { + if (d->dragX && d->dragged) { qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX; if (x < drag()->xmin()) x = drag()->xmin(); @@ -447,7 +455,7 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) x = drag()->xmax(); drag()->target()->setX(x); } - if (d->dragY) { + if (d->dragY && d->dragged) { qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY; if (y < drag()->ymin()) y = drag()->ymin(); @@ -455,8 +463,8 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) y = drag()->ymax(); drag()->target()->setY(y); } + d->moved = true; } - d->moved = true; QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress); emit positionChanged(&me); } @@ -643,7 +651,7 @@ bool QDeclarativeMouseArea::setPressed(bool p) emit positionChanged(&me); } else { emit released(&me); - if (isclick) + if (isclick && !d->longPress) emit clicked(&me); } diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p.h index db49b57..58faac1 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p.h @@ -55,7 +55,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDrag : public QObject Q_OBJECT Q_ENUMS(Axis) - Q_PROPERTY(QGraphicsObject *target READ target WRITE setTarget NOTIFY targetChanged) + Q_PROPERTY(QGraphicsObject *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget) Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged) Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged) Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged) @@ -69,6 +69,7 @@ public: QGraphicsObject *target() const; void setTarget(QGraphicsObject *); + void resetTarget(); enum Axis { XAxis=0x01, YAxis=0x02, XandYAxis=0x03 }; Axis axis() const; diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 813b525..06e3540 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -221,7 +221,7 @@ void QDeclarativePathViewPrivate::updateHighlight() tl.reset(moveHighlight); moveHighlight.setValue(highlightPosition); - const int duration = 300; + const int duration = highlightMoveDuration; if (target - highlightPosition > model->count()/2) { highlightUp = false; @@ -691,6 +691,31 @@ void QDeclarativePathView::setHighlightRangeMode(HighlightRangeMode mode) emit highlightRangeModeChanged(); } + +/*! + \qmlproperty int PathView::highlightMoveDuration + This property holds the move animation duration of the highlight delegate. + + If the highlightRangeMode is StrictlyEnforceRange then this property + determines the speed that the items move along the path. + + The default value for the duration is 300ms. +*/ +int QDeclarativePathView::highlightMoveDuration() const +{ + Q_D(const QDeclarativePathView); + return d->highlightMoveDuration; +} + +void QDeclarativePathView::setHighlightMoveDuration(int duration) +{ + Q_D(QDeclarativePathView); + if (d->highlightMoveDuration == duration) + return; + d->highlightMoveDuration = duration; + emit highlightMoveDurationChanged(); +} + /*! \qmlproperty real PathView::dragMargin This property holds the maximum distance from the path that initiate mouse dragging. @@ -1130,7 +1155,7 @@ void QDeclarativePathView::refill() d->updateItem(d->highlightItem, d->highlightRangeStart); if (QDeclarativePathViewAttached *att = d->attached(d->highlightItem)) att->setOnPath(true); - } else if (d->moveReason != QDeclarativePathViewPrivate::SetIndex) { + } else if (d->highlightItem && d->moveReason != QDeclarativePathViewPrivate::SetIndex) { d->updateItem(d->highlightItem, d->currentItemOffset); if (QDeclarativePathViewAttached *att = d->attached(d->highlightItem)) att->setOnPath(currentVisible); @@ -1316,7 +1341,7 @@ void QDeclarativePathViewPrivate::snapToCurrent() tl.reset(moveOffset); moveOffset.setValue(offset); - const int duration = 300; + const int duration = highlightMoveDuration; if (targetOffset - offset > model->count()/2) { qreal distance = model->count() - targetOffset + offset; diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p.h index 69770cd..7240578 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p.h @@ -68,6 +68,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativePathView : public QDeclarativeItem Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged) Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged) Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged) + Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged) Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin NOTIFY dragMarginChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) @@ -109,6 +110,9 @@ public: qreal preferredHighlightEnd() const; void setPreferredHighlightEnd(qreal); + int highlightMoveDuration() const; + void setHighlightMoveDuration(int); + qreal dragMargin() const; void setDragMargin(qreal margin); @@ -145,6 +149,7 @@ Q_SIGNALS: void interactiveChanged(); void highlightChanged(); void highlightItemChanged(); + void highlightMoveDurationChanged(); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h index 11712fd..303486f 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h @@ -85,7 +85,7 @@ public: , highlightPosition(0) , highlightRangeStart(0), highlightRangeEnd(0) , highlightRangeMode(QDeclarativePathView::StrictlyEnforceRange) - , highlightMoveSpeed(1.0) + , highlightMoveDuration(300) { } @@ -160,7 +160,7 @@ public: qreal highlightRangeStart; qreal highlightRangeEnd; QDeclarativePathView::HighlightRangeMode highlightRangeMode; - qreal highlightMoveSpeed; + int highlightMoveDuration; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp index e836788..95f6276 100644 --- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp +++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp @@ -62,10 +62,10 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate() /*! \qmlclass Repeater QDeclarativeRepeater - \since 4.7 + \since 4.7 \inherits Item - \brief The Repeater item allows you to repeat a component based on a model. + \brief The Repeater item allows you to repeat an Item-based component using a model. The Repeater item is used when you want to create a large number of similar items. For each entry in the model, an item is instantiated @@ -102,15 +102,24 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate() The repeater instance continues to own all items it instantiates, even if they are otherwise manipulated. It is illegal to manually remove an item created by the Repeater. + + \note Repeater is Item-based, and cannot be used to repeat non-Item-derived objects. + For example, it cannot be used to repeat QtObjects. + \badcode + Item { + //XXX illegal. Can't repeat QtObject as it doesn't derive from Item. + Repeater { + model: 10 + QtObject {} + } + } + \endcode */ /*! \internal \class QDeclarativeRepeater \qmlclass Repeater - - XXX Repeater is very conservative in how it instatiates/deletes items. Also - new model entries will not be created and old ones will not be removed. */ /*! diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index a4f3068..f31f5aa 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -42,6 +42,7 @@ #include "private/qdeclarativetext_p.h" #include "private/qdeclarativetext_p_p.h" #include <qdeclarativestyledtext_p.h> +#include <qdeclarativeinfo.h> #include <QTextLayout> #include <QTextLine> @@ -70,7 +71,7 @@ QT_BEGIN_NAMESPACE \image declarative-text.png If height and width are not explicitly set, Text will attempt to determine how - much room is needed and set it accordingly. Unless \c wrap is set, it will always + much room is needed and set it accordingly. Unless \c wrapMode is set, it will always prefer width to height (all text will be placed on a single line). The \c elide property can alternatively be used to fit a single line of @@ -98,7 +99,7 @@ QT_BEGIN_NAMESPACE \image text.png If height and width are not explicitly set, Text will attempt to determine how - much room is needed and set it accordingly. Unless \c wrap is set, it will always + much room is needed and set it accordingly. Unless \c wrapMode is set, it will always prefer width to height (all text will be placed on a single line). The \c elide property can alternatively be used to fit a line of plain text to a set width. @@ -121,14 +122,116 @@ QDeclarativeTextPrivate::~QDeclarativeTextPrivate() /*! \qmlproperty string Text::font.family + + Sets the family name of the font. + + The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]". + If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen. + If the family isn't available a family will be set using the font matching algorithm. +*/ + +/*! \qmlproperty bool Text::font.bold + + Sets the font's weight to bold. +*/ + +/*! + \qmlproperty enumeration Text::font.weight + + Sets the font's weight. + + The weight can be one of: + \list + \o Light + \o Normal - the default + \o DemiBold + \o Bold + \o Black + \endlist + + \qml + Text { text: "Hello"; font.weight: Font.DemiBold } + \endqml +*/ + +/*! \qmlproperty bool Text::font.italic + + Sets the style of the text to italic. +*/ + +/*! \qmlproperty bool Text::font.underline + + Set the style of the text to underline. +*/ + +/*! + \qmlproperty bool Text::font.outline + + Set the style of the text to outline. +*/ + +/*! + \qmlproperty bool Text::font.strikeout + + Set the style of the text to strikeout. +*/ + +/*! \qmlproperty real Text::font.pointSize + + Sets the font size in points. The point size must be greater than zero. +*/ + +/*! \qmlproperty int Text::font.pixelSize - Set the Text's font attributes. + Sets the font size in pixels. + + Using this function makes the font device dependent. + Use \c pointSize to set the size of the font in a device independent manner. +*/ + +/*! + \qmlproperty real Text::font.letterSpacing + + Sets the letter spacing for the font. + + Letter spacing changes the default spacing between individual letters in the font. + A value of 100 will keep the spacing unchanged; a value of 200 will enlarge the spacing after a character by + the width of the character itself. +*/ + +/*! + \qmlproperty real Text::font.wordSpacing + + Sets the word spacing for the font. + + Word spacing changes the default spacing between individual words. + A positive value increases the word spacing by a corresponding amount of pixels, + while a negative value decreases the inter-word spacing accordingly. */ + +/*! + \qmlproperty enumeration Text::font.capitalization + + Sets the capitalization for the text. + + \list + \o MixedCase - This is the normal text rendering option where no capitalization change is applied. + \o AllUppercase - This alters the text to be rendered in all uppercase type. + \o AllLowercase - This alters the text to be rendered in all lowercase type. + \o SmallCaps - This alters the text to be rendered in small-caps type. + \o Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. + \endlist + + \qml + Text { text: "Hello"; font.capitalization: Font.AllLowercase } + \endqml +*/ + QFont QDeclarativeText::font() const { Q_D(const QDeclarativeText); @@ -319,37 +422,55 @@ void QDeclarativeText::setVAlign(VAlignment align) } /*! - \qmlproperty bool Text::wrap + \qmlproperty enumeration Text::wrapMode Set this property to wrap the text to the Text item's width. The text will only - wrap if an explicit width has been set. + wrap if an explicit width has been set. wrapMode can be one of: - Wrapping is done on word boundaries (i.e. it is a "word-wrap"). If the text cannot be + \list + \o NoWrap - no wrapping will be performed. + \o WordWrap - wrapping is done on word boundaries. If the text cannot be word-wrapped to the specified width it will be partially drawn outside of the item's bounds. If this is undesirable then enable clipping on the item (Item::clip). + \o WrapAnywhere - Text can be wrapped at any point on a line, even if it occurs in the middle of a word. + \o WrapAtWordBoundaryOrAnywhere - If possible, wrapping occurs at a word boundary; otherwise it + will occur at the appropriate point on the line, even in the middle of a word. + \endlist - Wrapping is off by default. + The default is NoWrap. */ -//### Future may provide choice of wrap modes, such as QTextOption::WrapAtWordBoundaryOrAnywhere -bool QDeclarativeText::wrap() const +QDeclarativeText::WrapMode QDeclarativeText::wrapMode() const { Q_D(const QDeclarativeText); - return d->wrap; + return d->wrapMode; } -void QDeclarativeText::setWrap(bool w) +void QDeclarativeText::setWrapMode(WrapMode mode) { Q_D(QDeclarativeText); - if (w == d->wrap) + if (mode == d->wrapMode) return; - d->wrap = w; + d->wrapMode = mode; d->updateLayout(); d->markImgDirty(); - emit wrapChanged(d->wrap); + emit wrapModeChanged(); } +bool QDeclarativeText::wrap() const +{ + Q_D(const QDeclarativeText); + return d->wrapMode != NoWrap; +} + +void QDeclarativeText::setWrap(bool w) +{ + qmlInfo(this) << "\"wrap\" property is deprecated and will soon be removed. Use wrapMode"; + setWrapMode(w ? WordWrap : NoWrap); +} + + /*! \qmlproperty enumeration Text::textFormat @@ -379,18 +500,18 @@ void QDeclarativeText::setWrap(bool w) \o \qml Column { - TextEdit { + Text { font.pointSize: 24 text: "<b>Hello</b> <i>World!</i>" } - TextEdit { + Text { font.pointSize: 24 - textFormat: "RichText" + textFormat: Text.RichText text: "<b>Hello</b> <i>World!</i>" } - TextEdit { + Text { font.pointSize: 24 - textFormat: "PlainText" + textFormat: Text.PlainText text: "<b>Hello</b> <i>World!</i>" } } @@ -437,9 +558,15 @@ void QDeclarativeText::setTextFormat(TextFormat format) Set this property to elide parts of the text fit to the Text item's width. The text will only elide if an explicit width has been set. - This property cannot be used with wrap enabled or with rich text. + This property cannot be used with wrapping enabled or with rich text. - Eliding can be \c ElideNone (the default), \c ElideLeft, \c ElideMiddle, or \c ElideRight. + Eliding can be: + \list + \o ElideNone - the default + \o ElideLeft + \o ElideMiddle + \o ElideRight + \endlist If the text is a multi-length string, and the mode is not \c ElideNone, the first string that fits will be used, otherwise the last will be elided. @@ -471,7 +598,7 @@ void QDeclarativeText::geometryChanged(const QRectF &newGeometry, { Q_D(QDeclarativeText); if (newGeometry.width() != oldGeometry.width()) { - if (d->wrap || d->elideMode != QDeclarativeText::ElideNone) { + if (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone) { //re-elide if needed if (d->singleline && d->elideMode != QDeclarativeText::ElideNone && isComponentComplete() && widthValid()) { @@ -538,12 +665,9 @@ void QDeclarativeTextPrivate::updateSize() singleline = false; // richtext can't elide or be optimized for single-line case doc->setDefaultFont(font); QTextOption option((Qt::Alignment)int(hAlign | vAlign)); - if (wrap) - option.setWrapMode(QTextOption::WordWrap); - else - option.setWrapMode(QTextOption::NoWrap); + option.setWrapMode(QTextOption::WrapMode(wrapMode)); doc->setDefaultTextOption(option); - if (wrap && !q->heightValid() && q->widthValid()) + if (wrapMode != QDeclarativeText::NoWrap && !q->heightValid() && q->widthValid()) doc->setTextWidth(q->width()); else doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug) @@ -623,9 +747,13 @@ QSize QDeclarativeTextPrivate::setupTextLayout(QTextLayout *layout) qreal lineWidth = 0; //set manual width - if ((wrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) + if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) lineWidth = q->width(); + QTextOption textOption = layout->textOption(); + textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); + layout->setTextOption(textOption); + layout->beginLayout(); while (1) { @@ -633,7 +761,7 @@ QSize QDeclarativeTextPrivate::setupTextLayout(QTextLayout *layout) if (!line.isValid()) break; - if ((wrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) + if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) line.setLineWidth(lineWidth); } layout->endLayout(); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index cbea8f3..871c833 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -42,6 +42,7 @@ #ifndef QDECLARATIVETEXT_H #define QDECLARATIVETEXT_H +#include <QtGui/qtextoption.h> #include "qdeclarativeitem.h" QT_BEGIN_HEADER @@ -58,6 +59,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeText : public QDeclarativeItem Q_ENUMS(TextStyle) Q_ENUMS(TextFormat) Q_ENUMS(TextElideMode) + Q_ENUMS(WrapMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) @@ -66,7 +68,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeText : public QDeclarativeItem Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor NOTIFY styleColorChanged) Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) - Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged) //### there are several wrap modes in Qt + Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) + Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapModeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? @@ -93,6 +96,12 @@ public: ElideMiddle = Qt::ElideMiddle, ElideNone = Qt::ElideNone }; + enum WrapMode { NoWrap = QTextOption::NoWrap, + WordWrap = QTextOption::WordWrap, + WrapAnywhere = QTextOption::WrapAnywhere, + WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere + }; + QString text() const; void setText(const QString &); @@ -116,6 +125,8 @@ public: bool wrap() const; void setWrap(bool w); + WrapMode wrapMode() const; + void setWrapMode(WrapMode w); TextFormat textFormat() const; void setTextFormat(TextFormat format); @@ -136,7 +147,7 @@ Q_SIGNALS: void styleColorChanged(const QColor &color); void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); - void wrapChanged(bool wrap); + void wrapModeChanged(); void textFormatChanged(TextFormat textFormat); void elideModeChanged(TextElideMode mode); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index 85a65ce..cc5a9f2 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -72,8 +72,8 @@ public: QDeclarativeTextPrivate() : color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft), vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), - imgDirty(true), dirty(true), wrap(false), richText(false), singleline(false), cache(true), doc(0), - format(QDeclarativeText::AutoText) + imgDirty(true), dirty(true), richText(false), singleline(false), cache(true), doc(0), + format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap) { #if defined(QML_NO_TEXT_CACHE) cache = false; @@ -115,7 +115,6 @@ public: QDeclarativeText::TextElideMode elideMode; bool imgDirty:1; bool dirty:1; - bool wrap:1; bool richText:1; bool singleline:1; bool cache:1; @@ -123,6 +122,7 @@ public: QTextLayout layout; QSize cachedLayoutSize; QDeclarativeText::TextFormat format; + QDeclarativeText::WrapMode wrapMode; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 7374bc8..1fec484 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -44,6 +44,7 @@ #include "private/qdeclarativeevents_p_p.h" #include <private/qdeclarativeglobal_p.h> +#include <qdeclarativeinfo.h> #include <QTextLayout> #include <QTextLine> @@ -117,13 +118,114 @@ QString QDeclarativeTextEdit::text() const /*! \qmlproperty string TextEdit::font.family + + Sets the family name of the font. + + The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]". + If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen. + If the family isn't available a family will be set using the font matching algorithm. +*/ + +/*! \qmlproperty bool TextEdit::font.bold + + Sets the font's weight to bold. +*/ + +/*! + \qmlproperty enumeration TextEdit::font.weight + + Sets the font's weight. + + The weight can be one of: + \list + \o Light + \o Normal - the default + \o DemiBold + \o Bold + \o Black + \endlist + + \qml + TextEdit { text: "Hello"; font.weight: Font.DemiBold } + \endqml +*/ + +/*! \qmlproperty bool TextEdit::font.italic + + Sets the style of the text to italic. +*/ + +/*! \qmlproperty bool TextEdit::font.underline + + Set the style of the text to underline. +*/ + +/*! + \qmlproperty bool TextEdit::font.outline + + Set the style of the text to outline. +*/ + +/*! + \qmlproperty bool TextEdit::font.strikeout + + Set the style of the text to strikeout. +*/ + +/*! \qmlproperty real TextEdit::font.pointSize + + Sets the font size in points. The point size must be greater than zero. +*/ + +/*! \qmlproperty int TextEdit::font.pixelSize - Set the TextEdit's font attributes. + Sets the font size in pixels. + + Using this function makes the font device dependent. + Use \c pointSize to set the size of the font in a device independent manner. +*/ + +/*! + \qmlproperty real TextEdit::font.letterSpacing + + Sets the letter spacing for the font. + + Letter spacing changes the default spacing between individual letters in the font. + A value of 100 will keep the spacing unchanged; a value of 200 will enlarge the spacing after a character by + the width of the character itself. +*/ + +/*! + \qmlproperty real TextEdit::font.wordSpacing + + Sets the word spacing for the font. + + Word spacing changes the default spacing between individual words. + A positive value increases the word spacing by a corresponding amount of pixels, + while a negative value decreases the inter-word spacing accordingly. +*/ + +/*! + \qmlproperty enumeration TextEdit::font.capitalization + + Sets the capitalization for the text. + + \list + \o MixedCase - This is the normal text rendering option where no capitalization change is applied. + \o AllUppercase - This alters the text to be rendered in all uppercase type. + \o AllLowercase - This alters the text to be rendered in all lowercase type. + \o SmallCaps - This alters the text to be rendered in small-caps type. + \o Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. + \endlist + + \qml + TextEdit { text: "Hello"; font.capitalization: Font.AllLowercase } + \endqml */ /*! @@ -170,12 +272,12 @@ Column { } TextEdit { font.pointSize: 24 - textFormat: "RichText" + textFormat: TextEdit.RichText text: "<b>Hello</b> <i>World!</i>" } TextEdit { font.pointSize: 24 - textFormat: "PlainText" + textFormat: TextEdit.PlainText text: "<b>Hello</b> <i>World!</i>" } } @@ -360,29 +462,50 @@ void QDeclarativeTextEdit::setVAlign(QDeclarativeTextEdit::VAlignment alignment) emit verticalAlignmentChanged(d->vAlign); } -bool QDeclarativeTextEdit::wrap() const -{ - Q_D(const QDeclarativeTextEdit); - return d->wrap; -} - /*! - \qmlproperty bool TextEdit::wrap + \qmlproperty enumeration TextEdit::wrapMode Set this property to wrap the text to the TextEdit item's width. The text will only wrap if an explicit width has been set. - Wrapping is done on word boundaries (i.e. it is a "word-wrap"). Wrapping is off by default. + \list + \o NoWrap - no wrapping will be performed. + \o WordWrap - wrapping is done on word boundaries. + \o WrapAnywhere - Text can be wrapped at any point on a line, even if it occurs in the middle of a word. + \o WrapAtWordBoundaryOrAnywhere - If possible, wrapping occurs at a word boundary; otherwise it + will occur at the appropriate point on the line, even in the middle of a word. + \endlist + + The default is NoWrap. */ -void QDeclarativeTextEdit::setWrap(bool w) +QDeclarativeTextEdit::WrapMode QDeclarativeTextEdit::wrapMode() const +{ + Q_D(const QDeclarativeTextEdit); + return d->wrapMode; +} + +void QDeclarativeTextEdit::setWrapMode(WrapMode mode) { Q_D(QDeclarativeTextEdit); - if (w == d->wrap) + if (mode == d->wrapMode) return; - d->wrap = w; + d->wrapMode = mode; d->updateDefaultTextOption(); updateSize(); - emit wrapChanged(d->wrap); + emit wrapModeChanged(); +} + +bool QDeclarativeTextEdit::wrap() const +{ + Q_D(const QDeclarativeTextEdit); + return d->wrapMode != QDeclarativeTextEdit::NoWrap; +} + +void QDeclarativeTextEdit::setWrap(bool w) +{ + + qmlInfo(this) << "\"wrap\" property is deprecated and will soon be removed. Use wrapMode"; + setWrapMode(w ? WordWrap : NoWrap); } /*! @@ -666,7 +789,7 @@ void QDeclarativeTextEdit::componentComplete() */ void QDeclarativeTextEdit::setReadOnly(bool r) { - Q_D(QDeclarativeTextEdit); + Q_D(QDeclarativeTextEdit); if (r == isReadOnly()) return; @@ -1020,11 +1143,7 @@ void QDeclarativeTextEditPrivate::updateDefaultTextOption() opt.setAlignment((Qt::Alignment)(int)(hAlign | vAlign)); QTextOption::WrapMode oldWrapMode = opt.wrapMode(); - - if (wrap) - opt.setWrapMode(QTextOption::WordWrap); - else - opt.setWrapMode(QTextOption::NoWrap); + opt.setWrapMode(QTextOption::WrapMode(wrapMode)); if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment()) return; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 0e91e73..605b620 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -64,6 +64,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_ENUMS(VAlignment) Q_ENUMS(HAlignment) Q_ENUMS(TextFormat) + Q_ENUMS(WrapMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) @@ -72,7 +73,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) - Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged) //### other wrap modes + Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged) //### deprecated + Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged) Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged) @@ -107,6 +109,12 @@ public: AutoText = Qt::AutoText }; + enum WrapMode { NoWrap = QTextOption::NoWrap, + WordWrap = QTextOption::WordWrap, + WrapAnywhere = QTextOption::WrapAnywhere, + WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere + }; + QString text() const; void setText(const QString &); @@ -133,6 +141,8 @@ public: bool wrap() const; void setWrap(bool w); + WrapMode wrapMode() const; + void setWrapMode(WrapMode w); bool isCursorVisible() const; void setCursorVisible(bool on); @@ -185,7 +195,7 @@ Q_SIGNALS: void fontChanged(const QFont &font); void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); - void wrapChanged(bool isWrapped); + void wrapModeChanged(); void textFormatChanged(TextFormat textFormat); void readOnlyChanged(bool isReadOnly); void cursorVisibleChanged(bool isCursorVisible); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 310db48..8d4b611 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -68,10 +68,11 @@ class QDeclarativeTextEditPrivate : public QDeclarativePaintedItemPrivate public: QDeclarativeTextEditPrivate() - : color("black"), imgDirty(true), hAlign(QDeclarativeTextEdit::AlignLeft), vAlign(QDeclarativeTextEdit::AlignTop), - dirty(false), wrap(false), richText(false), cursorVisible(false), focusOnPress(true), + : color("black"), hAlign(QDeclarativeTextEdit::AlignLeft), vAlign(QDeclarativeTextEdit::AlignTop), + imgDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true), persistentSelection(true), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), - cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0) + cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), + wrapMode(QDeclarativeTextEdit::NoWrap) { } @@ -89,17 +90,16 @@ public: QColor selectedTextColor; QString style; QColor styleColor; - bool imgDirty; QPixmap imgCache; QPixmap imgStyleCache; QDeclarativeTextEdit::HAlignment hAlign; QDeclarativeTextEdit::VAlignment vAlign; - bool dirty; - bool wrap; - bool richText; - bool cursorVisible; - bool focusOnPress; - bool persistentSelection; + bool imgDirty : 1; + bool dirty : 1; + bool richText : 1; + bool cursorVisible : 1; + bool focusOnPress : 1; + bool persistentSelection : 1; qreal textMargin; int lastSelectionStart; int lastSelectionEnd; @@ -108,6 +108,7 @@ public: QDeclarativeTextEdit::TextFormat format; QTextDocument *document; QTextControl *control; + QDeclarativeTextEdit::WrapMode wrapMode; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index e6d0948..89ec834 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -97,14 +97,116 @@ void QDeclarativeTextInput::setText(const QString &s) /*! \qmlproperty string TextInput::font.family + + Sets the family name of the font. + + The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]". + If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen. + If the family isn't available a family will be set using the font matching algorithm. +*/ + +/*! \qmlproperty bool TextInput::font.bold + + Sets the font's weight to bold. +*/ + +/*! + \qmlproperty enumeration TextInput::font.weight + + Sets the font's weight. + + The weight can be one of: + \list + \o Light + \o Normal - the default + \o DemiBold + \o Bold + \o Black + \endlist + + \qml + TextInput { text: "Hello"; font.weight: Font.DemiBold } + \endqml +*/ + +/*! \qmlproperty bool TextInput::font.italic + + Sets the style of the text to italic. +*/ + +/*! \qmlproperty bool TextInput::font.underline + + Set the style of the text to underline. +*/ + +/*! + \qmlproperty bool TextInput::font.outline + + Set the style of the text to outline. +*/ + +/*! + \qmlproperty bool TextInput::font.strikeout + + Set the style of the text to strikeout. +*/ + +/*! \qmlproperty real TextInput::font.pointSize + + Sets the font size in points. The point size must be greater than zero. +*/ + +/*! \qmlproperty int TextInput::font.pixelSize - Set the TextInput's font attributes. + Sets the font size in pixels. + + Using this function makes the font device dependent. + Use \c pointSize to set the size of the font in a device independent manner. +*/ + +/*! + \qmlproperty real TextInput::font.letterSpacing + + Sets the letter spacing for the font. + + Letter spacing changes the default spacing between individual letters in the font. + A value of 100 will keep the spacing unchanged; a value of 200 will enlarge the spacing after a character by + the width of the character itself. */ + +/*! + \qmlproperty real TextInput::font.wordSpacing + + Sets the word spacing for the font. + + Word spacing changes the default spacing between individual words. + A positive value increases the word spacing by a corresponding amount of pixels, + while a negative value decreases the inter-word spacing accordingly. +*/ + +/*! + \qmlproperty enumeration TextInput::font.capitalization + + Sets the capitalization for the text. + + \list + \o MixedCase - This is the normal text rendering option where no capitalization change is applied. + \o AllUppercase - This alters the text to be rendered in all uppercase type. + \o AllLowercase - This alters the text to be rendered in all lowercase type. + \o SmallCaps - This alters the text to be rendered in small-caps type. + \o Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. + \endlist + + \qml + TextInput { text: "Hello"; font.capitalization: Font.AllLowercase } + \endqml +*/ + QFont QDeclarativeTextInput::font() const { Q_D(const QDeclarativeTextInput); @@ -429,6 +531,29 @@ void QDeclarativeTextInput::setFocusOnPress(bool b) } /*! + \qmlproperty bool TextInput::autoScroll + + Whether the TextInput should scroll when the text is longer than the width. By default this is + set to true. +*/ +bool QDeclarativeTextInput::autoScroll() const +{ + Q_D(const QDeclarativeTextInput); + return d->autoScroll; +} + +void QDeclarativeTextInput::setAutoScroll(bool b) +{ + Q_D(QDeclarativeTextInput); + if (d->autoScroll == b) + return; + + d->autoScroll = b; + + emit autoScrollChanged(d->autoScroll); +} + +/*! \qmlproperty Validator TextInput::validator Allows you to set a validator on the TextInput. When a validator is set @@ -449,7 +574,7 @@ void QDeclarativeTextInput::setFocusOnPress(bool b) input of integers between 11 and 31 into the text input: \code - import Qt 4.6 + import Qt 4.7 TextInput{ validator: IntValidator{bottom: 11; top: 31;} focus: true @@ -658,6 +783,8 @@ void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus) q->setCursorVisible(hasFocus); if(q->echoMode() == QDeclarativeTextInput::PasswordEchoOnEdit && !hasFocus) control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events + if (!hasFocus) + control->deselect(); QDeclarativeItemPrivate::focusChanged(hasFocus); } @@ -692,7 +819,15 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) } setFocus(true); } - d->control->processEvent(event); + bool mark = event->modifiers() & Qt::ShiftModifier; + int cursor = d->xToPos(event->pos().x()); + d->control->moveCursor(cursor, mark); +} + +void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativeTextInput); + d->control->moveCursor(d->xToPos(event->pos().x()), true); } /*! @@ -717,6 +852,7 @@ bool QDeclarativeTextInput::event(QEvent* ev) case QEvent::KeyPress: case QEvent::KeyRelease://###Should the control be doing anything with release? case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMouseRelease: break; default: @@ -746,28 +882,56 @@ void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r) int flags = QLineControl::DrawText; if(!isReadOnly() && d->cursorVisible && !d->cursorItem) flags |= QLineControl::DrawCursor; - if (d->control->hasSelectedText()){ + if (d->control->hasSelectedText()) flags |= QLineControl::DrawSelections; - } - QPoint offset = QPoint(0,0); - if(d->hAlign != AlignLeft){ - QFontMetrics fm = QFontMetrics(d->font); - //###Is this using bearing appropriately? - int minLB = qMax(0, -fm.minLeftBearing()); - int minRB = qMax(0, -fm.minRightBearing()); - int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; - int hOffset = 0; + QFontMetrics fm = QFontMetrics(d->font); + int cix = qRound(d->control->cursorToX()); + QRect br(boundingRect().toRect()); + //###Is this using bearing appropriately? + int minLB = qMax(0, -fm.minLeftBearing()); + int minRB = qMax(0, -fm.minRightBearing()); + int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; + if (d->autoScroll) { + if ((minLB + widthUsed) <= br.width()) { + // text fits in br; use hscroll for alignment + switch (d->hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { + case Qt::AlignRight: + d->hscroll = widthUsed - br.width() + 1; + break; + case Qt::AlignHCenter: + d->hscroll = (widthUsed - br.width()) / 2; + break; + default: + // Left + d->hscroll = 0; + break; + } + d->hscroll -= minLB; + } else if (cix - d->hscroll >= br.width()) { + // text doesn't fit, cursor is to the right of br (scroll right) + d->hscroll = cix - br.width() + 1; + } else if (cix - d->hscroll < 0 && d->hscroll < widthUsed) { + // text doesn't fit, cursor is to the left of br (scroll left) + d->hscroll = cix; + } else if (widthUsed - d->hscroll < br.width()) { + // text doesn't fit, text document is to the left of br; align + // right + d->hscroll = widthUsed - br.width() + 1; + } + // the y offset is there to keep the baseline constant in case we have script changes in the text. + offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); + } else { if(d->hAlign == AlignRight){ - hOffset = width() - widthUsed; + d->hscroll = width() - widthUsed; }else if(d->hAlign == AlignHCenter){ - hOffset = (width() - widthUsed) / 2; + d->hscroll = (width() - widthUsed) / 2; } - hOffset -= minLB; - offset = QPoint(hOffset, 0); + d->hscroll -= minLB; + offset = QPoint(d->hscroll, 0); } - QRect clipRect = r; - d->control->draw(p, offset, clipRect, flags); + + d->control->draw(p, offset, r, flags); p->restore(); } @@ -973,10 +1137,11 @@ void QDeclarativeTextInput::q_textChanged() void QDeclarativeTextInput::updateRect(const QRect &r) { + Q_D(QDeclarativeTextInput); if(r == QRect()) clearCache(); else - dirtyCache(r); + dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height())); update(); } diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index e453f5d..c0c1e50 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -88,6 +88,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextInput : public QDeclarativePaintedIte Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY focusOnPressChanged) Q_PROPERTY(QString passwordCharacter READ passwordCharacter WRITE setPasswordCharacter NOTIFY passwordCharacterChanged) Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) + Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) public: QDeclarativeTextInput(QDeclarativeItem* parent=0); @@ -170,6 +171,9 @@ public: bool focusOnPress() const; void setFocusOnPress(bool); + bool autoScroll() const; + void setAutoScroll(bool); + bool hasAcceptableInput() const; void drawContents(QPainter *p,const QRect &r); @@ -198,12 +202,14 @@ Q_SIGNALS: void passwordCharacterChanged(); void displayTextChanged(const QString &text); void focusOnPressChanged(bool focusOnPress); + void autoScrollChanged(bool autoScroll); protected: virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void keyPressEvent(QKeyEvent* ev); bool event(QEvent *e); @@ -229,10 +235,8 @@ QT_END_NAMESPACE QML_DECLARE_TYPE(QDeclarativeTextInput) QML_DECLARE_TYPE(QValidator) QML_DECLARE_TYPE(QIntValidator) -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) QML_DECLARE_TYPE(QDoubleValidator) QML_DECLARE_TYPE(QRegExpValidator) -#endif QT_END_HEADER diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 9e44b15..26cf78c 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -72,7 +72,7 @@ public: color((QRgb)0), style(QDeclarativeText::Normal), styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), hscroll(0), oldScroll(0), focused(false), focusOnPress(true), - cursorVisible(false) + cursorVisible(false), autoScroll(true) { } @@ -81,6 +81,14 @@ public: delete control; } + int xToPos(int x, QTextLine::CursorPosition betweenOrOn = QTextLine::CursorBetweenCharacters) const + { + Q_Q(const QDeclarativeTextInput); + QRect cr = q->boundingRect().toRect(); + x-= cr.x() - hscroll; + return control->xToPos(x, betweenOrOn); + } + void init(); void startCreatingCursor(); void focusChanged(bool hasFocus); @@ -107,6 +115,7 @@ public: bool focused; bool focusOnPress; bool cursorVisible; + bool autoScroll; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 2938f51..15348ed 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -830,7 +830,7 @@ void QDeclarativeVisualDataModel::setDelegate(QDeclarativeComponent *delegate) \code // view.qml - import Qt 4.6 + import Qt 4.7 ListView { width: 200 @@ -1152,6 +1152,8 @@ void QDeclarativeVisualDataModel::_q_itemsChanged(int index, int count, void QDeclarativeVisualDataModel::_q_itemsInserted(int index, int count) { Q_D(QDeclarativeVisualDataModel); + if (!count) + return; // XXX - highly inefficient QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef> items; for (QHash<int,QDeclarativeVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin(); @@ -1179,6 +1181,8 @@ void QDeclarativeVisualDataModel::_q_itemsInserted(int index, int count) void QDeclarativeVisualDataModel::_q_itemsRemoved(int index, int count) { Q_D(QDeclarativeVisualDataModel); + if (!count) + return; // XXX - highly inefficient QHash<int, QDeclarativeVisualDataModelPrivate::ObjectRef> items; for (QHash<int, QDeclarativeVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin(); diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 7c7f6e5..6e36d4f 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -119,6 +119,38 @@ int qmlRegisterType() } template<typename T> +int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) +{ + QByteArray name(T::staticMetaObject.className()); + + QByteArray pointerName(name + '*'); + QByteArray listName("QDeclarativeListProperty<" + name + ">"); + + QDeclarativePrivate::RegisterType type = { + 0, + + qRegisterMetaType<T *>(pointerName.constData()), + qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), + 0, 0, + + uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + + QDeclarativePrivate::attachedPropertiesFunc<T>(), + QDeclarativePrivate::attachedPropertiesMetaObject<T>(), + + QDeclarativePrivate::StaticCastSelector<T,QDeclarativeParserStatus>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueSource>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueInterceptor>::cast(), + + 0, 0, + + 0 + }; + + return QDeclarativePrivate::registerType(type); +} + +template<typename T> int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { QByteArray name(T::staticMetaObject.className()); diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 71cf3cb..e172a8b 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -126,7 +126,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) QDeclarativeBindingData *data = d->bindingData(); - if (!data->enabled) + if (!data->enabled || !data->context() || !data->context()->engine) return; data->addref(); @@ -148,14 +148,37 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) idx, a); } else { + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context()->engine); + bool isUndefined = false; - QVariant value = this->value(&isUndefined); + QVariant value; + + QScriptValue scriptValue = d->scriptValue(0, &isUndefined); + if (data->property.propertyTypeCategory() == QDeclarativeProperty::List) { + value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >()); + } else { + value = ep->scriptValueToVariant(scriptValue, data->property.propertyType()); + if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) { + // If the object is null, we extract the predicted type. While this isn't + // 100% reliable, in many cases it gives us better error messages if we + // assign this null-object to an incompatible property + int type = ep->objectClass->objectType(scriptValue); + QObject *o = 0; + value = QVariant(type, (void *)&o); + } + } - if (isUndefined && !data->error.isValid() && data->property.isResettable()) { + if (data->error.isValid()) { + + } else if (isUndefined && data->property.isResettable()) { data->property.reset(); - } else if (isUndefined && !data->error.isValid()) { + } else if (isUndefined && data->property.propertyType() == qMetaTypeId<QVariant>()) { + + QDeclarativePropertyPrivate::write(data->property, QVariant(), flags); + + } else if (isUndefined) { QUrl url = QUrl(data->url); int line = data->line; @@ -166,7 +189,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) data->error.setColumn(-1); data->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(data->property.propertyType()))); - } else if (!isUndefined && data->property.object() && + } else if (data->property.object() && !QDeclarativePropertyPrivate::write(data->property, value, flags)) { QUrl url = QUrl(data->url); @@ -187,9 +210,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) } if (data->error.isValid()) { - QDeclarativeEnginePrivate *p = (data->context() && data->context()->engine)? - QDeclarativeEnginePrivate::get(data->context()->engine):0; - if (!data->addError(p)) + if (!data->addError(ep)) qWarning().nospace() << qPrintable(this->error().toString()); } else { data->removeError(); diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 53143d5..0c824fc 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL); DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER); DEFINE_BOOL_CONFIG_OPTION(qmlDisableFastProperties, QML_DISABLE_FAST_PROPERTIES); +DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP); Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties); @@ -137,7 +138,7 @@ public: Subscription *subscriptions; QScriptDeclarativeClass::PersistentIdentifier *identifiers; - void run(Binding *); + void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags); const char *programData; Binding *m_bindings; @@ -147,7 +148,7 @@ public: void init(); void run(int instr, QDeclarativeContextData *context, - QDeclarativeDelayedError *error, QObject *scope, QObject *output); + QDeclarativeDelayedError *error, QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags); inline void unsubscribe(int subIndex); @@ -246,9 +247,9 @@ int QDeclarativeCompiledBindingsPrivate::Binding::propertyIndex() return property & 0xFFFF; } -void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags) +void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) { - parent->run(this); + parent->run(this, flags); } void QDeclarativeCompiledBindingsPrivate::Binding::destroy() @@ -270,13 +271,13 @@ int QDeclarativeCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void quint32 count = *reeval; ++reeval; for (quint32 ii = 0; ii < count; ++ii) { - d->run(d->m_bindings + reeval[ii]); + d->run(d->m_bindings + reeval[ii], QDeclarativePropertyPrivate::DontRemoveBinding); } } return -1; } -void QDeclarativeCompiledBindingsPrivate::run(Binding *binding) +void QDeclarativeCompiledBindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags) { Q_Q(QDeclarativeCompiledBindings); @@ -319,12 +320,11 @@ void QDeclarativeCompiledBindingsPrivate::run(Binding *binding) vt->read(binding->target, binding->property & 0xFFFF); QObject *target = vt; - run(binding->index, context, binding, binding->scope, target); + run(binding->index, context, binding, binding->scope, target, flags); - vt->write(binding->target, binding->property & 0xFFFF, - QDeclarativePropertyPrivate::DontRemoveBinding); + vt->write(binding->target, binding->property & 0xFFFF, flags); } else { - run(binding->index, context, binding, binding->scope, binding->target); + run(binding->index, context, binding, binding->scope, binding->target, flags); } binding->updating = false; } @@ -334,6 +334,7 @@ namespace { struct Instr { enum { Noop, + BindingId, // id Subscribe, // subscribe SubscribeId, // subscribe @@ -404,6 +405,12 @@ struct Instr { } common; struct { quint8 type; + quint8 packing; + quint16 column; + quint32 line; + } id; + struct { + quint8 type; quint8 packing[3]; quint16 subscriptions; quint16 identifiers; @@ -943,156 +950,158 @@ static void dumpInstruction(const Instr *instr) { switch (instr->common.type) { case Instr::Noop: - qWarning().nospace() << "Noop"; + qWarning().nospace() << "\t" << "Noop"; + break; + case Instr::BindingId: + qWarning().nospace() << instr->id.line << ":" << instr->id.column << ":"; break; case Instr::Subscribe: - qWarning().nospace() << "Subscribe" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index; + qWarning().nospace() << "\t" << "Subscribe" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index; break; case Instr::SubscribeId: - qWarning().nospace() << "SubscribeId" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index; + qWarning().nospace() << "\t" << "SubscribeId" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index; break; case Instr::FetchAndSubscribe: - qWarning().nospace() << "FetchAndSubscribe" << "\t" << instr->fetchAndSubscribe.output << "\t" << instr->fetchAndSubscribe.objectReg << "\t" << instr->fetchAndSubscribe.subscription; + qWarning().nospace() << "\t" << "FetchAndSubscribe" << "\t" << instr->fetchAndSubscribe.output << "\t" << instr->fetchAndSubscribe.objectReg << "\t" << instr->fetchAndSubscribe.subscription; break; case Instr::LoadId: - qWarning().nospace() << "LoadId" << "\t\t\t" << instr->load.index << "\t" << instr->load.reg; + qWarning().nospace() << "\t" << "LoadId" << "\t\t\t" << instr->load.index << "\t" << instr->load.reg; break; case Instr::LoadScope: - qWarning().nospace() << "LoadScope" << "\t\t" << instr->load.index << "\t" << instr->load.reg; + qWarning().nospace() << "\t" << "LoadScope" << "\t\t" << instr->load.index << "\t" << instr->load.reg; break; case Instr::LoadRoot: - qWarning().nospace() << "LoadRoot" << "\t\t" << instr->load.index << "\t" << instr->load.reg; + qWarning().nospace() << "\t" << "LoadRoot" << "\t\t" << instr->load.index << "\t" << instr->load.reg; break; case Instr::LoadAttached: - qWarning().nospace() << "LoadAttached" << "\t\t" << instr->attached.output << "\t" << instr->attached.reg << "\t" << instr->attached.index; + qWarning().nospace() << "\t" << "LoadAttached" << "\t\t" << instr->attached.output << "\t" << instr->attached.reg << "\t" << instr->attached.index; break; case Instr::ConvertIntToReal: - qWarning().nospace() << "ConvertIntToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; + qWarning().nospace() << "\t" << "ConvertIntToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; break; case Instr::ConvertRealToInt: - qWarning().nospace() << "ConvertRealToInt" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; + qWarning().nospace() << "\t" << "ConvertRealToInt" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; break; case Instr::Real: - qWarning().nospace() << "Real" << "\t\t\t" << instr->real_value.reg << "\t" << instr->real_value.value; + qWarning().nospace() << "\t" << "Real" << "\t\t\t" << instr->real_value.reg << "\t" << instr->real_value.value; break; case Instr::Int: - qWarning().nospace() << "Int" << "\t\t\t" << instr->int_value.reg << "\t" << instr->int_value.value; + qWarning().nospace() << "\t" << "Int" << "\t\t\t" << instr->int_value.reg << "\t" << instr->int_value.value; break; case Instr::Bool: - qWarning().nospace() << "Bool" << "\t\t\t" << instr->bool_value.reg << "\t" << instr->bool_value.value; + qWarning().nospace() << "\t" << "Bool" << "\t\t\t" << instr->bool_value.reg << "\t" << instr->bool_value.value; break; case Instr::String: - qWarning().nospace() << "String" << "\t\t\t" << instr->string_value.reg << "\t" << instr->string_value.offset << "\t" << instr->string_value.length; + qWarning().nospace() << "\t" << "String" << "\t\t\t" << instr->string_value.reg << "\t" << instr->string_value.offset << "\t" << instr->string_value.length; break; case Instr::AddReal: - qWarning().nospace() << "AddReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "AddReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::AddInt: - qWarning().nospace() << "AddInt" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "AddInt" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::AddString: - qWarning().nospace() << "AddString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "AddString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::MinusReal: - qWarning().nospace() << "MinusReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "MinusReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::MinusInt: - qWarning().nospace() << "MinusInt" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "MinusInt" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::CompareReal: - qWarning().nospace() << "CompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "CompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::CompareString: - qWarning().nospace() << "CompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "CompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::NotCompareReal: - qWarning().nospace() << "NotCompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "NotCompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::NotCompareString: - qWarning().nospace() << "NotCompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "NotCompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::GreaterThanReal: - qWarning().nospace() << "GreaterThanReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "GreaterThanReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::MaxReal: - qWarning().nospace() << "MaxReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "MaxReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::MinReal: - qWarning().nospace() << "MinReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; + qWarning().nospace() << "\t" << "MinReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2; break; case Instr::NewString: - qWarning().nospace() << "NewString" << "\t\t" << instr->construct.reg; + qWarning().nospace() << "\t" << "NewString" << "\t\t" << instr->construct.reg; break; case Instr::NewUrl: - qWarning().nospace() << "NewUrl" << "\t\t\t" << instr->construct.reg; + qWarning().nospace() << "\t" << "NewUrl" << "\t\t\t" << instr->construct.reg; break; case Instr::CleanupString: - qWarning().nospace() << "CleanupString" << "\t\t" << instr->cleanup.reg; + qWarning().nospace() << "\t" << "CleanupString" << "\t\t" << instr->cleanup.reg; break; case Instr::CleanupUrl: - qWarning().nospace() << "CleanupUrl" << "\t\t" << instr->cleanup.reg; + qWarning().nospace() << "\t" << "CleanupUrl" << "\t\t" << instr->cleanup.reg; break; case Instr::Fetch: - qWarning().nospace() << "Fetch" << "\t\t\t" << instr->fetch.output << "\t" << instr->fetch.index << "\t" << instr->fetch.objectReg; + qWarning().nospace() << "\t" << "Fetch" << "\t\t\t" << instr->fetch.output << "\t" << instr->fetch.index << "\t" << instr->fetch.objectReg; break; case Instr::Store: - qWarning().nospace() << "Store" << "\t\t\t" << instr->store.output << "\t" << instr->store.index << "\t" << instr->store.reg; + qWarning().nospace() << "\t" << "Store" << "\t\t\t" << instr->store.output << "\t" << instr->store.index << "\t" << instr->store.reg; break; case Instr::Copy: - qWarning().nospace() << "Copy" << "\t\t\t" << instr->copy.reg << "\t" << instr->copy.src; + qWarning().nospace() << "\t" << "Copy" << "\t\t\t" << instr->copy.reg << "\t" << instr->copy.src; break; case Instr::Skip: - qWarning().nospace() << "Skip" << "\t\t\t" << instr->skip.reg << "\t" << instr->skip.count; + qWarning().nospace() << "\t" << "Skip" << "\t\t\t" << instr->skip.reg << "\t" << instr->skip.count; break; case Instr::Done: - qWarning().nospace() << "Done"; + qWarning().nospace() << "\t" << "Done"; break; case Instr::InitString: - qWarning().nospace() << "InitString" << "\t\t" << instr->initstring.offset << "\t" << instr->initstring.dataIdx; + qWarning().nospace() << "\t" << "InitString" << "\t\t" << instr->initstring.offset << "\t" << instr->initstring.dataIdx; break; case Instr::FindGeneric: - qWarning().nospace() << "FindGeneric" << "\t\t" << instr->find.reg << "\t" << instr->find.name; + qWarning().nospace() << "\t" << "FindGeneric" << "\t\t" << instr->find.reg << "\t" << instr->find.name; break; case Instr::FindGenericTerminal: - qWarning().nospace() << "FindGenericTerminal" << "\t" << instr->find.reg << "\t" << instr->find.name; + qWarning().nospace() << "\t" << "FindGenericTerminal" << "\t" << instr->find.reg << "\t" << instr->find.name; break; case Instr::FindProperty: - qWarning().nospace() << "FindProperty" << "\t\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name; + qWarning().nospace() << "\t" << "FindProperty" << "\t\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name; break; case Instr::FindPropertyTerminal: - qWarning().nospace() << "FindPropertyTerminal" << "\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name; + qWarning().nospace() << "\t" << "FindPropertyTerminal" << "\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name; break; case Instr::CleanupGeneric: - qWarning().nospace() << "CleanupGeneric" << "\t\t" << instr->cleanup.reg; + qWarning().nospace() << "\t" << "CleanupGeneric" << "\t\t" << instr->cleanup.reg; break; case Instr::ConvertGenericToReal: - qWarning().nospace() << "ConvertGenericToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; + qWarning().nospace() << "\t" << "ConvertGenericToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; break; case Instr::ConvertGenericToBool: - qWarning().nospace() << "ConvertGenericToBool" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; + qWarning().nospace() << "\t" << "ConvertGenericToBool" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; break; case Instr::ConvertGenericToString: - qWarning().nospace() << "ConvertGenericToString" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; + qWarning().nospace() << "\t" << "ConvertGenericToString" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; break; case Instr::ConvertGenericToUrl: - qWarning().nospace() << "ConvertGenericToUrl" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; + qWarning().nospace() << "\t" << "ConvertGenericToUrl" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; break; default: - qWarning().nospace() << "Unknown"; + qWarning().nospace() << "\t" << "Unknown"; break; } } void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, QDeclarativeContextData *context, QDeclarativeDelayedError *error, - QObject *scope, QObject *output) + QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags) { Q_Q(QDeclarativeCompiledBindings); error->removeError(); Register registers[32]; - int storeFlags = 0; QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(context->engine); Program *program = (Program *)programData; @@ -1112,6 +1121,7 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, switch (instr->common.type) { case Instr::Noop: + case Instr::BindingId: break; case Instr::SubscribeId: @@ -1595,6 +1605,17 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node if (destination->type == -1) return false; + if (bindingsDump()) { + QDeclarativeJS::AST::ExpressionNode *n = node->expressionCast(); + if (n) { + Instr id; + id.common.type = Instr::BindingId; + id.id.column = n->firstSourceLocation().startColumn; + id.id.line = n->firstSourceLocation().startLine; + bytecode << id; + } + } + Result type; if (!parseExpression(node, type)) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index f4ccce1..fad7779 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -146,7 +146,7 @@ bool QDeclarativeCompiler::isSignalPropertyName(const QByteArray &name) For example: \code - COMPILE_EXCEPTION(property, QCoreApplication::translate("QDeclarativeCompiler","Error for property \"%1\"").arg(QString::fromUtf8(property->name))); + COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(QString::fromUtf8(property->name))); \endcode */ #define COMPILE_EXCEPTION(token, desc) \ @@ -184,7 +184,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, QString string = v->value.asScript(); if (!prop.isWritable()) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); if (prop.isEnumType()) { int value; @@ -193,7 +193,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, } else value = prop.enumerator().keyToValue(string.toUtf8().constData()); if (value == -1) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: unknown enumeration")); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration")); return true; } int type = prop.userType(); @@ -201,65 +201,65 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, case -1: break; case QVariant::String: - if (!v->value.isString()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: string expected")); + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected")); break; case QVariant::Url: - if (!v->value.isString()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: url expected")); + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: url expected")); break; case QVariant::UInt: { bool ok; string.toUInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: unsigned int expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsigned int expected")); } break; case QVariant::Int: { bool ok; string.toInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: int expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int expected")); } break; case QMetaType::Float: { bool ok; string.toFloat(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: float expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: float expected")); } break; case QVariant::Double: { bool ok; string.toDouble(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: double expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: double expected")); } break; case QVariant::Color: { bool ok; QDeclarativeStringConverters::colorFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: color expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected")); } break; case QVariant::Date: { bool ok; QDeclarativeStringConverters::dateFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: date expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected")); } break; case QVariant::Time: { bool ok; QDeclarativeStringConverters::timeFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: time expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected")); } break; case QVariant::DateTime: { bool ok; QDeclarativeStringConverters::dateTimeFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: datetime expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected")); } break; case QVariant::Point: @@ -267,7 +267,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QPointF point = QDeclarativeStringConverters::pointFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: point expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected")); } break; case QVariant::Size: @@ -275,7 +275,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QSizeF size = QDeclarativeStringConverters::sizeFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: size expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected")); } break; case QVariant::Rect: @@ -283,19 +283,19 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QRectF rect = QDeclarativeStringConverters::rectFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: rect expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected")); } break; case QVariant::Bool: { - if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: boolean expected")); + if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: boolean expected")); } break; case QVariant::Vector3D: { bool ok; QDeclarativeStringConverters::vector3DFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: 3D vector expected")); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected")); } break; default: @@ -304,7 +304,7 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(t); if (!converter) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type())))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type())))); } break; } @@ -342,9 +342,22 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, switch(type) { case -1: { - instr.type = QDeclarativeInstruction::StoreVariant; - instr.storeString.propertyIndex = prop.propertyIndex(); - instr.storeString.value = output->indexForString(string); + if (v->value.isNumber()) { + double n = v->value.asNumber(); + if (double(int(n)) == n) { + instr.type = QDeclarativeInstruction::StoreVariantInteger; + instr.storeInteger.propertyIndex = prop.propertyIndex(); + instr.storeInteger.value = int(n); + } else { + instr.type = QDeclarativeInstruction::StoreVariantDouble; + instr.storeDouble.propertyIndex = prop.propertyIndex(); + instr.storeDouble.value = n; + } + } else { + instr.type = QDeclarativeInstruction::StoreVariant; + instr.storeString.propertyIndex = prop.propertyIndex(); + instr.storeString.value = output->indexForString(string); + } } break; case QVariant::String: @@ -560,7 +573,7 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, if (tref.type) { ref.type = tref.type; if (!ref.type->isCreatable()) - COMPILE_EXCEPTION(parserRef->refObjects.first(), QCoreApplication::translate("QDeclarativeCompiler", "Element is not creatable.")); + COMPILE_EXCEPTION(parserRef->refObjects.first(), tr( "Element is not creatable.")); } else if (tref.unit) { ref.component = tref.unit->toComponent(engine); @@ -881,23 +894,38 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) } // Create the object - QDeclarativeInstruction create; - create.type = QDeclarativeInstruction::CreateObject; - create.line = obj->location.start.line; - create.create.column = obj->location.start.column; - create.create.data = -1; - if (!obj->custom.isEmpty()) - create.create.data = output->indexForByteArray(obj->custom); - create.create.type = obj->type; - if (!output->types.at(create.create.type).type && - !obj->bindingBitmask.isEmpty()) { - Q_ASSERT(obj->bindingBitmask.size() % 4 == 0); - create.create.bindingBits = - output->indexForByteArray(obj->bindingBitmask); + if (obj->custom.isEmpty() && output->types.at(obj->type).type && + !output->types.at(obj->type).type->isExtendedType() && obj != compileState.root) { + + QDeclarativeInstruction create; + create.type = QDeclarativeInstruction::CreateSimpleObject; + create.line = obj->location.start.line; + create.createSimple.create = output->types.at(obj->type).type->createFunction(); + create.createSimple.typeSize = output->types.at(obj->type).type->createSize(); + create.createSimple.column = obj->location.start.column; + output->bytecode << create; + } else { - create.create.bindingBits = -1; + + QDeclarativeInstruction create; + create.type = QDeclarativeInstruction::CreateObject; + create.line = obj->location.start.line; + create.create.column = obj->location.start.column; + create.create.data = -1; + if (!obj->custom.isEmpty()) + create.create.data = output->indexForByteArray(obj->custom); + create.create.type = obj->type; + if (!output->types.at(create.create.type).type && + !obj->bindingBitmask.isEmpty()) { + Q_ASSERT(obj->bindingBitmask.size() % 4 == 0); + create.create.bindingBits = + output->indexForByteArray(obj->bindingBitmask); + } else { + create.create.bindingBits = -1; + } + output->bytecode << create; + } - output->bytecode << create; // Setup the synthesized meta object if necessary if (!obj->metadata.isEmpty()) { @@ -1148,23 +1176,23 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, Property *idProp = 0; if (obj->properties.count() > 1 || (obj->properties.count() == 1 && obj->properties.begin().key() != "id")) - COMPILE_EXCEPTION(*obj->properties.begin(), QCoreApplication::translate("QDeclarativeCompiler","Component elements may not contain properties other than id")); + COMPILE_EXCEPTION(*obj->properties.begin(), tr("Component elements may not contain properties other than id")); if (!obj->scriptBlockObjects.isEmpty()) - COMPILE_EXCEPTION(obj->scriptBlockObjects.first(), QCoreApplication::translate("QDeclarativeCompiler","Component elements may not contain script blocks")); + COMPILE_EXCEPTION(obj->scriptBlockObjects.first(), tr("Component elements may not contain script blocks")); if (obj->properties.count()) idProp = *obj->properties.begin(); if (idProp) { if (idProp->value || idProp->values.count() > 1 || idProp->values.at(0)->object) - COMPILE_EXCEPTION(idProp, QCoreApplication::translate("QDeclarativeCompiler","Invalid component id specification")); + COMPILE_EXCEPTION(idProp, tr("Invalid component id specification")); COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive())); QString idVal = idProp->values.first()->primitive(); if (compileState.ids.contains(idVal)) - COMPILE_EXCEPTION(idProp, QCoreApplication::translate("QDeclarativeCompiler","id is not unique")); + COMPILE_EXCEPTION(idProp, tr("id is not unique")); obj->id = idVal; addId(idVal, obj); @@ -1174,14 +1202,14 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, if (obj->defaultProperty && (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 || (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object))) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Invalid component body specification")); + COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); Object *root = 0; if (obj->defaultProperty && obj->defaultProperty->values.count()) root = obj->defaultProperty->values.first()->object; if (!root) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Cannot create empty component specification")); + COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification")); // Build the component tree COMPILE_CHECK(buildComponentFromRoot(root, ctxt)); @@ -1200,11 +1228,11 @@ bool QDeclarativeCompiler::buildScript(QDeclarativeParser::Object *obj, QDeclara Property *source = *script->properties.begin(); if (script->defaultProperty) - COMPILE_EXCEPTION(source, QCoreApplication::translate("QDeclarativeCompiler","Invalid Script block. Specify either the source property or inline script")); + COMPILE_EXCEPTION(source, tr("Invalid Script block. Specify either the source property or inline script")); if (source->value || source->values.count() != 1 || source->values.at(0)->object || !source->values.at(0)->value.isStringList()) - COMPILE_EXCEPTION(source, QCoreApplication::translate("QDeclarativeCompiler","Invalid Script source value")); + COMPILE_EXCEPTION(source, tr("Invalid Script source value")); QStringList sources = source->values.at(0)->value.asStringList(); @@ -1229,7 +1257,7 @@ bool QDeclarativeCompiler::buildScript(QDeclarativeParser::Object *obj, QDeclara } } else if (!script->properties.isEmpty()) { - COMPILE_EXCEPTION(*script->properties.begin(), QCoreApplication::translate("QDeclarativeCompiler","Properties cannot be set on Script block")); + COMPILE_EXCEPTION(*script->properties.begin(), tr("Properties cannot be set on Script block")); } else if (script->defaultProperty) { QString scriptCode; @@ -1243,7 +1271,7 @@ bool QDeclarativeCompiler::buildScript(QDeclarativeParser::Object *obj, QDeclara if (lineNumber == 1) lineNumber = v->location.start.line; if (v->object || !v->value.isString()) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid Script block")); + COMPILE_EXCEPTION(v, tr("Invalid Script block")); if (ii == 0) { currentLocation = v->location.start; @@ -1387,7 +1415,7 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl } else { if (prop->value || prop->values.count() != 1) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Incorrectly specified signal assignment")); + COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment")); prop->index = sigIdx; obj->addSignalProperty(prop); @@ -1400,7 +1428,7 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl QString script = prop->values.at(0)->value.asScript().trimmed(); if (script.isEmpty()) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Empty signal assignment")); + COMPILE_EXCEPTION(prop, tr("Empty signal assignment")); compileState.signalExpressions.insert(prop->values.at(0), ctxt); } @@ -1438,7 +1466,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, const BindingContext &ctxt) { if (prop->isEmpty()) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Empty property assignment")); + COMPILE_EXCEPTION(prop, tr("Empty property assignment")); const QMetaObject *metaObject = obj->metaObject(); Q_ASSERT(metaObject); @@ -1450,7 +1478,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, // Attached properties cannot be used on sub-objects. Sub-objects // always exist in a binding sub-context, which is what we test // for here. - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Attached properties cannot be used here")); + COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here")); } QDeclarativeType *type = 0; @@ -1465,11 +1493,11 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, ctxt)); return true; } else if (!type || !type->attachedPropertiesType()) { - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Non-existent attached object")); + COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); } if (!prop->value) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Invalid attached object assignment")); + COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); Q_ASSERT(type->attachedPropertiesFunction()); prop->index = type->index(); @@ -1522,9 +1550,9 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, } else if (prop->index == -1) { if (prop->isDefault) { - COMPILE_EXCEPTION(prop->values.first(), QCoreApplication::translate("QDeclarativeCompiler","Cannot assign to non-existent default property")); + COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existent default property")); } else { - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); } } else if (prop->value) { @@ -1555,12 +1583,12 @@ QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeEnginePrivate::Import const BindingContext &ctxt) { if (!nsProp->value) - COMPILE_EXCEPTION(nsProp, QCoreApplication::translate("QDeclarativeCompiler","Invalid use of namespace")); + COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace")); foreach (Property *prop, nsProp->value->properties) { if (!isAttachedPropertyName(prop->name)) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Not an attached property name")); + COMPILE_EXCEPTION(prop, tr("Not an attached property name")); // Setup attached property data @@ -1569,10 +1597,10 @@ QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeEnginePrivate::Import &type, 0, 0, 0); if (!type || !type->attachedPropertiesType()) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Non-existent attached object")); + COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); if (!prop->value) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Invalid attached object assignment")); + COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); Q_ASSERT(type->attachedPropertiesFunction()); prop->index = type->index(); @@ -1743,7 +1771,7 @@ bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop, if (prop->value || prop->values.count() > 1 || prop->values.at(0)->object) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Invalid use of id property")); + COMPILE_EXCEPTION(prop, tr("Invalid use of id property")); QDeclarativeParser::Value *idValue = prop->values.at(0); QString val = idValue->primitive(); @@ -1751,7 +1779,7 @@ bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop, COMPILE_CHECK(checkValidId(idValue, val)); if (compileState.ids.contains(val)) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","id is not unique")); + COMPILE_EXCEPTION(prop, tr("id is not unique")); prop->values.at(0)->type = Value::Id; @@ -1832,17 +1860,21 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr if (prop->values.count()) { if (prop->values.at(0)->location < prop->value->location) { - COMPILE_EXCEPTION(prop->value, QCoreApplication::translate("QDeclarativeCompiler", "Property has already been assigned a value")); + COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value")); } else { - COMPILE_EXCEPTION(prop->values.at(0), QCoreApplication::translate("QDeclarativeCompiler", "Property has already been assigned a value")); + COMPILE_EXCEPTION(prop->values.at(0), tr( "Property has already been assigned a value")); } } + if (!obj->metaObject()->property(prop->index).isWritable()) { + COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + } + COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type], prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); } else { - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Invalid grouped property access")); + COMPILE_EXCEPTION(prop, tr("Invalid grouped property access")); } } else { @@ -1850,10 +1882,10 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr prop->value->metatype = QDeclarativeEnginePrivate::get(engine)->metaObjectForType(prop->type); if (!prop->value->metatype) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Invalid grouped property access")); + COMPILE_EXCEPTION(prop, tr("Invalid grouped property access")); if (prop->values.count()) - COMPILE_EXCEPTION(prop->values.at(0), QCoreApplication::translate("QDeclarativeCompiler", "Cannot assign a value directly to a grouped property")); + COMPILE_EXCEPTION(prop->values.at(0), tr( "Cannot assign a value directly to a grouped property")); obj->addGroupedProperty(prop); @@ -1869,28 +1901,28 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, const BindingContext &ctxt) { if (obj->defaultProperty) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Invalid property use")); + COMPILE_EXCEPTION(obj, tr("Invalid property use")); obj->metatype = type->metaObject(); foreach (Property *prop, obj->properties) { int idx = type->metaObject()->indexOfProperty(prop->name.constData()); if (idx == -1) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(prop->name))); QMetaProperty p = type->metaObject()->property(idx); prop->index = idx; prop->type = p.userType(); prop->isValueTypeSubProperty = true; if (prop->value) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Property assignment expected")); + COMPILE_EXCEPTION(prop, tr("Property assignment expected")); if (prop->values.count() > 1) { - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Single property assignment expected")); + COMPILE_EXCEPTION(prop, tr("Single property assignment expected")); } else if (prop->values.count()) { Value *value = prop->values.at(0); if (value->object) { - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Unexpected object assignment")); + COMPILE_EXCEPTION(prop, tr("Unexpected object assignment")); } else if (value->value.isScript()) { // ### Check for writability BindingReference reference; @@ -1947,19 +1979,19 @@ bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop, // at runtime. if (!listTypeIsInterface) { if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Cannot assign object to list")); + COMPILE_EXCEPTION(v, tr("Cannot assign object to list")); } } } else if (v->value.isScript()) { if (assignedBinding) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Can only assign one binding to lists")); + COMPILE_EXCEPTION(v, tr("Can only assign one binding to lists")); assignedBinding = true; COMPILE_CHECK(buildBinding(v, prop, ctxt)); v->type = Value::PropertyBinding; } else { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Cannot assign primitives to lists")); + COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists")); } } @@ -1972,10 +2004,10 @@ bool QDeclarativeCompiler::buildScriptStringProperty(QDeclarativeParser::Propert const BindingContext &ctxt) { if (prop->values.count() > 1) - COMPILE_EXCEPTION(prop->values.at(1), QCoreApplication::translate("QDeclarativeCompiler", "Cannot assign multiple values to a script property")); + COMPILE_EXCEPTION(prop->values.at(1), tr( "Cannot assign multiple values to a script property")); if (prop->values.at(0)->object || !prop->values.at(0)->value.isScript()) - COMPILE_EXCEPTION(prop->values.at(0), QCoreApplication::translate("QDeclarativeCompiler", "Invalid property assignment: script expected")); + COMPILE_EXCEPTION(prop->values.at(0), tr( "Invalid property assignment: script expected")); obj->addScriptStringProperty(prop, ctxt.stack); @@ -2022,7 +2054,7 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro Q_ASSERT(v->object->type != -1); if (!obj->metaObject()->property(prop->index).isWritable()) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); if (QDeclarativeMetaType::isInterface(prop->type)) { @@ -2081,7 +2113,7 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro v->object = component; COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt)); } else { - COMPILE_EXCEPTION(v->object, QCoreApplication::translate("QDeclarativeCompiler","Cannot assign object to property")); + COMPILE_EXCEPTION(v->object, tr("Cannot assign object to property")); } } @@ -2104,7 +2136,7 @@ bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeParser::Propert Q_ASSERT(v->object->type != -1); if (!obj->metaObject()->property(prop->index).isWritable()) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); // Normally buildObject() will set this up, but we need the static @@ -2131,7 +2163,7 @@ bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeParser::Propert buildDynamicMeta(baseObj, ForceCreation); v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; } else { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","\"%1\" cannot operate on \"%2\"").arg(QString::fromUtf8(v->object->typeName)).arg(QString::fromUtf8(prop->name.constData()))); + COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(QString::fromUtf8(v->object->typeName)).arg(QString::fromUtf8(prop->name.constData()))); } return true; @@ -2179,7 +2211,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop return true; if (!prop.isWritable()) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); QString string = v->value.asString(); if (!string.at(0).isUpper()) @@ -2248,32 +2280,32 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) if (prop.isDefaultProperty) { if (seenDefaultProperty) - COMPILE_EXCEPTION(&prop, QCoreApplication::translate("QDeclarativeCompiler","Duplicate default property")); + COMPILE_EXCEPTION(&prop, tr("Duplicate default property")); seenDefaultProperty = true; } if (propNames.contains(prop.name)) - COMPILE_EXCEPTION(&prop, QCoreApplication::translate("QDeclarativeCompiler","Duplicate property name")); + COMPILE_EXCEPTION(&prop, tr("Duplicate property name")); if (QString::fromUtf8(prop.name).at(0).isUpper()) - COMPILE_EXCEPTION(&prop, QCoreApplication::translate("QDeclarativeCompiler","Property names cannot begin with an upper case letter")); + COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter")); propNames.insert(prop.name); } for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { QByteArray name = obj->dynamicSignals.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Duplicate signal name")); + COMPILE_EXCEPTION(obj, tr("Duplicate signal name")); if (QString::fromUtf8(name).at(0).isUpper()) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Signal names cannot begin with an upper case letter")); + COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter")); methodNames.insert(name); } for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { QByteArray name = obj->dynamicSlots.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Duplicate method name")); + COMPILE_EXCEPTION(obj, tr("Duplicate method name")); if (QString::fromUtf8(name).at(0).isUpper()) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Method names cannot begin with an upper case letter")); + COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter")); methodNames.insert(name); } @@ -2294,11 +2326,11 @@ bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeParser::Object } else { property = obj->getProperty(p.name); if (!property->values.isEmpty()) - COMPILE_EXCEPTION(property, QCoreApplication::translate("QDeclarativeCompiler","Property value set multiple times")); + COMPILE_EXCEPTION(property, tr("Property value set multiple times")); } if (property->value) - COMPILE_EXCEPTION(property, QCoreApplication::translate("QDeclarativeCompiler","Invalid property nesting")); + COMPILE_EXCEPTION(property, tr("Invalid property nesting")); for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) { Value *v = p.defaultValue->values.at(ii); @@ -2351,7 +2383,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn if (-1 != propIdx) { QMetaProperty prop = obj->metaObject()->property(propIdx); if (prop.isFinal()) - COMPILE_EXCEPTION(&p, QCoreApplication::translate("QDeclarativeCompiler","Cannot override FINAL property")); + COMPILE_EXCEPTION(&p, tr("Cannot override FINAL property")); } if (p.isDefaultProperty && @@ -2376,7 +2408,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine); if (!priv->resolveType(unit->imports, p.customType, &qmltype, &url, 0, 0, 0)) - COMPILE_EXCEPTION(&p, QCoreApplication::translate("QDeclarativeCompiler","Invalid property type")); + COMPILE_EXCEPTION(&p, tr("Invalid property type")); if (!qmltype) { QDeclarativeCompositeTypeData *tdata = priv->typeManager.get(url); @@ -2505,7 +2537,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn ((QDeclarativeVMEMetaData *)dynamicData.data())->methodCount++; QDeclarativeVMEMetaData::MethodData methodData = - { s.parameterNames.count(), 0, funcScript.length(), 0 }; + { s.parameterNames.count(), 0, funcScript.length(), s.location.start.line }; dynamicData.append((char *)&methodData, sizeof(methodData)); } @@ -2535,24 +2567,24 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QString &val) { if (val.isEmpty()) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "Invalid empty ID")); + COMPILE_EXCEPTION(v, tr( "Invalid empty ID")); if (val.at(0).isLetter() && !val.at(0).isLower()) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "IDs cannot start with an uppercase letter")); + COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter")); QChar u(QLatin1Char('_')); for (int ii = 0; ii < val.count(); ++ii) { if (ii == 0 && !val.at(ii).isLetter() && val.at(ii) != u) { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "IDs must start with a letter or underscore")); + COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore")); } else if (ii != 0 && !val.at(ii).isLetterOrNumber() && val.at(ii) != u) { - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "IDs must contain only letters, numbers, and underscores")); + COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores")); } } if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(val)) - COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "ID illegally masks global JavaScript property")); + COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property")); return true; } @@ -2583,24 +2615,24 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, const Object::DynamicProperty &prop) { if (!prop.defaultValue) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","No property alias location")); + COMPILE_EXCEPTION(obj, tr("No property alias location")); if (prop.defaultValue->values.count() != 1 || prop.defaultValue->values.at(0)->object || !prop.defaultValue->values.at(0)->value.isScript()) - COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QDeclarativeCompiler","Invalid alias location")); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); QDeclarativeJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST(); if (!node) - COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","No property alias location")); // ### Can this happen? + COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen? QStringList alias = astNodeToStringList(node); if (alias.count() != 1 && alias.count() != 2) - COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QDeclarativeCompiler","Invalid alias reference. An alias reference must be specified as <id> or <id>.<property>")); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id> or <id>.<property>")); if (!compileState.ids.contains(alias.at(0))) - COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QDeclarativeCompiler","Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0))); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0))); Object *idObject = compileState.ids[alias.at(0)]; @@ -2613,7 +2645,7 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); if (-1 == propIdx) - COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QDeclarativeCompiler","Invalid alias location")); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); writable = aliasProperty.isWritable(); @@ -2667,7 +2699,7 @@ bool QDeclarativeCompiler::buildBinding(QDeclarativeParser::Value *value, QMetaProperty mp = prop->parent->metaObject()->property(prop->index); if (!mp.isWritable() && !QDeclarativeMetaType::isList(prop->type)) - COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); BindingReference reference; reference.expression = value->value; @@ -2944,4 +2976,9 @@ QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeParser::Object return rv; } +QString QDeclarativeCompiler::tr(const char *str) +{ + return QCoreApplication::translate("QDeclarativeCompiler", str); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 11364bb..0e47774 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -281,6 +281,8 @@ private: void addId(const QString &, QDeclarativeParser::Object *); + QString tr(const char *); + void dumpStats(); struct BindingReference { diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp index 55723ea..05e8d22 100644 --- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp +++ b/src/declarative/qml/qdeclarativecompositetypemanager.cpp @@ -55,13 +55,6 @@ QT_BEGIN_NAMESPACE -#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0)) -inline uint qHash(const QUrl &uri) -{ - return qHash(uri.toEncoded(QUrl::FormattingOption(0x100))); -} -#endif - QDeclarativeCompositeTypeData::QDeclarativeCompositeTypeData() : status(Invalid), errorType(NoError), component(0), compiledComponent(0) { @@ -633,10 +626,12 @@ int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData // - type with unknown namespace (UnknownNamespace.SomeType {}) QDeclarativeError error; error.setUrl(unit->imports.baseUrl()); + QString userTypeName = QString::fromUtf8(typeName); + userTypeName.replace(QLatin1Char('/'),QLatin1Char('.')); if (typeNamespace) - error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QString::fromUtf8(typeName))); + error.setDescription(tr("Namespace %1 cannot be used as a type").arg(userTypeName)); else - error.setDescription(tr("%1 is not a type").arg(QString::fromUtf8(typeName))); + error.setDescription(tr("%1 is not a type").arg(userTypeName)); if (!parserRef->refObjects.isEmpty()) { QDeclarativeParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 55c2f7c..9307bcc 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -623,6 +623,7 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object if (iter == enginePriv->m_sharedScriptImports.end()) { QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); + scriptContext->pushScope(enginePriv->contextClass->newContext(0, 0)); scriptContext->pushScope(enginePriv->globalClass->globalObject()); QScriptValue scope = scriptEngine->newObject(); diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index 6c5a1f7..eee72b6 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -174,7 +174,7 @@ public: inline ContextGuard &operator=(QObject *obj) { QDeclarativeGuard<QObject>::operator=(obj); return *this; } virtual void objectDestroyed(QObject *) { - if (!QObjectPrivate::get(context->contextObject)->wasDeleted) bindings.notify(); + if (context->contextObject && !QObjectPrivate::get(context->contextObject)->wasDeleted) bindings.notify(); } QDeclarativeContextData *context; QDeclarativeNotifier bindings; diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp index 8566744..461fab5 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp +++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp @@ -79,7 +79,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { via QtScript. */ QDeclarativeContextScriptClass::QDeclarativeContextScriptClass(QDeclarativeEngine *bindEngine) -: QDeclarativeScriptClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), +: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1) { } @@ -223,7 +223,7 @@ QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindConte return 0; } -QDeclarativeContextScriptClass::ScriptValue +QDeclarativeContextScriptClass::Value QDeclarativeContextScriptClass::property(Object *object, const Identifier &name) { Q_UNUSED(object); @@ -295,7 +295,7 @@ void QDeclarativeContextScriptClass::setProperty(Object *object, const Identifie QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - ep->objectClass->setProperty(lastScopeObject, name, value, bindContext); + ep->objectClass->setProperty(lastScopeObject, name, value, context(), bindContext); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecontextscriptclass_p.h b/src/declarative/qml/qdeclarativecontextscriptclass_p.h index b89f0cd..1936d38 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass_p.h +++ b/src/declarative/qml/qdeclarativecontextscriptclass_p.h @@ -54,14 +54,14 @@ // #include "private/qdeclarativetypenamecache_p.h" -#include "private/qdeclarativescriptclass_p.h" +#include <private/qscriptdeclarativeclass_p.h> QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QDeclarativeContext; class QDeclarativeContextData; -class QDeclarativeContextScriptClass : public QDeclarativeScriptClass +class QDeclarativeContextScriptClass : public QScriptDeclarativeClass { public: QDeclarativeContextScriptClass(QDeclarativeEngine *); @@ -76,7 +76,7 @@ public: protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual ScriptValue property(Object *, const Identifier &); + virtual Value property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: diff --git a/src/declarative/qml/qdeclarativecustomparser.cpp b/src/declarative/qml/qdeclarativecustomparser.cpp index 8b6ee7c..1a97315 100644 --- a/src/declarative/qml/qdeclarativecustomparser.cpp +++ b/src/declarative/qml/qdeclarativecustomparser.cpp @@ -108,6 +108,9 @@ QDeclarativeCustomParserNodePrivate::fromObject(QDeclarativeParser::Object *root rootNode.d->properties << fromProperty(p); } + if (root->defaultProperty) + rootNode.d->properties << fromProperty(root->defaultProperty); + return rootNode; } diff --git a/src/declarative/qml/qdeclarativedeclarativedata_p.h b/src/declarative/qml/qdeclarativedeclarativedata_p.h index adfff19..5b12629 100644 --- a/src/declarative/qml/qdeclarativedeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedeclarativedata_p.h @@ -64,6 +64,10 @@ class QDeclarativeAbstractBinding; class QDeclarativeContext; class QDeclarativePropertyCache; class QDeclarativeContextData; +// This class is structured in such a way, that simply zero'ing it is the +// default state for elemental object allocations. This is crucial in the +// workings of the QDeclarativeInstruction::CreateSimpleObject instruction. +// Don't change anything here without first considering that case! class Q_AUTOTEST_EXPORT QDeclarativeDeclarativeData : public QDeclarativeData { public: @@ -71,10 +75,20 @@ public: : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), - attachedProperties(0), propertyCache(0), guards(0) {} + attachedProperties(0), scriptValue(0), propertyCache(0), guards(0) { + init(); + } - virtual void destroyed(QObject *); - virtual void parentChanged(QObject *, QObject *); + static inline void init() { + QDeclarativeData::destroyed = destroyed; + QDeclarativeData::parentChanged = parentChanged; + } + + static void destroyed(QDeclarativeData *, QObject *); + static void parentChanged(QDeclarativeData *, QObject *, QObject *); + + void destroyed(QObject *); + void parentChanged(QObject *, QObject *); void setImplicitDestructible() { if (!explicitIndestructibleSet) indestructible = false; @@ -109,7 +123,9 @@ public: QHash<int, QObject *> *attachedProperties; - QScriptValue scriptValue; + // ### Can we make this QScriptValuePrivate so we incur no additional allocation + // cost? + QScriptValue *scriptValue; QDeclarativePropertyCache *propertyCache; QDeclarativeGuard<QObject> *guards; diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 52a1f45..a3a43e6 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -61,7 +61,6 @@ #include "private/qdeclarativeglobal_p.h" #include "private/qdeclarativeworkerscript_p.h" #include "private/qdeclarativecomponent_p.h" -#include "private/qdeclarativescriptclass_p.h" #include "qdeclarativenetworkaccessmanagerfactory.h" #include "qdeclarativeimageprovider.h" #include "private/qdeclarativedirparser_p.h" @@ -183,11 +182,11 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) fileImportPath.append(canonicalPath); } } -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); if (!builtinPath.isEmpty()) fileImportPath += builtinPath; -#endif + + filePluginPath += QLatin1String("."); } @@ -226,6 +225,7 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr // XXX used to add Qt.Sound class. //types + qtObject.setProperty(QLatin1String("isQtObject"), newFunction(QDeclarativeEnginePrivate::isQtObject, 1)); qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4)); qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4)); qtObject.setProperty(QLatin1String("rect"), newFunction(QDeclarativeEnginePrivate::rect, 4)); @@ -346,6 +346,17 @@ Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer); typedef QMap<QString, QString> StringStringMap; Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri + +void QDeclarativeDeclarativeData::destroyed(QDeclarativeData *d, QObject *o) +{ + static_cast<QDeclarativeDeclarativeData *>(d)->destroyed(o); +} + +void QDeclarativeDeclarativeData::parentChanged(QDeclarativeData *d, QObject *o, QObject *p) +{ + static_cast<QDeclarativeDeclarativeData *>(d)->parentChanged(o, p); +} + void QDeclarativeEnginePrivate::init() { Q_Q(QDeclarativeEngine); @@ -353,6 +364,8 @@ void QDeclarativeEnginePrivate::init() qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString"); qRegisterMetaType<QScriptValue>("QScriptValue"); + QDeclarativeDeclarativeData::init(); + contextClass = new QDeclarativeContextScriptClass(q); objectClass = new QDeclarativeObjectScriptClass(q); valueTypeClass = new QDeclarativeValueTypeScriptClass(q); @@ -396,7 +409,7 @@ QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine \code QDeclarativeEngine engine; QDeclarativeComponent component(&engine); - component.setData("import Qt 4.6\nText { text: \"Hello world!\" }", QUrl()); + component.setData("import Qt 4.7\nText { text: \"Hello world!\" }", QUrl()); QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create()); //add item to view, etc @@ -848,15 +861,16 @@ void QDeclarativeDeclarativeData::destroyed(QObject *object) if (ownContext) context->destroy(); + if (scriptValue) + delete scriptValue; + if (ownMemory) delete this; - else - this->~QDeclarativeDeclarativeData(); } void QDeclarativeDeclarativeData::parentChanged(QObject *, QObject *parent) { - if (!parent && scriptValue.isValid()) scriptValue = QScriptValue(); + if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; } } bool QDeclarativeDeclarativeData::hasBindingBit(int bit) const @@ -1014,6 +1028,14 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar); } +QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine) +{ + if (ctxt->argumentCount() == 0) + return QScriptValue(engine, false); + + return QScriptValue(engine, 0 != ctxt->argument(0).toQObject()); +} + QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 3) @@ -1310,7 +1332,6 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); } - QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) { if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) { @@ -1321,6 +1342,14 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } else { return scriptEngine.nullValue(); } + } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) { + const QList<QObject *> &list = *(QList<QObject *>*)val.constData(); + QScriptValue rv = scriptEngine.newArray(list.count()); + for (int ii = 0; ii < list.count(); ++ii) { + QObject *object = list.at(ii); + rv.setProperty(ii, objectClass->newQObject(object)); + } + return rv; } bool objOk; @@ -1332,35 +1361,29 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } } -QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val) +QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint) { QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); if (dc == objectClass) return QVariant::fromValue(objectClass->toQObject(val)); + else if (dc == valueTypeClass) + return valueTypeClass->toVariant(val); else if (dc == contextClass) return QVariant(); - QScriptDeclarativeClass *sc = QScriptDeclarativeClass::scriptClass(val); - if (!sc) { - return val.toVariant(); - } else if (sc == valueTypeClass) { - return valueTypeClass->toVariant(val); - } else { - return QVariant(); + // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted + if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) { + QList<QObject *> list; + int length = val.property(QLatin1String("length")).toInt32(); + for (int ii = 0; ii < length; ++ii) { + QScriptValue arrayItem = val.property(ii); + QObject *d = arrayItem.toQObject(); + list << d; + } + return QVariant::fromValue(list); } -} - -QDeclarativeScriptClass::QDeclarativeScriptClass(QScriptEngine *engine) -: QScriptDeclarativeClass(engine) -{ -} - -QVariant QDeclarativeScriptClass::toVariant(QDeclarativeEngine *engine, const QScriptValue &val) -{ - QDeclarativeEnginePrivate *ep = - static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine)); - return ep->scriptValueToVariant(val); + return val.toVariant(); } // XXX this beyonds in QUrl::toLocalFile() @@ -1483,19 +1506,13 @@ public: foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { - QDir pluginDir = dir.absoluteFilePath(plugin.path); - - // hack for resources, should probably go away - if (absoluteFilePath.startsWith(QLatin1Char(':'))) - pluginDir = QDir(QCoreApplication::applicationDirPath()); - QString resolvedFilePath = QDeclarativeEnginePrivate::get(engine) - ->resolvePlugin(pluginDir, + ->resolvePlugin(dir, plugin.path, plugin.name); if (!resolvedFilePath.isEmpty()) { - engine->importExtension(resolvedFilePath, uri); + engine->importPlugin(resolvedFilePath, uri); } } } @@ -1619,6 +1636,18 @@ public: url.chop(1); } + if (vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { + QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin(); + for (; it != qmldircomponents.end(); ++it) { + if (it->majorVersion > vmaj || (it->majorVersion == vmaj && it->minorVersion >= vmin)) + break; + } + if (it == qmldircomponents.end()) { + *errorString = QDeclarativeEngine::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); + return false; + } + } + s->uris.prepend(uri); s->urls.prepend(url); s->majversions.prepend(vmaj); @@ -1778,8 +1807,8 @@ QUrl QDeclarativeEnginePrivate::Imports::baseUrl() const } /*! - Adds \a path as a directory where installed QML components are - defined in a URL-based directory structure. + Adds \a path as a directory where the engine searches for + installed modules in a URL-based directory structure. The newly added \a path will be first in the importPathList(). @@ -1802,7 +1831,7 @@ void QDeclarativeEngine::addImportPath(const QString& path) /*! Returns the list of directories where the engine searches for - installed modules. + installed modules in a URL-based directory structure. For example, if \c /opt/MyApp/lib/imports is in the path, then QML that imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look @@ -1823,7 +1852,7 @@ QStringList QDeclarativeEngine::importPathList() const /*! Sets the list of directories where the engine searches for - installed modules. + installed modules in a URL-based directory structure. By default, the list contains the paths specified in the \c QML_IMPORT_PATH environment variable, then the builtin \c ImportsPath from QLibraryInfo. @@ -1836,15 +1865,73 @@ void QDeclarativeEngine::setImportPathList(const QStringList &paths) d->fileImportPath = paths; } + /*! - Imports the extension named \a fileName from the \a uri provided. - Returns true if the extension was successfully imported. + Adds \a path as a directory where the engine searches for + native plugins for imported modules (referenced in the \c qmldir file). + + By default, the list contains only \c ., i.e. the engine searches + in the directory of the \c qmldir file itself. + + The newly added \a path will be first in the pluginPathList(). + + \sa setPluginPathList() */ -bool QDeclarativeEngine::importExtension(const QString &fileName, const QString &uri) +void QDeclarativeEngine::addPluginPath(const QString& path) { if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::importExtension" << uri << "from" << fileName; - QFileInfo fileInfo(fileName); + qDebug() << "QDeclarativeEngine::addPluginPath" << path; + Q_D(QDeclarativeEngine); + QUrl url = QUrl(path); + if (url.isRelative() || url.scheme() == QString::fromLocal8Bit("file")) { + QDir dir = QDir(path); + d->filePluginPath.prepend(dir.canonicalPath()); + } else { + d->filePluginPath.prepend(path); + } +} + + +/*! + Returns the list of directories where the engine searches for + native plugins for imported modules (referenced in the \c qmldir file). + + By default, the list contains only \c ., i.e. the engine searches + in the directory of the \c qmldir file itself. + + \sa addPluginPath() setPluginPathList() +*/ +QStringList QDeclarativeEngine::pluginPathList() const +{ + Q_D(const QDeclarativeEngine); + return d->filePluginPath; +} + +/*! + Sets the list of directories where the engine searches for + native plugins for imported modules (referenced in the \c qmldir file). + + By default, the list contains only \c ., i.e. the engine searches + in the directory of the \c qmldir file itself. + + \sa pluginPathList() addPluginPath() + */ +void QDeclarativeEngine::setPluginPathList(const QStringList &paths) +{ + Q_D(QDeclarativeEngine); + d->filePluginPath = paths; +} + + +/*! + Imports the plugin named \a filePath with the \a uri provided. + Returns true if the plugin was successfully imported; otherwise returns false. +*/ +bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri) +{ + if (qmlImportTrace()) + qDebug() << "QDeclarativeEngine::importPlugin" << uri << "from" << filePath; + QFileInfo fileInfo(filePath); const QString absoluteFilePath = fileInfo.absoluteFilePath(); QDeclarativeEnginePrivate *d = QDeclarativeEnginePrivate::get(this); @@ -1917,27 +2004,53 @@ QString QDeclarativeEngine::offlineStoragePath() const /*! \internal - Returns the result of the merge of \a baseName with \a dir, \a suffixes, and \a prefix. + Returns the result of the merge of \a baseName with \a path, \a suffixes, and \a prefix. The \a prefix must contain the dot. + + \a qmldirPath is the location of the qmldir file. */ -QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName, +QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName, const QStringList &suffixes, const QString &prefix) { - foreach (const QString &suffix, suffixes) { - QString pluginFileName = prefix; + QStringList searchPaths = filePluginPath; + bool qmldirPluginPathIsRelative = QDir::isRelativePath(qmldirPluginPath); + if (!qmldirPluginPathIsRelative) + searchPaths.prepend(qmldirPluginPath); + + foreach (const QString &pluginPath, searchPaths) { + + QString resolvedPath; + + if (pluginPath == QLatin1String(".")) { + if (qmldirPluginPathIsRelative) + resolvedPath = qmldirPath.absoluteFilePath(qmldirPluginPath); + else + resolvedPath = qmldirPath.absolutePath(); + } else { + resolvedPath = pluginPath; + } + + // hack for resources, should probably go away + if (resolvedPath.startsWith(QLatin1Char(':'))) + resolvedPath = QCoreApplication::applicationDirPath(); - pluginFileName += baseName; - pluginFileName += suffix; + QDir dir(resolvedPath); + foreach (const QString &suffix, suffixes) { + QString pluginFileName = prefix; - QFileInfo fileInfo(dir, pluginFileName); + pluginFileName += baseName; + pluginFileName += suffix; - if (fileInfo.exists()) - return fileInfo.absoluteFilePath(); + QFileInfo fileInfo(dir, pluginFileName); + + if (fileInfo.exists()) + return fileInfo.absoluteFilePath(); + } } if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::resolvePlugin: Could not resolve plugin" << baseName << "in" << dir.absolutePath(); + qDebug() << "QDeclarativeEngine::resolvePlugin: Could not resolve plugin" << baseName << "in" << qmldirPath.absolutePath(); return QString(); } @@ -1958,17 +2071,17 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString Version number on unix are ignored. */ -QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName) +QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName) { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - return resolvePlugin(dir, baseName, + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, QStringList() # ifdef QT_DEBUG << QLatin1String("d.dll") // try a qmake-style debug build first # endif << QLatin1String(".dll")); #elif defined(Q_OS_SYMBIAN) - return resolvePlugin(dir, baseName, + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, QStringList() << QLatin1String(".dll") << QLatin1String(".qtplugin")); @@ -1976,7 +2089,7 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString # if defined(Q_OS_DARWIN) - return resolvePlugin(dir, baseName, + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, QStringList() # ifdef QT_DEBUG << QLatin1String("_debug.dylib") // try a qmake-style debug build first @@ -2010,7 +2123,7 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString // Examples of valid library names: // libfoo.so - return resolvePlugin(dir, baseName, validSuffixList, QLatin1String("lib")); + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib")); # endif #endif diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h index b861c1b..fcaddcf 100644 --- a/src/declarative/qml/qdeclarativeengine.h +++ b/src/declarative/qml/qdeclarativeengine.h @@ -81,7 +81,11 @@ public: void setImportPathList(const QStringList &paths); void addImportPath(const QString& dir); - bool importExtension(const QString &fileName, const QString &uri); + QStringList pluginPathList() const; + void setPluginPathList(const QStringList &paths); + void addPluginPath(const QString& dir); + + bool importPlugin(const QString &filePath, const QString &uri); void setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *); QDeclarativeNetworkAccessManagerFactory *networkAccessManagerFactory() const; diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 45089d0..7766ad6 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -231,6 +231,7 @@ public: QDeclarativeCompositeTypeManager typeManager; QStringList fileImportPath; + QStringList filePluginPath; QString offlineStoragePath; mutable quint32 uniqueId; @@ -274,10 +275,10 @@ public: QSet<QString> initializedPlugins; - QString resolvePlugin(const QDir &dir, const QString &baseName, + QString resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName, const QStringList &suffixes, const QString &prefix = QString()); - QString resolvePlugin(const QDir &dir, const QString &baseName); + QString resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName); bool addToImport(Imports*, const QDeclarativeDirComponents &qmldircomponentsnetwork, @@ -308,7 +309,7 @@ public: QHash<QString, QScriptValue> m_sharedScriptImports; QScriptValue scriptValueFromVariant(const QVariant &); - QVariant scriptValueToVariant(const QScriptValue &); + QVariant scriptValueToVariant(const QScriptValue &, int hint = QVariant::Invalid); void sendQuit (); @@ -316,6 +317,7 @@ public: static QScriptValue createComponent(QScriptContext*, QScriptEngine*); static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*); + static QScriptValue isQtObject(QScriptContext*, QScriptEngine*); static QScriptValue vector(QScriptContext*, QScriptEngine*); static QScriptValue rgba(QScriptContext*, QScriptEngine*); static QScriptValue hsla(QScriptContext*, QScriptEngine*); diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index a250f21..2a3e557 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -175,7 +175,8 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex } QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object, - const QString &program, QScriptValue *contextObject) + const QString &program, const QString &fileName, + int lineNumber, QScriptValue *contextObject) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); @@ -186,7 +187,7 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex scriptContext->pushScope(ep->contextClass->newContext(context, object)); } scriptContext->pushScope(ep->globalClass->globalObject()); - QScriptValue rv = ep->scriptEngine.evaluate(program); + QScriptValue rv = ep->scriptEngine.evaluate(program, fileName, lineNumber); ep->scriptEngine.popContext(); return rv; } @@ -351,7 +352,7 @@ void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine } } -QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined) +QScriptValue QDeclarativeExpressionPrivate::eval(QObject *secondaryScope, bool *isUndefined) { QDeclarativeExpressionData *data = this->data; QDeclarativeEngine *engine = data->context()->engine; @@ -376,7 +377,7 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo const QString code = rewriteBinding(data->expression, &ok); if (!ok) { scriptEngine->popContext(); - return QVariant(); + return QScriptValue(); } data->expressionFunction = scriptEngine->evaluate(code, data->url, data->line); } @@ -413,54 +414,20 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo if (scriptEngine->hasUncaughtException()) { exceptionToError(scriptEngine, data->error); scriptEngine->clearExceptions(); - return QVariant(); + return QScriptValue(); } else { data->error = QDeclarativeError(); + return svalue; } - - QVariant rv; - - if (svalue.isArray()) { - int length = svalue.property(QLatin1String("length")).toInt32(); - if (length && svalue.property(0).isObject()) { - QList<QObject *> list; - for (int ii = 0; ii < length; ++ii) { - QScriptValue arrayItem = svalue.property(ii); - QObject *d = arrayItem.toQObject(); - list << d; - } - rv = QVariant::fromValue(list); - } - } else if (svalue.isObject() && - ep->objectClass->scriptClass(svalue) == ep->objectClass) { - QObject *o = svalue.toQObject(); - int type = QMetaType::QObjectStar; - // If the object is null, we extract the predicted type. While this isn't - // 100% reliable, in many cases it gives us better error messages if we - // assign this null-object to an incompatible property - if (!o) type = ep->objectClass->objectType(svalue); - - return QVariant(type, &o); - } - - if (rv.isNull()) - rv = svalue.toVariant(); - - return rv; } -QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined) +QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined) { Q_Q(QDeclarativeExpression); - - QVariant rv; - if (!q->engine()) { - qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context"); - return rv; - } + Q_ASSERT(q->engine()); if (data->expression.isEmpty()) - return rv; + return QScriptValue(); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine()); @@ -476,7 +443,7 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU QDeclarativeExpressionData *localData = data; localData->addref(); - rv = evalQtScript(secondaryScope, isUndefined); + QScriptValue value = eval(secondaryScope, isUndefined); ep->currentExpression = lastCurrentExpression; ep->captureProperties = lastCaptureProperties; @@ -494,7 +461,21 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU lastCapturedProperties.copyAndClear(ep->capturedProperties); - return rv; + return value; +} + +QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined) +{ + Q_Q(QDeclarativeExpression); + + if (!q->engine()) { + qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context"); + return QVariant(); + } + + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine()); + + return ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId<QList<QObject*> >()); } /*! diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h index 9a90fb6..d39aa2c 100644 --- a/src/declarative/qml/qdeclarativeexpression_p.h +++ b/src/declarative/qml/qdeclarativeexpression_p.h @@ -150,7 +150,9 @@ public: QDeclarativeExpressionData *data; QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0); - QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0); + QScriptValue scriptValue(QObject *secondaryScope = 0, bool *isUndefined = 0); + + QScriptValue eval(QObject *secondaryScope, bool *isUndefined = 0); void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties); void clearGuards(); @@ -165,8 +167,10 @@ public: virtual void emitValueChanged(); static void exceptionToError(QScriptEngine *, QDeclarativeError &); - static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QString &, QScriptValue * = 0); - static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &, QScriptValue * = 0); + static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QString &, const QString &, + int, QScriptValue *); + static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &, + QScriptValue *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 3cf4d2b..d88d06a 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -60,6 +60,8 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) break; case QDeclarativeInstruction::CreateObject: qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className; + case QDeclarativeInstruction::CreateSimpleObject: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize; break; case QDeclarativeInstruction::SetId: qWarning().nospace() << idx << "\t\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value); @@ -128,6 +130,12 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) case QDeclarativeInstruction::StoreVariant: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); break; + case QDeclarativeInstruction::StoreVariantInteger: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value; + break; + case QDeclarativeInstruction::StoreVariantDouble: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; + break; case QDeclarativeInstruction::StoreObject: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex; break; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index 877179d..e8287c0 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -74,6 +74,7 @@ public: // top of the stack. Init, /* init */ CreateObject, /* create */ + CreateSimpleObject, /* createSimple */ SetId, /* setId */ SetDefault, CreateComponent, /* createComponent */ @@ -113,6 +114,8 @@ public: StoreRectF, /* storeRect */ StoreVector3D, /* storeVector3D */ StoreVariant, /* storeString */ + StoreVariantInteger, /* storeInteger */ + StoreVariantDouble, /* storeDouble */ StoreObject, /* storeObject */ StoreVariantObject, /* storeObject */ StoreInterface, /* storeObject */ @@ -175,6 +178,11 @@ public: int bindingBits; ushort column; }; + struct CreateSimpleInstruction { + void (*create)(void *); + int typeSize; + ushort column; + }; struct StoreMetaInstruction { int data; int aliasData; @@ -305,6 +313,7 @@ public: union { InitInstruction init; CreateInstruction create; + CreateSimpleInstruction createSimple; StoreMetaInstruction storeMeta; SetIdInstruction setId; AssignValueSourceInstruction assignValueSource; diff --git a/src/declarative/qml/qdeclarativelistscriptclass.cpp b/src/declarative/qml/qdeclarativelistscriptclass.cpp index 3958dd5..d27427e 100644 --- a/src/declarative/qml/qdeclarativelistscriptclass.cpp +++ b/src/declarative/qml/qdeclarativelistscriptclass.cpp @@ -54,7 +54,7 @@ struct ListData : public QScriptDeclarativeClass::Object { }; QDeclarativeListScriptClass::QDeclarativeListScriptClass(QDeclarativeEngine *e) -: QDeclarativeScriptClass(QDeclarativeEnginePrivate::getScriptEngine(e)), engine(e) +: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(e)), engine(e) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); Q_UNUSED(scriptEngine); @@ -114,7 +114,7 @@ QDeclarativeListScriptClass::queryProperty(Object *object, const Identifier &nam } } -QDeclarativeListScriptClass::ScriptValue QDeclarativeListScriptClass::property(Object *obj, const Identifier &name) +QDeclarativeListScriptClass::Value QDeclarativeListScriptClass::property(Object *obj, const Identifier &name) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); diff --git a/src/declarative/qml/qdeclarativelistscriptclass_p.h b/src/declarative/qml/qdeclarativelistscriptclass_p.h index 68c680d..89984a1 100644 --- a/src/declarative/qml/qdeclarativelistscriptclass_p.h +++ b/src/declarative/qml/qdeclarativelistscriptclass_p.h @@ -53,13 +53,13 @@ // We mean it. // -#include <private/qdeclarativescriptclass_p.h> +#include <private/qscriptdeclarativeclass_p.h> #include "qdeclarativelist.h" QT_BEGIN_NAMESPACE class QDeclarativeEngine; -class QDeclarativeListScriptClass : public QDeclarativeScriptClass +class QDeclarativeListScriptClass : public QScriptDeclarativeClass { public: QDeclarativeListScriptClass(QDeclarativeEngine *); @@ -71,7 +71,7 @@ public: protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual ScriptValue property(Object *, const Identifier &); + virtual Value property(Object *, const Identifier &); virtual QVariant toVariant(Object *, bool *ok); private: diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index af21765..7b71608 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -313,11 +313,28 @@ QDeclarativeCustomParser *QDeclarativeType::customParser() const return d->m_customParser; } +QDeclarativeType::CreateFunc QDeclarativeType::createFunction() const +{ + return d->m_newFunc; +} + +int QDeclarativeType::createSize() const +{ + return d->m_allocationSize; +} + bool QDeclarativeType::isCreatable() const { return d->m_newFunc != 0; } +bool QDeclarativeType::isExtendedType() const +{ + d->init(); + + return !d->m_metaObjects.isEmpty(); +} + bool QDeclarativeType::isInterface() const { return d->m_isInterface; diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index b3ec5e3..70b7c90 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -115,9 +115,14 @@ public: QObject *create() const; void create(QObject **, void **, size_t) const; + typedef void (*CreateFunc)(void *); + CreateFunc createFunction() const; + int createSize() const; + QDeclarativeCustomParser *customParser() const; bool isCreatable() const; + bool isExtendedType() const; bool isInterface() const; int typeId() const; diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index d3ee67b..e1e33ab 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -52,6 +52,7 @@ #include <QtCore/qtimer.h> #include <QtCore/qvarlengtharray.h> +#include <QtScript/qscriptcontextinfo.h> Q_DECLARE_METATYPE(QScriptValue); @@ -78,11 +79,8 @@ struct ObjectData : public QScriptDeclarativeClass::Object { QtScript for QML. */ QDeclarativeObjectScriptClass::QDeclarativeObjectScriptClass(QDeclarativeEngine *bindEngine) -: QDeclarativeScriptClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), -#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) - methods(bindEngine), -#endif - lastData(0), engine(bindEngine) +: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), + methods(bindEngine), lastData(0), engine(bindEngine) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -103,17 +101,20 @@ QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type if (!object) return newObject(scriptEngine, this, new ObjectData(object, type)); + if (QObjectPrivate::get(object)->wasDeleted) + return scriptEngine->undefinedValue(); + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, true); if (!ddata) { return scriptEngine->undefinedValue(); } else if (!ddata->indestructible && !object->parent()) { return newObject(scriptEngine, this, new ObjectData(object, type)); - } else if (!ddata->scriptValue.isValid()) { - ddata->scriptValue = newObject(scriptEngine, this, new ObjectData(object, type)); - return ddata->scriptValue; - } else if (ddata->scriptValue.engine() == QDeclarativeEnginePrivate::getScriptEngine(engine)) { - return ddata->scriptValue; + } else if (!ddata->scriptValue) { + ddata->scriptValue = new QScriptValue(newObject(scriptEngine, this, new ObjectData(object, type))); + return *ddata->scriptValue; + } else if (ddata->scriptValue->engine() == QDeclarativeEnginePrivate::getScriptEngine(engine)) { + return *ddata->scriptValue; } else { return newObject(scriptEngine, this, new ObjectData(object, type)); } @@ -191,13 +192,13 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam return 0; } -QDeclarativeObjectScriptClass::ScriptValue +QDeclarativeObjectScriptClass::Value QDeclarativeObjectScriptClass::property(Object *object, const Identifier &name) { return property(toQObject(object), name); } -QDeclarativeObjectScriptClass::ScriptValue +QDeclarativeObjectScriptClass::Value QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -225,15 +226,10 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name) if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) { return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex)); } else { -#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) // Uncomment to use QtScript method call logic // QScriptValue sobj = scriptEngine->newQObject(obj); // return Value(scriptEngine, sobj.property(toString(name))); return Value(scriptEngine, methods.newMethod(obj, lastData)); -#else - QScriptValue sobj = scriptEngine->newQObject(obj); - return Value(scriptEngine, sobj.property(toString(name))); -#endif } } else { if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) { @@ -298,7 +294,6 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name) QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); return Value(scriptEngine, enginePriv->scriptValueFromVariant(var)); } - } } @@ -306,40 +301,41 @@ void QDeclarativeObjectScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { - return setProperty(toQObject(object), name, value); + return setProperty(toQObject(object), name, value, context()); } void QDeclarativeObjectScriptClass::setProperty(QObject *obj, - const Identifier &name, - const QScriptValue &value, - QDeclarativeContextData *evalContext) + const Identifier &name, + const QScriptValue &value, + QScriptContext *context, + QDeclarativeContextData *evalContext) { Q_UNUSED(name); Q_ASSERT(obj); Q_ASSERT(lastData); + Q_ASSERT(context); if (!lastData->isValid()) { QString error = QLatin1String("Cannot assign to non-existent property \"") + toString(name) + QLatin1Char('\"'); - if (context()) - context()->throwError(error); + context->throwError(error); return; } - if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable)) { + if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) && + !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) { QString error = QLatin1String("Cannot assign to read-only property \"") + toString(name) + QLatin1Char('\"'); - if (context()) - context()->throwError(error); + context->throwError(error); return; } QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); - if (!evalContext && context()) { + if (!evalContext) { // Global object, QScriptContext activation object, QDeclarativeContext object - QScriptValue scopeNode = scopeChainValue(context(), -3); + QScriptValue scopeNode = scopeChainValue(context, -3); if (scopeNode.isValid()) { Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass); @@ -355,10 +351,30 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) { void *a[] = { 0 }; QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a); + } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) { + QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext); + } else if (value.isUndefined()) { + QString error = QLatin1String("Cannot assign [undefined] to ") + + QLatin1String(QMetaType::typeName(lastData->propType)); + context->throwError(error); } else { - // ### Can well known types be optimized? - QVariant v = QDeclarativeScriptClass::toVariant(engine, value); - QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext); + QVariant v; + if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) + v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >()); + else + v = enginePriv->scriptValueToVariant(value, lastData->propType); + + if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) { + const char *valueType = 0; + if (v.userType() == QVariant::Invalid) valueType = "null"; + else valueType = QMetaType::typeName(v.userType()); + + QString error = QLatin1String("Cannot assign ") + + QLatin1String(valueType) + + QLatin1String(" to ") + + QLatin1String(QMetaType::typeName(lastData->propType)); + context->throwError(error); + } } } @@ -459,8 +475,6 @@ bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2) return d1 == d2 || d1->object == d2->object; } -#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) - struct MethodData : public QScriptDeclarativeClass::Object { MethodData(QObject *o, const QDeclarativePropertyCache::Data &d) : object(o), data(d) {} @@ -557,7 +571,7 @@ QDeclarativeObjectMethodScriptClass::queryProperty(Object *, const Identifier &n } -QDeclarativeObjectScriptClass::ScriptValue +QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::property(Object *, const Identifier &name) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -687,16 +701,26 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, *((QObject **)&data) = value.toQObject(); type = callType; } else if (callType == qMetaTypeId<QVariant>()) { - new (&data) QVariant(QDeclarativeScriptClass::toVariant(engine, value)); + new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value)); type = callType; } else if (callType == qMetaTypeId<QList<QObject*> >()) { - new (&data) QList<QObject *>(); // We don't support passing in QList<QObject*> + QList<QObject *> *list = new (&data) QList<QObject *>(); + if (value.isArray()) { + int length = value.property(QLatin1String("length")).toInt32(); + for (int ii = 0; ii < length; ++ii) { + QScriptValue arrayItem = value.property(ii); + QObject *d = arrayItem.toQObject(); + list->append(d); + } + } else if (QObject *d = value.toQObject()) { + list->append(d); + } type = callType; } else { new (&data) QVariant(); type = -1; - QVariant v = QDeclarativeScriptClass::toVariant(engine, value); + QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value); if (v.userType() == callType) { *((QVariant *)&data) = v; } else if (v.canConvert((QVariant::Type)callType)) { @@ -803,7 +827,5 @@ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass:: return Value(); } -#endif - QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h index 8941ae0..4b27e53 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h +++ b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h @@ -56,7 +56,7 @@ #include "private/qdeclarativepropertycache_p.h" #include "private/qdeclarativetypenamecache_p.h" -#include <private/qdeclarativescriptclass_p.h> +#include <private/qscriptdeclarativeclass_p.h> #include <QtScript/qscriptengine.h> QT_BEGIN_NAMESPACE @@ -66,7 +66,6 @@ class QScriptContext; class QScriptEngine; class QDeclarativeContextData; -#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) class Q_AUTOTEST_EXPORT QDeclarativeObjectMethodScriptClass : public QScriptDeclarativeClass { public: @@ -91,9 +90,8 @@ private: QDeclarativeEngine *engine; }; -#endif -class Q_AUTOTEST_EXPORT QDeclarativeObjectScriptClass : public QDeclarativeScriptClass +class Q_AUTOTEST_EXPORT QDeclarativeObjectScriptClass : public QScriptDeclarativeClass { public: QDeclarativeObjectScriptClass(QDeclarativeEngine *); @@ -115,10 +113,10 @@ public: QDeclarativeContextData *evalContext, QueryHints hints = 0); - ScriptValue property(QObject *, const Identifier &); + Value property(QObject *, const Identifier &); void setProperty(QObject *, const Identifier &name, const QScriptValue &, - QDeclarativeContextData *evalContext = 0); + QScriptContext *context, QDeclarativeContextData *evalContext = 0); virtual QStringList propertyNames(Object *); virtual bool compare(Object *, Object *); @@ -126,16 +124,14 @@ protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual ScriptValue property(Object *, const Identifier &); + virtual Value property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); virtual bool isQObject() const; virtual QObject *toQObject(Object *, bool *ok = 0); private: -#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) friend class QDeclarativeObjectMethodScriptClass; QDeclarativeObjectMethodScriptClass methods; -#endif QDeclarativeTypeNameCache::Data *lastTNData; QDeclarativePropertyCache::Data *lastData; diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index 69186b6..d1f209a 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -200,7 +200,7 @@ QDeclarativeParser::Object::DynamicSlot::DynamicSlot() } QDeclarativeParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o) -: name(o.name), body(o.body), parameterNames(o.parameterNames) +: name(o.name), body(o.body), parameterNames(o.parameterNames), location(o.location) { } diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 57df04c..00fc65b 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -227,6 +227,7 @@ namespace QDeclarativeParser QByteArray name; QString body; QList<QByteArray> parameterNames; + LocationSpan location; }; // The list of dynamic properties diff --git a/src/declarative/qml/qdeclarativescriptclass_p.h b/src/declarative/qml/qdeclarativescriptclass_p.h deleted file mode 100644 index d8733db..0000000 --- a/src/declarative/qml/qdeclarativescriptclass_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVESCRIPTCLASS_P_H -#define QDECLARATIVESCRIPTCLASS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtScript/qscriptclass.h> -#include <private/qscriptdeclarativeclass_p.h> - -QT_BEGIN_NAMESPACE - -class QDeclarativeEngine; -class QDeclarativeScriptClass : public QScriptDeclarativeClass -{ -public: - QDeclarativeScriptClass(QScriptEngine *); - - static QVariant toVariant(QDeclarativeEngine *, const QScriptValue &); - -#if (QT_VERSION <= QT_VERSION_CHECK(4, 6, 2)) && !defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE) - struct Value : public QScriptValue { - Value() : QScriptValue() {} - Value(QScriptEngine *engine, int v) : QScriptValue(engine, v) {} - Value(QScriptEngine *engine, uint v) : QScriptValue(engine, v) {} - Value(QScriptEngine *engine, bool v) : QScriptValue(engine, v) {} - Value(QScriptEngine *engine, double v) : QScriptValue(engine, v) {} - Value(QScriptEngine *engine, float v) : QScriptValue(engine, v) {} - Value(QScriptEngine *engine, const QString &v) : QScriptValue(engine, v) {} - Value(QScriptEngine *, const QScriptValue &v) : QScriptValue(v) {} - }; - - typedef QScriptValue ScriptValue; -#else - typedef Value ScriptValue; -#endif -}; - -QT_END_NAMESPACE - -#endif // QDECLARATIVESCRIPTCLASS_P_H diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index cba5bb9..ac49332 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -488,8 +488,8 @@ bool ProcessAST::visit(AST::UiImport *node) } else if (import.type == QDeclarativeScriptParser::Import::Script) { QDeclarativeError error; error.setDescription(QCoreApplication::translate("QDeclarativeParser","Script import requires a qualifier")); - error.setLine(node->importIdToken.startLine); - error.setColumn(node->importIdToken.startColumn); + error.setLine(node->fileNameToken.startLine); + error.setColumn(node->fileNameToken.startColumn); _parser->_errors << error; return false; } @@ -535,7 +535,8 @@ bool ProcessAST::visit(AST::UiPublicMember *node) // { "time", Object::DynamicProperty::Time, "QTime" }, // { "date", Object::DynamicProperty::Date, "QDate" }, { "date", Object::DynamicProperty::DateTime, "QDateTime" }, - { "var", Object::DynamicProperty::Variant, "QVariant" } + { "var", Object::DynamicProperty::Variant, "QVariant" }, + { "variant", Object::DynamicProperty::Variant, "QVariant" } }; const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) / sizeof(propTypeNameToTypes[0]); @@ -563,7 +564,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node) _parser->_errors << error; return false; } - + signal.parameterTypes << qtType; signal.parameterNames << p->name->asString().toUtf8(); p = p->finish(); @@ -646,6 +647,11 @@ bool ProcessAST::visit(AST::UiPublicMember *node) property.location = location(node->firstSourceLocation(), node->lastSourceLocation()); + if (memberType == QLatin1String("var")) + qWarning().nospace() << qPrintable(_parser->_scriptFile) << ":" << property.location.start.line << ":" + << property.location.start.column << ": var type has been replaced by variant. " + << "Support will be removed entirely shortly."; + if (node->expression) { // default value property.defaultValue = new Property; property.defaultValue->parent = _stateStack.top().object; @@ -828,6 +834,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node) if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) { Object::DynamicSlot slot; + slot.location = location(funDecl->firstSourceLocation(), funDecl->lastSourceLocation()); AST::FormalParameterList *f = funDecl->formals; while (f) { @@ -908,6 +915,7 @@ bool QDeclarativeScriptParser::parse(const QByteArray &qmldata, const QUrl &url) clear(); const QString fileName = url.toString(); + _scriptFile = fileName; QTextStream stream(qmldata, QIODevice::ReadOnly); stream.setCodec("UTF-8"); diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index 5c88b9a..bbcc00b 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -82,10 +82,6 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) { if (s.isEmpty()) return QVariant(s); - if (s.startsWith(QLatin1Char('\'')) && s.endsWith(QLatin1Char('\''))) { - QString data = s.mid(1, s.length() - 2); - return QVariant(data); - } bool ok = false; QRectF r = rectFFromString(s, &ok); if (ok) return QVariant(r); @@ -104,6 +100,10 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) QVariant QDeclarativeStringConverters::variantFromString(const QString &s, int preferredType, bool *ok) { switch (preferredType) { + case QMetaType::Int: + return QVariant(int(qRound(s.toDouble(ok)))); + case QMetaType::UInt: + return QVariant(uint(qRound(s.toDouble(ok)))); case QMetaType::QColor: return QVariant::fromValue(colorFromString(s, ok)); case QMetaType::QDate: diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp index 9cac3e1..2a3417a 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp +++ b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp @@ -62,7 +62,7 @@ struct TypeNameData : public QScriptDeclarativeClass::Object { }; QDeclarativeTypeNameScriptClass::QDeclarativeTypeNameScriptClass(QDeclarativeEngine *bindEngine) -: QDeclarativeScriptClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), +: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), object(0), type(0) { } @@ -139,7 +139,7 @@ QDeclarativeTypeNameScriptClass::queryProperty(Object *obj, const Identifier &na return 0; } -QDeclarativeTypeNameScriptClass::ScriptValue +QDeclarativeTypeNameScriptClass::Value QDeclarativeTypeNameScriptClass::property(Object *obj, const Identifier &name) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); @@ -159,7 +159,7 @@ void QDeclarativeTypeNameScriptClass::setProperty(Object *o, const Identifier &n Q_ASSERT(!type); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v); + ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v, context()); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h b/src/declarative/qml/qdeclarativetypenamescriptclass_p.h index 8e07f02..310e14e 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h +++ b/src/declarative/qml/qdeclarativetypenamescriptclass_p.h @@ -54,16 +54,15 @@ // #include "private/qdeclarativeengine_p.h" +#include <private/qscriptdeclarativeclass_p.h> #include <QtScript/qscriptclass.h> -#include <private/qdeclarativescriptclass_p.h> - QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QDeclarativeType; class QDeclarativeTypeNameCache; -class QDeclarativeTypeNameScriptClass : public QDeclarativeScriptClass +class QDeclarativeTypeNameScriptClass : public QScriptDeclarativeClass { public: QDeclarativeTypeNameScriptClass(QDeclarativeEngine *); @@ -77,7 +76,7 @@ protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual ScriptValue property(Object *, const Identifier &); + virtual Value property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp index 839e0dd..261c84a 100644 --- a/src/declarative/qml/qdeclarativevaluetype.cpp +++ b/src/declarative/qml/qdeclarativevaluetype.cpp @@ -47,10 +47,6 @@ QT_BEGIN_NAMESPACE -#if (QT_VERSION < QT_VERSION_CHECK(4,7,0)) -Q_DECLARE_METATYPE(QEasingCurve); -#endif - template<typename T> int qmlRegisterValueTypeEnums(const char *qmlName) { @@ -82,29 +78,18 @@ QDeclarativeValueTypeFactory::QDeclarativeValueTypeFactory() // ### Optimize for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii) valueTypes[ii] = valueType(ii); -#if (QT_VERSION < QT_VERSION_CHECK(4,7,0)) - easingType = qMetaTypeId<QEasingCurve>(); - easingValueType = valueType(easingType); -#endif } QDeclarativeValueTypeFactory::~QDeclarativeValueTypeFactory() { for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii) delete valueTypes[ii]; -#if (QT_VERSION < QT_VERSION_CHECK(4,7,0)) - delete easingValueType; -#endif } bool QDeclarativeValueTypeFactory::isValueType(int idx) { if ((uint)idx < QVariant::UserType) return true; -#if (QT_VERSION < QT_VERSION_CHECK(4,7,0)) - if (idx == qMetaTypeId<QEasingCurve>()) - return true; -#endif return false; } @@ -116,9 +101,6 @@ void QDeclarativeValueTypeFactory::registerValueTypes() QDeclarativeValueType *QDeclarativeValueTypeFactory::operator[](int idx) const { -#if (QT_VERSION < QT_VERSION_CHECK(4,7,0)) - if (idx == easingType) return easingValueType; -#endif return valueTypes[idx]; } @@ -140,17 +122,11 @@ QDeclarativeValueType *QDeclarativeValueTypeFactory::valueType(int t) return new QDeclarativeRectFValueType; case QVariant::Vector3D: return new QDeclarativeVector3DValueType; -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) case QVariant::EasingCurve: return new QDeclarativeEasingValueType; -#endif case QVariant::Font: return new QDeclarativeFontValueType; default: -#if (QT_VERSION < QT_VERSION_CHECK(4,7,0)) - if (t == qMetaTypeId<QEasingCurve>()) - return new QDeclarativeEasingValueType; -#endif return 0; } } @@ -566,11 +542,7 @@ void QDeclarativeEasingValueType::write(QObject *obj, int idx, QDeclarativePrope QVariant QDeclarativeEasingValueType::value() { -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) return QVariant(easing); -#else - return QVariant::fromValue<QEasingCurve>(easing); -#endif } void QDeclarativeEasingValueType::setValue(QVariant value) @@ -619,7 +591,7 @@ void QDeclarativeEasingValueType::setPeriod(qreal period) } QDeclarativeFontValueType::QDeclarativeFontValueType(QObject *parent) -: QDeclarativeValueType(parent), hasPixelSize(false) +: QDeclarativeValueType(parent), pixelSizeSet(false), pointSizeSet(false) { } @@ -627,6 +599,8 @@ void QDeclarativeFontValueType::read(QObject *obj, int idx) { void *a[] = { &font, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); + pixelSizeSet = false; + pointSizeSet = false; } void QDeclarativeFontValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags) @@ -724,13 +698,17 @@ qreal QDeclarativeFontValueType::pointSize() const void QDeclarativeFontValueType::setPointSize(qreal size) { - if (hasPixelSize) { + if (pixelSizeSet) { qWarning() << "Both point size and pixel size set. Using pixel size."; return; } - if (size >= 0.0) + if (size >= 0.0) { + pointSizeSet = true; font.setPointSizeF(size); + } else { + pointSizeSet = false; + } } int QDeclarativeFontValueType::pixelSize() const @@ -741,10 +719,12 @@ int QDeclarativeFontValueType::pixelSize() const void QDeclarativeFontValueType::setPixelSize(int size) { if (size >=0) { + if (pointSizeSet) + qWarning() << "Both point size and pixel size set. Using pixel size."; font.setPixelSize(size); - hasPixelSize = true; + pixelSizeSet = true; } else { - hasPixelSize = false; + pixelSizeSet = false; } } diff --git a/src/declarative/qml/qdeclarativevaluetype_p.h b/src/declarative/qml/qdeclarativevaluetype_p.h index 1fe8bd2..5bfc27d 100644 --- a/src/declarative/qml/qdeclarativevaluetype_p.h +++ b/src/declarative/qml/qdeclarativevaluetype_p.h @@ -90,10 +90,6 @@ public: private: QDeclarativeValueType *valueTypes[QVariant::UserType - 1]; -#if (QT_VERSION < QT_VERSION_CHECK(4,7,0)) - int easingType; - QDeclarativeValueType *easingValueType; -#endif }; class Q_AUTOTEST_EXPORT QDeclarativePointFValueType : public QDeclarativeValueType @@ -399,7 +395,8 @@ public: private: QFont font; - bool hasPixelSize; + bool pixelSizeSet; + bool pointSizeSet; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index f7902b9..fdb71c6 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -55,7 +55,7 @@ struct QDeclarativeValueTypeReference : public QScriptDeclarativeClass::Object { }; QDeclarativeValueTypeScriptClass::QDeclarativeValueTypeScriptClass(QDeclarativeEngine *bindEngine) -: QDeclarativeScriptClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) +: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) { } @@ -100,7 +100,7 @@ QDeclarativeValueTypeScriptClass::queryProperty(Object *obj, const Identifier &n return rv; } -QDeclarativeValueTypeScriptClass::ScriptValue QDeclarativeValueTypeScriptClass::property(Object *obj, const Identifier &) +QDeclarativeValueTypeScriptClass::Value QDeclarativeValueTypeScriptClass::property(Object *obj, const Identifier &) { QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj); @@ -113,7 +113,7 @@ QDeclarativeValueTypeScriptClass::ScriptValue QDeclarativeValueTypeScriptClass:: } void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier &, - const QScriptValue &value) + const QScriptValue &value) { QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj); @@ -122,7 +122,7 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier if (delBinding) delBinding->destroy(); - QVariant v = QDeclarativeScriptClass::toVariant(engine, value); + QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value); ref->type->read(ref->object, ref->property); QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h b/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h index 31bd415..2bbb61f 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h @@ -54,13 +54,13 @@ // -#include <private/qdeclarativescriptclass_p.h> +#include <private/qscriptdeclarativeclass_p.h> QT_BEGIN_NAMESPACE class QDeclarativeEngine; class QDeclarativeValueType; -class QDeclarativeValueTypeScriptClass : public QDeclarativeScriptClass +class QDeclarativeValueTypeScriptClass : public QScriptDeclarativeClass { public: QDeclarativeValueTypeScriptClass(QDeclarativeEngine *); @@ -70,7 +70,7 @@ public: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual ScriptValue property(Object *, const Identifier &); + virtual Value property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); virtual QVariant toVariant(Object *, bool *ok = 0); diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 5ba7f9b..0addfabd 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -236,13 +236,44 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, } } else { QDeclarative_setParent_noEvent(o, parent); - // o->setParent(parent); } } stack.push(o); } break; + case QDeclarativeInstruction::CreateSimpleObject: + { + QObject *o = (QObject *)operator new(instr.createSimple.typeSize + + sizeof(QDeclarativeDeclarativeData)); +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) + ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeDeclarativeData)); +#else + // faster than memset + ::bzero(o, instr.createSimple.typeSize + sizeof(QDeclarativeDeclarativeData)); +#endif + instr.createSimple.create(o); + + QDeclarativeDeclarativeData *ddata = + (QDeclarativeDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); + ddata->lineNumber = instr.line; + ddata->columnNumber = instr.createSimple.column; + + QObjectPrivate::get(o)->declarativeData = ddata; + ddata->context = ddata->outerContext = ctxt; + ddata->nextContextObject = ctxt->contextObjects; + if (ddata->nextContextObject) + ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; + ddata->prevContextObject = &ctxt->contextObjects; + ctxt->contextObjects = ddata; + + QObject *parent = stack.top(); + QDeclarative_setParent_noEvent(o, parent); + + stack.push(o); + } + break; + case QDeclarativeInstruction::SetId: { QObject *target = stack.top(); @@ -314,6 +345,26 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, } break; + case QDeclarativeInstruction::StoreVariantInteger: + { + QObject *target = stack.top(); + QVariant v(instr.storeInteger.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.storeString.propertyIndex, a); + } + break; + + case QDeclarativeInstruction::StoreVariantDouble: + { + QObject *target = stack.top(); + QVariant v(instr.storeDouble.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.storeString.propertyIndex, a); + } + break; + case QDeclarativeInstruction::StoreString: { QObject *target = stack.top(); diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 2644ecf..2e2a8e8 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -671,7 +671,8 @@ QScriptValue QDeclarativeVMEMetaObject::method(int index) // XXX We should evaluate all methods in a single big script block to // improve the call time between dynamic methods defined on the same // object - methods[index] = QDeclarativeExpressionPrivate::evalInObjectScope(ctxt, object, code); + methods[index] = QDeclarativeExpressionPrivate::evalInObjectScope(ctxt, object, code, ctxt->url.toString(), + data->lineNumber, 0); } return methods[index]; diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h index f13dd34..76390c9 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject_p.h +++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h @@ -94,7 +94,7 @@ struct QDeclarativeVMEMetaData int parameterCount; int bodyOffset; int bodyLength; - int scriptProgram; + int lineNumber; }; PropertyData *propertyData() const { diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index ddb0ece..138d979 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -107,16 +107,20 @@ class QDeclarativeWorkerScriptEnginePrivate : public QObject { Q_OBJECT public: + enum WorkerEventTypes { + WorkerDestroyEvent = QEvent::User + 100 + }; + QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *eng); - struct ScriptEngine : public QDeclarativeScriptEngine + struct ScriptEngine : public QDeclarativeScriptEngine { ScriptEngine(QDeclarativeWorkerScriptEnginePrivate *parent) : QDeclarativeScriptEngine(0), p(parent), accessManager(0) {} ~ScriptEngine() { delete accessManager; } QDeclarativeWorkerScriptEnginePrivate *p; QNetworkAccessManager *accessManager; - virtual QNetworkAccessManager *networkAccessManager() { + virtual QNetworkAccessManager *networkAccessManager() { if (!accessManager) { if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) { accessManager = p->qmlengine->networkAccessManagerFactory()->create(this); @@ -159,6 +163,9 @@ public: static QScriptValue onMessage(QScriptContext *ctxt, QScriptEngine *engine); static QScriptValue sendMessage(QScriptContext *ctxt, QScriptEngine *engine); +signals: + void stopThread(); + protected: virtual bool event(QEvent *); @@ -182,7 +189,7 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::onMessage(QScriptContext *ct if (!script) return engine->undefinedValue(); - if (ctxt->argumentCount() >= 1) + if (ctxt->argumentCount() >= 1) script->callback = ctxt->argument(0); return script->callback; @@ -198,13 +205,13 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::sendMessage(QScriptContext * int id = ctxt->thisObject().data().toVariant().toInt(); WorkerScript *script = p->workers.value(id); - if (!script) + if (!script) return engine->undefinedValue(); QMutexLocker(&p->m_lock); - if (script->owner) - QCoreApplication::postEvent(script->owner, + if (script->owner) + QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, scriptValueToVariant(ctxt->argument(0)))); return engine->undefinedValue(); @@ -226,7 +233,7 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::getWorker(int id) QScriptValue api = workerEngine->newObject(); api.setData(script->id); - api.setProperty(QLatin1String("onMessage"), workerEngine->newFunction(onMessage), + api.setProperty(QLatin1String("onMessage"), workerEngine->newFunction(onMessage), QScriptValue::PropertyGetter | QScriptValue::PropertySetter); api.setProperty(QLatin1String("sendMessage"), workerEngine->newFunction(sendMessage)); @@ -246,6 +253,9 @@ bool QDeclarativeWorkerScriptEnginePrivate::event(QEvent *event) WorkerLoadEvent *workerEvent = static_cast<WorkerLoadEvent *>(event); processLoad(workerEvent->workerId(), workerEvent->url()); return true; + } else if (event->type() == (QEvent::Type)WorkerDestroyEvent) { + emit stopThread(); + return true; } else { return QObject::event(event); } @@ -362,7 +372,7 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(const Q QVariantList list = qvariant_cast<QVariantList>(value); QScriptValue rv = engine->newArray(list.count()); - for (quint32 ii = 0; ii < quint32(list.count()); ++ii) + for (quint32 ii = 0; ii < quint32(list.count()); ++ii) rv.setProperty(ii, variantToScriptValue(list.at(ii), engine)); return rv; @@ -372,7 +382,7 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(const Q QScriptValue rv = engine->newObject(); - for (QVariantHash::ConstIterator iter = hash.begin(); iter != hash.end(); ++iter) + for (QVariantHash::ConstIterator iter = hash.begin(); iter != hash.end(); ++iter) rv.setProperty(iter.key(), variantToScriptValue(iter.value(), engine)); return rv; @@ -429,6 +439,7 @@ QDeclarativeWorkerScriptEngine::QDeclarativeWorkerScriptEngine(QDeclarativeEngin : QThread(parent), d(new QDeclarativeWorkerScriptEnginePrivate(parent)) { d->m_lock.lock(); + connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection); start(QThread::LowPriority); d->m_wait.wait(&d->m_lock); d->moveToThread(this); @@ -440,8 +451,10 @@ QDeclarativeWorkerScriptEngine::~QDeclarativeWorkerScriptEngine() d->m_lock.lock(); qDeleteAll(d->workers); d->workers.clear(); + QCoreApplication::postEvent(d, new QEvent((QEvent::Type)QDeclarativeWorkerScriptEnginePrivate::WorkerDestroyEvent)); d->m_lock.unlock(); + wait(); d->deleteLater(); } @@ -504,36 +517,10 @@ void QDeclarativeWorkerScriptEngine::run() Messages can be passed between the new thread and the parent thread using sendMessage() and the onMessage() handler. - - Here is an example: - - \qml - import Qt 4.6 - Rectangle { - width: 300 - height: 300 - - Text { - id: myText - text: 'Click anywhere' - } + Here is an example: - WorkerScript { - id: myWorker - source: "script.js" - - onMessage: { - myText.text = messageObject.reply - } - } - - MouseArea { - anchors.fill: parent - onClicked: myWorker.sendMessage( {'x': mouse.x, 'y': mouse.y} ); - } - } - \endqml + \snippet doc/src/snippets/declarative/workerscript.qml 0 The above worker script specifies a javascript file, "script.js", that handles the operations to be performed in the new thread: @@ -541,10 +528,10 @@ void QDeclarativeWorkerScriptEngine::run() \qml WorkerScript.onMessage = function(message) { // ... long-running operations and calculations are done here - WorkerScript.sendMessage( {'reply': 'Mouse is at ' + message.x + ',' + message.y} ); + WorkerScript.sendMessage({ 'reply': 'Mouse is at ' + message.x + ',' + message.y }) } \endqml - + When the user clicks anywhere within the rectangle, \c sendMessage() is called, triggering the \tt WorkerScript.onMessage() handler in \tt source.js. This in turn sends a reply message that is then received @@ -578,7 +565,7 @@ void QDeclarativeWorkerScript::setSource(const QUrl &source) m_source = source; - if (m_engine) + if (m_engine) m_engine->executeUrl(m_scriptId, m_source); emit sourceChanged(); @@ -632,7 +619,7 @@ bool QDeclarativeWorkerScript::event(QEvent *event) if (engine) { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event); - QScriptValue value = + QScriptValue value = QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(workerEvent->data(), scriptEngine); emit message(value); } diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index e2f0c67..1087f44 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -121,7 +121,6 @@ HEADERS += \ $$PWD/qdeclarativetypenamescriptclass_p.h \ $$PWD/qdeclarativelistscriptclass_p.h \ $$PWD/qdeclarativeworkerscript_p.h \ - $$PWD/qdeclarativescriptclass_p.h \ $$PWD/qdeclarativeguard_p.h \ $$PWD/qdeclarativeimageprovider.h \ $$PWD/qdeclarativenetworkaccessmanagerfactory.h \ diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index ec23bb2..e3680f2 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -248,6 +248,20 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM */ +/* + A ListModel internally uses either a NestedListModel or FlatListModel. + + A NestedListModel can contain lists of ListElements (which + when retrieved from get() is accessible as a list model within the list + model) whereas a FlatListModel cannot. + + ListModel uses a NestedListModel to begin with, and if the model is later + used from a WorkerScript, it changes to use a FlatListModel instead. This + is because ModelNode (which abstracts the nested list model data) needs + access to the declarative engine and script engine, which cannot be + safely used from outside of the main thread. +*/ + QDeclarativeListModel::QDeclarativeListModel(QObject *parent) : QListModelInterface(parent), m_agent(0), m_nested(new NestedListModel(this)), m_flat(0), m_isWorkerCopy(false) { @@ -264,6 +278,9 @@ QDeclarativeListModel::QDeclarativeListModel(bool workerCopy, QObject *parent) QDeclarativeListModel::~QDeclarativeListModel() { + if (m_agent) + m_agent->release(); + delete m_nested; delete m_flat; } @@ -622,6 +639,11 @@ bool QDeclarativeListModelParser::compileProperty(const QDeclarativeCustomParser QDeclarativeCustomParserNode node = qvariant_cast<QDeclarativeCustomParserNode>(value); + if (node.name() != "ListElement") { + error(node, QDeclarativeListModel::tr("ListElement: cannot contain nested elements")); + return false; + } + { ListInstruction li; li.type = ListInstruction::Push; @@ -633,7 +655,7 @@ bool QDeclarativeListModelParser::compileProperty(const QDeclarativeCustomParser for(int jj = 0; jj < props.count(); ++jj) { const QDeclarativeCustomParserProperty &nodeProp = props.at(jj); if (nodeProp.name() == "") { - error(nodeProp, QDeclarativeListModel::tr("ListElement: cannot use default property")); + error(nodeProp, QDeclarativeListModel::tr("ListElement: cannot contain nested elements")); return false; } if (nodeProp.name() == "id") { @@ -1343,6 +1365,7 @@ ModelObject::ModelObject() void ModelObject::setValue(const QByteArray &name, const QVariant &val) { _mo->setValue(name, val); + setProperty(name.constData(), val); } diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h index b6a643b..53d30c2 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h +++ b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h @@ -66,7 +66,6 @@ QT_MODULE(Declarative) class QDeclarativeListModel; -// Currently this will leak as no-one releases it in the worker thread class QDeclarativeListModelWorkerAgent : public QObject { Q_OBJECT diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index e57d3c2..5e60819 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -65,13 +65,6 @@ static const int maxImageRequestCount = 8; QT_BEGIN_NAMESPACE -#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0)) -inline uint qHash(const QUrl &uri) -{ - return qHash(uri.toEncoded(QUrl::FormattingOption(0x100))); -} -#endif - static QString toLocalFileOrQrc(const QUrl& url) { QString r = url.toLocalFile(); diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index e7228cc..9c3ee9f 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -103,7 +103,7 @@ QT_BEGIN_NAMESPACE natural width (which is the whole string on one line). \qml - import Qt 4.6 + import Qt 4.7 Rectangle { width: 640 @@ -111,7 +111,7 @@ QT_BEGIN_NAMESPACE Text { id: theText width: 50 - wrap: true + wrapMode: Text.WordWrap text: "a text string that is longer than 50 pixels" } @@ -377,7 +377,7 @@ QDeclarativeProperty QDeclarativePropertyChangesPrivate::property(const QByteArray &property) { Q_Q(QDeclarativePropertyChanges); - QDeclarativeProperty prop(object, QString::fromUtf8(property)); + QDeclarativeProperty prop(object, QString::fromUtf8(property), qmlContext(q)); if (!prop.isValid()) { qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(property)); return QDeclarativeProperty(); @@ -400,16 +400,11 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() QByteArray property = d->properties.at(ii).first; - QDeclarativeAction a(d->object, QString::fromLatin1(property), - d->properties.at(ii).second); + QDeclarativeAction a(d->object, QString::fromUtf8(property), + qmlContext(this), d->properties.at(ii).second); if (a.property.isValid()) { a.restore = restoreEntryValues(); - - if (a.property.propertyType() == QVariant::Url && - (a.toValue.userType() == QVariant::String || a.toValue.userType() == QVariant::ByteArray) && !a.toValue.isNull()) - a.toValue.setValue(qmlContext(this)->resolvedUrl(QUrl(a.toValue.toString()))); - list << a; } } @@ -436,7 +431,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() a.property = prop; a.fromValue = a.property.read(); a.specifiedObject = d->object; - a.specifiedProperty = QString::fromLatin1(property); + a.specifiedProperty = QString::fromUtf8(property); if (d->isExplicit) { a.toValue = d->expressions.at(ii).second->value(); diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/declarative/util/qdeclarativesmoothedanimation.cpp index 3411642..48a7583 100644 --- a/src/declarative/util/qdeclarativesmoothedanimation.cpp +++ b/src/declarative/util/qdeclarativesmoothedanimation.cpp @@ -69,6 +69,7 @@ QSmoothedAnimation::QSmoothedAnimation(QObject *parent) void QSmoothedAnimation::restart() { + initialVelocity = trackVelocity; if (state() != QAbstractAnimation::Running) start(); else @@ -224,6 +225,7 @@ void QSmoothedAnimation::init() QDeclarativePropertyPrivate::write(target, to, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); + stop(); return; case QDeclarativeSmoothedAnimation::Immediate: initialVelocity = 0; @@ -248,13 +250,14 @@ void QSmoothedAnimation::init() /*! \qmlclass SmoothedAnimation QDeclarativeSmoothedAnimation \since 4.7 + \inherits NumberAnimation \brief The SmoothedAnimation element allows a property to smoothly track a value. - The SmoothedAnimation smoothly animates a property's value to a set target value + The SmoothedAnimation animates a property's value to a set target value using an ease in/out quad easing curve. If the animation is restarted with a different target value, the easing curves used to animate to the old - and the new target values are spliced together to avoid any obvious visual - glitches. + and the new target values are smoothly spliced together to avoid any obvious + visual glitches by maintaining the current velocity. The property animation is configured by setting the velocity at which the animation should occur, or the duration that the animation should take. @@ -270,7 +273,7 @@ void QSmoothedAnimation::init() The follow example shows one rectangle tracking the position of another. \code -import Qt 4.6 +import Qt 4.7 Rectangle { width: 800; height: 600; color: "blue" @@ -343,17 +346,14 @@ void QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions QSet<QAbstractAnimation*> anims; for (int i = 0; i < d->actions->size(); i++) { QSmoothedAnimation *ease; - qreal trackVelocity; bool needsRestart; if (!d->activeAnimations.contains((*d->actions)[i].property)) { ease = new QSmoothedAnimation(); d->wrapperGroup->addAnimation(ease); d->activeAnimations.insert((*d->actions)[i].property, ease); - trackVelocity = 0.0; needsRestart = false; } else { ease = d->activeAnimations.value((*d->actions)[i].property); - trackVelocity = ease->trackVelocity; needsRestart = true; } @@ -366,8 +366,7 @@ void QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions ease->velocity = d->anim->velocity; ease->userDuration = d->anim->userDuration; - ease->trackVelocity = trackVelocity; - ease->initialVelocity = trackVelocity; + ease->initialVelocity = ease->trackVelocity; if (needsRestart) ease->init(); @@ -458,14 +457,14 @@ void QDeclarativeSmoothedAnimation::setVelocity(qreal v) } /*! -\qmlproperty qreal SmoothedAnimation::maximumEasingTime + \qmlproperty qreal SmoothedAnimation::maximumEasingTime -This property specifies the maximum time, in msecs, an "eases" during the follow should take. -Setting this property causes the velocity to "level out" after at a time. Setting -a negative value reverts to the normal mode of easing over the entire animation -duration. + This property specifies the maximum time, in msecs, an "eases" during the follow should take. + Setting this property causes the velocity to "level out" after at a time. Setting + a negative value reverts to the normal mode of easing over the entire animation + duration. -The default value is -1. + The default value is -1. */ int QDeclarativeSmoothedAnimation::maximumEasingTime() const { diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p.h index df53104..17aafa4 100644 --- a/src/declarative/util/qdeclarativesmoothedanimation_p.h +++ b/src/declarative/util/qdeclarativesmoothedanimation_p.h @@ -83,7 +83,6 @@ public: int maximumEasingTime() const; void setMaximumEasingTime(int); -public: virtual void transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction); diff --git a/src/declarative/util/qdeclarativesmoothedfollow.cpp b/src/declarative/util/qdeclarativesmoothedfollow.cpp new file mode 100644 index 0000000..63c9618 --- /dev/null +++ b/src/declarative/util/qdeclarativesmoothedfollow.cpp @@ -0,0 +1,299 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativesmoothedfollow_p.h" +#include "qdeclarativesmoothedanimation_p_p.h" + +#include <private/qobject_p.h> +#include <QtCore/qnumeric.h> + +#include "qdeclarativeglobal_p.h" + + +QT_BEGIN_NAMESPACE + +class QDeclarativeSmoothedFollowPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeSmoothedFollow) +public: + QDeclarativeSmoothedFollowPrivate(); + + bool enabled; + QSmoothedAnimation *anim; +}; + +/*! + \qmlclass SmoothedFollow QDeclarativeSmoothedFollow + \since 4.7 + \inherits NumberAnimation + \brief The SmoothedFollow element allows a property to smoothly track a value. + + The SmoothedFollow animates a property's value to a set target value + using an ease in/out quad easing curve. If the animation is restarted + with a different target value, the easing curves used to animate to the old + and the new target values are smoothly spliced together to avoid any obvious + visual glitches by maintaining the current velocity. + + The property animation is configured by setting the velocity at which the + animation should occur, or the duration that the animation should take. + If both a velocity and a duration are specified, the one that results in + the quickest animation is chosen for each change in the target value. + + For example, animating from 0 to 800 will take 4 seconds if a velocity + of 200 is set, will take 8 seconds with a duration of 8000 set, and will + take 4 seconds with both a velocity of 200 and a duration of 8000 set. + Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set, + will take 8 seconds with a duration of 8000 set, and will take 8 seconds + with both a velocity of 200 and a duration of 8000 set. + + The follow example shows one rectangle tracking the position of another. +\code +import Qt 4.6 + +Rectangle { + width: 800; height: 600; color: "blue" + + Rectangle { + color: "green" + width: 60; height: 60; + SmoothedFollow on x { to: rect1.x - 5; velocity: 200 } + SmoothedFollow on y { to: rect1.y - 5; velocity: 200 } + } + + Rectangle { + id: rect1 + color: "red" + width: 50; height: 50; + } + + focus: true + Keys.onRightPressed: rect1.x = rect1.x + 100 + Keys.onLeftPressed: rect1.x = rect1.x - 100 + Keys.onUpPressed: rect1.y = rect1.y - 100 + Keys.onDownPressed: rect1.y = rect1.y + 100 +} +\endcode + + The default velocity of SmoothedFollow is 200 units/second. Note that if the range of the + value being animated is small, then the velocity will need to be adjusted + appropriately. For example, the opacity of an item ranges from 0 - 1.0. + To enable a smooth animation in this range the velocity will need to be + set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity + of 0.5 will take 2000 ms to complete. + + \sa SpringFollow +*/ + +QDeclarativeSmoothedFollow::QDeclarativeSmoothedFollow(QObject *parent) + : QObject(*(new QDeclarativeSmoothedFollowPrivate), parent) +{ +} + +QDeclarativeSmoothedFollow::~QDeclarativeSmoothedFollow() +{ +} + +QDeclarativeSmoothedFollowPrivate::QDeclarativeSmoothedFollowPrivate() + : enabled(true), anim(new QSmoothedAnimation) +{ + Q_Q(QDeclarativeSmoothedFollow); + QDeclarative_setParent_noEvent(anim, q); +} + +/*! + \qmlproperty enumeration SmoothedFollow::reversingMode + + Sets how the SmoothedFollow behaves if an animation direction is reversed. + + If reversing mode is \c Eased, the animation will smoothly decelerate, and + then reverse direction. If the reversing mode is \c Immediate, the + animation will immediately begin accelerating in the reverse direction, + begining with a velocity of 0. If the reversing mode is \c Sync, the + property is immediately set to the target value. +*/ +QDeclarativeSmoothedFollow::ReversingMode QDeclarativeSmoothedFollow::reversingMode() const +{ + Q_D(const QDeclarativeSmoothedFollow); + return (ReversingMode) d->anim->reversingMode; +} + +void QDeclarativeSmoothedFollow::setReversingMode(ReversingMode m) +{ + Q_D(QDeclarativeSmoothedFollow); + if (d->anim->reversingMode == (QDeclarativeSmoothedAnimation::ReversingMode) m) + return; + + d->anim->reversingMode = (QDeclarativeSmoothedAnimation::ReversingMode) m; + emit reversingModeChanged(); +} + +/*! + \qmlproperty int SmoothedFollow::duration + + This property holds the animation duration, in msecs, used when tracking the source. + + Setting this to -1 (the default) disables the duration value. +*/ +int QDeclarativeSmoothedFollow::duration() const +{ + Q_D(const QDeclarativeSmoothedFollow); + return d->anim->userDuration; +} + +void QDeclarativeSmoothedFollow::setDuration(int duration) +{ + Q_D(QDeclarativeSmoothedFollow); + if (duration == d->anim->duration()) + return; + + d->anim->userDuration = duration; + emit durationChanged(); +} + +qreal QDeclarativeSmoothedFollow::velocity() const +{ + Q_D(const QDeclarativeSmoothedFollow); + return d->anim->velocity; +} + +/*! + \qmlproperty qreal SmoothedFollow::velocity + + This property holds the average velocity allowed when tracking the 'to' value. + + The default velocity of SmoothedFollow is 200 units/second. + + Setting this to -1 disables the velocity value. +*/ +void QDeclarativeSmoothedFollow::setVelocity(qreal v) +{ + Q_D(QDeclarativeSmoothedFollow); + if (d->anim->velocity == v) + return; + + d->anim->velocity = v; + emit velocityChanged(); +} + +/*! + \qmlproperty qreal SmoothedFollow::maximumEasingTime + + This property specifies the maximum time, in msecs, an "eases" during the follow should take. + Setting this property causes the velocity to "level out" after at a time. Setting + a negative value reverts to the normal mode of easing over the entire animation + duration. + + The default value is -1. +*/ +int QDeclarativeSmoothedFollow::maximumEasingTime() const +{ + Q_D(const QDeclarativeSmoothedFollow); + return d->anim->maximumEasingTime; +} + +void QDeclarativeSmoothedFollow::setMaximumEasingTime(int v) +{ + Q_D(QDeclarativeSmoothedFollow); + d->anim->maximumEasingTime = v; + emit maximumEasingTimeChanged(); +} + +/*! + \qmlproperty real SmoothedFollow::to + This property holds the ending value. + If not set, then the value defined in the end state of the transition or Behavior. +*/ +qreal QDeclarativeSmoothedFollow::to() const +{ + Q_D(const QDeclarativeSmoothedFollow); + return d->anim->to; +} + +void QDeclarativeSmoothedFollow::setTo(qreal t) +{ + Q_D(QDeclarativeSmoothedFollow); + + if (qIsNaN(t)) + return; + + if (d->anim->to == t) + return; + + d->anim->to = t; + + if (d->enabled) + d->anim->restart(); +} + +/*! + \qmlproperty bool SmoothedFollow::enabled + This property whether this animation should automatically restart when + the 'to' property is upated. + + The default value of this property is 'true'. +*/ +bool QDeclarativeSmoothedFollow::enabled() const +{ + Q_D(const QDeclarativeSmoothedFollow); + return d->enabled; +} + +void QDeclarativeSmoothedFollow::setEnabled(bool e) +{ + Q_D(QDeclarativeSmoothedFollow); + if (d->enabled == e) + return; + d->enabled = e; + + if (d->enabled) + d->anim->restart(); + else + d->anim->stop(); + emit enabledChanged(); +} + +void QDeclarativeSmoothedFollow::setTarget(const QDeclarativeProperty &t) +{ + Q_D(QDeclarativeSmoothedFollow); + d->anim->target = t; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativesmoothedfollow_p.h b/src/declarative/util/qdeclarativesmoothedfollow_p.h new file mode 100644 index 0000000..d860052 --- /dev/null +++ b/src/declarative/util/qdeclarativesmoothedfollow_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESMOOTHEDFOLLOW_H +#define QDECLARATIVESMOOTHEDFOLLOW_H + +#include <qdeclarative.h> +#include <qdeclarativepropertyvaluesource.h> + +#include <QtCore/qobject.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeProperty; +class QDeclarativeSmoothedFollowPrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeSmoothedFollow : public QObject, + public QDeclarativePropertyValueSource +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeSmoothedFollow) + Q_INTERFACES(QDeclarativePropertyValueSource) + Q_ENUMS(ReversingMode) + + Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged) + Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged) + Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged) + Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged) + Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged) + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + +public: + enum ReversingMode { Eased, Immediate, Sync }; + + QDeclarativeSmoothedFollow(QObject *parent = 0); + ~QDeclarativeSmoothedFollow(); + + qreal to() const; + void setTo(qreal); + + ReversingMode reversingMode() const; + void setReversingMode(ReversingMode); + + int duration() const; + void setDuration(int); + + qreal velocity() const; + void setVelocity(qreal); + + int maximumEasingTime() const; + void setMaximumEasingTime(int); + + bool enabled() const; + void setEnabled(bool); + + virtual void setTarget(const QDeclarativeProperty &); + +Q_SIGNALS: + void velocityChanged(); + void durationChanged(); + void reversingModeChanged(); + void maximumEasingTimeChanged(); + void enabledChanged(); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeSmoothedFollow); + +QT_END_HEADER + +#endif // QDECLARATIVESMOOTHEDFOLLOW_H diff --git a/src/declarative/util/qdeclarativespringfollow.cpp b/src/declarative/util/qdeclarativespringfollow.cpp index c42261d..7921735 100644 --- a/src/declarative/util/qdeclarativespringfollow.cpp +++ b/src/declarative/util/qdeclarativespringfollow.cpp @@ -59,13 +59,13 @@ class QDeclarativeSpringFollowPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QDeclarativeSpringFollow) public: QDeclarativeSpringFollowPrivate() - : currentValue(0), sourceValue(0), maxVelocity(0), lastTime(0) + : currentValue(0), to(0), maxVelocity(0), lastTime(0) , mass(1.0), spring(0.), damping(0.), velocity(0), epsilon(0.01) , modulus(0.0), useMass(false), haveModulus(false), enabled(true), mode(Track), clock(this) {} QDeclarativeProperty property; qreal currentValue; - qreal sourceValue; + qreal to; qreal maxVelocity; qreal velocityms; int lastTime; @@ -102,7 +102,7 @@ void QDeclarativeSpringFollowPrivate::tick(int time) int elapsed = time - lastTime; if (!elapsed) return; - qreal srcVal = sourceValue; + qreal srcVal = to; if (haveModulus) { currentValue = fmod(currentValue, modulus); srcVal = fmod(srcVal, modulus); @@ -158,16 +158,16 @@ void QDeclarativeSpringFollowPrivate::tick(int time) currentValue += moveBy; if (haveModulus) currentValue = fmod(currentValue, modulus); - if (currentValue > sourceValue) { - currentValue = sourceValue; + if (currentValue > to) { + currentValue = to; clock.stop(); } } else { currentValue -= moveBy; if (haveModulus && currentValue < 0.0) currentValue = fmod(currentValue, modulus) + modulus; - if (currentValue < sourceValue) { - currentValue = sourceValue; + if (currentValue < to) { + currentValue = to; clock.stop(); } } @@ -196,9 +196,9 @@ void QDeclarativeSpringFollowPrivate::start() Q_Q(QDeclarativeSpringFollow); if (mode == QDeclarativeSpringFollowPrivate::Track) { - currentValue = sourceValue; + currentValue = to; property.write(currentValue); - } else if (sourceValue != currentValue && clock.state() != QAbstractAnimation::Running) { + } else if (to != currentValue && clock.state() != QAbstractAnimation::Running) { lastTime = 0; currentValue = property.read().toReal(); clock.start(); // infinity?? @@ -239,7 +239,7 @@ void QDeclarativeSpringFollowPrivate::stop() x: rect1.width width: 20; height: 20 color: "#ff0000" - SpringFollow on y { source: rect1.y; velocity: 200 } + SpringFollow on y { to: rect1.y; velocity: 200 } } \endcode */ @@ -260,26 +260,26 @@ void QDeclarativeSpringFollow::setTarget(const QDeclarativeProperty &property) d->currentValue = property.read().toReal(); } -qreal QDeclarativeSpringFollow::sourceValue() const +qreal QDeclarativeSpringFollow::to() const { Q_D(const QDeclarativeSpringFollow); - return d->sourceValue; + return d->to; } /*! - \qmlproperty qreal SpringFollow::source - This property holds the source value which will be tracked. + \qmlproperty qreal SpringFollow::to + This property holds the target value which will be tracked. Bind to a property in order to track its changes. */ -void QDeclarativeSpringFollow::setSourceValue(qreal value) +void QDeclarativeSpringFollow::setTo(qreal value) { Q_D(QDeclarativeSpringFollow); - if (d->clock.state() == QAbstractAnimation::Running && d->sourceValue == value) + if (d->clock.state() == QAbstractAnimation::Running && d->to == value) return; - d->sourceValue = value; + d->to = value; d->start(); } @@ -307,7 +307,7 @@ void QDeclarativeSpringFollow::setVelocity(qreal velocity) This property holds the spring constant The spring constant describes how strongly the target is pulled towards the - source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0 + source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0 When a spring constant is set and the velocity property is greater than 0, velocity limits the maximum speed. @@ -417,13 +417,10 @@ void QDeclarativeSpringFollow::setMass(qreal mass) } /*! - \qmlproperty qreal SpringFollow::value - The current value. -*/ - -/*! \qmlproperty bool SpringFollow::enabled This property holds whether the target will track the source. + + The default value of this property is 'true'. */ bool QDeclarativeSpringFollow::enabled() const { @@ -454,6 +451,10 @@ bool QDeclarativeSpringFollow::inSync() const return d->enabled && d->clock.state() != QAbstractAnimation::Running; } +/*! + \qmlproperty qreal SpringFollow::value + The current value. +*/ qreal QDeclarativeSpringFollow::value() const { Q_D(const QDeclarativeSpringFollow); diff --git a/src/declarative/util/qdeclarativespringfollow_p.h b/src/declarative/util/qdeclarativespringfollow_p.h index 2ac0d82..b829c57 100644 --- a/src/declarative/util/qdeclarativespringfollow_p.h +++ b/src/declarative/util/qdeclarativespringfollow_p.h @@ -59,7 +59,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeSpringFollow : public QObject, Q_DECLARE_PRIVATE(QDeclarativeSpringFollow) Q_INTERFACES(QDeclarativePropertyValueSource) - Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue) + Q_PROPERTY(qreal to READ to WRITE setTo) Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity) Q_PROPERTY(qreal spring READ spring WRITE setSpring) Q_PROPERTY(qreal damping READ damping WRITE setDamping) @@ -76,22 +76,30 @@ public: virtual void setTarget(const QDeclarativeProperty &); - qreal sourceValue() const; - void setSourceValue(qreal value); + qreal to() const; + void setTo(qreal value); + qreal velocity() const; void setVelocity(qreal velocity); + qreal spring() const; void setSpring(qreal spring); + qreal damping() const; void setDamping(qreal damping); + qreal epsilon() const; void setEpsilon(qreal epsilon); + qreal mass() const; void setMass(qreal modulus); + qreal modulus() const; void setModulus(qreal modulus); + bool enabled() const; void setEnabled(bool enabled); + bool inSync() const; qreal value() const; diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index 5e6c35e..78813fa 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -74,6 +74,18 @@ QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyN fromValue = property.read(); } +QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyName, + QDeclarativeContext *context, const QVariant &value) +: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), + property(target, propertyName, context), toValue(value), + fromBinding(0), toBinding(0), event(0), + specifiedObject(target), specifiedProperty(propertyName) +{ + if (property.isValid()) + fromValue = property.read(); +} + + QDeclarativeActionEvent::~QDeclarativeActionEvent() { } @@ -121,14 +133,13 @@ QDeclarativeStateOperation::QDeclarativeStateOperation(QObjectPrivate &dd, QObje /*! \qmlclass State QDeclarativeState - \since 4.7 + \since 4.7 \brief The State element defines configurations of objects and properties. A state is specified as a set of batched changes from the default configuration. - Note that setting the state of an object from within another state of the same object is - inadvisible. Not only would this have the same effect as going directly to the second state - it may cause the program to crash. + \note setting the state of an object from within another state of the same object is + not allowed. \sa {qmlstates}{States}, {state-transitions}{Transitions} */ @@ -191,6 +202,17 @@ bool QDeclarativeState::isWhenKnown() const This should be set to an expression that evaluates to true when you want the state to be applied. + + If multiple states in a group have \c when clauses that evaluate to true at the same time, + the first matching state will be applied. For example, in the following snippet + \c state1 will always be selected rather than \c state2 when sharedCondition becomes + \c true. + \qml + states: [ + State { name: "state1"; when: sharedCondition }, + State { name: "state2"; when: sharedCondition } + ] + \endqml */ QDeclarativeBinding *QDeclarativeState::when() const { diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index ee2b7e8..472897e 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -61,6 +61,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeAction public: QDeclarativeAction(); QDeclarativeAction(QObject *, const QString &, const QVariant &); + QDeclarativeAction(QObject *, const QString &, + QDeclarativeContext *, const QVariant &); bool restore:1; bool actionDone:1; diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index 2cc1fcc..410a269 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -1090,6 +1090,9 @@ bool QDeclarativeAnchorChanges::changesBindings() void QDeclarativeAnchorChanges::saveOriginals() { Q_D(QDeclarativeAnchorChanges); + if (!d->target) + return; + d->origLeft = d->target->anchors()->left(); d->origRight = d->target->anchors()->right(); d->origHCenter = d->target->anchors()->horizontalCenter(); @@ -1146,6 +1149,9 @@ void QDeclarativeAnchorChanges::copyOriginals(QDeclarativeActionEvent *other) void QDeclarativeAnchorChanges::clearBindings() { Q_D(QDeclarativeAnchorChanges); + if (!d->target) + return; + d->fromX = d->target->x(); d->fromY = d->target->y(); d->fromWidth = d->target->width(); @@ -1242,6 +1248,9 @@ void QDeclarativeAnchorChanges::rewind() void QDeclarativeAnchorChanges::saveCurrentValues() { Q_D(QDeclarativeAnchorChanges); + if (!d->target) + return; + d->rewindLeft = d->target->anchors()->left(); d->rewindRight = d->target->anchors()->right(); d->rewindHCenter = d->target->anchors()->horizontalCenter(); @@ -1259,6 +1268,9 @@ void QDeclarativeAnchorChanges::saveCurrentValues() void QDeclarativeAnchorChanges::saveTargetValues() { Q_D(QDeclarativeAnchorChanges); + if (!d->target) + return; + d->toX = d->target->x(); d->toY = d->target->y(); d->toWidth = d->target->width(); diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index d4c72bd..b9f1abb 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -46,6 +46,7 @@ #include "private/qdeclarativebind_p.h" #include "private/qdeclarativeconnections_p.h" #include "private/qdeclarativesmoothedanimation_p.h" +#include "private/qdeclarativesmoothedfollow_p.h" #include "private/qdeclarativefontloader_p.h" #include "private/qdeclarativelistaccessor_p.h" #include "private/qdeclarativelistmodel_p.h" @@ -71,38 +72,6 @@ #include "private/qdeclarativexmllistmodel_p.h" #endif -template<typename T> -int qmlRegisterTypeEnums(const char *qmlName) -{ - QByteArray name(T::staticMetaObject.className()); - - QByteArray pointerName(name + '*'); - QByteArray listName("QDeclarativeListProperty<" + name + ">"); - - QDeclarativePrivate::RegisterType type = { - 0, - - qRegisterMetaType<T *>(pointerName.constData()), - qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), - 0, 0, - - "Qt", 4, 6, qmlName, &T::staticMetaObject, - - QDeclarativePrivate::attachedPropertiesFunc<T>(), - QDeclarativePrivate::attachedPropertiesMetaObject<T>(), - - QDeclarativePrivate::StaticCastSelector<T,QDeclarativeParserStatus>::cast(), - QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueSource>::cast(), - QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueInterceptor>::cast(), - - 0, 0, - - 0 - }; - - return QDeclarativePrivate::registerType(type); -} - void QDeclarativeUtilModule::defineModule() { qmlRegisterType<QDeclarativeAnchorAnimation>("Qt",4,6,"AnchorAnimation"); @@ -112,6 +81,7 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterType<QDeclarativeColorAnimation>("Qt",4,6,"ColorAnimation"); qmlRegisterType<QDeclarativeConnections>("Qt",4,6,"Connections"); qmlRegisterType<QDeclarativeSmoothedAnimation>("Qt",4,6,"SmoothedAnimation"); + qmlRegisterType<QDeclarativeSmoothedFollow>("Qt",4,6,"SmoothedFollow"); qmlRegisterType<QDeclarativeFontLoader>("Qt",4,6,"FontLoader"); qmlRegisterType<QDeclarativeListElement>("Qt",4,6,"ListElement"); qmlRegisterType<QDeclarativeNumberAnimation>("Qt",4,6,"NumberAnimation"); @@ -142,7 +112,7 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterType<QDeclarativeStateOperation>(); qmlRegisterType<QDeclarativeAnchorSet>(); - qmlRegisterTypeEnums<QDeclarativeAbstractAnimation>("Animation"); + qmlRegisterUncreatableType<QDeclarativeAbstractAnimation>("Qt",4,6,"Animation"); qmlRegisterCustomType<QDeclarativeListModel>("Qt", 4,6, "ListModel", "QDeclarativeListModel", new QDeclarativeListModelParser); diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index b33af06..7f8b962 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -160,7 +160,7 @@ public: for (int i=0; i<roleObjects->count(); i++) { if (!roleObjects->at(i)->isValid()) { - job.roleQueries << ""; + job.roleQueries << QString(); continue; } job.roleQueries << roleObjects->at(i)->query(); diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index 4163596..f20bba1 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -9,6 +9,7 @@ SOURCES += \ $$PWD/qdeclarativesystempalette.cpp \ $$PWD/qdeclarativespringfollow.cpp \ $$PWD/qdeclarativesmoothedanimation.cpp \ + $$PWD/qdeclarativesmoothedfollow.cpp \ $$PWD/qdeclarativestate.cpp\ $$PWD/qdeclarativetransitionmanager.cpp \ $$PWD/qdeclarativestateoperations.cpp \ @@ -38,6 +39,7 @@ HEADERS += \ $$PWD/qdeclarativesystempalette_p.h \ $$PWD/qdeclarativespringfollow_p.h \ $$PWD/qdeclarativesmoothedanimation_p.h \ + $$PWD/qdeclarativesmoothedfollow_p.h \ $$PWD/qdeclarativesmoothedanimation_p_p.h \ $$PWD/qdeclarativestate_p.h\ $$PWD/qdeclarativestateoperations_p.h \ |