diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2016-07-19 08:00:49 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2016-07-19 08:00:49 +0000 |
commit | 90de20f17fc1b3690a263372b222682e5292e857 (patch) | |
tree | dde2a9e4c09e0c551ea9da89a963cd4985e183aa /src/quick/items | |
parent | bcd1e1bafa3ff4c8ba9288ccc8a70bdf2e11c06e (diff) | |
parent | ac79c052af096411fa7a50d30478accc15ce38ba (diff) |
Merge "Merge remote-tracking branch 'origin/dev' into HEAD" into refs/staging/wip/pointerhandler
Diffstat (limited to 'src/quick/items')
48 files changed, 1193 insertions, 1294 deletions
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri index 0c7dc97a2c..beaf3540bc 100644 --- a/src/quick/items/items.pri +++ b/src/quick/items/items.pri @@ -79,7 +79,13 @@ HEADERS += \ $$PWD/qquickrendercontrol.h \ $$PWD/qquickrendercontrol_p.h \ $$PWD/qquickgraphicsinfo_p.h \ - $$PWD/qquickitemgrabresult.h + $$PWD/qquickitemgrabresult.h \ + $$PWD/qquickspriteengine_p.h \ + $$PWD/qquicksprite_p.h \ + $$PWD/qquickspritesequence_p.h \ + $$PWD/qquickanimatedsprite_p.h \ + $$PWD/qquickanimatedsprite_p_p.h \ + $$PWD/qquickspritesequence_p_p.h SOURCES += \ $$PWD/qquickevents.cpp \ @@ -134,7 +140,11 @@ SOURCES += \ $$PWD/qquickgenericshadereffect.cpp \ $$PWD/qquickrendercontrol.cpp \ $$PWD/qquickgraphicsinfo.cpp \ - $$PWD/qquickitemgrabresult.cpp + $$PWD/qquickitemgrabresult.cpp \ + $$PWD/qquickspriteengine.cpp \ + $$PWD/qquicksprite.cpp \ + $$PWD/qquickspritesequence.cpp \ + $$PWD/qquickanimatedsprite.cpp # Items that depend on OpenGL Renderer contains(QT_CONFIG, opengl(es1|es2)?) { @@ -142,31 +152,19 @@ contains(QT_CONFIG, opengl(es1|es2)?) { $$PWD/qquickopenglinfo.cpp \ $$PWD/qquickopenglshadereffect.cpp \ $$PWD/qquickopenglshadereffectnode.cpp \ - $$PWD/qquickframebufferobject.cpp \ - $$PWD/qquickspriteengine.cpp \ - $$PWD/qquicksprite.cpp \ - $$PWD/qquickspritesequence.cpp \ - $$PWD/qquickanimatedsprite.cpp + $$PWD/qquickframebufferobject.cpp HEADERS += \ $$PWD/qquickopenglinfo_p.h \ - $$PWD/qquickspriteengine_p.h \ - $$PWD/qquicksprite_p.h \ - $$PWD/qquickspritesequence_p.h \ - $$PWD/qquickanimatedsprite_p.h \ $$PWD/qquickopenglshadereffect_p.h \ $$PWD/qquickopenglshadereffectnode_p.h \ $$PWD/qquickframebufferobject.h OTHER_FILES += \ - $$PWD/shaders/sprite.vert \ - $$PWD/shaders/sprite.frag \ $$PWD/shaders/shadereffect.vert \ $$PWD/shaders/shadereffect.frag \ $$PWD/shaders/shadereffectfallback.vert \ $$PWD/shaders/shadereffectfallback.frag \ - $$PWD/shaders/sprite_core.vert \ - $$PWD/shaders/sprite_core.frag \ $$PWD/shaders/shadereffect_core.vert \ $$PWD/shaders/shadereffect_core.frag \ $$PWD/shaders/shadereffectfallback_core.vert \ diff --git a/src/quick/items/items.qrc b/src/quick/items/items.qrc index 99f9b5224f..6aaf757c29 100644 --- a/src/quick/items/items.qrc +++ b/src/quick/items/items.qrc @@ -1,7 +1,5 @@ <RCC> <qresource prefix="/qt-project.org/items"> - <file>shaders/sprite.frag</file> - <file>shaders/sprite.vert</file> <file>shaders/shadereffect.vert</file> <file>shaders/shadereffect.frag</file> <file>shaders/shadereffectfallback.frag</file> @@ -10,7 +8,5 @@ <file>shaders/shadereffect_core.vert</file> <file>shaders/shadereffectfallback_core.frag</file> <file>shaders/shadereffectfallback_core.vert</file> - <file>shaders/sprite_core.frag</file> - <file>shaders/sprite_core.vert</file> </qresource> </RCC> diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index 4cbd41106e..b6978e534e 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -285,26 +285,26 @@ void QQuickAnchorsPrivate::clearItem(QQuickItem *item) } } -int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) +QQuickGeometryChange QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) { - QQuickItemPrivate::GeometryChangeTypes dependency = QQuickItemPrivate::NoChange; + QQuickGeometryChange dependency; if (!controlItem || inDestructor) return dependency; if (fill == controlItem) { if (controlItem == readParentItem(item)) - dependency |= QQuickItemPrivate::SizeChange; + dependency.setSizeChange(true); else //sibling - dependency |= QQuickItemPrivate::GeometryChange; + dependency.setAllChanged(true); return dependency; //exit early } if (centerIn == controlItem) { if (controlItem == readParentItem(item)) - dependency |= QQuickItemPrivate::SizeChange; + dependency.setSizeChange(true); else //sibling - dependency |= QQuickItemPrivate::GeometryChange; + dependency.setAllChanged(true); return dependency; //exit early } @@ -312,9 +312,9 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) (usedAnchors & QQuickAnchors::RightAnchor && rightAnchorItem == controlItem) || (usedAnchors & QQuickAnchors::HCenterAnchor && hCenterAnchorItem == controlItem)) { if (controlItem == readParentItem(item)) - dependency |= QQuickItemPrivate::WidthChange; + dependency.setWidthChange(true); else //sibling - dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::XChange | QQuickItemPrivate::WidthChange); + dependency.setHorizontalChange(true); } if ((usedAnchors & QQuickAnchors::TopAnchor && topAnchorItem == controlItem) || @@ -322,9 +322,9 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) (usedAnchors & QQuickAnchors::VCenterAnchor && vCenterAnchorItem == controlItem) || (usedAnchors & QQuickAnchors::BaselineAnchor && baselineAnchorItem == controlItem)) { if (controlItem == readParentItem(item)) - dependency |= QQuickItemPrivate::HeightChange; + dependency.setHeightChange(true); else //sibling - dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::YChange | QQuickItemPrivate::HeightChange); + dependency.setVerticalChange(true); } return dependency; @@ -336,7 +336,7 @@ void QQuickAnchorsPrivate::addDepend(QQuickItem *item) return; QQuickItemPrivate *p = QQuickItemPrivate::get(item); - p->updateOrAddGeometryChangeListener(this, QFlags<QQuickItemPrivate::GeometryChangeType>(calculateDependency(item))); + p->updateOrAddGeometryChangeListener(this, calculateDependency(item)); } void QQuickAnchorsPrivate::remDepend(QQuickItem *item) @@ -345,7 +345,7 @@ void QQuickAnchorsPrivate::remDepend(QQuickItem *item) return; QQuickItemPrivate *p = QQuickItemPrivate::get(item); - p->updateOrRemoveGeometryChangeListener(this, QFlags<QQuickItemPrivate::GeometryChangeType>(calculateDependency(item))); + p->updateOrRemoveGeometryChangeListener(this, calculateDependency(item)); } bool QQuickAnchors::mirrored() @@ -492,7 +492,7 @@ void QQuickAnchorsPrivate::update() } } -void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, const QRectF &oldG) +void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &) { if (!isItemComplete()) return; @@ -502,11 +502,9 @@ void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, } else if (centerIn) { centerInChanged(); } else { - if ((usedAnchors & QQuickAnchors::Horizontal_Mask) - && (newG.x() != oldG.x() || newG.width() != oldG.width())) + if ((usedAnchors & QQuickAnchors::Horizontal_Mask) && change.horizontalChange()) updateHorizontalAnchors(); - if ((usedAnchors & QQuickAnchors::Vertical_Mask) - && (newG.y() != oldG.y() || newG.height() != oldG.height())) + if ((usedAnchors & QQuickAnchors::Vertical_Mask) && change.verticalChange()) updateVerticalAnchors(); } } diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h index da659946c0..3357e134bf 100644 --- a/src/quick/items/qquickanchors_p_p.h +++ b/src/quick/items/qquickanchors_p_p.h @@ -124,7 +124,7 @@ public: void clearItem(QQuickItem *); - int calculateDependency(QQuickItem *); + QQuickGeometryChange calculateDependency(QQuickItem *); void addDepend(QQuickItem *); void remDepend(QQuickItem *); bool isItemComplete() const; @@ -141,7 +141,7 @@ public: void updateMe(); // QQuickItemGeometryListener interface - void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) Q_DECL_OVERRIDE; QQuickAnchorsPrivate *anchorPrivate() Q_DECL_OVERRIDE { return this; } bool checkHValid() const; diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 77c7ae106b..991ca8519f 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquickanimatedsprite_p.h" +#include "qquickanimatedsprite_p_p.h" #include "qquicksprite_p.h" #include "qquickspriteengine_p.h" #include <QtQuick/private/qsgcontext_p.h> @@ -55,111 +56,6 @@ QT_BEGIN_NAMESPACE -class QQuickAnimatedSpriteMaterial : public QSGMaterial -{ -public: - QQuickAnimatedSpriteMaterial(); - ~QQuickAnimatedSpriteMaterial(); - QSGMaterialType *type() const Q_DECL_OVERRIDE { static QSGMaterialType type; return &type; } - QSGMaterialShader *createShader() const Q_DECL_OVERRIDE; - int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE - { - return this - static_cast<const QQuickAnimatedSpriteMaterial *>(other); - } - - QSGTexture *texture; - - float animT; - float animX1; - float animY1; - float animX2; - float animY2; - float animW; - float animH; -}; - -QQuickAnimatedSpriteMaterial::QQuickAnimatedSpriteMaterial() - : texture(0) - , animT(0.0f) - , animX1(0.0f) - , animY1(0.0f) - , animX2(0.0f) - , animY2(0.0f) - , animW(1.0f) - , animH(1.0f) -{ - setFlag(Blending, true); -} - -QQuickAnimatedSpriteMaterial::~QQuickAnimatedSpriteMaterial() -{ - delete texture; -} - -class AnimatedSpriteMaterialData : public QSGMaterialShader -{ -public: - AnimatedSpriteMaterialData() - : QSGMaterialShader() - { - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/items/shaders/sprite.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/items/shaders/sprite.frag")); - } - - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE - { - QQuickAnimatedSpriteMaterial *m = static_cast<QQuickAnimatedSpriteMaterial *>(newEffect); - m->texture->bind(); - - program()->setUniformValue(m_opacity_id, state.opacity()); - program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT); - program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2); - - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrix_id, state.combinedMatrix()); - } - - void initialize() Q_DECL_OVERRIDE { - m_matrix_id = program()->uniformLocation("qt_Matrix"); - m_opacity_id = program()->uniformLocation("qt_Opacity"); - m_animData_id = program()->uniformLocation("animData"); - m_animPos_id = program()->uniformLocation("animPos"); - } - - char const *const *attributeNames() const Q_DECL_OVERRIDE { - static const char *attr[] = { - "vPos", - "vTex", - 0 - }; - return attr; - } - - int m_matrix_id; - int m_opacity_id; - int m_animData_id; - int m_animPos_id; -}; - -QSGMaterialShader *QQuickAnimatedSpriteMaterial::createShader() const -{ - return new AnimatedSpriteMaterialData; -} - -struct AnimatedSpriteVertex { - float x; - float y; - float tx; - float ty; -}; - -struct AnimatedSpriteVertices { - AnimatedSpriteVertex v1; - AnimatedSpriteVertex v2; - AnimatedSpriteVertex v3; - AnimatedSpriteVertex v4; -}; - /*! \qmltype AnimatedSprite \instantiates QQuickAnimatedSprite @@ -315,18 +211,11 @@ struct AnimatedSpriteVertices { //TODO: Implicitly size element to size of sprite QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) : - QQuickItem(parent) - , m_sprite(new QQuickSprite(this)) - , m_spriteEngine(0) - , m_curFrame(0) - , m_pleaseReset(false) - , m_running(true) - , m_paused(false) - , m_interpolate(true) - , m_loops(-1) - , m_curLoop(0) - , m_pauseOffset(0) + QQuickItem(*(new QQuickAnimatedSpritePrivate), parent) { + Q_D(QQuickAnimatedSprite); + d->m_sprite = new QQuickSprite(this); + setFlag(ItemHasContents); connect(this, SIGNAL(widthChanged()), this, SLOT(reset())); @@ -334,6 +223,96 @@ QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) : this, SLOT(reset())); } +bool QQuickAnimatedSprite::running() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_running; +} + +bool QQuickAnimatedSprite::interpolate() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_interpolate; +} + +QUrl QQuickAnimatedSprite::source() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->source(); +} + +bool QQuickAnimatedSprite::reverse() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->reverse(); +} + +bool QQuickAnimatedSprite::frameSync() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameSync(); +} + +int QQuickAnimatedSprite::frameCount() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frames(); +} + +int QQuickAnimatedSprite::frameHeight() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameHeight(); +} + +int QQuickAnimatedSprite::frameWidth() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameWidth(); +} + +int QQuickAnimatedSprite::frameX() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameX(); +} + +int QQuickAnimatedSprite::frameY() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameY(); +} + +qreal QQuickAnimatedSprite::frameRate() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameRate(); +} + +int QQuickAnimatedSprite::frameDuration() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameDuration(); +} + +int QQuickAnimatedSprite::loops() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_loops; +} + +bool QQuickAnimatedSprite::paused() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_paused; +} + +int QQuickAnimatedSprite::currentFrame() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_curFrame; +} + bool QQuickAnimatedSprite::isCurrentFrameChangedConnected() { IS_SIGNAL_CONNECTED(this, QQuickAnimatedSprite, currentFrameChanged, (int)); @@ -348,23 +327,25 @@ void QQuickAnimatedSprite::reloadImage() void QQuickAnimatedSprite::componentComplete() { + Q_D(const QQuickAnimatedSprite); createEngine(); QQuickItem::componentComplete(); - if (m_running) + if (d->m_running) start(); } void QQuickAnimatedSprite::start() { - m_running = true; + Q_D(QQuickAnimatedSprite); + d->m_running = true; if (!isComponentComplete()) return; - m_curLoop = 0; - m_timestamp.start(); - if (m_spriteEngine) { - m_spriteEngine->stop(0); - m_spriteEngine->updateSprites(0); - m_spriteEngine->start(0); + d->m_curLoop = 0; + d->m_timestamp.start(); + if (d->m_spriteEngine) { + d->m_spriteEngine->stop(0); + d->m_spriteEngine->updateSprites(0); + d->m_spriteEngine->start(0); } emit currentFrameChanged(0); emit runningChanged(true); @@ -373,10 +354,11 @@ void QQuickAnimatedSprite::start() void QQuickAnimatedSprite::stop() { - m_running = false; + Q_D(QQuickAnimatedSprite); + d->m_running = false; if (!isComponentComplete()) return; - m_pauseOffset = 0; + d->m_pauseOffset = 0; emit runningChanged(false); update(); } @@ -388,14 +370,15 @@ void QQuickAnimatedSprite::stop() */ void QQuickAnimatedSprite::advance(int frames) { + Q_D(QQuickAnimatedSprite); if (!frames) return; //TODO-C: May not work when running - only when paused - m_curFrame += frames; - while (m_curFrame < 0) - m_curFrame += m_spriteEngine->maxFrames(); - m_curFrame = m_curFrame % m_spriteEngine->maxFrames(); - emit currentFrameChanged(m_curFrame); + d->m_curFrame += frames; + while (d->m_curFrame < 0) + d->m_curFrame += d->m_spriteEngine->maxFrames(); + d->m_curFrame = d->m_curFrame % d->m_spriteEngine->maxFrames(); + emit currentFrameChanged(d->m_curFrame); update(); } @@ -409,10 +392,12 @@ void QQuickAnimatedSprite::advance(int frames) */ void QQuickAnimatedSprite::pause() { - if (m_paused) + Q_D(QQuickAnimatedSprite); + + if (d->m_paused) return; - m_pauseOffset = m_timestamp.elapsed(); - m_paused = true; + d->m_pauseOffset = d->m_timestamp.elapsed(); + d->m_paused = true; emit pausedChanged(true); update(); } @@ -427,246 +412,363 @@ void QQuickAnimatedSprite::pause() */ void QQuickAnimatedSprite::resume() { - if (!m_paused) + Q_D(QQuickAnimatedSprite); + + if (!d->m_paused) return; - m_pauseOffset = m_pauseOffset - m_timestamp.elapsed(); - m_paused = false; + d->m_pauseOffset = d->m_pauseOffset - d->m_timestamp.elapsed(); + d->m_paused = false; emit pausedChanged(false); update(); } -void QQuickAnimatedSprite::createEngine() +void QQuickAnimatedSprite::setRunning(bool arg) { - if (m_spriteEngine) - delete m_spriteEngine; - QList<QQuickSprite*> spriteList; - spriteList << m_sprite; - m_spriteEngine = new QQuickSpriteEngine(QList<QQuickSprite*>(spriteList), this); - m_spriteEngine->startAssemblingImage(); - reset(); - update(); + Q_D(QQuickAnimatedSprite); + + if (d->m_running != arg) { + if (d->m_running) + stop(); + else + start(); + } } -static QSGGeometry::Attribute AnimatedSprite_Attributes[] = { - QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // pos - QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // tex -}; +void QQuickAnimatedSprite::setPaused(bool arg) +{ + Q_D(const QQuickAnimatedSprite); -static QSGGeometry::AttributeSet AnimatedSprite_AttributeSet = + if (d->m_paused != arg) { + if (d->m_paused) + resume(); + else + pause(); + } +} + +void QQuickAnimatedSprite::setInterpolate(bool arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_interpolate != arg) { + d->m_interpolate = arg; + Q_EMIT interpolateChanged(arg); + } +} + +void QQuickAnimatedSprite::setSource(QUrl arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_source != arg) { + d->m_sprite->setSource(arg); + Q_EMIT sourceChanged(arg); + reloadImage(); + } +} + +void QQuickAnimatedSprite::setReverse(bool arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_reverse != arg) { + d->m_sprite->setReverse(arg); + Q_EMIT reverseChanged(arg); + } +} + +void QQuickAnimatedSprite::setFrameSync(bool arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameSync != arg) { + d->m_sprite->setFrameSync(arg); + Q_EMIT frameSyncChanged(arg); + if (d->m_running) + restart(); + } +} + +void QQuickAnimatedSprite::setFrameCount(int arg) { - 2, // Attribute Count - (2+2) * sizeof(float), - AnimatedSprite_Attributes -}; + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frames != arg) { + d->m_sprite->setFrameCount(arg); + Q_EMIT frameCountChanged(arg); + reloadImage(); + } +} -void QQuickAnimatedSprite::sizeVertices(QSGGeometryNode *node) +void QQuickAnimatedSprite::setFrameHeight(int arg) { - AnimatedSpriteVertices *p = (AnimatedSpriteVertices *) node->geometry()->vertexData(); - p->v1.x = 0; - p->v1.y = 0; + Q_D(QQuickAnimatedSprite); - p->v2.x = width(); - p->v2.y = 0; + if (d->m_sprite->m_frameHeight != arg) { + d->m_sprite->setFrameHeight(arg); + Q_EMIT frameHeightChanged(arg); + reloadImage(); + } +} - p->v3.x = 0; - p->v3.y = height(); +void QQuickAnimatedSprite::setFrameWidth(int arg) +{ + Q_D(QQuickAnimatedSprite); - p->v4.x = width(); - p->v4.y = height(); + if (d->m_sprite->m_frameWidth != arg) { + d->m_sprite->setFrameWidth(arg); + Q_EMIT frameWidthChanged(arg); + reloadImage(); + } } -QSGGeometryNode* QQuickAnimatedSprite::buildNode() +void QQuickAnimatedSprite::setFrameX(int arg) { - if (!m_spriteEngine) { + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameX != arg) { + d->m_sprite->setFrameX(arg); + Q_EMIT frameXChanged(arg); + reloadImage(); + } +} + +void QQuickAnimatedSprite::setFrameY(int arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameY != arg) { + d->m_sprite->setFrameY(arg); + Q_EMIT frameYChanged(arg); + reloadImage(); + } +} + +void QQuickAnimatedSprite::setFrameRate(qreal arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameRate != arg) { + d->m_sprite->setFrameRate(arg); + Q_EMIT frameRateChanged(arg); + if (d->m_running) + restart(); + } +} + +void QQuickAnimatedSprite::setFrameDuration(int arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameDuration != arg) { + d->m_sprite->setFrameDuration(arg); + Q_EMIT frameDurationChanged(arg); + if (d->m_running) + restart(); + } +} + +void QQuickAnimatedSprite::resetFrameRate() +{ + setFrameRate(-1.0); +} + +void QQuickAnimatedSprite::resetFrameDuration() +{ + setFrameDuration(-1); +} + +void QQuickAnimatedSprite::setLoops(int arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_loops != arg) { + d->m_loops = arg; + Q_EMIT loopsChanged(arg); + } +} + +void QQuickAnimatedSprite::setCurrentFrame(int arg) //TODO-C: Probably only works when paused +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_curFrame != arg) { + d->m_curFrame = arg; + Q_EMIT currentFrameChanged(arg); //TODO-C Only emitted on manual advance! + update(); + } +} + +void QQuickAnimatedSprite::createEngine() +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_spriteEngine) + delete d->m_spriteEngine; + QList<QQuickSprite*> spriteList; + spriteList << d->m_sprite; + d->m_spriteEngine = new QQuickSpriteEngine(QList<QQuickSprite*>(spriteList), this); + d->m_spriteEngine->startAssemblingImage(); + reset(); + update(); +} + +QSGSpriteNode* QQuickAnimatedSprite::initNode() +{ + Q_D(QQuickAnimatedSprite); + + if (!d->m_spriteEngine) { qmlInfo(this) << "No sprite engine..."; - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Null) { - m_spriteEngine->startAssemblingImage(); + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Null) { + d->m_spriteEngine->startAssemblingImage(); update();//Schedule another update, where we will check again - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Loading) { + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Loading) { update();//Schedule another update, where we will check again - return 0; + return nullptr; } - QQuickAnimatedSpriteMaterial *material = new QQuickAnimatedSpriteMaterial(); - - QImage image = m_spriteEngine->assembledImage(); //Engine prints errors if there are any + QImage image = d->m_spriteEngine->assembledImage(d->sceneGraphRenderContext()->maxTextureSize()); //Engine prints errors if there are any if (image.isNull()) - return 0; - m_sheetSize = QSizeF(image.size()); - material->texture = window()->createTextureFromImage(image); - m_spriteEngine->start(0); - material->animT = 0; - material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width(); - material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height(); - material->animX2 = material->animX1; - material->animY2 = material->animY1; - material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - - int vCount = 4; - int iCount = 6; - QSGGeometry *g = new QSGGeometry(AnimatedSprite_AttributeSet, vCount, iCount); - g->setDrawingMode(GL_TRIANGLES); - - AnimatedSpriteVertices *p = (AnimatedSpriteVertices *) g->vertexData(); - - QRectF texRect = material->texture->normalizedTextureSubRect(); - - p->v1.tx = texRect.topLeft().x(); - p->v1.ty = texRect.topLeft().y(); - - p->v2.tx = texRect.topRight().x(); - p->v2.ty = texRect.topRight().y(); - - p->v3.tx = texRect.bottomLeft().x(); - p->v3.ty = texRect.bottomLeft().y(); - - p->v4.tx = texRect.bottomRight().x(); - p->v4.ty = texRect.bottomRight().y(); - - quint16 *indices = g->indexDataAsUShort(); - indices[0] = 0; - indices[1] = 1; - indices[2] = 2; - indices[3] = 1; - indices[4] = 3; - indices[5] = 2; - - - QSGGeometryNode *node = new QSGGeometryNode(); - node->setGeometry(g); - node->setMaterial(material); - node->setFlag(QSGGeometryNode::OwnsMaterial); - node->setFlag(QSGGeometryNode::OwnsGeometry); - sizeVertices(node); + return nullptr; + + QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); + + d->m_sheetSize = QSize(image.size()); + node->setTexture(window()->createTextureFromImage(image)); + d->m_spriteEngine->start(0); + node->setTime(0.0f); + node->setSourceA(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSourceB(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSpriteSize(QSize(d->m_spriteEngine->spriteWidth(), d->m_spriteEngine->spriteHeight())); + node->setSheetSize(d->m_sheetSize); + node->setSize(QSizeF(width(), height())); return node; } void QQuickAnimatedSprite::reset() { - m_pleaseReset = true; + Q_D(QQuickAnimatedSprite); + d->m_pleaseReset = true; update(); } QSGNode *QQuickAnimatedSprite::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { - if (m_pleaseReset) { + Q_D(QQuickAnimatedSprite); + + if (d->m_pleaseReset) { delete oldNode; - oldNode = 0; - m_pleaseReset = false; + oldNode = nullptr; + d->m_pleaseReset = false; } - QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode); + QSGSpriteNode *node = static_cast<QSGSpriteNode *>(oldNode); if (!node) - node = buildNode(); + node = initNode(); if (node) prepareNextFrame(node); - if (m_running) { - if (!m_paused) - update(); - - if (node) { - node->markDirty(QSGNode::DirtyMaterial); - } - } + if (d->m_running && !d->m_paused) + update(); return node; } -void QQuickAnimatedSprite::prepareNextFrame(QSGGeometryNode *node) +void QQuickAnimatedSprite::prepareNextFrame(QSGSpriteNode *node) { - int timeInt = m_timestamp.elapsed() + m_pauseOffset; + Q_D(QQuickAnimatedSprite); + + int timeInt = d->m_timestamp.elapsed() + d->m_pauseOffset; qreal time = timeInt / 1000.; int frameAt; qreal progress = 0.0; - int lastFrame = m_curFrame; - if (m_running && !m_paused) { - const int nColumns = int(m_sheetSize.width()) / m_spriteEngine->spriteWidth(); + int lastFrame = d->m_curFrame; + if (d->m_running && !d->m_paused) { + const int nColumns = d->m_sheetSize.width() / d->m_spriteEngine->spriteWidth(); //Advance State (keeps time for psuedostates) - m_spriteEngine->updateSprites(timeInt); + d->m_spriteEngine->updateSprites(timeInt); //Advance AnimatedSprite - qreal animT = m_spriteEngine->spriteStart()/1000.0; - const int frameCountInRow = m_spriteEngine->spriteFrames(); - const qreal frameDuration = m_spriteEngine->spriteDuration()/frameCountInRow; + qreal animT = d->m_spriteEngine->spriteStart()/1000.0; + const int frameCountInRow = d->m_spriteEngine->spriteFrames(); + const qreal frameDuration = d->m_spriteEngine->spriteDuration() / frameCountInRow; if (frameDuration > 0) { qreal frame = (time - animT)/(frameDuration / 1000.0); - bool lastLoop = m_loops > 0 && m_curLoop == m_loops-1; + bool lastLoop = d->m_loops > 0 && d->m_curLoop == d->m_loops-1; //don't visually interpolate for the last frame of the last loop const int max = lastLoop ? frameCountInRow - 1 : frameCountInRow; frame = qBound(qreal(0.0), frame, qreal(max)); double intpart; progress = std::modf(frame,&intpart); frameAt = (int)intpart; - const int rowIndex = m_spriteEngine->spriteY()/frameHeight(); + const int rowIndex = d->m_spriteEngine->spriteY()/frameHeight(); const int newFrame = rowIndex * nColumns + frameAt; - if (m_curFrame > newFrame) //went around - m_curLoop++; - m_curFrame = newFrame; + if (d->m_curFrame > newFrame) //went around + d->m_curLoop++; + d->m_curFrame = newFrame; } else { - m_curFrame++; - if (m_curFrame >= m_spriteEngine->maxFrames()) { // maxFrames: total number of frames including all rows - m_curFrame = 0; - m_curLoop++; + d->m_curFrame++; + if (d->m_curFrame >= d->m_spriteEngine->maxFrames()) { // maxFrames: total number of frames including all rows + d->m_curFrame = 0; + d->m_curLoop++; } - frameAt = m_curFrame % nColumns; + frameAt = d->m_curFrame % nColumns; if (frameAt == 0) - m_spriteEngine->advance(); + d->m_spriteEngine->advance(); progress = 0; } - if (m_loops > 0 && m_curLoop >= m_loops) { + if (d->m_loops > 0 && d->m_curLoop >= d->m_loops) { frameAt = 0; - m_running = false; + d->m_running = false; emit runningChanged(false); update(); } } else { - frameAt = m_curFrame; + frameAt = d->m_curFrame; } - if (m_curFrame != lastFrame) { + if (d->m_curFrame != lastFrame) { if (isCurrentFrameChangedConnected()) - emit currentFrameChanged(m_curFrame); + emit currentFrameChanged(d->m_curFrame); update(); } - qreal frameCount = m_spriteEngine->spriteFrames(); - bool reverse = m_spriteEngine->sprite()->reverse(); + qreal frameCount = d->m_spriteEngine->spriteFrames(); + bool reverse = d->m_spriteEngine->sprite()->reverse(); if (reverse) frameAt = (frameCount - 1) - frameAt; - qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - qreal x1; - qreal y1; - if (m_paused) { - int spriteY = m_spriteEngine->spriteY(); + int w = d->m_spriteEngine->spriteWidth(); + int h = d->m_spriteEngine->spriteHeight(); + int x1; + int y1; + if (d->m_paused) { + int spriteY = d->m_spriteEngine->spriteY(); if (reverse) { - int rows = m_spriteEngine->maxFrames() * m_spriteEngine->spriteWidth() / m_sheetSize.width(); - spriteY -= rows * m_spriteEngine->spriteHeight(); + int rows = d->m_spriteEngine->maxFrames() * d->m_spriteEngine->spriteWidth() / d->m_sheetSize.width(); + spriteY -= rows * d->m_spriteEngine->spriteHeight(); frameAt = (frameCount - 1) - frameAt; } - int position = frameAt * m_spriteEngine->spriteWidth() + m_spriteEngine->spriteX(); - int row = position / m_sheetSize.width(); + int position = frameAt * d->m_spriteEngine->spriteWidth() + d->m_spriteEngine->spriteX(); + int row = position / d->m_sheetSize.width(); - x1 = (position - (row * m_sheetSize.width())) / m_sheetSize.width(); - y1 = (row * m_spriteEngine->spriteHeight() + spriteY) / m_sheetSize.height(); + x1 = (position - (row * d->m_sheetSize.width())); + y1 = (row * d->m_spriteEngine->spriteHeight() + spriteY); } else { - x1 = m_spriteEngine->spriteX() / m_sheetSize.width() + frameAt * w; - y1 = m_spriteEngine->spriteY() / m_sheetSize.height(); + x1 = d->m_spriteEngine->spriteX() + frameAt * w; + y1 = d->m_spriteEngine->spriteY(); } //### hard-coded 0/1 work because we are the only // images in the sprite sheet (without this we cannot assume // where in the sheet we begin/end). - qreal x2; - qreal y2; + int x2; + int y2; if (reverse) { if (frameAt > 0) { x2 = x1 - w; @@ -676,9 +778,9 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGGeometryNode *node) y2 = y1 - h; if (y2 < 0.0) { //the last row may not fill the entire width - int maxRowFrames = m_sheetSize.width() / m_spriteEngine->spriteWidth(); - if (m_spriteEngine->maxFrames() % maxRowFrames) - x2 = ((m_spriteEngine->maxFrames() % maxRowFrames) - 1) * w; + int maxRowFrames = d->m_sheetSize.width() / d->m_spriteEngine->spriteWidth(); + if (d->m_spriteEngine->maxFrames() % maxRowFrames) + x2 = ((d->m_spriteEngine->maxFrames() % maxRowFrames) - 1) * w; y2 = 1.0 - h; } @@ -695,15 +797,13 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGGeometryNode *node) } } - QQuickAnimatedSpriteMaterial *material = static_cast<QQuickAnimatedSpriteMaterial *>(node->material()); - material->animX1 = x1; - material->animY1 = y1; - material->animX2 = x2; - material->animY2 = y2; - material->animW = w; - material->animH = h; - material->animT = m_interpolate ? progress : 0.0; - material->texture->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + node->setSourceA(QPoint(x1, y1)); + node->setSourceB(QPoint(x2, y2)); + node->setSpriteSize(QSize(w, h)); + node->setTime(d->m_interpolate ? progress : 0.0); + node->setSize(QSizeF(width(), height())); + node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + node->update(); } QT_END_NAMESPACE diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h index 1e5981c1a4..cbd6524c40 100644 --- a/src/quick/items/qquickanimatedsprite_p.h +++ b/src/quick/items/qquickanimatedsprite_p.h @@ -62,6 +62,8 @@ class QQuickSprite; class QQuickSpriteEngine; class QSGGeometryNode; class QQuickAnimatedSpriteMaterial; +class QQuickAnimatedSpritePrivate; +class QSGSpriteNode; class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem { Q_OBJECT @@ -94,80 +96,21 @@ public: }; Q_ENUM(LoopParameters) - bool running() const - { - return m_running; - } - - bool interpolate() const - { - return m_interpolate; - } - - QUrl source() const - { - return m_sprite->source(); - } - - bool reverse() const - { - return m_sprite->reverse(); - } - - bool frameSync() const - { - return m_sprite->frameSync(); - } - - int frameCount() const - { - return m_sprite->frames(); - } - - int frameHeight() const - { - return m_sprite->frameHeight(); - } - - int frameWidth() const - { - return m_sprite->frameWidth(); - } - - int frameX() const - { - return m_sprite->frameX(); - } - - int frameY() const - { - return m_sprite->frameY(); - } - - qreal frameRate() const - { - return m_sprite->frameRate(); - } - - int frameDuration() const - { - return m_sprite->frameDuration(); - } - - int loops() const - { - return m_loops; - } - - bool paused() const - { - return m_paused; - } - - int currentFrame() const - { - return m_curFrame; - } + bool running() const; + bool interpolate() const; + QUrl source() const; + bool reverse() const; + bool frameSync() const; + int frameCount() const; + int frameHeight() const; + int frameWidth() const; + int frameX() const; + int frameY() const; + qreal frameRate() const; + int frameDuration() const; + int loops() const; + bool paused() const; + int currentFrame() const; Q_SIGNALS: @@ -176,27 +119,16 @@ Q_SIGNALS: void interpolateChanged(bool arg); void sourceChanged(QUrl arg); - void reverseChanged(bool arg); - void frameSyncChanged(bool arg); - void frameCountChanged(int arg); - void frameHeightChanged(int arg); - void frameWidthChanged(int arg); - void frameXChanged(int arg); - void frameYChanged(int arg); - void frameRateChanged(qreal arg); - void frameDurationChanged(int arg); - void loopsChanged(int arg); - void currentFrameChanged(int arg); public Q_SLOTS: @@ -207,157 +139,27 @@ public Q_SLOTS: void pause(); void resume(); - void setRunning(bool arg) - { - if (m_running != arg) { - if (m_running) - stop(); - else - start(); - } - } - - void setPaused(bool arg) - { - if (m_paused != arg) { - if (m_paused) - resume(); - else - pause(); - } - } - - void setInterpolate(bool arg) - { - if (m_interpolate != arg) { - m_interpolate = arg; - Q_EMIT interpolateChanged(arg); - } - } - - void setSource(QUrl arg) - { - if (m_sprite->m_source != arg) { - m_sprite->setSource(arg); - Q_EMIT sourceChanged(arg); - reloadImage(); - } - } - - void setReverse(bool arg) - { - if (m_sprite->m_reverse != arg) { - m_sprite->setReverse(arg); - Q_EMIT reverseChanged(arg); - } - } - - void setFrameSync(bool arg) - { - if (m_sprite->m_frameSync != arg) { - m_sprite->setFrameSync(arg); - Q_EMIT frameSyncChanged(arg); - if (m_running) - restart(); - } - } - - void setFrameCount(int arg) - { - if (m_sprite->m_frames != arg) { - m_sprite->setFrameCount(arg); - Q_EMIT frameCountChanged(arg); - reloadImage(); - } - } - - void setFrameHeight(int arg) - { - if (m_sprite->m_frameHeight != arg) { - m_sprite->setFrameHeight(arg); - Q_EMIT frameHeightChanged(arg); - reloadImage(); - } - } - - void setFrameWidth(int arg) - { - if (m_sprite->m_frameWidth != arg) { - m_sprite->setFrameWidth(arg); - Q_EMIT frameWidthChanged(arg); - reloadImage(); - } - } - - void setFrameX(int arg) - { - if (m_sprite->m_frameX != arg) { - m_sprite->setFrameX(arg); - Q_EMIT frameXChanged(arg); - reloadImage(); - } - } - - void setFrameY(int arg) - { - if (m_sprite->m_frameY != arg) { - m_sprite->setFrameY(arg); - Q_EMIT frameYChanged(arg); - reloadImage(); - } - } - - void setFrameRate(qreal arg) - { - if (m_sprite->m_frameRate != arg) { - m_sprite->setFrameRate(arg); - Q_EMIT frameRateChanged(arg); - if (m_running) - restart(); - } - } - - void setFrameDuration(int arg) - { - if (m_sprite->m_frameDuration != arg) { - m_sprite->setFrameDuration(arg); - Q_EMIT frameDurationChanged(arg); - if (m_running) - restart(); - } - } - - void resetFrameRate() - { - setFrameRate(-1.0); - } - - void resetFrameDuration() - { - setFrameDuration(-1); - } - - void setLoops(int arg) - { - if (m_loops != arg) { - m_loops = arg; - Q_EMIT loopsChanged(arg); - } - } - - void setCurrentFrame(int arg) //TODO-C: Probably only works when paused - { - if (m_curFrame != arg) { - m_curFrame = arg; - Q_EMIT currentFrameChanged(arg); //TODO-C Only emitted on manual advance! - update(); - } - } + void setRunning(bool arg); + void setPaused(bool arg); + void setInterpolate(bool arg); + void setSource(QUrl arg); + void setReverse(bool arg); + void setFrameSync(bool arg); + void setFrameCount(int arg); + void setFrameHeight(int arg); + void setFrameWidth(int arg); + void setFrameX(int arg); + void setFrameY(int arg); + void setFrameRate(qreal arg); + void setFrameDuration(int arg); + void resetFrameRate(); + void resetFrameDuration(); + void setLoops(int arg); + void setCurrentFrame(int arg); private Q_SLOTS: void createEngine(); - void sizeVertices(QSGGeometryNode *node); protected Q_SLOTS: void reset(); @@ -367,21 +169,13 @@ protected: QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; private: bool isCurrentFrameChangedConnected(); - void prepareNextFrame(QSGGeometryNode *node); + void prepareNextFrame(QSGSpriteNode *node); void reloadImage(); - QSGGeometryNode* buildNode(); - QQuickSprite* m_sprite; - QQuickSpriteEngine* m_spriteEngine; - QElapsedTimer m_timestamp; - int m_curFrame; - bool m_pleaseReset; - bool m_running; - bool m_paused; - bool m_interpolate; - QSizeF m_sheetSize; - int m_loops; - int m_curLoop; - int m_pauseOffset; + QSGSpriteNode* initNode(); + +private: + Q_DISABLE_COPY(QQuickAnimatedSprite) + Q_DECLARE_PRIVATE(QQuickAnimatedSprite) }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickanimatedsprite_p_p.h b/src/quick/items/qquickanimatedsprite_p_p.h new file mode 100644 index 0000000000..0e4a1e9066 --- /dev/null +++ b/src/quick/items/qquickanimatedsprite_p_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKANIMATEDSPRITE_P_P_H +#define QQUICKANIMATEDSPRITE_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickitem_p.h" +#include "qquicksprite_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickAnimatedSprite; + +class QQuickAnimatedSpritePrivate : public QQuickItemPrivate +{ + Q_DECLARE_PUBLIC(QQuickAnimatedSprite) + +public: + QQuickAnimatedSpritePrivate() + : m_sprite(nullptr) + , m_spriteEngine(nullptr) + , m_curFrame(0) + , m_pleaseReset(false) + , m_running(true) + , m_paused(false) + , m_interpolate(true) + , m_loops(-1) + , m_curLoop(0) + , m_pauseOffset(0) + { + } + + QQuickSprite* m_sprite; + QQuickSpriteEngine* m_spriteEngine; + QElapsedTimer m_timestamp; + int m_curFrame; + bool m_pleaseReset; + bool m_running; + bool m_paused; + bool m_interpolate; + QSize m_sheetSize; + int m_loops; + int m_curLoop; + int m_pauseOffset; +}; + +QT_END_NAMESPACE + +#endif // QQUICKANIMATEDSPRITE_P_P_H diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index cc30199253..8a0af6c263 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -82,7 +82,7 @@ public: { } - void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) Q_DECL_OVERRIDE; void itemParentChanged(QQuickItem *, QQuickItem *parent) Q_DECL_OVERRIDE; void updatePosition(); void restartDrag(); @@ -148,9 +148,10 @@ public: \sa {Qt Quick Examples - Drag and Drop}, {Qt Quick Examples - externaldraganddrop} */ -void QQuickDragAttachedPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry) +void QQuickDragAttachedPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, + const QRectF &) { - if (newGeometry.topLeft() == oldGeometry.topLeft() || !active || itemMoved) + if (!change.positionChange() || !active || itemMoved) return; updatePosition(); } diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index ca929bfab5..f9668eb434 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -222,6 +222,22 @@ private: bool _accepted; }; +class Q_QUICK_PRIVATE_EXPORT QQuickCloseEvent : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) + +public: + QQuickCloseEvent() + : _accepted(true) {} + + bool isAccepted() { return _accepted; } + void setAccepted(bool accepted) { _accepted = accepted; } + +private: + bool _accepted; +}; + class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject { Q_OBJECT @@ -461,6 +477,7 @@ QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickKeyEvent) QML_DECLARE_TYPE(QQuickMouseEvent) QML_DECLARE_TYPE(QQuickWheelEvent) +QML_DECLARE_TYPE(QQuickCloseEvent) QML_DECLARE_TYPE(QQuickPointerDevice) QML_DECLARE_TYPE(QPointerUniqueId) QML_DECLARE_TYPE(QQuickPointerEvent) diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 1bcc3cc0f9..a09088dfed 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -292,14 +292,14 @@ void QQuickFlickablePrivate::AxisData::updateVelocity() } } -void QQuickFlickablePrivate::itemGeometryChanged(QQuickItem *item, const QRectF &newGeom, const QRectF &oldGeom) +void QQuickFlickablePrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) { Q_Q(QQuickFlickable); if (item == contentItem) { Qt::Orientations orient = 0; - if (newGeom.x() != oldGeom.x()) + if (change.xChange()) orient |= Qt::Horizontal; - if (newGeom.y() != oldGeom.y()) + if (change.yChange()) orient |= Qt::Vertical; if (orient) q->viewportMoved(orient); diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 3d2b32286f..ac1e39d829 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -194,7 +194,7 @@ public: qreal overShootDistance(qreal size); - void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) Q_DECL_OVERRIDE; void draggingStarting(); void draggingEnding(); diff --git a/src/quick/items/qquickgenericshadereffect.cpp b/src/quick/items/qquickgenericshadereffect.cpp index 683453d4ee..9714f39663 100644 --- a/src/quick/items/qquickgenericshadereffect.cpp +++ b/src/quick/items/qquickgenericshadereffect.cpp @@ -305,8 +305,16 @@ void QQuickGenericShaderEffect::maybeUpdateShaders() m_vertNeedsUpdate = !updateShader(Vertex, m_vertShader); if (m_fragNeedsUpdate) m_fragNeedsUpdate = !updateShader(Fragment, m_fragShader); - if (m_vertNeedsUpdate || m_fragNeedsUpdate) - m_item->polish(); + if (m_vertNeedsUpdate || m_fragNeedsUpdate) { + // This function is invoked either from componentComplete or in a + // response to a previous invocation's polish() request. If this is + // case #1 then updateShader can fail due to not having a window or + // scenegraph ready. Schedule the polish to try again later. In case #2 + // the backend probably does not have shadereffect support so there is + // nothing to do for us here. + if (!m_item->window() || !m_item->window()->isSceneGraphInitialized()) + m_item->polish(); + } } void QQuickGenericShaderEffect::handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) diff --git a/src/quick/items/qquickimplicitsizeitem.cpp b/src/quick/items/qquickimplicitsizeitem.cpp index 5dadf81ce4..08886329fd 100644 --- a/src/quick/items/qquickimplicitsizeitem.cpp +++ b/src/quick/items/qquickimplicitsizeitem.cpp @@ -42,6 +42,19 @@ QT_BEGIN_NAMESPACE +/*! + \internal + + The purpose of QQuickImplicitSizeItem is not immediately clear, as both + the implicit size properties and signals exist on QQuickItem. However, + for some items - where the implicit size has an underlying meaning (such as + Image, where the implicit size represents the real size of the image) + having implicit size writable is an undesirable thing. + + QQuickImplicitSizeItem redefines the properties as being readonly. + Unfortunately, this also means they need to redefine the change signals. + See QTBUG-30258 for more information. +*/ void QQuickImplicitSizeItemPrivate::implicitWidthChanged() { Q_Q(QQuickImplicitSizeItem); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index d49283a3e1..07a415eecd 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -88,10 +88,6 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET) Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) -#ifndef QT_NO_DEBUG -static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK"); -#endif - void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1) { if (DBG_FOCUS().isEnabled(QtDebugMsg)) { @@ -102,7 +98,7 @@ void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1) << item->hasActiveFocus() << item->isFocusScope() << item; - foreach (QQuickItem *child, item->childItems()) { + for (QQuickItem *child : item->childItems()) { debugFocusTree( child, item->isFocusScope() || !scope ? item : scope, @@ -117,17 +113,17 @@ static void QQuickItem_parentNotifier(QObject *o, QQmlNotifier **n) *n = &d->parentNotifier; } -QML_PRIVATE_ACCESSOR(QQuickItem, QQuickItem *, parent, parentItem) -QML_PRIVATE_ACCESSOR(QQuickItem, qreal, x, x) -QML_PRIVATE_ACCESSOR(QQuickItem, qreal, y, y) -QML_PRIVATE_ACCESSOR(QQuickItem, qreal, width, width) -QML_PRIVATE_ACCESSOR(QQuickItem, qreal, height, height) +QML_PRIVATE_ACCESSOR(QQuickItem, QQuickItem *, parent, parentItem, setParentItem) +QML_PRIVATE_ACCESSOR(QQuickItem, qreal, x, x, setX) +QML_PRIVATE_ACCESSOR(QQuickItem, qreal, y, y, setY) +QML_PRIVATE_ACCESSOR(QQuickItem, qreal, width, width, setWidth) +QML_PRIVATE_ACCESSOR(QQuickItem, qreal, height, height, setHeight) -static QQmlAccessors QQuickItem_parent = { QQuickItem_parentRead, QQuickItem_parentNotifier }; -static QQmlAccessors QQuickItem_x = { QQuickItem_xRead, 0 }; -static QQmlAccessors QQuickItem_y = { QQuickItem_yRead, 0 }; -static QQmlAccessors QQuickItem_width = { QQuickItem_widthRead, 0 }; -static QQmlAccessors QQuickItem_height = { QQuickItem_heightRead, 0 }; +static QQmlAccessors QQuickItem_parent = { QQuickItem_parentRead, QQuickItem_parentWrite, QQuickItem_parentNotifier }; +static QQmlAccessors QQuickItem_x = { QQuickItem_xRead, QQuickItem_xWrite, 0 }; +static QQmlAccessors QQuickItem_y = { QQuickItem_yRead, QQuickItem_yWrite, 0 }; +static QQmlAccessors QQuickItem_width = { QQuickItem_widthRead, QQuickItem_widthWrite, 0 }; +static QQmlAccessors QQuickItem_height = { QQuickItem_heightRead, QQuickItem_heightWrite, 0 }; QML_DECLARE_PROPERTIES(QQuickItem) { { QML_PROPERTY_NAME(parent), 0, &QQuickItem_parent }, @@ -181,8 +177,8 @@ QQuickTransform::QQuickTransform(QQuickTransformPrivate &dd, QObject *parent) QQuickTransform::~QQuickTransform() { Q_D(QQuickTransform); - for (int ii = 0; ii < d->items.count(); ++ii) { - QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii)); + for (QQuickItem *item : qAsConst(d->items)) { + QQuickItemPrivate *p = QQuickItemPrivate::get(item); p->transforms.removeOne(this); p->dirty(QQuickItemPrivate::Transform); } @@ -191,8 +187,8 @@ QQuickTransform::~QQuickTransform() void QQuickTransform::update() { Q_D(QQuickTransform); - for (int ii = 0; ii < d->items.count(); ++ii) { - QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii)); + for (QQuickItem *item : qAsConst(d->items)) { + QQuickItemPrivate *p = QQuickItemPrivate::get(item); p->dirty(QQuickItemPrivate::Transform); } } @@ -204,9 +200,7 @@ QQuickContents::QQuickContents(QQuickItem *item) QQuickContents::~QQuickContents() { - QList<QQuickItem *> children = m_item->childItems(); - for (int i = 0; i < children.count(); ++i) { - QQuickItem *child = children.at(i); + for (QQuickItem *child : m_item->childItems()) { QQuickItemPrivate::get(child)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); } } @@ -229,9 +223,8 @@ bool QQuickContents::calcHeight(QQuickItem *changed) } else { qreal top = std::numeric_limits<qreal>::max(); qreal bottom = -std::numeric_limits<qreal>::max(); - QList<QQuickItem *> children = m_item->childItems(); - for (int i = 0; i < children.count(); ++i) { - QQuickItem *child = children.at(i); + const QList<QQuickItem*> children = m_item->childItems(); + for (QQuickItem *child : qAsConst(children)) { qreal y = child->y(); if (y + child->height() > bottom) bottom = y + child->height(); @@ -264,9 +257,8 @@ bool QQuickContents::calcWidth(QQuickItem *changed) } else { qreal left = std::numeric_limits<qreal>::max(); qreal right = -std::numeric_limits<qreal>::max(); - QList<QQuickItem *> children = m_item->childItems(); - for (int i = 0; i < children.count(); ++i) { - QQuickItem *child = children.at(i); + const QList<QQuickItem*> children = m_item->childItems(); + for (QQuickItem *child : qAsConst(children)) { qreal x = child->x(); if (x + child->width() > right) right = x + child->width(); @@ -285,9 +277,7 @@ void QQuickContents::complete() { QQuickItemPrivate::get(m_item)->addItemChangeListener(this, QQuickItemPrivate::Children); - QList<QQuickItem *> children = m_item->childItems(); - for (int i = 0; i < children.count(); ++i) { - QQuickItem *child = children.at(i); + for (QQuickItem *child : m_item->childItems()) { QQuickItemPrivate::get(child)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); //###what about changes to visibility? } @@ -299,15 +289,15 @@ void QQuickContents::updateRect() QQuickItemPrivate::get(m_item)->emitChildrenRectChanged(rectF()); } -void QQuickContents::itemGeometryChanged(QQuickItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry) +void QQuickContents::itemGeometryChanged(QQuickItem *changed, QQuickGeometryChange change, const QRectF &) { Q_UNUSED(changed) bool wChanged = false; bool hChanged = false; //### we can only pass changed if the left edge has moved left, or the right edge has moved right - if (newGeometry.width() != oldGeometry.width() || newGeometry.x() != oldGeometry.x()) + if (change.horizontalChange()) wChanged = calcWidth(/*changed*/); - if (newGeometry.height() != oldGeometry.height() || newGeometry.y() != oldGeometry.y()) + if (change.verticalChange()) hChanged = calcHeight(/*changed*/); if (wChanged || hChanged) updateRect(); @@ -1342,8 +1332,7 @@ void QQuickKeysAttached::componentComplete() #ifndef QT_NO_IM Q_D(QQuickKeysAttached); if (d->item) { - for (int ii = 0; ii < d->targets.count(); ++ii) { - QQuickItem *targetItem = d->targets.at(ii); + for (QQuickItem *targetItem : qAsConst(d->targets)) { if (targetItem && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) { d->item->setFlag(QQuickItem::ItemAcceptsInputMethod); break; @@ -1365,11 +1354,10 @@ void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post) // first process forwards if (d->item && d->item->window()) { d->inPress = true; - for (int ii = 0; ii < d->targets.count(); ++ii) { - QQuickItem *i = d->targets.at(ii); - if (i && i->isVisible()) { + for (QQuickItem *targetItem : qAsConst(d->targets)) { + if (targetItem && targetItem->isVisible()) { event->accept(); - QCoreApplication::sendEvent(i, event); + QCoreApplication::sendEvent(targetItem, event); if (event->isAccepted()) { d->inPress = false; return; @@ -1409,11 +1397,10 @@ void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post) if (d->item && d->item->window()) { d->inRelease = true; - for (int ii = 0; ii < d->targets.count(); ++ii) { - QQuickItem *i = d->targets.at(ii); - if (i && i->isVisible()) { + for (QQuickItem *targetItem : qAsConst(d->targets)) { + if (targetItem && targetItem->isVisible()) { event->accept(); - QCoreApplication::sendEvent(i, event); + QCoreApplication::sendEvent(targetItem, event); if (event->isAccepted()) { d->inRelease = false; return; @@ -1437,12 +1424,11 @@ void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post) Q_D(QQuickKeysAttached); if (post == m_processPost && d->item && !d->inIM && d->item->window()) { d->inIM = true; - for (int ii = 0; ii < d->targets.count(); ++ii) { - QQuickItem *i = d->targets.at(ii); - if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod)) { - d->item->window()->sendEvent(i, event); + for (QQuickItem *targetItem : qAsConst(d->targets)) { + if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) { + d->item->window()->sendEvent(targetItem, event); if (event->isAccepted()) { - d->imeItem = i; + d->imeItem = targetItem; d->inIM = false; return; } @@ -1457,13 +1443,12 @@ QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const { Q_D(const QQuickKeysAttached); if (d->item) { - for (int ii = 0; ii < d->targets.count(); ++ii) { - QQuickItem *i = d->targets.at(ii); - if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod) && i == d->imeItem) { - //### how robust is i == d->imeItem check? - QVariant v = i->inputMethodQuery(query); + for (QQuickItem *targetItem : qAsConst(d->targets)) { + if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod) && targetItem == d->imeItem) { + //### how robust is targetItem == d->imeItem check? + QVariant v = targetItem->inputMethodQuery(query); if (v.userType() == QVariant::RectF) - v = d->item->mapRectFromItem(i, v.toRectF()); //### cost? + v = d->item->mapRectFromItem(targetItem, v.toRectF()); //### cost? return v; } } @@ -1620,11 +1605,9 @@ void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit) if (isMirrorImplicit) setLayoutMirror(inherit ? inheritedLayoutMirror : false); - for (int i = 0; i < childItems.count(); ++i) { - if (QQuickItem *child = qmlobject_cast<QQuickItem *>(childItems.at(i))) { - QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); - childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent); - } + for (QQuickItem *child : qAsConst(childItems)) { + QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); + childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent); } } @@ -2328,29 +2311,11 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent) d->init(parent); } -#ifndef QT_NO_DEBUG -static int qt_item_count = 0; - -static void qt_print_item_count() -{ - qDebug("Number of leaked items: %i", qt_item_count); - qt_item_count = -1; -} -#endif - /*! Destroys the QQuickItem. */ QQuickItem::~QQuickItem() { -#ifndef QT_NO_DEBUG - if (qsg_leak_check) { - --qt_item_count; - if (qt_item_count < 0) - qDebug("Item destroyed after qt_print_item_count() was called."); - } -#endif - Q_D(QQuickItem); if (d->windowRefCount > 1) @@ -2364,7 +2329,7 @@ QQuickItem::~QQuickItem() while (!d->childItems.isEmpty()) d->childItems.constFirst()->setParentItem(0); - const auto listeners = d->changeListeners; + const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); if (anchor) @@ -2393,8 +2358,7 @@ QQuickItem::~QQuickItem() remove themselves from our list of transforms when that list has already been destroyed after ~QQuickItem() has run. */ - for (int ii = 0; ii < d->transforms.count(); ++ii) { - QQuickTransform *t = d->transforms.at(ii); + for (QQuickTransform *t : qAsConst(d->transforms)) { QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t); tp->items.removeOne(this); } @@ -2885,8 +2849,8 @@ QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const // If none of the items have set Z then the paint order list is the same as // the childItems list. This is by far the most common case. bool haveZ = false; - for (int i = 0; i < childItems.count(); ++i) { - if (QQuickItemPrivate::get(childItems.at(i))->z() != 0.) { + for (QQuickItem *childItem : qAsConst(childItems)) { + if (QQuickItemPrivate::get(childItem)->z() != 0.) { haveZ = true; break; } @@ -2915,7 +2879,7 @@ void QQuickItemPrivate::addChild(QQuickItem *child) // if the added child has a cursor and we do not currently have any children // with cursors, bubble the notification up - if (childPrivate->hasCursorInChild && !hasCursorInChild) + if (childPrivate->subtreeCursorEnabled && !subtreeCursorEnabled) setHasCursorInChild(true); #endif if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled) @@ -2942,7 +2906,7 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); // turn it off, if nothing else is using it - if (childPrivate->hasCursorInChild && hasCursorInChild) + if (childPrivate->subtreeCursorEnabled && subtreeCursorEnabled) setHasCursorInChild(false); #endif if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled) @@ -2985,8 +2949,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c) if (!parentItem) QQuickWindowPrivate::get(window)->parentlessItems.insert(q); - for (int ii = 0; ii < childItems.count(); ++ii) { - QQuickItem *child = childItems.at(ii); + for (QQuickItem *child : qAsConst(childItems)) { QQuickItemPrivate::get(child)->refWindow(c); } @@ -3038,8 +3001,7 @@ void QQuickItemPrivate::derefWindow() paintNode = 0; - for (int ii = 0; ii < childItems.count(); ++ii) { - QQuickItem *child = childItems.at(ii); + for (QQuickItem *child : qAsConst(childItems)) { QQuickItemPrivate::get(child)->derefWindow(); } @@ -3162,7 +3124,7 @@ QQuickItemPrivate::QQuickItemPrivate() , isAccessible(false) , culled(false) , hasCursor(false) - , hasCursorInChild(false) + , subtreeCursorEnabled(false) , subtreeHoverEnabled(false) , activeFocusOnTab(false) , implicitAntialiasing(false) @@ -3197,17 +3159,6 @@ QQuickItemPrivate::~QQuickItemPrivate() void QQuickItemPrivate::init(QQuickItem *parent) { -#ifndef QT_NO_DEBUG - if (qsg_leak_check) { - ++qt_item_count; - static bool atexit_registered = false; - if (!atexit_registered) { - atexit(qt_print_item_count); - atexit_registered = true; - } - } -#endif - Q_Q(QQuickItem); registerAccessorProperties(); @@ -3356,7 +3307,7 @@ void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop) QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object); QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem); if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty. - foreach (QObject *object, quickItemPrivate->extra->resourcesList) { + for (QObject *object : qAsConst(quickItemPrivate->extra->resourcesList)) { qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)), quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*))); } @@ -3497,8 +3448,7 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop) QQuickItem *that = static_cast<QQuickItem *>(prop->object); QQuickItemPrivate *p = QQuickItemPrivate::get(that); - for (int ii = 0; ii < p->transforms.count(); ++ii) { - QQuickTransform *t = p->transforms.at(ii); + for (QQuickTransform *t : qAsConst(p->transforms)) { QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t); tp->items.removeOne(that); } @@ -3622,7 +3572,7 @@ QQuickAnchors *QQuickItemPrivate::anchors() const void QQuickItemPrivate::siblingOrderChanged() { Q_Q(QQuickItem); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::SiblingOrder) { change.listener->itemSiblingOrderChanged(q); @@ -3726,32 +3676,31 @@ void QQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo if (d->_anchors) QQuickAnchorsPrivate::get(d->_anchors)->updateMe(); - bool xChange = (newGeometry.x() != oldGeometry.x()); - bool yChange = (newGeometry.y() != oldGeometry.y()); - bool widthChange = (newGeometry.width() != oldGeometry.width()); - bool heightChange = (newGeometry.height() != oldGeometry.height()); - - const auto listeners = d->changeListeners; - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Geometry) { - if (change.gTypes == QQuickItemPrivate::GeometryChange) { - change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); - } else if ((xChange && (change.gTypes & QQuickItemPrivate::XChange)) || - (yChange && (change.gTypes & QQuickItemPrivate::YChange)) || - (widthChange && (change.gTypes & QQuickItemPrivate::WidthChange)) || - (heightChange && (change.gTypes & QQuickItemPrivate::HeightChange))) { - change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); - } + QQuickGeometryChange change; + QRectF diff(newGeometry.x() - oldGeometry.x(), + newGeometry.y() - oldGeometry.y(), + newGeometry.width() - oldGeometry.width(), + newGeometry.height() - oldGeometry.height()); + change.setXChange(diff.x() != 0); + change.setYChange(diff.y() != 0); + change.setWidthChange(diff.width() != 0); + change.setHeightChange(diff.height() != 0); + + const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &listener : listeners) { + if (listener.types & QQuickItemPrivate::Geometry) { + if (change.matches(listener.gTypes)) + listener.listener->itemGeometryChanged(this, change, diff); } } - if (xChange) + if (change.xChange()) emit xChanged(); - if (yChange) + if (change.yChange()) emit yChanged(); - if (widthChange) + if (change.widthChange()) emit widthChanged(); - if (heightChange) + if (change.heightChange()) emit heightChanged(); } @@ -3870,7 +3819,8 @@ void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *liste changeListeners.removeOne(change); } -void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types) +void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, + QQuickGeometryChange types) { ChangeListener change(listener, types); int index = changeListeners.indexOf(change); @@ -3881,10 +3831,10 @@ void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListen } void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, - GeometryChangeTypes types) + QQuickGeometryChange types) { ChangeListener change(listener, types); - if (types == NoChange) { + if (types.noChange()) { changeListeners.removeOne(change); } else { int index = changeListeners.indexOf(change); @@ -4296,7 +4246,7 @@ void QQuickItem::setBaselineOffset(qreal offset) d->baselineOffset = offset; - const auto listeners = d->changeListeners; + const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::Geometry) { QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); @@ -4868,14 +4818,16 @@ void QQuickItem::componentComplete() QQuickAnchorsPrivate::get(d->_anchors)->updateOnComplete(); } - if (d->extra.isAllocated() && d->extra->layer) - d->extra->layer->componentComplete(); + if (d->extra.isAllocated()) { + if (d->extra->layer) + d->extra->layer->componentComplete(); - if (d->extra.isAllocated() && d->extra->keyHandler) - d->extra->keyHandler->componentComplete(); + if (d->extra->keyHandler) + d->extra->keyHandler->componentComplete(); - if (d->extra.isAllocated() && d->extra->contents) - d->extra->contents->complete(); + if (d->extra->contents) + d->extra->contents->complete(); + } if (d->window && d->dirtyAttributes) { d->addToDirtyList(); @@ -5773,8 +5725,9 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) } bool childVisibilityChanged = false; - for (int ii = 0; ii < childItems.count(); ++ii) - childVisibilityChanged |= QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible); + for (QQuickItem *childItem : qAsConst(childItems)) { + childVisibilityChanged |= QQuickItemPrivate::get(childItem)->setEffectiveVisibleRecur(newEffectiveVisible); + } itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible); #ifndef QT_NO_ACCESSIBILITY @@ -5823,8 +5776,8 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec } } - for (int ii = 0; ii < childItems.count(); ++ii) { - QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur( + for (QQuickItem *childItem : qAsConst(childItems)) { + QQuickItemPrivate::get(childItem)->setEffectiveEnableRecur( (flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable); } @@ -5968,7 +5921,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt switch (change) { case QQuickItem::ItemChildAddedChange: { q->itemChange(change, data); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::Children) { change.listener->itemChildAdded(q, data.item); @@ -5978,7 +5931,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt } case QQuickItem::ItemChildRemovedChange: { q->itemChange(change, data); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::Children) { change.listener->itemChildRemoved(q, data.item); @@ -5991,7 +5944,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt break; case QQuickItem::ItemVisibleHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::Visibility) { change.listener->itemVisibilityChanged(q); @@ -6001,7 +5954,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt } case QQuickItem::ItemParentHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::Parent) { change.listener->itemParentChanged(q, data.item); @@ -6011,7 +5964,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt } case QQuickItem::ItemOpacityHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::Opacity) { change.listener->itemOpacityChanged(q); @@ -6024,7 +5977,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt break; case QQuickItem::ItemRotationHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::Rotation) { change.listener->itemRotationChanged(q); @@ -6386,7 +6339,7 @@ void QQuickItem::resetWidth() void QQuickItemPrivate::implicitWidthChanged() { Q_Q(QQuickItem); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::ImplicitWidth) { change.listener->itemImplicitWidthChanged(q); @@ -6550,7 +6503,7 @@ void QQuickItem::resetHeight() void QQuickItemPrivate::implicitHeightChanged() { Q_Q(QQuickItem); - const auto listeners = changeListeners; + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) for (const QQuickItemPrivate::ChangeListener &change : listeners) { if (change.types & QQuickItemPrivate::ImplicitHeight) { change.listener->itemImplicitHeightChanged(q); @@ -7049,17 +7002,18 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) Q_Q(QQuickItem); // if we're asked to turn it off (because of an unsetcursor call, or a node - // removal) then we should check our children and make sure it's really ok - // to turn it off. - if (!hasCursor && hasCursorInChild) { - foreach (QQuickItem *otherChild, childItems) { + // removal) then we should make sure it's really ok to turn it off. + if (!hasCursor && subtreeCursorEnabled) { + if (hasCursor) + return; // nope! sorry, I have a cursor myself + for (QQuickItem *otherChild : qAsConst(childItems)) { QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild); - if (otherChildPrivate->hasCursorInChild) + if (otherChildPrivate->subtreeCursorEnabled || otherChildPrivate->hasCursor) return; // nope! sorry, something else wants it kept on. } } - hasCursorInChild = hasCursor; + subtreeCursorEnabled = hasCursor; QQuickItem *parent = q->parentItem(); if (parent) { QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent); @@ -7077,7 +7031,7 @@ void QQuickItemPrivate::setHasHoverInChild(bool hasHover) if (!hasHover && subtreeHoverEnabled) { if (hoverEnabled) return; // nope! sorry, I need hover myself - foreach (QQuickItem *otherChild, childItems) { + for (QQuickItem *otherChild : qAsConst(childItems)) { QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild); if (otherChildPrivate->subtreeHoverEnabled || otherChildPrivate->hoverEnabled) return; // nope! sorry, something else wants it kept on. @@ -7098,7 +7052,7 @@ void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e) Q_Q(QQuickItem); QV4::QObjectWrapper::markWrapper(q, e); - foreach (QQuickItem *child, childItems) + for (QQuickItem *child : qAsConst(childItems)) QQuickItemPrivate::get(child)->markObjects(e); } @@ -7266,25 +7220,7 @@ void QQuickItem::grabTouchPoints(const QVector<int> &ids) if (!d->window) return; QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window); - - QSet<QQuickItem*> ungrab; - for (int i = 0; i < ids.count(); ++i) { - QQuickItem *oldGrabber = windowPriv->itemForTouchPointId.value(ids.at(i)); - if (oldGrabber == this) - return; - - windowPriv->itemForTouchPointId[ids.at(i)] = this; - if (oldGrabber) - ungrab.insert(oldGrabber); - - QQuickItem *mouseGrabber = d->window->mouseGrabberItem(); - if (windowPriv->touchMouseId == ids.at(i) && mouseGrabber && mouseGrabber != this) { - qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: grabber" << mouseGrabber << "-> null"; - mouseGrabber->ungrabMouse(); - } - } - foreach (QQuickItem *oldGrabber, ungrab) - oldGrabber->touchUngrabEvent(); + windowPriv->grabTouchPoints(this, ids); } /*! @@ -8162,7 +8098,7 @@ void QQuickItemLayer::itemOpacityChanged(QQuickItem *item) updateOpacity(); } -void QQuickItemLayer::itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) +void QQuickItemLayer::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) { updateGeometry(); } diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 8328dd513b..9ea2712e18 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -98,7 +98,7 @@ public: void complete(); protected: - void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE; void itemDestroyed(QQuickItem *item) Q_DECL_OVERRIDE; void itemChildAdded(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE; void itemChildRemoved(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE; @@ -188,7 +188,7 @@ public: QQuickShaderEffectSource *effectSource() const { return m_effectSource; } - void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) Q_DECL_OVERRIDE; void itemOpacityChanged(QQuickItem *) Q_DECL_OVERRIDE; void itemParentChanged(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE; void itemSiblingOrderChanged(QQuickItem *) Q_DECL_OVERRIDE; @@ -318,24 +318,12 @@ public: Q_DECLARE_FLAGS(ChangeTypes, ChangeType) - enum GeometryChangeType { - NoChange = 0, - XChange = 0x01, - YChange = 0x02, - WidthChange = 0x04, - HeightChange = 0x08, - SizeChange = WidthChange | HeightChange, - GeometryChange = XChange | YChange | SizeChange - }; - - Q_DECLARE_FLAGS(GeometryChangeTypes, GeometryChangeType) - struct ChangeListener { - ChangeListener(QQuickItemChangeListener *l = Q_NULLPTR, QQuickItemPrivate::ChangeTypes t = 0) : listener(l), types(t), gTypes(GeometryChange) {} - ChangeListener(QQuickItemChangeListener *l, QQuickItemPrivate::GeometryChangeTypes gt) : listener(l), types(Geometry), gTypes(gt) {} + ChangeListener(QQuickItemChangeListener *l = nullptr, QQuickItemPrivate::ChangeTypes t = 0) : listener(l), types(t), gTypes(QQuickGeometryChange::All) {} + ChangeListener(QQuickItemChangeListener *l, QQuickGeometryChange gt) : listener(l), types(Geometry), gTypes(gt) {} QQuickItemChangeListener *listener; QQuickItemPrivate::ChangeTypes types; - QQuickItemPrivate::GeometryChangeTypes gTypes; //NOTE: not used for == + QQuickGeometryChange gTypes; //NOTE: not used for == bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; } }; @@ -389,8 +377,8 @@ public: void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types); void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types); - void updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types); - void updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types); + void updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, QQuickGeometryChange types); + void updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, QQuickGeometryChange types); QQuickStateGroup *_states(); QQuickStateGroup *_stateGroup; @@ -426,7 +414,7 @@ public: bool isAccessible:1; bool culled:1; bool hasCursor:1; - bool hasCursorInChild:1; + bool subtreeCursorEnabled:1; // Bit 32 bool subtreeHoverEnabled:1; bool activeFocusOnTab:1; diff --git a/src/quick/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h index 6e3ef25506..19ff73056b 100644 --- a/src/quick/items/qquickitemchangelistener_p.h +++ b/src/quick/items/qquickitemchangelistener_p.h @@ -58,12 +58,69 @@ QT_BEGIN_NAMESPACE class QRectF; class QQuickItem; class QQuickAnchorsPrivate; + +class QQuickGeometryChange +{ +public: + enum Kind: int { + Nothing = 0x00, + X = 0x01, + Y = 0x02, + Width = 0x04, + Height = 0x08, + + Size = Width | Height, + All = X | Y | Size + }; + + QQuickGeometryChange(int change = Nothing) + : kind(change) + {} + + bool noChange() const { return kind == Nothing; } + bool anyChange() const { return !noChange(); } + + bool xChange() const { return kind & X; } + bool yChange() const { return kind & Y; } + bool widthChange() const { return kind & Width; } + bool heightChange() const { return kind & Height; } + + bool positionChange() const { return xChange() || yChange(); } + bool sizeChange() const { return widthChange() || heightChange(); } + + bool horizontalChange() const { return xChange() || widthChange(); } + bool verticalChange() const { return yChange() || heightChange(); } + + void setXChange(bool enabled) { set(X, enabled); } + void setYChange(bool enabled) { set(Y, enabled); } + void setWidthChange(bool enabled) { set(Width, enabled); } + void setHeightChange(bool enabled) { set(Height, enabled); } + void setSizeChange(bool enabled) { set(Size, enabled); } + void setAllChanged(bool enabled) { set(All, enabled); } + void setHorizontalChange(bool enabled) { set(X | Width, enabled); } + void setVerticalChange(bool enabled) { set(Y | Height, enabled); } + + void set(int bits, bool enabled) + { + if (enabled) { + kind |= bits; + } else { + kind &= ~bits; + } + } + + bool matches(QQuickGeometryChange other) const { return kind & other.kind; } + +private: + int kind; +}; + class QQuickItemChangeListener { public: virtual ~QQuickItemChangeListener() {} - virtual void itemGeometryChanged(QQuickItem *, const QRectF & /* new */, const QRectF & /* old */ ) {} + virtual void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF & /* diff */) {} virtual void itemSiblingOrderChanged(QQuickItem *) {} virtual void itemVisibilityChanged(QQuickItem *) {} virtual void itemOpacityChanged(QQuickItem *) {} diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 8ed7f2bb05..fb60331ce2 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -73,11 +73,11 @@ //#include <private/qquickpincharea_p.h> #include <QtQuick/private/qquickcanvasitem_p.h> #include <QtQuick/private/qquickcontext2d_p.h> -# include "qquickitemgrabresult.h" +#include "qquickitemgrabresult.h" +#include "qquicksprite_p.h" +#include "qquickspritesequence_p.h" +#include "qquickanimatedsprite_p.h" #ifndef QT_NO_OPENGL -# include "qquicksprite_p.h" -# include "qquickspritesequence_p.h" -# include "qquickanimatedsprite_p.h" # include "qquickopenglinfo_p.h" #endif #include "qquickgraphicsinfo_p.h" @@ -218,11 +218,11 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterUncreatableType<QQuickPaintedItem>("QtQuick", 2, 0, "PaintedItem", QQuickPaintedItem::tr("Cannot create instance of abstract class PaintedItem")); qmlRegisterType<QQuickCanvasItem>("QtQuick", 2, 0, "Canvas"); -#ifndef QT_NO_OPENGL + qmlRegisterType<QQuickSprite>("QtQuick", 2, 0, "Sprite"); qmlRegisterType<QQuickAnimatedSprite>("QtQuick", 2, 0, "AnimatedSprite"); qmlRegisterType<QQuickSpriteSequence>("QtQuick", 2, 0, "SpriteSequence"); -#endif + qmlRegisterType<QQuickParentChange>(uri, major, minor,"ParentChange"); qmlRegisterType<QQuickAnchorChanges>(uri, major, minor,"AnchorChanges"); qmlRegisterType<QQuickAnchorSet>(); diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index aff03b7539..3c1a5a6ebe 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1205,10 +1205,11 @@ void QQuickItemViewPrivate::showVisibleItems() const } } -void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) +void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, + const QRectF &diff) { Q_Q(QQuickItemView); - QQuickFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry); + QQuickFlickablePrivate::itemGeometryChanged(item, change, diff); if (!q->isComponentComplete()) return; diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index 5e104cf208..0893d6e749 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -378,7 +378,7 @@ protected: virtual void updateSectionCriteria() {} virtual void updateSections() {} - void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE; }; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 4b9b7df98a..7bbc6dc9ba 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -131,7 +131,7 @@ public: void updateAverage(); - void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) Q_DECL_OVERRIDE; void fixupPosition() Q_DECL_OVERRIDE; void fixup(AxisData &data, qreal minExtent, qreal maxExtent) Q_DECL_OVERRIDE; bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, @@ -1400,10 +1400,12 @@ bool QQuickListViewPrivate::hasStickyFooter() const return footer && footerPositioning != QQuickListView::InlineFooter; } -void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) +void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, + const QRectF &diff) { Q_Q(QQuickListView); - QQuickItemViewPrivate::itemGeometryChanged(item, newGeometry, oldGeometry); + + QQuickItemViewPrivate::itemGeometryChanged(item, change, diff); if (!q->isComponentComplete()) return; @@ -1417,29 +1419,31 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF & } if (item != contentItem && (!highlight || item != highlight->item)) { - if ((orient == QQuickListView::Vertical && newGeometry.height() != oldGeometry.height()) - || (orient == QQuickListView::Horizontal && newGeometry.width() != oldGeometry.width())) { + if ((orient == QQuickListView::Vertical && change.heightChange()) + || (orient == QQuickListView::Horizontal && change.widthChange())) { // if visibleItems.first() has resized, adjust its pos since it is used to // position all subsequent items if (visibleItems.count() && item == visibleItems.first()->item) { FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.first()); + const QRectF oldGeometry(item->x() - diff.x(), + item->y() - diff.y(), + item->width() - diff.width(), + item->height() - diff.height()); if (listItem->transitionScheduledOrRunning()) return; if (orient == QQuickListView::Vertical) { const qreal oldItemEndPosition = verticalLayoutDirection == QQuickItemView::BottomToTop ? -oldGeometry.y() : oldGeometry.y() + oldGeometry.height(); - qreal diff = newGeometry.height() - oldGeometry.height(); if (verticalLayoutDirection == QQuickListView::TopToBottom && oldItemEndPosition < q->contentY()) - listItem->setPosition(listItem->position() - diff, true); + listItem->setPosition(listItem->position() - diff.height(), true); else if (verticalLayoutDirection == QQuickListView::BottomToTop && oldItemEndPosition > q->contentY()) - listItem->setPosition(listItem->position() + diff, true); + listItem->setPosition(listItem->position() + diff.height(), true); } else { const qreal oldItemEndPosition = q->effectiveLayoutDirection() == Qt::RightToLeft ? -oldGeometry.x() : oldGeometry.x() + oldGeometry.width(); - qreal diff = newGeometry.width() - oldGeometry.width(); if (q->effectiveLayoutDirection() == Qt::LeftToRight && oldItemEndPosition < q->contentX()) - listItem->setPosition(listItem->position() - diff, true); + listItem->setPosition(listItem->position() - diff.width(), true); else if (q->effectiveLayoutDirection() == Qt::RightToLeft && oldItemEndPosition > q->contentX()) - listItem->setPosition(listItem->position() + diff, true); + listItem->setPosition(listItem->position() + diff.width(), true); } } forceLayoutPolish(); diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 63c9558d7a..9aea9c50df 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -65,11 +65,12 @@ QQuickLoaderPrivate::~QQuickLoaderPrivate() disposeInitialPropertyValues(); } -void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry) +void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change + , const QRectF &diff) { if (resizeItem == item) _q_updateSize(false); - QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry); + QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, diff); } void QQuickLoaderPrivate::itemImplicitWidthChanged(QQuickItem *) diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index 9ef89a74d6..fcccbfe4f5 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -84,7 +84,7 @@ public: QQuickLoaderPrivate(); ~QQuickLoaderPrivate(); - void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) Q_DECL_OVERRIDE; void itemImplicitWidthChanged(QQuickItem *) Q_DECL_OVERRIDE; void itemImplicitHeightChanged(QQuickItem *) Q_DECL_OVERRIDE; void clear(); diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp index 3f057ecd64..9d24a6c511 100644 --- a/src/quick/items/qquickopenglshadereffect.cpp +++ b/src/quick/items/qquickopenglshadereffect.cpp @@ -187,7 +187,7 @@ public: explicit MappedSlotObject(PropChangedFunc func) : QSlotObjectBase(&impl), _signalIndex(-1), func(func) - {} + { ref(); } void setSignalIndex(int idx) { _signalIndex = idx; } int signalIndex() const { return _signalIndex; } @@ -215,6 +215,12 @@ private: }; } +QQuickOpenGLShaderEffectCommon::~QQuickOpenGLShaderEffectCommon() +{ + for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) + clearSignalMappers(shaderType); +} + void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType) { for (int i = 0; i < uniformData[shaderType].size(); ++i) { @@ -363,7 +369,7 @@ void QQuickOpenGLShaderEffectCommon::updateShader(QQuickItem *item, { disconnectPropertySignals(item, shaderType); uniformData[shaderType].clear(); - signalMappers[shaderType].clear(); + clearSignalMappers(shaderType); if (shaderType == Key::VertexShader) attributes.clear(); @@ -593,6 +599,15 @@ void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item, } } +void QQuickOpenGLShaderEffectCommon::clearSignalMappers(int shader) +{ + for (auto mapper : qAsConst(signalMappers[shader])) { + if (mapper) + mapper->destroyIfLastRef(); + } + signalMappers[shader].clear(); +} + QQuickOpenGLShaderEffect::QQuickOpenGLShaderEffect(QQuickShaderEffect *item, QObject *parent) : QObject(parent) , m_item(item) diff --git a/src/quick/items/qquickopenglshadereffect_p.h b/src/quick/items/qquickopenglshadereffect_p.h index 44b60c97d9..ed56a76409 100644 --- a/src/quick/items/qquickopenglshadereffect_p.h +++ b/src/quick/items/qquickopenglshadereffect_p.h @@ -84,6 +84,8 @@ struct Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffectCommon : host(host), mappedPropertyChanged(mappedPropertyChanged), fileSelector(nullptr) { } + ~QQuickOpenGLShaderEffectCommon(); + void disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType); void connectPropertySignals(QQuickItem *item, const QMetaObject *itemMetaObject, Key::ShaderType shaderType); void updateParseLog(bool ignoreAttributes); @@ -97,6 +99,8 @@ struct Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffectCommon void sourceDestroyed(QObject *object); void propertyChanged(QQuickItem *item, const QMetaObject *itemMetaObject, int mappedId, bool *textureProviderChanged); + void clearSignalMappers(int shader); + QObject *host; std::function<void(int)> mappedPropertyChanged; Key source; diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 652af3487f..0441603a4b 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -76,9 +76,8 @@ public: void init(); - void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE { - if ((newGeometry.size() != oldGeometry.size()) - && (!highlightItem || item != highlightItem)) { + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE { + if (change.sizeChange() && (!highlightItem || item != highlightItem)) { if (QQuickPathViewAttached *att = attached(item)) att->m_percent = -1; scheduleLayout(); diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h index f0fbac2df7..d18f9b3724 100644 --- a/src/quick/items/qquickpositioners_p_p.h +++ b/src/quick/items/qquickpositioners_p_p.h @@ -137,9 +137,9 @@ public: setPositioningDirty(); } - void itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE + void itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE { - if (newGeometry.size() != oldGeometry.size()) + if (change.sizeChange()) setPositioningDirty(); } diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index dbe1add345..8b69447002 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -56,9 +56,9 @@ #include <QtQuick/QQuickWindow> #include <QtQuick/private/qquickwindow_p.h> +#include <QtQuick/private/qsgsoftwarerenderer_p.h> #include <QtCore/private/qobject_p.h> - QT_BEGIN_NAMESPACE #ifndef QT_NO_OPENGL extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); @@ -124,6 +124,10 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_ To send events, for example mouse or keyboard events, to the scene, use QCoreApplication::sendEvent() with the QQuickWindow instance as the receiver. + \note In general QQuickRenderControl is supported in combination with all Qt + Quick backends. However, some functionality, in particular grab(), may not be + available in all cases. + \inmodule QtQuick */ @@ -209,8 +213,9 @@ void QQuickRenderControl::prepareThread(QThread *targetThread) } /*! - Initializes the scene graph resources. The context \a gl has to - be the current context. + Initializes the scene graph resources. The context \a gl has to be the + current OpenGL context or null if it is not relevant because a Qt Quick + backend other than OpenGL is in use. \note Qt Quick does not take ownership of the context. It is up to the application to destroy it after a call to invalidate() or after the @@ -369,12 +374,31 @@ QImage QQuickRenderControl::grab() if (!d->window) return QImage(); - render(); + QImage grabContent; + + if (d->window->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL) { #ifndef QT_NO_OPENGL - QImage grabContent = qt_gl_read_framebuffer(d->window->size() * d->window->effectiveDevicePixelRatio(), false, false); -#else - QImage grabContent = d->window->grabWindow(); + render(); + grabContent = qt_gl_read_framebuffer(d->window->size() * d->window->effectiveDevicePixelRatio(), false, false); #endif + } else if (d->window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) { + QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window); + QSGSoftwareRenderer *softwareRenderer = static_cast<QSGSoftwareRenderer *>(cd->renderer); + if (softwareRenderer) { + const qreal dpr = d->window->effectiveDevicePixelRatio(); + const QSize imageSize = d->window->size() * dpr; + grabContent = QImage(imageSize, QImage::Format_ARGB32_Premultiplied); + grabContent.setDevicePixelRatio(dpr); + QPaintDevice *prevDev = softwareRenderer->currentPaintDevice(); + softwareRenderer->setCurrentPaintDevice(&grabContent); + softwareRenderer->markDirty(); + render(); + softwareRenderer->setCurrentPaintDevice(prevDev); + } + } else { + qWarning("QQuickRenderControl: grabs are not supported with the current Qt Quick backend"); + } + return grabContent; } diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 57462219f9..5670696ce2 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -432,7 +432,9 @@ QT_BEGIN_NAMESPACE do its job. The selector-less version is the GLSL source, while the \c hlsl selector is used when running on the D3D12 backend. The file under \c{+hlsl} can then contain either HLSL source code or compiled bytecode - from the \c fxc tool. + from the \c fxc tool. Additionally, when using a version 3.2 or newer core + profile context with OpenGL, GLSL sources with a core profile compatible + syntax can be placed under \c{+glslcore}. \qml import QtQuick 2.8 // for GraphicsInfo diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index d74dd99fe8..a60a06f59a 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -308,11 +308,11 @@ QQuickItem *QQuickShaderEffectSource::sourceItem() const return m_sourceItem; } -void QQuickShaderEffectSource::itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect) +void QQuickShaderEffectSource::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) { Q_ASSERT(item == m_sourceItem); Q_UNUSED(item); - if (newRect.size() != oldRect.size()) + if (change.sizeChange()) update(); } diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index de62c21488..ee18bf195a 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -168,7 +168,7 @@ protected: void releaseResources() Q_DECL_OVERRIDE; QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; - void itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE; void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE; private: diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 1b8c8cee84..684d432f39 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -300,7 +300,7 @@ private Q_SLOTS: private: friend class QQuickImageParticle; - friend class QQuickSpriteSequence; + //friend class QQuickSpriteSequence; friend class QQuickAnimatedSprite; friend class QQuickSpriteEngine; friend class QQuickStochasticEngine; diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 2137c8d8d5..083e02fe3f 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -372,7 +372,7 @@ void QQuickSpriteEngine::startAssemblingImage() m_startedImageAssembly = true; } -QImage QQuickSpriteEngine::assembledImage() +QImage QQuickSpriteEngine::assembledImage(int maxSize) { QQuickPixmap::Status stat = status(); if (!m_errorsPrinted && stat == QQuickPixmap::Error) { @@ -389,19 +389,7 @@ QImage QQuickSpriteEngine::assembledImage() int w = 0; m_maxFrames = 0; m_imageStateCount = 0; - int maxSize = 0; -#ifndef QT_NO_OPENGL - //If there is no current OpenGL Context - if (!QOpenGLContext::currentContext()) - return QImage(); - QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize); -#else - maxSize = 2048; -#endif -#ifdef SPRITE_IMAGE_DEBUG - qDebug() << "MAX TEXTURE SIZE" << maxSize; -#endif foreach (QQuickSprite* state, m_sprites){ if (state->frames() > m_maxFrames) m_maxFrames = state->frames(); diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index 65f58fafcb..1bdcc9a741 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -295,7 +295,7 @@ public: bool isError() { return status() == QQuickPixmap::Error; } QQuickPixmap::Status status();//Composed status of all Sprites void startAssemblingImage(); - QImage assembledImage(); + QImage assembledImage(int maxSize = 2048); private: int pseudospriteProgress(int,int,int*rd=0); diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index f32e1afd50..25a39f951a 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquickspritesequence_p.h" +#include "qquickspritesequence_p_p.h" #include "qquicksprite_p.h" #include "qquickspriteengine_p.h" #include <QtQuick/private/qsgcontext_p.h> @@ -54,111 +55,6 @@ QT_BEGIN_NAMESPACE -class QQuickSpriteSequenceMaterial : public QSGMaterial -{ -public: - QQuickSpriteSequenceMaterial(); - ~QQuickSpriteSequenceMaterial(); - QSGMaterialType *type() const Q_DECL_OVERRIDE{ static QSGMaterialType type; return &type; } - QSGMaterialShader *createShader() const Q_DECL_OVERRIDE; - int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE - { - return this - static_cast<const QQuickSpriteSequenceMaterial *>(other); - } - - QSGTexture *texture; - - float animT; - float animX1; - float animY1; - float animX2; - float animY2; - float animW; - float animH; -}; - -QQuickSpriteSequenceMaterial::QQuickSpriteSequenceMaterial() - : texture(0) - , animT(0.0f) - , animX1(0.0f) - , animY1(0.0f) - , animX2(0.0f) - , animY2(0.0f) - , animW(1.0f) - , animH(1.0f) -{ - setFlag(Blending, true); -} - -QQuickSpriteSequenceMaterial::~QQuickSpriteSequenceMaterial() -{ - delete texture; -} - -class SpriteSequenceMaterialData : public QSGMaterialShader -{ -public: - SpriteSequenceMaterialData() - : QSGMaterialShader() - { - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/items/shaders/sprite.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/items/shaders/sprite.frag")); - } - - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE - { - QQuickSpriteSequenceMaterial *m = static_cast<QQuickSpriteSequenceMaterial *>(newEffect); - m->texture->bind(); - - program()->setUniformValue(m_opacity_id, state.opacity()); - program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT); - program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2); - - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrix_id, state.combinedMatrix()); - } - - void initialize() Q_DECL_OVERRIDE { - m_matrix_id = program()->uniformLocation("qt_Matrix"); - m_opacity_id = program()->uniformLocation("qt_Opacity"); - m_animData_id = program()->uniformLocation("animData"); - m_animPos_id = program()->uniformLocation("animPos"); - } - - char const *const *attributeNames() const Q_DECL_OVERRIDE { - static const char *attr[] = { - "vPos", - "vTex", - 0 - }; - return attr; - } - - int m_matrix_id; - int m_opacity_id; - int m_animData_id; - int m_animPos_id; -}; - -QSGMaterialShader *QQuickSpriteSequenceMaterial::createShader() const -{ - return new SpriteSequenceMaterialData; -} - -struct SpriteVertex { - float x; - float y; - float tx; - float ty; -}; - -struct SpriteVertices { - SpriteVertex v1; - SpriteVertex v2; - SpriteVertex v3; - SpriteVertex v4; -}; - /*! \qmltype SpriteSequence \instantiates QQuickSpriteSequence @@ -218,213 +114,185 @@ struct SpriteVertices { //TODO: Implicitly size element to size of first sprite? QQuickSpriteSequence::QQuickSpriteSequence(QQuickItem *parent) : - QQuickItem(parent) - , m_node(0) - , m_material(0) - , m_spriteEngine(0) - , m_curFrame(0) - , m_pleaseReset(false) - , m_running(true) - , m_interpolate(true) - , m_curStateIdx(0) + QQuickItem(*(new QQuickSpriteSequencePrivate), parent) { setFlag(ItemHasContents); connect(this, SIGNAL(runningChanged(bool)), this, SLOT(update())); - connect(this, SIGNAL(widthChanged()), - this, SLOT(sizeVertices())); - connect(this, SIGNAL(heightChanged()), - this, SLOT(sizeVertices())); } void QQuickSpriteSequence::jumpTo(const QString &sprite) { - if (!m_spriteEngine) + Q_D(QQuickSpriteSequence); + if (!d->m_spriteEngine) return; - m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite), 0, true); + d->m_spriteEngine->setGoal(d->m_spriteEngine->stateIndex(sprite), 0, true); } void QQuickSpriteSequence::setGoalSprite(const QString &sprite) { - if (m_goalState != sprite){ - m_goalState = sprite; + Q_D(QQuickSpriteSequence); + if (d->m_goalState != sprite){ + d->m_goalState = sprite; emit goalSpriteChanged(sprite); - if (m_spriteEngine) - m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite)); + if (d->m_spriteEngine) + d->m_spriteEngine->setGoal(d->m_spriteEngine->stateIndex(sprite)); } } -QQmlListProperty<QQuickSprite> QQuickSpriteSequence::sprites() +void QQuickSpriteSequence::setRunning(bool arg) { - return QQmlListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); + Q_D(QQuickSpriteSequence); + if (d->m_running != arg) { + d->m_running = arg; + Q_EMIT runningChanged(arg); + } } -void QQuickSpriteSequence::createEngine() +void QQuickSpriteSequence::setInterpolate(bool arg) { - //TODO: delay until component complete - if (m_spriteEngine) - delete m_spriteEngine; - if (m_sprites.count()) { - m_spriteEngine = new QQuickSpriteEngine(m_sprites, this); - if (!m_goalState.isEmpty()) - m_spriteEngine->setGoal(m_spriteEngine->stateIndex(m_goalState)); - } else { - m_spriteEngine = 0; + Q_D(QQuickSpriteSequence); + if (d->m_interpolate != arg) { + d->m_interpolate = arg; + Q_EMIT interpolateChanged(arg); } - reset(); } -static QSGGeometry::Attribute SpriteSequence_Attributes[] = { - QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // pos - QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // tex -}; - -static QSGGeometry::AttributeSet SpriteSequence_AttributeSet = +QQmlListProperty<QQuickSprite> QQuickSpriteSequence::sprites() { - 2, // Attribute Count - (2+2) * sizeof(float), - SpriteSequence_Attributes -}; + Q_D(QQuickSpriteSequence); + return QQmlListProperty<QQuickSprite>(this, &d->m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); +} -void QQuickSpriteSequence::sizeVertices() +bool QQuickSpriteSequence::running() const { - if (!m_node) - return; + Q_D(const QQuickSpriteSequence); + return d->m_running; +} - SpriteVertices *p = (SpriteVertices *) m_node->geometry()->vertexData(); - p->v1.x = 0; - p->v1.y = 0; +bool QQuickSpriteSequence::interpolate() const +{ + Q_D(const QQuickSpriteSequence); + return d->m_interpolate; +} - p->v2.x = width(); - p->v2.y = 0; +QString QQuickSpriteSequence::goalSprite() const +{ + Q_D(const QQuickSpriteSequence); + return d->m_goalState; +} - p->v3.x = 0; - p->v3.y = height(); +QString QQuickSpriteSequence::currentSprite() const +{ + Q_D(const QQuickSpriteSequence); + return d->m_curState; +} - p->v4.x = width(); - p->v4.y = height(); +void QQuickSpriteSequence::createEngine() +{ + Q_D(QQuickSpriteSequence); + //TODO: delay until component complete + if (d->m_spriteEngine) + delete d->m_spriteEngine; + if (d->m_sprites.count()) { + d->m_spriteEngine = new QQuickSpriteEngine(d->m_sprites, this); + if (!d->m_goalState.isEmpty()) + d->m_spriteEngine->setGoal(d->m_spriteEngine->stateIndex(d->m_goalState)); + } else { + d->m_spriteEngine = 0; + } + reset(); } -QSGGeometryNode* QQuickSpriteSequence::buildNode() +QSGSpriteNode *QQuickSpriteSequence::initNode() { - if (!m_spriteEngine) { + Q_D(QQuickSpriteSequence); + + if (!d->m_spriteEngine) { qmlInfo(this) << "No sprite engine..."; - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Null) { - m_spriteEngine->startAssemblingImage(); + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Null) { + d->m_spriteEngine->startAssemblingImage(); update();//Schedule another update, where we will check again - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Loading) { + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Loading) { update();//Schedule another update, where we will check again - return 0; + return nullptr; } - m_material = new QQuickSpriteSequenceMaterial(); - - QImage image = m_spriteEngine->assembledImage(); + QImage image = d->m_spriteEngine->assembledImage(d->sceneGraphRenderContext()->maxTextureSize()); if (image.isNull()) - return 0; - m_sheetSize = QSizeF(image.size()); - m_material->texture = window()->createTextureFromImage(image); - m_material->texture->setFiltering(QSGTexture::Linear); - m_spriteEngine->start(0); - m_material->animT = 0; - m_material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width(); - m_material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height(); - m_material->animX2 = m_material->animX1; - m_material->animY2 = m_material->animY1; - m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name(); - emit currentSpriteChanged(m_curState); - - int vCount = 4; - int iCount = 6; - QSGGeometry *g = new QSGGeometry(SpriteSequence_AttributeSet, vCount, iCount); - g->setDrawingMode(GL_TRIANGLES); - - SpriteVertices *p = (SpriteVertices *) g->vertexData(); - QRectF texRect = m_material->texture->normalizedTextureSubRect(); - - p->v1.tx = texRect.topLeft().x(); - p->v1.ty = texRect.topLeft().y(); - - p->v2.tx = texRect.topRight().x(); - p->v2.ty = texRect.topRight().y(); - - p->v3.tx = texRect.bottomLeft().x(); - p->v3.ty = texRect.bottomLeft().y(); - - p->v4.tx = texRect.bottomRight().x(); - p->v4.ty = texRect.bottomRight().y(); - - quint16 *indices = g->indexDataAsUShort(); - indices[0] = 0; - indices[1] = 1; - indices[2] = 2; - indices[3] = 1; - indices[4] = 3; - indices[5] = 2; - - - m_timestamp.start(); - m_node = new QSGGeometryNode(); - m_node->setGeometry(g); - m_node->setMaterial(m_material); - m_node->setFlag(QSGGeometryNode::OwnsMaterial); - sizeVertices(); - return m_node; + return nullptr; + + QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); + + d->m_sheetSize = QSize(image.size()); + node->setTexture(window()->createTextureFromImage(image)); + d->m_spriteEngine->start(0); + node->setTime(0.0f); + node->setSourceA(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSourceB(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSpriteSize(QSize(d->m_spriteEngine->spriteWidth(), d->m_spriteEngine->spriteHeight())); + node->setSheetSize(d->m_sheetSize); + node->setSize(QSizeF(width(), height())); + + d->m_curState = d->m_spriteEngine->state(d->m_spriteEngine->curState())->name(); + emit currentSpriteChanged(d->m_curState); + d->m_timestamp.start(); + return node; } void QQuickSpriteSequence::reset() { - m_pleaseReset = true; + Q_D(QQuickSpriteSequence); + d->m_pleaseReset = true; } -QSGNode *QQuickSpriteSequence::updatePaintNode(QSGNode *, UpdatePaintNodeData *) +QSGNode *QQuickSpriteSequence::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { - if (m_pleaseReset) { - delete m_node; + Q_D(QQuickSpriteSequence); - m_node = 0; - m_material = 0; - m_pleaseReset = false; + if (d->m_pleaseReset) { + delete oldNode; + + oldNode = nullptr; + d->m_pleaseReset = false; } - prepareNextFrame(); + QSGSpriteNode *node = static_cast<QSGSpriteNode *>(oldNode); + if (!node) + node = initNode(); + + if (node) + prepareNextFrame(node); - if (m_running) { + if (d->m_running) { update(); - if (m_node) - m_node->markDirty(QSGNode::DirtyMaterial); } - return m_node; + return node; } -void QQuickSpriteSequence::prepareNextFrame() +void QQuickSpriteSequence::prepareNextFrame(QSGSpriteNode *node) { - if (m_node == 0) - m_node = buildNode(); - if (m_node == 0) //error creating node - return; + Q_D(QQuickSpriteSequence); - uint timeInt = m_timestamp.elapsed(); + uint timeInt = d->m_timestamp.elapsed(); qreal time = timeInt / 1000.; //Advance State - m_spriteEngine->updateSprites(timeInt); - if (m_curStateIdx != m_spriteEngine->curState()) { - m_curStateIdx = m_spriteEngine->curState(); - m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name(); - emit currentSpriteChanged(m_curState); - m_curFrame= -1; + d->m_spriteEngine->updateSprites(timeInt); + if (d->m_curStateIdx != d->m_spriteEngine->curState()) { + d->m_curStateIdx = d->m_spriteEngine->curState(); + d->m_curState = d->m_spriteEngine->state(d->m_spriteEngine->curState())->name(); + emit currentSpriteChanged(d->m_curState); + d->m_curFrame= -1; } //Advance Sprite - qreal animT = m_spriteEngine->spriteStart()/1000.0; - qreal frameCount = m_spriteEngine->spriteFrames(); - qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount; + qreal animT = d->m_spriteEngine->spriteStart()/1000.0; + qreal frameCount = d->m_spriteEngine->spriteFrames(); + qreal frameDuration = d->m_spriteEngine->spriteDuration()/frameCount; double frameAt; qreal progress; if (frameDuration > 0) { @@ -432,32 +300,32 @@ void QQuickSpriteSequence::prepareNextFrame() frame = qBound(qreal(0.0), frame, frameCount - qreal(1.0));//Stop at count-1 frames until we have between anim interpolation progress = std::modf(frame,&frameAt); } else { - m_curFrame++; - if (m_curFrame >= frameCount){ - m_curFrame = 0; - m_spriteEngine->advance(); + d->m_curFrame++; + if (d->m_curFrame >= frameCount){ + d->m_curFrame = 0; + d->m_spriteEngine->advance(); } - frameAt = m_curFrame; + frameAt = d->m_curFrame; progress = 0; } - if (m_spriteEngine->sprite()->reverse()) - frameAt = (m_spriteEngine->spriteFrames() - 1) - frameAt; - qreal y = m_spriteEngine->spriteY() / m_sheetSize.height(); - qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - qreal x1 = m_spriteEngine->spriteX() / m_sheetSize.width(); + if (d->m_spriteEngine->sprite()->reverse()) + frameAt = (d->m_spriteEngine->spriteFrames() - 1) - frameAt; + int y = d->m_spriteEngine->spriteY(); + int w = d->m_spriteEngine->spriteWidth(); + int h = d->m_spriteEngine->spriteHeight(); + int x1 = d->m_spriteEngine->spriteX(); x1 += frameAt * w; - qreal x2 = x1; + int x2 = x1; if (frameAt < (frameCount-1)) x2 += w; - m_material->animX1 = x1; - m_material->animY1 = y; - m_material->animX2 = x2; - m_material->animY2 = y; - m_material->animW = w; - m_material->animH = h; - m_material->animT = m_interpolate ? progress : 0.0; + node->setSourceA(QPoint(x1, y)); + node->setSourceB(QPoint(x2, y)); + node->setSpriteSize(QSize(w, h)); + node->setTime(d->m_interpolate ? progress : 0.0); + node->setSize(QSizeF(width(), height())); + node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + node->update(); } QT_END_NAMESPACE diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h index b4cc133821..34af110a98 100644 --- a/src/quick/items/qquickspritesequence_p.h +++ b/src/quick/items/qquickspritesequence_p.h @@ -59,8 +59,8 @@ QT_BEGIN_NAMESPACE class QSGContext; class QQuickSprite; class QQuickSpriteEngine; -class QSGGeometryNode; -class QQuickSpriteSequenceMaterial; +class QQuickSpriteSequencePrivate; +class QSGSpriteNode; class Q_AUTOTEST_EXPORT QQuickSpriteSequence : public QQuickItem { Q_OBJECT @@ -77,25 +77,10 @@ public: QQmlListProperty<QQuickSprite> sprites(); - bool running() const - { - return m_running; - } - - bool interpolate() const - { - return m_interpolate; - } - - QString goalSprite() const - { - return m_goalState; - } - - QString currentSprite() const - { - return m_curState; - } + bool running() const; + bool interpolate() const; + QString goalSprite() const; + QString currentSprite() const; Q_SIGNALS: @@ -108,46 +93,23 @@ public Q_SLOTS: void jumpTo(const QString &sprite); void setGoalSprite(const QString &sprite); - - void setRunning(bool arg) - { - if (m_running != arg) { - m_running = arg; - Q_EMIT runningChanged(arg); - } - } - - void setInterpolate(bool arg) - { - if (m_interpolate != arg) { - m_interpolate = arg; - Q_EMIT interpolateChanged(arg); - } - } + void setRunning(bool arg); + void setInterpolate(bool arg); private Q_SLOTS: void createEngine(); - void sizeVertices(); protected: void reset(); QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; private: - void prepareNextFrame(); - QSGGeometryNode* buildNode(); - QSGGeometryNode *m_node; - QQuickSpriteSequenceMaterial *m_material; - QList<QQuickSprite*> m_sprites; - QQuickSpriteEngine* m_spriteEngine; - QTime m_timestamp; - int m_curFrame; - bool m_pleaseReset; - bool m_running; - bool m_interpolate; - QString m_goalState; - QString m_curState; - int m_curStateIdx; - QSizeF m_sheetSize; + void prepareNextFrame(QSGSpriteNode *node); + QSGSpriteNode* initNode(); + + +private: + Q_DISABLE_COPY(QQuickSpriteSequence) + Q_DECLARE_PRIVATE(QQuickSpriteSequence) }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickspritesequence_p_p.h b/src/quick/items/qquickspritesequence_p_p.h new file mode 100644 index 0000000000..4f352b5b69 --- /dev/null +++ b/src/quick/items/qquickspritesequence_p_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSPRITESEQUENCE_P_P_H +#define QQUICKSPRITESEQUENCE_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickitem_p.h" +#include "qquicksprite_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickSpriteSequence; + +class QQuickSpriteSequencePrivate :public QQuickItemPrivate +{ + Q_DECLARE_PUBLIC(QQuickSpriteSequence) +public: + QQuickSpriteSequencePrivate() + : m_spriteEngine(nullptr) + , m_curFrame(0) + , m_pleaseReset(false) + , m_running(true) + , m_interpolate(true) + , m_curStateIdx(0) + { + + } + QList<QQuickSprite*> m_sprites; + QQuickSpriteEngine* m_spriteEngine; + QTime m_timestamp; + int m_curFrame; + bool m_pleaseReset; + bool m_running; + bool m_interpolate; + QString m_goalState; + QString m_curState; + int m_curStateIdx; + QSize m_sheetSize; +}; + +QT_END_NAMESPACE + +#endif // QQUICKSPRITESEQUENCE_P_P_H diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 65e066c611..0078c4ac21 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -2682,8 +2682,8 @@ void QQuickTextInputPrivate::init() #endif q->setFlag(QQuickItem::ItemHasContents); #ifndef QT_NO_CLIPBOARD - q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()), - q, SLOT(q_canPasteChanged())); + qmlobject_connect(QGuiApplication::clipboard(), QClipboard, SIGNAL(dataChanged()), + q, QQuickTextInput, SLOT(q_canPasteChanged())); #endif // QT_NO_CLIPBOARD lastSelectionStart = 0; diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h index fb30956fea..2969ce9dbc 100644 --- a/src/quick/items/qquicktextnode_p.h +++ b/src/quick/items/qquicktextnode_p.h @@ -77,15 +77,6 @@ class QQuickTextNodeEngine; class Q_QUICK_PRIVATE_EXPORT QQuickTextNode : public QSGTransformNode { public: - enum Decoration { - NoDecoration = 0x0, - Underline = 0x1, - Overline = 0x2, - StrikeOut = 0x4, - Background = 0x8 - }; - Q_DECLARE_FLAGS(Decorations, Decoration) - QQuickTextNode(QQuickItem *ownerElement); ~QQuickTextNode(); diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index 11249be8c6..4631b2e724 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -68,7 +68,7 @@ QQuickTextNodeEngine::BinaryTreeNodeKey::BinaryTreeNodeKey(BinaryTreeNode *node) QQuickTextNodeEngine::BinaryTreeNode::BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect, - const QQuickTextNode::Decorations &decs, + const Decorations &decs, const QColor &c, const QColor &bc, const QPointF &pos, qreal a) @@ -90,7 +90,7 @@ QQuickTextNodeEngine::BinaryTreeNode::BinaryTreeNode(const QGlyphRun &g, void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState, - QQuickTextNode::Decorations decorations, const QColor &textColor, + Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QPointF &position) { QRectF searchRect = glyphRun.boundingRect(); @@ -99,10 +99,10 @@ void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height())) return; - decorations |= (glyphRun.underline() ? QQuickTextNode::Underline : QQuickTextNode::NoDecoration); - decorations |= (glyphRun.overline() ? QQuickTextNode::Overline : QQuickTextNode::NoDecoration); - decorations |= (glyphRun.strikeOut() ? QQuickTextNode::StrikeOut : QQuickTextNode::NoDecoration); - decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration); + decorations |= (glyphRun.underline() ? Decoration::Underline : Decoration::NoDecoration); + decorations |= (glyphRun.overline() ? Decoration::Overline : Decoration::NoDecoration); + decorations |= (glyphRun.strikeOut() ? Decoration::StrikeOut : Decoration::NoDecoration); + decorations |= (backgroundColor.isValid() ? Decoration::Background : Decoration::NoDecoration); qreal ascent = glyphRun.rawFont().ascent(); insert(binaryTree, BinaryTreeNode(glyphRun, @@ -237,7 +237,7 @@ void QQuickTextNodeEngine::processCurrentLine() SelectionState currentSelectionState = Unselected; QRectF currentRect; - QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration; + Decorations currentDecorations = Decoration::NoDecoration; qreal underlineOffset = 0.0; qreal underlineThickness = 0.0; @@ -271,7 +271,7 @@ void QQuickTextNodeEngine::processCurrentLine() currentSelectionState = node->selectionState; // Update decorations - if (currentDecorations != QQuickTextNode::NoDecoration) { + if (currentDecorations != Decoration::NoDecoration) { decorationRect.setY(m_position.y() + m_currentLine.y()); decorationRect.setHeight(m_currentLine.height()); @@ -279,16 +279,16 @@ void QQuickTextNodeEngine::processCurrentLine() decorationRect.setRight(node->boundingRect.left()); TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor); - if (currentDecorations & QQuickTextNode::Underline) + if (currentDecorations & Decoration::Underline) pendingUnderlines.append(textDecoration); - if (currentDecorations & QQuickTextNode::Overline) + if (currentDecorations & Decoration::Overline) pendingOverlines.append(textDecoration); - if (currentDecorations & QQuickTextNode::StrikeOut) + if (currentDecorations & Decoration::StrikeOut) pendingStrikeOuts.append(textDecoration); - if (currentDecorations & QQuickTextNode::Background) + if (currentDecorations & Decoration::Background) m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor)); } @@ -344,7 +344,7 @@ void QQuickTextNodeEngine::processCurrentLine() // If previous item(s) had underline and current does not, then we add the // pending lines to the lists and likewise for overlines and strikeouts if (!pendingUnderlines.isEmpty() - && !(node->decorations & QQuickTextNode::Underline)) { + && !(node->decorations & Decoration::Underline)) { addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness); pendingUnderlines.clear(); @@ -377,19 +377,19 @@ void QQuickTextNodeEngine::processCurrentLine() // Merge current values with previous. Prefer greatest thickness QRawFont rawFont = node->glyphRun.rawFont(); - if (node->decorations & QQuickTextNode::Underline) { + if (node->decorations & Decoration::Underline) { if (rawFont.lineThickness() > underlineThickness) { underlineThickness = rawFont.lineThickness(); underlineOffset = rawFont.underlinePosition(); } } - if (node->decorations & QQuickTextNode::Overline) { + if (node->decorations & Decoration::Overline) { overlineOffset = -rawFont.ascent(); overlineThickness = rawFont.lineThickness(); } - if (node->decorations & QQuickTextNode::StrikeOut) { + if (node->decorations & Decoration::StrikeOut) { strikeOutThickness = rawFont.lineThickness(); strikeOutOffset = rawFont.ascent() / -3.0; } @@ -495,7 +495,7 @@ void QQuickTextNodeEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun) BinaryTreeNode::insert(&m_currentLineTree, glyphRun, Unselected, - QQuickTextNode::NoDecoration, + Decoration::NoDecoration, m_textColor, m_backgroundColor, m_position); @@ -507,7 +507,7 @@ void QQuickTextNodeEngine::addSelectedGlyphs(const QGlyphRun &glyphRun) BinaryTreeNode::insert(&m_currentLineTree, glyphRun, Selected, - QQuickTextNode::NoDecoration, + Decoration::NoDecoration, m_textColor, m_backgroundColor, m_position); diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h index 87235344e6..91ed6f4430 100644 --- a/src/quick/items/qquicktextnodeengine_p.h +++ b/src/quick/items/qquicktextnodeengine_p.h @@ -68,8 +68,15 @@ QT_BEGIN_NAMESPACE // number of nodes, and join decorations in neighbouring items class QQuickTextNodeEngine { - public: + enum Decoration { + NoDecoration = 0x0, + Underline = 0x1, + Overline = 0x2, + StrikeOut = 0x4, + Background = 0x8 + }; + Q_DECLARE_FLAGS(Decorations, Decoration) enum SelectionState { Unselected, @@ -79,26 +86,26 @@ public: struct BinaryTreeNode { BinaryTreeNode() - : selectionState(Unselected), clipNode(0), decorations(QQuickTextNode::NoDecoration) + : selectionState(Unselected), clipNode(0), decorations(Decoration::NoDecoration) , ascent(0.0), leftChildIndex(-1), rightChildIndex(-1) { } BinaryTreeNode(const QRectF &brect, const QImage &i, SelectionState selState, qreal a) - : boundingRect(brect), selectionState(selState), clipNode(0), decorations(QQuickTextNode::NoDecoration) + : boundingRect(brect), selectionState(selState), clipNode(0), decorations(Decoration::NoDecoration) , image(i), ascent(a), leftChildIndex(-1), rightChildIndex(-1) { } BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect, - const QQuickTextNode::Decorations &decs, const QColor &c, const QColor &bc, + const Decorations &decs, const QColor &c, const QColor &bc, const QPointF &pos, qreal a); QGlyphRun glyphRun; QRectF boundingRect; SelectionState selectionState; QQuickDefaultClipNode *clipNode; - QQuickTextNode::Decorations decorations; + Decorations decorations; QColor color; QColor backgroundColor; QPointF position; @@ -114,7 +121,7 @@ public: { insert(binaryTree, BinaryTreeNode(rect, image, selectionState, ascent)); } static void insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState, - QQuickTextNode::Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QPointF &position); + Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QPointF &position); static void insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const BinaryTreeNode &binaryTreeNode); static void inOrder(const QVarLengthArray<BinaryTreeNode, 16> &binaryTree, QVarLengthArray<int> *sortedIndexes, int currentIndex = 0); }; diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index 1101b88992..1d89c8bfc2 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -131,14 +131,15 @@ void QQuickViewPrivate::execute() } } -void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry) +void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change, + const QRectF &diff) { Q_Q(QQuickView); if (resizeItem == root && resizeMode == QQuickView::SizeViewToRootObject) { // wait for both width and height to be changed resizetimer.start(0,q); } - QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry); + QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, diff); } /*! @@ -432,9 +433,14 @@ void QQuickViewPrivate::updateSize() q->resize(newSize); } } else if (resizeMode == QQuickView::SizeRootObjectToView) { - if (!qFuzzyCompare(q->width(), root->width())) + bool needToUpdateWidth = !qFuzzyCompare(q->width(), root->width()); + bool needToUpdateHeight = !qFuzzyCompare(q->height(), root->height()); + + if (needToUpdateWidth && needToUpdateHeight) + root->setSize(QSizeF(q->width(), q->height())); + else if (needToUpdateWidth) root->setWidth(q->width()); - if (!qFuzzyCompare(q->height(), root->height())) + else if (needToUpdateHeight) root->setHeight(q->height()); } } diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index 1bbff0de0e..c21468ef53 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -88,7 +88,7 @@ public: ~QQuickViewPrivate(); void execute(); - void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE; void initResize(); void updateSize(); void setRootObject(QObject *); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 364637a793..36410024d1 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -777,6 +777,31 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) } } +void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids) +{ + Q_Q(QQuickWindow); + QSet<QQuickItem*> ungrab; + for (int i = 0; i < ids.count(); ++i) { + QQuickItem *oldGrabber = itemForTouchPointId.value(ids.at(i)); + if (oldGrabber == grabber) + continue; + + itemForTouchPointId[ids.at(i)] = grabber; + if (oldGrabber) + ungrab.insert(oldGrabber); + + QQuickItem *originalMouseGrabberItem = mouseGrabberItem; + if (touchMouseId == ids.at(i) && mouseGrabberItem && mouseGrabberItem != grabber) { + qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: grabber" << mouseGrabberItem << "-> null"; + mouseGrabberItem = 0; + QEvent ev(QEvent::UngrabMouse); + q->sendEvent(originalMouseGrabberItem, &ev); + } + } + foreach (QQuickItem *oldGrabber, ungrab) + oldGrabber->touchUngrabEvent(); +} + void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool touch) { Q_Q(QQuickWindow); @@ -2598,7 +2623,7 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF return 0; } - if (itemPrivate->hasCursorInChild) { + if (itemPrivate->subtreeCursorEnabled) { QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); for (int ii = children.count() - 1; ii >= 0; --ii) { QQuickItem *child = children.at(ii); @@ -3371,7 +3396,9 @@ bool QQuickWindow::isSceneGraphInitialized() const /*! \fn void QQuickWindow::frameSwapped() - This signal is emitted when the frame buffers have been swapped. + This signal is emitted when a frame has been queued for presenting. With + vertical synchronization enabled the signal is emitted at most once per + vsync interval in a continuously animating scene. This signal will be emitted from the scene graph rendering thread. */ @@ -4524,7 +4551,7 @@ void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs) jobs->clear(); renderJobMutex.unlock(); - foreach (QRunnable *r, jobList) { + for (QRunnable *r : qAsConst(jobList)) { r->run(); delete r; } diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index c22b6dc7d0..940ac7c77b 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -141,6 +141,7 @@ public: bool translateTouchToMouse(QQuickItem *item, QTouchEvent *event); void translateTouchEvent(QTouchEvent *touchEvent); void setMouseGrabber(QQuickItem *grabber); + void grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids); void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true); static void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform); static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0); @@ -310,22 +311,6 @@ private: static void cleanupNodesOnShutdown(QQuickItem *); }; -class Q_QUICK_PRIVATE_EXPORT QQuickCloseEvent : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) - -public: - QQuickCloseEvent() - : _accepted(true) {} - - bool isAccepted() { return _accepted; } - void setAccepted(bool accepted) { _accepted = accepted; } - -private: - bool _accepted; -}; - class QQuickWindowQObjectCleanupJob : public QRunnable { public: @@ -343,6 +328,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickWindowPrivate::FocusOptions) QT_END_NAMESPACE -QML_DECLARE_TYPE(QQuickCloseEvent) - #endif // QQUICKWINDOW_P_H diff --git a/src/quick/items/shaders/sprite.frag b/src/quick/items/shaders/sprite.frag deleted file mode 100644 index e1fcb0f006..0000000000 --- a/src/quick/items/shaders/sprite.frag +++ /dev/null @@ -1,12 +0,0 @@ -uniform sampler2D _qt_texture; -uniform lowp float qt_Opacity; - -varying highp vec4 fTexS; -varying lowp float progress; - -void main() -{ - gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), - texture2D(_qt_texture, fTexS.zw), - progress) * qt_Opacity; -}
\ No newline at end of file diff --git a/src/quick/items/shaders/sprite.vert b/src/quick/items/shaders/sprite.vert deleted file mode 100644 index fc826f60b4..0000000000 --- a/src/quick/items/shaders/sprite.vert +++ /dev/null @@ -1,23 +0,0 @@ -attribute highp vec2 vPos; -attribute highp vec2 vTex; - -uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress -uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation) - -uniform highp mat4 qt_Matrix; - -varying highp vec4 fTexS; -varying lowp float progress; - -void main() -{ - progress = animData.z; - - // Calculate frame location in texture - fTexS.xy = animPos.xy + vTex.xy * animData.xy; - - // Next frame is also passed, for interpolation - fTexS.zw = animPos.zw + vTex.xy * animData.xy; - - gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1); -}
\ No newline at end of file diff --git a/src/quick/items/shaders/sprite_core.frag b/src/quick/items/shaders/sprite_core.frag deleted file mode 100644 index c1087a8754..0000000000 --- a/src/quick/items/shaders/sprite_core.frag +++ /dev/null @@ -1,16 +0,0 @@ -#version 150 core - -in vec4 fTexS; -in float progress; - -out vec4 fragColor; - -uniform sampler2D _qt_texture; -uniform float qt_Opacity; - -void main() -{ - fragColor = mix(texture(_qt_texture, fTexS.xy), - texture(_qt_texture, fTexS.zw), - progress) * qt_Opacity; -}
\ No newline at end of file diff --git a/src/quick/items/shaders/sprite_core.vert b/src/quick/items/shaders/sprite_core.vert deleted file mode 100644 index 5027bf03fc..0000000000 --- a/src/quick/items/shaders/sprite_core.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 150 core - -in vec2 vPos; -in vec2 vTex; - -out vec4 fTexS; -out float progress; - -uniform vec3 animData; // w,h(premultiplied of anim), interpolation progress -uniform vec4 animPos; // x,y, x,y (two frames for interpolation) -uniform mat4 qt_Matrix; - -void main() -{ - progress = animData.z; - - // Calculate frame location in texture - fTexS.xy = animPos.xy + vTex.xy * animData.xy; - - // Next frame is also passed, for interpolation - fTexS.zw = animPos.zw + vTex.xy * animData.xy; - - gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1); -}
\ No newline at end of file |