summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2010-02-04 03:39:58 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2010-02-04 03:39:58 (GMT)
commit4c8b9316de5728276d24f2d72599cf9c6534fced (patch)
treeb726d4826db4d98fd355f0c2c8a69229cf790b6a /src/declarative
parent0b8ef5c78b724901cfae343920b3e9e8f4a78fda (diff)
parente1c72879ed2c25819537bc5bbb12569b705ba79f (diff)
downloadQt-4c8b9316de5728276d24f2d72599cf9c6534fced.zip
Qt-4c8b9316de5728276d24f2d72599cf9c6534fced.tar.gz
Qt-4c8b9316de5728276d24f2d72599cf9c6534fced.tar.bz2
Merge branch 'kinetic-declarativeui' of scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable.cpp26
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable_p.h1
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsgridview.cpp182
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsgridview_p.h1
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimage.cpp3
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimage_p.h2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem.cpp10
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem.h3
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview.cpp42
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsloader.cpp10
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspathview.cpp63
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspathview_p_p.h18
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextedit.cpp11
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextinput.cpp10
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp11
-rw-r--r--src/declarative/qml/qmlcompiler.cpp59
-rw-r--r--src/declarative/qml/qmlengine.cpp41
-rw-r--r--src/declarative/qml/qmlengine.h3
-rw-r--r--src/declarative/qml/qmlengine_p.h8
-rw-r--r--src/declarative/qml/qmlexpression.cpp4
-rw-r--r--src/declarative/qml/qmlmoduleplugin.cpp26
-rw-r--r--src/declarative/qml/qmlmoduleplugin.h8
-rw-r--r--src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp14
-rw-r--r--src/declarative/qml/qmlnetworkaccessmanagerfactory.h6
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp6
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h4
-rw-r--r--src/declarative/qml/qmlscript.cpp2
-rw-r--r--src/declarative/qml/qmlscriptclass_p.h2
-rw-r--r--src/declarative/qml/qmlworkerscript.cpp13
-rw-r--r--src/declarative/qml/qmlxmlhttprequest.cpp60
-rw-r--r--src/declarative/util/qmlanimation.cpp2
-rw-r--r--src/declarative/util/qmllistmodel.cpp4
-rw-r--r--src/declarative/util/qmlpixmapcache.cpp257
-rw-r--r--src/declarative/util/qmlpixmapcache_p.h1
34 files changed, 550 insertions, 363 deletions
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
index da031f1..c4edb28 100644
--- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
@@ -819,6 +819,32 @@ void QmlGraphicsFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
}
+void QmlGraphicsFlickable::wheelEvent(QGraphicsSceneWheelEvent *event)
+{
+ Q_D(QmlGraphicsFlickable);
+ if (!d->interactive) {
+ QmlGraphicsItem::wheelEvent(event);
+ } else if (yflick()) {
+ if (event->delta() > 0)
+ d->velocityY = qMax(event->delta() - d->verticalVelocity.value(), qreal(250.0));
+ else
+ d->velocityY = qMin(event->delta() - d->verticalVelocity.value(), qreal(-250.0));
+ d->flicked = false;
+ d->flickY(d->velocityY);
+ event->accept();
+ } else if (xflick()) {
+ if (event->delta() > 0)
+ d->velocityX = qMax(event->delta() - d->horizontalVelocity.value(), qreal(250.0));
+ else
+ d->velocityX = qMin(event->delta() - d->horizontalVelocity.value(), qreal(-250.0));
+ d->flicked = false;
+ d->flickX(d->velocityX);
+ event->accept();
+ } else {
+ QmlGraphicsItem::wheelEvent(event);
+ }
+}
+
void QmlGraphicsFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event)
{
Q_Q(QmlGraphicsFlickable);
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable_p.h b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
index df6f6b1..ea07da4 100644
--- a/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable_p.h
@@ -166,6 +166,7 @@ protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void wheelEvent(QGraphicsSceneWheelEvent *event);
void timerEvent(QTimerEvent *event);
QmlGraphicsFlickableVisibleArea *visibleArea();
diff --git a/src/declarative/graphicsitems/qmlgraphicsgridview.cpp b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
index 2fad3bb..afc2e15 100644
--- a/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
@@ -151,14 +151,14 @@ class QmlGraphicsGridViewPrivate : public QmlGraphicsFlickablePrivate
public:
QmlGraphicsGridViewPrivate()
- : model(0), currentItem(0), flow(QmlGraphicsGridView::LeftToRight)
+ : currentItem(0), flow(QmlGraphicsGridView::LeftToRight)
, visiblePos(0), visibleIndex(0) , currentIndex(-1)
, cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1)
, highlightComponent(0), highlight(0), trackedItem(0)
, moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
, bufferMode(NoBuffer)
, ownModel(false), wrap(false), autoHighlight(true)
- , fixCurrentVisibility(false), lazyRelease(false) {}
+ , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false) {}
void init();
void clear();
@@ -167,6 +167,7 @@ public:
void refill(qreal from, qreal to, bool doBuffer=false);
void updateGrid();
+ void scheduleLayout();
void layout(bool removed=false);
void updateUnrequestedIndexes();
void updateUnrequestedPositions();
@@ -306,7 +307,7 @@ public:
}
}
- QmlGraphicsVisualModel *model;
+ QGuard<QmlGraphicsVisualModel> model;
QVariant modelVariant;
QList<FxGridItem*> visibleItems;
QHash<QmlGraphicsItem*,int> unrequestedItems;
@@ -335,6 +336,7 @@ public:
bool autoHighlight : 1;
bool fixCurrentVisibility : 1;
bool lazyRelease : 1;
+ bool layoutScheduled : 1;
};
void QmlGraphicsGridViewPrivate::init()
@@ -372,6 +374,7 @@ FxGridItem *QmlGraphicsGridViewPrivate::createItem(int modelIndex)
model->completeItem();
listItem->item->setZValue(1);
listItem->item->setParent(q->viewport());
+ unrequestedItems.remove(listItem->item);
}
requestedIndex = 0;
return listItem;
@@ -381,7 +384,7 @@ FxGridItem *QmlGraphicsGridViewPrivate::createItem(int modelIndex)
void QmlGraphicsGridViewPrivate::releaseItem(FxGridItem *item)
{
Q_Q(QmlGraphicsGridView);
- if (!item)
+ if (!item || !model)
return;
if (trackedItem == item) {
QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
@@ -435,7 +438,7 @@ void QmlGraphicsGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
// creating/releasing multiple items in one frame
// while flicking (as much as possible).
while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
- //qDebug() << "refill: append item" << modelIndex;
+// qDebug() << "refill: append item" << modelIndex;
if (!(item = createItem(modelIndex)))
break;
item->setPosition(colPos, rowPos);
@@ -463,7 +466,7 @@ void QmlGraphicsGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
}
colNum = colPos / colSize();
while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
- //qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+// qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
if (!(item = createItem(visibleIndex-1)))
break;
--visibleIndex;
@@ -487,7 +490,7 @@ void QmlGraphicsGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
&& item->endRowPos() < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
if (item->attached->delayRemove())
break;
- //qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
+// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
if (item->index != -1)
visibleIndex++;
visibleItems.removeFirst();
@@ -499,7 +502,7 @@ void QmlGraphicsGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
&& item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
if (item->attached->delayRemove())
break;
- //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
visibleItems.removeLast();
releaseItem(item);
changed = true;
@@ -528,19 +531,27 @@ void QmlGraphicsGridViewPrivate::updateGrid()
}
}
+void QmlGraphicsGridViewPrivate::scheduleLayout()
+{
+ Q_Q(QmlGraphicsGridView);
+ if (!layoutScheduled) {
+ layoutScheduled = true;
+ QMetaObject::invokeMethod(q, "layout", Qt::QueuedConnection);
+ }
+}
+
void QmlGraphicsGridViewPrivate::layout(bool removed)
{
Q_Q(QmlGraphicsGridView);
+ layoutScheduled = false;
if (visibleItems.count()) {
qreal rowPos = visibleItems.first()->rowPos();
qreal colPos = visibleItems.first()->colPos();
- if (visibleIndex % columns != 0) {
+ int col = visibleIndex % columns;
+ if (colPos != col * colSize()) {
if (removed)
rowPos -= rowSize();
- colPos = (visibleIndex % columns) * colSize();
- visibleItems.first()->setPosition(colPos, rowPos);
- } else if (colPos != 0) {
- colPos = 0;
+ colPos = col * colSize();
visibleItems.first()->setPosition(colPos, rowPos);
}
for (int i = 1; i < visibleItems.count(); ++i) {
@@ -555,6 +566,7 @@ void QmlGraphicsGridViewPrivate::layout(bool removed)
}
q->refill();
updateHighlight();
+ moveReason = Other;
if (flow == QmlGraphicsGridView::LeftToRight) {
q->setViewportHeight(endPosition() - startPosition());
fixupY();
@@ -1126,7 +1138,7 @@ void QmlGraphicsGridView::setCacheBuffer(int buffer)
These properties holds the width and height of each cell in the grid
- The default sell size is 100x100.
+ The default cell size is 100x100.
*/
int QmlGraphicsGridView::cellWidth() const
{
@@ -1406,7 +1418,7 @@ void QmlGraphicsGridView::trackedPositionChanged()
Q_D(QmlGraphicsGridView);
if (!d->trackedItem)
return;
- if (!isFlicking() && !d->moving && d->moveReason != QmlGraphicsGridViewPrivate::Mouse) {
+ if (!isFlicking() && !d->moving && d->moveReason == QmlGraphicsGridViewPrivate::SetIndex) {
const qreal viewPos = d->position();
if (d->trackedItem->rowPos() < viewPos && d->currentItem->rowPos() < viewPos) {
d->setPosition(d->currentItem->rowPos() < d->trackedItem->rowPos() ? d->trackedItem->rowPos() : d->currentItem->rowPos());
@@ -1446,12 +1458,12 @@ void QmlGraphicsGridView::itemsInserted(int modelIndex, int count)
// Special case of appending an item to the model.
index = d->visibleIndex + d->visibleItems.count();
} else {
- if (modelIndex + count - 1 < d->visibleIndex) {
+ if (modelIndex <= d->visibleIndex) {
// Insert before visible items
d->visibleIndex += count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxGridItem *listItem = d->visibleItems.at(i);
- if (listItem->index != -1)
+ if (listItem->index != -1 && listItem->index >= modelIndex)
listItem->index += count;
}
}
@@ -1492,71 +1504,25 @@ void QmlGraphicsGridView::itemsInserted(int modelIndex, int count)
}
QList<FxGridItem*> added;
- FxGridItem *firstItem = d->firstVisibleItem();
- if (firstItem && rowPos < firstItem->rowPos()) {
- int from = d->position() - d->buffer;
- int i = 0;
- int insertionIdx = index;
- for (i = insertCount-1; i >= 0 && rowPos > from; --i) {
- int mod = (modelIndex+i) % d->columns;
- while (mod++ < d->columns && modelIndex + i < d->model->count() && i < insertCount) {
- FxGridItem *item = d->createItem(modelIndex + i);
- d->visibleItems.insert(insertionIdx, item);
- item->setPosition(colPos, rowPos);
- added.append(item);
- colPos -= d->colSize();
- if (colPos < 0) {
- colPos = d->colSize() * (d->columns-1);
- rowPos -= d->rowSize();
- }
- ++index;
- ++i;
- }
- }
- if (i >= 0) {
- // If we didn't insert all our new items - anything
- // before the current index is not visible - remove it.
- while (insertionIdx--) {
- FxGridItem *item = d->visibleItems.takeFirst();
- if (item->index != -1)
- d->visibleIndex++;
- d->releaseItem(item);
- }
- } else {
- // adjust pos of items before inserted items.
- for (int i = insertionIdx-1; i >= 0; i--) {
- FxGridItem *gridItem = d->visibleItems.at(i);
- gridItem->setPosition(colPos, rowPos);
- colPos -= d->colSize();
- if (colPos < 0) {
- colPos = d->colSize() * (d->columns-1);
- rowPos -= d->rowSize();
- }
- }
- }
- } else {
- int i = 0;
- for (i = 0; i < insertCount && rowPos + d->rowSize() - 1 <= to; ++i) {
- int mod = (modelIndex+i) % d->columns;
- while (mod++ < d->columns && modelIndex + i < d->model->count() && i < insertCount) {
- FxGridItem *item = d->createItem(modelIndex + i);
- d->visibleItems.insert(index, item);
- item->setPosition(colPos, rowPos);
- added.append(item);
- colPos += d->colSize();
- if (colPos > d->colSize() * (d->columns-1)) {
- colPos = 0;
- rowPos += d->rowSize();
- }
- ++index;
- ++i;
- }
+ int i = 0;
+ while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
+ FxGridItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(colPos, rowPos);
+ added.append(item);
+ colPos += d->colSize();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
}
- if (i < insertCount) {
- // We didn't insert all our new items, which means anything
- // beyond the current index is not visible - remove it.
- while (d->visibleItems.count() > index)
- d->releaseItem(d->visibleItems.takeLast());
+ ++index;
+ ++i;
+ }
+ if (i < insertCount) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index) {
+ d->releaseItem(d->visibleItems.takeLast());
}
}
@@ -1586,32 +1552,7 @@ void QmlGraphicsGridView::itemsRemoved(int modelIndex, int count)
{
Q_D(QmlGraphicsGridView);
bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
- int index = d->mapFromModel(modelIndex);
- if (index == -1) {
- if (modelIndex + count - 1 < d->visibleIndex) {
- // Items removed before our visible items.
- d->visibleIndex -= count;
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxGridItem *listItem = d->visibleItems.at(i);
- if (listItem->index != -1)
- listItem->index -= count;
- }
- }
- if (d->currentIndex >= modelIndex + count) {
- d->currentIndex -= count;
- if (d->currentItem)
- d->currentItem->index -= count;
- } else if (currentRemoved) {
- // current item has been removed.
- d->releaseItem(d->currentItem);
- d->currentItem = 0;
- d->currentIndex = -1;
- d->updateCurrent(qMin(modelIndex, d->model->count()-1));
- }
- d->layout(true);
- emit countChanged();
- return;
- }
+ bool removedVisible = false;
// Remove the items from the visible list, skipping anything already marked for removal
QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
@@ -1619,6 +1560,8 @@ void QmlGraphicsGridView::itemsRemoved(int modelIndex, int count)
FxGridItem *item = *it;
if (item->index == -1 || item->index < modelIndex) {
// already removed, or before removed items
+ if (item->index < modelIndex)
+ removedVisible = true;
++it;
} else if (item->index >= modelIndex + count) {
// after removed items
@@ -1626,6 +1569,7 @@ void QmlGraphicsGridView::itemsRemoved(int modelIndex, int count)
++it;
} else {
// removed item
+ removedVisible = true;
item->attached->emitRemove();
if (item->attached->delayRemove()) {
item->index = -1;
@@ -1659,17 +1603,27 @@ void QmlGraphicsGridView::itemsRemoved(int modelIndex, int count)
}
}
- if (d->visibleItems.isEmpty()) {
- d->visibleIndex = 0;
- d->setPosition(0);
- refill();
- } else {
- // Correct the positioning of the items
- d->layout();
+ if (removedVisible) {
+ if (d->visibleItems.isEmpty()) {
+ d->visibleIndex = 0;
+ d->setPosition(0);
+ refill();
+ } else {
+ // Correct the positioning of the items
+ d->scheduleLayout();
+ }
}
+
emit countChanged();
}
+void QmlGraphicsGridView::layout()
+{
+ Q_D(QmlGraphicsGridView);
+ if (d->layoutScheduled)
+ d->layout();
+}
+
void QmlGraphicsGridView::destroyRemoved()
{
Q_D(QmlGraphicsGridView);
diff --git a/src/declarative/graphicsitems/qmlgraphicsgridview_p.h b/src/declarative/graphicsitems/qmlgraphicsgridview_p.h
index 1615469..d2ef70e 100644
--- a/src/declarative/graphicsitems/qmlgraphicsgridview_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsgridview_p.h
@@ -148,6 +148,7 @@ private Q_SLOTS:
void createdItem(int index, QmlGraphicsItem *item);
void destroyingItem(QmlGraphicsItem *item);
void sizeChange();
+ void layout();
private:
void refill();
diff --git a/src/declarative/graphicsitems/qmlgraphicsimage.cpp b/src/declarative/graphicsitems/qmlgraphicsimage.cpp
index ad43027..a1e8c17 100644
--- a/src/declarative/graphicsitems/qmlgraphicsimage.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsimage.cpp
@@ -128,6 +128,7 @@ QML_DEFINE_TYPE(Qt,4,6,Image,QmlGraphicsImage)
QmlGraphicsImage::QmlGraphicsImage(QmlGraphicsItem *parent)
: QmlGraphicsImageBase(*(new QmlGraphicsImagePrivate), parent)
{
+ connect(this, SIGNAL(sourceChanged(QUrl)), this, SLOT(updatePaintedGeometry()));
}
QmlGraphicsImage::QmlGraphicsImage(QmlGraphicsImagePrivate &dd, QmlGraphicsItem *parent)
@@ -270,6 +271,8 @@ void QmlGraphicsImage::updatePaintedGeometry()
if (d->fillMode == PreserveAspectFit) {
qreal widthScale = width() / qreal(d->pix.width());
qreal heightScale = height() / qreal(d->pix.height());
+ if (!d->pix.width() || !d->pix.height())
+ return;
if (widthScale <= heightScale) {
d->paintedWidth = width();
d->paintedHeight = widthScale * qreal(d->pix.height());
diff --git a/src/declarative/graphicsitems/qmlgraphicsimage_p.h b/src/declarative/graphicsitems/qmlgraphicsimage_p.h
index 36066e1..dde5d79 100644
--- a/src/declarative/graphicsitems/qmlgraphicsimage_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsimage_p.h
@@ -86,6 +86,8 @@ Q_SIGNALS:
protected:
QmlGraphicsImage(QmlGraphicsImagePrivate &dd, QmlGraphicsItem *parent);
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+
+protected Q_SLOTS:
void updatePaintedGeometry();
private:
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
index bd3c1ea..b03f359 100644
--- a/src/declarative/graphicsitems/qmlgraphicsitem.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
@@ -57,6 +57,7 @@
#include <QFile>
#include <QEvent>
#include <QGraphicsSceneMouseEvent>
+#include <QtCore/qnumeric.h>
#include <QtScript/qscriptengine.h>
#include <QtGui/qgraphicstransform.h>
#include <QtGui/qgraphicseffect.h>
@@ -2160,6 +2161,7 @@ QmlGraphicsAnchorLine QmlGraphicsItem::baseline() const
\qmlproperty Item Item::anchors.fill
\qmlproperty Item Item::anchors.centerIn
+ \qmlproperty real Item::anchors.margins
\qmlproperty real Item::anchors.topMargin
\qmlproperty real Item::anchors.bottomMargin
\qmlproperty real Item::anchors.leftMargin
@@ -2172,6 +2174,7 @@ QmlGraphicsAnchorLine QmlGraphicsItem::baseline() const
relationship with other items.
Margins apply to top, bottom, left, right, and fill anchors.
+ The margins property can be used to set all of the various margins at once, to the same value.
Offsets apply for horizontal center, vertical center, and baseline anchors.
@@ -2790,6 +2793,7 @@ void QmlGraphicsItem::setTransformOrigin(TransformOrigin origin)
if (origin != d->origin) {
d->origin = origin;
QGraphicsItem::setTransformOriginPoint(d->computeTransformOrigin());
+ emit transformOriginChanged(d->origin);
}
}
@@ -2842,6 +2846,9 @@ qreal QmlGraphicsItem::width() const
void QmlGraphicsItem::setWidth(qreal w)
{
Q_D(QmlGraphicsItem);
+ if (qIsNaN(w))
+ return;
+
d->widthValid = true;
if (d->width == w)
return;
@@ -2911,6 +2918,9 @@ qreal QmlGraphicsItem::height() const
void QmlGraphicsItem::setHeight(qreal h)
{
Q_D(QmlGraphicsItem);
+ if (qIsNaN(h))
+ return;
+
d->heightValid = true;
if (d->height == h)
return;
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.h b/src/declarative/graphicsitems/qmlgraphicsitem.h
index df8c634..8ae2d5c 100644
--- a/src/declarative/graphicsitems/qmlgraphicsitem.h
+++ b/src/declarative/graphicsitems/qmlgraphicsitem.h
@@ -91,7 +91,7 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsItem : public QGraphicsObject, public QmlP
Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL)
Q_PROPERTY(bool wantsFocus READ wantsFocus NOTIFY wantsFocusChanged)
Q_PROPERTY(QmlList<QGraphicsTransform *>* transform READ transform DESIGNABLE false FINAL)
- Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin NOTIFY transformOriginChanged)
Q_PROPERTY(bool smooth READ smooth WRITE setSmooth)
Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect)
Q_ENUMS(TransformOrigin)
@@ -176,6 +176,7 @@ Q_SIGNALS:
void focusChanged();
void wantsFocusChanged();
void parentChanged();
+ void transformOriginChanged(TransformOrigin);
protected:
bool isComponentComplete() const;
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
index f75833a..8fb7c84 100644
--- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
@@ -210,7 +210,7 @@ class QmlGraphicsListViewPrivate : public QmlGraphicsFlickablePrivate, private Q
public:
QmlGraphicsListViewPrivate()
- : model(0), currentItem(0), orient(QmlGraphicsListView::Vertical)
+ : currentItem(0), orient(QmlGraphicsListView::Vertical)
, visiblePos(0), visibleIndex(0)
, averageSize(100.0), currentIndex(-1), requestedIndex(-1)
, highlightRangeStart(0), highlightRangeEnd(0)
@@ -495,7 +495,7 @@ public:
virtual void flickX(qreal velocity);
virtual void flickY(qreal velocity);
- QmlGraphicsVisualModel *model;
+ QGuard<QmlGraphicsVisualModel> model;
QVariant modelVariant;
QList<FxListItem*> visibleItems;
QHash<QmlGraphicsItem*,int> unrequestedItems;
@@ -605,6 +605,7 @@ FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex)
if (listItem->attached->m_prevSection != listItem->attached->m_section)
createSection(listItem);
}
+ unrequestedItems.remove(listItem->item);
}
requestedIndex = -1;
@@ -614,7 +615,7 @@ FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex)
void QmlGraphicsListViewPrivate::releaseItem(FxListItem *item)
{
Q_Q(QmlGraphicsListView);
- if (!item)
+ if (!item || !model)
return;
if (trackedItem == item) {
const char *notifier1 = orient == QmlGraphicsListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
@@ -731,6 +732,7 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
if (footer)
updateFooter();
updateViewport();
+ updateUnrequestedPositions();
} else if (!doBuffer && buffer && bufferMode != NoBuffer) {
refill(from, to, true);
}
@@ -765,7 +767,6 @@ void QmlGraphicsListViewPrivate::layout()
updateHeader();
if (footer)
updateFooter();
- updateUnrequestedPositions();
updateViewport();
}
@@ -779,14 +780,20 @@ void QmlGraphicsListViewPrivate::updateUnrequestedIndexes()
void QmlGraphicsListViewPrivate::updateUnrequestedPositions()
{
- QHash<QmlGraphicsItem*,int>::const_iterator it;
- for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
- if (visibleItem(*it))
- continue;
- if (orient == QmlGraphicsListView::Vertical)
- it.key()->setY(positionAt(*it));
- else
- it.key()->setX(positionAt(*it));
+ Q_Q(QmlGraphicsListView);
+ if (unrequestedItems.count()) {
+ qreal pos = position();
+ QHash<QmlGraphicsItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ QmlGraphicsItem *item = it.key();
+ if (orient == QmlGraphicsListView::Vertical) {
+ if (item->y() + item->height() > pos && item->y() < pos + q->height())
+ item->setY(positionAt(*it));
+ } else {
+ if (item->x() + item->width() > pos && item->x() < pos + q->width())
+ item->setX(positionAt(*it));
+ }
+ }
}
}
@@ -2114,12 +2121,14 @@ void QmlGraphicsListView::viewportMoved()
const qreal minX = minXExtent();
if ((minX - d->_moveX.value() < height()/2 || d->flickTargetX - d->_moveX.value() < height()/2)
&& minX != d->flickTargetX)
- d->flickX(-d->verticalVelocity.value());
+ d->flickX(-d->horizontalVelocity.value());
+ d->bufferMode = QmlGraphicsListViewPrivate::BufferBefore;
} else if (d->velocityX < 0) {
const qreal maxX = maxXExtent();
if ((d->_moveX.value() - maxX < height()/2 || d->_moveX.value() - d->flickTargetX < height()/2)
&& maxX != d->flickTargetX)
- d->flickX(-d->verticalVelocity.value());
+ d->flickX(-d->horizontalVelocity.value());
+ d->bufferMode = QmlGraphicsListViewPrivate::BufferAfter;
}
}
d->inFlickCorrection = false;
@@ -2399,12 +2408,12 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count)
// Special case of appending an item to the model.
modelIndex = d->visibleIndex + d->visibleItems.count();
} else {
- if (modelIndex + count - 1 < d->visibleIndex) {
+ if (modelIndex < d->visibleIndex) {
// Insert before visible items
d->visibleIndex += count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxListItem *listItem = d->visibleItems.at(i);
- if (listItem->index != -1)
+ if (listItem->index != -1 && listItem->index >= modelIndex)
listItem->index += count;
}
}
@@ -2609,6 +2618,7 @@ void QmlGraphicsListView::destroyRemoved()
void QmlGraphicsListView::itemsMoved(int from, int to, int count)
{
Q_D(QmlGraphicsListView);
+ d->updateUnrequestedIndexes();
if (d->visibleItems.isEmpty()) {
refill();
diff --git a/src/declarative/graphicsitems/qmlgraphicsloader.cpp b/src/declarative/graphicsitems/qmlgraphicsloader.cpp
index bb1020c..7cd4d1a 100644
--- a/src/declarative/graphicsitems/qmlgraphicsloader.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsloader.cpp
@@ -64,8 +64,14 @@ void QmlGraphicsLoaderPrivate::clear()
}
source = QUrl();
- delete item;
- item = 0;
+ if (item) {
+ // We can't delete immediately because our item may have triggered
+ // the Loader to load a different item.
+ item->setVisible(false);
+ static_cast<QGraphicsItem*>(item)->setParentItem(0);
+ item->deleteLater();
+ item = 0;
+ }
}
void QmlGraphicsLoaderPrivate::initResize()
diff --git a/src/declarative/graphicsitems/qmlgraphicspathview.cpp b/src/declarative/graphicsitems/qmlgraphicspathview.cpp
index 112eda2..85e87eb 100644
--- a/src/declarative/graphicsitems/qmlgraphicspathview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicspathview.cpp
@@ -71,9 +71,11 @@ inline qreal qmlMod(qreal x, qreal y)
class QmlGraphicsPathViewAttached : public QObject
{
Q_OBJECT
+
+ Q_PROPERTY(bool onPath READ isOnPath NOTIFY onPathChanged)
public:
QmlGraphicsPathViewAttached(QObject *parent)
- : QObject(parent), mo(new QmlOpenMetaObject(this))
+ : QObject(parent), mo(new QmlOpenMetaObject(this)), onPath(false)
{
}
@@ -91,10 +93,49 @@ public:
mo->setValue(name, val);
}
+ bool isOnPath() const { return onPath; }
+ void setOnPath(bool on) {
+ if (on != onPath) {
+ onPath = on;
+ emit onPathChanged();
+ }
+ }
+
+Q_SIGNALS:
+ void onPathChanged();
+
private:
QmlOpenMetaObject *mo;
+ bool onPath;
};
+
+QmlGraphicsItem *QmlGraphicsPathViewPrivate::getItem(int modelIndex)
+{
+ Q_Q(QmlGraphicsPathView);
+ requestedIndex = modelIndex;
+ QmlGraphicsItem *item = model->item(modelIndex);
+ if (item) {
+ if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
+ static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(true);
+ item->setParentItem(q);
+ }
+ requestedIndex = -1;
+ return item;
+}
+
+void QmlGraphicsPathViewPrivate::releaseItem(QmlGraphicsItem *item)
+{
+ if (!item || !model)
+ return;
+ if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
+ static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(false);
+ if (model->release(item) == 0) {
+ if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
+ static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(false);
+ }
+}
+
/*!
\qmlclass PathView QmlGraphicsPathView
\brief The PathView element lays out model-provided items on a path.
@@ -126,6 +167,26 @@ QmlGraphicsPathView::~QmlGraphicsPathView()
}
/*!
+ \qmlattachedproperty bool PathView::onPath
+ This attached property holds whether the item is currently on the path.
+
+ If a pathItemCount has been set, it is possible that some items may
+ be instantiated, but not considered to be currently on the path.
+ Usually, these items would be set invisible, for example:
+
+ \code
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ ...
+ }
+ }
+ \endcode
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
\qmlproperty model PathView::model
This property holds the model providing data for the view.
diff --git a/src/declarative/graphicsitems/qmlgraphicspathview_p_p.h b/src/declarative/graphicsitems/qmlgraphicspathview_p_p.h
index 7ffe6ac..18cb205 100644
--- a/src/declarative/graphicsitems/qmlgraphicspathview_p_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicspathview_p_p.h
@@ -79,7 +79,7 @@ public:
: path(0), currentIndex(0), startPc(0), lastDist(0)
, lastElapsed(0), stealMouse(false), ownModel(false), activeItem(0)
, snapPos(0), dragMargin(0), moveOffset(this, &QmlGraphicsPathViewPrivate::setOffset)
- , firstIndex(0), pathItems(-1), pathOffset(0), requestedIndex(-1), model(0)
+ , firstIndex(0), pathItems(-1), pathOffset(0), requestedIndex(-1)
, moveReason(Other)
{
fixupOffsetEvent = QmlTimeLineEvent::timeLineEvent<QmlGraphicsPathViewPrivate, &QmlGraphicsPathViewPrivate::fixOffset>(&moveOffset, this);
@@ -95,18 +95,8 @@ public:
q->connect(&tl, SIGNAL(updated()), q, SLOT(ticked()));
}
- QmlGraphicsItem *getItem(int modelIndex) {
- Q_Q(QmlGraphicsPathView);
- requestedIndex = modelIndex;
- QmlGraphicsItem *item = model->item(modelIndex);
- if (item)
- item->setParentItem(q);
- requestedIndex = -1;
- return item;
- }
- void releaseItem(QmlGraphicsItem *item) {
- model->release(item);
- }
+ QmlGraphicsItem *getItem(int modelIndex);
+ void releaseItem(QmlGraphicsItem *item);
bool isValid() const {
return model && model->count() > 0 && model->isValid() && path;
@@ -143,7 +133,7 @@ public:
int pathOffset;
int requestedIndex;
QList<QmlGraphicsItem *> items;
- QmlGraphicsVisualModel *model;
+ QGuard<QmlGraphicsVisualModel> model;
QVariant modelVariant;
enum MovementReason { Other, Key, Mouse };
MovementReason moveReason;
diff --git a/src/declarative/graphicsitems/qmlgraphicstextedit.cpp b/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
index 6e14d3a..c3495b3 100644
--- a/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
@@ -784,8 +784,17 @@ Handles the given mouse \a event.
void QmlGraphicsTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QmlGraphicsTextEdit);
- if (d->focusOnPress)
+ if (d->focusOnPress){
+ QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope?
+ while(p) {
+ if(p->flags() & QGraphicsItem::ItemIsFocusScope){
+ p->setFocus();
+ break;
+ }
+ p = p->parentItem();
+ }
setFocus(true);
+ }
d->control->processEvent(event, QPointF(0, 0));
if (!event->isAccepted())
QmlGraphicsPaintedItem::mousePressEvent(event);
diff --git a/src/declarative/graphicsitems/qmlgraphicstextinput.cpp b/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
index 6068e93..cfb93f6 100644
--- a/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
@@ -647,9 +647,15 @@ void QmlGraphicsTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QmlGraphicsTextInput);
if(d->focusOnPress){
+ QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope?
+ while(p) {
+ if(p->flags() & QGraphicsItem::ItemIsFocusScope){
+ p->setFocus();
+ break;
+ }
+ p = p->parentItem();
+ }
setFocus(true);
- setCursorVisible(true);
- d->focused = true;
}
d->control->processEvent(event);
}
diff --git a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
index 70e3a43..2fc143d 100644
--- a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
@@ -462,7 +462,8 @@ int QmlGraphicsVisualDataModelDataMetaObject::createProperty(const char *name, c
QmlGraphicsVisualDataModelPrivate *model = QmlGraphicsVisualDataModelPrivate::get(data->m_model);
if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
- if (model->m_listAccessor->type() == QmlListAccessor::QmlList) {
+ if (model->m_listAccessor->type() == QmlListAccessor::QmlList
+ || model->m_listAccessor->type() == QmlListAccessor::QListPtr) {
model->ensureRoles();
QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
if (object && object->property(name).isValid())
@@ -724,7 +725,7 @@ void QmlGraphicsVisualDataModel::setModel(const QVariant &model)
}
d->m_listAccessor = new QmlListAccessor;
d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
- if (d->m_listAccessor->type() != QmlListAccessor::QmlList)
+ if (d->m_listAccessor->type() != QmlListAccessor::QmlList && d->m_listAccessor->type() != QmlListAccessor::QListPtr)
d->m_metaDataCacheable = true;
if (d->m_delegate && d->modelCount()) {
emit itemsInserted(0, d->modelCount());
@@ -805,8 +806,12 @@ QmlGraphicsVisualDataModel::ReleaseFlags QmlGraphicsVisualDataModel::release(Qml
}
if (d->m_cache.releaseItem(obj)) {
- if (inPackage)
+ if (inPackage) {
emit destroyingPackage(qobject_cast<QmlPackage*>(obj));
+ } else {
+ item->setVisible(false);
+ static_cast<QGraphicsItem*>(item)->setParentItem(0);
+ }
stat |= Destroyed;
obj->deleteLater();
} else if (!inPackage) {
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index bb7abf3..26ebd27 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -115,7 +115,7 @@ QList<QmlError> QmlCompiler::errors() const
/*!
Returns true if \a val is a legal object id, false otherwise.
- Legal ids must start with a letter or underscore, and contain only
+ Legal ids must start with a lower-case letter or underscore, and contain only
letters, numbers and underscores.
*/
bool QmlCompiler::isValidId(const QString &val)
@@ -123,6 +123,12 @@ bool QmlCompiler::isValidId(const QString &val)
if (val.isEmpty())
return false;
+ // TODO this will be enforced and return false
+ if (val.at(0).isLetter() && !val.at(0).isLower()) {
+ //return false;
+ qWarning() << "id '" + val + "' is invalid: ids cannot start with uppercase letters. This will be enforced in an upcoming version of QML.";
+ }
+
QChar u(QLatin1Char('_'));
for (int ii = 0; ii < val.count(); ++ii)
if (val.at(ii) != u &&
@@ -677,6 +683,13 @@ void QmlCompiler::compileTree(Object *tree)
QmlEnginePrivate::get(engine)->registerCompositeType(output);
}
+static bool ValuePtrLessThan(const Value *t1, const Value *t2)
+{
+ return t1->location.start.line < t2->location.start.line ||
+ (t1->location.start.line == t2->location.start.line &&
+ t1->location.start.column < t2->location.start.column);
+}
+
bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
{
componentStat.objects++;
@@ -736,9 +749,46 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
}
}
+ // Merge
+ Property *defaultProperty = 0;
+ Property *skipProperty = 0;
+ if (obj->defaultProperty) {
+ const QMetaObject *metaObject = obj->metaObject();
+ Q_ASSERT(metaObject);
+ QMetaProperty p = QmlMetaType::defaultProperty(metaObject);
+ if (p.name()) {
+ Property *explicitProperty = obj->getProperty(p.name(), false);
+ if (explicitProperty && !explicitProperty->value) {
+ skipProperty = explicitProperty;
+
+ defaultProperty = new Property;
+ defaultProperty->parent = obj;
+ defaultProperty->isDefault = true;
+ defaultProperty->location = obj->defaultProperty->location;
+ defaultProperty->listValueRange = obj->defaultProperty->listValueRange;
+ defaultProperty->listCommaPositions = obj->defaultProperty->listCommaPositions;
+
+ defaultProperty->values = obj->defaultProperty->values;
+ defaultProperty->values += explicitProperty->values;
+ foreach(Value *value, defaultProperty->values)
+ value->addref();
+ qSort(defaultProperty->values.begin(), defaultProperty->values.end(), ValuePtrLessThan);
+
+ } else {
+ defaultProperty = obj->defaultProperty;
+ defaultProperty->addref();
+ }
+ } else {
+ defaultProperty = obj->defaultProperty;
+ defaultProperty->addref();
+ }
+ }
+
// Build all explicit properties specified
foreach(Property *prop, obj->properties) {
+ if (prop == skipProperty)
+ continue;
if (prop->name == "id")
continue;
@@ -768,8 +818,8 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
}
// Build the default property
- if (obj->defaultProperty) {
- Property *prop = obj->defaultProperty;
+ if (defaultProperty) {
+ Property *prop = defaultProperty;
bool canDefer = false;
if (isCustomParser) {
@@ -791,6 +841,9 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
prop->isDeferred = true;
}
+ if (defaultProperty)
+ defaultProperty->release();
+
// Compile custom parser parts
if (isCustomParser && !customProps.isEmpty()) {
QmlCustomParser *cp = output->types.at(obj->type).type->customParser();
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index b3ac1bb..ea0c054 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -122,7 +122,7 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0),
globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0),
scriptEngine(this), workerScriptEngine(0), componentAttacheds(0), inBeginCreate(false),
- networkAccessManager(0), networkAccessManagerFactory(0), accessManagerValid(false),
+ networkAccessManager(0), networkAccessManagerFactory(0),
typeManager(e), uniqueId(1)
{
globalClass = new QmlGlobalScriptClass(&scriptEngine);
@@ -221,6 +221,11 @@ QScriptValue QmlScriptEngine::resolvedUrl(QScriptContext *ctxt, QScriptEngine *e
return QScriptValue(r.toString());
}
+QNetworkAccessManager *QmlScriptEngine::networkAccessManager()
+{
+ return p->getNetworkAccessManager();
+}
+
QmlEnginePrivate::~QmlEnginePrivate()
{
while (cleanup) {
@@ -412,10 +417,18 @@ QmlNetworkAccessManagerFactory *QmlEngine::networkAccessManagerFactory() const
return d->networkAccessManagerFactory;
}
-void QmlEngine::namInvalidated()
+QNetworkAccessManager *QmlEnginePrivate::getNetworkAccessManager() const
{
- Q_D(QmlEngine);
- d->accessManagerValid = false;
+ Q_Q(const QmlEngine);
+
+ if (!networkAccessManager) {
+ if (networkAccessManagerFactory) {
+ networkAccessManager = networkAccessManagerFactory->create(const_cast<QmlEngine*>(q));
+ } else {
+ networkAccessManager = new QNetworkAccessManager(const_cast<QmlEngine*>(q));
+ }
+ }
+ return networkAccessManager;
}
/*!
@@ -432,21 +445,7 @@ void QmlEngine::namInvalidated()
QNetworkAccessManager *QmlEngine::networkAccessManager() const
{
Q_D(const QmlEngine);
- if (!d->accessManagerValid) {
- delete d->networkAccessManagerFactory;
- d->networkAccessManagerFactory = 0;
- }
- if (!d->networkAccessManager) {
- if (d->networkAccessManagerFactory) {
- connect(d->networkAccessManagerFactory, SIGNAL(invalidated())
- , this, SLOT(namInvalidated()), Qt::UniqueConnection);
- d->networkAccessManager = d->networkAccessManagerFactory->create(const_cast<QmlEngine*>(this));
- } else {
- d->networkAccessManager = new QNetworkAccessManager(const_cast<QmlEngine*>(this));
- }
- d->accessManagerValid = true;
- }
- return d->networkAccessManager;
+ return d->getNetworkAccessManager();
}
/*!
@@ -1234,8 +1233,10 @@ public:
QFactoryLoader *l = loader();
QmlModuleFactoryInterface *factory =
qobject_cast<QmlModuleFactoryInterface*>(l->instance(uri));
- if (factory)
+ if (factory) {
+ factory->defineModuleOnce(uri);
isbuiltin = true;
+ }
} else {
url = base.resolved(QUrl(url)).toString();
}
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
index b9ec277..7ee014a 100644
--- a/src/declarative/qml/qmlengine.h
+++ b/src/declarative/qml/qmlengine.h
@@ -95,9 +95,6 @@ public:
Q_SIGNALS:
void quit ();
-private Q_SLOTS:
- void namInvalidated();
-
private:
Q_DECLARE_PRIVATE(QmlEngine)
};
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 6f62b40..6aa5d69 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -108,8 +108,7 @@ class QmlScriptEngine : public QScriptEngine
{
public:
QmlScriptEngine(QmlEnginePrivate *priv);
-
- ~QmlScriptEngine();
+ virtual ~QmlScriptEngine();
QUrl resolvedUrl(QScriptContext *context, const QUrl& url); // resolved against p's context, or baseUrl if no p
static QScriptValue resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine);
@@ -127,6 +126,8 @@ public:
QScriptClass *nodeListClass;
QUrl baseUrl;
+
+ virtual QNetworkAccessManager *networkAccessManager();
};
class Q_AUTOTEST_EXPORT QmlEnginePrivate : public QObjectPrivate
@@ -209,9 +210,10 @@ public:
QmlComponentAttached *componentAttacheds;
bool inBeginCreate;
+
+ QNetworkAccessManager *getNetworkAccessManager() const;
mutable QNetworkAccessManager *networkAccessManager;
mutable QmlNetworkAccessManagerFactory *networkAccessManagerFactory;
- mutable bool accessManagerValid;
QmlCompositeTypeManager typeManager;
QStringList fileImportPath;
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index 3e8d71a..ff1705b 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -184,7 +184,7 @@ QScriptValue QmlExpressionPrivate::evalInObjectScope(QmlContext *context, QObjec
/*!
\class QmlExpression
- \brief The QmlExpression class evaluates ECMAScript in a QML context.
+ \brief The QmlExpression class evaluates JavaScript in a QML context.
*/
/*!
@@ -212,7 +212,7 @@ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
/*!
Create a QmlExpression object.
- The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ The \a expression JavaScript will be executed in the \a ctxt QmlContext.
If specified, the \a scope object's properties will also be in scope during
the expression's execution.
*/
diff --git a/src/declarative/qml/qmlmoduleplugin.cpp b/src/declarative/qml/qmlmoduleplugin.cpp
index 3346ec7..2f2cb25 100644
--- a/src/declarative/qml/qmlmoduleplugin.cpp
+++ b/src/declarative/qml/qmlmoduleplugin.cpp
@@ -59,11 +59,12 @@ QT_BEGIN_NAMESPACE
exporting the class with the Q_EXPORT_PLUGIN2() macro. See \l{How
to Create Qt Plugins} for details.
- The plugin should register QML types with QML_DEFINE_TYPE.
-
The strings returned by keys() should be the list of URIs of modules
that the plugin registers.
+ The plugin should register QML types with qmlRegisterType() when the
+ defineModule() method is called.
+
\sa examples/declarative/plugins
*/
@@ -86,4 +87,25 @@ QmlModulePlugin::~QmlModulePlugin()
{
}
+/*!
+ \fn void QmlModulePlugin::defineModule(const QString& uri)
+
+ Subclasses must override this function to register types
+ of the module \a uri, which will be one of the strings returned by keys().
+
+ The plugin registers QML types with qmlRegisterType():
+
+ \code
+ qmlRegisterType<MyClass>("com.nokia.MyModule", 1, 0, "MyType", "MyClass");
+ \endcode
+*/
+
+void QmlModulePlugin::defineModuleOnce(const QString& uri)
+{
+ if (!defined.contains(uri)) {
+ defined += uri;
+ defineModule(uri);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmoduleplugin.h b/src/declarative/qml/qmlmoduleplugin.h
index 315209d..384e05e 100644
--- a/src/declarative/qml/qmlmoduleplugin.h
+++ b/src/declarative/qml/qmlmoduleplugin.h
@@ -45,6 +45,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
#include <QtCore/qlist.h>
+#include <QtCore/qset.h>
#include <QtCore/qbytearray.h>
QT_BEGIN_HEADER
@@ -55,6 +56,7 @@ QT_MODULE(Declarative)
struct Q_DECLARATIVE_EXPORT QmlModuleFactoryInterface : public QFactoryInterface
{
+ virtual void defineModuleOnce(const QString& uri) = 0;
};
#define QmlModuleFactoryInterface_iid "com.nokia.Qt.QmlModuleFactoryInterface"
@@ -69,6 +71,12 @@ class Q_DECLARATIVE_EXPORT QmlModulePlugin : public QObject, public QmlModuleFac
public:
explicit QmlModulePlugin(QObject *parent = 0);
~QmlModulePlugin();
+
+ virtual void defineModule(const QString& uri) = 0;
+
+private:
+ void defineModuleOnce(const QString& uri);
+ QSet<QString> defined;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
index 6ae20de..76f20d8 100644
--- a/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
+++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.cpp
@@ -76,18 +76,4 @@ QmlNetworkAccessManagerFactory::~QmlNetworkAccessManagerFactory()
implementation of this method is reentrant.
*/
-/*!
- Invalidates all currently created QNetworkAccessManager(s) which
- will cause create() to be called for subsequent network access.
-*/
-void QmlNetworkAccessManagerFactory::invalidate()
-{
- emit invalidated();
-}
-
-/*!
- \internal
- \fn QmlNetworkAccessManagerFactory::invalidated()
-*/
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlnetworkaccessmanagerfactory.h b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
index f64918b..ce9860f 100644
--- a/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
+++ b/src/declarative/qml/qmlnetworkaccessmanagerfactory.h
@@ -51,16 +51,12 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QNetworkAccessManager;
-class Q_DECLARATIVE_EXPORT QmlNetworkAccessManagerFactory : public QObject
+class Q_DECLARATIVE_EXPORT QmlNetworkAccessManagerFactory
{
- Q_OBJECT
public:
virtual ~QmlNetworkAccessManagerFactory();
- void invalidate();
virtual QNetworkAccessManager *create(QObject *parent) = 0;
-Q_SIGNALS:
- void invalidated();
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
index 5fd76c6..4ff4746 100644
--- a/src/declarative/qml/qmlobjectscriptclass.cpp
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -70,7 +70,7 @@ struct ObjectData : public QScriptDeclarativeClass::Object {
*/
QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
: QmlScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)),
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
methods(bindEngine),
#endif
lastData(0), engine(bindEngine)
@@ -231,7 +231,7 @@ QmlObjectScriptClass::property(QObject *obj, const Identifier &name)
if (lastData->flags & QmlPropertyCache::Data::IsVMEFunction) {
return Value(scriptEngine, ((QmlVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
} else {
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
// Uncomment to use QtScript method call logic
// QScriptValue sobj = scriptEngine->newQObject(obj);
// return Value(scriptEngine, sobj.property(toString(name)));
@@ -444,7 +444,7 @@ QStringList QmlObjectScriptClass::propertyNames(Object *object)
return cache->propertyNames();
}
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
struct MethodData : public QScriptDeclarativeClass::Object {
MethodData(QObject *o, const QmlPropertyCache::Data &d) : object(o), data(d) {}
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
index ebb2c2a..470c555 100644
--- a/src/declarative/qml/qmlobjectscriptclass_p.h
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -65,7 +65,7 @@ class QScriptContext;
class QScriptEngine;
class QmlContext;
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
class Q_AUTOTEST_EXPORT QmlObjectMethodScriptClass : public QScriptDeclarativeClass
{
public:
@@ -118,7 +118,7 @@ protected:
virtual QObject *toQObject(Object *, bool *ok = 0);
private:
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
QmlObjectMethodScriptClass methods;
#endif
diff --git a/src/declarative/qml/qmlscript.cpp b/src/declarative/qml/qmlscript.cpp
index ba62898..10fc9a6 100644
--- a/src/declarative/qml/qmlscript.cpp
+++ b/src/declarative/qml/qmlscript.cpp
@@ -70,7 +70,7 @@
defining functions that are only executed later once the context is fully
defined.
- \sa {ECMAScript Blocks}
+ \sa {JavaScript Blocks}
*/
/*!
diff --git a/src/declarative/qml/qmlscriptclass_p.h b/src/declarative/qml/qmlscriptclass_p.h
index 7ffb2ae..847ee66 100644
--- a/src/declarative/qml/qmlscriptclass_p.h
+++ b/src/declarative/qml/qmlscriptclass_p.h
@@ -66,7 +66,7 @@ public:
static QVariant toVariant(QmlEngine *, const QScriptValue &);
-#if (QT_VERSION < QT_VERSION_CHECK(4, 6, 2))
+#if (QT_VERSION <= QT_VERSION_CHECK(4, 6, 2)) && !defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
struct Value : public QScriptValue {
Value() : QScriptValue() {}
Value(QScriptEngine *engine, int v) : QScriptValue(engine, v) {}
diff --git a/src/declarative/qml/qmlworkerscript.cpp b/src/declarative/qml/qmlworkerscript.cpp
index 75c5179..f58aa8b 100644
--- a/src/declarative/qml/qmlworkerscript.cpp
+++ b/src/declarative/qml/qmlworkerscript.cpp
@@ -51,6 +51,7 @@
#include <QtCore/qwaitcondition.h>
#include <QtScript/qscriptvalueiterator.h>
#include <QtCore/qfile.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
#include <QtDeclarative/qmlinfo.h>
QT_BEGIN_NAMESPACE
@@ -107,7 +108,14 @@ public:
struct ScriptEngine : public QmlScriptEngine
{
ScriptEngine(QmlWorkerScriptEnginePrivate *parent) : QmlScriptEngine(0), p(parent) {}
+ ~ScriptEngine() { delete manager; };
QmlWorkerScriptEnginePrivate *p;
+ QNetworkAccessManager *manager;
+
+ virtual QNetworkAccessManager *networkAccessManager() {
+ if (!manager) manager = new QNetworkAccessManager;
+ return manager;
+ }
};
ScriptEngine *workerEngine;
static QmlWorkerScriptEnginePrivate *get(QScriptEngine *e) {
@@ -128,6 +136,9 @@ public:
QScriptValue callback;
};
+ QNetworkAccessManager *networkAccessManager;
+ QNetworkAccessManager *getNetworkAccessManager();
+
QHash<int, WorkerScript *> workers;
QScriptValue getWorker(int);
@@ -224,7 +235,7 @@ private:
Q_DECLARE_METATYPE(QmlWorkerListModelAgent::VariantRef);
QmlWorkerScriptEnginePrivate::QmlWorkerScriptEnginePrivate()
-: workerEngine(0), m_nextId(0)
+: workerEngine(0), networkAccessManager(0), m_nextId(0)
{
}
diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp
index f69f254..86bec20 100644
--- a/src/declarative/qml/qmlxmlhttprequest.cpp
+++ b/src/declarative/qml/qmlxmlhttprequest.cpp
@@ -940,7 +940,7 @@ public:
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
- QmlXMLHttpRequest();
+ QmlXMLHttpRequest(QNetworkAccessManager *manager);
virtual ~QmlXMLHttpRequest();
QScriptValue callback() const;
@@ -966,12 +966,16 @@ private slots:
void finished();
private:
+ void requestFromUrl(const QUrl &url);
+
State m_state;
bool m_errorFlag;
bool m_sendFlag;
QString m_method;
QUrl m_url;
QByteArray m_responseEntityBody;
+ QByteArray m_data;
+ int m_redirectCount;
typedef QPair<QByteArray, QByteArray> HeaderPair;
typedef QList<HeaderPair> HeadersList;
@@ -989,26 +993,18 @@ private:
void destroyNetwork();
QNetworkAccessManager *m_nam;
- QNetworkAccessManager *networkAccessManager()
- {
- if (!m_nam) {
- m_nam = new QNetworkAccessManager;
- // XXX proxy, etc...
- }
- return m_nam;
- }
+ QNetworkAccessManager *networkAccessManager() { return m_nam; }
};
-QmlXMLHttpRequest::QmlXMLHttpRequest()
+QmlXMLHttpRequest::QmlXMLHttpRequest(QNetworkAccessManager *manager)
: m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
- m_network(0), m_nam(0)
+ m_redirectCount(0), m_network(0), m_nam(manager)
{
}
QmlXMLHttpRequest::~QmlXMLHttpRequest()
{
destroyNetwork();
- delete m_nam;
}
QScriptValue QmlXMLHttpRequest::callback() const
@@ -1109,16 +1105,10 @@ void QmlXMLHttpRequest::fillHeadersList()
}
}
-QScriptValue QmlXMLHttpRequest::send(const QByteArray &data)
+void QmlXMLHttpRequest::requestFromUrl(const QUrl &url)
{
- m_errorFlag = false;
- m_sendFlag = true;
-
- QScriptValue cbv = dispatchCallback();
- if (cbv.isError()) return cbv;
-
- m_request.setUrl(m_url);
QNetworkRequest request = m_request;
+ request.setUrl(url);
if(m_method == QLatin1String("POST") ||
m_method == QLatin1String("PUT")) {
QVariant var = request.header(QNetworkRequest::ContentTypeHeader);
@@ -1153,9 +1143,9 @@ QScriptValue QmlXMLHttpRequest::send(const QByteArray &data)
else if (m_method == QLatin1String("HEAD"))
m_network = networkAccessManager()->head(request);
else if(m_method == QLatin1String("POST"))
- m_network = networkAccessManager()->post(request, data);
+ m_network = networkAccessManager()->post(request, m_data);
else if(m_method == QLatin1String("PUT"))
- m_network = networkAccessManager()->put(request, data);
+ m_network = networkAccessManager()->put(request, m_data);
QObject::connect(m_network, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(downloadProgress(qint64)));
@@ -1163,6 +1153,16 @@ QScriptValue QmlXMLHttpRequest::send(const QByteArray &data)
this, SLOT(error(QNetworkReply::NetworkError)));
QObject::connect(m_network, SIGNAL(finished()),
this, SLOT(finished()));
+}
+
+QScriptValue QmlXMLHttpRequest::send(const QByteArray &data)
+{
+ m_errorFlag = false;
+ m_sendFlag = true;
+ m_redirectCount = 0;
+ m_data = data;
+
+ requestFromUrl(m_url);
return QScriptValue();
}
@@ -1224,6 +1224,7 @@ void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
m_responseEntityBody = QByteArray();
m_request = QNetworkRequest();
+ m_data.clear();
destroyNetwork();
if (error == QNetworkReply::ContentAccessDenied ||
@@ -1243,9 +1244,19 @@ void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
if (cbv.isError()) printError(cbv);
}
+#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
void QmlXMLHttpRequest::finished()
{
- // ### We need to transparently redirect as dictated by the spec
+ m_redirectCount++;
+ if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) {
+ QVariant redirect = m_network->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = redirect.toUrl();
+ destroyNetwork();
+ requestFromUrl(url);
+ return;
+ }
+ }
m_status =
m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -1259,6 +1270,7 @@ void QmlXMLHttpRequest::finished()
if (cbv.isError()) printError(cbv);
}
m_responseEntityBody.append(m_network->readAll());
+ m_data.clear();
destroyNetwork();
if (m_state < Loading) {
m_state = Loading;
@@ -1548,7 +1560,7 @@ static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context
static QScriptValue qmlxmlhttprequest_new(QScriptContext *context, QScriptEngine *engine)
{
if (context->isCalledAsConstructor()) {
- context->thisObject().setData(engine->newQObject(new QmlXMLHttpRequest(), QScriptEngine::ScriptOwnership));
+ context->thisObject().setData(engine->newQObject(new QmlXMLHttpRequest(QmlScriptEngine::get(engine)->networkAccessManager()), QScriptEngine::ScriptOwnership));
}
return engine->undefinedValue();
}
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
index 63044bc..74f5b3a 100644
--- a/src/declarative/util/qmlanimation.cpp
+++ b/src/declarative/util/qmlanimation.cpp
@@ -1762,7 +1762,7 @@ void QmlPropertyAnimation::setTo(const QVariant &t)
\table
\row
- \o \c easeNone
+ \o \c easeLinear
\o Easing curve for a linear (t) function: velocity is constant.
\o \inlineimage qeasingcurve-linear.png
\row
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
index 8c70539..0b19574 100644
--- a/src/declarative/util/qmllistmodel.cpp
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -161,10 +161,10 @@ static void dump(ModelNode *node, int ind);
id: fruitDelegate
Item {
width: 200; height: 50
- Text { id: Name; text: name }
+ Text { id: name; text: name }
Text { text: '$'+cost; anchors.right: parent.right }
Row {
- anchors.top: Name.bottom
+ anchors.top: name.bottom
spacing: 5
Text { text: "Attributes:" }
Repeater {
diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp
index 5189118..755863a 100644
--- a/src/declarative/util/qmlpixmapcache.cpp
+++ b/src/declarative/util/qmlpixmapcache.cpp
@@ -75,6 +75,20 @@ inline uint qHash(const QUrl &uri)
return qHash(uri.toEncoded(QUrl::FormattingOption(0x100)));
}
+
+class QmlImageReaderEvent : public QEvent
+{
+public:
+ enum ReadError { NoError, Loading, Decoding };
+
+ QmlImageReaderEvent(QmlImageReaderEvent::ReadError err, QImage &img)
+ : QEvent(QEvent::User), error(err), image(img) {}
+
+ ReadError error;
+ QImage image;
+};
+
+class QmlImageRequestHandler;
class QmlImageReader : public QThread
{
Q_OBJECT
@@ -89,130 +103,61 @@ public:
protected:
void run();
- bool event(QEvent *event);
-
-private slots:
- void networkRequestDone();
- void namInvalidated() {
- accessManagerValid = false;
- }
private:
- QNetworkAccessManager *networkAccessManager() {
- if (!accessManagerValid) {
- delete accessManager;
- accessManager = 0;
- }
- if (!accessManager) {
- if (engine && engine->networkAccessManagerFactory()) {
- connect(engine->networkAccessManagerFactory(), SIGNAL(invalidated())
- , this, SLOT(namInvalidated()), Qt::UniqueConnection);
- accessManager = engine->networkAccessManagerFactory()->create(this);
- } else {
- accessManager = new QNetworkAccessManager(this);
- }
- accessManagerValid = true;
- }
- return accessManager;
- }
-
QList<QmlPixmapReply*> jobs;
QList<QmlPixmapReply*> cancelled;
- QHash<QNetworkReply*,QmlPixmapReply*> replies;
- QNetworkAccessManager *accessManager;
- bool accessManagerValid;
QmlEngine *engine;
+ QmlImageRequestHandler *handler;
QMutex mutex;
+
static QHash<QmlEngine *,QmlImageReader*> readers;
+ friend class QmlImageRequestHandler;
};
QHash<QmlEngine *,QmlImageReader*> QmlImageReader::readers;
-class QmlImageReaderEvent : public QEvent
-{
-public:
- enum ReadError { NoError, Loading, Decoding };
-
- QmlImageReaderEvent(QmlImageReaderEvent::ReadError err, QImage &img)
- : QEvent(QEvent::User), error(err), image(img) {}
-
- ReadError error;
- QImage image;
-};
-
-QmlImageReader::QmlImageReader(QmlEngine *eng)
- : QThread(eng), accessManager(0), accessManagerValid(false), engine(eng)
+class QmlImageRequestHandler : public QObject
{
- start(QThread::LowPriority);
-}
-
-QmlImageReader::~QmlImageReader()
-{
-}
-
-QmlImageReader *QmlImageReader::instance(QmlEngine *engine)
-{
- QmlImageReader *reader = readers.value(engine);
- if (!reader) {
- static QMutex rmutex;
- rmutex.lock();
- reader = new QmlImageReader(engine);
- readers.insert(engine, reader);
- rmutex.unlock();
+ Q_OBJECT
+public:
+ QmlImageRequestHandler(QmlImageReader *read, QmlEngine *eng)
+ : QObject(), accessManager(0), engine(eng), reader(read)
+ {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
- return reader;
-}
+ QmlPixmapReply *getImage(const QUrl &url);
+ void cancel(QmlPixmapReply *reply);
-QmlPixmapReply *QmlImageReader::getImage(const QUrl &url)
-{
- mutex.lock();
- QmlPixmapReply *reply = new QmlPixmapReply(engine, url);
- jobs.append(reply);
- if (jobs.count() == 1)
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- mutex.unlock();
- return reply;
-}
+protected:
+ bool event(QEvent *event);
-void QmlImageReader::cancel(QmlPixmapReply *reply)
-{
- mutex.lock();
- if (reply->isLoading()) {
- // Already requested. Add to cancel list to be cancelled in reader thread.
- cancelled.append(reply);
- if (cancelled.count() == 1)
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
- } else {
- // Not yet processed - just remove from waiting list
- QList<QmlPixmapReply*>::iterator it = jobs.begin();
- while (it != jobs.end()) {
- QmlPixmapReply *job = *it;
- if (job == reply) {
- jobs.erase(it);
- break;
+private slots:
+ void networkRequestDone();
+
+private:
+ QNetworkAccessManager *networkAccessManager() {
+ if (!accessManager) {
+ if (engine && engine->networkAccessManagerFactory()) {
+ accessManager = engine->networkAccessManagerFactory()->create(this);
+ } else {
+ accessManager = new QNetworkAccessManager(this);
}
- ++it;
}
+ return accessManager;
}
- mutex.unlock();
-}
-
-void QmlImageReader::run()
-{
-#ifdef Q_OS_LINUX
- struct sched_param param;
- int policy;
- pthread_getschedparam(pthread_self(), &policy, &param);
- pthread_setschedparam(pthread_self(), SCHED_IDLE, &param);
-#endif
+ QHash<QNetworkReply*,QmlPixmapReply*> replies;
+ QNetworkAccessManager *accessManager;
+ QmlEngine *engine;
+ QmlImageReader *reader;
+};
- exec();
-}
+//===========================================================================
-bool QmlImageReader::event(QEvent *event)
+bool QmlImageRequestHandler::event(QEvent *event)
{
if (event->type() == QEvent::User) {
static int replyDownloadProgress = -1;
@@ -224,15 +169,15 @@ bool QmlImageReader::event(QEvent *event)
replyDownloadProgress = QNetworkReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
replyFinished = QNetworkReply::staticMetaObject.indexOfSignal("finished()");
downloadProgress = QmlPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
- thisNetworkRequestDone = QmlImageReader::staticMetaObject.indexOfSlot("networkRequestDone()");
+ thisNetworkRequestDone = QmlImageRequestHandler::staticMetaObject.indexOfSlot("networkRequestDone()");
}
while (1) {
- mutex.lock();
+ reader->mutex.lock();
- if (cancelled.count()) {
- for (int i = 0; i < cancelled.count(); ++i) {
- QmlPixmapReply *job = cancelled.at(i);
+ if (reader->cancelled.count()) {
+ for (int i = 0; i < reader->cancelled.count(); ++i) {
+ QmlPixmapReply *job = reader->cancelled.at(i);
QNetworkReply *reply = replies.key(job, 0);
if (reply && reply->isRunning()) {
replies.remove(reply);
@@ -240,29 +185,19 @@ bool QmlImageReader::event(QEvent *event)
job->release(true);
}
}
- cancelled.clear();
- }
-
- if (!accessManagerValid) {
- // throw away existing requests and reschedule.
- QHash<QNetworkReply*,QmlPixmapReply*>::iterator it = replies.begin();
- for (; it != replies.end(); ++it) {
- delete it.key();
- jobs.prepend(*it);
- }
- replies.clear();
+ reader->cancelled.clear();
}
- if (!jobs.count() || replies.count() > maxImageRequestCount) {
- mutex.unlock();
+ if (!reader->jobs.count() || replies.count() > maxImageRequestCount) {
+ reader->mutex.unlock();
break;
}
- QmlPixmapReply *runningJob = jobs.takeFirst();
+ QmlPixmapReply *runningJob = reader->jobs.takeFirst();
runningJob->addRef();
runningJob->setLoading();
QUrl url = runningJob->url();
- mutex.unlock();
+ reader->mutex.unlock();
// fetch
QNetworkRequest req(url);
@@ -280,7 +215,7 @@ bool QmlImageReader::event(QEvent *event)
return QObject::event(event);
}
-void QmlImageReader::networkRequestDone()
+void QmlImageRequestHandler::networkRequestDone()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
QmlPixmapReply *job = replies.take(reply);
@@ -306,6 +241,84 @@ void QmlImageReader::networkRequestDone()
reply->deleteLater();
}
+//===========================================================================
+
+QmlImageReader::QmlImageReader(QmlEngine *eng)
+ : QThread(eng), engine(eng), handler(0)
+{
+ start(QThread::LowPriority);
+}
+
+QmlImageReader::~QmlImageReader()
+{
+ delete handler;
+}
+
+QmlImageReader *QmlImageReader::instance(QmlEngine *engine)
+{
+ QmlImageReader *reader = readers.value(engine);
+ if (!reader) {
+ static QMutex rmutex;
+ rmutex.lock();
+ reader = new QmlImageReader(engine);
+ readers.insert(engine, reader);
+ rmutex.unlock();
+ }
+
+ return reader;
+}
+
+QmlPixmapReply *QmlImageReader::getImage(const QUrl &url)
+{
+ mutex.lock();
+ QmlPixmapReply *reply = new QmlPixmapReply(engine, url);
+ jobs.append(reply);
+ if (jobs.count() == 1 && handler)
+ QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ mutex.unlock();
+ return reply;
+}
+
+void QmlImageReader::cancel(QmlPixmapReply *reply)
+{
+ mutex.lock();
+ if (reply->isLoading()) {
+ // Already requested. Add to cancel list to be cancelled in reader thread.
+ cancelled.append(reply);
+ if (cancelled.count() == 1 && handler)
+ QCoreApplication::postEvent(handler, new QEvent(QEvent::User));
+ } else {
+ // Not yet processed - just remove from waiting list
+ QList<QmlPixmapReply*>::iterator it = jobs.begin();
+ while (it != jobs.end()) {
+ QmlPixmapReply *job = *it;
+ if (job == reply) {
+ jobs.erase(it);
+ break;
+ }
+ ++it;
+ }
+ }
+ mutex.unlock();
+}
+
+void QmlImageReader::run()
+{
+#if defined(Q_OS_LINUX) && defined(SCHED_IDLE)
+ struct sched_param param;
+ int policy;
+
+ pthread_getschedparam(pthread_self(), &policy, &param);
+ pthread_setschedparam(pthread_self(), SCHED_IDLE, &param);
+#endif
+
+ handler = new QmlImageRequestHandler(this, engine);
+
+ exec();
+}
+
+//===========================================================================
+
static bool readImage(QIODevice *dev, QPixmap *pixmap)
{
QImageReader imgio(dev);
diff --git a/src/declarative/util/qmlpixmapcache_p.h b/src/declarative/util/qmlpixmapcache_p.h
index 0140352..c202ea8 100644
--- a/src/declarative/util/qmlpixmapcache_p.h
+++ b/src/declarative/util/qmlpixmapcache_p.h
@@ -83,6 +83,7 @@ private:
private:
Q_DISABLE_COPY(QmlPixmapReply)
Q_DECLARE_PRIVATE(QmlPixmapReply)
+ friend class QmlImageRequestHandler;
friend class QmlImageReader;
friend class QmlPixmapCache;
};