diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2010-02-04 03:39:58 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2010-02-04 03:39:58 (GMT) |
commit | 4c8b9316de5728276d24f2d72599cf9c6534fced (patch) | |
tree | b726d4826db4d98fd355f0c2c8a69229cf790b6a /src/declarative | |
parent | 0b8ef5c78b724901cfae343920b3e9e8f4a78fda (diff) | |
parent | e1c72879ed2c25819537bc5bbb12569b705ba79f (diff) | |
download | Qt-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')
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, ¶m); - pthread_setschedparam(pthread_self(), SCHED_IDLE, ¶m); -#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, ¶m); + pthread_setschedparam(pthread_self(), SCHED_IDLE, ¶m); +#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; }; |