diff options
Diffstat (limited to 'src/quick/items')
105 files changed, 3108 insertions, 1013 deletions
diff --git a/src/quick/items/context2d/qquickcanvascontext_p.h b/src/quick/items/context2d/qquickcanvascontext_p.h index b7a7f6db71..0010862044 100644 --- a/src/quick/items/context2d/qquickcanvascontext_p.h +++ b/src/quick/items/context2d/qquickcanvascontext_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKCANVASCONTEXT_P_H #define QQUICKCANVASCONTEXT_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 <QtQuick/qquickitem.h> #include <private/qv8engine_p.h> diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 6ef2d6123b..9abca59b1c 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -46,7 +46,7 @@ #include <QtCore/QBuffer> #include <QtCore/qdatetime.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4scopedvalue_p.h> @@ -256,19 +256,6 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() The default render target is Canvas.Image and the default renderStrategy is Canvas.Immediate. - \section1 Tiled Canvas - The Canvas item supports tiled rendering by setting \l canvasSize, \l tileSize - and \l canvasWindow properties. - - Tiling allows efficient display of a very large virtual canvas via a smaller - canvas window. The actual memory consumption is in relation to the canvas - window size. The painting code can draw within the virtual canvas without - handling coordinate system transformations. - - The tiles overlapping with the canvas window may be cached eliminating the - need to redraw, which can lead to significantly improved performance in - some situations. - \section1 Pixel Operations All HTML5 2D context pixel operations are supported. In order to ensure improved pixel reading/writing performance the \a Canvas.Image render @@ -431,6 +418,8 @@ void QQuickCanvasItem::setCanvasSize(const QSizeF & size) By default the tileSize is the same as the canvasSize. + \obsolete This feature is incomplete. For details, see QTBUG-33129. + \sa canvasSize, canvasWindow */ QSize QQuickCanvasItem::tileSize() const @@ -464,6 +453,8 @@ void QQuickCanvasItem::setTileSize(const QSize & size) can display different visible areas by changing the canvas windowSize and/or position. + \obsolete This feature is incomplete. For details, see QTBUG-33129 + \sa canvasSize, tileSize */ QRectF QQuickCanvasItem::canvasWindow() const @@ -1000,7 +991,7 @@ void QQuickCanvasItem::loadImage(const QUrl& url) if (!d->pixmaps.contains(fullPathUrl)) { QQuickPixmap* pix = new QQuickPixmap(); QQmlRefPointer<QQuickCanvasPixmap> canvasPix; - canvasPix.take(new QQuickCanvasPixmap(pix)); + canvasPix.adopt(new QQuickCanvasPixmap(pix)); d->pixmaps.insert(fullPathUrl, canvasPix); pix->load(qmlEngine(this) diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h index bcd7072903..a32ce5389d 100644 --- a/src/quick/items/context2d/qquickcanvasitem_p.h +++ b/src/quick/items/context2d/qquickcanvasitem_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKCANVASITEM_P_H #define QQUICKCANVASITEM_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 <QtQuick/qquickitem.h> #include <private/qv8engine_p.h> #include <QtCore/QThread> @@ -68,8 +79,6 @@ private: class QQuickCanvasItem : public QQuickItem { Q_OBJECT - Q_ENUMS(RenderTarget) - Q_ENUMS(RenderStrategy) Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged) Q_PROPERTY(QString contextType READ contextType WRITE setContextType NOTIFY contextTypeChanged) @@ -85,12 +94,14 @@ public: Image, FramebufferObject }; + Q_ENUM(RenderTarget) enum RenderStrategy { Immediate, Threaded, Cooperative }; + Q_ENUM(RenderStrategy) QQuickCanvasItem(QQuickItem *parent = 0); ~QQuickCanvasItem(); diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index c71a354e0c..1c021e7dc6 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -53,7 +53,7 @@ #include <private/qv4object_p.h> #include <private/qquickwindow_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4objectproto_p.h> #include <private/qv4scopedvalue_p.h> @@ -300,7 +300,7 @@ static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesStr */ static bool qSetFontFamilyFromTokens(QFont &font, const QStringList &fontFamilyTokens) { - foreach (QString fontFamilyToken, fontFamilyTokens) { + foreach (const QString &fontFamilyToken, fontFamilyTokens) { QFontDatabase fontDatabase; if (fontDatabase.hasFamily(fontFamilyToken)) { font.setFamily(fontFamilyToken); @@ -411,7 +411,7 @@ static QFont qt_font_from_string(const QString& fontString, const QFont ¤t int usedTokens = NoTokens; // Optional properties can be in any order, but font-size and font-family must be last. - foreach (const QString token, tokens) { + foreach (const QString &token, tokens) { if (token.compare(QLatin1String("normal")) == 0) { if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) { // Could be font-style, font-variant or font-weight. @@ -475,17 +475,20 @@ namespace QV4 { namespace Heap { struct QQuickJSContext2D : Object { - QQuickJSContext2D(QV4::ExecutionEngine *engine); + QQuickJSContext2D() {} QQuickContext2D* context; }; struct QQuickJSContext2DPrototype : Object { - QQuickJSContext2DPrototype(ExecutionEngine *e) - : Object(e) {} + QQuickJSContext2DPrototype() {} }; struct QQuickContext2DStyle : Object { - QQuickContext2DStyle(QV4::ExecutionEngine *e); + QQuickContext2DStyle() + { + patternRepeatX = false; + patternRepeatY = false; + } QBrush brush; bool patternRepeatX:1; @@ -493,13 +496,13 @@ struct QQuickContext2DStyle : Object { }; struct QQuickJSContext2DPixelData : Object { - QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine); + QQuickJSContext2DPixelData(); QImage image; }; struct QQuickJSContext2DImageData : Object { - QQuickJSContext2DImageData(QV4::ExecutionEngine *engine); + QQuickJSContext2DImageData(); QV4::Value pixelData; }; @@ -552,11 +555,6 @@ struct QQuickJSContext2D : public QV4::Object static QV4::ReturnedValue method_set_textBaseline(QV4::CallContext *ctx); }; -QV4::Heap::QQuickJSContext2D::QQuickJSContext2D(QV4::ExecutionEngine *engine) - : QV4::Heap::Object(engine) -{ -} - DEFINE_OBJECT_VTABLE(QQuickJSContext2D); @@ -567,7 +565,7 @@ public: static QV4::Heap::QQuickJSContext2DPrototype *create(QV4::ExecutionEngine *engine) { QV4::Scope scope(engine); - QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->alloc<QQuickJSContext2DPrototype>(engine)); + QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->allocObject<QQuickJSContext2DPrototype>()); o->defineDefaultProperty(QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0); o->defineDefaultProperty(QStringLiteral("restore"), method_restore, 0); @@ -675,12 +673,7 @@ struct QQuickContext2DStyle : public QV4::Object static QV4::ReturnedValue gradient_proto_addColorStop(QV4::CallContext *ctx); }; -QV4::Heap::QQuickContext2DStyle::QQuickContext2DStyle(QV4::ExecutionEngine *e) - : QV4::Heap::Object(e) -{ - patternRepeatX = false; - patternRepeatY = false; -} + DEFINE_OBJECT_VTABLE(QQuickContext2DStyle); @@ -884,16 +877,15 @@ struct QQuickJSContext2DPixelData : public QV4::Object V4_OBJECT2(QQuickJSContext2DPixelData, QV4::Object) V4_NEEDS_DESTROY - static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty); + static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty); static void putIndexed(QV4::Managed *m, uint index, const QV4::Value &value); static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx); }; -QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine) - : QV4::Heap::Object(engine) +QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData() { - QV4::Scope scope(engine); + QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); o->setArrayType(QV4::Heap::ArrayData::Custom); } @@ -914,12 +906,11 @@ struct QQuickJSContext2DImageData : public QV4::Object } }; -QV4::Heap::QQuickJSContext2DImageData::QQuickJSContext2DImageData(QV4::ExecutionEngine *engine) - : QV4::Heap::Object(engine) +QV4::Heap::QQuickJSContext2DImageData::QQuickJSContext2DImageData() { pixelData = QV4::Primitive::undefinedValue(); - QV4::Scope scope(engine); + QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); o->defineAccessorProperty(QStringLiteral("width"), ::QQuickJSContext2DImageData::method_get_width, 0); @@ -933,7 +924,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE { QV4::Scope scope(v4); QQuickContext2DEngineData *ed = engineData(scope.engine); - QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->alloc<QQuickJSContext2DPixelData>(v4)); + QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DPixelData>()); QV4::ScopedObject p(scope, ed->pixelArrayProto.value()); pixelData->setPrototype(p); @@ -945,7 +936,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32); } - QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->alloc<QQuickJSContext2DImageData>(v4)); + QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DImageData>()); imageData->d()->pixelData = pixelData.asReturnedValue(); return imageData.asReturnedValue(); } @@ -1379,7 +1370,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx QV4::ScopedValue value(scope, ctx->argument(0)); - if (value->asObject()) { + if (value->as<Object>()) { QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>(); if (color.isValid()) { r->d()->context->state.fillStyle = color; @@ -1488,7 +1479,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c QV4::ScopedValue value(scope, ctx->argument(0)); - if (value->asObject()) { + if (value->as<Object>()) { QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>(); if (color.isValid()) { r->d()->context->state.fillStyle = color; @@ -1553,7 +1544,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4:: } QQuickContext2DEngineData *ed = engineData(scope.engine); - QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine)); + QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); gradient->d()->brush = QLinearGradient(x0, y0, x1, y1); @@ -1604,7 +1595,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: QQuickContext2DEngineData *ed = engineData(scope.engine); - QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine)); + QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); @@ -1647,7 +1638,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4: QQuickContext2DEngineData *ed = engineData(scope.engine); - QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine)); + QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); gradient->d()->brush = QConicalGradient(x, y, angle); @@ -1706,7 +1697,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon CHECK_CONTEXT(r) if (ctx->argc() >= 2) { - QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine)); + QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QColor color = scope.engine->toVariant(ctx->args()[0], qMetaTypeId<QColor>()).value<QColor>(); if (color.isValid()) { @@ -1719,7 +1710,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon } else { QImage patternTexture; - if (QV4::Object *o = ctx->args()[0].asObject()) { + if (const QV4::Object *o = ctx->args()[0].as<Object>()) { QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data"))); QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s)); if (!!pixelData) { @@ -2912,7 +2903,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext } else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) { QImage img = canvas->toImage(); if (!img.isNull()) - pixmap.take(new QQuickCanvasPixmap(img)); + pixmap.adopt(new QQuickCanvasPixmap(img)); } else { V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } @@ -2921,7 +2912,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext if (!!imageData) { QV4::Scoped<QQuickJSContext2DPixelData> pix(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>()); if (pix && !pix->d()->image.isNull()) { - pixmap.take(new QQuickCanvasPixmap(pix->d()->image)); + pixmap.adopt(new QQuickCanvasPixmap(pix->d()->image)); } else { V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } @@ -3089,12 +3080,12 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::CallContext return QV4::Encode(r->d()->image.width() * r->d()->image.height() * 4); } -QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint index, bool *hasProperty) +QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, uint index, bool *hasProperty) { Q_ASSERT(m->as<QQuickJSContext2DPixelData>()); - QV4::ExecutionEngine *v4 = static_cast<QQuickJSContext2DPixelData *>(m)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const QQuickJSContext2DPixelData *>(m)->engine(); QV4::Scope scope(v4); - QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<QQuickJSContext2DPixelData *>(m)); + QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<const QQuickJSContext2DPixelData *>(m)); if (index < static_cast<quint32>(r->d()->image.width() * r->d()->image.height() * 4)) { if (hasProperty) @@ -3357,7 +3348,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo qreal pos = ctx->args()[0].toNumber(); QColor color; - if (ctx->args()[1].asObject()) { + if (ctx->args()[1].as<Object>()) { color = scope.engine->toVariant(ctx->args()[1], qMetaTypeId<QColor>()).value<QColor>(); } else { color = qt_color_from_string(ctx->args()[1]); @@ -4235,7 +4226,7 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV4::ExecutionEngine *v4) gradientProto = proto; proto = scope.engine->newObject(); - proto->defineAccessorProperty(scope.engine->id_length, QQuickJSContext2DPixelData::proto_get_length, 0); + proto->defineAccessorProperty(scope.engine->id_length(), QQuickJSContext2DPixelData::proto_get_length, 0); pixelArrayProto = proto; } @@ -4324,7 +4315,7 @@ void QQuickContext2D::setV4Engine(QV4::ExecutionEngine *engine) QQuickContext2DEngineData *ed = engineData(engine); QV4::Scope scope(engine); - QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->alloc<QQuickJSContext2D>(engine)); + QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->allocObject<QQuickJSContext2D>()); QV4::ScopedObject p(scope, ed->contextPrototype.value()); wrapper->setPrototype(p); wrapper->d()->context = this; diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h index 67d3a2e4fb..94762fe7a2 100644 --- a/src/quick/items/context2d/qquickcontext2d_p.h +++ b/src/quick/items/context2d/qquickcontext2d_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKCONTEXT2D_P_H #define QQUICKCONTEXT2D_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 <QtQuick/qtquickglobal.h> #include <QtQml/qqml.h> #include <QtQml/qqmlcomponent.h> @@ -48,7 +59,7 @@ #include <private/qv8engine_p.h> #include <QtCore/QWaitCondition> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> //#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose! diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h index 54bf209c79..48cf21ad71 100644 --- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h +++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKCONTEXT2DCOMMANDBUFFER_P_H #define QQUICKCONTEXT2DCOMMANDBUFFER_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 <QtCore/qmutex.h> #include "qquickcontext2d_p.h" diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h index 88d7b6858f..50ce95e19b 100644 --- a/src/quick/items/context2d/qquickcontext2dtexture_p.h +++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKCONTEXT2DTEXTURE_P_H #define QQUICKCONTEXT2DTEXTURE_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 <QtQuick/qsgtexture.h> #include "qquickcanvasitem_p.h" #include "qquickcontext2d_p.h" diff --git a/src/quick/items/context2d/qquickcontext2dtile_p.h b/src/quick/items/context2d/qquickcontext2dtile_p.h index d923313a28..781261c8d2 100644 --- a/src/quick/items/context2d/qquickcontext2dtile_p.h +++ b/src/quick/items/context2d/qquickcontext2dtile_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKCONTEXT2DTILE_P_H #define QQUICKCONTEXT2DTILE_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 "qquickcontext2d_p.h" #include <QOpenGLFramebufferObject> diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index be78e74b19..617b5aa886 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKACCESSIBLEATTACHED_H #define QQUICKACCESSIBLEATTACHED_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 <QtQuick/qquickitem.h> #include <QtCore/qobject.h> diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index f559f166bf..606d4c45da 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -414,13 +414,27 @@ void QQuickAnchorsPrivate::updateMe() void QQuickAnchorsPrivate::updateOnComplete() { //optimization to only set initial dependencies once, at completion time - QSet<QQuickItem *> dependencies; - dependencies << fill << centerIn - << left.item << right.item << hCenter.item - << top.item << bottom.item << vCenter.item << baseline.item; - - foreach (QQuickItem *dependency, dependencies) - addDepend(dependency); + QQuickItem *dependencies[9]; + dependencies[0] = fill; + dependencies[1] = centerIn; + dependencies[2] = left.item; + dependencies[3] = right.item; + dependencies[4] = hCenter.item; + dependencies[5] = top.item; + dependencies[6] = bottom.item; + dependencies[7] = vCenter.item; + dependencies[8] = baseline.item; + + std::sort(dependencies, dependencies + 9); + + QQuickItem *lastDependency = 0; + for (int i = 0; i < 9; ++i) { + QQuickItem *dependency = dependencies[i]; + if (lastDependency != dependency) { + addDepend(dependency); + lastDependency = dependency; + } + } update(); } diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index a2328162e5..4157e4bf6d 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKANCHORS_P_H #define QQUICKANCHORS_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 <qqml.h> #include <QtCore/QObject> diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h index 409933817f..42f2d4cb64 100644 --- a/src/quick/items/qquickanimatedimage_p.h +++ b/src/quick/items/qquickanimatedimage_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKANIMATEDIMAGE_P_H #define QQUICKANIMATEDIMAGE_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 "qquickimage_p.h" #ifndef QT_NO_MOVIE diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h index e535f1b077..87d489a60a 100644 --- a/src/quick/items/qquickanimatedsprite_p.h +++ b/src/quick/items/qquickanimatedsprite_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKANIMATEDSPRITE_P_H #define QQUICKANIMATEDSPRITE_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 <QtQuick/QQuickItem> #include <private/qquicksprite_p.h> #include <QTime> @@ -70,12 +81,12 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged) - Q_ENUMS(LoopParameters) public: explicit QQuickAnimatedSprite(QQuickItem *parent = 0); enum LoopParameters { Infinite = -1 }; + Q_ENUM(LoopParameters) bool running() const { diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h index f2a172fad3..02e01dedd5 100644 --- a/src/quick/items/qquickborderimage_p.h +++ b/src/quick/items/qquickborderimage_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKBORDERIMAGE_P_H #define QQUICKBORDERIMAGE_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 "qquickimagebase_p.h" QT_BEGIN_NAMESPACE @@ -44,7 +55,6 @@ class QQuickBorderImagePrivate; class Q_AUTOTEST_EXPORT QQuickBorderImage : public QQuickImageBase { Q_OBJECT - Q_ENUMS(TileMode) Q_PROPERTY(QQuickScaleGrid *border READ border CONSTANT) Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged) @@ -59,6 +69,7 @@ public: QQuickScaleGrid *border(); enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile }; + Q_ENUM(TileMode) TileMode horizontalTileMode() const; void setHorizontalTileMode(TileMode); diff --git a/src/quick/items/qquickclipnode_p.h b/src/quick/items/qquickclipnode_p.h index 2e7fa1f495..70dbf149b2 100644 --- a/src/quick/items/qquickclipnode_p.h +++ b/src/quick/items/qquickclipnode_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKCLIPNODE_P_H #define QQUICKCLIPNODE_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 <private/qtquickglobal_p.h> #include <QtQuick/qsgnode.h> diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h index 4bd4cfc6fd..5599831b6f 100644 --- a/src/quick/items/qquickdrag_p.h +++ b/src/quick/items/qquickdrag_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKDRAG_P_H #define QQUICKDRAG_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 <QtQuick/qquickitem.h> #include <private/qv8engine_p.h> @@ -140,7 +151,6 @@ class Q_AUTOTEST_EXPORT QQuickDrag : public QObject { Q_OBJECT - Q_ENUMS(Axis DragType) Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget) Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged) Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged) @@ -160,12 +170,14 @@ public: ~QQuickDrag(); enum DragType { None, Automatic, Internal }; + Q_ENUM(DragType) QQuickItem *target() const; void setTarget(QQuickItem *target); void resetTarget(); enum Axis { XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis }; + Q_ENUM(Axis) Axis axis() const; void setAxis(Axis); diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h index 3223f4203b..127b3bd4a3 100644 --- a/src/quick/items/qquickdroparea_p.h +++ b/src/quick/items/qquickdroparea_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKDROPAREA_P_H #define QQUICKDROPAREA_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.h" #include <private/qqmlguard_p.h> diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 19fb66c19c..9d6c51f37a 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -218,7 +218,7 @@ QQuickFlickablePrivate::QQuickFlickablePrivate() , hMoved(false), vMoved(false) , stealMouse(false), pressed(false) , scrollingPhase(false), interactive(true), calcVelocity(false) - , pixelAligned(false), replayingPressEvent(false) + , pixelAligned(false) , lastPosTime(-1) , lastPressTime(0) , deceleration(QML_FLICK_DEFAULTDECELERATION) @@ -619,7 +619,7 @@ is finished. \qmlsignal QtQuick::Flickable::movementStarted() This signal is emitted when the view begins moving due to user - interaction. + interaction or a generated flick(). The corresponding handler is \c onMovementStarted. */ @@ -628,9 +628,9 @@ is finished. \qmlsignal QtQuick::Flickable::movementEnded() This signal is emitted when the view stops moving due to user - interaction. If a flick was generated, this signal will + interaction or a generated flick(). If a flick was active, this signal will be emitted once the flick stops. If a flick was not - generated, this signal will be emitted when the + active, this signal will be emitted when the user stops dragging - i.e. a mouse or touch release. The corresponding handler is \c onMovementEnded. @@ -1347,7 +1347,7 @@ void QQuickFlickable::mouseReleaseEvent(QMouseEvent *event) if (window() && window()->mouseGrabberItem()) { QPointF localPos = window()->mouseGrabberItem()->mapFromScene(event->windowPos()); QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos)); - window()->sendEvent(window()->mouseGrabberItem(), mouseEvent.data()); + QCoreApplication::sendEvent(window(), mouseEvent.data()); } // And the event has been consumed @@ -1451,6 +1451,7 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) d->lastPosTime = currentTimestamp; d->accumulatedWheelPixelDelta += QVector2D(event->pixelDelta()); d->drag(currentTimestamp, event->type(), event->posF(), d->accumulatedWheelPixelDelta, true, !d->scrollingPhase, true, velocity); + event->accept(); } if (!event->isAccepted()) @@ -1639,10 +1640,8 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry, bool changed = false; if (newGeometry.width() != oldGeometry.width()) { changed = true; // we must update visualArea.widthRatio - if (d->hData.viewSize < 0) { + if (d->hData.viewSize < 0) d->contentItem->setWidth(width()); - emit contentWidthChanged(); - } // Make sure that we're entirely in view. if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QQuickFlickablePrivate::Immediate; @@ -1651,10 +1650,8 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry, } if (newGeometry.height() != oldGeometry.height()) { changed = true; // we must update visualArea.heightRatio - if (d->vData.viewSize < 0) { + if (d->vData.viewSize < 0) d->contentItem->setHeight(height()); - emit contentHeightChanged(); - } // Make sure that we're entirely in view. if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QQuickFlickablePrivate::Immediate; @@ -1670,6 +1667,9 @@ void QQuickFlickable::geometryChanged(const QRectF &newGeometry, \qmlmethod QtQuick::Flickable::flick(qreal xVelocity, qreal yVelocity) Flicks the content with \a xVelocity horizontally and \a yVelocity vertically in pixels/sec. + + Calling this method will update the corresponding moving and flicking properties and signals, + just like a real flick. */ void QQuickFlickable::flick(qreal xVelocity, qreal yVelocity) @@ -1679,8 +1679,15 @@ void QQuickFlickable::flick(qreal xVelocity, qreal yVelocity) d->vData.reset(); d->hData.velocity = xVelocity; d->vData.velocity = yVelocity; + bool flickedX = d->flickX(xVelocity); bool flickedY = d->flickY(yVelocity); + + if (flickedX) + d->hMoved = true; + if (flickedY) + d->vMoved = true; + movementStarting(); d->flickingStarted(flickedX, flickedY); } @@ -2195,10 +2202,6 @@ bool QQuickFlickable::sendMouseEvent(QQuickItem *item, QMouseEvent *event) d->handleMouseMoveEvent(mouseEvent.data()); break; case QEvent::MouseButtonPress: - // Don't process a replayed event during replay - if (d->replayingPressEvent) - return false; - d->handleMousePressEvent(mouseEvent.data()); d->captureDelayedPress(item, event); stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h index 3c3cd362dd..ac072f0e50 100644 --- a/src/quick/items/qquickflickable_p.h +++ b/src/quick/items/qquickflickable_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKFLICKABLE_P_H #define QQUICKFLICKABLE_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.h" #include <private/qtquickglobal_p.h> @@ -93,7 +104,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem Q_PROPERTY(QQmlListProperty<QQuickItem> flickableChildren READ flickableChildren) Q_CLASSINFO("DefaultProperty", "flickableData") - Q_ENUMS(FlickableDirection) Q_FLAGS(BoundsBehavior) public: @@ -177,6 +187,7 @@ public: QQuickItem *contentItem(); enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 }; + Q_ENUM(FlickableDirection) FlickableDirection flickableDirection() const; void setFlickableDirection(FlickableDirection); diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 65bb3e802d..9d75533c8a 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -211,7 +211,6 @@ public: bool interactive : 1; bool calcVelocity : 1; bool pixelAligned : 1; - bool replayingPressEvent : 1; QElapsedTimer timer; qint64 lastPosTime; qint64 lastPressTime; diff --git a/src/quick/items/qquickflickablebehavior_p.h b/src/quick/items/qquickflickablebehavior_p.h index a79297894c..69fca4d0fb 100644 --- a/src/quick/items/qquickflickablebehavior_p.h +++ b/src/quick/items/qquickflickablebehavior_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKFLICKABLEBEHAVIOR_H #define QQUICKFLICKABLEBEHAVIOR_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. +// + /* ### Platform specific flickable mechanics are defined either here, or in mkspec files. Long-term (QtQuick 3) Flickable needs to allow such mechanic details to be controlled via QML so that platforms can easily diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h index bd2efe0676..93610031f6 100644 --- a/src/quick/items/qquickflipable_p.h +++ b/src/quick/items/qquickflipable_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKFLIPABLE_P_H #define QQUICKFLIPABLE_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.h" #include <QtGui/qtransform.h> @@ -47,7 +58,6 @@ class Q_AUTOTEST_EXPORT QQuickFlipable : public QQuickItem { Q_OBJECT - Q_ENUMS(Side) Q_PROPERTY(QQuickItem *front READ front WRITE setFront NOTIFY frontChanged) Q_PROPERTY(QQuickItem *back READ back WRITE setBack NOTIFY backChanged) Q_PROPERTY(Side side READ side NOTIFY sideChanged) @@ -64,6 +74,7 @@ public: void setBack(QQuickItem *); enum Side { Front, Back }; + Q_ENUM(Side) Side side() const; Q_SIGNALS: diff --git a/src/quick/items/qquickfocusscope_p.h b/src/quick/items/qquickfocusscope_p.h index b0e92cb312..eb42cf83b5 100644 --- a/src/quick/items/qquickfocusscope_p.h +++ b/src/quick/items/qquickfocusscope_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKFOCUSSCOPE_P_H #define QQUICKFOCUSSCOPE_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.h" QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp index 4638bbbdf3..5ce3ae57f7 100644 --- a/src/quick/items/qquickframebufferobject.cpp +++ b/src/quick/items/qquickframebufferobject.cpp @@ -47,11 +47,13 @@ class QQuickFramebufferObjectPrivate : public QQuickItemPrivate public: QQuickFramebufferObjectPrivate() : followsItemSize(true) + , mirrorVertically(false) , node(0) { } bool followsItemSize; + bool mirrorVertically; mutable QSGFramebufferObjectNode *node; }; @@ -138,6 +140,34 @@ bool QQuickFramebufferObject::textureFollowsItemSize() const } /*! + * \property QQuickFramebufferObject::mirrorVertically + * + * This property controls if the size of the FBO's contents should be mirrored + * vertically when drawing. This allows easy integration of third-party + * rendering code that does not follow the standard expectations. + * + * The default value is \c {false}. + * + * \since 5.6 + */ + +void QQuickFramebufferObject::setMirrorVertically(bool enable) +{ + Q_D(QQuickFramebufferObject); + if (d->mirrorVertically == enable) + return; + d->mirrorVertically = enable; + emit mirrorVerticallyChanged(d->mirrorVertically); + update(); +} + +bool QQuickFramebufferObject::mirrorVertically() const +{ + Q_D(const QQuickFramebufferObject); + return d->mirrorVertically; +} + +/*! * \internal */ void QQuickFramebufferObject::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) @@ -290,6 +320,7 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode QQuickWindow::TextureHasAlphaChannel)); } + n->setTextureCoordinatesTransform(d->mirrorVertically ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform); n->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest); n->setRect(0, 0, width(), height()); diff --git a/src/quick/items/qquickframebufferobject.h b/src/quick/items/qquickframebufferobject.h index 4a0248c082..7fb7262222 100644 --- a/src/quick/items/qquickframebufferobject.h +++ b/src/quick/items/qquickframebufferobject.h @@ -49,6 +49,7 @@ class Q_QUICK_EXPORT QQuickFramebufferObject : public QQuickItem Q_DECLARE_PRIVATE(QQuickFramebufferObject) Q_PROPERTY(bool textureFollowsItemSize READ textureFollowsItemSize WRITE setTextureFollowsItemSize NOTIFY textureFollowsItemSizeChanged) + Q_PROPERTY(bool mirrorVertically READ mirrorVertically WRITE setMirrorVertically NOTIFY mirrorVerticallyChanged) public: @@ -73,6 +74,9 @@ public: bool textureFollowsItemSize() const; void setTextureFollowsItemSize(bool follows); + bool mirrorVertically() const; + void setMirrorVertically(bool enable); + virtual Renderer *createRenderer() const = 0; bool isTextureProvider() const Q_DECL_OVERRIDE; @@ -87,6 +91,7 @@ protected: Q_SIGNALS: void textureFollowsItemSizeChanged(bool); + void mirrorVerticallyChanged(bool); private Q_SLOTS: void invalidateSceneGraph(); diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 99c77488f4..3ac9c6eb1c 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -267,9 +267,13 @@ qreal QQuickGridViewPrivate::originPosition() const qreal QQuickGridViewPrivate::lastPosition() const { qreal pos = 0; - if (model && model->count()) { - // get end position of last item - pos = (rowPosAt(model->count() - 1) + rowSize()); + if (model && (model->count() || !visibleItems.isEmpty())) { + qreal lastRowPos = model->count() ? rowPosAt(model->count() - 1) : 0; + if (!visibleItems.isEmpty()) { + // If there are items in delayRemove state, they may be after any items linked to the model + lastRowPos = qMax(lastRowPos, static_cast<FxGridItemSG*>(visibleItems.last())->rowPos()); + } + pos = lastRowPos + rowSize(); } return pos; } @@ -918,13 +922,13 @@ void QQuickGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte tempPosition -= bias; } FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart); - if (!topItem && strictHighlightRange && currentItem) { + if (strictHighlightRange && currentItem) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); topItem = currentItem; } FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd); - if (!bottomItem && strictHighlightRange && currentItem) { + if (strictHighlightRange && currentItem) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); bottomItem = currentItem; diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h index 7e1ace01dd..8c93f4ce97 100644 --- a/src/quick/items/qquickgridview_p.h +++ b/src/quick/items/qquickgridview_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKGRIDVIEW_P_H #define QQUICKGRIDVIEW_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 "qquickitemview_p.h" @@ -52,8 +63,6 @@ class Q_AUTOTEST_EXPORT QQuickGridView : public QQuickItemView Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged) - Q_ENUMS(SnapMode) - Q_ENUMS(Flow) Q_CLASSINFO("DefaultProperty", "data") public: @@ -61,6 +70,7 @@ public: FlowLeftToRight = LeftToRight, FlowTopToBottom = TopToBottom }; + Q_ENUM(Flow) QQuickGridView(QQuickItem *parent=0); ~QQuickGridView(); @@ -78,6 +88,7 @@ public: void setCellHeight(qreal); enum SnapMode { NoSnap, SnapToRow, SnapOneRow }; + Q_ENUM(SnapMode) SnapMode snapMode() const; void setSnapMode(SnapMode mode); diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h index be514ae2f5..82bd005463 100644 --- a/src/quick/items/qquickimage_p.h +++ b/src/quick/items/qquickimage_p.h @@ -34,18 +34,26 @@ #ifndef QQUICKIMAGE_P_H #define QQUICKIMAGE_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 "qquickimagebase_p.h" #include <QtQuick/qsgtextureprovider.h> QT_BEGIN_NAMESPACE class QQuickImagePrivate; -class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase +class Q_QUICK_PRIVATE_EXPORT QQuickImage : public QQuickImageBase { Q_OBJECT - Q_ENUMS(FillMode) - Q_ENUMS(HAlignment) - Q_ENUMS(VAlignment) Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged) Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged) @@ -62,11 +70,14 @@ public: enum HAlignment { AlignLeft = Qt::AlignLeft, AlignRight = Qt::AlignRight, AlignHCenter = Qt::AlignHCenter }; + Q_ENUM(HAlignment) enum VAlignment { AlignTop = Qt::AlignTop, AlignBottom = Qt::AlignBottom, AlignVCenter = Qt::AlignVCenter }; + Q_ENUM(VAlignment) enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally, Pad }; + Q_ENUM(FillMode) FillMode fillMode() const; void setFillMode(FillMode); diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 72325243df..073fe58e7b 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -213,15 +213,27 @@ void QQuickImageBase::load() d->devicePixelRatio = 1.0; QUrl loadUrl = d->url; - if (d->url.scheme() == QStringLiteral("image") - || d->url.toString().endsWith(QLatin1String(".svg")) - || d->url.toString().endsWith(QLatin1String(".svgz"))) { - // QQuickImageProvider and SVG can generate a high resolution image when - // sourceSize is set. If sourceSize is not set then the provider default size - // will be used, as usual. - if (!d->sourcesize.isEmpty()) + + // QQuickImageProvider and SVG can generate a high resolution image when + // sourceSize is set. If sourceSize is not set then the provider default size + // will be used, as usual. + bool setDevicePixelRatio = false; + if (!d->sourcesize.isValid()) { + if (loadUrl.scheme() == QStringLiteral("image")) { + setDevicePixelRatio = true; + } else { + QString stringUrl = loadUrl.path(QUrl::PrettyDecoded); + if (stringUrl.endsWith(QLatin1String("svg")) || + stringUrl.endsWith(QLatin1String("svgz"))) { + setDevicePixelRatio = true; + } + } + + if (setDevicePixelRatio) d->devicePixelRatio = targetDevicePixelRatio; - } else { + } + + if (!setDevicePixelRatio) { // (possible) local file: loadUrl and d->devicePixelRatio will be modified if // an "@2x" file is found. resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio); @@ -346,7 +358,7 @@ void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixe Q_ASSERT(sourceDevicePixelRatio); // Bail out if "@2x" image loading is disabled, don't change the source url or devicePixelRatio. - static bool disable2xImageLoading = !qgetenv("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING").isEmpty(); + static const bool disable2xImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING"); if (disable2xImageLoading) return; @@ -368,7 +380,7 @@ void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixe // Look for an @2x version QString localFile2x = image2xPath(localFile); - if (!QFile(localFile2x).exists()) + if (!QFile::exists(localFile2x)) return; // @2x file found found: Change url and devicePixelRatio diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h index 4fcfaecd7d..b6d592c826 100644 --- a/src/quick/items/qquickimagebase_p.h +++ b/src/quick/items/qquickimagebase_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKIMAGEBASE_P_H #define QQUICKIMAGEBASE_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 "qquickimplicitsizeitem_p.h" #include <private/qtquickglobal_p.h> @@ -43,7 +54,6 @@ class QQuickImageBasePrivate; class Q_QUICK_PRIVATE_EXPORT QQuickImageBase : public QQuickImplicitSizeItem { Q_OBJECT - Q_ENUMS(Status) Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) @@ -57,6 +67,7 @@ public: QQuickImageBase(QQuickItem *parent=0); ~QQuickImageBase(); enum Status { Null, Ready, Loading, Error }; + Q_ENUM(Status) Status status() const; qreal progress() const; diff --git a/src/quick/items/qquickimplicitsizeitem_p.h b/src/quick/items/qquickimplicitsizeitem_p.h index 3499cf22c5..1acbb7791d 100644 --- a/src/quick/items/qquickimplicitsizeitem_p.h +++ b/src/quick/items/qquickimplicitsizeitem_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKIMPLICITSIZEITEM_H #define QQUICKIMPLICITSIZEITEM_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 "qquickpainteditem.h" #include <private/qtquickglobal_p.h> diff --git a/src/quick/items/qquickimplicitsizeitem_p_p.h b/src/quick/items/qquickimplicitsizeitem_p_p.h index f2e502af15..d606474e9d 100644 --- a/src/quick/items/qquickimplicitsizeitem_p_p.h +++ b/src/quick/items/qquickimplicitsizeitem_p_p.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE -class QQuickImplicitSizeItemPrivate : public QQuickItemPrivate +class Q_QUICK_PRIVATE_EXPORT QQuickImplicitSizeItemPrivate : public QQuickItemPrivate { Q_DECLARE_PUBLIC(QQuickImplicitSizeItem) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index fbea3a0ee1..b6f35ad638 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_DEBUG -static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty(); +static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK"); #endif void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1) @@ -622,7 +622,7 @@ void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post) mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror; QQuickItem* leftItem = mirror ? d->right : d->left; if (leftItem) { - setFocusNavigation(leftItem, mirror ? "right" : "left"); + setFocusNavigation(leftItem, mirror ? "right" : "left", mirror ? Qt::TabFocusReason : Qt::BacktabFocusReason); event->accept(); } break; @@ -632,20 +632,20 @@ void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post) mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror; QQuickItem* rightItem = mirror ? d->left : d->right; if (rightItem) { - setFocusNavigation(rightItem, mirror ? "left" : "right"); + setFocusNavigation(rightItem, mirror ? "left" : "right", mirror ? Qt::BacktabFocusReason : Qt::TabFocusReason); event->accept(); } break; } case Qt::Key_Up: if (d->up) { - setFocusNavigation(d->up, "up"); + setFocusNavigation(d->up, "up", Qt::BacktabFocusReason); event->accept(); } break; case Qt::Key_Down: if (d->down) { - setFocusNavigation(d->down, "down"); + setFocusNavigation(d->down, "down", Qt::TabFocusReason); event->accept(); } break; @@ -1306,8 +1306,8 @@ void QQuickKeysAttached::setPriority(Priority order) void QQuickKeysAttached::componentComplete() { - Q_D(QQuickKeysAttached); #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); @@ -1610,6 +1610,85 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror) } } +/*! + \qmltype EnterKey + \instantiates QQuickEnterKeyAttached + \inqmlmodule QtQuick + \ingroup qtquick-input + \since 5.6 + \brief Provides a property to manipulate the appearance of Enter key on + an on-screen keyboard. + + The EnterKey attached property is used to manipulate the appearance and + behavior of the Enter key on an on-screen keyboard. +*/ + +/*! + \qmlproperty enumeration QtQuick::EnterKey::type + + Holds the type of the Enter key. + + \note Not all of these values are supported on all platforms. For + unsupported values the default key is used instead. + + \value Qt.EnterKeyDefault The default Enter key. This can be either a + button to accept the input and close the + keyboard, or a \e Return button to enter a + newline in case of a multi-line input field. + + \value Qt.EnterKeyReturn Show a \e Return button that inserts a + newline. + + \value Qt.EnterKeyDone Show a \e {"Done"} button. Typically, the + keyboard is expected to close when the button + is pressed. + + \value Qt.EnterKeyGo Show a \e {"Go"} button. Typically used in an + address bar when entering a URL. + + \value Qt.EnterKeySend Show a \e {"Send"} button. + + \value Qt.EnterKeySearch Show a \e {"Search"} button. + + \value Qt.EnterKeyNext Show a \e {"Next"} button. Typically used in a + form to allow navigating to the next input + field without the keyboard closing. + + \value Qt.EnterKeyPrevious Show a \e {"Previous"} button. +*/ + +QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent) + : QObject(parent), itemPrivate(0), keyType(Qt::EnterKeyDefault) +{ + if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) { + itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->extra.value().enterKeyAttached = this; + } else + qmlInfo(parent) << tr("EnterKey attached property only works with Items"); +} + +QQuickEnterKeyAttached *QQuickEnterKeyAttached::qmlAttachedProperties(QObject *object) +{ + return new QQuickEnterKeyAttached(object); +} + +Qt::EnterKeyType QQuickEnterKeyAttached::type() const +{ + return keyType; +} + +void QQuickEnterKeyAttached::setType(Qt::EnterKeyType type) +{ + if (keyType != type) { + keyType = type; +#ifndef QT_NO_IM + if (itemPrivate && itemPrivate->activeFocus) + QGuiApplication::inputMethod()->update(Qt::ImEnterKeyType); +#endif + typeChanged(); + } +} + void QQuickItemPrivate::setAccessible() { isAccessible = true; @@ -2345,6 +2424,50 @@ bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward) return true; } +QQuickItem *QQuickItemPrivate::nextTabChildItem(const QQuickItem *item, int start) +{ + if (!item) { + qWarning() << "QQuickItemPrivate::nextTabChildItem called with null item."; + return Q_NULLPTR; + } + const QList<QQuickItem *> &children = item->childItems(); + const int count = children.count(); + if (start < 0 || start >= count) { + qWarning() << "QQuickItemPrivate::nextTabChildItem: Start index value out of range for item" << item; + return Q_NULLPTR; + } + while (start < count) { + QQuickItem *child = children.at(start); + if (!child->d_func()->isTabFence) + return child; + ++start; + } + return Q_NULLPTR; +} + +QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int start) +{ + if (!item) { + qWarning() << "QQuickItemPrivate::prevTabChildItem called with null item."; + return Q_NULLPTR; + } + const QList<QQuickItem *> &children = item->childItems(); + const int count = children.count(); + if (start == -1) + start = count - 1; + if (start < 0 || start >= count) { + qWarning() << "QQuickItemPrivate::prevTabChildItem: Start index value out of range for item" << item; + return Q_NULLPTR; + } + while (start >= 0) { + QQuickItem *child = children.at(start); + if (!child->d_func()->isTabFence) + return child; + --start; + } + return Q_NULLPTR; +} + QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward) { Q_ASSERT(item); @@ -2367,7 +2490,6 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo from = item->parentItem(); } bool skip = false; - const QQuickItem * const originalItem = item; QQuickItem * startItem = item; QQuickItem * firstFromItem = from; QQuickItem *current = item; @@ -2376,46 +2498,53 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo QQuickItem *last = current; bool hasChildren = !current->childItems().isEmpty() && current->isEnabled() && current->isVisible(); + QQuickItem *firstChild = Q_NULLPTR; + QQuickItem *lastChild = Q_NULLPTR; + if (hasChildren) { + firstChild = nextTabChildItem(current, 0); + if (!firstChild) + hasChildren = false; + else + lastChild = prevTabChildItem(current, -1); + } + bool isTabFence = current->d_func()->isTabFence; // coming from parent: check children if (hasChildren && from == current->parentItem()) { if (forward) { - current = current->childItems().first(); + current = firstChild; } else { - current = current->childItems().last(); + current = lastChild; if (!current->childItems().isEmpty()) skip = true; } - } else if (hasChildren && forward && from != current->childItems().last()) { + } else if (hasChildren && forward && from != lastChild) { // not last child going forwards int nextChild = current->childItems().indexOf(from) + 1; - current = current->childItems().at(nextChild); - } else if (hasChildren && !forward && from != current->childItems().first()) { + current = nextTabChildItem(current, nextChild); + } else if (hasChildren && !forward && from != firstChild) { // not first child going backwards int prevChild = current->childItems().indexOf(from) - 1; - current = current->childItems().at(prevChild); + current = prevTabChildItem(current, prevChild); if (!current->childItems().isEmpty()) skip = true; // back to the parent - } else if (current->parentItem()) { - current = current->parentItem(); + } else if (QQuickItem *parent = !isTabFence ? current->parentItem() : Q_NULLPTR) { // we would evaluate the parent twice, thus we skip if (forward) { skip = true; - } else if (!forward && !current->childItems().isEmpty()) { - if (last != current->childItems().first()) { - skip = true; - } else if (last == current->childItems().first()) { - if (current->isFocusScope() && current->activeFocusOnTab() && current->hasActiveFocus()) + } else if (QQuickItem *firstSibling = !forward ? nextTabChildItem(parent, 0) : Q_NULLPTR) { + if (last != firstSibling + || (parent->isFocusScope() && parent->activeFocusOnTab() && parent->hasActiveFocus())) skip = true; - } } + current = parent; } else if (hasChildren) { // Wrap around after checking all items forward if (forward) { - current = current->childItems().first(); + current = firstChild; } else { - current = current->childItems().last(); + current = lastChild; if (!current->childItems().isEmpty()) skip = true; } @@ -2423,9 +2552,9 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo from = last; if (current == startItem && from == firstFromItem) { // wrapped around, avoid endless loops - if (originalItem == contentItem) { + if (item == contentItem) { qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem"; - return item->window()->contentItem(); + return item; } else { qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem; return startItem; @@ -2475,7 +2604,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) QQuickItem *itemAncestor = parentItem; while (itemAncestor != 0) { if (itemAncestor == this) { - qWarning("QQuickItem::setParentItem: Parent is already part of this items subtree."); + qWarning() << "QQuickItem::setParentItem: Parent" << parentItem << "is already part of the subtree of" << this; return; } itemAncestor = itemAncestor->parentItem(); @@ -2587,7 +2716,15 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) /*! Moves the specified \a sibling item to the index before this item - within the visual stacking order. + within the list of children. The order of children affects both the + visual stacking order and tab focus navigation order. + + Assuming the z values of both items are the same, this will cause \a + sibling to be rendered above this item. + + If both items have activeFocusOnTab set to \c true, this will also cause + the tab focus order to change, with \a sibling receiving focus after this + item. The given \a sibling must be a sibling of this item; that is, they must have the same immediate \l parent. @@ -2623,7 +2760,15 @@ void QQuickItem::stackBefore(const QQuickItem *sibling) /*! Moves the specified \a sibling item to the index after this item - within the visual stacking order. + within the list of children. The order of children affects both the + visual stacking order and tab focus navigation order. + + Assuming the z values of both items are the same, this will cause \a + sibling to be rendered below this item. + + If both items have activeFocusOnTab set to \c true, this will also cause + the tab focus order to change, with \a sibling receiving focus before this + item. The given \a sibling must be a sibling of this item; that is, they must have the same immediate \l parent. @@ -2778,7 +2923,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c) window = c; if (polishScheduled) - QQuickWindowPrivate::get(window)->itemsToPolish.insert(q); + QQuickWindowPrivate::get(window)->itemsToPolish.append(q); if (!parentItem) QQuickWindowPrivate::get(window)->parentlessItems.insert(q); @@ -2810,7 +2955,7 @@ void QQuickItemPrivate::derefWindow() removeFromDirtyList(); QQuickWindowPrivate *c = QQuickWindowPrivate::get(window); if (polishScheduled) - c->itemsToPolish.remove(q); + c->itemsToPolish.removeOne(q); QMutableHashIterator<int, QQuickItem *> itemTouchMapIt(c->itemForTouchPointId); while (itemTouchMapIt.hasNext()) { if (itemTouchMapIt.next().value() == q) @@ -2949,6 +3094,8 @@ QQuickItemPrivate::QQuickItemPrivate() , activeFocusOnTab(false) , implicitAntialiasing(false) , antialiasingValid(false) + , isTabFence(false) + , replayingPressEvent(false) , dirtyAttributes(0) , nextDirtyItem(0) , prevDirtyItem(0) @@ -3962,6 +4109,11 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const case Qt::ImPreferredLanguage: if (d->extra.isAllocated() && d->extra->keyHandler) v = d->extra->keyHandler->inputMethodQuery(query); + break; + case Qt::ImEnterKeyType: + if (d->extra.isAllocated() && d->extra->enterKeyAttached) + v = d->extra->enterKeyAttached->type(); + break; default: break; } @@ -4104,7 +4256,7 @@ void QQuickItem::polish() if (d->window) { QQuickWindowPrivate *p = QQuickWindowPrivate::get(d->window); bool maybeupdate = p->itemsToPolish.isEmpty(); - p->itemsToPolish.insert(this); + p->itemsToPolish.append(this); if (maybeupdate) d->window->maybeUpdate(); } } @@ -5578,7 +5730,7 @@ QString QQuickItemPrivate::dirtyToString() const { #define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \ if (!rv.isEmpty()) \ - rv.append(QLatin1String("|")); \ + rv.append(QLatin1Char('|')); \ rv.append(QLatin1String(#value)); \ } @@ -7408,6 +7560,7 @@ QQuickItemLayer::QQuickItemLayer(QQuickItem *item) , m_effectComponent(0) , m_effect(0) , m_effectSource(0) + , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically) { } @@ -7481,6 +7634,7 @@ void QQuickItemLayer::activate() m_effectSource->setMipmap(m_mipmap); m_effectSource->setWrapMode(m_wrapMode); m_effectSource->setFormat(m_format); + m_effectSource->setTextureMirroring(m_textureMirroring); if (m_effectComponent) activateEffect(); @@ -7745,6 +7899,35 @@ void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode) } /*! + \qmlproperty enumeration QtQuick::Item::layer.textureMirroring + \since 5.6 + + This property defines how the generated OpenGL texture should be mirrored. + The default value is \c{ShaderEffectSource.MirrorVertically}. + Custom mirroring can be useful if the generated texture is directly accessed by custom shaders, + such as those specified by ShaderEffect. If no effect is specified for the layered + item, mirroring has no effect on the UI representation of the item. + + \list + \li ShaderEffectSource.NoMirroring - No mirroring + \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis. + \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis. + \endlist + */ + +void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring) +{ + if (mirroring == m_textureMirroring) + return; + m_textureMirroring = mirroring; + + if (m_effectSource) + m_effectSource->setTextureMirroring(m_textureMirroring); + + emit textureMirroringChanged(mirroring); +} + +/*! \qmlproperty string QtQuick::Item::layer.samplerName Holds the name of the effect's source texture property. @@ -7856,6 +8039,7 @@ void QQuickItemLayer::updateMatrix() QQuickItemPrivate::ExtraData::ExtraData() : z(0), scale(1), rotation(0), opacity(1), contents(0), screenAttached(0), layoutDirectionAttached(0), + enterKeyAttached(0), keyHandler(0), layer(0), effectRefCount(0), hideRefCount(0), opacityNode(0), clipNode(0), rootNode(0), @@ -7864,6 +8048,19 @@ QQuickItemPrivate::ExtraData::ExtraData() { } + +#ifndef QT_NO_ACCESSIBILITY +QAccessible::Role QQuickItemPrivate::accessibleRole() const +{ + Q_Q(const QQuickItem); + QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, false)); + if (accessibleAttached) + return accessibleAttached->role(); + + return QAccessible::NoRole; +} +#endif + QT_END_NAMESPACE #include <moc_qquickitem.cpp> diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 463113386b..d92910ce9c 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -141,7 +141,6 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL) - Q_ENUMS(TransformOrigin) Q_CLASSINFO("DefaultProperty", "data") Q_CLASSINFO("qt_HasQmlAccessors", "true") @@ -187,6 +186,7 @@ public: Left, Center, Right, BottomLeft, Bottom, BottomRight }; + Q_ENUM(TransformOrigin) QQuickItem(QQuickItem *parent = 0); virtual ~QQuickItem(); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 64d8bd0ede..634aa2b658 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -78,6 +78,7 @@ QT_BEGIN_NAMESPACE class QNetworkReply; class QQuickItemKeyFilter; class QQuickLayoutMirroringAttached; +class QQuickEnterKeyAttached; class QQuickScreenAttached; class QQuickContents : public QQuickItemChangeListener @@ -142,6 +143,7 @@ class QQuickItemLayer : public QObject, public QQuickItemChangeListener Q_PROPERTY(QQuickShaderEffectSource::Format format READ format WRITE setFormat NOTIFY formatChanged) Q_PROPERTY(QByteArray samplerName READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QQmlComponent *effect READ effect WRITE setEffect NOTIFY effectChanged) + Q_PROPERTY(QQuickShaderEffectSource::TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged) public: QQuickItemLayer(QQuickItem *item); ~QQuickItemLayer(); @@ -176,6 +178,9 @@ public: QQmlComponent *effect() const { return m_effectComponent; } void setEffect(QQmlComponent *effect); + QQuickShaderEffectSource::TextureMirroring textureMirroring() const { return m_textureMirroring; } + void setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring); + QQuickShaderEffectSource *effectSource() const { return m_effectSource; } void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE; @@ -199,6 +204,7 @@ Q_SIGNALS: void smoothChanged(bool smooth); void formatChanged(QQuickShaderEffectSource::Format format); void sourceRectChanged(const QRectF &sourceRect); + void textureMirroringChanged(QQuickShaderEffectSource::TextureMirroring mirroring); private: friend class QQuickTransformAnimatorJob; @@ -222,6 +228,7 @@ private: QQmlComponent *m_effectComponent; QQuickItem *m_effect; QQuickShaderEffectSource *m_effectSource; + QQuickShaderEffectSource::TextureMirroring m_textureMirroring; }; class Q_QUICK_PRIVATE_EXPORT QQuickItemPrivate : public QObjectPrivate @@ -338,6 +345,7 @@ public: QQuickContents *contents; QQuickScreenAttached *screenAttached; QQuickLayoutMirroringAttached* layoutDirectionAttached; + QQuickEnterKeyAttached *enterKeyAttached; QQuickItemKeyFilter *keyHandler; mutable QQuickItemLayer *layer; #ifndef QT_NO_CURSOR @@ -419,6 +427,13 @@ public: bool activeFocusOnTab:1; bool implicitAntialiasing:1; bool antialiasingValid:1; + // isTabFence: When true, the item acts as a fence within the tab focus chain. + // This means that the item and its children will be skipped from the tab focus + // chain when navigating from its parent or any of its siblings. Similarly, + // when any of the item's descendants gets focus, the item constrains the tab + // focus chain and prevents tabbing outside. + bool isTabFence:1; + bool replayingPressEvent:1; enum DirtyType { TransformOrigin = 0x00000001, @@ -490,6 +505,8 @@ public: void itemToParentTransform(QTransform &) const; static bool focusNextPrev(QQuickItem *item, bool forward); + static QQuickItem *nextTabChildItem(const QQuickItem *item, int start); + static QQuickItem *prevTabChildItem(const QQuickItem *item, int start); static QQuickItem *nextPrevItemInTabFocusChain(QQuickItem *item, bool forward); static bool canAcceptTabFocus(QQuickItem *item); @@ -517,6 +534,10 @@ public: virtual void implicitWidthChanged(); virtual void implicitHeightChanged(); +#ifndef QT_NO_ACCESSIBILITY + virtual QAccessible::Role accessibleRole() const; +#endif + void setImplicitAntialiasing(bool antialiasing); void resolveLayoutMirror(); @@ -645,8 +666,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickKeyNavigationAttached : public QObject, publi Q_PROPERTY(QQuickItem *backtab READ backtab WRITE setBacktab NOTIFY backtabChanged) Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged) - Q_ENUMS(Priority) - public: QQuickKeyNavigationAttached(QObject * = 0); @@ -664,6 +683,7 @@ public: void setBacktab(QQuickItem *); enum Priority { BeforeItem, AfterItem }; + Q_ENUM(Priority) Priority priority() const; void setPriority(Priority); @@ -710,6 +730,27 @@ private: QQuickItemPrivate *itemPrivate; }; +class QQuickEnterKeyAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(Qt::EnterKeyType type READ type WRITE setType NOTIFY typeChanged) + +public: + explicit QQuickEnterKeyAttached(QObject *parent = Q_NULLPTR); + + Qt::EnterKeyType type() const; + void setType(Qt::EnterKeyType type); + + static QQuickEnterKeyAttached *qmlAttachedProperties(QObject *); +Q_SIGNALS: + void typeChanged(); +private: + friend class QQuickItemPrivate; + QQuickItemPrivate *itemPrivate; + + Qt::EnterKeyType keyType; +}; + class QQuickKeysAttachedPrivate : public QObjectPrivate { public: @@ -739,8 +780,6 @@ class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter Q_PROPERTY(QQmlListProperty<QQuickItem> forwardTo READ forwardTo) Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged) - Q_ENUMS(Priority) - public: QQuickKeysAttached(QObject *parent=0); ~QQuickKeysAttached(); @@ -755,6 +794,7 @@ public: } enum Priority { BeforeItem, AfterItem}; + Q_ENUM(Priority) Priority priority() const; void setPriority(Priority); @@ -895,5 +935,7 @@ QML_DECLARE_TYPE(QQuickKeyNavigationAttached) QML_DECLARE_TYPEINFO(QQuickKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES) QML_DECLARE_TYPE(QQuickLayoutMirroringAttached) QML_DECLARE_TYPEINFO(QQuickLayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES) +QML_DECLARE_TYPE(QQuickEnterKeyAttached) +QML_DECLARE_TYPEINFO(QQuickEnterKeyAttached, QML_HAS_ATTACHED_PROPERTIES) #endif // QQUICKITEM_P_H diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h index 907687a2bd..338af46ecb 100644 --- a/src/quick/items/qquickitemanimation_p.h +++ b/src/quick/items/qquickitemanimation_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKITEMANIMATION_H #define QQUICKITEMANIMATION_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.h" #include <QtQuick/private/qquickanimation_p.h> @@ -136,7 +147,7 @@ public: BottomFirst, TopFirst }; - Q_ENUMS(Orientation) + Q_ENUM(Orientation) int duration() const; void setDuration(int); diff --git a/src/quick/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h index d987b62454..fd8076c6a2 100644 --- a/src/quick/items/qquickitemchangelistener_p.h +++ b/src/quick/items/qquickitemchangelistener_p.h @@ -55,16 +55,16 @@ class QQuickAnchorsPrivate; class QQuickItemChangeListener { public: - virtual ~QQuickItemChangeListener() {}; + virtual ~QQuickItemChangeListener() {} virtual void itemGeometryChanged(QQuickItem *, const QRectF & /* new */, const QRectF & /* old */ ) {} virtual void itemSiblingOrderChanged(QQuickItem *) {} virtual void itemVisibilityChanged(QQuickItem *) {} virtual void itemOpacityChanged(QQuickItem *) {} virtual void itemDestroyed(QQuickItem *) {} - virtual void itemChildAdded(QQuickItem *, QQuickItem *) {} - virtual void itemChildRemoved(QQuickItem *, QQuickItem *) {} - virtual void itemParentChanged(QQuickItem *, QQuickItem *) {} + virtual void itemChildAdded(QQuickItem *, QQuickItem * /* child */ ) {} + virtual void itemChildRemoved(QQuickItem *, QQuickItem * /* child */ ) {} + virtual void itemParentChanged(QQuickItem *, QQuickItem * /* parent */ ) {} virtual void itemRotationChanged(QQuickItem *) {} virtual void itemImplicitWidthChanged(QQuickItem *) {} virtual void itemImplicitHeightChanged(QQuickItem *) {} diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 5fbae66b6c..62e0adcb0a 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -158,11 +158,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView"); qmlRegisterUncreatableType<QQuickBasePositioner>(uri,major,minor,"Positioner", QStringLiteral("Positioner is an abstract type that is only available as an attached property.")); -#ifndef QT_NO_VALIDATOR - qmlRegisterType<QQuickIntValidator>(uri,major,minor,"IntValidator"); - qmlRegisterType<QQuickDoubleValidator>(uri,major,minor,"DoubleValidator"); - qmlRegisterType<QRegExpValidator>(uri,major,minor,"RegExpValidator"); -#endif qmlRegisterType<QQuickRectangle>(uri,major,minor,"Rectangle"); qmlRegisterType<QQuickRepeater>(uri,major,minor,"Repeater"); qmlRegisterType<QQuickRow>(uri,major,minor,"Row"); @@ -190,9 +185,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickCurve>(); qmlRegisterType<QQuickScaleGrid>(); qmlRegisterType<QQuickTextLine>(); -#ifndef QT_NO_VALIDATOR - qmlRegisterType<QValidator>(); -#endif qmlRegisterType<QQuickPen>(); qmlRegisterType<QQuickFlickableVisibleArea>(); qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine"); @@ -269,6 +261,19 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickPinchArea, 1>(uri, 2, 5,"PinchArea"); qmlRegisterType<QQuickImage, 2>(uri, 2, 5,"Image"); qmlRegisterType<QQuickMouseArea, 2>(uri, 2, 5, "MouseArea"); + + qmlRegisterType<QQuickText, 6>(uri, 2, 6, "Text"); + qmlRegisterType<QQuickTextEdit, 6>(uri, 2, 6, "TextEdit"); + qmlRegisterType<QQuickTextInput, 6>(uri, 2, 6, "TextInput"); + qmlRegisterUncreatableType<QQuickBasePositioner, 6>(uri, 2, 6, "Positioner", + QStringLiteral("Positioner is an abstract type that is only available as an attached property.")); + qmlRegisterType<QQuickColumn, 6>(uri, 2, 6, "Column"); + qmlRegisterType<QQuickRow, 6>(uri, 2, 6, "Row"); + qmlRegisterType<QQuickGrid, 6>(uri, 2, 6, "Grid"); + qmlRegisterType<QQuickFlow, 6>(uri, 2, 6, "Flow"); + qmlRegisterUncreatableType<QQuickEnterKeyAttached, 6>(uri, 2, 6, "EnterKey", + QQuickEnterKeyAttached::tr("EnterKey is only available via attached properties")); + qmlRegisterType<QQuickShaderEffectSource, 1>(uri, 2, 6, "ShaderEffectSource"); } static void initResources() diff --git a/src/quick/items/qquickitemsmodule_p.h b/src/quick/items/qquickitemsmodule_p.h index a7442e972a..b04e9ff23f 100644 --- a/src/quick/items/qquickitemsmodule_p.h +++ b/src/quick/items/qquickitemsmodule_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKITEMSMODULE_P_H #define QQUICKITEMSMODULE_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 <qqml.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 01ef1e65f7..b618daf64b 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -71,19 +71,19 @@ FxViewItem::~FxViewItem() qreal FxViewItem::itemX() const { - return transitionableItem ? transitionableItem->itemX() : item->x(); + return transitionableItem ? transitionableItem->itemX() : (item ? item->x() : 0); } qreal FxViewItem::itemY() const { - return transitionableItem ? transitionableItem->itemY() : item->y(); + return transitionableItem ? transitionableItem->itemY() : (item ? item->y() : 0); } void FxViewItem::moveTo(const QPointF &pos, bool immediate) { if (transitionableItem) transitionableItem->moveTo(pos, immediate); - else + else if (item) item->setPosition(pos); } @@ -91,21 +91,26 @@ void FxViewItem::setVisible(bool visible) { if (!visible && transitionableItem && transitionableItem->transitionScheduledOrRunning()) return; - QQuickItemPrivate::get(item)->setCulled(!visible); + if (item) + QQuickItemPrivate::get(item)->setCulled(!visible); } void FxViewItem::trackGeometry(bool track) { if (track) { if (!trackGeom) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + if (item) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + } trackGeom = true; } } else { if (trackGeom) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + if (item) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + } trackGeom = false; } } @@ -905,11 +910,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) qreal pos = isContentFlowReversed() ? -position() - size() : position(); FxViewItem *item = visibleItem(idx); - qreal maxExtent; - if (layoutOrientation() == Qt::Vertical) - maxExtent = isContentFlowReversed() ? q->minYExtent()-size(): -q->maxYExtent(); - else - maxExtent = isContentFlowReversed() ? q->minXExtent()-size(): -q->maxXExtent(); + qreal maxExtent = calculatedMaxExtent(); if (!item) { qreal itemPos = positionAt(idx); changedVisibleIndex(idx); @@ -955,11 +956,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) break; } pos = qMin(pos, maxExtent); - qreal minExtent; - if (layoutOrientation() == Qt::Vertical) - minExtent = isContentFlowReversed() ? q->maxYExtent()-size(): -q->minYExtent(); - else - minExtent = isContentFlowReversed() ? q->maxXExtent()-size(): -q->minXExtent(); + qreal minExtent = calculatedMinExtent(); pos = qMax(pos, minExtent); moveReason = QQuickItemViewPrivate::Other; q->cancelFlick(); @@ -1130,6 +1127,29 @@ qreal QQuickItemViewPrivate::maxExtentForAxis(const AxisData &axisData, bool for return extent; } +qreal QQuickItemViewPrivate::calculatedMinExtent() const +{ + Q_Q(const QQuickItemView); + qreal minExtent; + if (layoutOrientation() == Qt::Vertical) + minExtent = isContentFlowReversed() ? q->maxYExtent() - size(): -q->minYExtent(); + else + minExtent = isContentFlowReversed() ? q->maxXExtent() - size(): -q->minXExtent(); + return minExtent; + +} + +qreal QQuickItemViewPrivate::calculatedMaxExtent() const +{ + Q_Q(const QQuickItemView); + qreal maxExtent; + if (layoutOrientation() == Qt::Vertical) + maxExtent = isContentFlowReversed() ? q->minYExtent() - size(): -q->maxYExtent(); + else + maxExtent = isContentFlowReversed() ? q->minXExtent() - size(): -q->maxXExtent(); + return maxExtent; +} + // for debugging only void QQuickItemViewPrivate::checkVisible() const { @@ -1199,7 +1219,7 @@ void QQuickItemView::destroyRemoved() for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end();) { FxViewItem *item = *it; - if (item->index == -1 && item->attached->delayRemove() == false) { + if (item->index == -1 && (!item->attached || item->attached->delayRemove() == false)) { if (d->transitioner && d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) { // don't remove from visibleItems until next layout() d->runDelayedRemoveTransition = true; @@ -1277,10 +1297,12 @@ void QQuickItemView::trackedPositionChanged() if (trackedPos < pos + d->highlightRangeStart) pos = trackedPos - d->highlightRangeStart; if (d->highlightRange != StrictlyEnforceRange) { - if (pos > d->endPosition() - d->size()) - pos = d->endPosition() - d->size(); - if (pos < d->startPosition()) - pos = d->startPosition(); + qreal maxExtent = d->calculatedMaxExtent(); + if (pos > maxExtent) + pos = maxExtent; + qreal minExtent = d->calculatedMinExtent(); + if (pos < minExtent) + pos = minExtent; } } else { if (d->trackedItem != d->currentItem) { @@ -1344,7 +1366,7 @@ void QQuickItemView::geometryChanged(const QRectF &newGeometry, const QRectF &ol { Q_D(QQuickItemView); d->markExtentsDirty(); - if (isComponentComplete() && d->isValid()) + if (isComponentComplete() && (d->isValid() || !d->visibleItems.isEmpty())) d->forceLayoutPolish(); QQuickFlickable::geometryChanged(newGeometry, oldGeometry); } @@ -1641,7 +1663,8 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex) applyPendingChanges(); if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) { if (currentItem) { - currentItem->attached->setIsCurrentItem(false); + if (currentItem->attached) + currentItem->attached->setIsCurrentItem(false); releaseItem(currentItem); currentItem = 0; currentIndex = modelIndex; @@ -1664,18 +1687,20 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex) int oldCurrentIndex = currentIndex; currentIndex = modelIndex; currentItem = createItem(modelIndex, false); - if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item)) + if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item)) oldCurrentItem->attached->setIsCurrentItem(false); if (currentItem) { currentItem->item->setFocus(true); - currentItem->attached->setIsCurrentItem(true); + if (currentItem->attached) + currentItem->attached->setIsCurrentItem(true); initializeCurrentItem(); } updateHighlight(); if (oldCurrentIndex != currentIndex) emit q->currentIndexChanged(); - if (oldCurrentItem != currentItem) + if (oldCurrentItem != currentItem + && (!oldCurrentItem || !currentItem || oldCurrentItem->item != currentItem->item)) emit q->currentItemChanged(); releaseItem(oldCurrentItem); } @@ -1806,7 +1831,7 @@ void QQuickItemViewPrivate::updateViewport() { Q_Q(QQuickItemView); qreal extra = headerSize() + footerSize(); - qreal contentSize = isValid() ? (endPosition() - startPosition()) : 0.0; + qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0; if (layoutOrientation() == Qt::Vertical) q->setContentHeight(contentSize + extra); else @@ -1824,6 +1849,7 @@ void QQuickItemViewPrivate::layout() if (!isValid() && !visibleItems.count()) { clear(); setPosition(contentStartOffset()); + updateViewport(); if (transitioner) transitioner->setPopulateTransitionEnabled(false); inLayout = false; @@ -1967,7 +1993,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult QQmlChangeSet::Change removal; for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) { FxViewItem *item = *it; - if (item->index == -1 && !item->attached->delayRemove()) { + if (item->index == -1 && (!item->attached || !item->attached->delayRemove())) { removeItem(item, removal, &removalResult); removedCount++; it = visibleItems.erase(it); @@ -2007,8 +2033,10 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult } itemCount += insertions[i].count; } - for (int i=0; i<newItems.count(); i++) - newItems.at(i)->attached->emitAdd(); + for (int i=0; i<newItems.count(); i++) { + if (newItems.at(i)->attached) + newItems.at(i)->attached->emitAdd(); + } // for each item that was moved directly into the view as a result of a move(), // find the index it was moved from in order to set its initial position, so that we @@ -2040,7 +2068,8 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult if (currentChanges.currentChanged) { if (currentChanges.currentRemoved && currentItem) { - currentItem->attached->setIsCurrentItem(false); + if (currentItem->item && currentItem->attached) + currentItem->attached->setIsCurrentItem(false); releaseItem(currentItem); currentItem = 0; } @@ -2092,10 +2121,10 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QQmlChangeSet::Change &remo } else { // removed item visibleAffected = true; - if (!removal.isMove()) + if (!removal.isMove() && item->item && item->attached) item->attached->emitRemove(); - if (item->attached->delayRemove() && !removal.isMove()) { + if (item->item && item->attached && item->attached->delayRemove() && !removal.isMove()) { item->index = -1; QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection); ++it; @@ -2352,12 +2381,14 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item) item->trackGeometry(false); QQmlInstanceModel::ReleaseFlags flags = model->release(item->item); - if (flags == 0) { - // item was not destroyed, and we no longer reference it. - QQuickItemPrivate::get(item->item)->setCulled(true); - unrequestedItems.insert(item->item, model->indexOf(item->item, q)); - } else if (flags & QQmlInstanceModel::Destroyed) { - item->item->setParentItem(0); + if (item->item) { + if (flags == 0) { + // item was not destroyed, and we no longer reference it. + QQuickItemPrivate::get(item->item)->setCulled(true); + unrequestedItems.insert(item->item, model->indexOf(item->item, q)); + } else if (flags & QQmlInstanceModel::Destroyed) { + item->item->setParentItem(0); + } } delete item; return flags != QQmlInstanceModel::Referenced; @@ -2421,7 +2452,7 @@ void QQuickItemViewPrivate::updateUnrequestedIndexes() void QQuickItemViewPrivate::updateUnrequestedPositions() { - for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.begin(), cend = unrequestedItems.end(); it != cend; ++it) + for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it) repositionPackageItemAt(it.key(), it.value()); } diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index 6e5ae032c2..789b5a3e55 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKITEMVIEW_P_H #define QQUICKITEMVIEW_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 "qquickflickable_p.h" #include <qpointer.h> #include <QtCore/QLoggingCategory> @@ -88,11 +99,6 @@ class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd) Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged) - Q_ENUMS(HighlightRangeMode) - Q_ENUMS(PositionMode) - Q_ENUMS(VerticalLayoutDirection) - Q_ENUMS(LayoutDirection) - public: // this holds all layout enum values so they can be referred to by other enums // to ensure consistent values - e.g. QML references to GridView.TopToBottom flow @@ -103,11 +109,13 @@ public: VerticalTopToBottom, VerticalBottomToTop }; + Q_ENUM(LayoutDirection) enum VerticalLayoutDirection { TopToBottom = VerticalTopToBottom, BottomToTop = VerticalBottomToTop }; + Q_ENUM(VerticalLayoutDirection) QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent = 0); ~QQuickItemView(); @@ -185,6 +193,7 @@ public: virtual void setHighlightFollowsCurrentItem(bool); enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange }; + Q_ENUM(HighlightRangeMode) HighlightRangeMode highlightRangeMode() const; void setHighlightRangeMode(HighlightRangeMode mode); @@ -200,6 +209,7 @@ public: virtual void setHighlightMoveDuration(int); enum PositionMode { Beginning, Center, End, Visible, Contain, SnapPosition }; + Q_ENUM(PositionMode) Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(qreal x, qreal y) const; diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index a8352b229e..8af703eb03 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKITEMVIEW_P_P_H #define QQUICKITEMVIEW_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 "qquickitemview_p.h" #include "qquickitemviewtransition_p.h" #include "qquickflickable_p_p.h" @@ -53,6 +64,8 @@ public: qreal itemX() const; qreal itemY() const; + inline qreal itemWidth() const { return item ? item->width() : 0; } + inline qreal itemHeight() const { return item ? item->height() : 0; } void moveTo(const QPointF &pos, bool immediate); void setVisible(bool visible); @@ -75,7 +88,7 @@ public: virtual bool contains(qreal x, qreal y) const = 0; - QQuickItem *item; + QPointer<QQuickItem> item; QQuickItemView *view; QQuickItemViewTransitionableItem *transitionableItem; QQuickItemViewAttached *attached; @@ -198,6 +211,8 @@ public: qreal minExtentForAxis(const AxisData &axisData, bool forXAxis) const; qreal maxExtentForAxis(const AxisData &axisData, bool forXAxis) const; + qreal calculatedMinExtent() const; + qreal calculatedMaxExtent() const; void applyPendingChanges(); bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult); diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp index 3218e3847c..565377df58 100644 --- a/src/quick/items/qquickitemviewtransition.cpp +++ b/src/quick/items/qquickitemviewtransition.cpp @@ -34,6 +34,7 @@ #include "qquickitemviewtransition_p.h" #include <QtQuick/qquickitem.h> #include <QtQuick/private/qquicktransition_p.h> +#include <QtQuick/private/qquicktransitionmanager_p_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h index 170072a814..b4c2705fd3 100644 --- a/src/quick/items/qquickitemviewtransition_p.h +++ b/src/quick/items/qquickitemviewtransition_p.h @@ -34,16 +34,31 @@ #ifndef QQUICKITEMVIEWTRANSITION_P_P_H #define QQUICKITEMVIEWTRANSITION_P_P_H -#include <private/qquicktransitionmanager_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 <QtQuick/private/qtquickglobal_p.h> +#include <QtCore/qobject.h> +#include <QtCore/qpoint.h> +#include <QtQml/qqml.h> QT_BEGIN_NAMESPACE class QQuickItem; +class QQuickTransition; class QQuickItemViewTransitionableItem; class QQuickItemViewTransitionJob; -class QQuickItemViewTransitionChangeListener +class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionChangeListener { public: QQuickItemViewTransitionChangeListener() {} @@ -53,7 +68,7 @@ public: }; -class QQuickItemViewTransitioner +class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitioner { public: enum TransitionType { @@ -113,7 +128,7 @@ private: /* An item that can be transitioned using QQuickViewTransitionJob. */ -class QQuickItemViewTransitionableItem +class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionableItem { public: QQuickItemViewTransitionableItem(QQuickItem *i); diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 20b6dd5b36..2958c0a67a 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -267,18 +267,18 @@ public: } qreal itemPosition() const { if (view->orientation() == QQuickListView::Vertical) - return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -item->height()-itemY() : itemY()); + return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -itemHeight()-itemY() : itemY()); else - return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-itemX() : itemX()); + return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -itemWidth()-itemX() : itemX()); } qreal size() const Q_DECL_OVERRIDE { if (section()) - return (view->orientation() == QQuickListView::Vertical ? item->height()+section()->height() : item->width()+section()->width()); + return (view->orientation() == QQuickListView::Vertical ? itemHeight()+section()->height() : itemWidth()+section()->width()); else - return (view->orientation() == QQuickListView::Vertical ? item->height() : item->width()); + return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth()); } qreal itemSize() const { - return (view->orientation() == QQuickListView::Vertical ? item->height() : item->width()); + return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth()); } qreal sectionSize() const Q_DECL_OVERRIDE { if (section()) @@ -289,11 +289,11 @@ public: if (view->orientation() == QQuickListView::Vertical) { return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -itemY() - : itemY() + item->height()); + : itemY() + itemHeight()); } else { return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -itemX() - : itemX() + item->width()); + : itemX() + itemWidth()); } } void setPosition(qreal pos, bool immediate = false) { @@ -320,8 +320,8 @@ public: item->setWidth(size); } bool contains(qreal x, qreal y) const Q_DECL_OVERRIDE { - return (x >= itemX() && x < itemX() + item->width() && - y >= itemY() && y < itemY() + item->height()); + return (x >= itemX() && x < itemX() + itemWidth() && + y >= itemY() && y < itemY() + itemHeight()); } QQuickListView *view; @@ -332,7 +332,7 @@ private: if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop) { if (section()) pos += section()->height(); - return QPointF(itemX(), -item->height() - pos); + return QPointF(itemX(), -itemHeight() - pos); } else { if (section()) pos += section()->height(); @@ -342,7 +342,7 @@ private: if (view->effectiveLayoutDirection() == Qt::RightToLeft) { if (section()) pos += section()->width(); - return QPointF(-item->width() - pos, itemY()); + return QPointF(-itemWidth() - pos, itemY()); } else { if (section()) pos += section()->width(); @@ -427,14 +427,24 @@ qreal QQuickListViewPrivate::lastPosition() const { qreal pos = 0; if (!visibleItems.isEmpty()) { - int invisibleCount = visibleItems.count() - visibleIndex; + int invisibleCount = INT_MIN; + int delayRemovedCount = 0; for (int i = visibleItems.count()-1; i >= 0; --i) { if (visibleItems.at(i)->index != -1) { - invisibleCount = model->count() - visibleItems.at(i)->index - 1; + // Find the invisible count after the last visible item with known index + invisibleCount = model->count() - (visibleItems.at(i)->index + 1 + delayRemovedCount); break; + } else if (visibleItems.at(i)->attached->delayRemove()) { + ++delayRemovedCount; } } - pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing); + if (invisibleCount == INT_MIN) { + // All visible items are in delayRemove state + invisibleCount = model->count(); + } + pos = (*(--visibleItems.constEnd()))->endPosition(); + if (invisibleCount > 0) + pos += invisibleCount * (averageSize + spacing); } else if (model && model->count()) { pos = (model->count() * averageSize + (model->count()-1) * spacing); } @@ -599,10 +609,11 @@ bool QQuickListViewPrivate::releaseItem(FxViewItem *item) if (!item || !model) return true; + QPointer<QQuickItem> it = item->item; QQuickListViewAttached *att = static_cast<QQuickListViewAttached*>(item->attached); bool released = QQuickItemViewPrivate::releaseItem(item); - if (released && att && att->m_sectionItem) { + if (released && it && att && att->m_sectionItem) { // We hold no more references to this item int i = 0; do { @@ -657,10 +668,11 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal while (modelIndex < model->count() && pos <= fillTo) { if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer)))) break; - qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << item->item->objectName(); + qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << (QObject *)(item->item); if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems() item->setPosition(pos, true); - QQuickItemPrivate::get(item->item)->setCulled(doBuffer); + if (item->item) + QQuickItemPrivate::get(item->item)->setCulled(doBuffer); pos += item->size() + spacing; visibleItems.append(item); ++modelIndex; @@ -673,12 +685,13 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) { if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, doBuffer)))) break; - qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << item->item->objectName(); + qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << (QObject *)(item->item); --visibleIndex; visiblePos -= item->size() + spacing; if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems() item->setPosition(visiblePos, true); - QQuickItemPrivate::get(item->item)->setCulled(doBuffer); + if (item->item) + QQuickItemPrivate::get(item->item)->setCulled(doBuffer); visibleItems.prepend(item); changed = true; } @@ -709,7 +722,7 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer visibleIndex++; visibleItems.removeAt(index); if (item->transitionScheduledOrRunning()) { - qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << item->item->objectName(); + qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << (QObject *)(item->item); item->releaseAfterTransition = true; releasePendingTransition.append(item); } else { @@ -728,10 +741,10 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) { if (item->attached->delayRemove()) break; - qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << item->item->objectName(); + qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << (QObject *)(item->item); visibleItems.removeLast(); if (item->transitionScheduledOrRunning()) { - qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << item->item->objectName(); + qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << (QObject *)(item->item); item->releaseAfterTransition = true; releasePendingTransition.append(item); } else { @@ -1388,6 +1401,15 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF & if (!q->isComponentComplete()) return; + if (currentItem && currentItem->item == item) { + const bool contentFlowReversed = isContentFlowReversed(); + const qreal pos = position(); + const qreal sz = size(); + const qreal from = contentFlowReversed ? -pos - displayMarginBeginning - sz : pos - displayMarginBeginning; + const qreal to = contentFlowReversed ? -pos + displayMarginEnd : pos + sz + displayMarginEnd; + QQuickItemPrivate::get(currentItem->item)->setCulled(currentItem->endPosition() < from || currentItem->position() > to); + } + if (item != contentItem && (!highlight || item != highlight->item)) { if ((orient == QQuickListView::Vertical && newGeometry.height() != oldGeometry.height()) || (orient == QQuickListView::Horizontal && newGeometry.width() != oldGeometry.width())) { @@ -1457,13 +1479,13 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte tempPosition -= bias; } FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart); - if (!topItem && strictHighlightRange && currentItem) { + if (strictHighlightRange && currentItem) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); topItem = currentItem; } FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd); - if (!bottomItem && strictHighlightRange && currentItem) { + if (strictHighlightRange && currentItem) { // StrictlyEnforceRange always keeps an item in range updateHighlight(); bottomItem = currentItem; @@ -2844,7 +2866,8 @@ void QQuickListView::viewportMoved(Qt::Orientations orient) qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd; for (int i = 0; i < d->visibleItems.count(); ++i) { FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i)); - QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to); + if (item->item) + QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to); } if (d->currentItem) QQuickItemPrivate::get(d->currentItem->item)->setCulled(d->currentItem->endPosition() < from || d->currentItem->position() > to); diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h index bcb4e18751..5f8be2ab02 100644 --- a/src/quick/items/qquicklistview_p.h +++ b/src/quick/items/qquicklistview_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKLISTVIEW_P_H #define QQUICKLISTVIEW_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 "qquickitemview_p.h" QT_BEGIN_NAMESPACE @@ -47,8 +58,6 @@ class Q_AUTOTEST_EXPORT QQuickViewSection : public QObject Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY criteriaChanged) Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_PROPERTY(int labelPositioning READ labelPositioning WRITE setLabelPositioning NOTIFY labelPositioningChanged) - Q_ENUMS(SectionCriteria) - Q_ENUMS(LabelPositioning) public: QQuickViewSection(QQuickListView *parent=0); @@ -56,6 +65,7 @@ public: void setProperty(const QString &); enum SectionCriteria { FullString, FirstCharacter }; + Q_ENUM(SectionCriteria) SectionCriteria criteria() const { return m_criteria; } void setCriteria(SectionCriteria); @@ -65,6 +75,7 @@ public: QString sectionString(const QString &value); enum LabelPositioning { InlineLabels = 0x01, CurrentLabelAtStart = 0x02, NextLabelAtEnd = 0x04 }; + Q_ENUM(LabelPositioning) int labelPositioning() { return m_labelPositioning; } void setLabelPositioning(int pos); @@ -106,10 +117,6 @@ class Q_AUTOTEST_EXPORT QQuickListView : public QQuickItemView Q_PROPERTY(HeaderPositioning headerPositioning READ headerPositioning WRITE setHeaderPositioning NOTIFY headerPositioningChanged REVISION 2) Q_PROPERTY(FooterPositioning footerPositioning READ footerPositioning WRITE setFooterPositioning NOTIFY footerPositioningChanged REVISION 2) - Q_ENUMS(Orientation) - Q_ENUMS(SnapMode) - Q_ENUMS(HeaderPositioning) - Q_ENUMS(FooterPositioning) Q_CLASSINFO("DefaultProperty", "data") public: @@ -120,6 +127,7 @@ public: void setSpacing(qreal spacing); enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical }; + Q_ENUM(Orientation) Orientation orientation() const; void setOrientation(Orientation); @@ -140,14 +148,17 @@ public: void setHighlightMoveDuration(int) Q_DECL_OVERRIDE; enum SnapMode { NoSnap, SnapToItem, SnapOneItem }; + Q_ENUM(SnapMode) SnapMode snapMode() const; void setSnapMode(SnapMode mode); enum HeaderPositioning { InlineHeader, OverlayHeader, PullBackHeader }; + Q_ENUM(HeaderPositioning) HeaderPositioning headerPositioning() const; void setHeaderPositioning(HeaderPositioning positioning); enum FooterPositioning { InlineFooter, OverlayFooter, PullBackFooter }; + Q_ENUM(FooterPositioning) FooterPositioning footerPositioning() const; void setFooterPositioning(FooterPositioning positioning); diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index dd04568db2..456eedd0be 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -576,7 +576,6 @@ void QQuickLoader::setSource(QQmlV4Function *args) if (!ipv->isUndefined()) { d->disposeInitialPropertyValues(); d->initialPropertyValues.set(args->v4engine(), ipv); - d->qmlGlobalForIpv.set(args->v4engine(), args->qmlGlobal()); } setSource(sourceUrl, false); // already cleared and set ipv above. @@ -642,11 +641,11 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj) QQmlComponentPrivate *d = QQmlComponentPrivate::get(component); Q_ASSERT(d && d->engine); - QV4::ExecutionEngine *v4 = qmlGlobalForIpv.engine(); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(d->engine); Q_ASSERT(v4); QV4::Scope scope(v4); QV4::ScopedValue ipv(scope, initialPropertyValues.value()); - d->initializeObjectWithInitialProperties(*qmlGlobalForIpv.valueRef(), ipv, obj); + d->initializeObjectWithInitialProperties(ipv, obj); } void QQuickLoaderIncubator::statusChanged(Status status) @@ -932,7 +931,7 @@ QUrl QQuickLoaderPrivate::resolveSourceUrl(QQmlV4Function *args) if (arg.isEmpty()) return QUrl(); - QQmlContextData *context = args->context(); + QQmlContextData *context = scope.engine->callingQmlContext(); Q_ASSERT(context); return context->resolvedUrl(QUrl(arg)); } @@ -943,7 +942,7 @@ QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Funct QV4::ScopedValue valuemap(scope, QV4::Primitive::undefinedValue()); if (args->length() >= 2) { QV4::ScopedValue v(scope, (*args)[1]); - if (!v->isObject() || v->asArrayObject()) { + if (!v->isObject() || v->as<QV4::ArrayObject>()) { *error = true; qmlInfo(loader) << QQuickLoader::tr("setSource: value is not an object"); } else { diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h index 2c0e98de59..e9d765fa5c 100644 --- a/src/quick/items/qquickloader_p.h +++ b/src/quick/items/qquickloader_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKLOADER_P_H #define QQUICKLOADER_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 "qquickimplicitsizeitem_p.h" QT_BEGIN_NAMESPACE @@ -42,7 +53,6 @@ class QQuickLoaderPrivate; class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem { Q_OBJECT - Q_ENUMS(Status) Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) @@ -69,6 +79,7 @@ public: void resetSourceComponent(); enum Status { Null, Ready, Loading, Error }; + Q_ENUM(Status) Status status() const; qreal progress() const; diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index 621419d1a7..9677318b58 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -50,7 +50,7 @@ #include "qquickitemchangelistener_p.h" #include <qqmlincubator.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> QT_BEGIN_NAMESPACE @@ -102,7 +102,6 @@ public: QQmlContext *itemContext; QQuickLoaderIncubator *incubator; QV4::PersistentValue initialPropertyValues; - QV4::PersistentValue qmlGlobalForIpv; bool updatingSize: 1; bool active : 1; bool loadingFromSource : 1; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 4a44760035..b933dc240a 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -921,6 +921,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event) break; case QEvent::MouseButtonRelease: mouseReleaseEvent(&mouseEvent); + stealThisEvent = d->stealMouse; break; default: break; diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index 4ad14e6bdd..e3cbf2553c 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKMOUSEAREA_P_H #define QQUICKMOUSEAREA_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.h" #include <private/qtquickglobal_p.h> #include <QtCore/qstringlist.h> diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index e6b63d32f2..13ace44f9a 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -451,6 +451,12 @@ void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event) } break; } + case QEvent::TouchCancel: + _stealMouse = false; + setKeepMouseGrab(false); + setKeepTouchGrab(false); + ungrabTouchPoints(); + break; default: QQuickItem::touchEvent(event); break; diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h index e5c547da81..792724a9c8 100644 --- a/src/quick/items/qquickmultipointtoucharea_p.h +++ b/src/quick/items/qquickmultipointtoucharea_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKMULTIPOINTTOUCHAREA_H #define QQUICKMULTIPOINTTOUCHAREA_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.h" #include "qevent.h" diff --git a/src/quick/items/qquickopenglinfo_p.h b/src/quick/items/qquickopenglinfo_p.h index 2a2e2a719b..511413c814 100644 --- a/src/quick/items/qquickopenglinfo_p.h +++ b/src/quick/items/qquickopenglinfo_p.h @@ -63,7 +63,6 @@ class QQuickOpenGLInfo : public QObject Q_PROPERTY(int minorVersion READ minorVersion NOTIFY minorVersionChanged FINAL) Q_PROPERTY(ContextProfile profile READ profile NOTIFY profileChanged FINAL) Q_PROPERTY(RenderableType renderableType READ renderableType NOTIFY renderableTypeChanged FINAL) - Q_ENUMS(ContextProfile RenderableType) public: QQuickOpenGLInfo(QQuickItem *item = 0); @@ -77,6 +76,7 @@ public: CoreProfile = QSurfaceFormat::CoreProfile, CompatibilityProfile = QSurfaceFormat::CompatibilityProfile }; + Q_ENUM(ContextProfile) ContextProfile profile() const; // keep in sync with QSurfaceFormat::RenderableType @@ -85,6 +85,7 @@ public: OpenGL = QSurfaceFormat::OpenGL, OpenGLES = QSurfaceFormat::OpenGLES }; + Q_ENUM(RenderableType) RenderableType renderableType() const; static QQuickOpenGLInfo *qmlAttachedProperties(QObject *object); diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index 8d93c577ab..4172b83419 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -67,15 +67,11 @@ public: To enable QPainter to do anti-aliased rendering, use setAntialiasing(). - To write your own painted item, you first create a subclass of QQuickPaintedItem, and then - start by implementing its only pure virtual public function: paint(), which implements - the actual painting. To get the size of the area painted by the item, use - contentsBoundingRect(). - - Starting Qt 5.4, the QQuickPaintedItem is a - \l{QSGTextureProvider}{texture provider} - and can be used directly in \l {ShaderEffect}{ShaderEffects} and other - classes that consume texture providers. + To write your own painted item, you first create a subclass of + QQuickPaintedItem, and then start by implementing its only pure virtual + public function: paint(), which implements the actual painting. The + painting will be inside the rectangle spanning from 0,0 to + width(),height(). */ /*! @@ -109,11 +105,12 @@ public: This enum describes flags that you can enable to improve rendering performance in QQuickPaintedItem. By default, none of these flags are set. - \value FastFBOResizing If your item gets resized often and you are using the - QQuickPaintedItem::FramebufferObject render target, set this flag to true to reduce the - item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object - is a costly operation, by enabling this property the Framebuffer Object will use a texture - larger than the actual size of the item to avoid as much as possible resizing it. + \value FastFBOResizing Resizing an FBO can be a costly operation on a few + OpenGL driver implementations. To work around this, one can set this flag + to let the QQuickPaintedItem allocate one large framebuffer object and + instead draw into a subregion of it. This saves the resize at the cost of + using more memory. Please note that this is not a common problem. + */ /*! @@ -332,16 +329,47 @@ void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints update(); } +QSize QQuickPaintedItem::textureSize() const +{ + Q_D(const QQuickPaintedItem); + return d->textureSize; +} + /*! - This function returns the outer bounds of the item as a rectangle; all painting must be - restricted to inside an item's bounding rect. + \property QQuickPaintedItem::textureSize + + \brief Defines the size of the texture. - If the contents size has not been set it reflects the size of the item; otherwise - it reflects the contents size scaled by the contents scale. + Changing the texture's size does not affect the coordinate system used in + paint(). A scale factor is instead applied so painting should still happen + inside 0,0 to width(),height(). - Use this function to know the area painted by the item. + By default, the texture size will have the same size as this item. - \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale() + \note If the item is on a window with a device pixel ratio different from + 1, this scale factor will be implicitly applied to the texture size. + + */ +void QQuickPaintedItem::setTextureSize(const QSize &size) +{ + Q_D(QQuickPaintedItem); + if (d->textureSize == size) + return; + d->textureSize = size; + emit textureSizeChanged(); +} + +#if QT_VERSION >= 0x060000 +#warning "Remove: QQuickPaintedItem::contentsBoundingRect, contentsScale, contentsSize. Also remove them from qsgadaptationlayer_p.h and qsgdefaultpainternode.h/cpp." +#endif + +/*! + \obsolete + + This function is provided for compatibility, use size in combination + with textureSize to decide the size of what you are drawing. + + \sa width(), height(), textureSize() */ QRectF QQuickPaintedItem::contentsBoundingRect() const { @@ -360,11 +388,13 @@ QRectF QQuickPaintedItem::contentsBoundingRect() const /*! \property QQuickPaintedItem::contentsSize - \brief The size of the contents + \brief Obsolete method for setting the contents size. + \obsolete + + This function is provided for compatibility, use size in combination + with textureSize to decide the size of what you are drawing. - The contents size is the size of the item in regards to how it is painted - using the paint() function. This is distinct from the size of the - item in regards to height() and width(). + \sa width(), height(), textureSize() */ QSize QQuickPaintedItem::contentsSize() const { @@ -386,6 +416,7 @@ void QQuickPaintedItem::setContentsSize(const QSize &size) } /*! + \obsolete This convenience function is equivalent to calling setContentsSize(QSize()). */ void QQuickPaintedItem::resetContentsSize() @@ -395,12 +426,13 @@ void QQuickPaintedItem::resetContentsSize() /*! \property QQuickPaintedItem::contentsScale - \brief The scale of the contents + \brief Obsolete method for scaling the contents. + \obsolete - All painting happening in paint() is scaled by the contents scale. This is distinct - from the scale of the item in regards to scale(). + This function is provided for compatibility, use size() in combination + with textureSize() to decide the size of what you are drawing. - The default value is 1. + \sa width(), height(), textureSize() */ qreal QQuickPaintedItem::contentsScale() const { @@ -487,6 +519,9 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target) This function, which is usually called by the QML Scene Graph, paints the contents of an item in local coordinates. + The underlying texture will have a size defined by textureSize when set, + or the item's size, multiplied by the window's device pixel ratio. + The function is called after the item has been filled with the fillColor. Reimplement this function in a QQuickPaintedItem subclass to provide the @@ -500,6 +535,8 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target) \warning Extreme caution must be used when creating QObjects, emitting signals, starting timers and similar inside this function as these will have affinity to the rendering thread. + + \sa width(), height(), textureSize */ /*! @@ -525,17 +562,35 @@ QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat d->node = node; } - QRectF br = contentsBoundingRect(); + bool hasTextureSize = d->textureSize.width() > 0 && d->textureSize.height() > 0; + + // Use the compat mode if any of the compat things are set and + // textureSize is 0x0. + if (!hasTextureSize + && (d->contentsScale != 1 + || (d->contentsSize.width() > 0 && d->contentsSize.height() > 0))) { + QRectF br = contentsBoundingRect(); + node->setContentsScale(d->contentsScale); + QSize size = QSize(qRound(br.width()), qRound(br.height())); + node->setSize(size); + node->setTextureSize(size); + } else { + // The default, use textureSize or item's size * device pixel ratio + node->setContentsScale(1); + QSize itemSize(qRound(width()), qRound(height())); + node->setSize(itemSize); + QSize textureSize = (hasTextureSize ? d->textureSize : itemSize) + * window()->effectiveDevicePixelRatio(); + node->setTextureSize(textureSize); + } node->setPreferredRenderTarget(d->renderTarget); node->setFastFBOResizing(d->performanceHints & FastFBOResizing); - node->setSize(QSize(qRound(br.width()), qRound(br.height()))); node->setSmoothPainting(d->antialiasing); node->setLinearFiltering(d->smooth); node->setMipmapping(d->mipmap); node->setOpaquePainting(d->opaquePainting); node->setFillColor(d->fillColor); - node->setContentsScale(d->contentsScale); node->setDirty(d->dirtyRect); node->update(); diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h index 356e4a46f6..8c9ae2eebb 100644 --- a/src/quick/items/qquickpainteditem.h +++ b/src/quick/items/qquickpainteditem.h @@ -43,12 +43,13 @@ class QQuickPaintedItemPrivate; class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem { Q_OBJECT - Q_ENUMS(RenderTarget) Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged) Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged) Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged) Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged) + Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged) + public: QQuickPaintedItem(QQuickItem *parent = 0); virtual ~QQuickPaintedItem(); @@ -58,6 +59,7 @@ public: FramebufferObject, InvertedYFramebufferObject }; + Q_ENUM(RenderTarget) enum PerformanceHint { FastFBOResizing = 0x1 @@ -88,6 +90,9 @@ public: qreal contentsScale() const; void setContentsScale(qreal); + QSize textureSize() const; + void setTextureSize(const QSize &size); + QColor fillColor() const; void setFillColor(const QColor&); @@ -104,6 +109,7 @@ Q_SIGNALS: void contentsSizeChanged(); void contentsScaleChanged(); void renderTargetChanged(); + void textureSizeChanged(); protected: QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0); diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h index 3712e964f8..d0e4f9481d 100644 --- a/src/quick/items/qquickpainteditem_p.h +++ b/src/quick/items/qquickpainteditem_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKPAINTEDITEM_P_P_H #define QQUICKPAINTEDITEM_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 <QtGui/qcolor.h> @@ -42,7 +53,7 @@ QT_BEGIN_NAMESPACE class QQuickPaintedItemTextureProvider; class QSGPainterNode; -class QQuickPaintedItemPrivate : public QQuickItemPrivate +class Q_QUICK_PRIVATE_EXPORT QQuickPaintedItemPrivate : public QQuickItemPrivate { public: QQuickPaintedItemPrivate(); @@ -52,6 +63,7 @@ public: QColor fillColor; QQuickPaintedItem::RenderTarget renderTarget; QQuickPaintedItem::PerformanceHints performanceHints; + QSize textureSize; QRect dirtyRect; diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 58605f79dd..05bf50574c 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -98,7 +98,7 @@ QQuickPathViewPrivate::QQuickPathViewPrivate() , inRefill(false) , dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY) , moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0) - , firstIndex(-1), pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0) + , pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0) , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0) , moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition) , highlightPosition(0) @@ -447,7 +447,6 @@ void QQuickPathViewPrivate::regenerate() if (!isValid()) return; - firstIndex = -1; updateMappedRange(); q->refill(); } @@ -754,7 +753,7 @@ void QQuickPathView::setCurrentIndex(int idx) if (d->modelCount) { d->createCurrentItem(); if (d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) - d->snapToIndex(d->currentIndex); + d->snapToIndex(d->currentIndex, QQuickPathViewPrivate::SetIndex); d->currentItemOffset = d->positionOfIndex(d->currentIndex); d->updateHighlight(); } @@ -989,7 +988,7 @@ void QQuickPathView::setHighlightRangeMode(HighlightRangeMode mode) d->regenerate(); int index = d->highlightRangeMode != NoHighlightRange ? d->currentIndex : d->calcCurrentIndex(); if (index >= 0) - d->snapToIndex(index); + d->snapToIndex(index, QQuickPathViewPrivate::Other); } emit highlightRangeModeChanged(); } @@ -1473,7 +1472,7 @@ int QQuickPathView::indexAt(qreal x, qreal y) const QQuickItem *item = d->items.at(idx); QPointF p = item->mapFromItem(this, QPointF(x, y)); if (item->contains(p)) - return (d->firstIndex + idx) % d->modelCount; + return d->model->indexOf(item, 0); } return -1; @@ -1896,12 +1895,12 @@ void QQuickPathView::refill() int count = d->pathItems == -1 ? d->modelCount : qMin(d->pathItems, d->modelCount); // first move existing items and remove items off path - int idx = d->firstIndex; - qCDebug(lcItemViewDelegateLifecycle) << "firstIndex" << idx << "currentIndex" << d->currentIndex << "offset" << d->offset; + qCDebug(lcItemViewDelegateLifecycle) << "currentIndex" << d->currentIndex << "offset" << d->offset; QList<QQuickItem*>::iterator it = d->items.begin(); while (it != d->items.end()) { - qreal pos = d->positionOfIndex(idx); QQuickItem *item = *it; + int idx = d->model->indexOf(item, 0); + qreal pos = d->positionOfIndex(idx); if (lcItemViewDelegateLifecycle().isDebugEnabled()) { QQuickText *text = qmlobject_cast<QQuickText*>(item); if (text) @@ -1923,81 +1922,140 @@ void QQuickPathView::refill() if (!d->isInBound(pos, d->mappedRange - d->mappedCache, 1.0 + d->mappedCache)) { qCDebug(lcItemViewDelegateLifecycle) << "release" << idx << "@" << pos << ", !isInBound: lower" << (d->mappedRange - d->mappedCache) << "upper" << (1.0 + d->mappedCache); d->releaseItem(item); - if (it == d->items.begin()) { - if (++d->firstIndex >= d->modelCount) { - d->firstIndex = 0; - } - } it = d->items.erase(it); } else { ++it; } } - ++idx; - if (idx >= d->modelCount) - idx = 0; } - if (!d->items.count()) - d->firstIndex = -1; - bool waiting = false; if (d->modelCount) { - // add items to beginning and end + // add items as needed if (d->items.count() < count+d->cacheSize) { - int idx = qRound(d->modelCount - d->offset) % d->modelCount; + int endIdx = 0; + qreal endPos; + int startIdx = 0; qreal startPos = 0.0; - if (d->haveHighlightRange && (d->highlightRangeMode != QQuickPathView::NoHighlightRange - || d->snapMode != QQuickPathView::NoSnap)) - startPos = d->highlightRangeStart; - if (d->firstIndex >= 0) { - startPos = d->positionOfIndex(d->firstIndex); - idx = (d->firstIndex + d->items.count()) % d->modelCount; + if (d->items.count()) { + //Find the beginning and end, items may not be in sorted order + endPos = -1.0; + startPos = 2.0; + + for (int i = 0; i < d->items.count(); i++) { + int idx = d->model->indexOf(d->items[i], 0); + qreal curPos = d->positionOfIndex(idx); + if (curPos > endPos) { + endPos = curPos; + endIdx = idx; + } + + if (curPos < startPos) { + startPos = curPos; + startIdx = idx; + } + } + } else { + if (d->haveHighlightRange + && (d->highlightRangeMode != QQuickPathView::NoHighlightRange + || d->snapMode != QQuickPathView::NoSnap)) + startPos = d->highlightRangeStart; + // With no items, then "end" is just off the top so we populate via append + endIdx = (qRound(d->modelCount - d->offset) - 1) % d->modelCount; + endPos = d->positionOfIndex(endIdx); } - qreal pos = d->positionOfIndex(idx); - while ((d->isInBound(pos, startPos, 1.0 + d->mappedCache) || !d->items.count()) && d->items.count() < count+d->cacheSize) { - qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); - QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0); + //Append + int idx = endIdx + 1; + if (idx >= d->modelCount) + idx = 0; + qreal nextPos = d->positionOfIndex(idx); + while ((d->isInBound(nextPos, endPos, 1.0 + d->mappedCache) || !d->items.count()) + && d->items.count() < count+d->cacheSize) { + qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); + QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0); if (!item) { waiting = true; break; } + if (d->items.contains(item)) { + break; //Otherwise we'd "re-add" it, and get confused + } if (d->currentIndex == idx) { currentVisible = true; - d->currentItemOffset = pos; + d->currentItemOffset = nextPos; } - if (d->items.count() == 0) - d->firstIndex = idx; d->items.append(item); - d->updateItem(item, pos); + d->updateItem(item, nextPos); + endIdx = idx; + endPos = nextPos; ++idx; if (idx >= d->modelCount) idx = 0; - pos = d->positionOfIndex(idx); + nextPos = d->positionOfIndex(idx); } - idx = d->firstIndex - 1; + //Prepend + idx = startIdx - 1; if (idx < 0) idx = d->modelCount - 1; - pos = d->positionOfIndex(idx); - while (!waiting && d->isInBound(pos, d->mappedRange - d->mappedCache, startPos) && d->items.count() < count+d->cacheSize) { - qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); - QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0); + nextPos = d->positionOfIndex(idx); + while (!waiting && d->isInBound(nextPos, d->mappedRange - d->mappedCache, startPos) + && d->items.count() < count+d->cacheSize) { + qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); + QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0); if (!item) { waiting = true; break; } + if (d->items.contains(item)) { + break; //Otherwise we'd "re-add" it, and get confused + } if (d->currentIndex == idx) { currentVisible = true; - d->currentItemOffset = pos; + d->currentItemOffset = nextPos; } d->items.prepend(item); - d->updateItem(item, pos); - d->firstIndex = idx; - idx = d->firstIndex - 1; + d->updateItem(item, nextPos); + startIdx = idx; + startPos = nextPos; + --idx; if (idx < 0) idx = d->modelCount - 1; - pos = d->positionOfIndex(idx); + nextPos = d->positionOfIndex(idx); + } + + // In rare cases, when jumping around with pathCount close to modelCount, + // new items appear in the middle. This more generic addition iteration handles this + // Since this is the rare case, we try append/prepend first and only do this if + // there are gaps still left to fill. + if (!waiting && d->items.count() < count+d->cacheSize) { + qCDebug(lcItemViewDelegateLifecycle) << "Checking for pathview middle inserts, items count was" << d->items.count(); + idx = startIdx; + QQuickItem *lastItem = d->items[0]; + while (idx != endIdx) { + //This gets the reference from the delegate model, and will not re-create + QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0); + if (!item) { + waiting = true; + break; + } + if (!d->items.contains(item)) { //We found a hole + nextPos = d->positionOfIndex(idx); + qCDebug(lcItemViewDelegateLifecycle) << "middle insert" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); + if (d->currentIndex == idx) { + currentVisible = true; + d->currentItemOffset = nextPos; + } + int lastListIdx = d->items.indexOf(lastItem); + d->items.insert(lastListIdx + 1, item); + d->updateItem(item, nextPos); + } + + lastItem = item; + ++idx; + if (idx >= d->modelCount) + idx = 0; + } } } } @@ -2128,7 +2186,6 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) d->offset = qmlMod(d->modelCount - d->currentIndex, d->modelCount); changedOffset = true; } - d->firstIndex = -1; d->updateMappedRange(); d->scheduleLayout(); } @@ -2185,8 +2242,16 @@ void QQuickPathViewPrivate::createCurrentItem() { if (requestedIndex != -1) return; - int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount; - if (itemIndex < items.count()) { + + bool inItems = false; + for (int i = 0; i < items.count(); i++) { + if (model->indexOf(items[i], 0) == currentIndex) { + inItems = true; + break; + } + } + + if (inItems) { if ((currentItem = getItem(currentIndex, currentIndex))) { currentItem->setFocus(true); if (QQuickPathViewAttached *att = attached(currentItem)) @@ -2241,12 +2306,12 @@ void QQuickPathViewPrivate::fixOffset() if (curr != currentIndex && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) q->setCurrentIndex(curr); else - snapToIndex(curr); + snapToIndex(curr, Other); } } } -void QQuickPathViewPrivate::snapToIndex(int index) +void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) { if (!model || modelCount <= 0) return; @@ -2256,7 +2321,7 @@ void QQuickPathViewPrivate::snapToIndex(int index) if (offset == targetOffset) return; - moveReason = Other; + moveReason = reason; offsetAdj = 0.0; tl.reset(moveOffset); moveOffset.setValue(offset); diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h index 8062e07795..0973d65a58 100644 --- a/src/quick/items/qquickpathview_p.h +++ b/src/quick/items/qquickpathview_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKPATHVIEW_P_H #define QQUICKPATHVIEW_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.h" #include <private/qquickpath_p.h> @@ -78,10 +89,6 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged) - Q_ENUMS(HighlightRangeMode) - Q_ENUMS(SnapMode) - Q_ENUMS(PositionMode) - public: QQuickPathView(QQuickItem *parent=0); virtual ~QQuickPathView(); @@ -105,6 +112,7 @@ public: QQuickItem *highlightItem(); enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange }; + Q_ENUM(HighlightRangeMode) HighlightRangeMode highlightRangeMode() const; void setHighlightRangeMode(HighlightRangeMode mode); @@ -146,10 +154,12 @@ public: void setCacheItemCount(int); enum SnapMode { NoSnap, SnapToItem, SnapOneItem }; + Q_ENUM(SnapMode) SnapMode snapMode() const; void setSnapMode(SnapMode mode); enum PositionMode { Beginning, Center, End, Contain=4, SnapPosition }; // 3 == Visible in other views + Q_ENUM(PositionMode) Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(qreal x, qreal y) const; Q_INVOKABLE QQuickItem *itemAt(qreal x, qreal y) const; diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 35ea8616a5..73e4884424 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -114,7 +114,8 @@ public: void setAdjustedOffset(qreal offset); void regenerate(); void updateItem(QQuickItem *, qreal); - void snapToIndex(int index); + enum MovementReason { Other, SetIndex, Mouse }; + void snapToIndex(int index, MovementReason reason); QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const; void addVelocitySample(qreal v); qreal calcVelocity() const; @@ -155,7 +156,6 @@ public: QQuickTimeLine tl; QQuickTimeLineValueProxy<QQuickPathViewPrivate> moveOffset; int flickDuration; - int firstIndex; int pathItems; int requestedIndex; int cacheSize; @@ -164,7 +164,6 @@ public: QList<QQuickItem *> itemCache; QPointer<QQmlInstanceModel> model; QVariant modelVariant; - enum MovementReason { Other, SetIndex, Mouse }; MovementReason moveReason; enum MovementDirection { Shortest, Negative, Positive }; MovementDirection moveDirection; diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h index d2de59b5d6..d623a70010 100644 --- a/src/quick/items/qquickpincharea_p.h +++ b/src/quick/items/qquickpincharea_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKPINCHAREA_H #define QQUICKPINCHAREA_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.h" QT_BEGIN_NAMESPACE @@ -42,7 +53,6 @@ class Q_AUTOTEST_EXPORT QQuickPinch : public QObject { Q_OBJECT - Q_ENUMS(Axis) Q_PROPERTY(QQuickItem *target READ target WRITE setTarget RESET resetTarget) Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged) Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged) @@ -103,6 +113,7 @@ public: } enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis }; + Q_ENUM(Axis) Axis axis() const { return m_axis; } void setAxis(Axis a) { if (a == m_axis) diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index 887d317069..de2596b679 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -70,6 +70,10 @@ QQuickBasePositioner::PositionedItem::PositionedItem(QQuickItem *i) , index(-1) , isNew(false) , isVisible(true) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) { } @@ -116,6 +120,13 @@ void QQuickBasePositioner::PositionedItem::startTransition(QQuickItemViewTransit transitionableItem->startTransition(transitioner, index); } +void QQuickBasePositioner::PositionedItem::updatePadding(qreal lp, qreal tp, qreal rp, qreal bp) +{ + leftPadding = lp; + topPadding = tp; + rightPadding = rp; + bottomPadding = bp; +} QQuickBasePositioner::QQuickBasePositioner(PositionerType at, QQuickItem *parent) : QQuickImplicitSizeItem(*(new QQuickBasePositionerPrivate), parent) @@ -388,11 +399,8 @@ void QQuickBasePositioner::prePositioning() void QQuickBasePositioner::positionItem(qreal x, qreal y, PositionedItem *target) { - Q_D(QQuickBasePositioner); - if ( (target->itemX() != x || target->itemY() != y) - && d->type == Both) { + if ( target->itemX() != x || target->itemY() != y ) target->moveTo(QPointF(x, y)); - } } void QQuickBasePositioner::positionItemX(qreal x, PositionedItem *target) @@ -503,6 +511,185 @@ void QQuickBasePositioner::updateAttachedProperties(QQuickPositionerAttached *sp } } +qreal QQuickBasePositioner::padding() const +{ + Q_D(const QQuickBasePositioner); + return d->padding(); +} + +void QQuickBasePositioner::setPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + if (qFuzzyCompare(d->padding(), padding)) + return; + + d->extra.value().padding = padding; + d->setPositioningDirty(); + emit paddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitTopPadding) + emit topPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickBasePositioner::resetPadding() +{ + setPadding(0); +} + +qreal QQuickBasePositioner::topPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->extra.isAllocated() && d->extra->explicitTopPadding) + return d->extra->topPadding; + return d->padding(); +} + +void QQuickBasePositioner::setTopPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setTopPadding(padding); +} + +void QQuickBasePositioner::resetTopPadding() +{ + Q_D(QQuickBasePositioner); + d->setTopPadding(0, true); +} + +qreal QQuickBasePositioner::leftPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->extra.isAllocated() && d->extra->explicitLeftPadding) + return d->extra->leftPadding; + return d->padding(); +} + +void QQuickBasePositioner::setLeftPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setLeftPadding(padding); +} + +void QQuickBasePositioner::resetLeftPadding() +{ + Q_D(QQuickBasePositioner); + d->setLeftPadding(0, true); +} + +qreal QQuickBasePositioner::rightPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->extra.isAllocated() && d->extra->explicitRightPadding) + return d->extra->rightPadding; + return d->padding(); +} + +void QQuickBasePositioner::setRightPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setRightPadding(padding); +} + +void QQuickBasePositioner::resetRightPadding() +{ + Q_D(QQuickBasePositioner); + d->setRightPadding(0, true); +} + +qreal QQuickBasePositioner::bottomPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->extra.isAllocated() && d->extra->explicitBottomPadding) + return d->extra->bottomPadding; + return d->padding(); +} + +void QQuickBasePositioner::setBottomPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setBottomPadding(padding); +} + +void QQuickBasePositioner::resetBottomPadding() +{ + Q_D(QQuickBasePositioner); + d->setBottomPadding(0, true); +} + +QQuickBasePositionerPrivate::ExtraData::ExtraData() + : padding(0) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , explicitTopPadding(false) + , explicitLeftPadding(false) + , explicitRightPadding(false) + , explicitBottomPadding(false) +{ +} + +void QQuickBasePositionerPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal oldPadding = q->topPadding(); + if (!reset || extra.isAllocated()) { + extra.value().topPadding = value; + extra.value().explicitTopPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + setPositioningDirty(); + emit q->topPaddingChanged(); + } +} + +void QQuickBasePositionerPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal oldPadding = q->leftPadding(); + if (!reset || extra.isAllocated()) { + extra.value().leftPadding = value; + extra.value().explicitLeftPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + setPositioningDirty(); + emit q->leftPaddingChanged(); + } +} + +void QQuickBasePositionerPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal oldPadding = q->rightPadding(); + if (!reset || extra.isAllocated()) { + extra.value().rightPadding = value; + extra.value().explicitRightPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + setPositioningDirty(); + emit q->rightPaddingChanged(); + } +} + +void QQuickBasePositionerPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal oldPadding = q->bottomPadding(); + if (!reset || extra.isAllocated()) { + extra.value().bottomPadding = value; + extra.value().explicitBottomPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + setPositioningDirty(); + emit q->bottomPaddingChanged(); + } +} + /*! \qmltype Positioner \instantiates QQuickPositionerAttached @@ -640,6 +827,16 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem) \sa Row, Grid, Flow, Positioner, ColumnLayout, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Column::padding + \qmlproperty real QtQuick::Column::topPadding + \qmlproperty real QtQuick::Column::leftPadding + \qmlproperty real QtQuick::Column::bottomPadding + \qmlproperty real QtQuick::Column::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Column::populate This property holds the transition to be run for items that are part of @@ -715,20 +912,23 @@ QQuickColumn::QQuickColumn(QQuickItem *parent) void QQuickColumn::doPositioning(QSizeF *contentSize) { //Precondition: All items in the positioned list have a valid item pointer and should be positioned - qreal voffset = 0; + qreal voffset = topPadding(); + const qreal padding = leftPadding() + rightPadding(); + contentSize->setWidth(qMax(contentSize->width(), padding)); for (int ii = 0; ii < positionedItems.count(); ++ii) { PositionedItem &child = positionedItems[ii]; - positionItemY(voffset, &child); - contentSize->setWidth(qMax(contentSize->width(), child.item->width())); + positionItem(child.itemX() + leftPadding() - child.leftPadding, voffset, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); + contentSize->setWidth(qMax(contentSize->width(), child.item->width() + padding)); voffset += child.item->height(); voffset += spacing(); } - if (voffset != 0)//If we positioned any items, undo the spacing from the last item + if (voffset - topPadding() != 0)//If we positioned any items, undo the spacing from the last item voffset -= spacing(); - contentSize->setHeight(voffset); + contentSize->setHeight(voffset + bottomPadding()); } void QQuickColumn::reportConflictingAnchors() @@ -794,6 +994,16 @@ void QQuickColumn::reportConflictingAnchors() \sa Column, Grid, Flow, Positioner, RowLayout, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Row::padding + \qmlproperty real QtQuick::Row::topPadding + \qmlproperty real QtQuick::Row::leftPadding + \qmlproperty real QtQuick::Row::bottomPadding + \qmlproperty real QtQuick::Row::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Row::populate This property holds the transition to be run for items that are part of @@ -940,27 +1150,34 @@ void QQuickRow::doPositioning(QSizeF *contentSize) { //Precondition: All items in the positioned list have a valid item pointer and should be positioned QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this)); - qreal hoffset = 0; + qreal hoffset1 = leftPadding(); + qreal hoffset2 = rightPadding(); + if (!d->isLeftToRight()) + qSwap(hoffset1, hoffset2); + qreal hoffset = hoffset1; + const qreal padding = topPadding() + bottomPadding(); + contentSize->setHeight(qMax(contentSize->height(), padding)); QList<qreal> hoffsets; for (int ii = 0; ii < positionedItems.count(); ++ii) { PositionedItem &child = positionedItems[ii]; if (d->isLeftToRight()) { - positionItemX(hoffset, &child); + positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); } else { hoffsets << hoffset; } - contentSize->setHeight(qMax(contentSize->height(), child.item->height())); + contentSize->setHeight(qMax(contentSize->height(), child.item->height() + padding)); hoffset += child.item->width(); hoffset += spacing(); } - if (hoffset != 0)//If we positioned any items, undo the extra spacing from the last item + if (hoffset - hoffset1 != 0)//If we positioned any items, undo the extra spacing from the last item hoffset -= spacing(); - contentSize->setWidth(hoffset); + contentSize->setWidth(hoffset + hoffset2); if (d->isLeftToRight()) return; @@ -976,7 +1193,8 @@ void QQuickRow::doPositioning(QSizeF *contentSize) for (int ii = 0; ii < positionedItems.count(); ++ii) { PositionedItem &child = positionedItems[ii]; hoffset = end - hoffsets[acc++] - child.item->width(); - positionItemX(hoffset, &child); + positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); } } @@ -1044,6 +1262,16 @@ void QQuickRow::reportConflictingAnchors() \sa Flow, Row, Column, Positioner, GridLayout, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Grid::padding + \qmlproperty real QtQuick::Grid::topPadding + \qmlproperty real QtQuick::Grid::leftPadding + \qmlproperty real QtQuick::Grid::bottomPadding + \qmlproperty real QtQuick::Grid::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Grid::populate This property holds the transition to be run for items that are part of @@ -1423,8 +1651,11 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) c = (numVisible+(m_rows-1))/m_rows; } - if (r == 0 || c == 0) - return; //Nothing to do + if (r == 0 || c == 0) { + contentSize->setHeight(topPadding() + bottomPadding()); + contentSize->setWidth(leftPadding() + rightPadding()); + return; //Nothing else to do + } QList<qreal> maxColWidth; QList<qreal> maxRowHeight; @@ -1476,6 +1707,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) widthSum += columnSpacing; widthSum += maxColWidth[j]; } + widthSum += leftPadding() + rightPadding(); qreal heightSum = 0; for (int i = 0; i < maxRowHeight.size(); i++) { @@ -1483,6 +1715,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) heightSum += rowSpacing; heightSum += maxRowHeight[i]; } + heightSum += topPadding() + bottomPadding(); contentSize->setHeight(heightSum); contentSize->setWidth(widthSum); @@ -1493,10 +1726,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) else end = widthSum; - qreal xoffset = 0; + qreal xoffset = leftPadding(); if (!d->isLeftToRight()) - xoffset = end; - qreal yoffset = 0; + xoffset = end - rightPadding(); + qreal yoffset = topPadding(); int curRow =0; int curCol =0; for (int i = 0; i < positionedItems.count(); ++i) { @@ -1518,6 +1751,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) alignYOffset += maxRowHeight[curRow] - child.item->height(); positionItem(childXOffset, alignYOffset, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); if (m_flow == LeftToRight) { if (d->isLeftToRight()) @@ -1529,9 +1763,9 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) if (!curCol) { yoffset += maxRowHeight[curRow]+rowSpacing; if (d->isLeftToRight()) - xoffset = 0; + xoffset = leftPadding(); else - xoffset = end; + xoffset = end - rightPadding(); curRow++; if (curRow>=r) break; @@ -1545,7 +1779,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) xoffset += maxColWidth[curCol]+columnSpacing; else xoffset -= maxColWidth[curCol]+columnSpacing; - yoffset = 0; + yoffset = topPadding(); curCol++; if (curCol>=c) break; @@ -1603,6 +1837,16 @@ void QQuickGrid::reportConflictingAnchors() \sa Column, Row, Grid, Positioner, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Flow::padding + \qmlproperty real QtQuick::Flow::topPadding + \qmlproperty real QtQuick::Flow::leftPadding + \qmlproperty real QtQuick::Flow::bottomPadding + \qmlproperty real QtQuick::Flow::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Flow::populate This property holds the transition to be run for items that are part of @@ -1786,23 +2030,30 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) //Precondition: All items in the positioned list have a valid item pointer and should be positioned Q_D(QQuickFlow); - qreal hoffset = 0; - qreal voffset = 0; + qreal hoffset1 = leftPadding(); + qreal hoffset2 = rightPadding(); + if (!d->isLeftToRight()) + qSwap(hoffset1, hoffset2); + qreal hoffset = hoffset1; + const qreal voffset1 = topPadding(); + qreal voffset = voffset1; qreal linemax = 0; QList<qreal> hoffsets; + contentSize->setWidth(qMax(contentSize->width(), hoffset1 + hoffset2)); + contentSize->setHeight(qMax(contentSize->height(), voffset + bottomPadding())); for (int i = 0; i < positionedItems.count(); ++i) { PositionedItem &child = positionedItems[i]; if (d->flow == LeftToRight) { - if (widthValid() && hoffset && hoffset + child.item->width() > width()) { - hoffset = 0; + if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) { + hoffset = hoffset1; voffset += linemax + spacing(); linemax = 0; } } else { - if (heightValid() && voffset && voffset + child.item->height() > height()) { - voffset = 0; + if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) { + voffset = voffset1; hoffset += linemax + spacing(); linemax = 0; } @@ -1810,13 +2061,16 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) if (d->isLeftToRight()) { positionItem(hoffset, voffset, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); } else { hoffsets << hoffset; positionItemY(voffset, &child); + child.topPadding = topPadding(); + child.bottomPadding = bottomPadding(); } - contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width())); - contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height())); + contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2)); + contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding())); if (d->flow == LeftToRight) { hoffset += child.item->width(); @@ -1828,6 +2082,7 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) linemax = qMax(linemax, child.item->width()); } } + if (d->isLeftToRight()) return; @@ -1841,6 +2096,8 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) PositionedItem &child = positionedItems[i]; hoffset = end - hoffsets[acc++] - child.item->width(); positionItemX(hoffset, &child); + child.leftPadding = leftPadding(); + child.rightPadding = rightPadding(); } } diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index ea779695eb..fca64b0a22 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKPOSITIONERS_P_H #define QQUICKPOSITIONERS_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 "qquickimplicitsizeitem_p.h" #include "qquickitemviewtransition_p.h" @@ -86,6 +97,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte Q_PROPERTY(QQuickTransition *populate READ populate WRITE setPopulate NOTIFY populateChanged) Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged) Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged) + + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) public: enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 }; @@ -108,6 +125,26 @@ public: void updateAttachedProperties(QQuickPositionerAttached *specificProperty = 0, QQuickItem *specificPropertyOwner = 0) const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + protected: QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent); void componentComplete() Q_DECL_OVERRIDE; @@ -120,6 +157,11 @@ Q_SIGNALS: void populateChanged(); void moveChanged(); void addChanged(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); protected Q_SLOTS: void prePositioning(); @@ -144,11 +186,18 @@ protected: bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds); void startTransition(QQuickItemViewTransitioner *transitioner); + void updatePadding(qreal lp, qreal tp, qreal rp, qreal bp); + QQuickItem *item; QQuickItemViewTransitionableItem *transitionableItem; int index; bool isNew; bool isVisible; + + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; }; QPODVector<PositionedItem,8> positionedItems; @@ -236,8 +285,8 @@ public: void setColumnSpacing(qreal); void resetColumnSpacing() { m_useColumnSpacing = false; } - Q_ENUMS(Flow) enum Flow { LeftToRight, TopToBottom }; + Q_ENUM(Flow) Flow flow() const; void setFlow(Flow); @@ -245,14 +294,14 @@ public: void setLayoutDirection (Qt::LayoutDirection); Qt::LayoutDirection effectiveLayoutDirection() const; - Q_ENUMS(HAlignment) - Q_ENUMS(VAlignment) enum HAlignment { AlignLeft = Qt::AlignLeft, AlignRight = Qt::AlignRight, AlignHCenter = Qt::AlignHCenter}; + Q_ENUM(HAlignment) enum VAlignment { AlignTop = Qt::AlignTop, AlignBottom = Qt::AlignBottom, AlignVCenter = Qt::AlignVCenter }; + Q_ENUM(VAlignment) HAlignment hItemAlign() const; void setHItemAlign(HAlignment align); @@ -301,8 +350,8 @@ class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner public: QQuickFlow(QQuickItem *parent=0); - Q_ENUMS(Flow) enum Flow { LeftToRight, TopToBottom }; + Q_ENUM(Flow) Flow flow() const; void setFlow(Flow); diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h index 3a8fe20351..6e1e15d4ef 100644 --- a/src/quick/items/qquickpositioners_p_p.h +++ b/src/quick/items/qquickpositioners_p_p.h @@ -51,6 +51,7 @@ #include <QtQuick/private/qquickstate_p.h> #include <private/qquicktransitionmanager_p_p.h> #include <private/qquickstatechangescript_p.h> +#include <private/qlazilyallocated_p.h> #include <QtCore/qobject.h> #include <QtCore/qstring.h> @@ -65,10 +66,26 @@ class QQuickBasePositionerPrivate : public QQuickImplicitSizeItemPrivate, public Q_DECLARE_PUBLIC(QQuickBasePositioner) public: + struct ExtraData { + ExtraData(); + + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding : 1; + bool explicitLeftPadding : 1; + bool explicitRightPadding : 1; + bool explicitBottomPadding : 1; + }; + QLazilyAllocated<ExtraData> extra; + QQuickBasePositionerPrivate() : spacing(0), type(QQuickBasePositioner::None) , transitioner(0), positioningDirty(false) , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight) + { } @@ -149,6 +166,12 @@ public: virtual void effectiveLayoutDirectionChange() { } + + inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; } + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h index 8a00dbaf92..feca74cb41 100644 --- a/src/quick/items/qquickrectangle_p.h +++ b/src/quick/items/qquickrectangle_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKRECTANGLE_P_H #define QQUICKRECTANGLE_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.h" #include <QtGui/qbrush.h> @@ -125,7 +136,7 @@ private: }; class QQuickRectanglePrivate; -class Q_AUTOTEST_EXPORT QQuickRectangle : public QQuickItem +class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem { Q_OBJECT diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 6b0b9c3a06..cc4cec443a 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -46,7 +46,6 @@ #include <QtQuick/QQuickWindow> #include <QtQuick/private/qquickwindow_p.h> -#include <private/qqmlprofilerservice_p.h> #include <QtCore/private/qobject_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp index 0168d73c8f..09b504b742 100644 --- a/src/quick/items/qquickrepeater.cpp +++ b/src/quick/items/qquickrepeater.cpp @@ -50,6 +50,7 @@ QQuickRepeaterPrivate::QQuickRepeaterPrivate() , delegateValidated(false) , itemCount(0) { + setTransparentForPositioner(true); } QQuickRepeaterPrivate::~QQuickRepeaterPrivate() @@ -360,8 +361,8 @@ void QQuickRepeater::clear() if (QQuickItem *item = d->deletables.at(i)) { if (complete) emit itemRemoved(i, item); - item->setParentItem(0); d->model->release(item); + item->setParentItem(0); } } } @@ -397,9 +398,17 @@ void QQuickRepeaterPrivate::requestItems() void QQuickRepeater::createdItem(int index, QObject *) { Q_D(QQuickRepeater); + QObject *object = d->model->object(index, false); + QQuickItem *item = qmlobject_cast<QQuickItem*>(object); + emit itemAdded(index, item); +} + +void QQuickRepeater::initItem(int index, QObject *object) +{ + Q_D(QQuickRepeater); + QQuickItem *item = qmlobject_cast<QQuickItem*>(object); + if (!d->deletables.at(index)) { - QObject *object = d->model->object(index, false); - QQuickItem *item = qmlobject_cast<QQuickItem*>(object); if (!item) { if (object) { d->model->release(object); @@ -425,17 +434,9 @@ void QQuickRepeater::createdItem(int index, QObject *) } item->stackBefore(after); } - emit itemAdded(index, item); } } -void QQuickRepeater::initItem(int, QObject *object) -{ - QQuickItem *item = qmlobject_cast<QQuickItem*>(object); - if (item) - item->setParentItem(parentItem()); -} - void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset) { Q_D(QQuickRepeater); @@ -465,8 +466,8 @@ void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset) d->deletables.remove(index); emit itemRemoved(index, item); if (item) { - item->setParentItem(0); d->model->release(item); + item->setParentItem(0); } --d->itemCount; } diff --git a/src/quick/items/qquickrepeater_p.h b/src/quick/items/qquickrepeater_p.h index 5f652da975..c0a0a32f5f 100644 --- a/src/quick/items/qquickrepeater_p.h +++ b/src/quick/items/qquickrepeater_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKREPEATER_P_H #define QQUICKREPEATER_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.h" QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h index 7e0c021c19..1d067f1a94 100644 --- a/src/quick/items/qquickscalegrid_p_p.h +++ b/src/quick/items/qquickscalegrid_p_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSCALEGRID_P_P_H #define QQUICKSCALEGRID_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 "qquickborderimage_p.h" #include <QtQml/qqml.h> @@ -47,7 +58,6 @@ QT_BEGIN_NAMESPACE class QQuickScaleGrid : public QObject { Q_OBJECT - Q_ENUMS(TileRule) Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged) Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged) diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h index 266f7bfed8..d8c8cbde2f 100644 --- a/src/quick/items/qquickscreen_p.h +++ b/src/quick/items/qquickscreen_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSCREEN_P_H #define QQUICKSCREEN_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 <qqml.h> #include <QRect> #include <QSize> diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h index 1c60d9feaa..a5e993ee0c 100644 --- a/src/quick/items/qquickshadereffect_p.h +++ b/src/quick/items/qquickshadereffect_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSHADEREFFECT_P_H #define QQUICKSHADEREFFECT_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 <QtQuick/qquickitem.h> #include <QtQuick/qsgmaterial.h> @@ -92,8 +103,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffect : public QQuickItem Q_PROPERTY(QString log READ log NOTIFY logChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(bool supportsAtlasTextures READ supportsAtlasTextures WRITE setSupportsAtlasTextures NOTIFY supportsAtlasTexturesChanged REVISION 1) - Q_ENUMS(CullMode) - Q_ENUMS(Status) public: enum CullMode @@ -102,6 +111,7 @@ public: BackFaceCulling = QQuickShaderEffectMaterial::BackFaceCulling, FrontFaceCulling = QQuickShaderEffectMaterial::FrontFaceCulling }; + Q_ENUM(CullMode) enum Status { @@ -109,6 +119,7 @@ public: Uncompiled, Error }; + Q_ENUM(Status) QQuickShaderEffect(QQuickItem *parent = 0); ~QQuickShaderEffect(); diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h index b392753bf8..eb0f03ea81 100644 --- a/src/quick/items/qquickshadereffectmesh_p.h +++ b/src/quick/items/qquickshadereffectmesh_p.h @@ -43,6 +43,17 @@ #ifndef QQUICKSHADEREFFECTMESH_P_H #define QQUICKSHADEREFFECTMESH_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. +// + QT_BEGIN_NAMESPACE class QSGGeometry; diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp index be6ecfae18..ed9e29d599 100644 --- a/src/quick/items/qquickshadereffectnode.cpp +++ b/src/quick/items/qquickshadereffectnode.cpp @@ -83,7 +83,9 @@ QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickShaderEffectM , m_compiled(false) , m_initialized(false) { - for (int i = 0; i < m_attributes.count(); ++i) + const int attributesCount = m_attributes.count(); + m_attributeNames.reserve(attributesCount + 1); + for (int i = 0; i < attributesCount; ++i) m_attributeNames.append(m_attributes.at(i).constData()); m_attributeNames.append(0); } diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h index a6a6d1b2fc..76aecd1b04 100644 --- a/src/quick/items/qquickshadereffectnode_p.h +++ b/src/quick/items/qquickshadereffectnode_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSHADEREFFECTNODE_P_H #define QQUICKSHADEREFFECTNODE_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 <QtQuick/qsgnode.h> #include <QtQuick/qsgmaterial.h> #include <QtQuick/qsgtextureprovider.h> diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index bf69fe4277..2effc0d0ae 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -189,6 +189,7 @@ QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent) , m_mipmap(false) , m_recursive(false) , m_grab(true) + , m_textureMirroring(MirrorVertically) { setFlag(ItemHasContents); } @@ -543,6 +544,37 @@ void QQuickShaderEffectSource::setRecursive(bool enabled) } /*! + \qmlproperty enumeration QtQuick::ShaderEffectSource::textureMirroring + \since 5.6 + + This property defines how the generated OpenGL texture should be mirrored. + The default value is \c{ShaderEffectSource.MirrorVertically}. + Custom mirroring can be useful if the generated texture is directly accessed by custom shaders, + such as those specified by ShaderEffect. Mirroring has no effect on the UI representation of + the ShaderEffectSource item itself. + + \list + \li ShaderEffectSource.NoMirroring - No mirroring + \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis. + \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis. + \endlist +*/ + +QQuickShaderEffectSource::TextureMirroring QQuickShaderEffectSource::textureMirroring() const +{ + return QQuickShaderEffectSource::TextureMirroring(m_textureMirroring); +} + +void QQuickShaderEffectSource::setTextureMirroring(TextureMirroring mirroring) +{ + if (mirroring == QQuickShaderEffectSource::TextureMirroring(m_textureMirroring)) + return; + m_textureMirroring = mirroring; + update(); + emit textureMirroringChanged(); +} + +/*! \qmlmethod QtQuick::ShaderEffectSource::scheduleUpdate() Schedules a re-rendering of the texture for the next frame. @@ -642,6 +674,8 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint m_texture->setRecursive(m_recursive); m_texture->setFormat(GLenum(m_format)); m_texture->setHasMipmaps(m_mipmap); + m_texture->setMirrorHorizontal(m_textureMirroring & MirrorHorizontally); + m_texture->setMirrorVertical(m_textureMirroring & MirrorVertically); if (m_grab) m_texture->scheduleUpdate(); diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index 31e503be42..c9d50cef9e 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSHADEREFFECTSOURCE_P_H #define QQUICKSHADEREFFECTSOURCE_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.h" #include <QtQuick/qsgtextureprovider.h> #include <private/qsgadaptationlayer_p.h> @@ -66,8 +77,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffectSource : public QQuickItem, publi Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged) Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged) Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) + Q_PROPERTY(TextureMirroring textureMirroring READ textureMirroring WRITE setTextureMirroring NOTIFY textureMirroringChanged REVISION 1) - Q_ENUMS(Format WrapMode) public: enum WrapMode { ClampToEdge, @@ -75,12 +86,21 @@ public: RepeatVertically, Repeat }; + Q_ENUM(WrapMode) enum Format { Alpha = GL_ALPHA, RGB = GL_RGB, RGBA = GL_RGBA }; + Q_ENUM(Format) + + enum TextureMirroring { + NoMirroring = 0x00, + MirrorHorizontally = 0x01, + MirrorVertically = 0x02 + }; + Q_ENUM(TextureMirroring) QQuickShaderEffectSource(QQuickItem *parent = 0); ~QQuickShaderEffectSource(); @@ -112,6 +132,9 @@ public: bool recursive() const; void setRecursive(bool enabled); + TextureMirroring textureMirroring() const; + void setTextureMirroring(TextureMirroring mirroring); + bool isTextureProvider() const Q_DECL_OVERRIDE { return true; } QSGTextureProvider *textureProvider() const Q_DECL_OVERRIDE; @@ -127,6 +150,7 @@ Q_SIGNALS: void hideSourceChanged(); void mipmapChanged(); void recursiveChanged(); + void textureMirroringChanged(); void scheduledUpdateCompleted(); @@ -156,6 +180,7 @@ private: uint m_mipmap : 1; uint m_recursive : 1; uint m_grab : 1; + uint m_textureMirroring : 2; // Stores TextureMirroring enum }; QT_END_NAMESPACE diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 86350738a0..43c5e44be3 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSPRITE_P_H #define QQUICKSPRITE_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 <QObject> #include <QUrl> #include <QVariantMap> diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index ef52bcc9fe..48808e73c9 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSPRITEENGINE_P_H #define QQUICKSPRITEENGINE_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 <QObject> #include <QVector> #include <QTimer> diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h index f5d467580d..54ed2636b2 100644 --- a/src/quick/items/qquickspritesequence_p.h +++ b/src/quick/items/qquickspritesequence_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSPRITESEQUENCE_P_H #define QQUICKSPRITESEQUENCE_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 <QtQuick/QQuickItem> #include <QTime> diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp index 579919db27..ac7fbc24af 100644 --- a/src/quick/items/qquickstateoperations.cpp +++ b/src/quick/items/qquickstateoperations.cpp @@ -358,7 +358,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickStateAction xa; xa.property = property; - xa.toBinding = QQmlAbstractBinding::getPointer(newBinding); + xa.toBinding = newBinding; xa.fromValue = xa.property.read(); xa.deletableToBinding = true; actions << xa; @@ -377,7 +377,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickStateAction ya; ya.property = property; - ya.toBinding = QQmlAbstractBinding::getPointer(newBinding); + ya.toBinding = newBinding; ya.fromValue = ya.property.read(); ya.deletableToBinding = true; actions << ya; @@ -396,7 +396,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickStateAction sa; sa.property = property; - sa.toBinding = QQmlAbstractBinding::getPointer(newBinding); + sa.toBinding = newBinding; sa.fromValue = sa.property.read(); sa.deletableToBinding = true; actions << sa; @@ -415,7 +415,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickStateAction ra; ra.property = property; - ra.toBinding = QQmlAbstractBinding::getPointer(newBinding); + ra.toBinding = newBinding; ra.fromValue = ra.property.read(); ra.deletableToBinding = true; actions << ra; @@ -434,7 +434,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickStateAction wa; wa.property = property; - wa.toBinding = QQmlAbstractBinding::getPointer(newBinding); + wa.toBinding = newBinding; wa.fromValue = wa.property.read(); wa.deletableToBinding = true; actions << wa; @@ -453,7 +453,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickStateAction ha; ha.property = property; - ha.toBinding = QQmlAbstractBinding::getPointer(newBinding); + ha.toBinding = newBinding; ha.fromValue = ha.property.read(); ha.deletableToBinding = true; actions << ha; @@ -482,7 +482,7 @@ void QQuickParentChange::saveOriginals() saveCurrentValues(); }*/ -void QQuickParentChange::execute(Reason) +void QQuickParentChange::execute() { Q_D(QQuickParentChange); d->doChange(d->parent); @@ -493,7 +493,7 @@ bool QQuickParentChange::isReversable() return true; } -void QQuickParentChange::reverse(Reason) +void QQuickParentChange::reverse() { Q_D(QQuickParentChange); d->doChange(d->origParent, d->origStackBefore); @@ -765,12 +765,7 @@ class QQuickAnchorChangesPrivate : public QQuickStateOperationPrivate { public: QQuickAnchorChangesPrivate() - : target(0), anchorSet(new QQuickAnchorSet), - leftBinding(0), rightBinding(0), hCenterBinding(0), - topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0), - origLeftBinding(0), origRightBinding(0), origHCenterBinding(0), - origTopBinding(0), origBottomBinding(0), origVCenterBinding(0), - origBaselineBinding(0) + : target(0), anchorSet(new QQuickAnchorSet) { } @@ -779,21 +774,21 @@ public: QQuickItem *target; QQuickAnchorSet *anchorSet; - QQmlBinding *leftBinding; - QQmlBinding *rightBinding; - QQmlBinding *hCenterBinding; - QQmlBinding *topBinding; - QQmlBinding *bottomBinding; - QQmlBinding *vCenterBinding; - QQmlBinding *baselineBinding; - - QQmlAbstractBinding *origLeftBinding; - QQmlAbstractBinding *origRightBinding; - QQmlAbstractBinding *origHCenterBinding; - QQmlAbstractBinding *origTopBinding; - QQmlAbstractBinding *origBottomBinding; - QQmlAbstractBinding *origVCenterBinding; - QQmlAbstractBinding *origBaselineBinding; + QExplicitlySharedDataPointer<QQmlBinding> leftBinding; + QExplicitlySharedDataPointer<QQmlBinding> rightBinding; + QExplicitlySharedDataPointer<QQmlBinding> hCenterBinding; + QExplicitlySharedDataPointer<QQmlBinding> topBinding; + QExplicitlySharedDataPointer<QQmlBinding> bottomBinding; + QExplicitlySharedDataPointer<QQmlBinding> vCenterBinding; + QExplicitlySharedDataPointer<QQmlBinding> baselineBinding; + + QQmlAbstractBinding::Ptr origLeftBinding; + QQmlAbstractBinding::Ptr origRightBinding; + QQmlAbstractBinding::Ptr origHCenterBinding; + QQmlAbstractBinding::Ptr origTopBinding; + QQmlAbstractBinding::Ptr origBottomBinding; + QQmlAbstractBinding::Ptr origVCenterBinding; + QQmlAbstractBinding::Ptr origBaselineBinding; QQuickAnchorLine rewindLeft; QQuickAnchorLine rewindRight; @@ -831,8 +826,6 @@ public: qreal origX; qreal origY; - QList<QQmlAbstractBinding*> oldBindings; - QQmlProperty leftProp; QQmlProperty rightProp; QQmlProperty hCenterProp; @@ -849,29 +842,6 @@ QQuickAnchorChanges::QQuickAnchorChanges(QObject *parent) QQuickAnchorChanges::~QQuickAnchorChanges() { - /* - if the anchorchanges is active at destruction, any non-active orig - bindings need to be destroyed - - the basic logic is that if both e.g. left and origLeft are present, - then we are active (otherwise left would have been destroyed), and - left is in use and origLeft needs to be cleaned up. - */ - Q_D(QQuickAnchorChanges); - if (d->leftBinding && d->origLeftBinding) - d->origLeftBinding->destroy(); - if (d->rightBinding && d->origRightBinding) - d->origRightBinding->destroy(); - if (d->hCenterBinding && d->origHCenterBinding) - d->origHCenterBinding->destroy(); - if (d->topBinding && d->origTopBinding) - d->origTopBinding->destroy(); - if (d->bottomBinding && d->origBottomBinding) - d->origBottomBinding->destroy(); - if (d->vCenterBinding && d->origVCenterBinding) - d->origVCenterBinding->destroy(); - if (d->baselineBinding && d->origBaselineBinding) - d->origBaselineBinding->destroy(); } QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions() @@ -967,7 +937,7 @@ void QQuickAnchorChanges::setObject(QQuickItem *target) \endqml */ -void QQuickAnchorChanges::execute(Reason reason) +void QQuickAnchorChanges::execute() { Q_D(QQuickAnchorChanges); if (!d->target) @@ -978,94 +948,84 @@ void QQuickAnchorChanges::execute(Reason reason) if (d->applyOrigLeft) { if (!d->origLeftBinding) targetPrivate->anchors()->resetLeft(); - QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding); + QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data()); } if (d->applyOrigRight) { if (!d->origRightBinding) targetPrivate->anchors()->resetRight(); - QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding); + QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data()); } if (d->applyOrigHCenter) { if (!d->origHCenterBinding) targetPrivate->anchors()->resetHorizontalCenter(); - QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding); + QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data()); } if (d->applyOrigTop) { if (!d->origTopBinding) targetPrivate->anchors()->resetTop(); - QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding); + QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data()); } if (d->applyOrigBottom) { if (!d->origBottomBinding) targetPrivate->anchors()->resetBottom(); - QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding); + QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data()); } if (d->applyOrigVCenter) { if (!d->origVCenterBinding) targetPrivate->anchors()->resetVerticalCenter(); - QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding); + QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data()); } if (d->applyOrigBaseline) { if (!d->origBaselineBinding) targetPrivate->anchors()->resetBaseline(); - QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding); - } - - //destroy old bindings - if (reason == ActualChange) { - for (int i = 0; i < d->oldBindings.size(); ++i) { - QQmlAbstractBinding *binding = d->oldBindings.at(i); - if (binding) - binding->destroy(); - } - d->oldBindings.clear(); + QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data()); } //reset any anchors that have been specified as "undefined" if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::LeftAnchor) { targetPrivate->anchors()->resetLeft(); - QQmlPropertyPrivate::setBinding(d->leftProp, 0); + QQmlPropertyPrivate::removeBinding(d->leftProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) { targetPrivate->anchors()->resetRight(); - QQmlPropertyPrivate::setBinding(d->rightProp, 0); + QQmlPropertyPrivate::removeBinding(d->rightProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) { targetPrivate->anchors()->resetHorizontalCenter(); - QQmlPropertyPrivate::setBinding(d->hCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->hCenterProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) { targetPrivate->anchors()->resetTop(); - QQmlPropertyPrivate::setBinding(d->topProp, 0); + QQmlPropertyPrivate::removeBinding(d->topProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) { targetPrivate->anchors()->resetBottom(); - QQmlPropertyPrivate::setBinding(d->bottomProp, 0); + QQmlPropertyPrivate::removeBinding(d->bottomProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) { targetPrivate->anchors()->resetVerticalCenter(); - QQmlPropertyPrivate::setBinding(d->vCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->vCenterProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) { targetPrivate->anchors()->resetBaseline(); - QQmlPropertyPrivate::setBinding(d->baselineProp, 0); + QQmlPropertyPrivate::removeBinding(d->baselineProp); } //set any anchors that have been specified if (d->leftBinding) - QQmlPropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding); + QQmlPropertyPrivate::setBinding(d->leftBinding.data()); if (d->rightBinding) - QQmlPropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding); + QQmlPropertyPrivate::setBinding(d->rightBinding.data()); if (d->hCenterBinding) - QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding); + QQmlPropertyPrivate::setBinding(d->hCenterBinding.data()); if (d->topBinding) - QQmlPropertyPrivate::setBinding(d->topBinding->property(), d->topBinding); + QQmlPropertyPrivate::setBinding(d->topBinding.data()); if (d->bottomBinding) - QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding); + QQmlPropertyPrivate::setBinding(d->bottomBinding.data()); if (d->vCenterBinding) - QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding); + QQmlPropertyPrivate::setBinding(d->vCenterBinding.data()); if (d->baselineBinding) - QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding); + QQmlPropertyPrivate::setBinding(d->baselineBinding.data()); } bool QQuickAnchorChanges::isReversable() @@ -1073,7 +1033,7 @@ bool QQuickAnchorChanges::isReversable() return true; } -void QQuickAnchorChanges::reverse(Reason reason) +void QQuickAnchorChanges::reverse() { Q_D(QQuickAnchorChanges); if (!d->target) @@ -1083,69 +1043,48 @@ void QQuickAnchorChanges::reverse(Reason reason) //reset any anchors set by the state if (d->leftBinding) { targetPrivate->anchors()->resetLeft(); - QQmlPropertyPrivate::setBinding(d->leftBinding->property(), 0); - if (reason == ActualChange) { - d->leftBinding->destroy(); d->leftBinding = 0; - } + QQmlPropertyPrivate::removeBinding(d->leftBinding.data()); } if (d->rightBinding) { targetPrivate->anchors()->resetRight(); - QQmlPropertyPrivate::setBinding(d->rightBinding->property(), 0); - if (reason == ActualChange) { - d->rightBinding->destroy(); d->rightBinding = 0; - } + QQmlPropertyPrivate::removeBinding(d->rightBinding.data()); } if (d->hCenterBinding) { targetPrivate->anchors()->resetHorizontalCenter(); - QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), 0); - if (reason == ActualChange) { - d->hCenterBinding->destroy(); d->hCenterBinding = 0; - } + QQmlPropertyPrivate::removeBinding(d->hCenterBinding.data()); } if (d->topBinding) { targetPrivate->anchors()->resetTop(); - QQmlPropertyPrivate::setBinding(d->topBinding->property(), 0); - if (reason == ActualChange) { - d->topBinding->destroy(); d->topBinding = 0; - } + QQmlPropertyPrivate::removeBinding(d->topBinding.data()); } if (d->bottomBinding) { targetPrivate->anchors()->resetBottom(); - QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), 0); - if (reason == ActualChange) { - d->bottomBinding->destroy(); d->bottomBinding = 0; - } + QQmlPropertyPrivate::removeBinding(d->bottomBinding.data()); } if (d->vCenterBinding) { targetPrivate->anchors()->resetVerticalCenter(); - QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), 0); - if (reason == ActualChange) { - d->vCenterBinding->destroy(); d->vCenterBinding = 0; - } + QQmlPropertyPrivate::removeBinding(d->vCenterBinding.data()); } if (d->baselineBinding) { targetPrivate->anchors()->resetBaseline(); - QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), 0); - if (reason == ActualChange) { - d->baselineBinding->destroy(); d->baselineBinding = 0; - } + QQmlPropertyPrivate::removeBinding(d->baselineBinding.data()); } //restore previous anchors if (d->origLeftBinding) - QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding); + QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data()); if (d->origRightBinding) - QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding); + QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data()); if (d->origHCenterBinding) - QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding); + QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data()); if (d->origTopBinding) - QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding); + QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data()); if (d->origBottomBinding) - QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding); + QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data()); if (d->origVCenterBinding) - QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding); + QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data()); if (d->origBaselineBinding) - QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding); + QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data()); //restore any absolute geometry changed by the state's anchors QQuickAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Vertical_Mask; @@ -1289,10 +1228,6 @@ void QQuickAnchorChanges::copyOriginals(QQuickStateActionEvent *other) d->origX = acp->origX; d->origY = acp->origY; - d->oldBindings.clear(); - d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding - << acp->topBinding << acp->bottomBinding << acp->vCenterBinding << acp->baselineBinding; - //clear old values from other //### could this be generalized for all QQuickStateActionEvents, and called after copyOriginals? acp->leftBinding = 0; @@ -1333,31 +1268,31 @@ void QQuickAnchorChanges::clearBindings() d->anchorSet->d_func()->usedAnchors; if (d->applyOrigLeft || (combined & QQuickAnchors::LeftAnchor)) { targetPrivate->anchors()->resetLeft(); - QQmlPropertyPrivate::setBinding(d->leftProp, 0); + QQmlPropertyPrivate::removeBinding(d->leftProp); } if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) { targetPrivate->anchors()->resetRight(); - QQmlPropertyPrivate::setBinding(d->rightProp, 0); + QQmlPropertyPrivate::removeBinding(d->rightProp); } if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) { targetPrivate->anchors()->resetHorizontalCenter(); - QQmlPropertyPrivate::setBinding(d->hCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->hCenterProp); } if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) { targetPrivate->anchors()->resetTop(); - QQmlPropertyPrivate::setBinding(d->topProp, 0); + QQmlPropertyPrivate::removeBinding(d->topProp); } if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) { targetPrivate->anchors()->resetBottom(); - QQmlPropertyPrivate::setBinding(d->bottomProp, 0); + QQmlPropertyPrivate::removeBinding(d->bottomProp); } if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) { targetPrivate->anchors()->resetVerticalCenter(); - QQmlPropertyPrivate::setBinding(d->vCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->vCenterProp); } if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) { targetPrivate->anchors()->resetBaseline(); - QQmlPropertyPrivate::setBinding(d->baselineProp, 0); + QQmlPropertyPrivate::removeBinding(d->baselineProp); } } diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h index 8d4231c5fa..f1959fa374 100644 --- a/src/quick/items/qquickstateoperations_p.h +++ b/src/quick/items/qquickstateoperations_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKSTATEOPERATIONS_P_H #define QQUICKSTATEOPERATIONS_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.h" #include "qquickanchors_p.h" @@ -97,9 +108,9 @@ public: void saveOriginals() Q_DECL_OVERRIDE; //virtual void copyOriginals(QQuickStateActionEvent*); - void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE; + void execute() Q_DECL_OVERRIDE; bool isReversable() Q_DECL_OVERRIDE; - void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE; + void reverse() Q_DECL_OVERRIDE; EventType type() const Q_DECL_OVERRIDE; bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE; void rewind() Q_DECL_OVERRIDE; @@ -180,9 +191,9 @@ public: QQuickItem *object() const; void setObject(QQuickItem *); - void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE; + void execute() Q_DECL_OVERRIDE; bool isReversable() Q_DECL_OVERRIDE; - void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE; + void reverse() Q_DECL_OVERRIDE; EventType type() const Q_DECL_OVERRIDE; bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE; bool changesBindings() Q_DECL_OVERRIDE; diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index f848d0baee..3b5982c3d0 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -85,7 +85,16 @@ QQuickTextPrivate::QQuickTextPrivate() } QQuickTextPrivate::ExtraData::ExtraData() - : lineHeight(1.0) + : padding(0) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , explicitTopPadding(false) + , explicitLeftPadding(false) + , explicitRightPadding(false) + , explicitBottomPadding(false) + , lineHeight(1.0) , doc(0) , minimumPixelSize(12) , minimumPointSize(12) @@ -280,6 +289,74 @@ qreal QQuickTextPrivate::getImplicitHeight() const return implicitHeight; } +qreal QQuickTextPrivate::availableWidth() const +{ + Q_Q(const QQuickText); + return q->width() - q->leftPadding() - q->rightPadding(); +} + +qreal QQuickTextPrivate::availableHeight() const +{ + Q_Q(const QQuickText); + return q->height() - q->topPadding() - q->bottomPadding(); +} + +void QQuickTextPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->topPadding(); + if (!reset || extra.isAllocated()) { + extra.value().topPadding = value; + extra.value().explicitTopPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateSize(); + emit q->topPaddingChanged(); + } +} + +void QQuickTextPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->leftPadding(); + if (!reset || extra.isAllocated()) { + extra.value().leftPadding = value; + extra.value().explicitLeftPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateSize(); + emit q->leftPaddingChanged(); + } +} + +void QQuickTextPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->rightPadding(); + if (!reset || extra.isAllocated()) { + extra.value().rightPadding = value; + extra.value().explicitRightPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateSize(); + emit q->rightPaddingChanged(); + } +} + +void QQuickTextPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->bottomPadding(); + if (!reset || extra.isAllocated()) { + extra.value().bottomPadding = value; + extra.value().explicitBottomPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateSize(); + emit q->bottomPaddingChanged(); + } +} + /*! \qmlproperty bool QtQuick::Text::antialiasing @@ -323,9 +400,9 @@ void QQuickTextPrivate::updateLayout() formatModifiesFontSize = fontSizeModified; multilengthEos = -1; } else { - layout.clearAdditionalFormats(); + layout.clearFormats(); if (elideLayout) - elideLayout->clearAdditionalFormats(); + elideLayout->clearFormats(); QString tmp = text; multilengthEos = tmp.indexOf(QLatin1Char('\x9c')); if (multilengthEos != -1) { @@ -406,7 +483,7 @@ void QQuickTextPrivate::updateBaseline(qreal baseline, qreal dy) yoff = dy/2; } - q->setBaselineOffset(baseline + yoff); + q->setBaselineOffset(baseline + yoff + q->topPadding()); } void QQuickTextPrivate::updateSize() @@ -426,6 +503,9 @@ void QQuickTextPrivate::updateSize() return; } + qreal hPadding = q->leftPadding() + q->rightPadding(); + qreal vPadding = q->topPadding() + q->bottomPadding(); + if (text.isEmpty() && !isLineLaidOutConnected() && fontSizeMode() == QQuickText::FixedSize) { // How much more expensive is it to just do a full layout on an empty string here? // There may be subtle differences in the height and baseline calculations between @@ -438,8 +518,8 @@ void QQuickTextPrivate::updateSize() ? lineHeight() : fontHeight * lineHeight(); } - updateBaseline(fm.ascent(), q->height() - fontHeight); - q->setImplicitSize(0, fontHeight); + updateBaseline(fm.ascent(), q->height() - fontHeight - vPadding); + q->setImplicitSize(hPadding, fontHeight + vPadding); layedOutTextRect = QRectF(0, 0, 0, fontHeight); emit q->contentSizeChanged(); updateType = UpdatePaintNode; @@ -460,7 +540,7 @@ void QQuickTextPrivate::updateSize() layedOutTextRect = textRect; size = textRect.size(); - updateBaseline(baseline, q->height() - size.height()); + updateBaseline(baseline, q->height() - size.height() - vPadding); } else { widthExceeded = true; // always relayout rich text on width changes.. heightExceeded = false; // rich text layout isn't affected by height changes. @@ -484,15 +564,15 @@ void QQuickTextPrivate::updateSize() naturalWidth = extra->doc->idealWidth(); const bool wasInLayout = internalWidthUpdate; internalWidthUpdate = true; - q->setImplicitWidth(naturalWidth); + q->setImplicitWidth(naturalWidth + hPadding); internalWidthUpdate = wasInLayout; } if (internalWidthUpdate) return; extra->doc->setPageSize(QSizeF()); - if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < q->width())) - extra->doc->setTextWidth(q->width()); + if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < availableWidth())) + extra->doc->setTextWidth(availableWidth()); else extra->doc->setTextWidth(extra->doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug) @@ -501,7 +581,7 @@ void QQuickTextPrivate::updateSize() size = QSizeF(extra->doc->idealWidth(),dsize.height()); QFontMetricsF fm(font); - updateBaseline(fm.ascent(), q->height() - size.height()); + updateBaseline(fm.ascent(), q->height() - size.height() - vPadding); //### need to confirm cost of always setting these for richText internalWidthUpdate = true; @@ -509,11 +589,11 @@ void QQuickTextPrivate::updateSize() if (!q->widthValid()) iWidth = size.width(); if (iWidth > -1) - q->setImplicitSize(iWidth, size.height()); + q->setImplicitSize(iWidth + hPadding, size.height() + vPadding); internalWidthUpdate = false; if (iWidth == -1) - q->setImplicitHeight(size.height()); + q->setImplicitHeight(size.height() + vPadding); } if (layedOutTextRect.size() != previousSize) @@ -619,7 +699,7 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, // use the text item's width by default if it has one and wrap is on or text must be aligned if (q->widthValid() && (q->wrapMode() != QQuickText::NoWrap || q->effectiveHAlign() != QQuickText::AlignLeft)) - textLine->setWidth(q->width()); + textLine->setWidth(availableWidth()); else textLine->setWidth(INT_MAX); if (lineHeight() != 1.0) @@ -631,10 +711,10 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, } void QQuickTextPrivate::elideFormats( - const int start, const int length, int offset, QList<QTextLayout::FormatRange> *elidedFormats) + const int start, const int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats) { const int end = start + length; - QList<QTextLayout::FormatRange> formats = layout.additionalFormats(); + const QVector<QTextLayout::FormatRange> formats = layout.formats(); for (int i = 0; i < formats.count(); ++i) { QTextLayout::FormatRange format = formats.at(i); const int formatLength = qMin(format.start + format.length, end) - qMax(format.start, start); @@ -687,10 +767,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) && (q->heightValid() || maximumLineCountValid); if ((!requireImplicitSize || (implicitWidthValid && implicitHeightValid)) - && ((singlelineElide && q->width() <= 0.) || (multilineElide && q->heightValid() && q->height() <= 0.))) { + && ((singlelineElide && availableWidth() <= 0.) + || (multilineElide && q->heightValid() && availableHeight() <= 0.))) { // we are elided and we have a zero width or height - widthExceeded = q->widthValid() && q->width() <= 0.; - heightExceeded = q->heightValid() && q->height() <= 0.; + widthExceeded = q->widthValid() && availableWidth() <= 0.; + heightExceeded = q->heightValid() && availableHeight() <= 0.; if (!truncated) { truncated = true; @@ -726,7 +807,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) lineWidth = (q->widthValid() || implicitWidthValid) && q->width() > 0 ? q->width() : FLT_MAX; - qreal maxHeight = q->heightValid() ? q->height() : FLT_MAX; + qreal maxHeight = q->heightValid() ? availableHeight() : FLT_MAX; const bool customLayout = isLineLaidOutConnected(); const bool wasTruncated = truncated; @@ -747,8 +828,8 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) int scaledFontSize = largeFont; bool widthChanged = false; - widthExceeded = q->width() <= 0 && (singlelineElide || canWrap || horizontalFit); - heightExceeded = q->height() <= 0 && (multilineElide || verticalFit); + widthExceeded = availableWidth() <= 0 && (singlelineElide || canWrap || horizontalFit); + heightExceeded = availableHeight() <= 0 && (multilineElide || verticalFit); QRectF br; @@ -918,7 +999,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) bool wasInLayout = internalWidthUpdate; internalWidthUpdate = true; - q->setImplicitSize(naturalWidth, naturalHeight); + q->setImplicitSize(naturalWidth + q->leftPadding() + q->rightPadding(), naturalHeight + q->topPadding() + q->bottomPadding()); internalWidthUpdate = wasInLayout; // Update any variables that are dependent on the validity of the width or height. @@ -935,8 +1016,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) const qreal oldWidth = lineWidth; const qreal oldHeight = maxHeight; - lineWidth = q->widthValid() && q->width() > 0 ? q->width() : naturalWidth; - maxHeight = q->heightValid() ? q->height() : FLT_MAX; + const qreal availWidth = availableWidth(); + const qreal availHeight = availableHeight(); + + lineWidth = q->widthValid() && availWidth > 0 ? availWidth : naturalWidth; + maxHeight = q->heightValid() ? availHeight : FLT_MAX; // If the width of the item has changed and it's possible the result of wrapping, // eliding, scaling has changed, or the text is not left aligned do another layout. @@ -989,7 +1073,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) && (q->heightValid() || (maximumLineCountValid && canWrap)); const qreal oldHeight = maxHeight; - maxHeight = q->heightValid() ? q->height() : FLT_MAX; + maxHeight = q->heightValid() ? availableHeight() : FLT_MAX; // If the height of the item has changed and it's possible the result of eliding, // line count truncation or scaling has changed, do another layout. if ((maxHeight < qMin(oldHeight, naturalHeight) || (heightExceeded && maxHeight > oldHeight)) @@ -1069,7 +1153,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) elideLayout->setCacheEnabled(true); } if (styledText) { - QList<QTextLayout::FormatRange> formats; + QVector<QTextLayout::FormatRange> formats; switch (elideMode) { case QQuickText::ElideRight: elideFormats(elideStart, elideText.length() - 1, 0, &formats); @@ -1092,7 +1176,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) default: break; } - elideLayout->setAdditionalFormats(formats); + elideLayout->setFormats(formats); } elideLayout->setFont(layout.font()); @@ -1283,6 +1367,13 @@ QQuickText::QQuickText(QQuickItem *parent) d->init(); } +QQuickText::QQuickText(QQuickTextPrivate &dd, QQuickItem *parent) +: QQuickImplicitSizeItem(dd, parent) +{ + Q_D(QQuickText); + d->init(); +} + QQuickText::~QQuickText() { } @@ -1357,6 +1448,16 @@ QQuickText::~QQuickText() */ /*! + \qmlproperty string QtQuick::Text::font.styleName + \since 5.6 + + Sets the style name of the font. + + The style name is case insensitive. If set, the font will be matched against style name instead + of the font properties \l font.weight, \l font.bold and \l font.italic. +*/ + +/*! \qmlproperty bool QtQuick::Text::font.bold Sets whether the font weight is bold. @@ -2194,18 +2295,19 @@ void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo bool widthMaximum = newGeometry.width() >= oldGeometry.width() && !d->widthExceeded; bool heightMaximum = newGeometry.height() >= oldGeometry.height() && !d->heightExceeded; + bool verticalPositionChanged = heightChanged && d->vAlign != AlignTop; + if ((!widthChanged && !heightChanged) || d->internalWidthUpdate) goto geomChangeDone; - if ((effectiveHAlign() != QQuickText::AlignLeft && widthChanged) - || (vAlign() != QQuickText::AlignTop && heightChanged)) { + if ((effectiveHAlign() != QQuickText::AlignLeft && widthChanged) || verticalPositionChanged) { // If the width has changed and we're not left aligned do an update so the text is // repositioned even if a full layout isn't required. And the same for vertical. d->updateType = QQuickTextPrivate::UpdatePaintNode; update(); } - if (!wrapped && !elide && !scaleFont) + if (!wrapped && !elide && !scaleFont && !verticalPositionChanged) goto geomChangeDone; // left aligned unwrapped text without eliding never needs relayout if (elide // eliding and dimensions were and remain invalid; @@ -2214,7 +2316,7 @@ void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo goto geomChangeDone; } - if (widthMaximum && heightMaximum && !d->isLineLaidOutConnected()) // Size is sufficient and growing. + if (widthMaximum && heightMaximum && !d->isLineLaidOutConnected() && !verticalPositionChanged) // Size is sufficient and growing. goto geomChangeDone; if (!(widthChanged || widthMaximum) && !d->isLineLaidOutConnected()) { // only height has changed @@ -2275,7 +2377,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data d->updateType = QQuickTextPrivate::UpdateNone; - const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), height(), d->vAlign); + const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), d->availableHeight(), d->vAlign) + topPadding(); QQuickTextNode *node = 0; if (!oldNode) @@ -2292,11 +2394,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data const QColor linkColor = QColor::fromRgba(d->linkColor); if (d->richText) { - const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), effectiveHAlign()); + const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), d->availableWidth(), effectiveHAlign()) + leftPadding(); d->ensureDoc(); node->addTextDocument(QPointF(dx, dy), d->extra->doc, color, d->style, styleColor, linkColor); } else if (d->layedOutTextRect.width() > 0) { - const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), effectiveHAlign()); + const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, d->availableWidth(), effectiveHAlign()) + leftPadding(); int unelidedLineCount = d->lineCount; if (d->elideLayout) unelidedLineCount -= 1; @@ -2566,7 +2668,7 @@ QString QQuickTextPrivate::anchorAt(const QTextLayout *layout, const QPointF &mo QTextLine line = layout->lineAt(i); if (line.naturalTextRect().contains(mousePos)) { int charPos = line.xToCursor(mousePos.x(), QTextLine::CursorOnCharacter); - foreach (const QTextLayout::FormatRange &formatRange, layout->additionalFormats()) { + foreach (const QTextLayout::FormatRange &formatRange, layout->formats()) { if (formatRange.format.isAnchor() && charPos >= formatRange.start && charPos < formatRange.start + formatRange.length) { @@ -2583,14 +2685,15 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) const { Q_Q(const QQuickText); QPointF translatedMousePos = mousePos; - translatedMousePos.ry() -= QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), q->height(), vAlign); + translatedMousePos.rx() -= q->leftPadding(); + translatedMousePos.ry() -= q->topPadding() + QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), availableHeight(), vAlign); if (styledText) { QString link = anchorAt(&layout, translatedMousePos); if (link.isEmpty() && elideLayout) link = anchorAt(elideLayout, translatedMousePos); return link; } else if (richText && extra.isAllocated() && extra->doc) { - translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), q->effectiveHAlign()); + translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), availableWidth(), q->effectiveHAlign()); return extra->doc->documentLayout()->anchorAt(translatedMousePos); } return QString(); @@ -2808,4 +2911,125 @@ void QQuickText::invalidateFontCaches() } } +/*! + \since 5.6 + \qmlproperty real QtQuick::Text::padding + \qmlproperty real QtQuick::Text::topPadding + \qmlproperty real QtQuick::Text::leftPadding + \qmlproperty real QtQuick::Text::bottomPadding + \qmlproperty real QtQuick::Text::rightPadding + + These properties hold the padding around the content. This space is reserved + in addition to the contentWidth and contentHeight. +*/ +qreal QQuickText::padding() const +{ + Q_D(const QQuickText); + return d->padding(); +} + +void QQuickText::setPadding(qreal padding) +{ + Q_D(QQuickText); + if (qFuzzyCompare(d->padding(), padding)) + return; + + d->extra.value().padding = padding; + d->updateSize(); + emit paddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitTopPadding) + emit topPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickText::resetPadding() +{ + setPadding(0); +} + +qreal QQuickText::topPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitTopPadding) + return d->extra->topPadding; + return d->padding(); +} + +void QQuickText::setTopPadding(qreal padding) +{ + Q_D(QQuickText); + d->setTopPadding(padding); +} + +void QQuickText::resetTopPadding() +{ + Q_D(QQuickText); + d->setTopPadding(0, true); +} + +qreal QQuickText::leftPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitLeftPadding) + return d->extra->leftPadding; + return d->padding(); +} + +void QQuickText::setLeftPadding(qreal padding) +{ + Q_D(QQuickText); + d->setLeftPadding(padding); +} + +void QQuickText::resetLeftPadding() +{ + Q_D(QQuickText); + d->setLeftPadding(0, true); +} + +qreal QQuickText::rightPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitRightPadding) + return d->extra->rightPadding; + return d->padding(); +} + +void QQuickText::setRightPadding(qreal padding) +{ + Q_D(QQuickText); + d->setRightPadding(padding); +} + +void QQuickText::resetRightPadding() +{ + Q_D(QQuickText); + d->setRightPadding(0, true); +} + +qreal QQuickText::bottomPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitBottomPadding) + return d->extra->bottomPadding; + return d->padding(); +} + +void QQuickText::setBottomPadding(qreal padding) +{ + Q_D(QQuickText); + d->setBottomPadding(padding); +} + +void QQuickText::resetBottomPadding() +{ + Q_D(QQuickText); + d->setBottomPadding(0, true); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index 283e3b510b..5b385aeb0a 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKTEXT_P_H #define QQUICKTEXT_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 "qquickimplicitsizeitem_p.h" #include <private/qtquickglobal_p.h> #include <QtGui/qtextoption.h> @@ -45,15 +56,6 @@ class QQuickTextLine; class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem { Q_OBJECT - Q_ENUMS(HAlignment) - Q_ENUMS(VAlignment) - Q_ENUMS(TextStyle) - Q_ENUMS(TextFormat) - Q_ENUMS(TextElideMode) - Q_ENUMS(WrapMode) - Q_ENUMS(LineHeightMode) - Q_ENUMS(FontSizeMode) - Q_ENUMS(RenderType) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) @@ -84,6 +86,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) + public: QQuickText(QQuickItem *parent=0); ~QQuickText(); @@ -92,21 +100,26 @@ public: AlignRight = Qt::AlignRight, AlignHCenter = Qt::AlignHCenter, AlignJustify = Qt::AlignJustify }; + Q_ENUM(HAlignment) enum VAlignment { AlignTop = Qt::AlignTop, AlignBottom = Qt::AlignBottom, AlignVCenter = Qt::AlignVCenter }; + Q_ENUM(VAlignment) enum TextStyle { Normal, Outline, Raised, Sunken }; + Q_ENUM(TextStyle) enum TextFormat { PlainText = Qt::PlainText, RichText = Qt::RichText, AutoText = Qt::AutoText, StyledText = 4 }; + Q_ENUM(TextFormat) enum TextElideMode { ElideLeft = Qt::ElideLeft, ElideRight = Qt::ElideRight, ElideMiddle = Qt::ElideMiddle, ElideNone = Qt::ElideNone }; + Q_ENUM(TextElideMode) enum WrapMode { NoWrap = QTextOption::NoWrap, WordWrap = QTextOption::WordWrap, @@ -114,15 +127,19 @@ public: WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + Q_ENUM(WrapMode) enum RenderType { QtRendering, NativeRendering }; + Q_ENUM(RenderType) enum LineHeightMode { ProportionalHeight, FixedHeight }; + Q_ENUM(LineHeightMode) enum FontSizeMode { FixedSize = 0x0, HorizontalFit = 0x01, VerticalFit = 0x02, Fit = HorizontalFit | VerticalFit }; + Q_ENUM(FontSizeMode) QString text() const; void setText(const QString &); @@ -204,6 +221,26 @@ public: Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + Q_SIGNALS: void textChanged(const QString &text); void linkActivated(const QString &link); @@ -231,8 +268,15 @@ Q_SIGNALS: void lineLaidOut(QQuickTextLine *line); void baseUrlChanged(); void renderTypeChanged(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); protected: + QQuickText(QQuickTextPrivate &dd, QQuickItem *parent = 0); + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE; diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h index 28435bc8c5..acdf45dfad 100644 --- a/src/quick/items/qquicktext_p_p.h +++ b/src/quick/items/qquicktext_p_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; class QQuickTextDocumentWithImageResources; -class Q_AUTOTEST_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate +class Q_QUICK_PRIVATE_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate { Q_DECLARE_PUBLIC(QQuickText) public: @@ -78,7 +78,7 @@ public: int lineHeightOffset() const; QString elidedText(qreal lineWidth, const QTextLine &line, QTextLine *nextLine = 0) const; - void elideFormats(int start, int length, int offset, QList<QTextLayout::FormatRange> *elidedFormats); + void elideFormats(int start, int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats); void processHoverEvent(QHoverEvent *event); @@ -87,6 +87,15 @@ public: struct ExtraData { ExtraData(); + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding : 1; + bool explicitLeftPadding : 1; + bool explicitRightPadding : 1; + bool explicitBottomPadding : 1; qreal lineHeight; QQuickTextDocumentWithImageResources *doc; QString activeLink; @@ -160,6 +169,15 @@ public: qreal getImplicitWidth() const Q_DECL_OVERRIDE; qreal getImplicitHeight() const Q_DECL_OVERRIDE; + qreal availableWidth() const; + qreal availableHeight() const; + + inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; } + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); + void ensureDoc(); QRectF setupTextLayout(qreal * const baseline); diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 6929bb44a2..04e43c017e 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -106,7 +106,9 @@ QQuickTextControlPrivate::QQuickTextControlPrivate() hadSelectionOnMousePress(false), wordSelectionEnabled(false), hasImState(false), - cursorRectangleChanged(false) + cursorRectangleChanged(false), + lastSelectionStart(-1), + lastSelectionEnd(-1) {} bool QQuickTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) @@ -403,11 +405,19 @@ void QQuickTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged / } bool current = cursor.hasSelection(); - if (current == lastSelectionState) + int selectionStart = cursor.selectionStart(); + int selectionEnd = cursor.selectionEnd(); + if (current == lastSelectionState && (!current || (selectionStart == lastSelectionStart && selectionEnd == lastSelectionEnd))) return; - lastSelectionState = current; - emit q->copyAvailable(current); + if (lastSelectionState != current) { + lastSelectionState = current; + emit q->copyAvailable(current); + } + + lastSelectionStart = selectionStart; + lastSelectionEnd = selectionEnd; + if (!forceEmitSelectionChanged) { #ifndef QT_NO_IM if (hasFocus) @@ -1313,7 +1323,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) QTextLayout *layout = block.layout(); if (isGettingInput) layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); - QList<QTextLayout::FormatRange> overrides; + QVector<QTextLayout::FormatRange> overrides; const int oldPreeditCursor = preeditCursor; preeditCursor = e->preeditString().length(); hasImState = !e->preeditString().isEmpty(); @@ -1336,7 +1346,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } } } - layout->setAdditionalFormats(overrides); + layout->setFormats(overrides); cursor.endEditBlock(); diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h index 4c3e03a552..3c2e579737 100644 --- a/src/quick/items/qquicktextcontrol_p_p.h +++ b/src/quick/items/qquicktextcontrol_p_p.h @@ -156,6 +156,9 @@ public: bool hasImState : 1; bool cursorRectangleChanged : 1; + int lastSelectionStart; + int lastSelectionEnd; + void _q_copyLink(); }; diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index cd1cf5eef1..7cf3b449a0 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -172,6 +172,13 @@ QQuickTextEdit::QQuickTextEdit(QQuickItem *parent) d->init(); } +QQuickTextEdit::QQuickTextEdit(QQuickTextEditPrivate &dd, QQuickItem *parent) +: QQuickImplicitSizeItem(dd, parent) +{ + Q_D(QQuickTextEdit); + d->init(); +} + QString QQuickTextEdit::text() const { Q_D(const QQuickTextEdit); @@ -199,6 +206,17 @@ QString QQuickTextEdit::text() const */ /*! + \qmlproperty string QtQuick::TextEdit::font.styleName + \since 5.6 + + Sets the style name of the font. + + The style name is case insensitive. If set, the font will be matched against style name instead + of the font properties \l font.weight, \l font.bold and \l font.italic. +*/ + + +/*! \qmlproperty bool QtQuick::TextEdit::font.bold Sets whether the font weight is bold. @@ -699,6 +717,75 @@ Qt::InputMethodHints QQuickTextEditPrivate::effectiveInputMethodHints() const } #endif +void QQuickTextEditPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->topPadding(); + if (!reset || extra.isAllocated()) { + extra.value().topPadding = value; + extra.value().explicitTopPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + q->updateSize(); + emit q->topPaddingChanged(); + } +} + +void QQuickTextEditPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->leftPadding(); + if (!reset || extra.isAllocated()) { + extra.value().leftPadding = value; + extra.value().explicitLeftPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + q->updateSize(); + emit q->leftPaddingChanged(); + } +} + +void QQuickTextEditPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->rightPadding(); + if (!reset || extra.isAllocated()) { + extra.value().rightPadding = value; + extra.value().explicitRightPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + q->updateSize(); + emit q->rightPaddingChanged(); + } +} + +void QQuickTextEditPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->bottomPadding(); + if (!reset || extra.isAllocated()) { + extra.value().bottomPadding = value; + extra.value().explicitBottomPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + q->updateSize(); + emit q->bottomPaddingChanged(); + } +} + +bool QQuickTextEditPrivate::isImplicitResizeEnabled() const +{ + return !extra.isAllocated() || extra->implicitResize; +} + +void QQuickTextEditPrivate::setImplicitResizeEnabled(bool enabled) +{ + if (!enabled) + extra.value().implicitResize = false; + else if (extra.isAllocated()) + extra->implicitResize = true; +} + QQuickTextEdit::VAlignment QQuickTextEdit::vAlign() const { Q_D(const QQuickTextEdit); @@ -1658,6 +1745,8 @@ void QQuickTextEdit::mousePressEvent(QMouseEvent *event) #ifndef QT_NO_IM if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) qGuiApp->inputMethod()->show(); +#else + Q_UNUSED(hadActiveFocus); #endif } if (!event->isAccepted()) @@ -1793,6 +1882,14 @@ void QQuickTextEdit::invalidateFontCaches() } } +inline void resetEngine(QQuickTextNodeEngine *engine, const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor) +{ + *engine = QQuickTextNodeEngine(); + engine->setTextColor(textColor); + engine->setSelectedTextColor(selectedTextColor); + engine->setSelectionColor(selectionColor); +} + QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) { Q_UNUSED(updatePaintNodeData); @@ -1818,6 +1915,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * while (nodeIterator != d->textNodeMap.end() && !(*nodeIterator)->dirty()) ++nodeIterator; + QQuickTextNodeEngine engine; + QQuickTextNodeEngine frameDecorationsEngine; if (!oldNode || nodeIterator < d->textNodeMap.end()) { @@ -1837,6 +1936,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * // FIXME: the text decorations could probably be handled separately (only updated for affected textFrames) rootNode->resetFrameDecorations(d->createTextNode()); + resetEngine(&frameDecorationsEngine, d->color, d->selectedTextColor, d->selectionColor); QQuickTextNode *node = 0; @@ -1856,11 +1956,12 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * while (!frames.isEmpty()) { QTextFrame *textFrame = frames.takeFirst(); frames.append(textFrame->childFrames()); - rootNode->frameDecorationsNode->m_engine->addFrameDecorations(d->document, textFrame); + frameDecorationsEngine.addFrameDecorations(d->document, textFrame); if (textFrame->lastPosition() < firstDirtyPos || (firstCleanNode && textFrame->firstPosition() >= firstCleanNode->startPos())) continue; node = d->createTextNode(); + resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor); if (textFrame->firstPosition() > textFrame->lastPosition() && textFrame->frameFormat().position() != QTextFrameFormat::InFlow) { @@ -1869,8 +1970,8 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * ProtectedLayoutAccessor *a = static_cast<ProtectedLayoutAccessor *>(d->document->documentLayout()); QTextCharFormat format = a->formatAccessor(pos); QTextBlock block = textFrame->firstCursorPosition().block(); - node->m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position())); - node->m_engine->addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document, + engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position())); + engine.addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document, pos, textFrame->frameFormat().position()); nodeStart = pos; } else { @@ -1888,13 +1989,13 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * if (block.position() < firstDirtyPos) continue; - if (!node->m_engine->hasContents()) { + if (!engine.hasContents()) { nodeOffset = d->document->documentLayout()->blockBoundingRect(block).topLeft(); updateNodeTransform(node, nodeOffset); nodeStart = block.position(); } - node->m_engine->addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1); + engine.addTextBlock(d->document, block, -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1); currentNodeSize += block.length(); if ((it.atEnd()) || (firstCleanNode && block.next().position() >= firstCleanNode->startPos())) // last node that needed replacing or last block of the frame @@ -1903,15 +2004,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * QList<int>::const_iterator lowerBound = std::lower_bound(frameBoundaries.constBegin(), frameBoundaries.constEnd(), block.next().position()); if (currentNodeSize > nodeBreakingSize || lowerBound == frameBoundaries.constEnd() || *lowerBound > nodeStart) { currentNodeSize = 0; - d->addCurrentTextNodeToRoot(rootNode, node, nodeIterator, nodeStart); + d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart); node = d->createTextNode(); + resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor); nodeStart = block.next().position(); } } } - d->addCurrentTextNodeToRoot(rootNode, node, nodeIterator, nodeStart); + d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart); } - rootNode->frameDecorationsNode->m_engine->addToSceneGraph(rootNode->frameDecorationsNode, QQuickText::Normal, QColor()); + frameDecorationsEngine.addToSceneGraph(rootNode->frameDecorationsNode, QQuickText::Normal, QColor()); // Now prepend the frame decorations since we want them rendered first, with the text nodes and cursor in front. rootNode->prependChildNode(rootNode->frameDecorationsNode); @@ -2016,6 +2118,20 @@ bool QQuickTextEdit::isInputMethodComposing() const #endif // QT_NO_IM } +QQuickTextEditPrivate::ExtraData::ExtraData() + : padding(0) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , explicitTopPadding(false) + , explicitLeftPadding(false) + , explicitRightPadding(false) + , explicitBottomPadding(false) + , implicitResize(true) +{ +} + void QQuickTextEditPrivate::init() { Q_Q(QQuickTextEdit); @@ -2099,7 +2215,7 @@ void QQuickTextEdit::markDirtyNodesForRange(int start, int end, int charDelta) } // mark the affected nodes as dirty - while (it != d->textNodeMap.constEnd()) { + while (it != d->textNodeMap.end()) { if ((*it)->startPos() <= end) (*it)->setDirty(); else if (charDelta) @@ -2225,7 +2341,7 @@ void QQuickTextEdit::updateSize() return; } - qreal naturalWidth = d->implicitWidth; + qreal naturalWidth = d->implicitWidth - leftPadding() - rightPadding(); qreal newWidth = d->document->idealWidth(); // ### assumes that if the width is set, the text will fill to edges @@ -2243,13 +2359,14 @@ void QQuickTextEdit::updateSize() const bool wasInLayout = d->inLayout; d->inLayout = true; - setImplicitWidth(naturalWidth); + if (d->isImplicitResizeEnabled()) + setImplicitWidth(naturalWidth + leftPadding() + rightPadding()); d->inLayout = wasInLayout; if (d->inLayout) // probably the result of a binding loop, but by letting it return; // get this far we'll get a warning to that effect. } if (d->document->textWidth() != width()) { - d->document->setTextWidth(width()); + d->document->setTextWidth(width() - leftPadding() - rightPadding()); newWidth = d->document->idealWidth(); } //### need to confirm cost of always setting these @@ -2262,14 +2379,16 @@ void QQuickTextEdit::updateSize() QFontMetricsF fm(d->font); qreal newHeight = d->document->isEmpty() ? qCeil(fm.height()) : d->document->size().height(); - // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed. - if (!widthValid() && !d->requireImplicitWidth) - setImplicitSize(newWidth, newHeight); - else - setImplicitHeight(newHeight); + if (d->isImplicitResizeEnabled()) { + // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed. + if (!widthValid() && !d->requireImplicitWidth) + setImplicitSize(newWidth + leftPadding() + rightPadding(), newHeight + topPadding() + bottomPadding()); + else + setImplicitHeight(newHeight + topPadding() + bottomPadding()); + } - d->xoff = qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign())); - d->yoff = QQuickTextUtil::alignedY(d->document->size().height(), height(), d->vAlign); + d->xoff = leftPadding() + qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width() - leftPadding() - rightPadding(), effectiveHAlign())); + d->yoff = topPadding() + QQuickTextUtil::alignedY(d->document->size().height(), height() - topPadding() - bottomPadding(), d->vAlign); setBaselineOffset(fm.ascent() + d->yoff + d->textMargin); QSizeF size(newWidth, newHeight); @@ -2416,16 +2535,19 @@ void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event) qGuiApp->inputMethod()->show(); q->connect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)), q, SLOT(q_updateAlignment())); +#endif } else { +#ifndef QT_NO_IM q->disconnect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)), q, SLOT(q_updateAlignment())); #endif + emit q->editingFinished(); } } -void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QSGTransformNode *root, QQuickTextNode *node, TextNodeIterator &it, int startPos) +void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QQuickTextNodeEngine *engine, QSGTransformNode *root, QQuickTextNode *node, TextNodeIterator &it, int startPos) { - node->m_engine->addToSceneGraph(node, QQuickText::Normal, QColor()); + engine->addToSceneGraph(node, QQuickText::Normal, QColor()); it = textNodeMap.insert(it, new TextNode(startPos, node)); ++it; root->appendChildNode(node); @@ -2436,7 +2558,6 @@ QQuickTextNode *QQuickTextEditPrivate::createTextNode() Q_Q(QQuickTextEdit); QQuickTextNode* node = new QQuickTextNode(q); node->setUseNativeRenderer(renderType == QQuickTextEdit::NativeRendering); - node->initEngine(color, selectedTextColor, selectionColor); return node; } @@ -2588,6 +2709,15 @@ bool QQuickTextEditPrivate::isLinkHoveredConnected() */ /*! + \qmlsignal QtQuick::TextEdit::editingFinished() + \since 5.6 + + This signal is emitted when the text edit loses focus. + + The corresponding handler is \c onEditingFinished. +*/ + +/*! \qmlproperty string QtQuick::TextEdit::hoveredLink \since 5.2 @@ -2680,7 +2810,132 @@ void QQuickTextEdit::append(const QString &text) QString QQuickTextEdit::linkAt(qreal x, qreal y) const { Q_D(const QQuickTextEdit); - return d->control->anchorAt(QPointF(x, y)); + return d->control->anchorAt(QPointF(x + topPadding(), y + leftPadding())); +} + +/*! + \since 5.6 + \qmlproperty real QtQuick::TextEdit::padding + \qmlproperty real QtQuick::TextEdit::topPadding + \qmlproperty real QtQuick::TextEdit::leftPadding + \qmlproperty real QtQuick::TextEdit::bottomPadding + \qmlproperty real QtQuick::TextEdit::rightPadding + + These properties hold the padding around the content. This space is reserved + in addition to the contentWidth and contentHeight. +*/ +qreal QQuickTextEdit::padding() const +{ + Q_D(const QQuickTextEdit); + return d->padding(); +} + +void QQuickTextEdit::setPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + if (qFuzzyCompare(d->padding(), padding)) + return; + + d->extra.value().padding = padding; + updateSize(); + if (isComponentComplete()) { + d->updateType = QQuickTextEditPrivate::UpdatePaintNode; + update(); + } + emit paddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitTopPadding) + emit topPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickTextEdit::resetPadding() +{ + setPadding(0); +} + +qreal QQuickTextEdit::topPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->extra.isAllocated() && d->extra->explicitTopPadding) + return d->extra->topPadding; + return d->padding(); +} + +void QQuickTextEdit::setTopPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setTopPadding(padding); +} + +void QQuickTextEdit::resetTopPadding() +{ + Q_D(QQuickTextEdit); + d->setTopPadding(0, true); +} + +qreal QQuickTextEdit::leftPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->extra.isAllocated() && d->extra->explicitLeftPadding) + return d->extra->leftPadding; + return d->padding(); +} + +void QQuickTextEdit::setLeftPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setLeftPadding(padding); +} + +void QQuickTextEdit::resetLeftPadding() +{ + Q_D(QQuickTextEdit); + d->setLeftPadding(0, true); +} + +qreal QQuickTextEdit::rightPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->extra.isAllocated() && d->extra->explicitRightPadding) + return d->extra->rightPadding; + return d->padding(); +} + +void QQuickTextEdit::setRightPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setRightPadding(padding); +} + +void QQuickTextEdit::resetRightPadding() +{ + Q_D(QQuickTextEdit); + d->setRightPadding(0, true); +} + +qreal QQuickTextEdit::bottomPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->extra.isAllocated() && d->extra->explicitBottomPadding) + return d->extra->bottomPadding; + return d->padding(); +} + +void QQuickTextEdit::setBottomPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setBottomPadding(padding); +} + +void QQuickTextEdit::resetBottomPadding() +{ + Q_D(QQuickTextEdit); + d->setBottomPadding(0, true); } QT_END_NAMESPACE diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index bf6763f772..f8b7100cfa 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKTEXTEDIT_P_H #define QQUICKTEXTEDIT_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 "qquickimplicitsizeitem_p.h" #include <QtGui/qtextoption.h> @@ -47,12 +58,6 @@ class QTextBlock; class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem { Q_OBJECT - Q_ENUMS(VAlignment) - Q_ENUMS(HAlignment) - Q_ENUMS(TextFormat) - Q_ENUMS(WrapMode) - Q_ENUMS(SelectionMode) - Q_ENUMS(RenderType) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) @@ -91,8 +96,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged) Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged) Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) - Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument FINAL REVISION 1) + Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument CONSTANT FINAL REVISION 1) Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) public: QQuickTextEdit(QQuickItem *parent=0); @@ -103,18 +113,21 @@ public: AlignHCenter = Qt::AlignHCenter, AlignJustify = Qt::AlignJustify }; + Q_ENUM(HAlignment) enum VAlignment { AlignTop = Qt::AlignTop, AlignBottom = Qt::AlignBottom, AlignVCenter = Qt::AlignVCenter }; + Q_ENUM(VAlignment) enum TextFormat { PlainText = Qt::PlainText, RichText = Qt::RichText, AutoText = Qt::AutoText }; + Q_ENUM(TextFormat) enum WrapMode { NoWrap = QTextOption::NoWrap, WordWrap = QTextOption::WordWrap, @@ -122,15 +135,18 @@ public: WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + Q_ENUM(WrapMode) enum SelectionMode { SelectCharacters, SelectWords }; + Q_ENUM(SelectionMode) enum RenderType { QtRendering, NativeRendering }; + Q_ENUM(RenderType) QString text() const; void setText(const QString &); @@ -247,6 +263,26 @@ public: Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + Q_SIGNALS: void textChanged(); void contentSizeChanged(); @@ -283,6 +319,12 @@ Q_SIGNALS: void baseUrlChanged(); void inputMethodHintsChanged(); void renderTypeChanged(); + Q_REVISION(6) void editingFinished(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); public Q_SLOTS: void selectAll(); @@ -321,6 +363,8 @@ private: void invalidateFontCaches(); protected: + QQuickTextEdit(QQuickTextEditPrivate &dd, QQuickItem *parent = 0); + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index 0cf0f46532..fed0688fd7 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -47,18 +47,19 @@ #include "qquicktextedit_p.h" #include "qquickimplicitsizeitem_p_p.h" -#include "qquicktextcontrol_p.h" #include <QtQml/qqml.h> #include <QtCore/qlist.h> +#include <private/qlazilyallocated_p.h> QT_BEGIN_NAMESPACE class QTextLayout; class QQuickTextDocumentWithImageResources; class QQuickTextControl; class QQuickTextNode; +class QQuickTextNodeEngine; -class QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate +class Q_QUICK_PRIVATE_EXPORT QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate { public: Q_DECLARE_PUBLIC(QQuickTextEdit) @@ -81,10 +82,27 @@ public: }; typedef QList<Node*>::iterator TextNodeIterator; + struct ExtraData { + ExtraData(); + + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding : 1; + bool explicitLeftPadding : 1; + bool explicitRightPadding : 1; + bool explicitBottomPadding : 1; + bool implicitResize : 1; + }; + QLazilyAllocated<ExtraData> extra; + QQuickTextEditPrivate() : color(QRgb(0xFF000000)), selectionColor(QRgb(0xFF000080)), selectedTextColor(QRgb(0xFFFFFFFF)) - , textMargin(0.0), xoff(0), yoff(0), font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0) + , textMargin(0.0), xoff(0), yoff(0) + , font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0) , quickDocument(0), lastSelectionStart(0), lastSelectionEnd(0), lineCount(0) , hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop) , format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap) @@ -124,13 +142,22 @@ public: void setNativeCursorEnabled(bool) {} void handleFocusEvent(QFocusEvent *event); - void addCurrentTextNodeToRoot(QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos); + void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos); QQuickTextNode* createTextNode(); #ifndef QT_NO_IM Qt::InputMethodHints effectiveInputMethodHints() const; #endif + inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; } + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); + + bool isImplicitResizeEnabled() const; + void setImplicitResizeEnabled(bool enabled); + QColor color; QColor selectionColor; QColor selectedTextColor; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 5c67d914a5..ab8e75bfef 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -90,6 +90,13 @@ QQuickTextInput::QQuickTextInput(QQuickItem* parent) d->init(); } +QQuickTextInput::QQuickTextInput(QQuickTextInputPrivate &dd, QQuickItem *parent) +: QQuickImplicitSizeItem(dd, parent) +{ + Q_D(QQuickTextInput); + d->init(); +} + QQuickTextInput::~QQuickTextInput() { } @@ -222,6 +229,16 @@ QString QQuickTextInputPrivate::realText() const */ /*! + \qmlproperty string QtQuick::TextInput::font.styleName + \since 5.6 + + Sets the style name of the font. + + The style name is case insensitive. If set, the font will be matched against style name instead + of the font properties \l font.weight, \l font.bold and \l font.italic. +*/ + +/*! \qmlproperty bool QtQuick::TextInput::font.bold Sets whether the font weight is bold. @@ -786,8 +803,8 @@ QRectF QQuickTextInput::cursorRectangle() const QTextLine l = d->m_textLayout.lineForTextPosition(c); if (!l.isValid()) return QRectF(); - qreal x = l.cursorToX(c) - d->hscroll; - qreal y = l.y() - d->vscroll; + qreal x = l.cursorToX(c) - d->hscroll + leftPadding(); + qreal y = l.y() - d->vscroll + topPadding(); return QRectF(x, y, 1, l.height()); } @@ -910,189 +927,6 @@ void QQuickTextInput::setAutoScroll(bool b) emit autoScrollChanged(d->autoScroll); } -#ifndef QT_NO_VALIDATOR - -/*! - \qmltype IntValidator - \instantiates QIntValidator - \inqmlmodule QtQuick - \ingroup qtquick-text-utility - \brief Defines a validator for integer values - - The IntValidator type provides a validator for integer values. - - If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to - interpret the number and will accept locale specific digits, group separators, and positive - and negative signs. In addition, IntValidator is always guaranteed to accept a number - formatted according to the "C" locale. -*/ - - -QQuickIntValidator::QQuickIntValidator(QObject *parent) - : QIntValidator(parent) -{ -} - -/*! - \qmlproperty string QtQuick::IntValidator::locale - - This property holds the name of the locale used to interpret the number. - - \sa {QtQml::Qt::locale()}{Qt.locale()} -*/ - -QString QQuickIntValidator::localeName() const -{ - return locale().name(); -} - -void QQuickIntValidator::setLocaleName(const QString &name) -{ - if (locale().name() != name) { - setLocale(QLocale(name)); - emit localeNameChanged(); - } -} - -void QQuickIntValidator::resetLocaleName() -{ - QLocale defaultLocale; - if (locale() != defaultLocale) { - setLocale(defaultLocale); - emit localeNameChanged(); - } -} - -/*! - \qmlproperty int QtQuick::IntValidator::top - - This property holds the validator's highest acceptable value. - By default, this property's value is derived from the highest signed integer available (typically 2147483647). -*/ -/*! - \qmlproperty int QtQuick::IntValidator::bottom - - This property holds the validator's lowest acceptable value. - By default, this property's value is derived from the lowest signed integer available (typically -2147483647). -*/ - -/*! - \qmltype DoubleValidator - \instantiates QDoubleValidator - \inqmlmodule QtQuick - \ingroup qtquick-text-utility - \brief Defines a validator for non-integer numbers - - The DoubleValidator type provides a validator for non-integer numbers. - - Input is accepted if it contains a double that is within the valid range - and is in the correct format. - - Input is accepected but invalid if it contains a double that is outside - the range or is in the wrong format; e.g. with too many digits after the - decimal point or is empty. - - Input is rejected if it is not a double. - - Note: If the valid range consists of just positive doubles (e.g. 0.0 to - 100.0) and input is a negative double then it is rejected. If \l notation - is set to DoubleValidator.StandardNotation, and the input contains more - digits before the decimal point than a double in the valid range may have, - it is also rejected. If \l notation is DoubleValidator.ScientificNotation, - and the input is not in the valid range, it is accecpted but invalid. The - value may yet become valid by changing the exponent. -*/ - -QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent) - : QDoubleValidator(parent) -{ -} - -/*! - \qmlproperty string QtQuick::DoubleValidator::locale - - This property holds the name of the locale used to interpret the number. - - \sa {QtQml::Qt::locale()}{Qt.locale()} -*/ - -QString QQuickDoubleValidator::localeName() const -{ - return locale().name(); -} - -void QQuickDoubleValidator::setLocaleName(const QString &name) -{ - if (locale().name() != name) { - setLocale(QLocale(name)); - emit localeNameChanged(); - } -} - -void QQuickDoubleValidator::resetLocaleName() -{ - QLocale defaultLocale; - if (locale() != defaultLocale) { - setLocale(defaultLocale); - emit localeNameChanged(); - } -} - -#endif // QT_NO_VALIDATOR - -/*! - \qmlproperty real QtQuick::DoubleValidator::top - - This property holds the validator's maximum acceptable value. - By default, this property contains a value of infinity. -*/ -/*! - \qmlproperty real QtQuick::DoubleValidator::bottom - - This property holds the validator's minimum acceptable value. - By default, this property contains a value of -infinity. -*/ -/*! - \qmlproperty int QtQuick::DoubleValidator::decimals - - This property holds the validator's maximum number of digits after the decimal point. - By default, this property contains a value of 1000. -*/ -/*! - \qmlproperty enumeration QtQuick::DoubleValidator::notation - This property holds the notation of how a string can describe a number. - - The possible values for this property are: - - \list - \li DoubleValidator.StandardNotation - \li DoubleValidator.ScientificNotation (default) - \endlist - - If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2). -*/ - -/*! - \qmltype RegExpValidator - \instantiates QRegExpValidator - \inqmlmodule QtQuick - \ingroup qtquick-text-utility - \brief Provides a string validator - - The RegExpValidator type provides a validator, which counts as valid any string which - matches a specified regular expression. -*/ -/*! - \qmlproperty regExp QtQuick::RegExpValidator::regExp - - This property holds the regular expression used for validation. - - Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression - matching "a". - - By default, this property contains a regular expression with the pattern .* that matches any string. -*/ - /*! \qmlproperty Validator QtQuick::TextInput::validator @@ -1489,8 +1323,9 @@ void QQuickTextInput::positionAt(QQmlV4Function *args) const int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPosition position) const { - x += hscroll; - y += vscroll; + Q_Q(const QQuickTextInput); + x += hscroll - q->leftPadding(); + y += vscroll - q->topPadding(); QTextLine line = m_textLayout.lineAt(0); for (int i = 1; i < m_textLayout.lineCount(); ++i) { QTextLine nextLine = m_textLayout.lineAt(i); @@ -1748,7 +1583,7 @@ void QQuickTextInputPrivate::ensureVisible(int position, int preeditCursor, int { Q_Q(QQuickTextInput); QTextLine textLine = m_textLayout.lineForTextPosition(position + preeditCursor); - const qreal width = qMax<qreal>(0, q->width()); + const qreal width = qMax<qreal>(0, q->width() - q->leftPadding() - q->rightPadding()); qreal cix = 0; qreal widthUsed = 0; if (textLine.isValid()) { @@ -1811,7 +1646,7 @@ void QQuickTextInputPrivate::updateVerticalScroll() #ifndef QT_NO_IM const int preeditLength = m_textLayout.preeditAreaText().length(); #endif - const qreal height = qMax<qreal>(0, q->height()); + const qreal height = qMax<qreal>(0, q->height() - q->topPadding() - q->bottomPadding()); qreal heightUsed = contentSize.height(); qreal previousScroll = vscroll; @@ -1879,14 +1714,15 @@ void QQuickTextInput::invalidateFontCaches() void QQuickTextInput::ensureActiveFocus() { - Q_D(QQuickTextInput); - bool hadActiveFocus = hasActiveFocus(); forceActiveFocus(); #ifndef QT_NO_IM + Q_D(QQuickTextInput); // re-open input panel on press if already focused if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly) qGuiApp->inputMethod()->show(); +#else + Q_UNUSED(hadActiveFocus); #endif } @@ -1920,13 +1756,13 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData node->deleteContent(); node->setMatrix(QMatrix4x4()); - QPointF offset(0, 0); + QPointF offset(leftPadding(), topPadding()); if (d->autoScroll && d->m_textLayout.lineCount() > 0) { QFontMetricsF fm(d->font); // the y offset is there to keep the baseline constant in case we have script changes in the text. - offset = -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent()); + offset += -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent()); } else { - offset = -QPointF(d->hscroll, d->vscroll); + offset += -QPointF(d->hscroll, d->vscroll); } if (!d->m_textLayout.text().isEmpty() @@ -2672,6 +2508,20 @@ bool QQuickTextInput::isInputMethodComposing() const #endif } +QQuickTextInputPrivate::ExtraData::ExtraData() + : padding(0) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , explicitTopPadding(false) + , explicitLeftPadding(false) + , explicitRightPadding(false) + , explicitBottomPadding(false) + , implicitResize(true) +{ +} + void QQuickTextInputPrivate::init() { Q_Q(QQuickTextInput); @@ -2882,7 +2732,7 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const QTextLine line = layout.createLine(); line.setLineWidth(INT_MAX); - d->implicitWidth = qCeil(line.naturalTextWidth()); + d->implicitWidth = qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding(); layout.endLayout(); } @@ -2890,6 +2740,75 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const return implicitWidth; } +void QQuickTextInputPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->topPadding(); + if (!reset || extra.isAllocated()) { + extra.value().topPadding = value; + extra.value().explicitTopPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateLayout(); + emit q->topPaddingChanged(); + } +} + +void QQuickTextInputPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->leftPadding(); + if (!reset || extra.isAllocated()) { + extra.value().leftPadding = value; + extra.value().explicitLeftPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateLayout(); + emit q->leftPaddingChanged(); + } +} + +void QQuickTextInputPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->rightPadding(); + if (!reset || extra.isAllocated()) { + extra.value().rightPadding = value; + extra.value().explicitRightPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateLayout(); + emit q->rightPaddingChanged(); + } +} + +void QQuickTextInputPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->bottomPadding(); + if (!reset || extra.isAllocated()) { + extra.value().bottomPadding = value; + extra.value().explicitBottomPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { + updateLayout(); + emit q->bottomPaddingChanged(); + } +} + +bool QQuickTextInputPrivate::isImplicitResizeEnabled() const +{ + return !extra.isAllocated() || extra->implicitResize; +} + +void QQuickTextInputPrivate::setImplicitResizeEnabled(bool enabled) +{ + if (!enabled) + extra.value().implicitResize = false; + else if (extra.isAllocated()) + extra->implicitResize = true; +} + void QQuickTextInputPrivate::updateLayout() { Q_Q(QQuickTextInput); @@ -2915,12 +2834,13 @@ void QQuickTextInputPrivate::updateLayout() line.setLineWidth(INT_MAX); const bool wasInLayout = inLayout; inLayout = true; - q->setImplicitWidth(qCeil(line.naturalTextWidth())); + if (isImplicitResizeEnabled()) + q->setImplicitWidth(qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding()); inLayout = wasInLayout; if (inLayout) // probably the result of a binding loop, but by letting it return; // get this far we'll get a warning to that effect. } - qreal lineWidth = q->widthValid() ? q->width() : INT_MAX; + qreal lineWidth = q->widthValid() ? q->width() - q->leftPadding() - q->rightPadding() : INT_MAX; qreal height = 0; qreal width = 0; do { @@ -2946,10 +2866,12 @@ void QQuickTextInputPrivate::updateLayout() q->polish(); q->update(); - if (!requireImplicitWidth && !q->widthValid()) - q->setImplicitSize(width, height); - else - q->setImplicitHeight(height); + if (isImplicitResizeEnabled()) { + if (!requireImplicitWidth && !q->widthValid()) + q->setImplicitSize(width + q->leftPadding() + q->rightPadding(), height + q->topPadding() + q->bottomPadding()); + else + q->setImplicitHeight(height + q->topPadding() + q->bottomPadding()); + } updateBaselineOffset(); @@ -2971,13 +2893,13 @@ void QQuickTextInputPrivate::updateBaselineOffset() QFontMetricsF fm(font); qreal yoff = 0; if (q->heightValid()) { - const qreal surplusHeight = q->height() - contentSize.height(); + const qreal surplusHeight = q->height() - contentSize.height() - q->topPadding() - q->bottomPadding(); if (vAlign == QQuickTextInput::AlignBottom) yoff = surplusHeight; else if (vAlign == QQuickTextInput::AlignVCenter) yoff = surplusHeight/2; } - q->setBaselineOffset(fm.ascent() + yoff); + q->setBaselineOffset(fm.ascent() + yoff + q->topPadding()); } #ifndef QT_NO_CLIPBOARD @@ -3345,7 +3267,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event) m_preeditCursor = event->preeditString().length(); hasImState = !event->preeditString().isEmpty(); bool cursorVisible = true; - QList<QTextLayout::FormatRange> formats; + QVector<QTextLayout::FormatRange> formats; for (int i = 0; i < event->attributes().size(); ++i) { const QInputMethodEvent::Attribute &a = event->attributes().at(i); if (a.type == QInputMethodEvent::Cursor) { @@ -3364,7 +3286,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event) } } } - m_textLayout.setAdditionalFormats(formats); + m_textLayout.setFormats(formats); updateDisplayText(/*force*/ true); if ((cursorPositionChanged && !emitCursorPositionChanged()) @@ -4273,6 +4195,21 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) return; } + if (m_blinkPeriod > 0) { + if (m_blinkTimer) + q->killTimer(m_blinkTimer); + + m_blinkTimer = q->startTimer(m_blinkPeriod / 2); + + if (m_blinkStatus == 0) { + m_blinkStatus = 1; + + updateType = UpdatePaintNode; + q->polish(); + q->update(); + } + } + if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing && !m_readOnly @@ -4508,5 +4445,126 @@ void QQuickTextInput::ensureVisible(int position) updateCursorRectangle(false); } +/*! + \since 5.6 + \qmlproperty real QtQuick::TextInput::padding + \qmlproperty real QtQuick::TextInput::topPadding + \qmlproperty real QtQuick::TextInput::leftPadding + \qmlproperty real QtQuick::TextInput::bottomPadding + \qmlproperty real QtQuick::TextInput::rightPadding + + These properties hold the padding around the content. This space is reserved + in addition to the contentWidth and contentHeight. +*/ +qreal QQuickTextInput::padding() const +{ + Q_D(const QQuickTextInput); + return d->padding(); +} + +void QQuickTextInput::setPadding(qreal padding) +{ + Q_D(QQuickTextInput); + if (qFuzzyCompare(d->padding(), padding)) + return; + + d->extra.value().padding = padding; + d->updateLayout(); + emit paddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitTopPadding) + emit topPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickTextInput::resetPadding() +{ + setPadding(0); +} + +qreal QQuickTextInput::topPadding() const +{ + Q_D(const QQuickTextInput); + if (d->extra.isAllocated() && d->extra->explicitTopPadding) + return d->extra->topPadding; + return d->padding(); +} + +void QQuickTextInput::setTopPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setTopPadding(padding); +} + +void QQuickTextInput::resetTopPadding() +{ + Q_D(QQuickTextInput); + d->setTopPadding(0, true); +} + +qreal QQuickTextInput::leftPadding() const +{ + Q_D(const QQuickTextInput); + if (d->extra.isAllocated() && d->extra->explicitLeftPadding) + return d->extra->leftPadding; + return d->padding(); +} + +void QQuickTextInput::setLeftPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setLeftPadding(padding); +} + +void QQuickTextInput::resetLeftPadding() +{ + Q_D(QQuickTextInput); + d->setLeftPadding(0, true); +} + +qreal QQuickTextInput::rightPadding() const +{ + Q_D(const QQuickTextInput); + if (d->extra.isAllocated() && d->extra->explicitRightPadding) + return d->extra->rightPadding; + return d->padding(); +} + +void QQuickTextInput::setRightPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setRightPadding(padding); +} + +void QQuickTextInput::resetRightPadding() +{ + Q_D(QQuickTextInput); + d->setRightPadding(0, true); +} + +qreal QQuickTextInput::bottomPadding() const +{ + Q_D(const QQuickTextInput); + if (d->extra.isAllocated() && d->extra->explicitBottomPadding) + return d->extra->bottomPadding; + return d->padding(); +} + +void QQuickTextInput::setBottomPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setBottomPadding(padding); +} + +void QQuickTextInput::resetBottomPadding() +{ + Q_D(QQuickTextInput); + d->setBottomPadding(0, true); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 3bcbe0fa25..8733b31960 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKTEXTINPUT_P_H #define QQUICKTEXTINPUT_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 "qquickimplicitsizeitem_p.h" #include <QtGui/qtextoption.h> #include <QtGui/qvalidator.h> @@ -45,13 +56,6 @@ class QValidator; class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem { Q_OBJECT - Q_ENUMS(HAlignment) - Q_ENUMS(VAlignment) - Q_ENUMS(WrapMode) - Q_ENUMS(EchoMode) - Q_ENUMS(SelectionMode) - Q_ENUMS(CursorPosition) - Q_ENUMS(RenderType) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(int length READ length NOTIFY textChanged) @@ -96,6 +100,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentSizeChanged) Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) + public: QQuickTextInput(QQuickItem * parent=0); ~QQuickTextInput(); @@ -108,18 +118,21 @@ public: Password, PasswordEchoOnEdit }; + Q_ENUM(EchoMode) enum HAlignment { AlignLeft = Qt::AlignLeft, AlignRight = Qt::AlignRight, AlignHCenter = Qt::AlignHCenter }; + Q_ENUM(HAlignment) enum VAlignment { AlignTop = Qt::AlignTop, AlignBottom = Qt::AlignBottom, AlignVCenter = Qt::AlignVCenter }; + Q_ENUM(VAlignment) enum WrapMode { NoWrap = QTextOption::NoWrap, @@ -128,20 +141,24 @@ public: WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + Q_ENUM(WrapMode) enum SelectionMode { SelectCharacters, SelectWords }; + Q_ENUM(SelectionMode) enum CursorPosition { CursorBetweenCharacters, CursorOnCharacter }; + Q_ENUM(CursorPosition) enum RenderType { QtRendering, NativeRendering }; + Q_ENUM(RenderType) //Auxilliary functions needed to control the TextInput from QML Q_INVOKABLE void positionAt(QQmlV4Function *args) const; @@ -260,6 +277,26 @@ public: qreal contentWidth() const; qreal contentHeight() const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + Q_SIGNALS: void textChanged(); void cursorPositionChanged(); @@ -300,12 +337,19 @@ Q_SIGNALS: void contentSizeChanged(); void inputMethodHintsChanged(); void renderTypeChanged(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); private: void invalidateFontCaches(); void ensureActiveFocus(); protected: + QQuickTextInput(QQuickTextInputPrivate &dd, QQuickItem *parent = 0); + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; @@ -360,46 +404,8 @@ private: Q_DECLARE_PRIVATE(QQuickTextInput) }; -#ifndef QT_NO_VALIDATOR -class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator -{ - Q_OBJECT - Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) -public: - QQuickIntValidator(QObject *parent = 0); - - QString localeName() const; - void setLocaleName(const QString &name); - void resetLocaleName(); - -Q_SIGNALS: - void localeNameChanged(); -}; - -class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator -{ - Q_OBJECT - Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) -public: - QQuickDoubleValidator(QObject *parent = 0); - - QString localeName() const; - void setLocaleName(const QString &name); - void resetLocaleName(); - -Q_SIGNALS: - void localeNameChanged(); -}; -#endif - QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickTextInput) -#ifndef QT_NO_VALIDATOR -QML_DECLARE_TYPE(QValidator) -QML_DECLARE_TYPE(QQuickIntValidator) -QML_DECLARE_TYPE(QQuickDoubleValidator) -QML_DECLARE_TYPE(QRegExpValidator) -#endif #endif // QQUICKTEXTINPUT_P_H diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 3038573bb3..00d9b2b0fa 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -47,6 +47,7 @@ #include <QtGui/qpalette.h> #include <QtGui/qtextlayout.h> #include <QtGui/qstylehints.h> +#include <private/qlazilyallocated_p.h> #include "qplatformdefs.h" @@ -64,13 +65,29 @@ QT_BEGIN_NAMESPACE class QQuickTextNode; -class Q_AUTOTEST_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate +class Q_QUICK_PRIVATE_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate { public: Q_DECLARE_PUBLIC(QQuickTextInput) typedef QQuickTextInput Public; + struct ExtraData { + ExtraData(); + + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding : 1; + bool explicitLeftPadding : 1; + bool explicitRightPadding : 1; + bool explicitBottomPadding : 1; + bool implicitResize : 1; + }; + QLazilyAllocated<ExtraData> extra; + QQuickTextInputPrivate() : hscroll(0) , vscroll(0) @@ -420,6 +437,15 @@ public: qreal getImplicitWidth() const Q_DECL_OVERRIDE; + inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; } + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); + + bool isImplicitResizeEnabled() const; + void setImplicitResizeEnabled(bool enabled); + private: void removeSelectedText(); void internalSetText(const QString &txt, int pos = -1, bool edited = true); diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp index 010a443d18..d40dedd798 100644 --- a/src/quick/items/qquicktextnode.cpp +++ b/src/quick/items/qquicktextnode.cpp @@ -186,17 +186,6 @@ void QQuickTextNode::clearCursor() m_cursorNode = 0; } -void QQuickTextNode::initEngine(const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor, const QColor& anchorColor, const QPointF &position) -{ - m_engine.reset(new QQuickTextNodeEngine); - m_engine->m_hasContents = false; - m_engine->setTextColor(textColor); - m_engine->setSelectedTextColor(selectedTextColor); - m_engine->setSelectionColor(selectionColor); - m_engine->setAnchorColor(anchorColor); - m_engine->setPosition(position); -} - void QQuickTextNode::addRectangleNode(const QRectF &rect, const QColor &color) { QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); @@ -224,7 +213,12 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex const QColor &selectionColor, const QColor &selectedTextColor, int selectionStart, int selectionEnd) { - initEngine(textColor, selectedTextColor, selectionColor, anchorColor); + QQuickTextNodeEngine engine; + engine.setTextColor(textColor); + engine.setSelectedTextColor(selectedTextColor); + engine.setSelectionColor(selectionColor); + engine.setAnchorColor(anchorColor); + engine.setPosition(position); QList<QTextFrame *> frames; frames.append(textDocument->rootFrame()); @@ -232,7 +226,7 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex QTextFrame *textFrame = frames.takeFirst(); frames.append(textFrame->childFrames()); - m_engine->addFrameDecorations(textDocument, textFrame); + engine.addFrameDecorations(textDocument, textFrame); if (textFrame->firstPosition() > textFrame->lastPosition() && textFrame->frameFormat().position() != QTextFrameFormat::InFlow) { @@ -242,23 +236,23 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex QRectF rect = a->frameBoundingRect(textFrame); QTextBlock block = textFrame->firstCursorPosition().block(); - m_engine->setCurrentLine(block.layout()->lineForTextPosition(pos - block.position())); - m_engine->addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument, + engine.setCurrentLine(block.layout()->lineForTextPosition(pos - block.position())); + engine.addTextObject(rect.topLeft(), format, QQuickTextNodeEngine::Unselected, textDocument, pos, textFrame->frameFormat().position()); } else { QTextFrame::iterator it = textFrame->begin(); while (!it.atEnd()) { - Q_ASSERT(!m_engine->currentLine().isValid()); + Q_ASSERT(!engine.currentLine().isValid()); QTextBlock block = it.currentBlock(); - m_engine->addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd); + engine.addTextBlock(textDocument, block, position, textColor, anchorColor, selectionStart, selectionEnd); ++it; } } } - m_engine->addToSceneGraph(this, style, styleColor); + engine.addToSceneGraph(this, style, styleColor); } void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color, @@ -268,7 +262,12 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay int selectionStart, int selectionEnd, int lineStart, int lineCount) { - initEngine(color, selectedTextColor, selectionColor, anchorColor, position); + QQuickTextNodeEngine engine; + engine.setTextColor(color); + engine.setSelectedTextColor(selectedTextColor); + engine.setSelectionColor(selectionColor); + engine.setAnchorColor(anchorColor); + engine.setPosition(position); #ifndef QT_NO_IM int preeditLength = textLayout->preeditAreaText().length(); @@ -276,7 +275,7 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay #endif QVarLengthArray<QTextLayout::FormatRange> colorChanges; - m_engine->mergeFormats(textLayout, &colorChanges); + engine.mergeFormats(textLayout, &colorChanges); lineCount = lineCount >= 0 ? qMin(lineStart + lineCount, textLayout->lineCount()) @@ -297,11 +296,11 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay } #endif - m_engine->setCurrentLine(line); - m_engine->addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd); + engine.setCurrentLine(line); + engine.addGlyphsForRanges(colorChanges, start, end, selectionStart, selectionEnd); } - m_engine->addToSceneGraph(this, style, styleColor); + engine.addToSceneGraph(this, style, styleColor); } void QQuickTextNode::deleteContent() diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h index c7b9804ea6..c6a1059e8a 100644 --- a/src/quick/items/qquicktextnode_p.h +++ b/src/quick/items/qquicktextnode_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKTEXTNODE_P_H #define QQUICKTEXTNODE_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 <QtQuick/qsgnode.h> #include "qquicktext_p.h" #include <qglyphrun.h> @@ -101,14 +112,10 @@ public: void setUseNativeRenderer(bool on) { m_useNativeRenderer = on; } private: - void initEngine(const QColor &textColor, const QColor &selectedTextColor, const QColor &selectionColor, const QColor& anchorColor = QColor() - , const QPointF &position = QPointF()); - QSGRectangleNode *m_cursorNode; QList<QSGTexture *> m_textures; QQuickItem *m_ownerElement; bool m_useNativeRenderer; - QScopedPointer<QQuickTextNodeEngine> m_engine; friend class QQuickTextEdit; friend class QQuickTextEditPrivate; diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index efe79b382e..2b7f94d8bf 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -882,7 +882,7 @@ void QQuickTextNodeEngine::mergeFormats(QTextLayout *textLayout, QVarLengthArray if (textLayout == 0) return; - QList<QTextLayout::FormatRange> additionalFormats = textLayout->additionalFormats(); + QVector<QTextLayout::FormatRange> additionalFormats = textLayout->formats(); for (int i=0; i<additionalFormats.size(); ++i) { QTextLayout::FormatRange additionalFormat = additionalFormats.at(i); if (additionalFormat.format.hasProperty(QTextFormat::ForegroundBrush) diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h index 2f6cacf601..2eae950f06 100644 --- a/src/quick/items/qquicktextnodeengine_p.h +++ b/src/quick/items/qquicktextnodeengine_p.h @@ -44,6 +44,17 @@ #ifndef QQUICKTEXTNODEENGINE_P_H #define QQUICKTEXTNODEENGINE_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. +// + QT_BEGIN_NAMESPACE // Engine that takes glyph runs as input, and produces a set of glyph nodes, clip nodes, @@ -231,8 +242,6 @@ private: QList<TextDecoration> m_lines; QVector<BinaryTreeNode> m_processedNodes; - QList<QPair<QRectF, QImage> > m_images; - bool m_hasSelection : 1; bool m_hasContents : 1; friend class QQuickTextNode; diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h index 6dfb5a08b7..09868b5939 100644 --- a/src/quick/items/qquicktranslate_p.h +++ b/src/quick/items/qquicktranslate_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKTRANSLATE_P_H #define QQUICKTRANSLATE_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.h" #include <QtGui/qmatrix4x4.h> diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index 5b5413a4ba..867f7d9d15 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -38,8 +38,9 @@ #include "qquickitem_p.h" #include "qquickitemchangelistener_p.h" +#include <private/qqmldebugconnector_p.h> #include <private/qquickprofiler_p.h> -#include <private/qqmlinspectorservice_p.h> +#include <private/qqmldebugserviceinterfaces_p.h> #include <private/qqmlmemoryprofiler_p.h> #include <QtQml/qqmlengine.h> @@ -53,7 +54,7 @@ DEFINE_OBJECT_VTABLE(QV4::QQuickRootItemMarker); QV4::Heap::QQuickRootItemMarker *QV4::QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window) { QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine); - return e->memoryManager->alloc<QQuickRootItemMarker>(e, window); + return e->memoryManager->allocObject<QQuickRootItemMarker>(window); } void QV4::QQuickRootItemMarker::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e) @@ -86,8 +87,9 @@ void QQuickViewPrivate::init(QQmlEngine* e) rootItemMarker.set(v4, v); } - if (QQmlDebugService::isDebuggingEnabled()) - QQmlInspectorService::instance()->addView(q); + QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>(); + if (service) + service->addView(q); } QQuickViewPrivate::QQuickViewPrivate() @@ -97,8 +99,9 @@ QQuickViewPrivate::QQuickViewPrivate() QQuickViewPrivate::~QQuickViewPrivate() { - if (QQmlDebugService::isDebuggingEnabled()) - QQmlInspectorService::instance()->removeView(q_func()); + QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>(); + if (service) + service->removeView(q_func()); } void QQuickViewPrivate::execute() @@ -345,6 +348,9 @@ QQuickView::Status QQuickView::status() const if (!d->component) return QQuickView::Null; + if (d->component->status() == QQmlComponent::Ready && !d->root) + return QQuickView::Error; + return QQuickView::Status(d->component->status()); } @@ -364,6 +370,10 @@ QList<QQmlError> QQuickView::errors() const QQmlError error; error.setDescription(QLatin1String("QQuickView: invalid qml engine.")); errs << error; + } else if (d->component && d->component->status() == QQmlComponent::Ready && !d->root) { + QQmlError error; + error.setDescription(QLatin1String("QQuickView: invalid root object.")); + errs << error; } return errs; @@ -501,14 +511,15 @@ void QQuickViewPrivate::setRootObject(QObject *obj) if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) { root = sgItem; sgItem->setParentItem(q->QQuickWindow::contentItem()); + } else if (qobject_cast<QWindow *>(obj)) { + qWarning() << "QQuickView does not support using windows as a root item." << endl + << endl + << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl; } else { qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl << endl - << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl - << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl - << endl - << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl - << "QDeclarativeView class in the Qt Quick 1 module." << endl; + << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl + << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl; delete obj; root = 0; } diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h index f094c5a216..80da0ba4f1 100644 --- a/src/quick/items/qquickview.h +++ b/src/quick/items/qquickview.h @@ -53,7 +53,6 @@ class Q_QUICK_EXPORT QQuickView : public QQuickWindow Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode) Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true) - Q_ENUMS(ResizeMode Status) public: explicit QQuickView(QWindow *parent = 0); QQuickView(QQmlEngine* engine, QWindow *parent); @@ -68,10 +67,12 @@ public: QQuickItem *rootObject() const; enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView }; + Q_ENUM(ResizeMode) ResizeMode resizeMode() const; void setResizeMode(ResizeMode); enum Status { Null, Ready, Loading, Error }; + Q_ENUM(Status) Status status() const; QList<QQmlError> errors() const; diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index 6f673368d5..6f970f959d 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKVIEW_P_H #define QQUICKVIEW_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 "qquickview.h" #include <QtCore/qurl.h> @@ -98,7 +109,10 @@ namespace QV4 { namespace Heap { struct QQuickRootItemMarker : Object { - inline QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window); + inline QQuickRootItemMarker(QQuickWindow *window) + : window(window) + { + } QQuickWindow *window; }; @@ -115,12 +129,7 @@ struct QQuickRootItemMarker : public Object }; -inline -Heap::QQuickRootItemMarker::QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window) - : Heap::Object(engine) - , window(window) -{ -} + } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 76daa44225..6542bde4f1 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -64,7 +64,6 @@ #include <QtQuick/private/qquickpixmapcache_p.h> -#include <private/qqmlprofilerservice_p.h> #include <private/qqmlmemoryprofiler_p.h> #include <private/qopenglvertexarrayobject_p.h> @@ -83,8 +82,8 @@ bool QQuickWindowPrivate::defaultAlphaBuffer = false; void QQuickWindowPrivate::updateFocusItemTransform() { - Q_Q(QQuickWindow); #ifndef QT_NO_IM + Q_Q(QQuickWindow); QQuickItem *focus = q->activeFocusItem(); if (focus && QGuiApplication::focusObject() == focus) { QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus); @@ -259,8 +258,7 @@ void QQuickWindowPrivate::polishItems() // the user. int recursionSafeguard = INT_MAX; while (!itemsToPolish.isEmpty() && --recursionSafeguard > 0) { - QQuickItem *item = *itemsToPolish.begin(); - itemsToPolish.remove(item); + QQuickItem *item = itemsToPolish.takeLast(); QQuickItemPrivate::get(item)->polishScheduled = false; item->updatePolish(); } @@ -370,12 +368,15 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size) if (!customRenderStage || !customRenderStage->render()) { int fboId = 0; const qreal devicePixelRatio = q->effectiveDevicePixelRatio(); - renderer->setDeviceRect(QRect(QPoint(0, 0), size * devicePixelRatio)); if (renderTargetId) { + QRect rect(QPoint(0, 0), renderTargetSize); fboId = renderTargetId; - renderer->setViewportRect(QRect(QPoint(0, 0), renderTargetSize)); + renderer->setDeviceRect(rect); + renderer->setViewportRect(rect); } else { - renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio)); + QRect rect(QPoint(0, 0), devicePixelRatio * size); + renderer->setDeviceRect(rect); + renderer->setViewportRect(rect); } renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size)); renderer->setDevicePixelRatio(devicePixelRatio); @@ -1433,29 +1434,8 @@ void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e) { Q_Q(QQuickWindow); -#ifndef QT_NO_SHORTCUT - // Try looking for a Shortcut before sending key events - if (e->type() == QEvent::KeyPress - && QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(q->focusObject(), e)) - return; -#endif - if (activeFocusItem) q->sendEvent(activeFocusItem, e); -#ifdef Q_OS_MAC - else { - // This is the case for popup windows on Mac, where popup windows get focus - // in Qt (after exposure) but they are not "key windows" in the Cocoa sense. - // Therefore, the will never receive key events from Cocoa. Instead, the - // toplevel non-popup window (the application current "key window") will - // receive them. (QWidgetWindow does something similar for widgets, by keeping - // a list of popup windows, and forwarding the key event to the top-most popup.) - QWindow *focusWindow = QGuiApplication::focusWindow(); - if (focusWindow && focusWindow != q - && (focusWindow->flags() & Qt::Popup) == Qt::Popup) - QGuiApplication::sendEvent(focusWindow, e); - } -#endif } QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos) @@ -2389,7 +2369,9 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem if (target->childMouseEventFilter(item, targetEvent.data())) { qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target; QVector<int> touchIds; - for (int i = 0; i < targetEvent->touchPoints().size(); ++i) + const int touchPointCount = targetEvent->touchPoints().size(); + touchIds.reserve(touchPointCount); + for (int i = 0; i < touchPointCount; ++i) touchIds.append(targetEvent->touchPoints().at(i).id()); target->grabTouchPoints(touchIds); if (mouseGrabberItem) { @@ -2453,9 +2435,11 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem if (!target) return false; - bool filtered = false; - QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target); + if (targetPrivate->replayingPressEvent) + return false; + + bool filtered = false; if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) { hasFiltered->insert(target); if (target->childMouseEventFilter(item, event)) @@ -2733,7 +2717,7 @@ static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d) QQuickItem *before = 0; for (int i=0; i<childItems.size(); ++i) { QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i)); - // Perform the same check as the in buildOrderNodeList below. + // Perform the same check as the in fetchNextNode below. if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount))) before = childItems.at(i); else @@ -2742,13 +2726,9 @@ static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d) return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : 0; } -static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv) +static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode) { QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems(); - QVector<QSGNode *> desiredNodes; - desiredNodes.reserve(orderedChildren.size() + 1); // + 1 for the paintNode - - int ii = 0; for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) { QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii)); @@ -2756,11 +2736,14 @@ static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv) (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount)) continue; - desiredNodes.append(childPrivate->itemNode()); + ii++; + return childPrivate->itemNode(); } - if (itemPriv->paintNode) - desiredNodes.append(itemPriv->paintNode); + if (itemPriv->paintNode && !returnedPaintNode) { + returnedPaintNode = true; + return itemPriv->paintNode; + } for (; ii < orderedChildren.count(); ++ii) { QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii)); @@ -2768,10 +2751,11 @@ static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv) (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount)) continue; - desiredNodes.append(childPrivate->itemNode()); + ii++; + return childPrivate->itemNode(); } - return desiredNodes; + return 0; } void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) @@ -2874,7 +2858,10 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) } if (dirty & QQuickItemPrivate::ChildrenUpdateMask) { - QVector<QSGNode *> desiredNodes = buildOrderedNodeList(itemPriv); + int ii = 0; + bool fetchedPaintNode = false; + QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems(); + int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0); // now start making current state match the promised land of // desiredNodes. in the case of our current state matching desiredNodes @@ -2892,14 +2879,9 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) int added = 0; int removed = 0; int replaced = 0; -#if defined(CHILDRENUPDATE_DEBUG) - // This is slow! Do not do this in a normal/profiling build! - int initialCount = groupNode->childCount(); -#endif - - while (currentNode && desiredNodesProcessed < desiredNodes.size()) { - QSGNode *desiredNode = desiredNodes.at(desiredNodesProcessed); + QSGNode *desiredNode = 0; + while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) { // uh oh... reality and our utopic paradise are diverging! // we need to reconcile this... if (currentNode != desiredNode) { @@ -2923,9 +2905,8 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) // if we didn't process as many nodes as in the new list, then we have // more nodes at the end of desiredNodes to append to our list. // this will be the case when adding new nodes, for instance. - if (desiredNodesProcessed < desiredNodes.size()) { - for (int i = desiredNodesProcessed; i < desiredNodes.size(); ++i) { - QSGNode *desiredNode = desiredNodes.at(i); + if (desiredNodesProcessed < desiredNodesSize) { + while ((desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) { if (desiredNode->parent()) desiredNode->parent()->removeChildNode(desiredNode); groupNode->appendChildNode(desiredNode); @@ -2942,10 +2923,6 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) removed++; } } - -#if defined(CHILDRENUPDATE_DEBUG) - qDebug() << "Done children update for " << itemPriv << "- before:" << initialCount << "after:" << groupNode->childCount() << "added:" << added << "removed:" << removed << "replaced:" << replaced; -#endif } if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) { @@ -3311,12 +3288,7 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const QImage QQuickWindow::grabWindow() { Q_D(QQuickWindow); - if (!isVisible()) { - - if (d->context->openglContext()) { - qWarning("QQuickWindow::grabWindow: scene graph already in use"); - return QImage(); - } + if (!isVisible() && !d->context->openglContext()) { if (!handle() || !size().isValid()) { qWarning("QQuickWindow::grabWindow: window must be created and have a valid size"); @@ -3334,7 +3306,8 @@ QImage QQuickWindow::grabWindow() d->syncSceneGraph(); d->renderSceneGraph(size()); - QImage image = qt_gl_read_framebuffer(size() * effectiveDevicePixelRatio(), false, false); + bool alpha = format().alphaBufferSize() > 0 && color().alpha() < 255; + QImage image = qt_gl_read_framebuffer(size() * effectiveDevicePixelRatio(), alpha, alpha); d->cleanupNodesOnShutdown(); d->context->invalidate(); context.doneCurrent(); @@ -3386,6 +3359,11 @@ QQmlIncubationController *QQuickWindow::incubationController() const will delete the GL texture when the texture object is deleted. \value TextureCanUseAtlas The image can be uploaded into a texture atlas. + + \value TextureIsOpaque The texture will return false for + QSGTexture::hasAlphaChannel() and will not be blended. This flag was added + in Qt 5.6. + */ /*! @@ -3590,12 +3568,21 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const The caller of the function is responsible for deleting the returned texture. The actual GL texture will be deleted when the texture object is deleted. - When \a options contains TextureCanUseAtlas the engine may put the image + When \a options contains TextureCanUseAtlas, the engine may put the image into a texture atlas. Textures in an atlas need to rely on QSGTexture::normalizedTextureSubRect() for their geometry and will not support QSGTexture::Repeat. Other values from CreateTextureOption are ignored. + When \a options contains TextureIsOpaque, the engine will create an RGB + texture which returns false for QSGTexture::hasAlphaChannel(). Opaque + textures will in most cases be faster to render. When this flag is not set, + the texture will have an alpha channel based on the image's format. + + When \a options contains TextureHasMipmaps, the engine will create a + texture which can use mipmap filtering. Mipmapped textures can not be in + an atlas. + The returned texture will be using \c GL_TEXTURE_2D as texture target and \c GL_RGBA as internal format. Reimplement QSGTexture to create textures with different parameters. @@ -3617,14 +3604,13 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const { Q_D(const QQuickWindow); - if (d->context) { - if (options & TextureCanUseAtlas) - return d->context->createTexture(image); - else - return d->context->createTextureNoAtlas(image); - } - else - return 0; + if (!d->context) + return 0; + uint flags = 0; + if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas; + if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap; + if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha; + return d->context->createTexture(image, flags); } @@ -4119,6 +4105,7 @@ void QQuickWindow::resetOpenGLState() \value BeforeRenderingStage Before rendering. \value AfterRenderingStage After rendering. \value AfterSwapStage After the frame is swapped. + \value NoStage As soon as possible. This value was added in Qt 5.6. \sa {Scene Graph and Rendering} */ @@ -4144,8 +4131,17 @@ void QQuickWindow::resetOpenGLState() If the rendering is happening on a different thread, then the job will happen on the rendering thread. - \note This function does not trigger rendering; the job - will be stored run until rendering is triggered elsewhere. + If \a stage is \l NoStage, \a job will be run at the earliest opportunity + whenever the render thread is not busy rendering a frame. If there is no + OpenGL context available or the window is not exposed at the time the job is + either posted or handled, it is deleted without executing the run() method. + If a non-threaded renderer is in use, the run() method of the job is executed + synchronously. + The OpenGL context is changed to the renderer context before executing a + \l NoStage job. + + \note This function does not trigger rendering; the jobs targeting any other + stage than NoStage will be stored run until rendering is triggered elsewhere. To force the job to run earlier, call QQuickWindow::update(); \sa beforeRendering(), afterRendering(), beforeSynchronizing(), @@ -4157,16 +4153,22 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage) Q_D(QQuickWindow); d->renderJobMutex.lock(); - if (stage == BeforeSynchronizingStage) + if (stage == BeforeSynchronizingStage) { d->beforeSynchronizingJobs << job; - else if (stage == AfterSynchronizingStage) + } else if (stage == AfterSynchronizingStage) { d->afterSynchronizingJobs << job; - else if (stage == BeforeRenderingStage) + } else if (stage == BeforeRenderingStage) { d->beforeRenderingJobs << job; - else if (stage == AfterRenderingStage) + } else if (stage == AfterRenderingStage) { d->afterRenderingJobs << job; - else if (stage == AfterSwapStage) + } else if (stage == AfterSwapStage) { d->afterSwapJobs << job; + } else if (stage == NoStage) { + if (isExposed()) + d->windowManager->postJob(this, job); + else + delete job; + } d->renderJobMutex.unlock(); } diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index f7a1956120..d5bf9fba81 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -69,7 +69,8 @@ public: TextureHasAlphaChannel = 0x0001, TextureHasMipmaps = 0x0002, TextureOwnsGLTexture = 0x0004, - TextureCanUseAtlas = 0x0008 + TextureCanUseAtlas = 0x0008, + TextureIsOpaque = 0x0010 }; enum RenderStage { @@ -77,7 +78,8 @@ public: AfterSynchronizingStage, BeforeRenderingStage, AfterRenderingStage, - AfterSwapStage + AfterSwapStage, + NoStage }; Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption) @@ -85,7 +87,7 @@ public: enum SceneGraphError { ContextNotAvailable = 1 }; - Q_ENUMS(SceneGraphError) + Q_ENUM(SceneGraphError) QQuickWindow(QWindow *parent = 0); explicit QQuickWindow(QQuickRenderControl *renderControl); diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index b63143178b..e475c48b0a 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -202,7 +202,7 @@ public: QQuickItem *dirtyItemList; QList<QSGNode *> cleanupNodeList; - QSet<QQuickItem *> itemsToPolish; + QVector<QQuickItem *> itemsToPolish; void updateDirtyNodes(); void cleanupNodes(); diff --git a/src/quick/items/qquickwindowattached_p.h b/src/quick/items/qquickwindowattached_p.h index 8138ab216a..98b28430b2 100644 --- a/src/quick/items/qquickwindowattached_p.h +++ b/src/quick/items/qquickwindowattached_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKWINDOW_ATTACHED_P_H #define QQUICKWINDOW_ATTACHED_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 <qqml.h> #include <QWindow> diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h index bfc51953ca..8396019102 100644 --- a/src/quick/items/qquickwindowmodule_p.h +++ b/src/quick/items/qquickwindowmodule_p.h @@ -34,6 +34,17 @@ #ifndef QQUICKWINDOWMODULE_H #define QQUICKWINDOWMODULE_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 <private/qtquickglobal_p.h> #include <qquickwindow.h> #include <qqmlparserstatus.h> |