summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/declarative/snake/content/pics/pause.pngbin0 -> 4327 bytes
-rw-r--r--demos/declarative/snake/content/snake.js4
-rw-r--r--demos/declarative/snake/snake.qml12
-rw-r--r--src/declarative/graphicsitems/qdeclarativegridview.cpp67
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp35
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext.cpp8
-rw-r--r--src/declarative/qml/qdeclarativecompileddata.cpp2
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp8
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h5
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp57
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h7
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp298
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass_p.h9
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp113
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h9
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp19
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h2
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp12
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml10
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp1
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/testtypes.h41
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp53
-rw-r--r--tests/auto/declarative/qdeclarativegridview/data/gridview-noCurrent.qml52
-rw-r--r--tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp43
-rw-r--r--tests/auto/declarative/qdeclarativelistview/data/listview-noCurrent.qml50
-rw-r--r--tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp44
-rw-r--r--tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties.qml17
-rw-r--r--tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties2.qml17
-rw-r--r--tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp108
-rw-r--r--tests/auto/declarative/qmlvisual/qdeclarativetext/elide/elide2.qml2
-rw-r--r--tests/auto/declarative/qmlvisual/qdeclarativetext/elide/multilength.qml2
-rw-r--r--tools/qml/qmlruntime.cpp1
32 files changed, 915 insertions, 193 deletions
diff --git a/demos/declarative/snake/content/pics/pause.png b/demos/declarative/snake/content/pics/pause.png
new file mode 100644
index 0000000..056d97d
--- /dev/null
+++ b/demos/declarative/snake/content/pics/pause.png
Binary files differ
diff --git a/demos/declarative/snake/content/snake.js b/demos/declarative/snake/content/snake.js
index c2e9d3a..5c089de 100644
--- a/demos/declarative/snake/content/snake.js
+++ b/demos/declarative/snake/content/snake.js
@@ -32,7 +32,7 @@ function startNewGame()
if (state == "starting")
return;
- if (heartbeat.running) {
+ if (activeGame) {
endGame();
startNewGameTimer.running = true;
state = "";
@@ -87,7 +87,7 @@ function startNewGame()
function endGame()
{
- heartbeat.running = false;
+ activeGame = false;
for(var i in snake)
snake[i].dying = true;
if (cookie) {
diff --git a/demos/declarative/snake/snake.qml b/demos/declarative/snake/snake.qml
index 5b69217..6eaa976 100644
--- a/demos/declarative/snake/snake.qml
+++ b/demos/declarative/snake/snake.qml
@@ -47,6 +47,7 @@ Rectangle {
id: screen;
SystemPalette { id: activePalette }
color: activePalette.window
+ property bool activeGame: false
property int gridSize : 34
property int margin: 4
@@ -75,6 +76,7 @@ Rectangle {
Timer {
id: heartbeat;
interval: heartbeatInterval;
+ running: activeGame && runtime.isActiveWindow
repeat: true
onTriggered: { Logic.move() }
}
@@ -94,9 +96,17 @@ Rectangle {
Timer {
id: startHeartbeatTimer;
interval: 1000 ;
- onTriggered: { state = "running"; heartbeat.running = true; }
+ onTriggered: { state = "running"; activeGame = true; }
}
+ Image{
+ id: pauseDialog
+ z: 1
+ source: "content/pics/pause.png"
+ anchors.centerIn: parent;
+ //opacity is deliberately not animated
+ opacity: gameActive && !runtime.isActiveWindow
+ }
Image {
Image {
diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp
index 6ee6b0d..f53625f 100644
--- a/src/declarative/graphicsitems/qdeclarativegridview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp
@@ -112,7 +112,7 @@ public:
, bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarativeGridView::NoSnap)
, ownModel(false), wrap(false), autoHighlight(true)
, fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
- , deferredRelease(false), haveHighlightRange(false) {}
+ , deferredRelease(false), haveHighlightRange(false), currentIndexSet(false) {}
void init();
void clear();
@@ -392,6 +392,7 @@ public:
bool layoutScheduled : 1;
bool deferredRelease : 1;
bool haveHighlightRange : 1;
+ bool currentIndexSet : 1;
};
void QDeclarativeGridViewPrivate::init()
@@ -730,6 +731,8 @@ void QDeclarativeGridViewPrivate::createHighlight()
QDeclarative_setParent_noEvent(item, q->contentItem());
item->setParentItem(q->contentItem());
highlight = new FxGridItem(item, q);
+ if (currentItem)
+ highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
highlightXAnimator = new QSmoothedAnimation(q);
highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
highlightXAnimator->userDuration = highlightMoveDuration;
@@ -771,8 +774,11 @@ void QDeclarativeGridViewPrivate::updateCurrent(int modelIndex)
currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
- currentIndex = -1;
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
updateHighlight();
+ } else if (currentIndex != modelIndex) {
+ currentIndex = modelIndex;
emit q->currentIndexChanged();
}
return;
@@ -1236,7 +1242,7 @@ void QDeclarativeGridView::setModel(const QVariant &model)
d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore | QDeclarativeGridViewPrivate::BufferAfter;
if (isComponentComplete()) {
refill();
- if (d->currentIndex >= d->model->count() || d->currentIndex < 0) {
+ if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexSet) {
setCurrentIndex(0);
} else {
d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
@@ -1344,10 +1350,13 @@ void QDeclarativeGridView::setCurrentIndex(int index)
Q_D(QDeclarativeGridView);
if (d->requestedIndex >= 0) // currently creating item
return;
- if (isComponentComplete() && d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) {
+ d->currentIndexSet = true;
+ if (index == d->currentIndex)
+ return;
+ if (isComponentComplete() && d->isValid()) {
d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
d->updateCurrent(index);
- } else if (index != d->currentIndex) {
+ } else {
d->currentIndex = index;
emit currentIndexChanged();
}
@@ -1983,22 +1992,25 @@ void QDeclarativeGridView::keyPressEvent(QKeyEvent *event)
Move the currentIndex up one item in the view.
The current index will wrap if keyNavigationWraps is true and it
- is currently at the end.
+ is currently at the end. This method has no effect if the \l count is zero.
\bold Note: methods should only be called after the Component has completed.
*/
void QDeclarativeGridView::moveCurrentIndexUp()
{
Q_D(QDeclarativeGridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
if (d->flow == QDeclarativeGridView::LeftToRight) {
if (currentIndex() >= d->columns || d->wrap) {
int index = currentIndex() - d->columns;
- setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
}
} else {
if (currentIndex() > 0 || d->wrap) {
int index = currentIndex() - 1;
- setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
}
}
}
@@ -2008,22 +2020,25 @@ void QDeclarativeGridView::moveCurrentIndexUp()
Move the currentIndex down one item in the view.
The current index will wrap if keyNavigationWraps is true and it
- is currently at the end.
+ is currently at the end. This method has no effect if the \l count is zero.
\bold Note: methods should only be called after the Component has completed.
*/
void QDeclarativeGridView::moveCurrentIndexDown()
{
Q_D(QDeclarativeGridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
if (d->flow == QDeclarativeGridView::LeftToRight) {
- if (currentIndex() < d->model->count() - d->columns || d->wrap) {
+ if (currentIndex() < count - d->columns || d->wrap) {
int index = currentIndex()+d->columns;
- setCurrentIndex(index < d->model->count() ? index : 0);
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
}
} else {
- if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ if (currentIndex() < count - 1 || d->wrap) {
int index = currentIndex() + 1;
- setCurrentIndex(index < d->model->count() ? index : 0);
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
}
}
}
@@ -2033,22 +2048,25 @@ void QDeclarativeGridView::moveCurrentIndexDown()
Move the currentIndex left one item in the view.
The current index will wrap if keyNavigationWraps is true and it
- is currently at the end.
+ is currently at the end. This method has no effect if the \l count is zero.
\bold Note: methods should only be called after the Component has completed.
*/
void QDeclarativeGridView::moveCurrentIndexLeft()
{
Q_D(QDeclarativeGridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
if (d->flow == QDeclarativeGridView::LeftToRight) {
if (currentIndex() > 0 || d->wrap) {
int index = currentIndex() - 1;
- setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
}
} else {
if (currentIndex() >= d->columns || d->wrap) {
int index = currentIndex() - d->columns;
- setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
}
}
}
@@ -2058,22 +2076,25 @@ void QDeclarativeGridView::moveCurrentIndexLeft()
Move the currentIndex right one item in the view.
The current index will wrap if keyNavigationWraps is true and it
- is currently at the end.
+ is currently at the end. This method has no effect if the \l count is zero.
\bold Note: methods should only be called after the Component has completed.
*/
void QDeclarativeGridView::moveCurrentIndexRight()
{
Q_D(QDeclarativeGridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
if (d->flow == QDeclarativeGridView::LeftToRight) {
- if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ if (currentIndex() < count - 1 || d->wrap) {
int index = currentIndex() + 1;
- setCurrentIndex(index < d->model->count() ? index : 0);
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
}
} else {
- if (currentIndex() < d->model->count() - d->columns || d->wrap) {
+ if (currentIndex() < count - d->columns || d->wrap) {
int index = currentIndex()+d->columns;
- setCurrentIndex(index < d->model->count() ? index : 0);
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
}
}
}
@@ -2201,7 +2222,7 @@ void QDeclarativeGridView::componentComplete()
if (d->isValid()) {
refill();
d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
- if (d->currentIndex < 0)
+ if (d->currentIndex < 0 && !d->currentIndexSet)
d->updateCurrent(0);
else
d->updateCurrent(d->currentIndex);
@@ -2282,7 +2303,7 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count)
if (d->currentItem)
d->currentItem->index = d->currentIndex;
emit currentIndexChanged();
- } else if (d->currentIndex < 0) {
+ } else if (d->currentIndex < 0 && !d->currentIndexSet) {
d->updateCurrent(0);
}
d->itemCount += count;
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index 6fd3b71..7dd5c75 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -182,7 +182,8 @@ public:
, bufferMode(BufferBefore | BufferAfter)
, ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false)
, correctFlick(false), inFlickCorrection(false), lazyRelease(false)
- , deferredRelease(false), layoutScheduled(false), minExtentDirty(true), maxExtentDirty(true)
+ , deferredRelease(false), layoutScheduled(false), currentIndexSet(false)
+ , minExtentDirty(true), maxExtentDirty(true)
{}
void init();
@@ -544,6 +545,7 @@ public:
bool lazyRelease : 1;
bool deferredRelease : 1;
bool layoutScheduled : 1;
+ bool currentIndexSet : 1;
mutable bool minExtentDirty : 1;
mutable bool maxExtentDirty : 1;
};
@@ -881,6 +883,7 @@ void QDeclarativeListViewPrivate::createHighlight()
} else {
highlight->item->setWidth(currentItem->item->width());
}
+ highlight->setPosition(currentItem->itemPosition());
}
QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
@@ -1045,8 +1048,11 @@ void QDeclarativeListViewPrivate::updateCurrent(int modelIndex)
currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
- currentIndex = -1;
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
updateHighlight();
+ } else if (currentIndex != modelIndex) {
+ currentIndex = modelIndex;
emit q->currentIndexChanged();
}
return;
@@ -1598,7 +1604,7 @@ void QDeclarativeListView::setModel(const QVariant &model)
if (isComponentComplete()) {
updateSections();
refill();
- if (d->currentIndex >= d->model->count() || d->currentIndex < 0) {
+ if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexSet) {
setCurrentIndex(0);
} else {
d->moveReason = QDeclarativeListViewPrivate::SetIndex;
@@ -1708,10 +1714,13 @@ void QDeclarativeListView::setCurrentIndex(int index)
Q_D(QDeclarativeListView);
if (d->requestedIndex >= 0) // currently creating item
return;
- if (isComponentComplete() && d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) {
+ d->currentIndexSet = true;
+ if (index == d->currentIndex)
+ return;
+ if (isComponentComplete() && d->isValid()) {
d->moveReason = QDeclarativeListViewPrivate::SetIndex;
d->updateCurrent(index);
- } else if (index != d->currentIndex) {
+ } else {
d->currentIndex = index;
emit currentIndexChanged();
}
@@ -2523,16 +2532,18 @@ void QDeclarativeListView::geometryChanged(const QRectF &newGeometry,
Increments the current index. The current index will wrap
if keyNavigationWraps is true and it is currently at the end.
+ This method has no effect if the \l count is zero.
\bold Note: methods should only be called after the Component has completed.
*/
void QDeclarativeListView::incrementCurrentIndex()
{
Q_D(QDeclarativeListView);
- if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ int count = d->model ? d->model->count() : 0;
+ if (count && (currentIndex() < count - 1 || d->wrap)) {
d->moveReason = QDeclarativeListViewPrivate::SetIndex;
int index = currentIndex()+1;
- d->updateCurrent(index < d->model->count() ? index : 0);
+ d->updateCurrent((index >= 0 && index < count) ? index : 0);
}
}
@@ -2541,16 +2552,18 @@ void QDeclarativeListView::incrementCurrentIndex()
Decrements the current index. The current index will wrap
if keyNavigationWraps is true and it is currently at the beginning.
+ This method has no effect if the \l count is zero.
\bold Note: methods should only be called after the Component has completed.
*/
void QDeclarativeListView::decrementCurrentIndex()
{
Q_D(QDeclarativeListView);
- if (currentIndex() > 0 || d->wrap) {
+ int count = d->model ? d->model->count() : 0;
+ if (count && (currentIndex() > 0 || d->wrap)) {
d->moveReason = QDeclarativeListViewPrivate::SetIndex;
int index = currentIndex()-1;
- d->updateCurrent(index >= 0 ? index : d->model->count()-1);
+ d->updateCurrent((index >= 0 && index < count) ? index : count-1);
}
}
@@ -2684,7 +2697,7 @@ void QDeclarativeListView::componentComplete()
if (d->isValid()) {
refill();
d->moveReason = QDeclarativeListViewPrivate::SetIndex;
- if (d->currentIndex < 0)
+ if (d->currentIndex < 0 && !d->currentIndexSet)
d->updateCurrent(0);
else
d->updateCurrent(d->currentIndex);
@@ -2790,7 +2803,7 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count)
if (d->currentItem)
d->currentItem->index = d->currentIndex;
emit currentIndexChanged();
- } else if (d->currentIndex < 0) {
+ } else if (d->currentIndex < 0 && !d->currentIndexSet) {
d->updateCurrent(0);
}
d->itemCount += count;
diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp
index 308aefa..0717b78 100644
--- a/src/declarative/graphicsitems/qdeclarativetext.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetext.cpp
@@ -270,6 +270,7 @@ void QDeclarativeTextPrivate::updateSize()
internalWidthUpdate = false;
q->setImplicitHeight(size.height());
emit q->paintedSizeChanged();
+ q->update();
}
/*!
@@ -1143,9 +1144,10 @@ QRectF QDeclarativeText::boundingRect() const
void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QDeclarativeText);
- if (!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width() &&
- (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone)) {
-
+ if ((!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width())
+ && (d->wrapMode != QDeclarativeText::NoWrap
+ || d->elideMode != QDeclarativeText::ElideNone
+ || d->hAlign != Qt::AlignLeft)) {
if (d->singleline && d->elideMode != QDeclarativeText::ElideNone && widthValid()) {
// We need to re-elide
d->updateLayout();
diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp
index 5d73d89..a4ecc77 100644
--- a/src/declarative/qml/qdeclarativecompileddata.cpp
+++ b/src/declarative/qml/qdeclarativecompileddata.cpp
@@ -205,7 +205,7 @@ const QMetaObject *QDeclarativeCompiledData::TypeReference::metaObject() const
return type->metaObject();
} else {
Q_ASSERT(component);
- return static_cast<QDeclarativeComponentPrivate *>(QObjectPrivate::get(component))->cc->root;
+ return component->root;
}
}
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 74bc5bd..b2740b8 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -590,7 +590,7 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
COMPILE_EXCEPTION(parserRef->refObjects.first(), err);
}
} else if (tref.typeData) {
- ref.component = tref.typeData->component();
+ ref.component = tref.typeData->compiledData();
ref.ref = tref.typeData;
ref.ref->addref();
}
@@ -722,7 +722,7 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt)
obj->metatype = tr.metaObject();
if (tr.component)
- obj->url = tr.component->url();
+ obj->url = tr.component->url;
if (tr.type)
obj->typeName = tr.type->qmlTypeName();
obj->className = tr.className;
@@ -940,7 +940,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj)
// ### Surely the creation of this property cache could be more efficient
QDeclarativePropertyCache *propertyCache = 0;
if (tr.component)
- propertyCache = QDeclarativeComponentPrivate::get(tr.component)->cc->rootPropertyCache->copy();
+ propertyCache = tr.component->rootPropertyCache->copy();
else
propertyCache = enginePrivate->cache(obj->metaObject()->superClass())->copy();
@@ -957,7 +957,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj)
output->bytecode << meta;
} else if (obj == unitRoot) {
if (tr.component)
- output->rootPropertyCache = QDeclarativeComponentPrivate::get(tr.component)->cc->rootPropertyCache;
+ output->rootPropertyCache = tr.component->rootPropertyCache;
else
output->rootPropertyCache = enginePrivate->cache(obj->metaObject());
diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h
index 89eef09..43a0901 100644
--- a/src/declarative/qml/qdeclarativecompiler_p.h
+++ b/src/declarative/qml/qdeclarativecompiler_p.h
@@ -93,10 +93,11 @@ public:
QByteArray className;
QDeclarativeType *type;
- QDeclarativeComponent *component;
+// QDeclarativeComponent *component;
+ QDeclarativeCompiledData *component;
QDeclarativeRefCount *ref;
- QObject *createInstance(QDeclarativeContextData *, const QBitField &) const;
+ QObject *createInstance(QDeclarativeContextData *, const QBitField &, QList<QDeclarativeError> *) const;
const QMetaObject *metaObject() const;
};
QList<TypeReference> types;
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index cfef9cf..0a2a6db 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -733,48 +733,45 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, cons
return 0;
}
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ return begin(context, creationContext, cc, start, count, &state, 0, bindings);
+}
+
+QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentContext,
+ QDeclarativeContextData *componentCreationContext,
+ QDeclarativeCompiledData *component, int start, int count,
+ ConstructionState *state, QList<QDeclarativeError> *errors,
+ const QBitField &bindings)
+{
+ QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentContext->engine);
+ bool isRoot = !enginePriv->inBeginCreate;
+
+ Q_ASSERT(!isRoot || state); // Either this isn't a root component, or a state data must be provided
+ Q_ASSERT((state != 0) ^ (errors != 0)); // One of state or errors (but not both) must be provided
- bool isRoot = !ep->inBeginCreate;
if (isRoot)
QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
- QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, cc->url);
QDeclarativeContextData *ctxt = new QDeclarativeContextData;
ctxt->isInternal = true;
- ctxt->url = cc->url;
- ctxt->imports = cc->importCache;
+ ctxt->url = component->url;
+ ctxt->imports = component->importCache;
// Nested global imports
- if (creationContext && start != -1)
- ctxt->importedScripts = creationContext->importedScripts;
-
- cc->importCache->addref();
- ctxt->setParent(context);
+ if (componentCreationContext && start != -1)
+ ctxt->importedScripts = componentCreationContext->importedScripts;
- QObject *rv = begin(ctxt, ep, cc, start, count, &state, bindings);
+ component->importCache->addref();
+ ctxt->setParent(parentContext);
- if (ep->isDebugging && rv) {
- if (!context->isInternal)
- context->asQDeclarativeContextPrivate()->instances.append(rv);
- QDeclarativeEngineDebugServer::instance()->objectCreated(engine, rv);
- }
-
- return rv;
-}
-
-QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *ctxt, QDeclarativeEnginePrivate *enginePriv,
- QDeclarativeCompiledData *component, int start, int count,
- ConstructionState *state, const QBitField &bindings)
-{
- bool isRoot = !enginePriv->inBeginCreate;
enginePriv->inBeginCreate = true;
QDeclarativeVME vme;
QObject *rv = vme.run(ctxt, component, start, count, bindings);
- if (vme.isError())
- state->errors = vme.errors();
+ if (vme.isError()) {
+ if(errors) *errors = vme.errors();
+ else state->errors = vme.errors();
+ }
if (isRoot) {
enginePriv->inBeginCreate = false;
@@ -794,6 +791,12 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *ctxt, QDe
enginePriv->inProgressCreations++;
}
+ if (enginePriv->isDebugging && rv) {
+ if (!parentContext->isInternal)
+ parentContext->asQDeclarativeContextPrivate()->instances.append(rv);
+ QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv);
+ }
+
return rv;
}
diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h
index a551cc8..7b30bad 100644
--- a/src/declarative/qml/qdeclarativecomponent_p.h
+++ b/src/declarative/qml/qdeclarativecomponent_p.h
@@ -109,9 +109,10 @@ public:
};
ConstructionState state;
- static QObject *begin(QDeclarativeContextData *ctxt, QDeclarativeEnginePrivate *enginePriv,
- QDeclarativeCompiledData *component, int start, int count,
- ConstructionState *state, const QBitField &bindings = QBitField());
+ static QObject *begin(QDeclarativeContextData *parentContext, QDeclarativeContextData *componentCreationContext,
+ QDeclarativeCompiledData *component, int start, int count,
+ ConstructionState *state, QList<QDeclarativeError> *errors,
+ const QBitField &bindings = QBitField());
static void beginDeferred(QDeclarativeEnginePrivate *enginePriv, QObject *object,
ConstructionState *state);
static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state);
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
index 61a1f55..ea92111 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
@@ -838,9 +838,19 @@ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::
{
MethodData *method = static_cast<MethodData *>(o);
- if (method->data.flags & QDeclarativePropertyCache::Data::HasArguments) {
+ if (method->data.relatedIndex == -1)
+ return callPrecise(method->object, method->data, ctxt);
+ else
+ return callOverloaded(method, ctxt);
+}
- QMetaMethod m = method->object->metaObject()->method(method->data.coreIndex);
+QDeclarativeObjectMethodScriptClass::Value
+QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
+ QScriptContext *ctxt)
+{
+ if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
+
+ QMetaMethod m = object->metaObject()->method(data.coreIndex);
QList<QByteArray> argTypeNames = m.parameterTypes();
QVarLengthArray<int, 9> argTypes(argTypeNames.count());
@@ -848,7 +858,7 @@ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::
for (int ii = 0; ii < argTypeNames.count(); ++ii) {
argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
if (argTypes[ii] == QVariant::Invalid)
- argTypes[ii] = enumType(method->object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
+ argTypes[ii] = enumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
if (argTypes[ii] == QVariant::Invalid)
return Value(ctxt, ctxt->throwError(QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)))));
}
@@ -856,39 +866,301 @@ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::
if (argTypes.count() > ctxt->argumentCount())
return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments")));
- QVarLengthArray<MetaCallArgument, 9> args(argTypes.count() + 1);
- args[0].initAsType(method->data.propType, engine);
+ return callMethod(object, data.coreIndex, data.propType, argTypes.count(), argTypes.data(), ctxt);
+
+ } else {
+
+ return callMethod(object, data.coreIndex, data.propType, 0, 0, ctxt);
+
+ }
+}
+
+QDeclarativeObjectMethodScriptClass::Value
+QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index,
+ int returnType, int argCount, int *argTypes,
+ QScriptContext *ctxt)
+{
+ if (argCount > 0) {
- for (int ii = 0; ii < argTypes.count(); ++ii)
+ QVarLengthArray<MetaCallArgument, 9> args(argCount + 1);
+ args[0].initAsType(returnType, engine);
+
+ for (int ii = 0; ii < argCount; ++ii)
args[ii + 1].fromScriptValue(argTypes[ii], engine, ctxt->argument(ii));
QVarLengthArray<void *, 9> argData(args.count());
for (int ii = 0; ii < args.count(); ++ii)
argData[ii] = args[ii].dataPtr();
- QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, argData.data());
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
return args[0].toValue(engine);
- } else if (method->data.propType != 0) {
-
+ } else if (returnType != 0) {
+
MetaCallArgument arg;
- arg.initAsType(method->data.propType, engine);
+ arg.initAsType(returnType, engine);
void *args[] = { arg.dataPtr() };
- QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args);
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
return arg.toValue(engine);
} else {
void *args[] = { 0 };
- QMetaObject::metacall(method->object, QMetaObject::InvokeMetaMethod, method->data.coreIndex, args);
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
return Value();
}
- return Value();
+}
+
+/*!
+Resolve the overloaded method to call. The algorithm works conceptually like this:
+ 1. Resolve the set of overloads it is *possible* to call.
+ Impossible overloads include those that have too many parameters or have parameters
+ of unknown type.
+ 2. Filter the set of overloads to only contain those with the closest number of
+ parameters.
+ For example, if we are called with 3 parameters and there are 2 overloads that
+ take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
+ 3. Find the best remaining overload based on its match score.
+ If two or more overloads have the same match score, call the last one. The match
+ score is constructed by adding the matchScore() result for each of the parameters.
+*/
+QDeclarativeObjectMethodScriptClass::Value
+QDeclarativeObjectMethodScriptClass::callOverloaded(MethodData *method, QScriptContext *ctxt)
+{
+ int argumentCount = ctxt->argumentCount();
+
+ QDeclarativePropertyCache::Data *best = 0;
+ int bestParameterScore = INT_MAX;
+ int bestMatchScore = INT_MAX;
+
+ QDeclarativePropertyCache::Data dummy;
+ QDeclarativePropertyCache::Data *attempt = &method->data;
+
+ do {
+ QList<QByteArray> methodArgTypeNames;
+
+ if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
+ methodArgTypeNames = method->object->metaObject()->method(attempt->coreIndex).parameterTypes();
+
+ int methodArgumentCount = methodArgTypeNames.count();
+
+ if (methodArgumentCount > argumentCount)
+ continue; // We don't have sufficient arguments to call this method
+
+ int methodParameterScore = argumentCount - methodArgumentCount;
+ if (methodParameterScore > bestParameterScore)
+ continue; // We already have a better option
+
+ int methodMatchScore = 0;
+ QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
+
+ bool unknownArgument = false;
+ for (int ii = 0; ii < methodArgumentCount; ++ii) {
+ methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
+ if (methodArgTypes[ii] == QVariant::Invalid)
+ methodArgTypes[ii] = enumType(method->object->metaObject(),
+ QString::fromLatin1(methodArgTypeNames.at(ii)));
+ if (methodArgTypes[ii] == QVariant::Invalid) {
+ unknownArgument = true;
+ break;
+ }
+ methodMatchScore += matchScore(ctxt->argument(ii), methodArgTypes[ii], methodArgTypeNames.at(ii));
+ }
+ if (unknownArgument)
+ continue; // We don't understand all the parameters
+
+ if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
+ best = attempt;
+ bestParameterScore = methodParameterScore;
+ bestMatchScore = methodMatchScore;
+ }
+
+ if (bestParameterScore == 0 && bestMatchScore == 0)
+ break; // We can't get better than that
+
+ } while((attempt = relatedMethod(method->object, attempt, dummy)) != 0);
+
+ if (best) {
+ return callPrecise(method->object, *best, ctxt);
+ } else {
+ QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
+ QDeclarativePropertyCache::Data *candidate = &method->data;
+ while (candidate) {
+ error += QLatin1String("\n ") + QString::fromUtf8(method->object->metaObject()->method(candidate->coreIndex).signature());
+ candidate = relatedMethod(method->object, candidate, dummy);
+ }
+ return Value(ctxt, ctxt->throwError(error));
+ }
+}
+
+/*!
+ Returns the match score for converting \a actual to be of type \a conversionType. A
+ zero score means "perfect match" whereas a higher score is worse.
+
+ The conversion table is copied out of the QtScript callQtMethod() function.
+*/
+int QDeclarativeObjectMethodScriptClass::matchScore(const QScriptValue &actual, int conversionType,
+ const QByteArray &conversionTypeName)
+{
+ if (actual.isNumber()) {
+ switch (conversionType) {
+ case QMetaType::Double:
+ return 0;
+ case QMetaType::Float:
+ return 1;
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ return 2;
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ return 3;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ return 4;
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ return 5;
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ return 6;
+ default:
+ return 10;
+ }
+ } else if (actual.isString()) {
+ switch (conversionType) {
+ case QMetaType::QString:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual.isBoolean()) {
+ switch (conversionType) {
+ case QMetaType::Bool:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual.isDate()) {
+ switch (conversionType) {
+ case QMetaType::QDateTime:
+ return 0;
+ case QMetaType::QDate:
+ return 1;
+ case QMetaType::QTime:
+ return 2;
+ default:
+ return 10;
+ }
+ } else if (actual.isRegExp()) {
+ switch (conversionType) {
+ case QMetaType::QRegExp:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual.isVariant()) {
+ if (conversionType == qMetaTypeId<QVariant>())
+ return 0;
+ else if (actual.toVariant().userType() == conversionType)
+ return 0;
+ else
+ return 10;
+ } else if (actual.isArray()) {
+ switch (conversionType) {
+ case QMetaType::QStringList:
+ case QMetaType::QVariantList:
+ return 5;
+ default:
+ return 10;
+ }
+ } else if (actual.isQObject()) {
+ switch (conversionType) {
+ case QMetaType::QObjectStar:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual.isNull()) {
+ switch (conversionType) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ return 0;
+ default:
+ if (!conversionTypeName.endsWith('*'))
+ return 10;
+ else
+ return 0;
+ }
+ } else {
+ return 10;
+ }
+}
+
+static inline int QMetaObject_methods(const QMetaObject *metaObject)
+{
+ struct Private
+ {
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ };
+
+ return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
+}
+
+static QByteArray QMetaMethod_name(const QMetaMethod &m)
+{
+ QByteArray sig = m.signature();
+ int paren = sig.indexOf('(');
+ if (paren == -1)
+ return sig;
+ else
+ return sig.left(paren);
+}
+
+/*!
+Returns the next related method, if one, or 0.
+*/
+QDeclarativePropertyCache::Data *
+QDeclarativeObjectMethodScriptClass::relatedMethod(QObject *object, QDeclarativePropertyCache::Data *current,
+ QDeclarativePropertyCache::Data &dummy)
+{
+ QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
+ if (current->relatedIndex == -1)
+ return 0;
+
+ if (cache) {
+ return cache->method(current->relatedIndex);
+ } else {
+ const QMetaObject *mo = object->metaObject();
+ int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
+
+ while (methodOffset > current->relatedIndex) {
+ mo = mo->superClass();
+ methodOffset -= QMetaObject_methods(mo);
+ }
+
+ QMetaMethod method = mo->method(current->relatedIndex);
+ dummy.load(method);
+
+ // Look for overloaded methods
+ QByteArray methodName = QMetaMethod_name(method);
+ for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
+ if (methodName == QMetaMethod_name(mo->method(ii))) {
+ dummy.relatedIndex = ii;
+ return &dummy;
+ }
+ }
+
+ return &dummy;
+ }
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
index 75e384c..7956c40 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
@@ -65,6 +65,7 @@ class QDeclarativeEngine;
class QScriptContext;
class QScriptEngine;
class QDeclarativeContextData;
+class MethodData;
class Q_AUTOTEST_EXPORT QDeclarativeObjectMethodScriptClass : public QScriptDeclarativeClass
{
@@ -82,6 +83,14 @@ protected:
private:
int enumType(const QMetaObject *, const QString &);
+ Value callPrecise(QObject *, const QDeclarativePropertyCache::Data &, QScriptContext *);
+ Value callOverloaded(MethodData *, QScriptContext *);
+ Value callMethod(QObject *, int index, int returnType, int argCount, int *argTypes, QScriptContext *ctxt);
+
+ int matchScore(const QScriptValue &, int, const QByteArray &);
+ QDeclarativePropertyCache::Data *relatedMethod(QObject *, QDeclarativePropertyCache::Data *current,
+ QDeclarativePropertyCache::Data &dummy);
+
PersistentIdentifier m_connectId;
PersistentIdentifier m_disconnectId;
QScriptValue m_connect;
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 9e1ceb8..91aaaa4 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -93,6 +93,7 @@ void QDeclarativePropertyCache::Data::load(const QMetaProperty &p, QDeclarativeE
void QDeclarativePropertyCache::Data::load(const QMetaMethod &m)
{
coreIndex = m.methodIndex();
+ relatedIndex = -1;
flags |= Data::IsFunction;
if (m.methodType() == QMetaMethod::Signal)
flags |= Data::IsSignal;
@@ -140,15 +141,25 @@ void QDeclarativePropertyCache::clear()
if (indexCache.at(ii)) indexCache.at(ii)->release();
}
+ for (int ii = 0; ii < methodIndexCache.count(); ++ii) {
+ RData *data = methodIndexCache.at(ii);
+ if (data) data->release();
+ }
+
for (StringCache::ConstIterator iter = stringCache.begin();
- iter != stringCache.end(); ++iter)
- (*iter)->release();
+ iter != stringCache.end(); ++iter) {
+ RData *data = (*iter);
+ data->release();
+ }
for (IdentifierCache::ConstIterator iter = identifierCache.begin();
- iter != identifierCache.end(); ++iter)
- (*iter)->release();
+ iter != identifierCache.end(); ++iter) {
+ RData *data = (*iter);
+ data->release();
+ }
indexCache.clear();
+ methodIndexCache.clear();
stringCache.clear();
identifierCache.clear();
}
@@ -202,12 +213,16 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const
{
QDeclarativePropertyCache *cache = new QDeclarativePropertyCache(engine);
cache->indexCache = indexCache;
+ cache->methodIndexCache = methodIndexCache;
cache->stringCache = stringCache;
cache->identifierCache = identifierCache;
for (int ii = 0; ii < indexCache.count(); ++ii) {
if (indexCache.at(ii)) indexCache.at(ii)->addref();
}
+ for (int ii = 0; ii < methodIndexCache.count(); ++ii) {
+ if (methodIndexCache.at(ii)) methodIndexCache.at(ii)->addref();
+ }
for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
(*iter)->addref();
for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter)
@@ -227,19 +242,18 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
indexCache.resize(propCount);
for (int ii = propOffset; ii < propCount; ++ii) {
QMetaProperty p = metaObject->property(ii);
- if (!p.isScriptable())
+ if (!p.isScriptable())
continue;
QString propName = QString::fromUtf8(p.name());
RData *data = new RData;
data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
+ indexCache[ii] = data;
data->load(p, engine);
data->flags |= propertyFlags;
- indexCache[ii] = data;
-
if (stringCache.contains(propName)) {
stringCache[propName]->release();
identifierCache[data->identifier.identifier]->release();
@@ -252,12 +266,13 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
}
int methodCount = metaObject->methodCount();
- int methodOffset = qMax(2, metaObject->methodOffset()); // 2 to block the destroyed signal
+ // 3 to block the destroyed signal and the deleteLater() slot
+ int methodOffset = qMax(3, metaObject->methodOffset());
methodIndexCache.resize(methodCount);
for (int ii = methodOffset; ii < methodCount; ++ii) {
QMetaMethod m = metaObject->method(ii);
- if (m.access() == QMetaMethod::Private)
+ if (m.access() == QMetaMethod::Private)
continue;
QString methodName = QString::fromUtf8(m.signature());
@@ -267,11 +282,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
RData *data = new RData;
data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
-
- if (stringCache.contains(methodName)) {
- stringCache[methodName]->release();
- identifierCache[data->identifier.identifier]->release();
- }
+ methodIndexCache[ii] = data;
data->load(m);
if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method)
@@ -279,14 +290,32 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
else if (m.methodType() == QMetaMethod::Signal)
data->flags |= signalFlags;
- methodIndexCache[ii] = data;
+ if (stringCache.contains(methodName)) {
+ RData *old = stringCache[methodName];
+ // We only overload methods in the same class, exactly like C++
+ if (old->flags & Data::IsFunction && old->coreIndex >= methodOffset)
+ data->relatedIndex = old->coreIndex;
+ stringCache[methodName]->release();
+ identifierCache[data->identifier.identifier]->release();
+ }
stringCache.insert(methodName, data);
identifierCache.insert(data->identifier.identifier, data);
data->addref();
+ data->addref();
}
}
+void QDeclarativePropertyCache::updateRecur(QDeclarativeEngine *engine, const QMetaObject *metaObject)
+{
+ if (!metaObject)
+ return;
+
+ updateRecur(engine, metaObject->superClass());
+
+ append(engine, metaObject);
+}
+
void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaObject *metaObject)
{
Q_ASSERT(engine);
@@ -295,57 +324,11 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb
clear();
- // ### The properties/methods should probably be spliced on a per-metaobject basis
- int propCount = metaObject->propertyCount();
-
- indexCache.resize(propCount);
- for (int ii = propCount - 1; ii >= 0; --ii) {
- QMetaProperty p = metaObject->property(ii);
- if (!p.isScriptable()) {
- indexCache[ii] = 0;
- continue;
- }
- QString propName = QString::fromUtf8(p.name());
-
- RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
-
- data->load(p, engine);
-
- indexCache[ii] = data;
-
- if (stringCache.contains(propName))
- continue;
-
- stringCache.insert(propName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
- data->addref();
- }
-
- int methodCount = metaObject->methodCount();
- for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot
- QMetaMethod m = metaObject->method(ii);
- if (m.access() == QMetaMethod::Private)
- continue;
- QString methodName = QString::fromUtf8(m.signature());
-
- int parenIdx = methodName.indexOf(QLatin1Char('('));
- Q_ASSERT(parenIdx != -1);
- methodName = methodName.left(parenIdx);
-
- if (stringCache.contains(methodName))
- continue;
+ // Optimization to prevent unnecessary reallocation of lists
+ indexCache.reserve(metaObject->propertyCount());
+ methodIndexCache.reserve(metaObject->methodCount());
- RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
-
- data->load(m);
-
- stringCache.insert(methodName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
- }
+ updateRecur(engine,metaObject);
}
QDeclarativePropertyCache::Data *
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 79b126d..922010d 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -96,7 +96,7 @@ public:
IsVMEFunction = 0x00000400,
HasArguments = 0x00000800,
IsSignal = 0x00001000,
- IsVMESignal = 0x00002000,
+ IsVMESignal = 0x00002000
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -105,7 +105,10 @@ public:
Flags flags;
int propType;
int coreIndex;
- int notifyIndex;
+ union {
+ int notifyIndex; // When !IsFunction
+ int relatedIndex; // When IsFunction
+ };
static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0);
void load(const QMetaProperty &, QDeclarativeEngine *engine = 0);
@@ -152,6 +155,8 @@ private:
typedef QHash<QString, RData *> StringCache;
typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+ void updateRecur(QDeclarativeEngine *, const QMetaObject *);
+
QDeclarativeEngine *engine;
IndexCache indexCache;
IndexCache methodIndexCache;
diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp
index c8e1a07..c015519 100644
--- a/src/declarative/qml/qdeclarativetypeloader.cpp
+++ b/src/declarative/qml/qdeclarativetypeloader.cpp
@@ -719,7 +719,7 @@ void QDeclarativeTypeLoader::clearCache()
QDeclarativeTypeData::QDeclarativeTypeData(const QUrl &url, QDeclarativeTypeLoader::Options options,
QDeclarativeTypeLoader *manager)
: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_typesResolved(false),
- m_compiledData(0), m_component(0), m_typeLoader(manager)
+ m_compiledData(0), m_typeLoader(manager)
{
}
@@ -768,23 +768,6 @@ QDeclarativeCompiledData *QDeclarativeTypeData::compiledData() const
return m_compiledData;
}
-QDeclarativeComponent *QDeclarativeTypeData::component() const
-{
- if (!m_component) {
-
- if (m_compiledData) {
- m_component = new QDeclarativeComponent(typeLoader()->engine(), m_compiledData, -1, -1, 0);
- } else {
- m_component = new QDeclarativeComponent(typeLoader()->engine());
- QDeclarativeComponentPrivate::get(m_component)->url = finalUrl();
- QDeclarativeComponentPrivate::get(m_component)->state.errors = errors();
- }
-
- }
-
- return m_component;
-}
-
void QDeclarativeTypeData::registerCallback(TypeDataCallback *callback)
{
Q_ASSERT(!m_callbacks.contains(callback));
diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h
index 7381f28..718537a 100644
--- a/src/declarative/qml/qdeclarativetypeloader_p.h
+++ b/src/declarative/qml/qdeclarativetypeloader_p.h
@@ -243,7 +243,6 @@ public:
const QList<ScriptReference> &resolvedScripts() const;
QDeclarativeCompiledData *compiledData() const;
- QDeclarativeComponent *component() const;
// Used by QDeclarativeComponent to get notifications
struct TypeDataCallback {
@@ -278,7 +277,6 @@ private:
bool m_typesResolved:1;
QDeclarativeCompiledData *m_compiledData;
- mutable QDeclarativeComponent *m_component;
QList<TypeDataCallback *> m_callbacks;
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 360186c..db90aff 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -185,12 +185,9 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
bindings = bindings.united(bindingSkipList);
QObject *o =
- types.at(instr.create.type).createInstance(ctxt, bindings);
+ types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors);
if (!o) {
- if(types.at(instr.create.type).component)
- vmeErrors << types.at(instr.create.type).component->errors();
-
VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)));
}
@@ -933,8 +930,9 @@ QList<QDeclarativeError> QDeclarativeVME::errors() const
}
QObject *
-QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
- const QBitField &bindings) const
+QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
+ const QBitField &bindings,
+ QList<QDeclarativeError> *errors) const
{
if (type) {
QObject *rv = 0;
@@ -948,7 +946,7 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData
return rv;
} else {
Q_ASSERT(component);
- return QDeclarativeComponentPrivate::get(component)->create(ctxt, bindings);
+ return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, -1, 0, errors, bindings);
}
}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml b/tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml
new file mode 100644
index 0000000..7deb84a
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml
@@ -0,0 +1,10 @@
+import Qt.test 1.0
+import QtQuick 1.0
+
+MyDerivedObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ test = intProperty()
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
index 810a0f7..94135f9 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
@@ -109,6 +109,7 @@ void registerTypes()
qmlRegisterExtendedType<MyBaseExtendedObject, BaseExtensionObject>("Qt.test", 1,0, "MyBaseExtendedObject");
qmlRegisterExtendedType<MyExtendedObject, ExtensionObject>("Qt.test", 1,0, "MyExtendedObject");
qmlRegisterType<MyTypeObject>("Qt.test", 1,0, "MyTypeObject");
+ qmlRegisterType<MyDerivedObject>("Qt.test", 1,0, "MyDerivedObject");
qmlRegisterType<NumberAssignment>("Qt.test", 1,0, "NumberAssignment");
qmlRegisterExtendedType<DefaultPropertyExtendedObject, DefaultPropertyExtensionObject>("Qt.test", 1,0, "DefaultPropertyExtendedObject");
qmlRegisterType<OverrideDefaultPropertyObject>("Qt.test", 1,0, "OverrideDefaultPropertyObject");
diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
index 220318d..40451c3 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
+++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
@@ -562,8 +562,27 @@ signals:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
+class MyDerivedObject : public MyTypeObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE bool intProperty() const {
+ return true;
+ }
+};
+
Q_DECLARE_METATYPE(QScriptValue);
-class MyInvokableObject : public QObject
+class MyInvokableBaseObject : public QObject
+{
+ Q_OBJECT
+public:
+ inline ~MyInvokableBaseObject() = 0;
+
+ Q_INVOKABLE inline void method_inherited(int a);
+ Q_INVOKABLE inline void method_overload();
+};
+
+class MyInvokableObject : public MyInvokableBaseObject
{
Q_OBJECT
Q_ENUMS(TestEnum)
@@ -599,16 +618,34 @@ public:
Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; }
Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; }
+ Q_INVOKABLE void method_overload(QString a) { invoke(18); m_actuals << a; }
- Q_INVOKABLE void method_with_enum(TestEnum e) { invoke(18); m_actuals << (int)e; }
+ Q_INVOKABLE void method_with_enum(TestEnum e) { invoke(19); m_actuals << (int)e; }
+
+ Q_INVOKABLE int method_default(int a, int b = 19) { invoke(20); m_actuals << a << b; return b; }
private:
+ friend class MyInvokableBaseObject;
void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;}
int m_invoked;
bool m_invokedError;
QVariantList m_actuals;
};
+MyInvokableBaseObject::~MyInvokableBaseObject() {}
+
+void MyInvokableBaseObject::method_inherited(int a)
+{
+ static_cast<MyInvokableObject *>(this)->invoke(-3);
+ static_cast<MyInvokableObject *>(this)->m_actuals << a;
+}
+
+// This is a hidden overload of the MyInvokableObject::method_overload() method
+void MyInvokableBaseObject::method_overload()
+{
+ static_cast<MyInvokableObject *>(this)->invoke(-2);
+}
+
class NumberAssignment : public QObject
{
Q_OBJECT
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 02832f3..e4e5a54 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -139,6 +139,7 @@ private slots:
void strictlyEquals();
void compiled();
void numberAssignment();
+ void propertySplicing();
void bug1();
void bug2();
@@ -1709,7 +1710,6 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().at(0), QVariant(44));
QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
- // Test overloads - QML will always invoke the *last* method
o.reset();
QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
QCOMPARE(o.error(), false);
@@ -1717,10 +1717,11 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().count(), 0);
o.reset();
- QCOMPARE(engine->evaluate("object.method_overload(10)").isError(), true);
+ QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
QCOMPARE(o.error(), false);
- QCOMPARE(o.invoked(), -1);
- QCOMPARE(o.actuals().count(), 0);
+ QCOMPARE(o.invoked(), 16);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
o.reset();
QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
@@ -1731,10 +1732,40 @@ void tst_qdeclarativeecmascript::callQtInvokables()
QCOMPARE(o.actuals().at(1), QVariant(11));
o.reset();
- QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
+ QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
QCOMPARE(o.error(), false);
QCOMPARE(o.invoked(), 18);
QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 19);
+ QCOMPARE(o.actuals().count(), 1);
+ QCOMPARE(o.actuals().at(0), QVariant(9));
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 20);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+ QCOMPARE(o.actuals().at(1), QVariant(19));
+
+ o.reset();
+ QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), 20);
+ QCOMPARE(o.actuals().count(), 2);
+ QCOMPARE(o.actuals().at(0), QVariant(10));
+ QCOMPARE(o.actuals().at(1), QVariant(13));
+
+ o.reset();
+ QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
+ QCOMPARE(o.error(), false);
+ QCOMPARE(o.invoked(), -3);
+ QCOMPARE(o.actuals().count(), 1);
QCOMPARE(o.actuals().at(0), QVariant(9));
}
@@ -2175,6 +2206,18 @@ void tst_qdeclarativeecmascript::numberAssignment()
delete object;
}
+void tst_qdeclarativeecmascript::propertySplicing()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
// Test that assigning a null object works
// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
void tst_qdeclarativeecmascript::nullObjectBinding()
diff --git a/tests/auto/declarative/qdeclarativegridview/data/gridview-noCurrent.qml b/tests/auto/declarative/qdeclarativegridview/data/gridview-noCurrent.qml
new file mode 100644
index 0000000..1189649
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativegridview/data/gridview-noCurrent.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+
+Rectangle {
+ property int current: grid.currentIndex
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ width: 80
+ height: 60
+ border.color: "blue"
+ Text {
+ text: index
+ }
+ Text {
+ x: 40
+ text: wrapper.x + ", " + wrapper.y
+ }
+ Text {
+ y: 20
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ y: 40
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ color: GridView.isCurrentItem ? "lightsteelblue" : "white"
+ }
+ }
+ ]
+ GridView {
+ id: grid
+ objectName: "grid"
+ focus: true
+ width: 240
+ height: 320
+ currentIndex: -1
+ cellWidth: 80
+ cellHeight: 60
+ delegate: myDelegate
+ model: testModel
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
index f7acd87..327bba2 100644
--- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
+++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
@@ -71,6 +71,7 @@ private slots:
void moved();
void changeFlow();
void currentIndex();
+ void noCurrentIndex();
void defaultValues();
void properties();
void propertyChanges();
@@ -696,9 +697,51 @@ void tst_QDeclarativeGridView::currentIndex()
model.insertItem(0, "Foo", "1111");
QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
+ // check removing highlight by setting currentIndex to -1;
+ gridview->setCurrentIndex(-1);
+
+ QCOMPARE(gridview->currentIndex(), -1);
+ QVERIFY(!gridview->highlightItem());
+ QVERIFY(!gridview->currentItem());
+
delete canvas;
}
+void tst_QDeclarativeGridView::noCurrentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 60; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QDeclarativeView *canvas = new QDeclarativeView(0);
+ canvas->setFixedSize(240,320);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QString filename(SRCDIR "/data/gridview-noCurrent.qml");
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
+ QVERIFY(gridview != 0);
+
+ QDeclarativeItem *contentItem = gridview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ // current index should be -1
+ QCOMPARE(gridview->currentIndex(), -1);
+ QVERIFY(!gridview->currentItem());
+ QVERIFY(!gridview->highlightItem());
+ QCOMPARE(gridview->contentY(), 0.0);
+
+ gridview->setCurrentIndex(5);
+ QCOMPARE(gridview->currentIndex(), 5);
+ QVERIFY(gridview->currentItem());
+ QVERIFY(gridview->highlightItem());
+}
+
void tst_QDeclarativeGridView::changeFlow()
{
QDeclarativeView *canvas = createView();
diff --git a/tests/auto/declarative/qdeclarativelistview/data/listview-noCurrent.qml b/tests/auto/declarative/qdeclarativelistview/data/listview-noCurrent.qml
new file mode 100644
index 0000000..1997010
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelistview/data/listview-noCurrent.qml
@@ -0,0 +1,50 @@
+import QtQuick 1.0
+
+Rectangle {
+ property int current: list.currentIndex
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ height: 20
+ width: 240
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 120
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ color: ListView.isCurrentItem ? "lightsteelblue" : "white"
+ }
+ }
+ ]
+ ListView {
+ id: list
+ objectName: "list"
+ focus: true
+ currentIndex: -1
+ width: 240
+ height: 320
+ delegate: myDelegate
+ highlightMoveSpeed: 1000
+ model: testModel
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
index 2649c0d..080631c 100644
--- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
+++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
@@ -85,6 +85,7 @@ private slots:
void itemList();
void currentIndex();
+ void noCurrentIndex();
void enforceRange();
void spacing();
void sections();
@@ -1087,9 +1088,52 @@ void tst_QDeclarativeListView::currentIndex()
model.insertItem(0, "Foo", "1111");
QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
+ // check removing highlight by setting currentIndex to -1;
+ listview->setCurrentIndex(-1);
+
+ QCOMPARE(listview->currentIndex(), -1);
+ QVERIFY(!listview->highlightItem());
+ QVERIFY(!listview->currentItem());
+
delete canvas;
}
+void tst_QDeclarativeListView::noCurrentIndex()
+{
+ TestModel model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i));
+
+ QDeclarativeView *canvas = new QDeclarativeView(0);
+ canvas->setFixedSize(240,320);
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ QString filename(SRCDIR "/data/listview-noCurrent.qml");
+ canvas->setSource(QUrl::fromLocalFile(filename));
+
+ qApp->processEvents();
+
+ QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ // current index should be -1 at startup
+ // and we should not have a currentItem or highlightItem
+ QCOMPARE(listview->currentIndex(), -1);
+ QCOMPARE(listview->contentY(), 0.0);
+ QVERIFY(!listview->highlightItem());
+ QVERIFY(!listview->currentItem());
+
+ listview->setCurrentIndex(2);
+ QCOMPARE(listview->currentIndex(), 2);
+ QVERIFY(listview->highlightItem());
+ QVERIFY(listview->currentItem());
+}
+
void tst_QDeclarativeListView::itemList()
{
QDeclarativeView *canvas = createView();
diff --git a/tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties.qml b/tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties.qml
new file mode 100644
index 0000000..8cd5763
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties.qml
@@ -0,0 +1,17 @@
+import QtQuick 1.0
+
+ListView {
+ model: myModel
+ delegate: Item {
+ objectName: "delegate"
+ property variant test1: name
+ property variant test2: model.name
+ property variant test3: modelData
+ property variant test4: model.modelData
+ property variant test5: modelData.name
+ property variant test6: model
+ property variant test7: index
+ property variant test8: model.index
+ property variant test9: model.modelData.name
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties2.qml b/tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties2.qml
new file mode 100644
index 0000000..67721c9
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativevisualdatamodel/data/modelproperties2.qml
@@ -0,0 +1,17 @@
+import QtQuick 1.0
+
+ListView {
+ model: myModel
+ delegate: Item {
+ objectName: "delegate"
+ property variant test1: display
+ property variant test2: model.display
+ property variant test3: modelData
+ property variant test4: model.modelData
+ property variant test5: modelData.display
+ property variant test6: model
+ property variant test7: index
+ property variant test8: model.index
+ property variant test9: model.modelData.display
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp b/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp
index d73a872..0aad099 100644
--- a/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp
+++ b/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp
@@ -120,6 +120,7 @@ private slots:
void childChanged();
void objectListModel();
void singleRole();
+ void modelProperties();
private:
QDeclarativeEngine engine;
@@ -364,6 +365,113 @@ void tst_qdeclarativevisualdatamodel::singleRole()
}
}
+void tst_qdeclarativevisualdatamodel::modelProperties()
+{
+ {
+ QDeclarativeView view;
+
+ SingleRoleModel model;
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", &model);
+
+ view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
+ QCOMPARE(delegate->property("test1").toString(),QString("two"));
+ QCOMPARE(delegate->property("test2").toString(),QString("two"));
+ QCOMPARE(delegate->property("test3").toString(),QString("two"));
+ QCOMPARE(delegate->property("test4").toString(),QString("two"));
+ QVERIFY(!delegate->property("test9").isValid());
+ QCOMPARE(delegate->property("test5").toString(),QString(""));
+ QVERIFY(delegate->property("test6").value<QObject*>() != 0);
+ QCOMPARE(delegate->property("test7").toInt(),1);
+ QCOMPARE(delegate->property("test8").toInt(),1);
+ }
+
+ {
+ QDeclarativeView view;
+
+ QList<QObject*> dataList;
+ dataList.append(new DataObject("Item 1", "red"));
+ dataList.append(new DataObject("Item 2", "green"));
+ dataList.append(new DataObject("Item 3", "blue"));
+ dataList.append(new DataObject("Item 4", "yellow"));
+
+ QDeclarativeContext *ctxt = view.rootContext();
+ ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
+
+ view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
+ QCOMPARE(delegate->property("test1").toString(),QString("Item 2"));
+ QEXPECT_FAIL("", "QTBUG-13576", Continue);
+ QCOMPARE(delegate->property("test2").toString(),QString("Item 2"));
+ QVERIFY(qobject_cast<DataObject*>(delegate->property("test3").value<QObject*>()) != 0);
+ QVERIFY(qobject_cast<DataObject*>(delegate->property("test4").value<QObject*>()) != 0);
+ QCOMPARE(delegate->property("test5").toString(),QString("Item 2"));
+ QCOMPARE(delegate->property("test9").toString(),QString("Item 2"));
+ QVERIFY(delegate->property("test6").value<QObject*>() != 0);
+ QCOMPARE(delegate->property("test7").toInt(),1);
+ QCOMPARE(delegate->property("test8").toInt(),1);
+ }
+
+ {
+ QDeclarativeView view;
+
+ QStandardItemModel model;
+ initStandardTreeModel(&model);
+
+ view.rootContext()->setContextProperty("myModel", &model);
+
+ QUrl source(QUrl::fromLocalFile(SRCDIR "/data/modelproperties2.qml"));
+
+ //3 items, 3 warnings each
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
+ QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
+
+ view.setSource(source);
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
+ QVERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem != 0);
+
+ QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
+ QCOMPARE(delegate->property("test1").toString(),QString("Row 2 Item"));
+ QCOMPARE(delegate->property("test2").toString(),QString("Row 2 Item"));
+ QVERIFY(!delegate->property("test3").isValid());
+ QVERIFY(!delegate->property("test4").isValid());
+ QVERIFY(!delegate->property("test5").isValid());
+ QVERIFY(!delegate->property("test9").isValid());
+ QVERIFY(delegate->property("test6").value<QObject*>() != 0);
+ QCOMPARE(delegate->property("test7").toInt(),1);
+ QCOMPARE(delegate->property("test8").toInt(),1);
+ }
+
+ //### should also test QStringList and QVariantList
+}
+
template<typename T>
T *tst_qdeclarativevisualdatamodel::findItem(QGraphicsObject *parent, const QString &objectName, int index)
{
diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/elide2.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/elide2.qml
index edf0cb5..b772982 100644
--- a/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/elide2.qml
+++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/elide2.qml
@@ -5,7 +5,7 @@ Rectangle {
height: 100
Text {
- width: NumberAnimation { from: 500; to: 0; loops: Animation.Infinite; duration: 5000 }
+ NumberAnimation on width { from: 500; to: 0; loops: Animation.Infinite; duration: 5000 }
elide: Text.ElideRight
text: 'Here is some very long text that we should truncate when sizing window'
}
diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/multilength.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/multilength.qml
index 6698421..3ef64ef 100644
--- a/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/multilength.qml
+++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/elide/multilength.qml
@@ -11,7 +11,7 @@ Rectangle {
anchors.centerIn: parent
Text {
id: myText
- width: NumberAnimation { from: 500; to: 0; loops: Animation.Infinite; duration: 1000 }
+ NumberAnimation on width { from: 500; to: 0; loops: Animation.Infinite; duration: 5000 }
elide: "ElideRight"
text: "Brevity is the soul of wit, and tediousness the limbs and outward flourishes.\x9CBrevity is a great charm of eloquence.\x9CBe concise!\x9CSHHHHHHHHHHHHHHHHHHHHHHHHHHHH"
}
diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp
index 5e169d8..9f9eba0 100644
--- a/tools/qml/qmlruntime.cpp
+++ b/tools/qml/qmlruntime.cpp
@@ -1518,6 +1518,7 @@ void QDeclarativeViewer::updateSizeHints(bool initial)
//qWarning() << "USH: R2V: setting free size ";
layout()->setSizeConstraint(QLayout::SetNoConstraint);
layout()->activate();
+ setMinimumSize(QSize(1,1));
setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
canvas->setMinimumSize(QSize(0,0));
canvas->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));