summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-09-08 05:30:38 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-09-08 05:30:38 (GMT)
commitcad3b0bdacdbdf407dfbdda5f6dc9cb7d96fa709 (patch)
tree37a16ff73fe102ac0cd169b20f9b12135903d33a /src/declarative
parent5305831c3b0d58a61efadc1c1d3ce9ce4d6e8c77 (diff)
parentb9a924a1e77faeeba595d0619afb14e8fdbb2dd4 (diff)
downloadQt-cad3b0bdacdbdf407dfbdda5f6dc9cb7d96fa709.zip
Qt-cad3b0bdacdbdf407dfbdda5f6dc9cb7d96fa709.tar.gz
Qt-cad3b0bdacdbdf407dfbdda5f6dc9cb7d96fa709.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/QmlChanges.txt1
-rw-r--r--src/declarative/fx/qfxflickable.cpp88
-rw-r--r--src/declarative/fx/qfxflickable.h5
-rw-r--r--src/declarative/fx/qfxflickable_p.h7
-rw-r--r--src/declarative/fx/qfxitem.cpp11
-rw-r--r--src/declarative/fx/qfxlistview.cpp3
-rw-r--r--src/declarative/fx/qfxloader.cpp65
-rw-r--r--src/declarative/fx/qfxloader.h13
-rw-r--r--src/declarative/fx/qfxpathview.cpp3
-rw-r--r--src/declarative/fx/qfxtextinput.cpp54
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp19
-rw-r--r--src/declarative/qml/qmlcomponent.cpp23
-rw-r--r--src/declarative/qml/qmlcomponent.h3
-rw-r--r--src/declarative/qml/qmlcomponent_p.h4
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h2
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp26
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h2
-rw-r--r--src/declarative/qml/qmlengine.cpp4
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp2
-rw-r--r--src/declarative/qml/qmlmetatype.cpp8
-rw-r--r--src/declarative/qml/qmlmetatype.h1
-rw-r--r--src/declarative/qml/qmlparser.cpp2
-rw-r--r--src/declarative/util/qfxview.cpp2
-rw-r--r--src/declarative/util/qmllistmodel.cpp271
-rw-r--r--src/declarative/util/qmllistmodel.h8
25 files changed, 575 insertions, 52 deletions
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt
index 95c81c7..9bf4b10 100644
--- a/src/declarative/QmlChanges.txt
+++ b/src/declarative/QmlChanges.txt
@@ -66,6 +66,7 @@ MouseRegion: add "hoverEnabled" property
MouseRegion: add "pressedButtons" property
Timer: add start() and stop() slots
WebView: add newWindowComponent and newWindowParent properties
+Loader: add status() and progress() properties
Deletions:
Column/VerticalPositioner: lost "margins" property
diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp
index 007fa0e..5fe9617 100644
--- a/src/declarative/fx/qfxflickable.cpp
+++ b/src/declarative/fx/qfxflickable.cpp
@@ -148,6 +148,7 @@ QFxFlickablePrivate::QFxFlickablePrivate()
, vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false)
, pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true)
, interactive(true), maxVelocity(-1), reportedVelocitySmoothing(100)
+ , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0)
, horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0)
{
fixupXEvent = QmlTimeLineEvent::timeLineEvent<QFxFlickablePrivate, &QFxFlickablePrivate::fixupX>(&_moveX, this);
@@ -707,11 +708,57 @@ void QFxFlickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void QFxFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QFxFlickable);
+ d->clearDelayedPress();
d->handleMouseReleaseEvent(event);
event->accept();
ungrabMouse();
}
+void QFxFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QFxFlickable);
+ if (!q->scene() || pressDelay <= 0)
+ return;
+ delayedPressTarget = q->scene()->mouseGrabberItem();
+ delayedPressEvent = new QGraphicsSceneMouseEvent(event->type());
+ delayedPressEvent->setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ delayedPressEvent->setButtonDownPos(button, event->buttonDownPos(button));
+ }
+ }
+ delayedPressEvent->setScenePos(event->scenePos());
+ delayedPressEvent->setLastScenePos(event->lastScenePos());
+ delayedPressEvent->setPos(event->pos());
+ delayedPressEvent->setLastPos(event->lastPos());
+ delayedPressTimer.start(pressDelay, q);
+}
+
+void QFxFlickablePrivate::clearDelayedPress()
+{
+ if (delayedPressEvent) {
+ delayedPressTimer.stop();
+ delete delayedPressEvent;
+ delayedPressEvent = 0;
+ }
+}
+
+void QFxFlickable::timerEvent(QTimerEvent *event)
+{
+ Q_D(QFxFlickable);
+ if (event->timerId() == d->delayedPressTimer.timerId()) {
+ d->delayedPressTimer.stop();
+ if (d->delayedPressEvent) {
+ QFxItem *grabber = scene() ? qobject_cast<QFxItem*>(scene()->mouseGrabberItem()) : 0;
+ if (!grabber || grabber != this)
+ scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent);
+ delete d->delayedPressEvent;
+ d->delayedPressEvent = 0;
+ }
+ }
+}
+
qreal QFxFlickable::minYExtent() const
{
return 0.0;
@@ -996,22 +1043,34 @@ bool QFxFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
d->handleMouseMoveEvent(&mouseEvent);
break;
case QEvent::GraphicsSceneMousePress:
+ if (d->delayedPressEvent)
+ return false;
+
d->handleMousePressEvent(&mouseEvent);
+ d->captureDelayedPress(event);
break;
case QEvent::GraphicsSceneMouseRelease:
+ if (d->delayedPressEvent) {
+ scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent);
+ d->clearDelayedPress();
+ }
d->handleMouseReleaseEvent(&mouseEvent);
break;
default:
break;
}
grabber = qobject_cast<QFxItem*>(s->mouseGrabberItem());
- if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this)
+ if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this) {
+ d->clearDelayedPress();
grabMouse();
+ }
- return d->stealMouse;
+ return d->stealMouse || d->delayedPressEvent;
} else if (!d->lastPosTime.isNull()) {
d->lastPosTime = QTime();
}
+ if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease)
+ d->clearDelayedPress();
return false;
}
@@ -1055,6 +1114,31 @@ bool QFxFlickable::isFlicking() const
return d->flicked;
}
+/*!
+ \qmlproperty int Flickable::pressDelay
+
+ This property holds the time to delay (ms) delivering a press to
+ children of the Flickable. This can be useful where reacting
+ to a press before a flicking action has undesireable effects.
+
+ If the flickable is dragged/flicked before the delay times out
+ the press event will not be delivered. If the button is released
+ within the timeout, both the press and release will be delivered.
+*/
+int QFxFlickable::pressDelay() const
+{
+ Q_D(const QFxFlickable);
+ return d->pressDelay;
+}
+
+void QFxFlickable::setPressDelay(int delay)
+{
+ Q_D(QFxFlickable);
+ if (d->pressDelay == delay)
+ return;
+ d->pressDelay = delay;
+}
+
qreal QFxFlickable::reportedVelocitySmoothing() const
{
Q_D(const QFxFlickable);
diff --git a/src/declarative/fx/qfxflickable.h b/src/declarative/fx/qfxflickable.h
index 4905101..b3339b0 100644
--- a/src/declarative/fx/qfxflickable.h
+++ b/src/declarative/fx/qfxflickable.h
@@ -71,6 +71,7 @@ class Q_DECLARATIVE_EXPORT QFxFlickable : public QFxItem
Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive)
+ Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay)
Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged)
Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY isAtBoundaryChanged)
@@ -108,6 +109,9 @@ public:
bool isMoving() const;
bool isFlicking() const;
+ int pressDelay() const;
+ void setPressDelay(int delay);
+
qreal reportedVelocitySmoothing() const;
void setReportedVelocitySmoothing(qreal);
@@ -148,6 +152,7 @@ protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void timerEvent(QTimerEvent *event);
qreal visibleX() const;
qreal visibleY() const;
diff --git a/src/declarative/fx/qfxflickable_p.h b/src/declarative/fx/qfxflickable_p.h
index a506027..7224f21 100644
--- a/src/declarative/fx/qfxflickable_p.h
+++ b/src/declarative/fx/qfxflickable_p.h
@@ -76,6 +76,9 @@ public:
virtual void fixupY();
void updateBeginningEnd();
+ void captureDelayedPress(QGraphicsSceneMouseEvent *event);
+ void clearDelayedPress();
+
public:
QFxItem *viewport;
QmlTimeLineValueProxy<QFxItem> _moveX;
@@ -109,6 +112,10 @@ public:
qreal reportedVelocitySmoothing;
int flickTargetX;
int flickTargetY;
+ QGraphicsSceneMouseEvent *delayedPressEvent;
+ QGraphicsItem *delayedPressTarget;
+ QBasicTimer delayedPressTimer;
+ int pressDelay;
void updateVelocity();
struct Velocity : public QmlTimeLineValue
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
index 88a0854..3429010 100644
--- a/src/declarative/fx/qfxitem.cpp
+++ b/src/declarative/fx/qfxitem.cpp
@@ -336,6 +336,7 @@ public:
virtual void keyReleased(QKeyEvent *event);
virtual void inputMethodEvent(QInputMethodEvent *event);
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ virtual void componentComplete();
private:
QFxItemKeyFilter *m_next;
@@ -377,6 +378,11 @@ QVariant QFxItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
return QVariant();
}
+void QFxItemKeyFilter::componentComplete()
+{
+ if (m_next) m_next->componentComplete();
+}
+
class QFxKeyNavigationAttachedPrivate : public QObjectPrivate
{
public:
@@ -912,11 +918,10 @@ public:
QFxItem *item;
};
-class QFxKeysAttached : public QObject, public QFxItemKeyFilter, public QmlParserStatus
+class QFxKeysAttached : public QObject, public QFxItemKeyFilter
{
Q_OBJECT
Q_DECLARE_PRIVATE(QFxKeysAttached)
- Q_INTERFACES(QmlParserStatus)
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(QList<QFxItem *> *forwardTo READ forwardTo)
@@ -2496,6 +2501,8 @@ void QFxItem::componentComplete()
d->_anchors->componentComplete();
d->_anchors->d_func()->updateOnComplete();
}
+ if (d->keyHandler)
+ d->keyHandler->componentComplete();
}
QmlStateGroup *QFxItemPrivate::states()
diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp
index c24610f..6c0a83e 100644
--- a/src/declarative/fx/qfxlistview.cpp
+++ b/src/declarative/fx/qfxlistview.cpp
@@ -1507,7 +1507,8 @@ void QFxListView::itemsInserted(int modelIndex, int count)
// Update the indexes of the following visible items.
for (; index < d->visibleItems.count(); ++index) {
FxListItem *listItem = d->visibleItems.at(index);
- listItem->setPosition(listItem->position() + (pos - initialPos));
+ if (listItem->item != d->currentItem->item)
+ listItem->setPosition(listItem->position() + (pos - initialPos));
if (listItem->index != -1)
listItem->index += count;
}
diff --git a/src/declarative/fx/qfxloader.cpp b/src/declarative/fx/qfxloader.cpp
index 95ddae3..869a5b0 100644
--- a/src/declarative/fx/qfxloader.cpp
+++ b/src/declarative/fx/qfxloader.cpp
@@ -111,9 +111,12 @@ void QFxLoader::setSource(const QUrl &url)
d->source = url;
d->item = 0;
+ emit itemChanged();
if (d->source.isEmpty()) {
emit sourceChanged();
+ emit statusChanged();
+ emit progressChanged();
return;
}
@@ -122,14 +125,22 @@ void QFxLoader::setSource(const QUrl &url)
(*iter)->setOpacity(1.);
d->item = (*iter);
emit sourceChanged();
+ emit statusChanged();
+ emit progressChanged();
+ emit itemChanged();
} else {
d->qmlcomp =
new QmlComponent(qmlEngine(this), d->source, this);
- if (!d->qmlcomp->isLoading())
+ if (!d->qmlcomp->isLoading()) {
d->_q_sourceLoaded();
- else
+ } else {
connect(d->qmlcomp, SIGNAL(statusChanged(QmlComponent::Status)),
this, SLOT(_q_sourceLoaded()));
+ connect(d->qmlcomp, SIGNAL(progressChanged(qreal)),
+ this, SIGNAL(progressChanged()));
+ emit statusChanged();
+ emit progressChanged();
+ }
}
}
@@ -146,6 +157,8 @@ void QFxLoaderPrivate::_q_sourceLoaded()
delete qmlcomp;
qmlcomp = 0;
emit q->sourceChanged();
+ emit q->statusChanged();
+ emit q->progressChanged();
return;
}
QObject *obj = qmlcomp->create(ctxt);
@@ -163,10 +176,58 @@ void QFxLoaderPrivate::_q_sourceLoaded()
delete qmlcomp;
qmlcomp = 0;
emit q->sourceChanged();
+ emit q->statusChanged();
+ emit q->progressChanged();
+ emit q->itemChanged();
}
}
/*!
+ \qmlproperty enum Loader::status
+
+ This property holds the status of QML loading. It can be one of:
+ \list
+ \o Null - no QML source has been set
+ \o Ready - the QML source has been loaded
+ \o Loading - the QML source is currently being loaded
+ \o Error - an error occurred while loading the QML source
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real Loader::progress
+
+ This property holds the progress of QML data loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+QFxLoader::Status QFxLoader::status() const
+{
+ Q_D(const QFxLoader);
+
+ if (d->qmlcomp)
+ return static_cast<QFxLoader::Status>(d->qmlcomp->status());
+
+ if (d->item)
+ return Ready;
+
+ return d->source.isEmpty() ? Null : Error;
+}
+
+qreal QFxLoader::progress() const
+{
+ Q_D(const QFxLoader);
+
+ if (d->qmlcomp)
+ return d->qmlcomp->progress();
+
+ return d->item ? 1.0 : 0.0;
+}
+
+/*!
\qmlproperty Item Loader::item
This property holds the top-level item created from source.
*/
diff --git a/src/declarative/fx/qfxloader.h b/src/declarative/fx/qfxloader.h
index 8c555c6..132c8f4 100644
--- a/src/declarative/fx/qfxloader.h
+++ b/src/declarative/fx/qfxloader.h
@@ -54,12 +54,14 @@ class QFxLoaderPrivate;
class Q_DECLARATIVE_EXPORT QFxLoader : public QFxItem
{
Q_OBJECT
+ Q_ENUMS(Status)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
- Q_PROPERTY(QFxItem *item READ item) //### NOTIFY itemChanged
+ Q_PROPERTY(QFxItem *item READ item NOTIFY itemChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
//### sourceItem
//### sourceComponent
- //### status, progress
//### resizeMode { NoResize, SizeLoaderToItem (default), SizeItemToLoader }
public:
@@ -69,10 +71,17 @@ public:
QUrl source() const;
void setSource(const QUrl &);
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
QFxItem *item() const;
Q_SIGNALS:
+ void itemChanged();
void sourceChanged();
+ void statusChanged();
+ void progressChanged();
private:
Q_DISABLE_COPY(QFxLoader)
diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp
index 469e9f3..62f9db0 100644
--- a/src/declarative/fx/qfxpathview.cpp
+++ b/src/declarative/fx/qfxpathview.cpp
@@ -128,6 +128,9 @@ QFxPathView::QFxPathView(QFxPathViewPrivate &dd, QFxItem *parent)
QFxPathView::~QFxPathView()
{
+ Q_D(QFxPathView);
+ if (d->ownModel)
+ delete d->model;
}
/*!
diff --git a/src/declarative/fx/qfxtextinput.cpp b/src/declarative/fx/qfxtextinput.cpp
index 9718321..4dd29cd 100644
--- a/src/declarative/fx/qfxtextinput.cpp
+++ b/src/declarative/fx/qfxtextinput.cpp
@@ -555,33 +555,33 @@ void QFxTextInput::selectAll()
void QFxTextInputPrivate::init()
{
- Q_Q(QFxTextInput);
- control->setCursorWidth(1);
- control->setPasswordCharacter(QLatin1Char('*'));
- control->setLayoutDirection(Qt::LeftToRight);
- q->setSmoothTransform(smooth);
- q->setAcceptedMouseButtons(Qt::LeftButton);
- q->setFlag(QGraphicsItem::ItemHasNoContents, false);
- q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
- q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
- q, SLOT(cursorPosChanged()));
- q->connect(control, SIGNAL(selectionChanged()),
- q, SLOT(selectionChanged()));
- q->connect(control, SIGNAL(textChanged(const QString &)),
- q, SLOT(q_textChanged()));
- q->connect(control, SIGNAL(accepted()),
- q, SIGNAL(accepted()));
- q->connect(control, SIGNAL(updateNeeded(const QRect &)),
- // q, SLOT(dirtyCache(const QRect &)));
- q, SLOT(updateAll()));
- q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
- q, SLOT(updateAll()));
- q->connect(control, SIGNAL(selectionChanged()),
- q, SLOT(updateAll()));
- q->updateSize();
- oldValidity = control->hasAcceptableInput();
- lastSelectionStart = 0;
- lastSelectionEnd = 0;
+ Q_Q(QFxTextInput);
+ control->setCursorWidth(1);
+ control->setPasswordCharacter(QLatin1Char('*'));
+ control->setLayoutDirection(Qt::LeftToRight);
+ q->setSmoothTransform(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemHasNoContents, false);
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(cursorPosChanged()));
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(selectionChanged()));
+ q->connect(control, SIGNAL(textChanged(const QString &)),
+ q, SLOT(q_textChanged()));
+ q->connect(control, SIGNAL(accepted()),
+ q, SIGNAL(accepted()));
+ q->connect(control, SIGNAL(updateNeeded(const QRect &)),
+ // q, SLOT(dirtyCache(const QRect &)));
+ q, SLOT(updateAll()));
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(updateAll()));
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(updateAll()));
+ q->updateSize();
+ oldValidity = control->hasAcceptableInput();
+ lastSelectionStart = 0;
+ lastSelectionEnd = 0;
}
void QFxTextInput::cursorPosChanged()
diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp
index 82bec09..cac8b8d 100644
--- a/src/declarative/fx/qfxvisualitemmodel.cpp
+++ b/src/declarative/fx/qfxvisualitemmodel.cpp
@@ -243,6 +243,16 @@ public:
QmlContext *m_context;
QList<int> m_roles;
QHash<int,QString> m_roleNames;
+ void ensureRoles() {
+ if (m_roles.isEmpty()) {
+ if (m_listModelInterface) {
+ m_roles = m_listModelInterface->roles();
+ for (int ii = 0; ii < m_roles.count(); ++ii)
+ m_roleNames.insert(m_roles.at(ii),
+ m_listModelInterface->toString(m_roles.at(ii)));
+ }
+ }
+ }
struct ObjectRef {
ObjectRef(QObject *object=0) : obj(object), ref(1) {}
@@ -375,6 +385,7 @@ int QFxVisualDataModelDataMetaObject::createProperty(const char *name, const cha
return QmlOpenMetaObject::createProperty(name, type);
} else {
const QLatin1String sname(name);
+ data->m_model->ensureRoles();
for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
iter != data->m_model->m_roleNames.end(); ++iter) {
@@ -397,6 +408,7 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro
&& data->m_model->m_modelList) {
return data->m_model->m_modelList->at(data->m_index);
} else if (data->m_model->m_listModelInterface) {
+ data->m_model->ensureRoles();
for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
iter != data->m_model->m_roleNames.end(); ++iter) {
@@ -410,6 +422,7 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro
}
}
} else if (data->m_model->m_abstractItemModel) {
+ data->m_model->ensureRoles();
for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
iter != data->m_model->m_roleNames.end(); ++iter) {
@@ -560,12 +573,6 @@ void QFxVisualDataModel::setModel(const QVariant &model)
if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
d->m_roles.clear();
d->m_roleNames.clear();
- if (d->m_listModelInterface) {
- d->m_roles = d->m_listModelInterface->roles();
- for (int ii = 0; ii < d->m_roles.count(); ++ii)
- d->m_roleNames.insert(d->m_roles.at(ii),
- d->m_listModelInterface->toString(d->m_roles.at(ii)));
- }
QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
this, SLOT(_q_itemsChanged(int,int,QList<int>)));
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index e897cce..f291ac0 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -121,6 +121,14 @@ void QmlComponentPrivate::typeDataReady()
emit q->statusChanged(q->status());
}
+void QmlComponentPrivate::updateProgress(qreal p)
+{
+ Q_Q(QmlComponent);
+
+ progress = p;
+ emit q->progressChanged(p);
+}
+
void QmlComponentPrivate::fromTypeData(QmlCompositeTypeData *data)
{
url = data->imports.baseUrl();
@@ -238,6 +246,12 @@ bool QmlComponent::isLoading() const
return status() == Loading;
}
+qreal QmlComponent::progress() const
+{
+ Q_D(const QmlComponent);
+ return d->progress;
+}
+
/*!
\fn void QmlComponent::statusChanged(QmlComponent::Status status)
@@ -343,7 +357,9 @@ void QmlComponent::setData(const QByteArray &data, const QUrl &url)
}
+ d->progress = 1.0;
emit statusChanged(status());
+ emit progressChanged(d->progress);
}
/*!
@@ -364,17 +380,16 @@ void QmlComponent::loadUrl(const QUrl &url)
QmlEnginePrivate::get(d->engine)->typeManager.get(d->url);
if (data->status == QmlCompositeTypeData::Waiting) {
-
d->typeData = data;
d->typeData->addWaiter(d);
-
+ d->progress = data->progress;
} else {
-
d->fromTypeData(data);
-
+ d->progress = 1.0;
}
emit statusChanged(status());
+ emit progressChanged(d->progress);
}
/*!
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
index 60b7ccd..af250e5 100644
--- a/src/declarative/qml/qmlcomponent.h
+++ b/src/declarative/qml/qmlcomponent.h
@@ -84,6 +84,8 @@ public:
QList<QmlError> errors() const;
+ qreal progress() const;
+
QUrl url() const;
virtual QObject *create(QmlContext *context = 0);
@@ -95,6 +97,7 @@ public:
Q_SIGNALS:
void statusChanged(QmlComponent::Status);
+ void progressChanged(qreal);
protected:
QmlComponent(QmlComponentPrivate &dd, QObject* parent);
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
index 4b459c2..2b25b78 100644
--- a/src/declarative/qml/qmlcomponent_p.h
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -74,15 +74,17 @@ class QmlComponentPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QmlComponent)
public:
- QmlComponentPrivate() : typeData(0), start(-1), count(-1), cc(0), completePending(false), engine(0) {}
+ QmlComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), completePending(false), engine(0) {}
QmlCompositeTypeData *typeData;
void typeDataReady();
+ void updateProgress(qreal);
void fromTypeData(QmlCompositeTypeData *data);
QList<QmlError> errors;
QUrl url;
+ qreal progress;
int start;
int count;
diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h
index 54933c4..044b4ca 100644
--- a/src/declarative/qml/qmlcompositetypedata_p.h
+++ b/src/declarative/qml/qmlcompositetypedata_p.h
@@ -108,6 +108,8 @@ struct QmlCompositeTypeData : public QmlRefCount
void addWaiter(QmlComponentPrivate *p);
void remWaiter(QmlComponentPrivate *p);
+ qreal progress;
+
private:
friend class QmlCompositeTypeManager;
friend class QmlCompiler;
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
index f64547c..a99cff0 100644
--- a/src/declarative/qml/qmlcompositetypemanager.cpp
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -87,6 +87,7 @@ QmlComponent *QmlCompositeTypeData::toComponent(QmlEngine *engine)
QmlCompiledData *cc = toCompiledComponent(engine);
if (cc) {
component = new QmlComponent(engine, cc, -1, -1, 0);
+ cc->release();
} else {
component = new QmlComponent(engine, 0);
component->d_func()->url = imports.baseUrl();
@@ -135,6 +136,14 @@ QmlCompositeTypeManager::QmlCompositeTypeManager(QmlEngine *e)
{
}
+QmlCompositeTypeManager::~QmlCompositeTypeManager()
+{
+ for (Components::Iterator iter = components.begin(); iter != components.end();) {
+ (*iter)->release();
+ iter = components.erase(iter);
+ }
+}
+
QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url)
{
QmlCompositeTypeData *unit = components.value(url.toString());
@@ -234,9 +243,26 @@ void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
engine->networkAccessManager()->get(QNetworkRequest(url));
QObject::connect(reply, SIGNAL(finished()),
this, SLOT(replyFinished()));
+ QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
}
}
+void QmlCompositeTypeManager::requestProgress(qint64 received, qint64 total)
+{
+ if (total <= 0)
+ return;
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeData *unit = components.value(reply->url().toString());
+ Q_ASSERT(unit);
+
+ unit->progress = qreal(received)/total;
+
+ foreach (QmlComponentPrivate *comp, unit->waiters)
+ comp->updateProgress(unit->progress);
+}
+
void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit,
const QByteArray &data,
const QUrl &url)
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
index cb0fc43..41cbe80 100644
--- a/src/declarative/qml/qmlcompositetypemanager_p.h
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -73,6 +73,7 @@ class QmlCompositeTypeManager : public QObject
Q_OBJECT
public:
QmlCompositeTypeManager(QmlEngine *);
+ ~QmlCompositeTypeManager();
// Return a QmlCompositeTypeData for url. The QmlCompositeTypeData may be
// cached.
@@ -87,6 +88,7 @@ public:
private Q_SLOTS:
void replyFinished();
+ void requestProgress(qint64 received, qint64 total);
private:
void loadSource(QmlCompositeTypeData *);
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 6d3506c..e3d4840 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -1509,6 +1509,10 @@ public:
if (s) {
if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return))
return true;
+ if (s->urls.count() == 1 && !s->isBuiltin[0] && !s->isLibrary[0] && url_return) {
+ *url_return = QUrl(s->urls[0]+"/").resolved(QUrl(QLatin1String(unqualifiedtype + ".qml")));
+ return true;
+ }
}
if (url_return) {
*url_return = base.resolved(QUrl(QLatin1String(type + ".qml")));
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index f9b222f..fdba79e 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -219,6 +219,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (enginePrivate && name.at(0).isUpper()) {
// Attached property
+ //### needs to be done in a better way
QmlCompositeTypeData *typeData =
enginePrivate->typeManager.get(context->baseUrl());
@@ -230,6 +231,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (attachedFunc != -1)
type = QmlMetaProperty::Property | QmlMetaProperty::Attached;
}
+ typeData->release();
}
return;
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
index c488c13..14d85ff 100644
--- a/src/declarative/qml/qmlmetatype.cpp
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -83,6 +83,7 @@ QT_BEGIN_NAMESPACE
struct QmlMetaTypeData
{
+ ~QmlMetaTypeData();
QList<QmlType *> types;
typedef QHash<int, QmlType *> Ids;
Ids idToType;
@@ -101,6 +102,12 @@ struct QmlMetaTypeData
Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData)
Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
+QmlMetaTypeData::~QmlMetaTypeData()
+{
+ for (int i = 0; i < types.count(); ++i)
+ delete types.at(i);
+}
+
class QmlTypePrivate
{
public:
@@ -190,6 +197,7 @@ QmlType::QmlType(int type, int listType, int qmlListType,
QmlType::~QmlType()
{
+ delete d->m_customParser;
delete d;
}
diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h
index 5ed9a5a..02c817d 100644
--- a/src/declarative/qml/qmlmetatype.h
+++ b/src/declarative/qml/qmlmetatype.h
@@ -151,6 +151,7 @@ public:
private:
friend class QmlMetaType;
friend class QmlTypePrivate;
+ friend class QmlMetaTypeData;
QmlType(int, int, int, QmlPrivate::Func, const char *, int);
QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *);
~QmlType();
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index 0f2a282..e102f05 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -80,6 +80,8 @@ QmlParser::Object::~Object()
prop->release();
foreach(Property *prop, valueTypeProperties)
prop->release();
+ foreach(const DynamicProperty &prop, dynamicProperties)
+ if (prop.defaultValue) prop.defaultValue->release();
}
const QMetaObject *Object::metaObject() const
diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp
index 9291e1a..2a38cda 100644
--- a/src/declarative/util/qfxview.cpp
+++ b/src/declarative/util/qfxview.cpp
@@ -222,7 +222,7 @@ void QFxView::execute()
if (d->qml.isEmpty()) {
d->component = new QmlComponent(&d->engine, d->source, this);
} else {
- d->component = new QmlComponent(&d->engine, d->qml.toUtf8(), d->source);
+ d->component = new QmlComponent(&d->engine, d->qml.toUtf8(), d->source, this);
}
if (!d->component->isLoading()) {
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
index 0d9ea94..a5ae60f 100644
--- a/src/declarative/util/qmllistmodel.cpp
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -72,7 +72,9 @@ struct ListModelData
\qmlclass ListModel
\brief The ListModel element defines a free-form list data source.
- The ListModel is a simple hierarchy of elements containing data roles.
+ The ListModel is a simple hierarchy of elements containing data roles. The contents can
+ be defined dynamically, or explicitly in QML:
+
For example:
\code
@@ -166,6 +168,29 @@ struct ListModelData
}
\endcode
+ The content of a ListModel may be created and modified using the clear(),
+ append(), and set() methods. For example:
+
+ \code
+ Component {
+ id: FruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+
+ // Double the price when clicked.
+ MouseRegion {
+ anchors.fill: parent
+ onClicked: FruitModel.set(index, "cost", cost*2)
+ }
+ }
+ }
+ \endcode
+
+ When creating content dynamically, note that the set of available properties cannot be changed
+ except by first clearing the model - whatever properties are first added are then the
+ only permitted properties in the model.
*/
class ModelObject : public QObject
@@ -189,7 +214,6 @@ struct ModelNode
{
ModelNode();
~ModelNode();
- QString className;
QList<QVariant> values;
QHash<QString, ModelNode *> properties;
@@ -214,6 +238,19 @@ struct ModelNode
return objectCache;
}
+ void setProperty(const QString& prop, const QVariant& val) {
+ QHash<QString, ModelNode *>::const_iterator it = properties.find(prop);
+ if (it != properties.end()) {
+ (*it)->values[0] = val;
+ } else {
+ ModelNode *n = new ModelNode;
+ n->values << val;
+ properties.insert(prop,n);
+ }
+ if (objectCache)
+ objectCache->setValue(prop.toLatin1(), val);
+ }
+
QmlListModel *modelCache;
ModelObject *objectCache;
};
@@ -235,7 +272,7 @@ QmlListModel::~QmlListModel()
void QmlListModel::checkRoles() const
{
- if (_rolesOk)
+ if (_rolesOk || !_root)
return;
for (int ii = 0; ii < _root->values.count(); ++ii) {
@@ -341,6 +378,232 @@ int QmlListModel::count() const
return _root->values.count();
}
+/*!
+ \qmlmethod ListModel::clear()
+
+ Deletes all content from the model. The properties are cleared such that
+ different properties may be set on subsequent additions.
+
+ \sa append() remove()
+*/
+void QmlListModel::clear()
+{
+ int cleared = count();
+ _rolesOk = false;
+ delete _root;
+ _root = 0;
+ roleStrings.clear();
+ emit itemsRemoved(0,cleared);
+}
+
+/*!
+ \qmlmethod ListModel::remove(int index)
+
+ Deletes the content at \a index from the model.
+
+ \sa clear()
+*/
+void QmlListModel::remove(int index)
+{
+ if (_root) {
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ _root->values.remove(index);
+ if (node)
+ delete node;
+ emit itemsRemoved(index,1);
+ }
+}
+
+/*!
+ \qmlmethod ListModel::insert(index,dict)
+
+ Adds a new item to the list model at position \a index, with the
+ values in \a dict.
+
+ \code
+ FruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ If \a index is not in the list, sufficient empty items are
+ added to the list.
+
+ \sa set() append()
+*/
+void QmlListModel::insert(int index, const QVariantMap& valuemap)
+{
+ if (!_root)
+ _root = new ModelNode;
+ if (index >= _root->values.count()) {
+ set(index,valuemap);
+ return;
+ }
+ ModelNode *mn = new ModelNode;
+ for (QVariantMap::const_iterator it=valuemap.begin(); it!=valuemap.end(); ++it) {
+ addRole(it.key());
+ ModelNode *value = new ModelNode;
+ value->values << it.value();
+ mn->properties.insert(it.key(),value);
+ }
+ _root->values.insert(index,qVariantFromValue(mn));
+ emit itemsInserted(index,1);
+}
+
+/*!
+ \qmlmethod ListModel::move(from,to,n)
+
+ Moves \a n items \a from one position \a to another.
+
+ The from and to ranges must exist; for example, to move the first 3 items
+ to the end of the list:
+
+ \code
+ FruitModel.move(0,FruitModel.count-3,3)
+ \endcode
+
+ \sa append()
+*/
+void QmlListModel::move(int from, int to, int n)
+{
+ if (from+n > count() || to+n > count() || n==0 || from==to)
+ return;
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+ if (n==1) {
+ _root->values.move(from,to);
+ } else {
+ QList<QVariant> replaced;
+ int i=0;
+ QVariantList::const_iterator it=_root->values.begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=_root->values.begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ QVariantList::const_iterator f=replaced.begin();
+ QVariantList::iterator t=_root->values.begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+ emit itemsMoved(from,to,n);
+}
+
+/*!
+ \qmlmethod ListModel::append(dict)
+
+ Adds a new item to the end of the list model, with the
+ values in \a dict.
+
+ \code
+ FruitModel.append({"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ \sa set() remove()
+*/
+void QmlListModel::append(const QVariantMap& valuemap)
+{
+ if (!_root)
+ _root = new ModelNode;
+ ModelNode *mn = new ModelNode;
+ for (QVariantMap::const_iterator it=valuemap.begin(); it!=valuemap.end(); ++it) {
+ addRole(it.key());
+ ModelNode *value = new ModelNode;
+ value->values << it.value();
+ mn->properties.insert(it.key(),value);
+ }
+ _root->values << qVariantFromValue(mn);
+ emit itemsInserted(count()-1,1);
+}
+
+/*!
+ \qmlmethod ListModel::set(index,dict)
+
+ Changes the item at \a index in the list model to the
+ values in \a dict.
+
+ \code
+ FruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ If \a index is not in the list, sufficient empty items are
+ added to the list.
+
+ \sa append()
+*/
+void QmlListModel::set(int index, const QVariantMap& valuemap)
+{
+ if (!_root)
+ _root = new ModelNode;
+ int initialcount = _root->values.count();
+ while (index > _root->values.count())
+ _root->values.append(qVariantFromValue(new ModelNode));
+ if (index == _root->values.count())
+ append(valuemap);
+ else {
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ QList<int> roles;
+ for (QVariantMap::const_iterator it=valuemap.begin(); it!=valuemap.end(); ++it) {
+ node->setProperty(it.key(),it.value());
+ int r = roleStrings.indexOf(it.key());
+ if (r<0) {
+ r = roleStrings.count();
+ roleStrings << it.key();
+ }
+ roles.append(r);
+ }
+ if (initialcount < index) {
+ emit itemsInserted(initialcount,index-initialcount+1);
+ } else {
+ emit itemsChanged(index,1,roles);
+ }
+ }
+}
+
+/*!
+ \qmlmethod ListModel::set(index,property,value)
+
+ Changes the \a property of the item at \a index in the list model to \a value.
+
+ \code
+ FruitModel.set(3, "cost", 5.95)
+ \endcode
+
+ If \a index is not in the list, sufficient empty items are
+ added to the list.
+
+ \sa append()
+*/
+void QmlListModel::set(int index, const QString& property, const QVariant& value)
+{
+ if (!_root)
+ _root = new ModelNode;
+ int initialcount = _root->values.count();
+ while (index >= _root->values.count())
+ _root->values.append(qVariantFromValue(new ModelNode));
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ int r = roleStrings.indexOf(property);
+ if (r<0) {
+ r = roleStrings.count();
+ roleStrings << property;
+ }
+ QList<int> roles;
+ roles.append(r);
+
+ if (node)
+ node->setProperty(property,value);
+ if (initialcount < index)
+ emit itemsInserted(initialcount,index-initialcount+1);
+ else
+ emit itemsChanged(index,1,roles);
+}
+
+
class QmlListModelParser : public QmlCustomParser
{
public:
@@ -518,7 +781,7 @@ static void dump(ModelNode *node, int ind)
for (int ii = 0; ii < node->values.count(); ++ii) {
ModelNode *subNode = qvariant_cast<ModelNode *>(node->values.at(ii));
if (subNode) {
- qWarning().nospace() << indent << "Sub-node " << ii << ": class " << subNode->className;
+ qWarning().nospace() << indent << "Sub-node " << ii;
dump(subNode, ind + 1);
} else {
qWarning().nospace() << indent << "Sub-node " << ii << ": " << node->values.at(ii).toString();
diff --git a/src/declarative/util/qmllistmodel.h b/src/declarative/util/qmllistmodel.h
index 39edbe4..8bef347 100644
--- a/src/declarative/util/qmllistmodel.h
+++ b/src/declarative/util/qmllistmodel.h
@@ -72,6 +72,14 @@ public:
virtual int count() const;
virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void remove(int index);
+ Q_INVOKABLE void append(const QVariantMap& valuemap);
+ Q_INVOKABLE void insert(int index, const QVariantMap& valuemap);
+ Q_INVOKABLE void set(int index, const QVariantMap& valuemap);
+ Q_INVOKABLE void set(int index, const QString& property, const QVariant& value);
+ Q_INVOKABLE void move(int from, int to, int count);
+
private:
QVariant valueForNode(ModelNode *) const;
mutable QStringList roleStrings;