diff options
Diffstat (limited to 'src/quick')
31 files changed, 649 insertions, 230 deletions
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index b3a2c9f46a..763dd5251b 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -180,7 +180,7 @@ QQuickCanvasItemPrivate::QQuickCanvasItemPrivate() , renderTarget(QQuickCanvasItem::Image) , renderStrategy(QQuickCanvasItem::Immediate) { - antialiasing = true; + implicitAntialiasing = true; } QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() @@ -642,7 +642,7 @@ void QQuickCanvasItem::updatePolish() Q_D(QQuickCanvasItem); if (d->context && d->renderStrategy != QQuickCanvasItem::Cooperative) - d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, d->antialiasing); + d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, antialiasing()); if (d->animationCallbacks.size() > 0 && isVisible()) { QMap<int, QV4::PersistentValue> animationCallbacks = d->animationCallbacks; @@ -705,7 +705,7 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData node->setFiltering(QSGTexture::Nearest); if (d->renderStrategy == QQuickCanvasItem::Cooperative) { - d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, d->antialiasing); + d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, antialiasing()); d->context->flush(); } diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index b6d4f1073c..c8741335dd 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -871,7 +871,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object : QV4::Object(engine) { setVTable(&static_vtbl); - flags &= ~SimpleArray; + setArrayType(QV4::ArrayData::Custom); } static void destroy(QV4::Managed *that) { diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 1107425575..8587da5ac3 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -630,8 +630,8 @@ void QQuickGridViewPrivate::updateViewport() void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex) { if (visibleItems.count()) { - const qreal from = isContentFlowReversed() ? -position() - size() : position(); - const qreal to = isContentFlowReversed() ? -position() : position() + size(); + const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning; + const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd; FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first()); qreal rowPos = firstItem->rowPos(); @@ -1534,7 +1534,35 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) of additional memory usage. It is not a substitute for creating efficient delegates; the fewer objects and bindings in a delegate, the faster a view may be scrolled. + + The cacheBuffer operates outside of any display margins specified by + displayMarginBeginning or displayMarginEnd. +*/ + +/*! + \qmlproperty int QtQuick::GridView::displayMarginBeginning + \qmlproperty int QtQuick::GridView::displayMarginEnd + \since QtQuick 2.3 + + This property allows delegates to be displayed outside of the view geometry. + + If this value is non-zero, the view will create extra delegates before the + start of the view, or after the end. The view will create as many delegates + as it can fit into the pixel size specified. + + For example, if in a vertical view the delegate is 20 pixels high, + there are 3 columns, and + \c displayMarginBeginning and \c displayMarginEnd are both set to 40, + then 6 delegates above and 6 delegates below will be created and shown. + + The default value is 0. + + This property is meant for allowing certain UI configurations, + and not as a performance optimization. If you wish to create delegates + outside of the view geometry for performance reasons, you probably + want to use the cacheBuffer property instead. */ + void QQuickGridView::setHighlightMoveDuration(int duration) { Q_D(QQuickGridView); @@ -2000,8 +2028,8 @@ void QQuickGridView::viewportMoved(Qt::Orientations orient) d->refillOrLayout(); // Set visibility of items to eliminate cost of items outside the visible area. - qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position(); - qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size(); + qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning; + qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd; for (int i = 0; i < d->visibleItems.count(); ++i) { FxGridItemSG *item = static_cast<FxGridItemSG*>(d->visibleItems.at(i)); QQuickItemPrivate::get(item->item)->setCulled(item->rowPos() + d->rowSize() < from || item->rowPos() > to); @@ -2350,7 +2378,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch // Insert items before the visible item. int insertionIdx = index; int i = count - 1; - int from = tempPos - buffer; + int from = tempPos - buffer - displayMarginBeginning; while (i >= 0) { if (rowPos > from && insertionIdx < visibleIndex) { @@ -2387,7 +2415,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch } } else { int i = 0; - int to = buffer+tempPos+size()-1; + int to = buffer+displayMarginEnd+tempPos+size()-1; while (i < count && rowPos <= to + rowSize()*(columns - colNum)/qreal(columns+1)) { FxViewItem *item = 0; if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index 0708304051..62ac72d244 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -62,6 +62,13 @@ public: { } + void updateTexture(QSGTexture *texture) { + if (m_texture == texture) + return; + m_texture = texture; + emit textureChanged(); + } + QSGTexture *texture() const { if (m_texture) { m_texture->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest); @@ -542,7 +549,7 @@ QSGTextureProvider *QQuickImage::textureProvider() const QQuickImagePrivate *dd = const_cast<QQuickImagePrivate *>(d); dd->provider = new QQuickImageTextureProvider; dd->provider->m_smooth = d->smooth; - dd->provider->m_texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window()); + dd->provider->updateTexture(d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window())); } return d->provider; @@ -557,7 +564,7 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) // Copy over the current texture state into the texture provider... if (d->provider) { d->provider->m_smooth = d->smooth; - d->provider->m_texture = texture; + d->provider->updateTexture(texture); } if (!texture || width() <= 0 || height() <= 0) { diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 5739d6874e..2a507a27b1 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2707,6 +2707,8 @@ QQuickItemPrivate::QQuickItemPrivate() , culled(false) , hasCursor(false) , activeFocusOnTab(false) + , implicitAntialiasing(false) + , antialiasingValid(false) , dirtyAttributes(0) , nextDirtyItem(0) , prevDirtyItem(0) @@ -4478,96 +4480,6 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e) } #endif // QT_NO_IM -void QQuickItemPrivate::deliverFocusEvent(QFocusEvent *e) -{ - Q_Q(QQuickItem); - - if (e->type() == QEvent::FocusIn) { - q->focusInEvent(e); - } else { - q->focusOutEvent(e); - } -} - -void QQuickItemPrivate::deliverMouseEvent(QMouseEvent *e) -{ - Q_Q(QQuickItem); - - Q_ASSERT(e->isAccepted()); - - switch (e->type()) { - default: - Q_ASSERT(!"Unknown event type"); - case QEvent::MouseMove: - q->mouseMoveEvent(e); - break; - case QEvent::MouseButtonPress: - q->mousePressEvent(e); - break; - case QEvent::MouseButtonRelease: - q->mouseReleaseEvent(e); - break; - case QEvent::MouseButtonDblClick: - q->mouseDoubleClickEvent(e); - break; - } -} - -#ifndef QT_NO_WHEELEVENT -void QQuickItemPrivate::deliverWheelEvent(QWheelEvent *e) -{ - Q_Q(QQuickItem); - q->wheelEvent(e); -} -#endif - -void QQuickItemPrivate::deliverTouchEvent(QTouchEvent *e) -{ - Q_Q(QQuickItem); - q->touchEvent(e); -} - -void QQuickItemPrivate::deliverHoverEvent(QHoverEvent *e) -{ - Q_Q(QQuickItem); - switch (e->type()) { - default: - Q_ASSERT(!"Unknown event type"); - case QEvent::HoverEnter: - q->hoverEnterEvent(e); - break; - case QEvent::HoverLeave: - q->hoverLeaveEvent(e); - break; - case QEvent::HoverMove: - q->hoverMoveEvent(e); - break; - } -} - -#ifndef QT_NO_DRAGANDDROP -void QQuickItemPrivate::deliverDragEvent(QEvent *e) -{ - Q_Q(QQuickItem); - switch (e->type()) { - default: - Q_ASSERT(!"Unknown event type"); - case QEvent::DragEnter: - q->dragEnterEvent(static_cast<QDragEnterEvent *>(e)); - break; - case QEvent::DragLeave: - q->dragLeaveEvent(static_cast<QDragLeaveEvent *>(e)); - break; - case QEvent::DragMove: - q->dragMoveEvent(static_cast<QDragMoveEvent *>(e)); - break; - case QEvent::Drop: - q->dropEvent(static_cast<QDropEvent *>(e)); - break; - } -} -#endif // QT_NO_DRAGANDDROP - /*! Called when \a change occurs for this item. @@ -5573,6 +5485,9 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt } } break; + case QQuickItem::ItemAntialiasingHasChanged: + q->itemChange(change, data); + break; } } @@ -5666,37 +5581,65 @@ void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab) /*! \qmlproperty bool QtQuick::Item::antialiasing - Primarily used in Rectangle and image based elements to decide if the item should - use antialiasing or not. Items with antialiasing enabled require more memory and - are potentially slower to render. + Used by visual elements to decide if the item should use antialiasing or not. + In some cases items with antialiasing require more memory and are potentially + slower to render (see \l {Antialiasing} for more details). - The default is false. + The default is false, but may be overridden by derived elements. */ /*! \property QQuickItem::antialiasing \brief Specifies whether the item is antialiased or not - Primarily used in Rectangle and image based elements to decide if the item should - use antialiasing or not. Items with antialiasing enabled require more memory and - are potentially slower to render. + Used by visual elements to decide if the item should use antialiasing or not. + In some cases items with antialiasing require more memory and are potentially + slower to render (see \l {Antialiasing} for more details). - The default is false. + The default is false, but may be overridden by derived elements. */ bool QQuickItem::antialiasing() const { Q_D(const QQuickItem); - return d->antialiasing; + return d->antialiasingValid ? d->antialiasing : d->implicitAntialiasing; } -void QQuickItem::setAntialiasing(bool antialiasing) + +void QQuickItem::setAntialiasing(bool aa) { Q_D(QQuickItem); - if (d->antialiasing == antialiasing) + + bool changed = (aa != antialiasing()); + d->antialiasingValid = true; + + if (!changed) return; - d->antialiasing = antialiasing; + d->antialiasing = aa; d->dirty(QQuickItemPrivate::Antialiasing); - emit antialiasingChanged(antialiasing); + d->itemChange(ItemAntialiasingHasChanged, d->antialiasing); + + emit antialiasingChanged(antialiasing()); +} + +void QQuickItem::resetAntialiasing() +{ + Q_D(QQuickItem); + if (!d->antialiasingValid) + return; + + d->antialiasingValid = false; + + if (d->implicitAntialiasing != d->antialiasing) + emit antialiasingChanged(antialiasing()); +} + +void QQuickItemPrivate::setImplicitAntialiasing(bool antialiasing) +{ + Q_Q(QQuickItem); + bool prev = q->antialiasing(); + implicitAntialiasing = antialiasing; + if (componentComplete && (q->antialiasing() != prev)) + emit q->antialiasingChanged(q->antialiasing()); } /*! @@ -6539,6 +6482,17 @@ void QQuickItemPrivate::incrementCursorCount(int delta) #endif } +void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e) +{ + Q_Q(QQuickItem); + QQmlData *ddata = QQmlData::get(q); + if (ddata) + ddata->jsWrapper.markOnce(e); + + foreach (QQuickItem *child, childItems) + QQuickItemPrivate::get(child)->markObjects(e); +} + #ifndef QT_NO_CURSOR /*! @@ -6981,18 +6935,17 @@ QRectF QQuickItem::mapRectFromScene(const QRectF &rect) const */ bool QQuickItem::event(QEvent *ev) { + Q_D(QQuickItem); + + switch (ev->type()) { #if 0 - if (ev->type() == QEvent::PolishRequest) { - Q_D(QQuickItem); + case QEvent::PolishRequest: d->polishScheduled = false; updatePolish(); - return true; - } else { - return QObject::event(ev); - } + break; #endif #ifndef QT_NO_IM - if (ev->type() == QEvent::InputMethodQuery) { + case QEvent::InputMethodQuery: { QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(ev); Qt::InputMethodQueries queries = query->queries(); for (uint i = 0; i < 32; ++i) { @@ -7003,20 +6956,79 @@ bool QQuickItem::event(QEvent *ev) } } query->accept(); - return true; - } else if (ev->type() == QEvent::InputMethod) { + break; + } + case QEvent::InputMethod: inputMethodEvent(static_cast<QInputMethodEvent *>(ev)); - return true; - } else + break; #endif // QT_NO_IM - if (ev->type() == QEvent::StyleAnimationUpdate) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + touchEvent(static_cast<QTouchEvent*>(ev)); + break; + case QEvent::StyleAnimationUpdate: if (isVisible()) { ev->accept(); update(); } - return true; + break; + case QEvent::HoverEnter: + hoverEnterEvent(static_cast<QHoverEvent*>(ev)); + break; + case QEvent::HoverLeave: + hoverLeaveEvent(static_cast<QHoverEvent*>(ev)); + break; + case QEvent::HoverMove: + hoverMoveEvent(static_cast<QHoverEvent*>(ev)); + break; + case QEvent::KeyPress: + case QEvent::KeyRelease: + d->deliverKeyEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::FocusIn: + focusInEvent(static_cast<QFocusEvent*>(ev)); + break; + case QEvent::FocusOut: + focusOutEvent(static_cast<QFocusEvent*>(ev)); + break; + case QEvent::MouseMove: + mouseMoveEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonPress: + mousePressEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonRelease: + mouseReleaseEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonDblClick: + mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev)); + break; +#ifndef QT_NO_WHEELEVENT + case QEvent::Wheel: + wheelEvent(static_cast<QWheelEvent*>(ev)); + break; +#endif +#ifndef QT_NO_DRAGANDDROP + case QEvent::DragEnter: + dragEnterEvent(static_cast<QDragEnterEvent*>(ev)); + break; + case QEvent::DragLeave: + dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev)); + break; + case QEvent::DragMove: + dragMoveEvent(static_cast<QDragMoveEvent*>(ev)); + break; + case QEvent::Drop: + dropEvent(static_cast<QDropEvent*>(ev)); + break; +#endif // QT_NO_DRAGANDDROP + default: + return QObject::event(ev); } - return QObject::event(ev); + + return true; } #ifndef QT_NO_DEBUG_STREAM diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 2500a2d33a..c666af2729 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -141,7 +141,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_PROPERTY(QQmlListProperty<QQuickTransform> transform READ transform DESIGNABLE false FINAL) Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged) - Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged) + Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged RESET resetAntialiasing) Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged) Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged) @@ -172,7 +172,8 @@ public: ItemParentHasChanged, // value.item ItemOpacityHasChanged, // value.realValue ItemActiveFocusHasChanged, // value.boolValue - ItemRotationHasChanged // value.realValue + ItemRotationHasChanged, // value.realValue + ItemAntialiasingHasChanged // value.boolValue }; union ItemChangeData { @@ -267,6 +268,7 @@ public: bool antialiasing() const; void setAntialiasing(bool); + void resetAntialiasing(); Flags flags() const; void setFlag(Flag flag, bool enabled = true); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 44eabcf0d5..96cb9e8843 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -422,6 +422,8 @@ public: bool hasCursor:1; // Bit 32 bool activeFocusOnTab:1; + bool implicitAntialiasing:1; + bool antialiasingValid:1; enum DirtyType { TransformOrigin = 0x00000001, @@ -521,6 +523,8 @@ public: virtual void implicitWidthChanged(); virtual void implicitHeightChanged(); + void setImplicitAntialiasing(bool antialiasing); + void resolveLayoutMirror(); void setImplicitLayoutMirror(bool mirror, bool inherit); void setLayoutMirror(bool mirror); @@ -540,16 +544,6 @@ public: #ifndef QT_NO_IM void deliverInputMethodEvent(QInputMethodEvent *); #endif - void deliverFocusEvent(QFocusEvent *); - void deliverMouseEvent(QMouseEvent *); -#ifndef QT_NO_WHEELEVENT - void deliverWheelEvent(QWheelEvent *); -#endif - void deliverTouchEvent(QTouchEvent *); - void deliverHoverEvent(QHoverEvent *); -#ifndef QT_NO_DRAGANDDROP - void deliverDragEvent(QEvent *); -#endif bool calcEffectiveVisible() const; bool setEffectiveVisibleRecur(bool); @@ -589,6 +583,9 @@ public: virtual void mirrorChange() {} void incrementCursorCount(int delta); + + // recursive helper to let a visual parent mark its visual children + void markObjects(QV4::ExecutionEngine *e); }; /* diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index a5b78b28e1..96746223ce 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -184,6 +184,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickTranslate>(uri,major,minor,"Translate"); qmlRegisterType<QQuickRotation>(uri,major,minor,"Rotation"); qmlRegisterType<QQuickScale>(uri,major,minor,"Scale"); + qmlRegisterType<QQuickMatrix4x4>(uri,2,4,"Matrix4x4"); qmlRegisterType<QQuickText>(uri,major,minor,"Text"); qmlRegisterType<QQuickTextEdit>(uri,major,minor,"TextEdit"); qmlRegisterType<QQuickTextEdit,1>(uri,2,1,"TextEdit"); @@ -261,6 +262,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickItem, 1>(uri, 2, 1,"Item"); qmlRegisterType<QQuickGrid, 1>(uri, 2, 1, "Grid"); qmlRegisterUncreatableType<QQuickItemView, 1>(uri, 2, 1, "ItemView", QQuickItemView::tr("ItemView is an abstract base class")); + qmlRegisterUncreatableType<QQuickItemView, 2>(uri, 2, 3, "ItemView", QQuickItemView::tr("ItemView is an abstract base class")); qmlRegisterType<QQuickListView, 1>(uri, 2, 1, "ListView"); qmlRegisterType<QQuickGridView, 1>(uri, 2, 1, "GridView"); qmlRegisterType<QQuickTextEdit, 1>(uri, 2, 1, "TextEdit"); diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index d7b984788e..f5c0e3b8d2 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -459,6 +459,41 @@ void QQuickItemView::setCacheBuffer(int b) } } +int QQuickItemView::displayMarginBeginning() const +{ + Q_D(const QQuickItemView); + return d->displayMarginBeginning; +} + +void QQuickItemView::setDisplayMarginBeginning(int margin) +{ + Q_D(QQuickItemView); + if (d->displayMarginBeginning != margin) { + d->displayMarginBeginning = margin; + if (isComponentComplete()) { + d->refillOrLayout(); + } + emit displayMarginBeginningChanged(); + } +} + +int QQuickItemView::displayMarginEnd() const +{ + Q_D(const QQuickItemView); + return d->displayMarginEnd; +} + +void QQuickItemView::setDisplayMarginEnd(int margin) +{ + Q_D(QQuickItemView); + if (d->displayMarginEnd != margin) { + d->displayMarginEnd = margin; + if (isComponentComplete()) { + d->refillOrLayout(); + } + emit displayMarginEndChanged(); + } +} Qt::LayoutDirection QQuickItemView::layoutDirection() const { @@ -1443,6 +1478,7 @@ void QQuickItemView::componentComplete() QQuickItemViewPrivate::QQuickItemViewPrivate() : itemCount(0) , buffer(QML_VIEW_DEFAULTCACHEBUFFER), bufferMode(BufferBefore | BufferAfter) + , displayMarginBeginning(0), displayMarginEnd(0) , layoutDirection(Qt::LeftToRight), verticalLayoutDirection(QQuickItemView::TopToBottom) , moveReason(Other) , visibleIndex(0) @@ -1682,9 +1718,9 @@ void QQuickItemViewPrivate::refill() { qreal s = qMax(size(), qreal(0.)); if (isContentFlowReversed()) - refill(-position()-s, -position()); + refill(-position()-displayMarginBeginning-s, -position()+displayMarginEnd); else - refill(position(), position()+s); + refill(position()-displayMarginBeginning, position()+displayMarginEnd+s); } void QQuickItemViewPrivate::refill(qreal from, qreal to) diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index 17d150f480..ad026a3152 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -63,6 +63,8 @@ class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged) + Q_PROPERTY(int displayMarginBeginning READ displayMarginBeginning WRITE setDisplayMarginBeginning NOTIFY displayMarginBeginningChanged REVISION 2) + Q_PROPERTY(int displayMarginEnd READ displayMarginEnd WRITE setDisplayMarginEnd NOTIFY displayMarginEndChanged REVISION 2) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) @@ -133,6 +135,12 @@ public: int cacheBuffer() const; void setCacheBuffer(int); + int displayMarginBeginning() const; + void setDisplayMarginBeginning(int); + + int displayMarginEnd() const; + void setDisplayMarginEnd(int); + Qt::LayoutDirection layoutDirection() const; void setLayoutDirection(Qt::LayoutDirection); Qt::LayoutDirection effectiveLayoutDirection() const; @@ -218,6 +226,8 @@ Q_SIGNALS: void keyNavigationWrapsChanged(); void cacheBufferChanged(); + void displayMarginBeginningChanged(); + void displayMarginEndChanged(); void layoutDirectionChanged(); void effectiveLayoutDirectionChanged(); diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index e0f08fd50f..af7c23c02e 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -257,6 +257,8 @@ public: int itemCount; int buffer; int bufferMode; + int displayMarginBeginning; + int displayMarginEnd; Qt::LayoutDirection layoutDirection; QQuickItemView::VerticalLayoutDirection verticalLayoutDirection; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 06749be819..2dd61e386f 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -777,8 +777,8 @@ void QQuickListViewPrivate::visibleItemsChanged() void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex) { if (!visibleItems.isEmpty()) { - const qreal from = isContentFlowReversed() ? -position() - size() : position(); - const qreal to = isContentFlowReversed() ? -position() : position() + size(); + const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning; + const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd; FxViewItem *firstItem = *visibleItems.constBegin(); bool fixedCurrent = currentItem && firstItem->item == currentItem->item; @@ -2145,8 +2145,33 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation) of additional memory usage. It is not a substitute for creating efficient delegates; the fewer objects and bindings in a delegate, the faster a view can be scrolled. + + The cacheBuffer operates outside of any display margins specified by + displayMarginBeginning or displayMarginEnd. */ +/*! + \qmlproperty int QtQuick::ListView::displayMarginBeginning + \qmlproperty int QtQuick::ListView::displayMarginEnd + \since QtQuick 2.3 + + This property allows delegates to be displayed outside of the view geometry. + + If this value is non-zero, the view will create extra delegates before the + start of the view, or after the end. The view will create as many delegates + as it can fit into the pixel size specified. + + For example, if in a vertical view the delegate is 20 pixels high and + \c displayMarginBeginning and \c displayMarginEnd are both set to 40, + then 2 delegates above and 2 delegates below will be created and shown. + + The default value is 0. + + This property is meant for allowing certain UI configurations, + and not as a performance optimization. If you wish to create delegates + outside of the view geometry for performance reasons, you probably + want to use the cacheBuffer property instead. +*/ /*! \qmlpropertygroup QtQuick::ListView::section @@ -2703,8 +2728,8 @@ void QQuickListView::viewportMoved(Qt::Orientations orient) d->refillOrLayout(); // Set visibility of items to eliminate cost of items outside the visible area. - qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position(); - qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size(); + qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning; + qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd; for (int i = 0; i < d->visibleItems.count(); ++i) { FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i)); QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to); @@ -2910,7 +2935,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch // there are no visible items except items marked for removal index = visibleItems.count(); } else if (visibleItems.at(i)->index + 1 == modelIndex - && visibleItems.at(i)->endPosition() <= buffer+tempPos+size()) { + && visibleItems.at(i)->endPosition() <= buffer+displayMarginEnd+tempPos+size()) { // Special case of appending an item to the model. index = visibleItems.count(); } else { @@ -2939,7 +2964,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch // Insert items before the visible item. int insertionIdx = index; int i = 0; - int from = tempPos - buffer; + int from = tempPos - displayMarginBeginning - buffer; for (i = count-1; i >= 0; --i) { if (pos > from && insertionIdx < visibleIndex) { @@ -2970,7 +2995,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch } } else { int i = 0; - int to = buffer+tempPos+size(); + int to = buffer+displayMarginEnd+tempPos+size(); for (i = 0; i < count && pos <= to; ++i) { FxViewItem *item = 0; if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 7a4b359d91..f07571d3cc 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -49,6 +49,7 @@ #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qevent.h> +#include <QtGui/qstylehints.h> #include <float.h> @@ -56,8 +57,6 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING) -static const int PressAndHoldDelay = 800; - QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() : enabled(true), hovered(false), longPress(false), moved(false), stealMouse(false), doubleClick(false), preventStealing(false), @@ -627,7 +626,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event) #endif setHovered(true); d->startScene = event->windowPos(); - d->pressAndHoldTimer.start(PressAndHoldDelay, this); + d->pressAndHoldTimer.start(qApp->styleHints()->mousePressAndHoldInterval(), this); setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(event->button(), true)); } diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 8fe306b006..6b273dcd43 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -43,6 +43,7 @@ #include <QtQuick/qquickwindow.h> #include <private/qsgadaptationlayer_p.h> #include <private/qquickitem_p.h> +#include <private/qguiapplication_p.h> #include <QEvent> #include <QMouseEvent> #include <math.h> @@ -675,6 +676,10 @@ bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event) QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); mouseEvent.setAccepted(false); + QGuiApplicationPrivate::setMouseEventCapsAndVelocity(&mouseEvent, + QGuiApplicationPrivate::mouseEventCaps(event), + QGuiApplicationPrivate::mouseEventVelocity(event)); + QGuiApplicationPrivate::setMouseEventSource(&mouseEvent, Qt::MouseEventSynthesizedByQt); switch (mouseEvent.type()) { case QEvent::MouseMove: diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp index 48f79a2192..ee1b66f2b5 100644 --- a/src/quick/items/qquickrectangle.cpp +++ b/src/quick/items/qquickrectangle.cpp @@ -321,6 +321,16 @@ void QQuickRectangle::doUpdate() } /*! + \qmlproperty bool QtQuick::Rectangle::antialiasing + + Used to decide if the Rectangle should use antialiasing or not. + \l {Antialiasing} provides information on the performance implications + of this property. + + The default is true for Rectangles with a radius, and false otherwise. +*/ + +/*! \qmlpropertygroup QtQuick::Rectangle::border \qmlproperty int QtQuick::Rectangle::border.width \qmlproperty color QtQuick::Rectangle::border.color @@ -409,6 +419,8 @@ void QQuickRectangle::setRadius(qreal radius) return; d->radius = radius; + d->setImplicitAntialiasing(radius != 0.0); + update(); emit radiusChanged(); } @@ -476,7 +488,7 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData } rectangle->setRadius(d->radius); - rectangle->setAntialiasing(d->antialiasing || d->radius > 0); + rectangle->setAntialiasing(antialiasing()); QGradientStops stops; if (d->gradient) { diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index ad904a2579..beb2039924 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -88,6 +88,7 @@ QQuickTextPrivate::QQuickTextPrivate() , truncated(false), hAlignImplicit(true), rightToLeftText(false) , layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false) { + implicitAntialiasing = true; } QQuickTextPrivate::ExtraData::ExtraData() @@ -114,6 +115,7 @@ QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuic { setUndoRedoEnabled(false); documentLayout()->registerHandler(QTextFormat::ImageObject, this); + connect(this, SIGNAL(baseUrlChanged(QUrl)), this, SLOT(reset())); } QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources() @@ -125,14 +127,13 @@ QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources() QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name) { QQmlContext *context = qmlContext(parent()); - QUrl url = m_baseUrl.resolved(name); if (type == QTextDocument::ImageResource) { - QQuickPixmap *p = loadPixmap(context, url); + QQuickPixmap *p = loadPixmap(context, name); return p->image(); } - return QTextDocument::loadResource(type,url); // The *resolved* URL + return QTextDocument::loadResource(type, name); } void QQuickTextDocumentWithImageResources::requestFinished() @@ -144,14 +145,6 @@ void QQuickTextDocumentWithImageResources::requestFinished() } } -void QQuickTextDocumentWithImageResources::clear() -{ - clearResources(); - - QTextDocument::clear(); -} - - QSizeF QQuickTextDocumentWithImageResources::intrinsicSize( QTextDocument *, int, const QTextFormat &format) { @@ -166,7 +159,7 @@ QSizeF QQuickTextDocumentWithImageResources::intrinsicSize( QSizeF size(width, height); if (!hasWidth || !hasHeight) { QQmlContext *context = qmlContext(parent()); - QUrl url = m_baseUrl.resolved(QUrl(imageFormat.name())); + QUrl url = baseUrl().resolved(QUrl(imageFormat.name())); QQuickPixmap *p = loadPixmap(context, url); if (!p->isReady()) { @@ -204,19 +197,16 @@ void QQuickTextDocumentWithImageResources::drawObject( QImage QQuickTextDocumentWithImageResources::image(const QTextImageFormat &format) { QQmlContext *context = qmlContext(parent()); - QUrl url = m_baseUrl.resolved(QUrl(format.name())); + QUrl url = baseUrl().resolved(QUrl(format.name())); QQuickPixmap *p = loadPixmap(context, url); return p->image(); } -void QQuickTextDocumentWithImageResources::setBaseUrl(const QUrl &url, bool clear) +void QQuickTextDocumentWithImageResources::reset() { - m_baseUrl = url; - if (clear) { - clearResources(); - markContentsDirty(0, characterCount()); - } + clearResources(); + markContentsDirty(0, characterCount()); } QQuickPixmap *QQuickTextDocumentWithImageResources::loadPixmap( @@ -297,6 +287,15 @@ qreal QQuickTextPrivate::getImplicitHeight() const return implicitHeight; } +/*! + \qmlproperty bool QtQuick::Text::antialiasing + + Used to decide if the Text should use antialiasing or not. Only Text + with renderType of Text.NativeRendering can disable antialiasing. + + The default is true. +*/ + void QQuickText::q_imagesLoaded() { Q_D(QQuickText); @@ -620,8 +619,9 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, textLine->setHeight(0); textLine->setLineOffset(lineOffset); - // use the text item's width by default if it has one and wrap is on - if (q->widthValid() && q->wrapMode() != QQuickText::NoWrap) + // use the text item's width by default if it has one and wrap is on or text must be aligned + if (q->widthValid() && (q->wrapMode() != QQuickText::NoWrap || + q->effectiveHAlign() != QQuickText::AlignLeft)) textLine->setWidth(q->width()); else textLine->setWidth(INT_MAX); @@ -959,7 +959,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) // If the horizontal alignment is not left and the width was not valid we need to relayout // now that we know the maximum line width. - if (!implicitWidthValid && lineCount > 1 && q->effectiveHAlign() != QQuickText::AlignLeft) { + if (!implicitWidthValid && unwrappedLineCount > 1 && q->effectiveHAlign() != QQuickText::AlignLeft) { widthExceeded = false; heightExceeded = false; continue; @@ -1415,6 +1415,9 @@ void QQuickText::setFont(const QFont &font) QFont oldFont = d->font; d->font = font; + if (!antialiasing()) + d->font.setStyleStrategy(QFont::NoAntialias); + if (d->font.pointSizeF() != -1) { // 0.5pt resolution qreal size = qRound(d->font.pointSizeF()*2.0); @@ -1434,6 +1437,21 @@ void QQuickText::setFont(const QFont &font) emit fontChanged(d->sourceFont); } +void QQuickText::itemChange(ItemChange change, const ItemChangeData &value) +{ + Q_D(QQuickText); + Q_UNUSED(value); + if (change == ItemAntialiasingHasChanged) { + if (!antialiasing()) + d->font.setStyleStrategy(QFont::NoAntialias); + else + d->font.setStyleStrategy(QFont::PreferAntialias); + d->implicitWidthValid = false; + d->implicitHeightValid = false; + d->updateLayout(); + } +} + /*! \qmlproperty string QtQuick::Text::text diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index 489ef58344..d55dc7e287 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -241,6 +241,7 @@ Q_SIGNALS: protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); + virtual void itemChange(ItemChange change, const ItemChangeData &value); virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h index 1f6cd3eab5..12113f416c 100644 --- a/src/quick/items/qquicktext_p_p.h +++ b/src/quick/items/qquicktext_p_p.h @@ -195,16 +195,13 @@ public: void setText(const QString &); int resourcesLoading() const { return outstanding; } - void clearResources(); - - void clear(); - QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format); void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format); QImage image(const QTextImageFormat &format); - void setBaseUrl(const QUrl &url, bool clear = true); +public Q_SLOTS: + void clearResources(); Q_SIGNALS: void imagesLoaded(); @@ -215,11 +212,11 @@ protected: QQuickPixmap *loadPixmap(QQmlContext *context, const QUrl &name); private Q_SLOTS: + void reset(); void requestFinished(); private: QHash<QUrl, QQuickPixmap *> m_resources; - QUrl m_baseUrl; int outstanding; static QSet<QUrl> errors; diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index ffc732621d..c342c79ce5 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -830,7 +830,7 @@ void QQuickTextEdit::setBaseUrl(const QUrl &url) if (baseUrl() != url) { d->baseUrl = url; - d->document->setBaseUrl(url, d->richText); + d->document->setBaseUrl(url); emit baseUrlChanged(); } } @@ -1281,7 +1281,7 @@ void QQuickTextEdit::componentComplete() Q_D(QQuickTextEdit); QQuickImplicitSizeItem::componentComplete(); - d->document->setBaseUrl(baseUrl(), d->richText); + d->document->setBaseUrl(baseUrl()); #ifndef QT_NO_TEXTHTML_PARSER if (d->richText) d->control->setHtml(d->text); diff --git a/src/quick/items/qquicktranslate.cpp b/src/quick/items/qquicktranslate.cpp index f1b716cf5b..5c61fb33f8 100644 --- a/src/quick/items/qquicktranslate.cpp +++ b/src/quick/items/qquicktranslate.cpp @@ -458,4 +458,79 @@ void QQuickRotation::applyTo(QMatrix4x4 *matrix) const matrix->translate(-d->origin); } +class QQuickMatrix4x4Private : public QQuickTransformPrivate +{ +public: + QQuickMatrix4x4Private() + : matrix() {} + QMatrix4x4 matrix; +}; + +/*! + \qmltype Matrix4x4 + \instantiates QQuickMatrix4x4 + \inqmlmodule QtQuick + \ingroup qtquick-visual-transforms + \brief Provides a way to apply a 4x4 tranformation matrix to an \l Item + + The Matrix4x4 type provides a way to apply a transformation to an + \l Item through a 4x4 matrix. + + It allows for a combination of rotation, scale, translatation and shearing + by using just one tranformation provided in a 4x4-matrix. + + The following example rotates a Rectangle 45 degress (PI/4): + + \qml + Rectangle { + width: 100 + height: 100 + color: "red" + + transform: Matrix4x4 { + property real a: Math.PI / 4 + matrix: Qt.matrix4x4(Math.cos(a), -Math.sin(a), 0, 0, + Math.sin(a), Math.cos(a), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1) + } + } + \endqml +*/ +QQuickMatrix4x4::QQuickMatrix4x4(QObject *parent) + : QQuickTransform(*new QQuickMatrix4x4Private, parent) +{ +} + +QQuickMatrix4x4::~QQuickMatrix4x4() +{ +} + +/*! + \qmlproperty QMatrix4x4 QtQuick::Matrix4x4::matrix + + 4x4-matrix which will be used in the tranformation of an \l Item +*/ +QMatrix4x4 QQuickMatrix4x4::matrix() const +{ + Q_D(const QQuickMatrix4x4); + return d->matrix; +} + +void QQuickMatrix4x4::setMatrix(const QMatrix4x4 &matrix) +{ + Q_D(QQuickMatrix4x4); + if (d->matrix == matrix) + return; + d->matrix = matrix; + update(); + emit matrixChanged(); +} + +void QQuickMatrix4x4::applyTo(QMatrix4x4 *matrix) const +{ + Q_D(const QQuickMatrix4x4); + *matrix *= d->matrix; +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h index d7843fe103..dd93275a28 100644 --- a/src/quick/items/qquicktranslate_p.h +++ b/src/quick/items/qquicktranslate_p.h @@ -148,6 +148,29 @@ private: Q_DECLARE_PRIVATE(QQuickRotation) }; +class QQuickMatrix4x4Private; +class Q_AUTOTEST_EXPORT QQuickMatrix4x4 : public QQuickTransform +{ + Q_OBJECT + + Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix NOTIFY matrixChanged) +public: + QQuickMatrix4x4(QObject *parent = 0); + ~QQuickMatrix4x4(); + + QMatrix4x4 matrix() const; + void setMatrix(const QMatrix4x4& matrix); + + void applyTo(QMatrix4x4 *matrix) const; + +Q_SIGNALS: + void matrixChanged(); + +private: + Q_DECLARE_PRIVATE(QQuickMatrix4x4) +}; + + QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickTranslate) diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index d1fe489dcb..61f0f9bec2 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -56,6 +56,26 @@ QT_BEGIN_NAMESPACE +DEFINE_MANAGED_VTABLE(QQuickRootItemMarker); + +QQuickRootItemMarker::QQuickRootItemMarker(QQuickViewPrivate *view) + : QV4::Object(QQmlEnginePrivate::getV4Engine(view->engine.data())) + , view(view) +{ + setVTable(&static_vtbl); +} + +void QQuickRootItemMarker::markObjects(QV4::Managed *that, QV4::ExecutionEngine *e) +{ + QQuickItem *root = static_cast<QQuickRootItemMarker*>(that)->view->root; + if (root) { + QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root); + rootPrivate->markObjects(e); + } + + QV4::Object::markObjects(that, e); +} + void QQuickViewPrivate::init(QQmlEngine* e) { Q_Q(QQuickView); @@ -68,6 +88,13 @@ void QQuickViewPrivate::init(QQmlEngine* e) if (!engine.data()->incubationController()) engine.data()->setIncubationController(q->incubationController()); + { + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine.data()); + QV4::Scope scope(v4); + QV4::Scoped<QQuickRootItemMarker> v(scope, new (v4->memoryManager) QQuickRootItemMarker(this)); + rootItemMarker = v; + } + if (QQmlDebugService::isDebuggingEnabled()) QQmlInspectorService::instance()->addView(q); } diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index 170c93a6cf..e18b45dfbe 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -51,12 +51,17 @@ #include <QtCore/QWeakPointer> #include <QtQml/qqmlengine.h> +#include <private/qv4object_p.h> #include "qquickwindow_p.h" #include "qquickitemchangelistener_p.h" QT_BEGIN_NAMESPACE +namespace QV4 { +struct ExecutionEngine; +} + class QQmlContext; class QQmlError; class QQuickItem; @@ -94,6 +99,23 @@ public: QQuickView::ResizeMode resizeMode; QSize initialSize; QElapsedTimer frameTimer; + QV4::PersistentValue rootItemMarker; +}; + +struct QQuickRootItemMarker : public QV4::Object +{ + Q_MANAGED + + QQuickRootItemMarker(QQuickViewPrivate *view); + + static void destroy(Managed *that) + { + static_cast<QQuickRootItemMarker*>(that)->~QQuickRootItemMarker(); + } + + static void markObjects(Managed *that, QV4::ExecutionEngine *e); + + QQuickViewPrivate *view; }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index d286ccff0c..c57ca5e838 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -257,8 +257,10 @@ void QQuickWindowPrivate::polishItems() for (QSet<QQuickItem *>::iterator it = itms.begin(); it != itms.end(); ++it) { QQuickItem *item = *it; - QQuickItemPrivate::get(item)->polishScheduled = false; - item->updatePolish(); + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->polishScheduled = false; + if (item->isVisible() || (itemPrivate->extra.isAllocated() && itemPrivate->extra->effectRefCount>0)) + item->updatePolish(); } } @@ -470,6 +472,7 @@ static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::Touc transformedVelocity = transformMatrix.mapVector(p.velocity()).toVector2D(); } QGuiApplicationPrivate::setMouseEventCapsAndVelocity(me, event->device()->capabilities(), transformedVelocity); + QGuiApplicationPrivate::setMouseEventSource(me, Qt::MouseEventSynthesizedByQt); return me; } @@ -523,7 +526,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e item->grabMouse(); item->grabTouchPoints(QVector<int>() << touchMouseId); - QQuickItemPrivate::get(item)->deliverMouseEvent(mousePress.data()); + QCoreApplication::sendEvent(item, mousePress.data()); event->setAccepted(mousePress->isAccepted()); if (!mousePress->isAccepted()) { touchMouseId = -1; @@ -536,7 +539,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e if (mousePress->isAccepted() && checkIfDoubleClicked(event->timestamp())) { QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item)); - QQuickItemPrivate::get(item)->deliverMouseEvent(mouseDoubleClick.data()); + QCoreApplication::sendEvent(item, mouseDoubleClick.data()); event->setAccepted(mouseDoubleClick->isAccepted()); if (mouseDoubleClick->isAccepted()) { return true; @@ -557,7 +560,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e if (p.state() & Qt::TouchPointMoved) { if (mouseGrabberItem) { QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event, mouseGrabberItem)); - QQuickItemPrivate::get(item)->deliverMouseEvent(me.data()); + QCoreApplication::sendEvent(item, me.data()); event->setAccepted(me->isAccepted()); if (me->isAccepted()) { itemForTouchPointId[p.id()] = mouseGrabberItem; // N.B. the mouseGrabberItem may be different after returning from sendEvent() @@ -587,7 +590,7 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e touchMouseId = -1; if (mouseGrabberItem) { QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event, mouseGrabberItem)); - QQuickItemPrivate::get(item)->deliverMouseEvent(me.data()); + QCoreApplication::sendEvent(item, me.data()); if (mouseGrabberItem) // might have ungrabbed due to event mouseGrabberItem->ungrabMouse(); return me->isAccepted(); @@ -1296,24 +1299,43 @@ bool QQuickWindow::event(QEvent *e) void QQuickWindow::keyPressEvent(QKeyEvent *e) { Q_D(QQuickWindow); - -#ifndef QT_NO_SHORTCUT - // Try looking for a Shortcut before sending key events - if (QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focusObject(), e)) - return; -#endif - - if (d->activeFocusItem) - sendEvent(d->activeFocusItem, e); + d->deliverKeyEvent(e); } /*! \reimp */ void QQuickWindow::keyReleaseEvent(QKeyEvent *e) { Q_D(QQuickWindow); + d->deliverKeyEvent(e); +} - if (d->activeFocusItem) - sendEvent(d->activeFocusItem, e); +void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e) +{ + Q_Q(QQuickWindow); + +#ifndef QT_NO_SHORTCUT + // Try looking for a Shortcut before sending key events + if (e->type() == QEvent::KeyPress + && QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(q->focusObject(), e)) + return; +#endif + + if (activeFocusItem) + q->sendEvent(activeFocusItem, e); +#ifdef Q_OS_MAC + else { + // This is the case for popup windows on Mac, where popup windows get focus + // in Qt (after exposure) but they are not "key windows" in the Cocoa sense. + // Therefore, the will never receive key events from Cocoa. Instead, the + // toplevel non-popup window (the application current "key window") will + // receive them. (QWidgetWindow does something similar for widgets, by keeping + // a list of popup windows, and forwarding the key event to the top-most popup.) + QWindow *focusWindow = qApp->focusWindow(); + if (focusWindow && focusWindow != q + && (focusWindow->flags() & Qt::Popup) == Qt::Popup) + QGuiApplication::sendEvent(focusWindow, e); + } +#endif } QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos) @@ -1325,6 +1347,7 @@ QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *t event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QGuiApplicationPrivate::setMouseEventCapsAndVelocity(me, caps, velocity); + QGuiApplicationPrivate::setMouseEventSource(me, QGuiApplicationPrivate::mouseEventSource(event)); me->setTimestamp(event->timestamp()); return me; } @@ -1401,6 +1424,12 @@ bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event) void QQuickWindow::mousePressEvent(QMouseEvent *event) { Q_D(QQuickWindow); + + if (event->source() == Qt::MouseEventSynthesizedBySystem) { + event->accept(); + return; + } + #ifdef MOUSE_DEBUG qWarning() << "QQuickWindow::mousePressEvent()" << event->localPos() << event->button() << event->buttons(); #endif @@ -1412,6 +1441,12 @@ void QQuickWindow::mousePressEvent(QMouseEvent *event) void QQuickWindow::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickWindow); + + if (event->source() == Qt::MouseEventSynthesizedBySystem) { + event->accept(); + return; + } + #ifdef MOUSE_DEBUG qWarning() << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons(); #endif @@ -1430,6 +1465,12 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event) void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event) { Q_D(QQuickWindow); + + if (event->source() == Qt::MouseEventSynthesizedBySystem) { + event->accept(); + return; + } + #ifdef MOUSE_DEBUG qWarning() << "QQuickWindow::mouseDoubleClickEvent()" << event->localPos() << event->button() << event->buttons(); #endif @@ -1465,6 +1506,12 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item, void QQuickWindow::mouseMoveEvent(QMouseEvent *event) { Q_D(QQuickWindow); + + if (event->source() == Qt::MouseEventSynthesizedBySystem) { + event->accept(); + return; + } + #ifdef MOUSE_DEBUG qWarning() << "QQuickWindow::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons(); #endif @@ -1813,11 +1860,11 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv itemForTouchPointId[id] = item; // Deliver the touch event to the given item - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - itemPrivate->deliverTouchEvent(touchEvent.data()); + QCoreApplication::sendEvent(item, touchEvent.data()); touchEventAccepted = touchEvent->isAccepted(); // If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it. + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (!touchEventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) { // send mouse event event->setAccepted(translateTouchToMouse(item, event)); @@ -2235,16 +2282,12 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e) case QEvent::KeyPress: case QEvent::KeyRelease: e->accept(); - QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e)); + QCoreApplication::sendEvent(item, e); while (!e->isAccepted() && (item = item->parentItem())) { e->accept(); - QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e)); + QCoreApplication::sendEvent(item, e); } break; - case QEvent::FocusIn: - case QEvent::FocusOut: - QQuickItemPrivate::get(item)->deliverFocusEvent(static_cast<QFocusEvent *>(e)); - break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: @@ -2253,7 +2296,7 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e) if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) { // accept because qml items by default accept and have to explicitly opt out of accepting e->accept(); - QQuickItemPrivate::get(item)->deliverMouseEvent(static_cast<QMouseEvent *>(e)); + QCoreApplication::sendEvent(item, e); } break; case QEvent::UngrabMouse: @@ -2264,30 +2307,26 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e) break; #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: - QQuickItemPrivate::get(item)->deliverWheelEvent(static_cast<QWheelEvent *>(e)); - break; #endif +#ifndef QT_NO_DRAGANDDROP + case QEvent::DragEnter: + case QEvent::DragMove: + case QEvent::DragLeave: + case QEvent::Drop: +#endif + case QEvent::FocusIn: + case QEvent::FocusOut: case QEvent::HoverEnter: case QEvent::HoverLeave: case QEvent::HoverMove: - QQuickItemPrivate::get(item)->deliverHoverEvent(static_cast<QHoverEvent *>(e)); + case QEvent::TouchCancel: + QCoreApplication::sendEvent(item, e); break; case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: d->sendFilteredTouchEvent(item->parentItem(), item, static_cast<QTouchEvent *>(e)); break; - case QEvent::TouchCancel: - QQuickItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e)); - break; -#ifndef QT_NO_DRAGANDDROP - case QEvent::DragEnter: - case QEvent::DragMove: - case QEvent::DragLeave: - case QEvent::Drop: - QQuickItemPrivate::get(item)->deliverDragEvent(e); - break; -#endif default: break; } diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 418633b6ac..d5c7b5d64c 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -111,6 +111,8 @@ public: QQuickItem *activeFocusItem; + void deliverKeyEvent(QKeyEvent *e); + // Keeps track of the item currently receiving mouse events QQuickItem *mouseGrabberItem; #ifndef QT_NO_CURSOR diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index e9d883f248..eff8158335 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -2165,6 +2165,10 @@ void Renderer::renderUnmergedBatch(const Batch *batch) if (g->drawingMode() == GL_LINE_STRIP || g->drawingMode() == GL_LINE_LOOP || g->drawingMode() == GL_LINES) glLineWidth(g->lineWidth()); +#if !defined(QT_OPENGL_ES_2) + else if (g->drawingMode() == GL_POINTS) + glPointSize(g->lineWidth()); +#endif if (g->indexCount()) glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), iOffset); diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index ffb11fc6fa..40e0a014ab 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -525,8 +525,9 @@ void QSGGeometry::setDrawingMode(GLenum mode) } /*! - Gets the current line width to be used for this geometry. This property only - applies where the drawingMode is GL_LINES or a related value. + Gets the current line or point width or to be used for this geometry. This property + only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or + \c GL_LINE_LOOP, and only applies to point size when the drawingMode is \c GL_POINTS. The default value is \c 1.0 @@ -538,8 +539,9 @@ float QSGGeometry::lineWidth() const } /*! - Sets the line width to be used for this geometry to \a width. The line width - only applies where the drawingMode is \c GL_LINES or a related value. + Sets the line or point width to be used for this geometry to \a width. This property + only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or + \c GL_LINE_LOOP, and only applies to point size when the drawingMode is \c GL_POINTS. \sa lineWidth(), drawingMode() */ diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp index 460e2ca554..407b80915d 100644 --- a/src/quick/util/qquickbehavior.cpp +++ b/src/quick/util/qquickbehavior.cpp @@ -185,7 +185,8 @@ void QQuickBehavior::write(const QVariant &value) return; } - if (d->animation->isRunning() && value == d->targetValue) + bool behaviorActive = d->animation->isRunning(); + if (behaviorActive && value == d->targetValue) return; d->targetValue = value; @@ -201,6 +202,14 @@ void QQuickBehavior::write(const QVariant &value) // to the item, so we need to read the value after. const QVariant ¤tValue = d->property.read(); + // Don't unnecessarily wake up the animation system if no real animation + // is needed (value has not changed). If the Behavior was already + // running, let it continue as normal to ensure correct behavior and state. + if (!behaviorActive && d->targetValue == currentValue) { + QQmlPropertyPrivate::write(d->property, value, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding); + return; + } + QQuickStateOperation::ActionList actions; QQuickStateAction action; action.property = d->property; diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index 152d1f34c9..5ae74c2fec 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -398,7 +398,7 @@ public: if (!array) return QMatrix4x4(); - if (array->arrayLength() != 16) + if (array->getLength() != 16) return QMatrix4x4(); float matVals[16]; diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 148c55bbcb..55ac85e64d 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -259,6 +259,29 @@ QQuickPropertyChangesParser::compileList(QList<QPair<QString, QVariant> > &list, } } +void QQuickPropertyChangesParser::compileList(QList<QPair<QString, const QV4::CompiledData::Binding*> > &list, const QString &pre, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding) +{ + QString propName = pre + qmlUnit->header.stringAt(binding->propertyNameIndex); + + if (binding->type == QV4::CompiledData::Binding::Type_Object) { + error(qmlUnit->objectAt(binding->value.objectIndex), QQuickPropertyChanges::tr("PropertyChanges does not support creating state-specific objects.")); + return; + } + + if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty + || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + QString pre = propName + QLatin1Char('.'); + const QV4::CompiledData::Object *subObj = qmlUnit->objectAt(binding->value.objectIndex); + const QV4::CompiledData::Binding *subBinding = subObj->bindingTable(); + for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding) { + compileList(list, pre, qmlUnit, subBinding); + } + return; + } + + list << qMakePair(propName, binding); +} + QByteArray QQuickPropertyChangesParser::compile(const QList<QQmlCustomParserProperty> &props) { @@ -303,6 +326,44 @@ QQuickPropertyChangesParser::compile(const QList<QQmlCustomParserProperty> &prop return rv; } +QByteArray QQuickPropertyChangesParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props) +{ + QList<QPair<QString, const QV4::CompiledData::Binding *> > data; + for (int ii = 0; ii < props.count(); ++ii) + compileList(data, QString(), qmlUnit, props.at(ii)); + + QByteArray rv; + QDataStream ds(&rv, QIODevice::WriteOnly); + + ds << data.count(); + for (int ii = 0; ii < data.count(); ++ii) { + const QV4::CompiledData::Binding *binding = data.at(ii).second; + QVariant var; + bool isScript = binding->type == QV4::CompiledData::Binding::Type_Script; + QQmlBinding::Identifier id = QQmlBinding::Invalid; + switch (binding->type) { + case QV4::CompiledData::Binding::Type_Script: + // ### pre-compile binding + case QV4::CompiledData::Binding::Type_String: + var = binding->valueAsString(&qmlUnit->header); + break; + case QV4::CompiledData::Binding::Type_Number: + var = binding->valueAsNumber(); + break; + case QV4::CompiledData::Binding::Type_Boolean: + var = binding->valueAsBoolean(); + break; + default: + break; + } + ds << data.at(ii).first << isScript << var; + if (isScript) + ds << id; + } + + return rv; +} + void QQuickPropertyChangesPrivate::decode() { Q_Q(QQuickPropertyChanges); diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h index 0236e4529b..081ea72862 100644 --- a/src/quick/util/qquickpropertychanges_p.h +++ b/src/quick/util/qquickpropertychanges_p.h @@ -93,8 +93,10 @@ public: : QQmlCustomParser(AcceptsAttachedProperties) {} void compileList(QList<QPair<QString, QVariant> > &list, const QString &pre, const QQmlCustomParserProperty &prop); + void compileList(QList<QPair<QString, const QV4::CompiledData::Binding *> > &list, const QString &pre, const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding); virtual QByteArray compile(const QList<QQmlCustomParserProperty> &); + virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props); virtual void setCustomData(QObject *, const QByteArray &); }; |