diff options
Diffstat (limited to 'src/quick')
136 files changed, 1940 insertions, 1352 deletions
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 897e1143d5..fbde5d354d 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -269,8 +269,8 @@ void QAccessibleQuickItem::doAction(const QString &actionName) return; // Look for and call the accessible[actionName]Action() function on the item. // This allows for overriding the default action handling. - const QByteArray functionName = QByteArrayLiteral("accessible") + actionName.toLatin1() + QByteArrayLiteral("Action"); - if (object()->metaObject()->indexOfMethod(QByteArray(functionName + QByteArrayLiteral("()"))) != -1) { + const QByteArray functionName = "accessible" + actionName.toLatin1() + "Action"; + if (object()->metaObject()->indexOfMethod(QByteArray(functionName + "()")) != -1) { QMetaObject::invokeMethod(object(), functionName); return; } diff --git a/src/quick/accessible/qaccessiblequickview_p.h b/src/quick/accessible/qaccessiblequickview_p.h index 007a6fd990..7c103380cb 100644 --- a/src/quick/accessible/qaccessiblequickview_p.h +++ b/src/quick/accessible/qaccessiblequickview_p.h @@ -63,20 +63,20 @@ class QAccessibleQuickWindow : public QAccessibleObject public: QAccessibleQuickWindow(QQuickWindow *object); - QAccessibleInterface *parent() const; - QAccessibleInterface *child(int index) const; + QAccessibleInterface *parent() const override; + QAccessibleInterface *child(int index) const override; - QAccessible::Role role() const; - QAccessible::State state() const; - QRect rect() const; + QAccessible::Role role() const override; + QAccessible::State state() const override; + QRect rect() const override; - int childCount() const; - int indexOfChild(const QAccessibleInterface *iface) const; - QString text(QAccessible::Text text) const; - QAccessibleInterface *childAt(int x, int y) const; + int childCount() const override; + int indexOfChild(const QAccessibleInterface *iface) const override; + QString text(QAccessible::Text text) const override; + QAccessibleInterface *childAt(int x, int y) const override; private: - QQuickWindow *window() const { return static_cast<QQuickWindow*>(object()); } + QQuickWindow *window() const override { return static_cast<QQuickWindow*>(object()); } QList<QQuickItem *> rootItems() const; }; diff --git a/src/quick/designer/qqmldesignermetaobject_p.h b/src/quick/designer/qqmldesignermetaobject_p.h index 01512f6af0..3c02c0d3f5 100644 --- a/src/quick/designer/qqmldesignermetaobject_p.h +++ b/src/quick/designer/qqmldesignermetaobject_p.h @@ -74,7 +74,7 @@ protected: void createNewDynamicProperty(const QString &name); int openMetaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a); - int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a); + int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; void notifyPropertyChange(int id); void setValue(int id, const QVariant &value); QVariant propertyWriteValue(int, const QVariant &); diff --git a/src/quick/designer/qquickdesignerwindowmanager_p.h b/src/quick/designer/qquickdesignerwindowmanager_p.h index 09e15dad73..5322b6c421 100644 --- a/src/quick/designer/qquickdesignerwindowmanager_p.h +++ b/src/quick/designer/qquickdesignerwindowmanager_p.h @@ -75,24 +75,24 @@ class QQuickDesignerWindowManager : public QSGRenderLoop public: QQuickDesignerWindowManager(); - void show(QQuickWindow *window); - void hide(QQuickWindow *window); + void show(QQuickWindow *window) override; + void hide(QQuickWindow *window) override; - void windowDestroyed(QQuickWindow *window); + void windowDestroyed(QQuickWindow *window) override; void makeOpenGLContext(QQuickWindow *window); - void exposureChanged(QQuickWindow *window); - QImage grab(QQuickWindow *window); + void exposureChanged(QQuickWindow *window) override; + QImage grab(QQuickWindow *window) override; - void maybeUpdate(QQuickWindow *window); - void update(QQuickWindow *window); // identical for this implementation. + void maybeUpdate(QQuickWindow *window) override; + void update(QQuickWindow *window) override; // identical for this implementation. - void releaseResources(QQuickWindow *) { } + void releaseResources(QQuickWindow *) override { } - QAnimationDriver *animationDriver() const { return 0; } + QAnimationDriver *animationDriver() const override { return nullptr; } - QSGContext *sceneGraphContext() const; - QSGRenderContext *createRenderContext(QSGContext *) const { return m_renderContext.data(); } + QSGContext *sceneGraphContext() const override; + QSGRenderContext *createRenderContext(QSGContext *) const override { return m_renderContext.data(); } static void createOpenGLContext(QQuickWindow *window); diff --git a/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc b/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc index 9ce26e1bb8..3fd92177f9 100644 --- a/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc +++ b/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc @@ -58,6 +58,8 @@ The supported backends are the following \li Direct3D 12 - Requested by the string \c{"d3d12"} or the enum value QSGRendererInterface::Direct3D12. +\li OpenVG - Requested by the string \c{"openvg"} or the enum value QSGRendererInterface::OpenVG. + \endlist When in doubt which backend is in use, enable basic scenegraph information @@ -92,6 +94,14 @@ running on Windows 10, both for Win32 and UWP applications. The details for this adaptation are available here: \l{qtquick-visualcanvas-adaptations-d3d12.html}{Direct3D 12 Adaptation} +\section1 OpenVG + +The OpenVG adaptation is an alternative renderer for \l {Qt Quick} 2 that will +renderer the contents of the scene graph using OpenVG commands to provide +hardware-acclerated 2D vector and raster graphics. The details for this +adaptation are available here: +\l{qtquick-visualcanvas-scenegraph-openvg.html}{OpenVG Adaptation} + */ @@ -387,3 +397,73 @@ between the frames). By default blocking present is disabled. \endlist */ + +/*! +\title Qt Quick OpenVG Adaptation +\page qtquick-visualcanvas-adaptations-openvg.html + +The OpenVG adaptation is an alternative renderer for \l {Qt Quick} 2 that will +renderer the contents of the scene graph using OpenVG commands to provide +hardware-acclerated 2D vector and raster graphics. Much like the Software +adaptation, some features and optimizations are no longer available. Most +Qt Quick 2 applications will run without modification though any attempts to +use unsupported features will be ignored. + +\section2 EGL Requirement +Unlike the defualt OpenGL Renderer, there is no built in support for acquiring +an OpenVG context. This means that the renderer has the responsbility of +requesting and managing the the current context. To do this EGL has to be used +directly in the OpenVG renderer. This means that the OpenVG renderer is only +usable with platform plugins that support creating QWindows with support for +QSurfaceFormat::OpenVG. From this window, the renderer can get an EGLSurface +which can be used with an EGLContext to render OpenVG content. + +\section2 Renderer +The OpenVG Renderer works by using the OpenVG API to send commands and data to +a Vector GPU which will render the scenegraph in an accelerated manner, offloading +graphics rendering from the CPU. Many operations like the rendering of rectangles +and fonts glyphs ideal for OpenVG because these can be represented as paths which +are stroked and filled. Rendering scenegraph items that would typically involve +textures are handled in the OpenVG renderer by using VGImage. In addition when +rendering to offscreen surfaces (like when using Layers), the scene subtree is +rendered to a VGImage which can be reused in the scene. + +\section2 Render Loop +The OpenVG Renderer mirrors the behavior of the Basic render loop and will execute +all OpenVG commands in a single thread. + +See the \l{qtquick-visualcanvas-scenegraph.html}{Scene Graph page} for more +information on render loops + +\section2 Shader Effects +ShaderEffect components in QtQuick 2 can not be rendered by the OpenVG adaptation. +While it is possible to user ShaderEffectSource and QML Item Layers (which are both +offscreen surfaces), it is not actually possible to apply shader effects to them +via the ShaderEffect item. This is because OpenVG lacks an API for applying per +vertex and per fragment shader operations. It may be possible however to take +advantage of Image Filter operations in the OpenVG API to get similar effects to +what is provided by ShaderEffects in custom items. To integrate custom OpenVG +rendering, use QSGRenderNode in combination with QSGRendererInterface. + +\section2 Qt Graphical Effects Module +\l {Qt Graphical Effects} uses ShaderEffect items to render effects. If you use +graphical effects from this module, then you should not hide the source +item so that the original item can still be rendered. + +\section2 Particle Effects +It is not possible to render particle effects with the OpenVG adaptation. Whenever +possible, remove particles completely from the scene. Otherwise they will still +require some processing, even though they are not visible. + +\section2 Rendering Text +The text rendering with the OpenVG adaptation is based on rendering the glpyh +paths, and does not use the distance fields technique used by the OpenGL backend. + +\section2 Perspective Transforms +The OpenVG API does not allow paths to be transformed with non-affine transforms, +while it is possible with Qt Quick. This means that rendering components using +paths like Rectangles and Text, when applying perspective transforms the OpenVG +backend will first render to a VGImage before applying transformations. This uses +more memory at runtime and is a slower path so avoid doing this if necessary. + +*/ diff --git a/src/quick/items/checksync.pl b/src/quick/items/checksync.pl deleted file mode 100755 index c9771bb10c..0000000000 --- a/src/quick/items/checksync.pl +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/perl -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the Declarative module of the Qt Toolkit. -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -use strict; -use warnings; - -die "Usage: $0 <QML directory>" if (@ARGV != 1); - -my @excludes; -open (SYNCEXCLUDES, "<", "syncexcludes"); -while (<SYNCEXCLUDES>) { - if (/^([a-zA-Z0-9\._]+)/) { - my $exclude = $1; - push (@excludes, $exclude); - } -} - -my $portdir = "."; -my $qmldir = $ARGV[0]; - -opendir (PORTDIR, $portdir) or die "Cannot open port directory"; -opendir (QMLDIR, $qmldir) or die "Cannot open QML directory"; - -my @portfiles = readdir(PORTDIR); -my @qmlfiles = readdir(QMLDIR); - -closedir(PORTDIR); -closedir(QMLDIR); - -foreach my $qmlfile (@qmlfiles) { - if ($qmlfile =~ /^qdeclarative.*\.cpp$/ or $qmlfile =~ /qdeclarative.*\.h$/) { - - if (grep { $_ eq $qmlfile} @excludes) { - next; - } - - my $portfile = $qmlfile; - $portfile =~ s/^qdeclarative/qsg/; - - if (grep { $_ eq $portfile} @portfiles) { - - open (PORTFILE, "<", "$portdir/$portfile") or die("Cannot open $portdir/$portfile for reading"); - - my $firstline = <PORTFILE>; - - close (PORTFILE); - - if ($firstline and $firstline =~ /^\/\/ Commit: ([a-z0-9]+)/) { - my $sha1 = $1; - my $commitSha1 = ""; - - my $output = `cd $qmldir; git log $qmlfile | head -n 1`; - if ($output =~ /commit ([a-z0-9]+)/) { - $commitSha1 = $1; - } - - if ($commitSha1 eq $sha1) { - print ("$portfile: OK\n"); - } else { - print ("$portfile: OUT OF DATE\n"); - } - } else { - print ("$portfile: OUT OF DATE\n"); - } - } else { - print ("$portfile: MISSING\n"); - } - } -} diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 212148b754..78db92ba8a 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -1095,6 +1095,27 @@ QImage QQuickCanvasItem::toImage(const QRectF& rect) const return QImage(); } +static const char* mimeToType(const QString &mime) +{ + const QLatin1String imagePrefix("image/"); + if (!mime.startsWith(imagePrefix)) + return nullptr; + const QStringRef mimeExt = mime.midRef(imagePrefix.size()); + if (mimeExt == QLatin1String("png")) + return "png"; + else if (mimeExt == QLatin1String("bmp")) + return "bmp"; + else if (mimeExt == QLatin1String("jpeg")) + return "jpeg"; + else if (mimeExt == QLatin1String("x-portable-pixmap")) + return "ppm"; + else if (mimeExt == QLatin1String("tiff")) + return "tiff"; + else if (mimeExt == QLatin1String("xpm")) + return "xpm"; + return nullptr; +} + /*! \qmlmethod string QtQuick::Canvas::toDataURL(string mimeType) @@ -1112,27 +1133,14 @@ QString QQuickCanvasItem::toDataURL(const QString& mimeType) const QByteArray ba; QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); - QString mime = mimeType.toLower(); - QString type; - if (mime == QLatin1String("image/png")) { - type = QStringLiteral("PNG"); - } else if (mime == QLatin1String("image/bmp")) - type = QStringLiteral("BMP"); - else if (mime == QLatin1String("image/jpeg")) - type = QStringLiteral("JPEG"); - else if (mime == QLatin1String("image/x-portable-pixmap")) - type = QStringLiteral("PPM"); - else if (mime == QLatin1String("image/tiff")) - type = QStringLiteral("TIFF"); - else if (mime == QLatin1String("image/xpm")) - type = QStringLiteral("XPM"); - else + const QString mime = mimeType.toLower(); + const char* type = mimeToType(mime); + if (!type) return QStringLiteral("data:,"); - image.save(&buffer, type.toLatin1()); + image.save(&buffer, type); buffer.close(); - QString dataUrl = QStringLiteral("data:%1;base64,%2"); - return dataUrl.arg(mime).arg(QLatin1String(ba.toBase64().constData())); + return QLatin1String("data:") + mime + QLatin1String(";base64,") + QLatin1String(ba.toBase64().constData()); } return QStringLiteral("data:,"); } diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h index 8196debef1..8af84d0e7c 100644 --- a/src/quick/items/context2d/qquickcanvasitem_p.h +++ b/src/quick/items/context2d/qquickcanvasitem_p.h @@ -195,7 +195,7 @@ private: Q_INVOKABLE void delayedCreate(); bool createContext(const QString &contextType); void initializeContext(QQuickCanvasContext *context, const QVariantMap &args = QVariantMap()); - QRect tiledRect(const QRectF &window, const QSize &tileSize); + static QRect tiledRect(const QRectF &window, const QSize &tileSize); bool isPaintConnected(); }; diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h index e897263b6f..334bf08329 100644 --- a/src/quick/items/context2d/qquickcontext2d_p.h +++ b/src/quick/items/context2d/qquickcontext2d_p.h @@ -184,17 +184,17 @@ public: QQuickContext2D(QObject *parent = 0); ~QQuickContext2D(); - QStringList contextNames() const; - void init(QQuickCanvasItem *canvasItem, const QVariantMap &args); - void prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing); - void flush(); + QStringList contextNames() const override; + void init(QQuickCanvasItem *canvasItem, const QVariantMap &args) override; + void prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing) override; + void flush() override; void sync(); QThread *thread() const { return m_thread; } QQuickContext2DTexture *texture() const; - QImage toImage(const QRectF& bounds); + QImage toImage(const QRectF& bounds) override; - QV4::ReturnedValue v4value() const; - void setV4Engine(QV4::ExecutionEngine *eng); + QV4::ReturnedValue v4value() const override; + void setV4Engine(QV4::ExecutionEngine *eng) override; QQuickCanvasItem* canvas() const { return m_canvas; } QQuickContext2DCommandBuffer* buffer() const { return m_buffer; } @@ -243,8 +243,8 @@ public: QPainterPath createTextGlyphs(qreal x, qreal y, const QString& text); QQmlRefPointer<QQuickCanvasPixmap> createPixmap(const QUrl& url); - QOpenGLContext *glContext() { return m_glContext; } - QSurface *surface() { return m_surface.data(); } + QOpenGLContext *glContext() const { return m_glContext; } + QSurface *surface() const { return m_surface.data(); } void setGrabbedImage(const QImage& grab); State state; diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h index 3663e49f10..2a1ac7304e 100644 --- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h +++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h @@ -71,7 +71,7 @@ public: void reset(); void clear(); - inline int size() {return commands.size();} + inline int size() const { return commands.size(); } inline bool isEmpty() const {return commands.isEmpty(); } inline bool hasNext() const {return cmdIdx < commands.size(); } inline QQuickContext2D::PaintCommand takeNextCommand() { return commands.at(cmdIdx++); } @@ -249,7 +249,7 @@ public: void replay(QPainter* painter, QQuickContext2D::State& state, const QVector2D &scaleFactor); private: - QPen makePen(const QQuickContext2D::State& state); + static QPen makePen(const QQuickContext2D::State& state); void setPainterState(QPainter* painter, const QQuickContext2D::State& state, const QPen& pen); int cmdIdx; int intIdx; diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h index 04d7b40ab7..97135816a2 100644 --- a/src/quick/items/context2d/qquickcontext2dtexture_p.h +++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h @@ -124,7 +124,7 @@ public: // Called during sync() on the scene graph thread while GUI is blocked. virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame, QQuickWindow *window) = 0; - bool event(QEvent *e); + bool event(QEvent *e) override; #if QT_CONFIG(opengl) void initializeOpenGL(QOpenGLContext *gl, QOffscreenSurface *s) { m_gl = gl; @@ -225,17 +225,17 @@ public: QQuickContext2DImageTexture(); ~QQuickContext2DImageTexture(); - virtual QQuickCanvasItem::RenderTarget renderTarget() const; + QQuickCanvasItem::RenderTarget renderTarget() const override; - virtual QQuickContext2DTile* createTile() const; - virtual QPaintDevice* beginPainting(); - virtual void endPainting(); - virtual void compositeTile(QQuickContext2DTile* tile); + QQuickContext2DTile* createTile() const override; + QPaintDevice* beginPainting() override; + void endPainting() override; + void compositeTile(QQuickContext2DTile* tile) override; - virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame, QQuickWindow *window); + QSGTexture *textureForNextFrame(QSGTexture *lastFrame, QQuickWindow *window) override; public Q_SLOTS: - virtual void grabImage(const QRectF& region = QRectF()); + void grabImage(const QRectF& region = QRectF()) override; private: QImage m_image; diff --git a/src/quick/items/context2d/qquickcontext2dtile_p.h b/src/quick/items/context2d/qquickcontext2dtile_p.h index e7eed7b086..d5255edcfc 100644 --- a/src/quick/items/context2d/qquickcontext2dtile_p.h +++ b/src/quick/items/context2d/qquickcontext2dtile_p.h @@ -93,12 +93,12 @@ class QQuickContext2DFBOTile : public QQuickContext2DTile public: QQuickContext2DFBOTile(); ~QQuickContext2DFBOTile(); - virtual void setRect(const QRect& r); + virtual void setRect(const QRect& r) override; QOpenGLFramebufferObject* fbo() const {return m_fbo;} - void drawFinished(); + void drawFinished() override; protected: - void aboutToDraw(); + void aboutToDraw() override; private: @@ -110,7 +110,7 @@ class QQuickContext2DImageTile : public QQuickContext2DTile public: QQuickContext2DImageTile(); ~QQuickContext2DImageTile(); - void setRect(const QRect& r); + void setRect(const QRect& r) override; const QImage& image() const {return m_image;} private: QImage m_image; diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index c8538745cc..215a1e5db6 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -203,7 +203,7 @@ public: return object; } - QAccessible::State state() { return m_state; } + QAccessible::State state() const { return m_state; } bool ignored() const; bool doAction(const QString &actionName); void availableActions(QStringList *actions) const; diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index a069f1ece3..4162314cd3 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -285,7 +285,7 @@ void QQuickAnchorsPrivate::clearItem(QQuickItem *item) } } -QQuickGeometryChange QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) +QQuickGeometryChange QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) const { QQuickGeometryChange dependency; @@ -588,7 +588,7 @@ bool QQuickAnchorsPrivate::calcStretch(QQuickItem *edge1Item, qreal offset1, qreal offset2, QQuickAnchors::Anchor line, - qreal &stretch) + qreal &stretch) const { bool edge1IsParent = (edge1Item == readParentItem(item)); bool edge2IsParent = (edge2Item == readParentItem(item)); diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h index 0373b1f824..906f607302 100644 --- a/src/quick/items/qquickanchors_p_p.h +++ b/src/quick/items/qquickanchors_p_p.h @@ -124,7 +124,7 @@ public: void clearItem(QQuickItem *); - QQuickGeometryChange calculateDependency(QQuickItem *); + QQuickGeometryChange calculateDependency(QQuickItem *) const; void addDepend(QQuickItem *); void remDepend(QQuickItem *); bool isItemComplete() const; @@ -150,7 +150,7 @@ public: bool checkVAnchorValid(QQuickAnchorLine anchor) const; bool calcStretch(QQuickItem *edge1Item, QQuickAnchors::Anchor edge1Line, QQuickItem *edge2Item, QQuickAnchors::Anchor edge2Line, - qreal offset1, qreal offset2, QQuickAnchors::Anchor line, qreal &stretch); + qreal offset1, qreal offset2, QQuickAnchors::Anchor line, qreal &stretch) const; bool isMirrored() const; void updateHorizontalAnchors(); diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h index cc6318a4a3..357f72b3e7 100644 --- a/src/quick/items/qquickdrag_p.h +++ b/src/quick/items/qquickdrag_p.h @@ -77,7 +77,7 @@ class QQuickDragGrabber QIntrusiveListNode node; protected: - void objectDestroyed(QQuickItem *) { delete this; } + void objectDestroyed(QQuickItem *) override { delete this; } }; typedef QIntrusiveList<Item, &Item::node> ItemList; @@ -290,7 +290,7 @@ public: Q_INVOKABLE int drop(); - bool event(QEvent *event); + bool event(QEvent *event) override; public Q_SLOTS: void start(QQmlV4Function *); diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp index 84c44c6541..b314390915 100644 --- a/src/quick/items/qquickdroparea.cpp +++ b/src/quick/items/qquickdroparea.cpp @@ -513,7 +513,7 @@ void QQuickDropArea::dropEvent(QDropEvent *event) easily be translated into a QByteArray. \a format should be one contained in the \l formats property. */ -QObject *QQuickDropEvent::source() +QObject *QQuickDropEvent::source() const { if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(event->mimeData())) return dragMime->source(); diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h index ccde2bcd19..0c4c072db7 100644 --- a/src/quick/items/qquickdroparea_p.h +++ b/src/quick/items/qquickdroparea_p.h @@ -86,7 +86,7 @@ public: qreal x() const { return event->pos().x(); } qreal y() const { return event->pos().y(); } - QObject *source(); + QObject *source() const; Qt::DropActions supportedActions() const { return event->possibleActions(); } Qt::DropActions proposedAction() const { return event->proposedAction(); } diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index a5497f4627..2fad9f5a8d 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -945,7 +945,7 @@ Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *eve dbg << "QQuickEventPoint(valid:" << event->isValid() << " accepted:" << event->isAccepted() << " state:"; QtDebugUtils::formatQEnum(dbg, event->state()); - dbg << " scenePos:" << event->scenePos() << " id:" << event->pointId() + dbg << " scenePos:" << event->scenePos() << " id:" << hex << event->pointId() << dec << " timeHeld:" << event->timeHeld() << ')'; return dbg; } diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 1e778306e0..00a1306627 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -277,7 +277,7 @@ void QQuickFlickablePrivate::init() Returns the amount to overshoot by given a velocity. Will be roughly in range 0 - size/4 */ -qreal QQuickFlickablePrivate::overShootDistance(qreal size) +qreal QQuickFlickablePrivate::overShootDistance(qreal size) const { if (maxVelocity <= 0) return 0.0; @@ -874,9 +874,9 @@ bool QQuickFlickable::isAtYBeginning() const } \endcode */ -QQuickItem *QQuickFlickable::contentItem() +QQuickItem *QQuickFlickable::contentItem() const { - Q_D(QQuickFlickable); + Q_D(const QQuickFlickable); return d->contentItem; } @@ -951,7 +951,7 @@ void QQuickFlickable::setPixelAligned(bool align) } } -qint64 QQuickFlickablePrivate::computeCurrentTime(QInputEvent *event) +qint64 QQuickFlickablePrivate::computeCurrentTime(QInputEvent *event) const { if (0 != event->timestamp()) return event->timestamp(); @@ -960,7 +960,7 @@ qint64 QQuickFlickablePrivate::computeCurrentTime(QInputEvent *event) return timer.elapsed(); } -qreal QQuickFlickablePrivate::devicePixelRatio() +qreal QQuickFlickablePrivate::devicePixelRatio() const { return (window ? window->effectiveDevicePixelRatio() : qApp->devicePixelRatio()); } diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h index 62733bda1c..7384c7271a 100644 --- a/src/quick/items/qquickflickable_p.h +++ b/src/quick/items/qquickflickable_p.h @@ -190,7 +190,7 @@ public: bool isAtYEnd() const; bool isAtYBeginning() const; - QQuickItem *contentItem(); + QQuickItem *contentItem() const; enum FlickableDirection { AutoFlickDirection=0x0, HorizontalFlick=0x1, VerticalFlick=0x2, HorizontalAndVerticalFlick=0x3, AutoFlickIfNeeded=0xc }; diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index ac1e39d829..0c3bc21071 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -192,7 +192,7 @@ public: void setViewportX(qreal x); void setViewportY(qreal y); - qreal overShootDistance(qreal size); + qreal overShootDistance(qreal size) const; void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) Q_DECL_OVERRIDE; @@ -260,8 +260,8 @@ public: const QVector2D &deltas, bool overThreshold, bool momentum, bool velocitySensitiveOverBounds, const QVector2D &velocity); - qint64 computeCurrentTime(QInputEvent *event); - qreal devicePixelRatio(); + qint64 computeCurrentTime(QInputEvent *event) const; + qreal devicePixelRatio() const; // flickableData property static void data_append(QQmlListProperty<QObject> *, QObject *); diff --git a/src/quick/items/qquickflipable.cpp b/src/quick/items/qquickflipable.cpp index 342e6c07b8..6a6b6c00a9 100644 --- a/src/quick/items/qquickflipable.cpp +++ b/src/quick/items/qquickflipable.cpp @@ -143,7 +143,7 @@ QQuickFlipable::~QQuickFlipable() The front and back sides of the flipable. */ -QQuickItem *QQuickFlipable::front() +QQuickItem *QQuickFlipable::front() const { Q_D(const QQuickFlipable); return d->front; diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h index 17a74d1f7a..a76977d4ac 100644 --- a/src/quick/items/qquickflipable_p.h +++ b/src/quick/items/qquickflipable_p.h @@ -77,7 +77,7 @@ public: QQuickFlipable(QQuickItem *parent=0); ~QQuickFlipable(); - QQuickItem *front(); + QQuickItem *front() const; void setFront(QQuickItem *); QQuickItem *back(); diff --git a/src/quick/items/qquickgenericshadereffect.cpp b/src/quick/items/qquickgenericshadereffect.cpp index 9714f39663..2f8d71fc11 100644 --- a/src/quick/items/qquickgenericshadereffect.cpp +++ b/src/quick/items/qquickgenericshadereffect.cpp @@ -510,9 +510,9 @@ void QQuickGenericShaderEffect::updateShaderVars(Shader shaderType) QSGShaderEffectNode::VariableData &vd(m_shaders[shaderType].varData[i]); const bool isSpecial = v.name.startsWith("qt_"); // special names not mapped to properties if (isSpecial) { - if (v.name == QByteArrayLiteral("qt_Opacity")) + if (v.name == "qt_Opacity") vd.specialType = QSGShaderEffectNode::VariableData::Opacity; - else if (v.name == QByteArrayLiteral("qt_Matrix")) + else if (v.name == "qt_Matrix") vd.specialType = QSGShaderEffectNode::VariableData::Matrix; else if (v.name.startsWith("qt_SubRect_")) vd.specialType = QSGShaderEffectNode::VariableData::SubRect; diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index e36c070248..f71a2fbdbd 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -69,7 +69,7 @@ public: emit textureChanged(); } - QSGTexture *texture() const { + QSGTexture *texture() const override { if (m_texture) { m_texture->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest); m_texture->setMipmapFiltering(m_mipmap ? QSGTexture::Linear : QSGTexture::None); @@ -304,6 +304,15 @@ void QQuickImage::setFillMode(FillMode mode) if (d->fillMode == mode) return; d->fillMode = mode; + if ((mode == PreserveAspectCrop) != d->providerOptions.preserveAspectRatioCrop()) { + d->providerOptions.setPreserveAspectRatioCrop(mode == PreserveAspectCrop); + if (isComponentComplete()) + load(); + } else if ((mode == PreserveAspectFit) != d->providerOptions.preserveAspectRatioFit()) { + d->providerOptions.setPreserveAspectRatioFit(mode == PreserveAspectFit); + if (isComponentComplete()) + load(); + } update(); updatePaintedGeometry(); emit fillModeChanged(); @@ -423,7 +432,9 @@ qreal QQuickImage::paintedHeight() const (The \l fillMode is independent of this.) If both the sourceSize.width and sourceSize.height are set the image will be scaled - down to fit within the specified size, maintaining the image's aspect ratio. The actual + down to fit within the specified size (unless PreserveAspectCrop or PreserveAspectFit + are used, then it will be scaled to match the optimal size for cropping/fitting), + maintaining the image's aspect ratio. The actual size of the image after scaling is available via \l Item::implicitWidth and \l Item::implicitHeight. If the source is an intrinsically scalable image (eg. SVG), this property diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index a2b99b6395..a6bf6b4e8a 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -246,7 +246,7 @@ void QQuickImageBase::load() resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio); } - d->pix.load(qmlEngine(this), loadUrl, d->sourcesize * d->devicePixelRatio, options, d->autoTransform); + d->pix.load(qmlEngine(this), loadUrl, d->sourcesize * d->devicePixelRatio, options, d->providerOptions); if (d->pix.isLoading()) { if (d->progress != 0.0) { @@ -381,17 +381,18 @@ void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixe bool QQuickImageBase::autoTransform() const { Q_D(const QQuickImageBase); - if (d->autoTransform == UsePluginDefault) - return d->pix.autoTransform() == ApplyTransform; - return d->autoTransform == ApplyTransform; + if (d->providerOptions.autoTransform() == QQuickImageProviderOptions::UsePluginDefaultTransform) + return d->pix.autoTransform() == QQuickImageProviderOptions::ApplyTransform; + return d->providerOptions.autoTransform() == QQuickImageProviderOptions::ApplyTransform; } void QQuickImageBase::setAutoTransform(bool transform) { Q_D(QQuickImageBase); - if (d->autoTransform != UsePluginDefault && transform == (d->autoTransform == ApplyTransform)) + if (d->providerOptions.autoTransform() != QQuickImageProviderOptions::UsePluginDefaultTransform && + transform == (d->providerOptions.autoTransform() == QQuickImageProviderOptions::ApplyTransform)) return; - d->autoTransform = transform ? ApplyTransform : DoNotApplyTransform; + d->providerOptions.setAutoTransform(transform ? QQuickImageProviderOptions::ApplyTransform : QQuickImageProviderOptions::DoNotApplyTransform); emitAutoTransformBaseChanged(); } diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h index 1eb566a3c8..d9b609c7fe 100644 --- a/src/quick/items/qquickimagebase_p_p.h +++ b/src/quick/items/qquickimagebase_p_p.h @@ -68,7 +68,6 @@ public: : status(QQuickImageBase::Null), progress(0.0), devicePixelRatio(1.0), - autoTransform(UsePluginDefault), async(false), cache(true), mirror(false), @@ -83,7 +82,7 @@ public: QSize sourcesize; QSize oldSourceSize; qreal devicePixelRatio; - AutoTransform autoTransform; + QQuickImageProviderOptions providerOptions; bool async : 1; bool cache : 1; bool mirror: 1; diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index cbfd776941..504446a8be 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -333,6 +333,12 @@ QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const } #endif // im +void QQuickItemKeyFilter::shortcutOverride(QKeyEvent *event) +{ + if (m_next) + m_next->shortcutOverride(event); +} + void QQuickItemKeyFilter::componentComplete() { if (m_next) m_next->componentComplete(); @@ -774,7 +780,7 @@ const SigMap sigMap[] = { { 0, 0 } }; -const QByteArray QQuickKeysAttached::keyToSignal(int key) +QByteArray QQuickKeysAttached::keyToSignal(int key) { QByteArray keySignal; if (key >= Qt::Key_0 && key <= Qt::Key_9) { @@ -789,9 +795,9 @@ const QByteArray QQuickKeysAttached::keyToSignal(int key) return keySignal; } -bool QQuickKeysAttached::isConnected(const char *signalName) +bool QQuickKeysAttached::isConnected(const char *signalName) const { - Q_D(QQuickKeysAttached); + Q_D(const QQuickKeysAttached); int signal_index = d->signalIndex(signalName); return d->isSignalConnected(signal_index); } @@ -935,6 +941,46 @@ bool QQuickKeysAttached::isConnected(const char *signalName) */ /*! + \qmlsignal QtQuick::Keys::shortcutOverride(KeyEvent event) + \since 5.9 + + This signal is emitted when a key has been pressed that could potentially + be used as a shortcut. The \a event parameter provides information about + the event. + + Set \c event.accepted to \c true if you wish to prevent the pressed key + from being used as a shortcut by other types, such as \l Shortcut. For + example: + + \code + Item { + id: escapeItem + focus: true + + // Ensure that we get escape key press events first. + Keys.onShortcutOverride: event.accepted = (event.key === Qt.Key_Escape) + + Keys.onEscapePressed: { + console.log("escapeItem is handling escape"); + event.accepted = true; + } + } + + Shortcut { + sequence: "Escape" + onActivated: console.log("Shortcut is handling escape") + } + \endcode + + As with the other signals, \c shortcutOverride will only be emitted for an + item if that item has \l {Item::}{activeFocus}. + + The corresponding handler is \c onShortcutOverride. + + \sa Shortcut +*/ + +/*! \qmlsignal QtQuick::Keys::digit0Pressed(KeyEvent event) This signal is emitted when the digit '0' has been pressed. The \a event @@ -1426,6 +1472,16 @@ QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const } #endif // im +void QQuickKeysAttached::shortcutOverride(QKeyEvent *event) +{ + Q_D(QQuickKeysAttached); + QQuickKeyEvent &keyEvent = d->theKeyEvent; + keyEvent.reset(*event); + emit shortcutOverride(&keyEvent); + + event->setAccepted(keyEvent.isAccepted()); +} + QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj) { return new QQuickKeysAttached(obj); @@ -5019,6 +5075,13 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e) } #endif // im +void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event) +{ + if (extra.isAllocated() && extra->keyHandler) { + extra->keyHandler->shortcutOverride(event); + } +} + /*! Called when \a change occurs for this item. @@ -7652,6 +7715,9 @@ bool QQuickItem::event(QEvent *ev) case QEvent::KeyRelease: d->deliverKeyEvent(static_cast<QKeyEvent*>(ev)); break; + case QEvent::ShortcutOverride: + d->deliverShortcutOverrideEvent(static_cast<QKeyEvent*>(ev)); + break; case QEvent::FocusIn: focusInEvent(static_cast<QFocusEvent*>(ev)); break; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 45674a106d..c0c9bd46bd 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -559,6 +559,7 @@ public: #if QT_CONFIG(im) void deliverInputMethodEvent(QInputMethodEvent *); #endif + void deliverShortcutOverrideEvent(QKeyEvent *); bool isTransparentForPositioner() const; void setTransparentForPositioner(bool trans); @@ -622,6 +623,7 @@ public: virtual void inputMethodEvent(QInputMethodEvent *event, bool post); virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; #endif + virtual void shortcutOverride(QKeyEvent *event); virtual void componentComplete(); bool m_processPost; @@ -813,6 +815,7 @@ Q_SIGNALS: void priorityChanged(); void pressed(QQuickKeyEvent *event); void released(QQuickKeyEvent *event); + void shortcutOverride(QQuickKeyEvent *event); void digit0Pressed(QQuickKeyEvent *event); void digit1Pressed(QQuickKeyEvent *event); void digit2Pressed(QQuickKeyEvent *event); @@ -861,9 +864,10 @@ private: void inputMethodEvent(QInputMethodEvent *, bool post) Q_DECL_OVERRIDE; QVariant inputMethodQuery(Qt::InputMethodQuery query) const Q_DECL_OVERRIDE; #endif - const QByteArray keyToSignal(int key); + void shortcutOverride(QKeyEvent *event) override; + static QByteArray keyToSignal(int key); - bool isConnected(const char *signalName); + bool isConnected(const char *signalName) const; }; Qt::MouseButtons QQuickItemPrivate::acceptedMouseButtons() const diff --git a/src/quick/items/qquickitemanimation_p_p.h b/src/quick/items/qquickitemanimation_p_p.h index 92dd84e4a9..2d075dfab3 100644 --- a/src/quick/items/qquickitemanimation_p_p.h +++ b/src/quick/items/qquickitemanimation_p_p.h @@ -97,7 +97,7 @@ public: entryInterval(0), exitInterval(0) {} ~QQuickPathAnimationUpdater() {} - void setValue(qreal v); + void setValue(qreal v) override; QQuickPath *path; @@ -133,7 +133,7 @@ public: void clearTemplate() { animationTemplate = 0; } - QQuickPathAnimationUpdater *pathUpdater() { return static_cast<QQuickPathAnimationUpdater*>(getAnimValue()); } + QQuickPathAnimationUpdater *pathUpdater() const { return static_cast<QQuickPathAnimationUpdater*>(getAnimValue()); } private: QQuickPathAnimationPrivate *animationTemplate; }; diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp index 1b0e1f07f6..c6355ceed2 100644 --- a/src/quick/items/qquickitemgrabresult.cpp +++ b/src/quick/items/qquickitemgrabresult.cpp @@ -184,13 +184,26 @@ QQuickItemGrabResult::QQuickItemGrabResult(QObject *parent) /*! * Saves the grab result as an image to \a fileName. Returns true * if successful; otherwise returns false. + * + * \note In Qt versions prior to 5.9, this function is marked as non-\c{const}. */ -bool QQuickItemGrabResult::saveToFile(const QString &fileName) +bool QQuickItemGrabResult::saveToFile(const QString &fileName) const { - Q_D(QQuickItemGrabResult); + Q_D(const QQuickItemGrabResult); return d->image.save(fileName); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +/*! + * \overload + * \internal + */ +bool QQuickItemGrabResult::saveToFile(const QString &fileName) +{ + return qAsConst(*this).saveToFile(fileName); +} +#endif // < Qt 6 + QUrl QQuickItemGrabResult::url() const { Q_D(const QQuickItemGrabResult); diff --git a/src/quick/items/qquickitemgrabresult.h b/src/quick/items/qquickitemgrabresult.h index 42d71862de..30f8f0c2ef 100644 --- a/src/quick/items/qquickitemgrabresult.h +++ b/src/quick/items/qquickitemgrabresult.h @@ -64,10 +64,13 @@ public: QImage image() const; QUrl url() const; - Q_INVOKABLE bool saveToFile(const QString &fileName); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + Q_INVOKABLE bool saveToFile(const QString &fileName); // ### Qt 6: remove +#endif + Q_INVOKABLE bool saveToFile(const QString &fileName) const; protected: - bool event(QEvent *); + bool event(QEvent *) override; Q_SIGNALS: void ready(); diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 0296ebe88c..b0ddbb0034 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -373,6 +373,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) #if QT_CONFIG(quick_shadereffect) qmlRegisterType<QQuickBorderImageMesh>("QtQuick", 2, 8, "BorderImageMesh"); #endif + + qmlRegisterType<QQuickMouseArea, 9>(uri, 2, 9, "MouseArea"); } static void initResources() diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 7f8b26f20b..7d98cc2693 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -935,9 +935,11 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) return; applyPendingChanges(); - int idx = qMax(qMin(index, model->count()-1), 0); + const int modelCount = model->count(); + int idx = qMax(qMin(index, modelCount - 1), 0); - qreal pos = isContentFlowReversed() ? -position() - size() : position(); + const auto viewSize = size(); + qreal pos = isContentFlowReversed() ? -position() - viewSize : position(); FxViewItem *item = visibleItem(idx); qreal maxExtent = calculatedMaxExtent(); if (!item) { @@ -961,22 +963,22 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) pos -= headerSize(); break; case QQuickItemView::Center: - pos = itemPos - (size() - item->size())/2; + pos = itemPos - (viewSize - item->size())/2; break; case QQuickItemView::End: - pos = itemPos - size() + item->size(); - if (footer && (index >= model->count() || hasStickyFooter())) + pos = itemPos - viewSize + item->size(); + if (footer && (index >= modelCount || hasStickyFooter())) pos += footerSize(); break; case QQuickItemView::Visible: - if (itemPos > pos + size()) - pos = itemPos - size() + item->size(); + if (itemPos > pos + viewSize) + pos = itemPos - viewSize + item->size(); else if (item->endPosition() <= pos) pos = itemPos; break; case QQuickItemView::Contain: - if (item->endPosition() >= pos + size()) - pos = itemPos - size() + item->size(); + if (item->endPosition() >= pos + viewSize) + pos = itemPos - viewSize + item->size(); if (itemPos < pos) pos = itemPos; break; @@ -1025,28 +1027,27 @@ void QQuickItemView::positionViewAtEnd() d->positionViewAtIndex(d->model->count(), End); } -int QQuickItemView::indexAt(qreal x, qreal y) const +static FxViewItem * fxViewItemAtPosition(const QList<FxViewItem *> &items, qreal x, qreal y) { - Q_D(const QQuickItemView); - for (int i = 0; i < d->visibleItems.count(); ++i) { - const FxViewItem *item = d->visibleItems.at(i); + for (FxViewItem *item : items) { if (item->contains(x, y)) - return item->index; + return item; } + return nullptr; +} - return -1; +int QQuickItemView::indexAt(qreal x, qreal y) const +{ + Q_D(const QQuickItemView); + const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y); + return item ? item->index : -1; } QQuickItem *QQuickItemView::itemAt(qreal x, qreal y) const { Q_D(const QQuickItemView); - for (int i = 0; i < d->visibleItems.count(); ++i) { - const FxViewItem *item = d->visibleItems.at(i); - if (item->contains(x, y)) - return item->item; - } - - return 0; + const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y); + return item ? item->item : nullptr; } void QQuickItemView::forceLayout() @@ -1787,10 +1788,11 @@ void QQuickItemViewPrivate::animationFinished(QAbstractAnimationJob *) void QQuickItemViewPrivate::refill() { qreal s = qMax(size(), qreal(0.)); + const auto pos = position(); if (isContentFlowReversed()) - refill(-position()-displayMarginBeginning-s, -position()+displayMarginEnd); + refill(-pos - displayMarginBeginning-s, -pos + displayMarginEnd); else - refill(position()-displayMarginBeginning, position()+displayMarginEnd+s); + refill(pos - displayMarginBeginning, pos + displayMarginEnd+s); } void QQuickItemViewPrivate::refill(qreal from, qreal to) @@ -2428,14 +2430,14 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item) return flags != QQmlInstanceModel::Referenced; } -QQuickItem *QQuickItemViewPrivate::createHighlightItem() +QQuickItem *QQuickItemViewPrivate::createHighlightItem() const { return createComponentItem(highlightComponent, 0.0, true); } -QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault) +QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault) const { - Q_Q(QQuickItemView); + Q_Q(const QQuickItemView); QQuickItem *item = 0; if (component) { diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index c289ace408..3ac54ea3dc 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -316,7 +316,7 @@ public: : QObject(parent), m_isCurrent(false), m_delayRemove(false) {} ~QQuickItemViewAttached() {} - QQuickItemView *view() { return m_view; } + QQuickItemView *view() const { return m_view; } void setView(QQuickItemView *view) { if (view != m_view) { m_view = view; diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index 62851c9a89..a8e66301c1 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -209,8 +209,8 @@ public: FxViewItem *createItem(int modelIndex, bool asynchronous = false); virtual bool releaseItem(FxViewItem *item); - QQuickItem *createHighlightItem(); - QQuickItem *createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault = false); + QQuickItem *createHighlightItem() const; + QQuickItem *createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault = false) const; void updateCurrent(int modelIndex); void updateTrackedItem(); diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp index 6d2421c3df..83c451613e 100644 --- a/src/quick/items/qquickitemviewtransition.cpp +++ b/src/quick/items/qquickitemviewtransition.cpp @@ -246,7 +246,7 @@ void QQuickItemViewTransitioner::resetTargetLists() moveTransitionTargets.clear(); } -QQuickTransition *QQuickItemViewTransitioner::transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget) +QQuickTransition *QQuickItemViewTransitioner::transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const { if (type == QQuickItemViewTransitioner::NoTransition) return 0; diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h index ff0e82ac7b..3d2f5361b1 100644 --- a/src/quick/items/qquickitemviewtransition_p.h +++ b/src/quick/items/qquickitemviewtransition_p.h @@ -97,7 +97,7 @@ public: void addToTargetLists(QQuickItemViewTransitioner::TransitionType type, QQuickItemViewTransitionableItem *item, int index); void resetTargetLists(); - QQuickTransition *transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget); + QQuickTransition *transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const; const QList<int> &targetIndexes(QQuickItemViewTransitioner::TransitionType type) const; const QList<QObject *> &targetItems(QQuickItemViewTransitioner::TransitionType type) const; diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h index 8d0ad7f618..3a871e88e9 100644 --- a/src/quick/items/qquicklistview_p.h +++ b/src/quick/items/qquicklistview_p.h @@ -88,7 +88,7 @@ public: enum LabelPositioning { InlineLabels = 0x01, CurrentLabelAtStart = 0x02, NextLabelAtEnd = 0x04 }; Q_ENUM(LabelPositioning) - int labelPositioning() { return m_labelPositioning; } + int labelPositioning() const { return m_labelPositioning; } void setLabelPositioning(int pos); Q_SIGNALS: diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index a1e97b97d8..9b6267e011 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -94,7 +94,7 @@ public: void incubatorStateChanged(QQmlIncubator::Status status); void setInitialState(QObject *o); void disposeInitialPropertyValues(); - QUrl resolveSourceUrl(QQmlV4Function *args); + static QUrl resolveSourceUrl(QQmlV4Function *args); QV4::ReturnedValue extractInitialPropertyValues(QQmlV4Function *args, QObject *loader, bool *error); qreal getImplicitWidth() const Q_DECL_OVERRIDE; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 5e30bf9e0a..79c957832a 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -60,7 +60,8 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() : enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false), moved(false), stealMouse(false), doubleClick(false), preventStealing(false), - propagateComposedEvents(false), overThreshold(false), pressed(0) + propagateComposedEvents(false), overThreshold(false), pressed(0), + pressAndHoldInterval(-1) #if QT_CONFIG(draganddrop) , drag(0) #endif @@ -685,7 +686,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event) #endif setHovered(true); d->startScene = event->windowPos(); - d->pressAndHoldTimer.start(QGuiApplication::styleHints()->mousePressAndHoldInterval(), this); + d->pressAndHoldTimer.start(pressAndHoldInterval(), this); setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(event->button(), true, event->source())); } @@ -1294,6 +1295,48 @@ void QQuickMouseArea::setCursorShape(Qt::CursorShape shape) #endif + +/*! + \qmlproperty int QtQuick::MouseArea::pressAndHoldInterval + \since 5.9 + + This property overrides the elapsed time in milliseconds before + \c pressAndHold is emitted. + + If not explicitly set -- or after reset -- the value follows + \c QStyleHints::mousePressAndHoldInterval. + + Typically it's sufficient to set this property globally using the + application style hint. This property should be used when varying intervals + are needed for certain MouseAreas. + + \sa pressAndHold +*/ +int QQuickMouseArea::pressAndHoldInterval() const +{ + Q_D(const QQuickMouseArea); + return d->pressAndHoldInterval > -1 ? + d->pressAndHoldInterval : QGuiApplication::styleHints()->mousePressAndHoldInterval(); +} + +void QQuickMouseArea::setPressAndHoldInterval(int interval) +{ + Q_D(QQuickMouseArea); + if (interval != d->pressAndHoldInterval) { + d->pressAndHoldInterval = interval; + emit pressAndHoldIntervalChanged(); + } +} + +void QQuickMouseArea::resetPressAndHoldInterval() +{ + Q_D(QQuickMouseArea); + if (d->pressAndHoldInterval > -1) { + d->pressAndHoldInterval = -1; + emit pressAndHoldIntervalChanged(); + } +} + /*! \qmlpropertygroup QtQuick::MouseArea::drag \qmlproperty Item QtQuick::MouseArea::drag.target diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index d90c8e1baa..ee166a2082 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -84,6 +84,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged) #endif Q_PROPERTY(bool containsPress READ containsPress NOTIFY containsPressChanged REVISION 1) + Q_PROPERTY(int pressAndHoldInterval READ pressAndHoldInterval WRITE setPressAndHoldInterval NOTIFY pressAndHoldIntervalChanged RESET resetPressAndHoldInterval REVISION 9) public: QQuickMouseArea(QQuickItem *parent=0); @@ -125,6 +126,10 @@ public: void setCursorShape(Qt::CursorShape shape); #endif + int pressAndHoldInterval() const; + void setPressAndHoldInterval(int interval); + void resetPressAndHoldInterval(); + Q_SIGNALS: void hoveredChanged(); void pressedChanged(); @@ -152,6 +157,7 @@ Q_SIGNALS: void exited(); void canceled(); Q_REVISION(1) void containsPressChanged(); + Q_REVISION(9) void pressAndHoldIntervalChanged(); protected: void setHovered(bool); diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index 456b1866a3..2fa5f7cd44 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -95,6 +95,7 @@ public: bool propagateComposedEvents : 1; bool overThreshold : 1; Qt::MouseButtons pressed; + int pressAndHoldInterval; #if QT_CONFIG(draganddrop) QQuickDrag *drag; #endif diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp index b974641cca..42fcee3c0d 100644 --- a/src/quick/items/qquickopenglshadereffect.cpp +++ b/src/quick/items/qquickopenglshadereffect.cpp @@ -284,14 +284,14 @@ void QQuickOpenGLShaderEffectCommon::updateParseLog(bool ignoreAttributes) parseLog.clear(); if (!ignoreAttributes) { if (!attributes.contains(qtPositionAttributeName())) { - parseLog += QLatin1String("Warning: Missing reference to \'"); - parseLog += QLatin1String(qtPositionAttributeName()); - parseLog += QLatin1String("\'.\n"); + parseLog += QLatin1String("Warning: Missing reference to \'") + + QLatin1String(qtPositionAttributeName()) + + QLatin1String("\'.\n"); } if (!attributes.contains(qtTexCoordAttributeName())) { - parseLog += QLatin1String("Warning: Missing reference to \'"); - parseLog += QLatin1String(qtTexCoordAttributeName()); - parseLog += QLatin1String("\'.\n"); + parseLog += QLatin1String("Warning: Missing reference to \'") + + QLatin1String(qtTexCoordAttributeName()) + + QLatin1String("\'.\n"); } } bool respectsMatrix = false; @@ -918,9 +918,7 @@ QSGNode *QQuickOpenGLShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuic if (!mesh->validateAttributes(m_common.attributes, &posIndex)) { QString log = mesh->log(); if (!log.isNull()) { - m_log = parseLog(); - m_log += QLatin1String("*** Mesh ***\n"); - m_log += log; + m_log = parseLog() + QLatin1String("*** Mesh ***\n") + log; m_status = QQuickShaderEffect::Error; emit m_item->logChanged(); emit m_item->statusChanged(); diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp index 02b76b2dbc..2d2cffbeed 100644 --- a/src/quick/items/qquickopenglshadereffectnode.cpp +++ b/src/quick/items/qquickopenglshadereffectnode.cpp @@ -260,14 +260,12 @@ void QQuickCustomMaterialShader::compile() m_log.clear(); m_compiled = true; - if (!program()->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader())) { - m_log += QLatin1String("*** Vertex shader ***\n"); - m_log += program()->log(); + if (!program()->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader())) { + m_log += QLatin1String("*** Vertex shader ***\n") + program()->log(); m_compiled = false; } - if (!program()->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader())) { - m_log += QLatin1String("*** Fragment shader ***\n"); - m_log += program()->log(); + if (!program()->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader())) { + m_log += QLatin1String("*** Fragment shader ***\n") + program()->log(); m_compiled = false; } diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index c5155c9c35..3911bb0f28 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -53,7 +53,7 @@ class QQuickPaintedItemTextureProvider : public QSGTextureProvider { public: QSGPainterNode *node; - QSGTexture *texture() const { return node ? node->texture() : 0; } + QSGTexture *texture() const override { return node ? node->texture() : 0; } void fireTextureChanged() { emit textureChanged(); } }; diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index e54ee66fe5..11881ae0ab 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -63,13 +63,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcItemViewDelegateLifecycle) const qreal MinimumFlickVelocity = 75.0; -inline qreal qmlMod(qreal x, qreal y) -{ - using std::fmod; - return fmod(x, y); -} - -static QQmlOpenMetaObjectType *qPathViewAttachedType = 0; +static QQmlOpenMetaObjectType *qPathViewAttachedType = nullptr; QQuickPathViewAttached::QQuickPathViewAttached(QObject *parent) : QObject(parent), m_percent(-1), m_view(0), m_onPath(false), m_isCurrent(false) @@ -96,7 +90,7 @@ void QQuickPathViewAttached::setValue(const QByteArray &name, const QVariant &va } QQuickPathViewPrivate::QQuickPathViewPrivate() - : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0) + : path(nullptr), currentIndex(0), currentItemOffset(0.0), startPc(0) , offset(0.0), offsetAdj(0.0), mappedRange(1.0), mappedCache(0.0) , stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true) , autoHighlight(true), highlightUp(false), layoutScheduled(false) @@ -106,7 +100,7 @@ QQuickPathViewPrivate::QQuickPathViewPrivate() , moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0) , pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0) , moveReason(Other), movementDirection(QQuickPathView::Shortest), moveDirection(QQuickPathView::Shortest) - , attType(0), highlightComponent(0), highlightItem(0) + , attType(nullptr), highlightComponent(nullptr), highlightItem(nullptr) , moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition) , highlightPosition(0) , highlightRangeStart(0), highlightRangeEnd(0) @@ -163,7 +157,7 @@ void QQuickPathView::createdItem(int index, QObject *object) if (d->requestedIndex != index) { qPathViewAttachedType = d->attachedType(); QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item)); - qPathViewAttachedType = 0; + qPathViewAttachedType = nullptr; if (att) { att->m_view = this; att->setOnPath(false); @@ -186,7 +180,7 @@ void QQuickPathView::initItem(int index, QObject *object) item->setParentItem(this); qPathViewAttachedType = d->attachedType(); QQuickPathViewAttached *att = static_cast<QQuickPathViewAttached *>(qmlAttachedPropertiesObject<QQuickPathView>(item)); - qPathViewAttachedType = 0; + qPathViewAttachedType = nullptr; if (att) { att->m_view = this; qreal percent = d->positionOfIndex(index); @@ -215,7 +209,7 @@ void QQuickPathViewPrivate::releaseItem(QQuickItem *item) att->setOnPath(false); } else if (flags & QQmlInstanceModel::Destroyed) { // but we still reference it - item->setParentItem(0); + item->setParentItem(nullptr); } } @@ -244,7 +238,7 @@ void QQuickPathViewPrivate::clear() { if (currentItem) { releaseItem(currentItem); - currentItem = 0; + currentItem = nullptr; } for (QQuickItem *p : qAsConst(items)) releaseItem(p); @@ -280,13 +274,13 @@ qreal QQuickPathViewPrivate::positionOfIndex(qreal index) const || snapMode != QQuickPathView::NoSnap)) start = highlightRangeStart; qreal globalPos = index + offset; - globalPos = qmlMod(globalPos, qreal(modelCount)) / modelCount; + globalPos = std::fmod(globalPos, qreal(modelCount)) / modelCount; if (pathItems != -1 && pathItems < modelCount) { globalPos += start / mappedRange; - globalPos = qmlMod(globalPos, 1.0); + globalPos = std::fmod(globalPos, qreal(1.0)); pos = globalPos * mappedRange; } else { - pos = qmlMod(globalPos + start, 1.0); + pos = std::fmod(globalPos + start, qreal(1.0)); } } @@ -315,13 +309,13 @@ void QQuickPathViewPrivate::createHighlight() bool changed = false; if (highlightItem) { - highlightItem->setParentItem(0); + highlightItem->setParentItem(nullptr); highlightItem->deleteLater(); - highlightItem = 0; + highlightItem = nullptr; changed = true; } - QQuickItem *item = 0; + QQuickItem *item = nullptr; if (highlightComponent) { QQmlContext *creationContext = highlightComponent->creationContext(); QQmlContext *highlightContext = new QQmlContext( @@ -397,7 +391,7 @@ void QQuickPathViewPrivate::setHighlightPosition(qreal pos) qreal range = qreal(modelCount); // calc normalized position of highlight relative to offset - qreal relativeHighlight = qmlMod(pos + offset, range) / range; + qreal relativeHighlight = std::fmod(pos + offset, range) / range; if (!highlightUp && relativeHighlight > end / mappedRange) { qreal diff = 1.0 - relativeHighlight; @@ -636,7 +630,7 @@ void QQuickPathView::setModel(const QVariant &m) d->modelVariant = model; QObject *object = qvariant_cast<QObject*>(model); - QQmlInstanceModel *vim = 0; + QQmlInstanceModel *vim = nullptr; if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) { if (d->ownModel) { delete d->model; @@ -716,7 +710,7 @@ void QQuickPathView::setPath(QQuickPath *path) d->clear(); if (d->attType) { d->attType->release(); - d->attType = 0; + d->attType = nullptr; } d->regenerate(); } @@ -755,7 +749,7 @@ void QQuickPathView::setCurrentIndex(int idx) } int oldCurrentIdx = d->currentIndex; QQuickItem *oldCurrentItem = d->currentItem; - d->currentItem = 0; + d->currentItem = nullptr; d->moveReason = QQuickPathViewPrivate::SetIndex; d->currentIndex = idx; if (d->modelCount) { @@ -836,7 +830,7 @@ void QQuickPathViewPrivate::setOffset(qreal o) if (offset != o) { if (isValid() && q->isComponentComplete()) { qreal oldOffset = offset; - offset = qmlMod(o, qreal(modelCount)); + offset = std::fmod(o, qreal(modelCount)); if (offset < 0) offset += qreal(modelCount); qCDebug(lcItemViewDelegateLifecycle) << o << "was" << oldOffset << "now" << offset; @@ -902,7 +896,7 @@ void QQuickPathView::setHighlight(QQmlComponent *highlight) \sa highlight */ -QQuickItem *QQuickPathView::highlightItem() +QQuickItem *QQuickPathView::highlightItem() const { Q_D(const QQuickPathView); return d->highlightItem; @@ -1237,7 +1231,7 @@ QQmlComponent *QQuickPathView::delegate() const return dataModel->delegate(); } - return 0; + return nullptr; } void QQuickPathView::setDelegate(QQmlComponent *delegate) @@ -1468,7 +1462,7 @@ void QQuickPathView::positionViewAtIndex(int index, int mode) // Small offset since the last point coincides with the first and // this the only "end" position that gives the expected visual result. qreal adj = sizeof(qreal) == sizeof(float) ? 0.00001f : 0.000000000001; - endOffset = qmlMod(beginOffset + count, d->modelCount) - adj; + endOffset = std::fmod(beginOffset + count, qreal(d->modelCount)) - adj; } qreal offset = d->offset; switch (mode) { @@ -1489,8 +1483,8 @@ void QQuickPathView::positionViewAtIndex(int index, int mode) case Contain: if ((beginOffset < endOffset && (d->offset < beginOffset || d->offset > endOffset)) || (d->offset < beginOffset && d->offset > endOffset)) { - qreal diff1 = qmlMod(beginOffset - d->offset + d->modelCount, d->modelCount); - qreal diff2 = qmlMod(d->offset - endOffset + d->modelCount, d->modelCount); + qreal diff1 = std::fmod(beginOffset - d->offset + d->modelCount, qreal(d->modelCount)); + qreal diff2 = std::fmod(d->offset - endOffset + d->modelCount, qreal(d->modelCount)); if (diff1 < diff2) offset = beginOffset; else @@ -1518,7 +1512,7 @@ int QQuickPathView::indexAt(qreal x, qreal y) const { Q_D(const QQuickPathView); QQuickItem *item = itemAt(x, y); - return item ? d->model->indexOf(item, 0) : -1; + return item ? d->model->indexOf(item, nullptr) : -1; } /*! @@ -1533,7 +1527,7 @@ QQuickItem *QQuickPathView::itemAt(qreal x, qreal y) const { Q_D(const QQuickPathView); if (!d->isValid()) - return 0; + return nullptr; for (QQuickItem *item : d->items) { QPointF p = item->mapFromItem(this, QPointF(x, y)); @@ -1541,7 +1535,7 @@ QQuickItem *QQuickPathView::itemAt(qreal x, qreal y) const return item; } - return 0; + return nullptr; } QPointF QQuickPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const @@ -1606,7 +1600,7 @@ qreal QQuickPathViewPrivate::calcVelocity() const return velocity; } -qint64 QQuickPathViewPrivate::computeCurrentTime(QInputEvent *event) +qint64 QQuickPathViewPrivate::computeCurrentTime(QInputEvent *event) const { if (0 != event->timestamp()) return event->timestamp(); @@ -1810,7 +1804,7 @@ bool QQuickPathView::sendMouseEvent(QMouseEvent *event) QPointF localPos = mapFromScene(event->windowPos()); QQuickWindow *c = window(); - QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; + QQuickItem *grabber = c ? c->mouseGrabberItem() : nullptr; if (grabber == this && d->stealMouse) { // we are already the grabber and we do want the mouse event to ourselves. return true; @@ -1836,7 +1830,7 @@ bool QQuickPathView::sendMouseEvent(QMouseEvent *event) default: break; } - grabber = c ? c->mouseGrabberItem() : 0; + grabber = c ? c->mouseGrabberItem() : nullptr; if ((grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) || grabberDisabled) { grabMouse(); } @@ -1915,7 +1909,7 @@ void QQuickPathView::componentComplete() if (d->model) { d->modelCount = d->model->count(); if (d->modelCount && d->currentIndex != 0) // an initial value has been provided for currentIndex - d->offset = qmlMod(d->modelCount - currentIndexRemainder(d->currentIndex, d->modelCount), d->modelCount); + d->offset = std::fmod(qreal(d->modelCount - currentIndexRemainder(d->currentIndex, d->modelCount)), qreal(d->modelCount)); } d->createHighlight(); @@ -1951,7 +1945,7 @@ void QQuickPathView::refill() QList<QQuickItem*>::iterator it = d->items.begin(); while (it != d->items.end()) { QQuickItem *item = *it; - int idx = d->model->indexOf(item, 0); + int idx = d->model->indexOf(item, nullptr); qreal pos = d->positionOfIndex(idx); if (lcItemViewDelegateLifecycle().isDebugEnabled()) { QQuickText *text = qmlobject_cast<QQuickText*>(item); @@ -1996,7 +1990,7 @@ void QQuickPathView::refill() startPos = 2.0; for (QQuickItem * item : qAsConst(d->items)) { - int idx = d->model->indexOf(item, 0); + int idx = d->model->indexOf(item, nullptr); qreal curPos = d->positionOfIndex(idx); if (curPos > endPos) { endPos = curPos; @@ -2198,7 +2192,7 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) if (QQuickPathViewAttached *att = d->attached(d->currentItem)) att->setIsCurrentItem(true); d->releaseItem(d->currentItem); - d->currentItem = 0; + d->currentItem = nullptr; } d->currentIndex = qMin(r.index, d->modelCount - r.count - 1); currentChanged = true; @@ -2231,7 +2225,7 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) d->modelCount += i.count; } - d->offset = qmlMod(d->offset, d->modelCount); + d->offset = std::fmod(d->offset, qreal(d->modelCount)); if (d->offset < 0) d->offset += d->modelCount; if (d->currentIndex == -1) @@ -2249,7 +2243,7 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) d->tl.reset(d->moveOffset); } else { if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) { - d->offset = qmlMod(d->modelCount - d->currentIndex, d->modelCount); + d->offset = std::fmod(qreal(d->modelCount - d->currentIndex), qreal(d->modelCount)); changedOffset = true; } d->updateMappedRange(); @@ -2295,10 +2289,10 @@ int QQuickPathViewPrivate::calcCurrentIndex() { int current = 0; if (modelCount && model && items.count()) { - offset = qmlMod(offset, modelCount); + offset = std::fmod(offset, qreal(modelCount)); if (offset < 0) offset += modelCount; - current = qRound(qAbs(qmlMod(modelCount - offset, modelCount))); + current = qRound(qAbs(std::fmod(modelCount - offset, qreal(modelCount)))); current = current % modelCount; } @@ -2312,7 +2306,7 @@ void QQuickPathViewPrivate::createCurrentItem() bool inItems = false; for (QQuickItem *item : qAsConst(items)) { - if (model->indexOf(item, 0) == currentIndex) { + if (model->indexOf(item, nullptr) == currentIndex) { inItems = true; break; } @@ -2350,7 +2344,7 @@ void QQuickPathViewPrivate::updateCurrent() } int oldCurrentIndex = currentIndex; currentIndex = idx; - currentItem = 0; + currentItem = nullptr; createCurrentItem(); if (oldCurrentIndex != currentIndex) emit q->currentIndexChanged(); @@ -2383,7 +2377,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason) if (!model || modelCount <= 0) return; - qreal targetOffset = qmlMod(modelCount - index, modelCount); + qreal targetOffset = std::fmod(qreal(modelCount - index), qreal(modelCount)); if (offset == targetOffset) return; diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h index a44d1be5c4..669ef60ef7 100644 --- a/src/quick/items/qquickpathview_p.h +++ b/src/quick/items/qquickpathview_p.h @@ -102,7 +102,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathView : public QQuickItem Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged) public: - QQuickPathView(QQuickItem *parent=0); + QQuickPathView(QQuickItem *parent = nullptr); virtual ~QQuickPathView(); QVariant model() const; @@ -121,7 +121,7 @@ public: QQmlComponent *highlight() const; void setHighlight(QQmlComponent *highlight); - QQuickItem *highlightItem(); + QQuickItem *highlightItem() const; enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange }; Q_ENUM(HighlightRangeMode) @@ -259,7 +259,7 @@ public: QQuickPathViewAttached(QObject *parent); ~QQuickPathViewAttached(); - QQuickPathView *view() { return m_view; } + QQuickPathView *view() const { return m_view; } bool isCurrentItem() const { return m_isCurrent; } void setIsCurrentItem(bool c) { diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 64abe3d1dc..082f427f2c 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -129,7 +129,7 @@ public: QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const; void addVelocitySample(qreal v); qreal calcVelocity() const; - qint64 computeCurrentTime(QInputEvent *event); + qint64 computeCurrentTime(QInputEvent *event) const; void setDragging(bool d); QQuickPath *path; diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp index 5d01a2af9d..9347b55c70 100644 --- a/src/quick/items/qquickscreen.cpp +++ b/src/quick/items/qquickscreen.cpp @@ -207,100 +207,181 @@ QT_BEGIN_NAMESPACE By default it is set to the value of the QScreen that the window uses. */ -QQuickScreenAttached::QQuickScreenAttached(QObject* attachee) - : QObject(attachee) - , m_screen(NULL) - , m_window(NULL) - , m_updateMask(0) - , m_updateMaskSet(false) +QQuickScreenInfo::QQuickScreenInfo(QObject *parent) + : QObject(parent), + m_screen(nullptr) { - m_attachee = qobject_cast<QQuickItem*>(attachee); - - if (m_attachee) { - QQuickItemPrivate::get(m_attachee)->extra.value().screenAttached = this; - - if (m_attachee->window()) //It might not be assigned to a window yet - windowChanged(m_attachee->window()); - } else { - QQuickWindow *window = qobject_cast<QQuickWindow*>(attachee); - if (window) - windowChanged(window); - } - - if (!m_screen) - screenChanged(QGuiApplication::primaryScreen()); } -QString QQuickScreenAttached::name() const +QString QQuickScreenInfo::name() const { if (!m_screen) return QString(); return m_screen->name(); } -int QQuickScreenAttached::width() const +int QQuickScreenInfo::width() const { if (!m_screen) return 0; return m_screen->size().width(); } -int QQuickScreenAttached::height() const +int QQuickScreenInfo::height() const { if (!m_screen) return 0; return m_screen->size().height(); } -int QQuickScreenAttached::desktopAvailableWidth() const +int QQuickScreenInfo::desktopAvailableWidth() const { if (!m_screen) return 0; return m_screen->availableVirtualSize().width(); } -int QQuickScreenAttached::desktopAvailableHeight() const +int QQuickScreenInfo::desktopAvailableHeight() const { if (!m_screen) return 0; return m_screen->availableVirtualSize().height(); } -qreal QQuickScreenAttached::logicalPixelDensity() const +qreal QQuickScreenInfo::logicalPixelDensity() const { if (!m_screen) return 0.0; return m_screen->logicalDotsPerInch() / 25.4; } -qreal QQuickScreenAttached::pixelDensity() const +qreal QQuickScreenInfo::pixelDensity() const { if (!m_screen) return 0.0; return m_screen->physicalDotsPerInch() / 25.4; } -qreal QQuickScreenAttached::devicePixelRatio() const +qreal QQuickScreenInfo::devicePixelRatio() const { if (!m_screen) return 1.0; return m_screen->devicePixelRatio(); } -Qt::ScreenOrientation QQuickScreenAttached::primaryOrientation() const +Qt::ScreenOrientation QQuickScreenInfo::primaryOrientation() const { if (!m_screen) return Qt::PrimaryOrientation; return m_screen->primaryOrientation(); } -Qt::ScreenOrientation QQuickScreenAttached::orientation() const +Qt::ScreenOrientation QQuickScreenInfo::orientation() const { if (!m_screen) return Qt::PrimaryOrientation; return m_screen->orientation(); } +int QQuickScreenInfo::virtualX() const +{ + if (!m_screen) + return 0; + return m_screen->geometry().topLeft().x(); +} + +int QQuickScreenInfo::virtualY() const +{ + if (!m_screen) + return 0; + return m_screen->geometry().topLeft().y(); +} + +void QQuickScreenInfo::setWrappedScreen(QScreen *screen) +{ + if (screen == m_screen) + return; + + QScreen *oldScreen = m_screen; + m_screen = screen; + + if (oldScreen) + oldScreen->disconnect(this); + + if (!screen) //Don't bother emitting signals, because the new values are garbage anyways + return; + + if (!oldScreen || screen->geometry() != oldScreen->geometry()) { + emit virtualXChanged(); + emit virtualYChanged(); + } + if (!oldScreen || screen->size() != oldScreen->size()) { + emit widthChanged(); + emit heightChanged(); + } + if (!oldScreen || screen->name() != oldScreen->name()) + emit nameChanged(); + if (!oldScreen || screen->orientation() != oldScreen->orientation()) + emit orientationChanged(); + if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation()) + emit primaryOrientationChanged(); + if (!oldScreen || screen->availableVirtualGeometry() != oldScreen->availableVirtualGeometry()) + emit desktopGeometryChanged(); + if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch()) + emit logicalPixelDensityChanged(); + if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch()) + emit pixelDensityChanged(); + if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio()) + emit devicePixelRatioChanged(); + + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(widthChanged())); + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(heightChanged())); + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(virtualXChanged())); + connect(screen, SIGNAL(geometryChanged(QRect)), + this, SIGNAL(virtualYChanged())); + connect(screen, SIGNAL(orientationChanged(Qt::ScreenOrientation)), + this, SIGNAL(orientationChanged())); + connect(screen, SIGNAL(primaryOrientationChanged(Qt::ScreenOrientation)), + this, SIGNAL(primaryOrientationChanged())); + connect(screen, SIGNAL(virtualGeometryChanged(QRect)), + this, SIGNAL(desktopGeometryChanged())); + connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)), + this, SIGNAL(logicalPixelDensityChanged())); + connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)), + this, SIGNAL(pixelDensityChanged())); +} + +QScreen *QQuickScreenInfo::wrappedScreen() const +{ + return m_screen; +} + +QQuickScreenAttached::QQuickScreenAttached(QObject* attachee) + : QQuickScreenInfo(attachee) + , m_window(NULL) + , m_updateMask(0) + , m_updateMaskSet(false) +{ + m_attachee = qobject_cast<QQuickItem*>(attachee); + + if (m_attachee) { + QQuickItemPrivate::get(m_attachee)->extra.value().screenAttached = this; + + if (m_attachee->window()) //It might not be assigned to a window yet + windowChanged(m_attachee->window()); + } else { + QQuickWindow *window = qobject_cast<QQuickWindow*>(attachee); + if (window) + windowChanged(window); + } + + if (!m_screen) + screenChanged(QGuiApplication::primaryScreen()); +} + Qt::ScreenOrientations QQuickScreenAttached::orientationUpdateMask() const { return m_updateMask; @@ -341,55 +422,15 @@ void QQuickScreenAttached::screenChanged(QScreen *screen) { //qDebug() << "QQuickScreenAttached::screenChanged" << (screen ? screen->name() : QString::fromLatin1("null")); if (screen != m_screen) { - QScreen* oldScreen = m_screen; - m_screen = screen; - - if (oldScreen) - oldScreen->disconnect(this); - - if (!screen) - return; //Don't bother emitting signals, because the new values are garbage anyways - + setWrappedScreen(screen); + if (!m_screen) + return; if (m_updateMaskSet) { - screen->setOrientationUpdateMask(m_updateMask); - } else if (m_updateMask != screen->orientationUpdateMask()) { - m_updateMask = screen->orientationUpdateMask(); + m_screen->setOrientationUpdateMask(m_updateMask); + } else if (m_updateMask != m_screen->orientationUpdateMask()) { + m_updateMask = m_screen->orientationUpdateMask(); emit orientationUpdateMaskChanged(); } - - if (!oldScreen || screen->size() != oldScreen->size()) { - emit widthChanged(); - emit heightChanged(); - } - if (!oldScreen || screen->name() != oldScreen->name()) - emit nameChanged(); - if (!oldScreen || screen->orientation() != oldScreen->orientation()) - emit orientationChanged(); - if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation()) - emit primaryOrientationChanged(); - if (!oldScreen || screen->availableVirtualGeometry() != oldScreen->availableVirtualGeometry()) - emit desktopGeometryChanged(); - if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch()) - emit logicalPixelDensityChanged(); - if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch()) - emit pixelDensityChanged(); - if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio()) - emit devicePixelRatioChanged(); - - connect(screen, SIGNAL(geometryChanged(QRect)), - this, SIGNAL(widthChanged())); - connect(screen, SIGNAL(geometryChanged(QRect)), - this, SIGNAL(heightChanged())); - connect(screen, SIGNAL(orientationChanged(Qt::ScreenOrientation)), - this, SIGNAL(orientationChanged())); - connect(screen, SIGNAL(primaryOrientationChanged(Qt::ScreenOrientation)), - this, SIGNAL(primaryOrientationChanged())); - connect(screen, SIGNAL(virtualGeometryChanged(QRect)), - this, SIGNAL(desktopGeometryChanged())); - connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)), - this, SIGNAL(logicalPixelDensityChanged())); - connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)), - this, SIGNAL(pixelDensityChanged())); } } diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h index 06d9a06070..06efb3ab45 100644 --- a/src/quick/items/qquickscreen_p.h +++ b/src/quick/items/qquickscreen_p.h @@ -63,10 +63,10 @@ class QQuickItem; class QQuickWindow; class QScreen; -class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QObject + +class Q_AUTOTEST_EXPORT QQuickScreenInfo : public QObject { Q_OBJECT - Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(int width READ width NOTIFY widthChanged) Q_PROPERTY(int height READ height NOTIFY heightChanged) @@ -79,11 +79,12 @@ class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QObject Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY primaryOrientationChanged) // TODO Qt 6 Remove this orientation -> incomplete device orientation -> better use OrientationSensor Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged) - Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask - WRITE setOrientationUpdateMask NOTIFY orientationUpdateMaskChanged) + + Q_PROPERTY(int virtualX READ virtualX NOTIFY virtualXChanged REVISION 1) + Q_PROPERTY(int virtualY READ virtualY NOTIFY virtualYChanged REVISION 1) public: - QQuickScreenAttached(QObject* attachee); + QQuickScreenInfo(QObject *parent = nullptr); QString name() const; int width() const; @@ -95,13 +96,11 @@ public: qreal devicePixelRatio() const; Qt::ScreenOrientation primaryOrientation() const; Qt::ScreenOrientation orientation() const; - Qt::ScreenOrientations orientationUpdateMask() const; - void setOrientationUpdateMask(Qt::ScreenOrientations mask); + int virtualX() const; + int virtualY() const; - //Treats int as Qt::ScreenOrientation, due to QTBUG-20639 - Q_INVOKABLE int angleBetween(int a, int b); - - void windowChanged(QQuickWindow*); + void setWrappedScreen(QScreen *screen); + QScreen *wrappedScreen() const; Q_SIGNALS: void nameChanged(); @@ -113,13 +112,37 @@ Q_SIGNALS: void devicePixelRatioChanged(); void primaryOrientationChanged(); void orientationChanged(); + Q_REVISION(1) void virtualXChanged(); + Q_REVISION(1) void virtualYChanged(); + +protected: + QPointer<QScreen> m_screen; +}; + +class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QQuickScreenInfo +{ + Q_OBJECT + Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask + WRITE setOrientationUpdateMask NOTIFY orientationUpdateMaskChanged) + +public: + QQuickScreenAttached(QObject* attachee); + + Qt::ScreenOrientations orientationUpdateMask() const; + void setOrientationUpdateMask(Qt::ScreenOrientations mask); + + //Treats int as Qt::ScreenOrientation, due to QTBUG-20639 + Q_INVOKABLE int angleBetween(int a, int b); + + void windowChanged(QQuickWindow*); + +Q_SIGNALS: void orientationUpdateMaskChanged(); protected Q_SLOTS: void screenChanged(QScreen*); private: - QPointer<QScreen> m_screen; QQuickWindow* m_window; QQuickItem* m_attachee; Qt::ScreenOrientations m_updateMask; @@ -136,5 +159,6 @@ public: QT_END_NAMESPACE QML_DECLARE_TYPEINFO(QQuickScreen, QML_HAS_ATTACHED_PROPERTIES) +QML_DECLARE_TYPE(QQuickScreenInfo) #endif diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp index b572feb5ee..d23b576d42 100644 --- a/src/quick/items/qquickshadereffectmesh.cpp +++ b/src/quick/items/qquickshadereffectmesh.cpp @@ -95,9 +95,8 @@ bool QQuickGridMesh::validateAttributes(const QVector<QByteArray> &attributes, i return false; case 1: if (positionIndex != 0) { - m_log = QLatin1String("Error: Missing \'"); - m_log += QLatin1String(qtPositionAttributeName()); - m_log += QLatin1String("\' attribute.\n"); + m_log = QLatin1String("Error: Missing \'") + QLatin1String(qtPositionAttributeName()) + + QLatin1String("\' attribute.\n"); return false; } break; @@ -105,14 +104,12 @@ bool QQuickGridMesh::validateAttributes(const QVector<QByteArray> &attributes, i if (positionIndex == -1 || texCoordIndex == -1) { m_log.clear(); if (positionIndex == -1) { - m_log = QLatin1String("Error: Missing \'"); - m_log += QLatin1String(qtPositionAttributeName()); - m_log += QLatin1String("\' attribute.\n"); + m_log = QLatin1String("Error: Missing \'") + QLatin1String(qtPositionAttributeName()) + + QLatin1String("\' attribute.\n"); } if (texCoordIndex == -1) { - m_log += QLatin1String("Error: Missing \'"); - m_log += QLatin1String(qtTexCoordAttributeName()); - m_log += QLatin1String("\' attribute.\n"); + m_log += QLatin1String("Error: Missing \'") + QLatin1String(qtTexCoordAttributeName()) + + QLatin1String("\' attribute.\n"); } return false; } @@ -367,7 +364,7 @@ QSGGeometry *QQuickBorderImageMesh::updateGeometry(QSGGeometry *geometry, int at } \endqml */ -QQuickScaleGrid *QQuickBorderImageMesh::border() +QQuickScaleGrid *QQuickBorderImageMesh::border() const { return m_border; } diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h index cbf33b795f..aa3112b5a5 100644 --- a/src/quick/items/qquickshadereffectmesh_p.h +++ b/src/quick/items/qquickshadereffectmesh_p.h @@ -127,7 +127,7 @@ public: QSGGeometry *updateGeometry(QSGGeometry *geometry, int attrCount, int posIndex, const QRectF &srcRect, const QRectF &rect) override; - QQuickScaleGrid *border(); + QQuickScaleGrid *border() const; enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile }; Q_ENUM(TileMode) diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index a60a06f59a..1b37a746d3 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -64,7 +64,7 @@ public: { } - QSGTexture *texture() const { + QSGTexture *texture() const override { sourceTexture->setMipmapFiltering(mipmapFiltering); sourceTexture->setFiltering(filtering); sourceTexture->setHorizontalWrapMode(horizontalWrap); diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index b1905f2cc5..f54a8911b2 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -323,13 +323,13 @@ void QQuickStochasticEngine::setGoal(int state, int sprite, bool jump) return; } -QQuickPixmap::Status QQuickSpriteEngine::status()//Composed status of all Sprites +QQuickPixmap::Status QQuickSpriteEngine::status() const //Composed status of all Sprites { if (!m_startedImageAssembly) return QQuickPixmap::Null; int null, loading, ready; null = loading = ready = 0; - for (QQuickSprite* s : qAsConst(m_sprites)) { + for (QQuickSprite* s : m_sprites) { switch (s->m_pix.status()) { // ### Maybe add an error message here, because this null shouldn't be reached but when it does, the image fails without an error message. case QQuickPixmap::Null : null++; break; diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index 3b7fcfb1f1..90ee68b2f6 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -293,11 +293,11 @@ public: void advance(int index=0) Q_DECL_OVERRIDE; //Similar API to QQuickPixmap for async loading convenience - bool isNull() { return status() == QQuickPixmap::Null; } - bool isReady() { return status() == QQuickPixmap::Ready; } - bool isLoading() { return status() == QQuickPixmap::Loading; } - bool isError() { return status() == QQuickPixmap::Error; } - QQuickPixmap::Status status();//Composed status of all Sprites + bool isNull() const { return status() == QQuickPixmap::Null; } + bool isReady() const { return status() == QQuickPixmap::Ready; } + bool isLoading() const { return status() == QQuickPixmap::Loading; } + bool isError() const { return status() == QQuickPixmap::Error; } + QQuickPixmap::Status status() const; //Composed status of all Sprites void startAssemblingImage(); QImage assembledImage(int maxSize = 2048); diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp index 7e485c675c..9cd3b6a5f5 100644 --- a/src/quick/items/qquickstateoperations.cpp +++ b/src/quick/items/qquickstateoperations.cpp @@ -899,9 +899,9 @@ QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions() return ActionList() << a; } -QQuickAnchorSet *QQuickAnchorChanges::anchors() +QQuickAnchorSet *QQuickAnchorChanges::anchors() const { - Q_D(QQuickAnchorChanges); + Q_D(const QQuickAnchorChanges); return d->anchorSet; } @@ -1134,9 +1134,9 @@ QQuickStateActionEvent::EventType QQuickAnchorChanges::type() const return AnchorChanges; } -QList<QQuickStateAction> QQuickAnchorChanges::additionalActions() +QList<QQuickStateAction> QQuickAnchorChanges::additionalActions() const { - Q_D(QQuickAnchorChanges); + Q_D(const QQuickAnchorChanges); QList<QQuickStateAction> extra; QQuickAnchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors; diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h index 29dec218fa..48b4b23a76 100644 --- a/src/quick/items/qquickstateoperations_p.h +++ b/src/quick/items/qquickstateoperations_p.h @@ -192,7 +192,7 @@ public: ActionList actions() Q_DECL_OVERRIDE; - QQuickAnchorSet *anchors(); + QQuickAnchorSet *anchors() const; QQuickItem *object() const; void setObject(QQuickItem *); @@ -210,7 +210,7 @@ public: void rewind() Q_DECL_OVERRIDE; void saveCurrentValues() Q_DECL_OVERRIDE; - QList<QQuickStateAction> additionalActions(); + QList<QQuickStateAction> additionalActions() const; void saveTargetValues() Q_DECL_OVERRIDE; }; diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 66936b0943..555fd233b3 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -1660,8 +1660,8 @@ void QQuickTextControl::insertFromMimeData(const QMimeData *source) #if QT_CONFIG(texthtmlparser) if (source->hasFormat(QLatin1String("application/x-qrichtext")) && d->acceptRichText) { // x-qrichtext is always UTF-8 (taken from Qt3 since we don't use it anymore). - QString richtext = QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext"))); - richtext.prepend(QLatin1String("<meta name=\"qrichtext\" content=\"1\" />")); + const QString richtext = QLatin1String("<meta name=\"qrichtext\" content=\"1\" />") + + QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext"))); fragment = QTextDocumentFragment::fromHtml(richtext, d->doc); hasData = true; } else if (source->hasHtml() && d->acceptRichText) { diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h index 9bc5d057c7..70104a97e0 100644 --- a/src/quick/items/qquicktextcontrol_p.h +++ b/src/quick/items/qquicktextcontrol_p.h @@ -194,9 +194,11 @@ class QQuickTextEditMimeData : public QMimeData public: inline QQuickTextEditMimeData(const QTextDocumentFragment &aFragment) : fragment(aFragment) {} - virtual QStringList formats() const; + QStringList formats() const override; + protected: - virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const; + QVariant retrieveData(const QString &mimeType, QVariant::Type type) const override; + private: void setup() const; diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp index e7492b97ae..61d75fe99b 100644 --- a/src/quick/items/qquicktextdocument.cpp +++ b/src/quick/items/qquicktextdocument.cpp @@ -179,7 +179,7 @@ void QQuickTextDocumentWithImageResources::drawObject( { } -QImage QQuickTextDocumentWithImageResources::image(const QTextImageFormat &format) +QImage QQuickTextDocumentWithImageResources::image(const QTextImageFormat &format) const { QVariant res = resource(QTextDocument::ImageResource, QUrl(format.name())); return res.value<QImage>(); diff --git a/src/quick/items/qquicktextdocument_p.h b/src/quick/items/qquicktextdocument_p.h index 3ffedb5b96..1218b12b89 100644 --- a/src/quick/items/qquicktextdocument_p.h +++ b/src/quick/items/qquicktextdocument_p.h @@ -75,10 +75,10 @@ public: void setText(const QString &); int resourcesLoading() const { return outstanding; } - QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format); - void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format); + QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) override; + void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) override; - QImage image(const QTextImageFormat &format); + QImage image(const QTextImageFormat &format) const; public Q_SLOTS: void clearResources(); @@ -87,7 +87,7 @@ Q_SIGNALS: void imagesLoaded(); protected: - QVariant loadResource(int type, const QUrl &name); + QVariant loadResource(int type, const QUrl &name) override; QQuickPixmap *loadPixmap(QQmlContext *context, const QUrl &name); diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index b99e53b6c8..106acf57cf 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -2567,7 +2567,7 @@ void QQuickTextEditPrivate::updateDefaultTextOption() { Q_Q(QQuickTextEdit); QTextOption opt = document->defaultTextOption(); - int oldAlignment = opt.alignment(); + const Qt::Alignment oldAlignment = opt.alignment(); Qt::LayoutDirection oldTextDirection = opt.textDirection(); QQuickTextEdit::HAlignment horizontalAlignment = q->effectiveHAlign(); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index b3c7da1e3e..27f3dcecfa 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1994,7 +1994,7 @@ bool QQuickTextInput::isRightToLeft(int start, int end) qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start."; return false; } else { - return text().mid(start, end - start).isRightToLeft(); + return text().midRef(start, end - start).isRightToLeft(); } } @@ -2846,7 +2846,7 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate) // drawing boxes when using fonts that don't have glyphs for such // characters) QChar* uc = str.data(); - for (int i = 0; i < (int)str.length(); ++i) { + for (int i = 0; i < str.length(); ++i) { if ((uc[i].unicode() < 0x20 && uc[i] != QChar::Tabulation) || uc[i] == QChar::LineSeparator || uc[i] == QChar::ParagraphSeparator @@ -3232,7 +3232,7 @@ void QQuickTextInputPrivate::setSelection(int start, int length) commitPreedit(); #endif - if (start < 0 || start > (int)m_text.length()){ + if (start < 0 || start > m_text.length()) { qWarning("QQuickTextInputPrivate::setSelection: Invalid start position"); return; } @@ -3241,7 +3241,7 @@ void QQuickTextInputPrivate::setSelection(int start, int length) if (start == m_selstart && start + length == m_selend && m_cursor == m_selend) return; m_selstart = start; - m_selend = qMin(start + length, (int)m_text.length()); + m_selend = qMin(start + length, m_text.length()); m_cursor = m_selend; } else if (length < 0){ if (start == m_selend && start + length == m_selstart && m_cursor == m_selstart) @@ -3679,7 +3679,7 @@ void QQuickTextInputPrivate::internalInsert(const QString &s) Q_ASSERT(!hasSelectedText()); // insert(), processInputMethodEvent() call removeSelectedText() first. if (m_maskData) { QString ms = maskString(m_cursor, s); - for (int i = 0; i < (int) ms.length(); ++i) { + for (int i = 0; i < ms.length(); ++i) { addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1)); addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1)); } @@ -3690,9 +3690,10 @@ void QQuickTextInputPrivate::internalInsert(const QString &s) } else { int remaining = m_maxLength - m_text.length(); if (remaining != 0) { - m_text.insert(m_cursor, s.left(remaining)); - for (int i = 0; i < (int) s.leftRef(remaining).length(); ++i) - addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1)); + const QStringRef remainingStr = s.leftRef(remaining); + m_text.insert(m_cursor, remainingStr); + for (auto e : remainingStr) + addCommand(Command(Insert, m_cursor++, e, -1, -1)); m_textDirty = true; } } @@ -3711,7 +3712,7 @@ void QQuickTextInputPrivate::internalInsert(const QString &s) */ void QQuickTextInputPrivate::internalDelete(bool wasBackspace) { - if (m_cursor < (int) m_text.length()) { + if (m_cursor < m_text.length()) { cancelPasswordEchoTimer(); Q_ASSERT(!hasSelectedText()); // del(), backspace() call removeSelectedText() first. addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), @@ -3737,7 +3738,7 @@ void QQuickTextInputPrivate::internalDelete(bool wasBackspace) */ void QQuickTextInputPrivate::removeSelectedText() { - if (m_selstart < m_selend && m_selend <= (int) m_text.length()) { + if (m_selstart < m_selend && m_selend <= m_text.length()) { cancelPasswordEchoTimer(); int i ; if (m_selstart <= m_cursor && m_cursor < m_selend) { @@ -4023,44 +4024,44 @@ QString QQuickTextInputPrivate::maskString(uint pos, const QString &str, bool cl if (strIndex < str.length()) { if (m_maskData[i].separator) { s += m_maskData[i].maskChar; - if (str[(int)strIndex] == m_maskData[i].maskChar) + if (str[strIndex] == m_maskData[i].maskChar) strIndex++; ++i; } else { - if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) { + if (isValidInput(str[strIndex], m_maskData[i].maskChar)) { switch (m_maskData[i].caseMode) { case MaskInputData::Upper: - s += str[(int)strIndex].toUpper(); + s += str[strIndex].toUpper(); break; case MaskInputData::Lower: - s += str[(int)strIndex].toLower(); + s += str[strIndex].toLower(); break; default: - s += str[(int)strIndex]; + s += str[strIndex]; } ++i; } else { // search for separator first - int n = findInMask(i, true, true, str[(int)strIndex]); + int n = findInMask(i, true, true, str[strIndex]); if (n != -1) { - if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) { + if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[strIndex]))) { s += fill.midRef(i, n-i+1); i = n + 1; // update i to find + 1 } } else { // search for valid m_blank if not - n = findInMask(i, true, false, str[(int)strIndex]); + n = findInMask(i, true, false, str[strIndex]); if (n != -1) { s += fill.midRef(i, n-i); switch (m_maskData[n].caseMode) { case MaskInputData::Upper: - s += str[(int)strIndex].toUpper(); + s += str[strIndex].toUpper(); break; case MaskInputData::Lower: - s += str[(int)strIndex].toLower(); + s += str[strIndex].toLower(); break; default: - s += str[(int)strIndex]; + s += str[strIndex]; } i = n + 1; // updates i to find + 1 } @@ -4111,7 +4112,7 @@ QString QQuickTextInputPrivate::stripString(const QString &str) const return str; QString s; - int end = qMin(m_maxLength, (int)str.length()); + int end = qMin(m_maxLength, str.length()); for (int i = 0; i < end; ++i) { if (m_maskData[i].separator) s += m_maskData[i].maskChar; @@ -4201,7 +4202,7 @@ void QQuickTextInputPrivate::internalRedo() if (!isRedoAvailable()) return; internalDeselect(); - while (m_undoState < (int)m_history.size()) { + while (m_undoState < m_history.size()) { Command& cmd = m_history[m_undoState++]; switch (cmd.type) { case Insert: @@ -4228,7 +4229,7 @@ void QQuickTextInputPrivate::internalRedo() m_cursor = cmd.pos; break; } - if (m_undoState < (int)m_history.size()) { + if (m_undoState < m_history.size()) { Command& next = m_history[m_undoState]; if (next.type != cmd.type && cmd.type < RemoveSelection diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 155a52bd9b..07d87989b5 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -453,13 +453,15 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size) fboId = renderTargetId; renderer->setDeviceRect(rect); renderer->setViewportRect(rect); + renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), rect.size())); + renderer->setDevicePixelRatio(1); } else { QRect rect(QPoint(0, 0), devicePixelRatio * size); renderer->setDeviceRect(rect); renderer->setViewportRect(rect); + renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size)); + renderer->setDevicePixelRatio(devicePixelRatio); } - renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size)); - renderer->setDevicePixelRatio(devicePixelRatio); context->renderNextFrame(renderer, fboId); } @@ -1895,8 +1897,6 @@ void QQuickWindowPrivate::deliverDelayedTouchEvent() deliverPointerEvent(pointerEventInstance(e.data())); } -static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION"); - bool QQuickWindowPrivate::compressTouchEvent(QTouchEvent *event) { Q_Q(QQuickWindow); @@ -1973,6 +1973,8 @@ void QQuickWindowPrivate::handleTouchEvent(QTouchEvent *event) qCDebug(DBG_TOUCH) << event; + static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION"); + if (qquickwindow_no_touch_compression || pointerEventRecursionGuard) { deliverPointerEvent(pointerEventInstance(event)); return; @@ -2100,7 +2102,7 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents() There is a unique instance per QQuickPointerDevice, which is determined from \a event's device. */ -QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) +QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) const { QQuickPointerDevice *dev = nullptr; switch (event->type()) { @@ -4164,6 +4166,28 @@ void QQuickWindow::resetOpenGLState() */ /*! + \qmlproperty variant Window::targetScreen + + Specifies the screen the window should be placed on. Equivalent to + QWindow::setScreen(). + + The value must be an element from the Qt.application.screens array. + + By default the value is null which leads to using the primary screen. + + \note To ensure that the window is associated with the desired screen right + upon the underlying native window's initial creation, make sure this + property is set as early as possible and that the setting of its value is + not deferred. This can be particularly important on embedded platforms + without a windowing system, where only one window per screen is allowed at a + time. + + \since 5.9 + + \sa QWindow::setScreen(), QScreen, Qt.application + */ + +/*! \qmlproperty Item Window::activeFocusItem \since 5.1 diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index c1f690f325..27a73988ae 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -56,6 +56,7 @@ class QSGTexture; class QInputMethodEvent; class QQuickWindowPrivate; class QQuickWindowAttached; +class QOpenGLContext; class QOpenGLFramebufferObject; class QQmlIncubationController; class QInputMethodEvent; diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 829fe53458..be915903c6 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -163,7 +163,7 @@ public: void deliverDelayedTouchEvent(); // delivery of pointer events: - QQuickPointerEvent *pointerEventInstance(QEvent *ev); + QQuickPointerEvent *pointerEventInstance(QEvent *ev) const; void deliverPointerEvent(QQuickPointerEvent *); void deliverTouchEvent(QQuickPointerTouchEvent *); bool deliverTouchCancelEvent(QTouchEvent *); @@ -200,7 +200,7 @@ public: void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0); void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0); static void notifyFocusChangesRecur(QQuickItem **item, int remaining); - void clearFocusObject(); + void clearFocusObject() override; void updateFocusItemTransform(); diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index deb44ce34d..ea1fc2f106 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -59,6 +59,7 @@ public: : complete(false) , visible(false) , visibility(QQuickWindow::AutomaticVisibility) + , targetScreen(nullptr) { } @@ -66,6 +67,7 @@ public: bool visible; QQuickWindow::Visibility visibility; QV4::PersistentValue rootItemMarker; + QObject *targetScreen; }; QQuickWindowQmlImpl::QQuickWindowQmlImpl(QWindow *parent) @@ -170,6 +172,26 @@ void QQuickWindowQmlImpl::setWindowVisibility() } } +QObject *QQuickWindowQmlImpl::targetScreen() const +{ + Q_D(const QQuickWindowQmlImpl); + return d->targetScreen; +} + +void QQuickWindowQmlImpl::setTargetScreen(QObject *screen) +{ + Q_D(QQuickWindowQmlImpl); + if (d->targetScreen != screen) { + d->targetScreen = screen; + emit targetScreenChanged(); + QQuickScreenInfo *screenWrapper = qobject_cast<QQuickScreenInfo *>(screen); + if (screenWrapper) + setScreen(screenWrapper->wrappedScreen()); + else + setScreen(nullptr); + } +} + void QQuickWindowModule::defineModule() { const char uri[] = "QtQuick.Window"; @@ -181,7 +203,10 @@ void QQuickWindowModule::defineModule() qmlRegisterRevision<QQuickWindow,2>(uri, 2, 2); qmlRegisterType<QQuickWindowQmlImpl>(uri, 2, 1, "Window"); qmlRegisterType<QQuickWindowQmlImpl,1>(uri, 2, 2, "Window"); + qmlRegisterType<QQuickWindowQmlImpl,2>(uri, 2, 3, "Window"); qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property.")); + qmlRegisterUncreatableType<QQuickScreen,1>(uri, 2, 3, "Screen", QStringLiteral("Screen can only be used via the attached property.")); + qmlRegisterUncreatableType<QQuickScreenInfo,2>(uri, 2, 3, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property.")); } QT_END_NAMESPACE diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h index 8a6bbac412..7ca29880ea 100644 --- a/src/quick/items/qquickwindowmodule_p.h +++ b/src/quick/items/qquickwindowmodule_p.h @@ -67,6 +67,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickWindowQmlImpl : public QQuickWindow, public Q Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged) Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) + Q_PROPERTY(QObject *targetScreen READ targetScreen WRITE setTargetScreen NOTIFY targetScreenChanged REVISION 2) public: QQuickWindowQmlImpl(QWindow *parent = Q_NULLPTR); @@ -74,11 +75,15 @@ public: void setVisible(bool visible); void setVisibility(Visibility visibility); + QObject *targetScreen() const; + void setTargetScreen(QObject *screen); + static QQuickWindowAttached *qmlAttachedProperties(QObject *object); Q_SIGNALS: void visibleChanged(bool arg); void visibilityChanged(QWindow::Visibility visibility); + Q_REVISION(2) void targetScreenChanged(); protected: void classBegin() Q_DECL_OVERRIDE; diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp index 226e7bf219..c6b89fabd3 100644 --- a/src/quick/qtquick2.cpp +++ b/src/quick/qtquick2.cpp @@ -72,19 +72,19 @@ class QQmlQtQuick2DebugStatesDelegate : public QQmlDebugStatesDelegate { public: QQmlQtQuick2DebugStatesDelegate(); - virtual ~QQmlQtQuick2DebugStatesDelegate(); - virtual void buildStatesList(bool cleanList, const QList<QPointer<QObject> > &instances); - virtual void updateBinding(QQmlContext *context, - const QQmlProperty &property, - const QVariant &expression, bool isLiteralValue, - const QString &fileName, int line, int column, - bool *isBaseState); - virtual bool setBindingForInvalidProperty(QObject *object, - const QString &propertyName, - const QVariant &expression, - bool isLiteralValue); - virtual void resetBindingForInvalidProperty(QObject *object, - const QString &propertyName); + ~QQmlQtQuick2DebugStatesDelegate(); + void buildStatesList(bool cleanList, const QList<QPointer<QObject> > &instances) override; + void updateBinding(QQmlContext *context, + const QQmlProperty &property, + const QVariant &expression, bool isLiteralValue, + const QString &fileName, int line, int column, + bool *isBaseState) override; + bool setBindingForInvalidProperty(QObject *object, + const QString &propertyName, + const QVariant &expression, + bool isLiteralValue) override; + void resetBindingForInvalidProperty(QObject *object, + const QString &propertyName) override; private: void buildStatesList(QObject *obj); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp index 8ad9b50b09..92c02b4966 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp @@ -78,7 +78,7 @@ QSGRenderLoop *QSGSoftwareAdaptation::createWindowManager() static bool envChecked = false; if (!envChecked) { envChecked = true; - threaded = qgetenv("QSG_RENDER_LOOP") == QByteArrayLiteral("threaded"); + threaded = qgetenv("QSG_RENDER_LOOP") == "threaded"; } if (threaded) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index eb5bfca1ee..322192944b 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -561,7 +561,7 @@ public: void updateRootTransforms(Node *n); void updateRootTransforms(Node *n, Node *root, const QMatrix4x4 &combined); - void updateStates(QSGNode *n); + void updateStates(QSGNode *n) override; void visitNode(Node *n); void registerWithParentRoot(QSGNode *subRoot, QSGNode *parentRoot); diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index d2d27cd9aa..8d666d3d0b 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp @@ -364,8 +364,8 @@ void QSGMaterialShader::compile() { Q_ASSERT_X(!m_program.isLinked(), "QSGSMaterialShader::compile()", "Compile called multiple times!"); - program()->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader()); - program()->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader()); + program()->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader()); + program()->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader()); char const *const *attr = attributeNames(); #ifndef QT_NO_DEBUG diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h index f7ea6dbe23..1467f2233d 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.h +++ b/src/quick/scenegraph/coreapi/qsgnode.h @@ -325,7 +325,7 @@ public: void setCombinedOpacity(qreal opacity); qreal combinedOpacity() const { return m_combined_opacity; } - bool isSubtreeBlocked() const; + bool isSubtreeBlocked() const override; private: qreal m_opacity; diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h index 26e29d414d..4589685765 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h @@ -138,7 +138,7 @@ class QSGBindableFboId : public QSGBindable { public: QSGBindableFboId(GLuint); - virtual void bind() const; + void bind() const override; private: GLuint m_id; }; @@ -160,8 +160,8 @@ public: static void dump(QSGNode *n); QSGNodeDumper() : m_indent(0) {} - void visitNode(QSGNode *n); - void visitChildren(QSGNode *n); + void visitNode(QSGNode *n) override; + void visitChildren(QSGNode *n) override; private: int m_indent; diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp index d309044e8f..3b0b2faf97 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp @@ -77,6 +77,7 @@ QT_BEGIN_NAMESPACE \value Software The Qt Quick 2D Renderer is in use \value OpenGL OpenGL ES 2.0 or higher \value Direct3D12 Direct3D 12 + \value OpenVG OpenVG via EGL */ /*! diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.h b/src/quick/scenegraph/coreapi/qsgrendererinterface.h index cf8fcf9015..722488201b 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.h +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.h @@ -53,7 +53,8 @@ public: Unknown, Software, OpenGL, - Direct3D12 + Direct3D12, + OpenVG }; enum Resource { diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp index 3a35632d5c..48ab1aa52f 100644 --- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp +++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp @@ -193,13 +193,13 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat switch (profile) { case QSurfaceFormat::NoProfile: case QSurfaceFormat::CompatibilityProfile: - result += QByteArrayLiteral("attribute highp float _qt_order;\n"); - result += QByteArrayLiteral("uniform highp float _qt_zRange;\n"); + result += "attribute highp float _qt_order;\n" + "uniform highp float _qt_zRange;\n"; break; case QSurfaceFormat::CoreProfile: - result += QByteArrayLiteral("in float _qt_order;\n"); - result += QByteArrayLiteral("uniform float _qt_zRange;\n"); + result += "in float _qt_order;\n" + "uniform float _qt_zRange;\n"; break; } @@ -214,9 +214,9 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat case Tokenizer::Token_CloseBrace: braceDepth--; if (braceDepth == 0) { - result += QByteArray::fromRawData(voidPos, tok.pos - 1 - voidPos); - result += QByteArrayLiteral(" gl_Position.z = (gl_Position.z * _qt_zRange + _qt_order) * gl_Position.w;\n"); - result += QByteArray(tok.pos - 1); + result += QByteArray::fromRawData(voidPos, tok.pos - 1 - voidPos) + + " gl_Position.z = (gl_Position.z * _qt_zRange + _qt_order) * gl_Position.w;\n" + + QByteArray(tok.pos - 1); return result; } break; diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 5880c67af0..bf267ccf92 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -141,7 +141,7 @@ public: virtual void update() = 0; - virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } + void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } }; @@ -165,7 +165,7 @@ public: virtual void update() = 0; - virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } + void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } }; class Q_QUICK_PRIVATE_EXPORT QSGPainterNode : public QSGVisitableNode @@ -188,7 +188,7 @@ public: virtual void update() = 0; virtual QSGTexture *texture() const = 0; - virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } + void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } }; class Q_QUICK_EXPORT QSGLayer : public QSGDynamicTexture @@ -231,7 +231,7 @@ public: virtual void update() = 0; - virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } + void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } }; #endif @@ -389,7 +389,7 @@ public: void setOwnerElement(QQuickItem *ownerElement) { m_ownerElement = ownerElement; } QQuickItem *ownerElement() const { return m_ownerElement; } - virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } + void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } protected: QRectF m_bounding_rect; QQuickItem *m_ownerElement; diff --git a/src/quick/scenegraph/qsgbasicglyphnode_p.h b/src/quick/scenegraph/qsgbasicglyphnode_p.h index 1d09367ea5..0a43d17d2b 100644 --- a/src/quick/scenegraph/qsgbasicglyphnode_p.h +++ b/src/quick/scenegraph/qsgbasicglyphnode_p.h @@ -63,16 +63,16 @@ public: QSGBasicGlyphNode(); virtual ~QSGBasicGlyphNode(); - virtual QPointF baseLine() const { return m_baseLine; } - virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs); - virtual void setColor(const QColor &color); + QPointF baseLine() const override { return m_baseLine; } + void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) override; + void setColor(const QColor &color) override; - virtual void setPreferredAntialiasingMode(AntialiasingMode) { } - virtual void setStyle(QQuickText::TextStyle); - virtual void setStyleColor(const QColor &); + void setPreferredAntialiasingMode(AntialiasingMode) override { } + void setStyle(QQuickText::TextStyle) override; + void setStyleColor(const QColor &) override; virtual void setMaterialColor(const QColor &color) = 0; - virtual void update() = 0; + void update() override = 0; protected: QGlyphRun m_glyphs; diff --git a/src/quick/scenegraph/qsgcontextplugin_p.h b/src/quick/scenegraph/qsgcontextplugin_p.h index 08c3d21408..5914b42809 100644 --- a/src/quick/scenegraph/qsgcontextplugin_p.h +++ b/src/quick/scenegraph/qsgcontextplugin_p.h @@ -90,10 +90,10 @@ public: explicit QSGContextPlugin(QObject *parent = 0); virtual ~QSGContextPlugin(); - virtual QStringList keys() const = 0; + virtual QStringList keys() const override = 0; - virtual QQuickTextureFactory *createTextureFactoryFromImage(const QImage &) { return 0; } - virtual QSGRenderLoop *createWindowManager() { return 0; } + QQuickTextureFactory *createTextureFactoryFromImage(const QImage &) override { return 0; } + QSGRenderLoop *createWindowManager() override { return 0; } }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index eeea104e91..57dc4a5d07 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -72,10 +72,10 @@ public: QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font); virtual ~QSGDefaultDistanceFieldGlyphCache(); - void requestGlyphs(const QSet<glyph_t> &glyphs); - void storeGlyphs(const QList<QDistanceField> &glyphs); - void referenceGlyphs(const QSet<glyph_t> &glyphs); - void releaseGlyphs(const QSet<glyph_t> &glyphs); + void requestGlyphs(const QSet<glyph_t> &glyphs) override; + void storeGlyphs(const QList<QDistanceField> &glyphs) override; + void referenceGlyphs(const QSet<glyph_t> &glyphs) override; + void releaseGlyphs(const QSet<glyph_t> &glyphs) override; bool useTextureResizeWorkaround() const; bool useTextureUploadWorkaround() const; @@ -116,24 +116,16 @@ private: { m_blitProgram = new QOpenGLShaderProgram; { - QString source; - source.append(QLatin1String(qopenglslMainWithTexCoordsVertexShader)); - source.append(QLatin1String(qopenglslUntransformedPositionVertexShader)); + const QString source = QLatin1String(qopenglslMainWithTexCoordsVertexShader) + + QLatin1String(qopenglslUntransformedPositionVertexShader); - QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram); - vertexShader->compileSourceCode(source); - - m_blitProgram->addShader(vertexShader); + m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, source); } { - QString source; - source.append(QLatin1String(qopenglslMainFragmentShader)); - source.append(QLatin1String(qopenglslImageSrcFragmentShader)); - - QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram); - fragmentShader->compileSourceCode(source); + const QString source = QLatin1String(qopenglslMainFragmentShader) + + QLatin1String(qopenglslImageSrcFragmentShader); - m_blitProgram->addShader(fragmentShader); + m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, source); } m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h index caa7dfad07..b0a2788dd8 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h @@ -71,9 +71,9 @@ public: QSGTextMaskMaterial(const QRawFont &font, QFontEngine::GlyphFormat glyphFormat = QFontEngine::Format_None); virtual ~QSGTextMaskMaterial(); - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; - virtual int compare(const QSGMaterial *other) const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; + int compare(const QSGMaterial *other) const override; void setColor(const QColor &c) { m_color = QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF()); } void setColor(const QVector4D &color) { m_color = color; } @@ -115,10 +115,10 @@ public: void setStyleColor(const QVector4D &color) { m_styleColor = color; } const QVector4D &styleColor() const { return m_styleColor; } - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; - int compare(const QSGMaterial *other) const; + int compare(const QSGMaterial *other) const override; private: QVector2D m_styleShift; @@ -131,8 +131,8 @@ public: QSGOutlinedTextMaterial(const QRawFont &font); ~QSGOutlinedTextMaterial() { } - QSGMaterialType *type() const; - QSGMaterialShader *createShader() const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp index 1a17453baf..2c5b4ff5c8 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp +++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp @@ -262,8 +262,8 @@ void QSGDefaultRenderContext::compileShader(QSGMaterialShader *shader, QSGMateri "QSGRenderContext::compile()", "materials with custom compile step cannot have custom vertex/fragment code"); QOpenGLShaderProgram *p = shader->program(); - p->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexCode ? vertexCode : shader->vertexShader()); - p->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentCode ? fragmentCode : shader->fragmentShader()); + p->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexCode ? vertexCode : shader->vertexShader()); + p->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentCode ? fragmentCode : shader->fragmentShader()); p->link(); if (!p->isLinked()) qWarning() << "shader compilation failed:" << endl << p->log(); diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h index 22c68558ef..c0c6bda718 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h @@ -67,19 +67,19 @@ public: QSGDistanceFieldGlyphNode(QSGRenderContext *context); ~QSGDistanceFieldGlyphNode(); - virtual QPointF baseLine() const { return m_baseLine; } - virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs); - virtual void setColor(const QColor &color); + QPointF baseLine() const override { return m_baseLine; } + void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) override; + void setColor(const QColor &color) override; - virtual void setPreferredAntialiasingMode(AntialiasingMode mode); + void setPreferredAntialiasingMode(AntialiasingMode mode) override; - virtual void setStyle(QQuickText::TextStyle style); - virtual void setStyleColor(const QColor &color); + void setStyle(QQuickText::TextStyle style) override; + void setStyleColor(const QColor &color) override; - virtual void update(); - void preprocess(); + void update() override; + void preprocess() override; - void invalidateGlyphs(const QVector<quint32> &glyphs); + void invalidateGlyphs(const QVector<quint32> &glyphs) override; void updateGeometry(); diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h index 38dcf3d307..c13a0898eb 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h @@ -63,9 +63,9 @@ public: QSGDistanceFieldTextMaterial(); ~QSGDistanceFieldTextMaterial(); - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; - virtual int compare(const QSGMaterial *other) const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; + int compare(const QSGMaterial *other) const override; virtual void setColor(const QColor &color); const QVector4D &color() const { return m_color; } @@ -97,9 +97,9 @@ public: QSGDistanceFieldStyledTextMaterial(); ~QSGDistanceFieldStyledTextMaterial(); - virtual QSGMaterialType *type() const = 0; - virtual QSGMaterialShader *createShader() const = 0; - virtual int compare(const QSGMaterial *other) const; + QSGMaterialType *type() const override = 0; + QSGMaterialShader *createShader() const override = 0; + int compare(const QSGMaterial *other) const override; void setStyleColor(const QColor &color); const QVector4D &styleColor() const { return m_styleColor; } @@ -114,8 +114,8 @@ public: QSGDistanceFieldOutlineTextMaterial(); ~QSGDistanceFieldOutlineTextMaterial(); - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; }; class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldShiftedStyleTextMaterial : public QSGDistanceFieldStyledTextMaterial @@ -124,9 +124,9 @@ public: QSGDistanceFieldShiftedStyleTextMaterial(); ~QSGDistanceFieldShiftedStyleTextMaterial(); - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; - virtual int compare(const QSGMaterial *other) const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; + int compare(const QSGMaterial *other) const override; void setShift(const QPointF &shift) { m_shift = shift; } const QPointF &shift() const { return m_shift; } @@ -138,17 +138,17 @@ protected: class Q_QUICK_PRIVATE_EXPORT QSGHiQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial { public: - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; - void setColor(const QColor &color) { m_color = QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); } + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; + void setColor(const QColor &color) override { m_color = QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); } }; class Q_QUICK_PRIVATE_EXPORT QSGLoQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial { public: - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; - void setColor(const QColor &color) { m_color = QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); } + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; + void setColor(const QColor &color) override { m_color = QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); } }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index ec874f6ff0..48288bfc62 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -211,11 +211,11 @@ QSGRenderLoop *QSGRenderLoop::instance() if (Q_UNLIKELY(qEnvironmentVariableIsSet("QSG_RENDER_LOOP"))) { const QByteArray loopName = qgetenv("QSG_RENDER_LOOP"); - if (loopName == QByteArrayLiteral("windows")) + if (loopName == "windows") loopType = WindowsRenderLoop; - else if (loopName == QByteArrayLiteral("basic")) + else if (loopName == "basic") loopType = BasicRenderLoop; - else if (loopName == QByteArrayLiteral("threaded")) + else if (loopName == "threaded") loopType = ThreadedRenderLoop; } diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index 0ab83b444a..32bfcb7148 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -68,29 +68,29 @@ public: QSGThreadedRenderLoop(); ~QSGThreadedRenderLoop(); - void show(QQuickWindow *) {} - void hide(QQuickWindow *); + void show(QQuickWindow *) override {} + void hide(QQuickWindow *) override; - void windowDestroyed(QQuickWindow *window); - void exposureChanged(QQuickWindow *window); + void windowDestroyed(QQuickWindow *window) override; + void exposureChanged(QQuickWindow *window) override; - QImage grab(QQuickWindow *); + QImage grab(QQuickWindow *) override; - void update(QQuickWindow *window); - void maybeUpdate(QQuickWindow *window); - void handleUpdateRequest(QQuickWindow *window); + void update(QQuickWindow *window) override; + void maybeUpdate(QQuickWindow *window) override; + void handleUpdateRequest(QQuickWindow *window) override; - QSGContext *sceneGraphContext() const; - QSGRenderContext *createRenderContext(QSGContext *) const; + QSGContext *sceneGraphContext() const override; + QSGRenderContext *createRenderContext(QSGContext *) const override; - QAnimationDriver *animationDriver() const; + QAnimationDriver *animationDriver() const override; - void releaseResources(QQuickWindow *window); + void releaseResources(QQuickWindow *window) override; - bool event(QEvent *); - void postJob(QQuickWindow *window, QRunnable *job); + bool event(QEvent *) override; + void postJob(QQuickWindow *window, QRunnable *job) override; - bool interleaveIncubation() const; + bool interleaveIncubation() const override; public Q_SLOTS: void animationStarted(); diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index 13388c0841..e944ddbc4f 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -84,18 +84,17 @@ QSGWindowsRenderLoop::QSGWindowsRenderLoop() { m_rc = static_cast<QSGDefaultRenderContext *>(m_sg->createRenderContext()); - m_animationDriver = m_sg->createAnimationDriver(m_sg); - m_animationDriver->install(); - - connect(m_animationDriver, SIGNAL(started()), this, SLOT(started())); - connect(m_animationDriver, SIGNAL(stopped()), this, SLOT(stopped())); - m_vsyncDelta = 1000 / QGuiApplication::primaryScreen()->refreshRate(); if (m_vsyncDelta <= 0) m_vsyncDelta = 16; RLDEBUG("Windows Render Loop created"); + m_animationDriver = m_sg->createAnimationDriver(m_sg); + connect(m_animationDriver, SIGNAL(started()), this, SLOT(started())); + connect(m_animationDriver, SIGNAL(stopped()), this, SLOT(stopped())); + m_animationDriver->install(); + qsg_render_timer.start(); } diff --git a/src/quick/scenegraph/qsgwindowsrenderloop_p.h b/src/quick/scenegraph/qsgwindowsrenderloop_p.h index 9e5d7f04d3..1940a66af2 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop_p.h +++ b/src/quick/scenegraph/qsgwindowsrenderloop_p.h @@ -70,31 +70,31 @@ public: explicit QSGWindowsRenderLoop(); ~QSGWindowsRenderLoop(); - void show(QQuickWindow *window); - void hide(QQuickWindow *window); + void show(QQuickWindow *window) override; + void hide(QQuickWindow *window) override; - void windowDestroyed(QQuickWindow *window); + void windowDestroyed(QQuickWindow *window) override; - void exposureChanged(QQuickWindow *window); - QImage grab(QQuickWindow *window); + void exposureChanged(QQuickWindow *window) override; + QImage grab(QQuickWindow *window) override; - void update(QQuickWindow *window); - void maybeUpdate(QQuickWindow *window); + void update(QQuickWindow *window) override; + void maybeUpdate(QQuickWindow *window) override; - QAnimationDriver *animationDriver() const { return m_animationDriver; } + QAnimationDriver *animationDriver() const override { return m_animationDriver; } - QSGContext *sceneGraphContext() const { return m_sg; } - QSGRenderContext *createRenderContext(QSGContext *) const; + QSGContext *sceneGraphContext() const override { return m_sg; } + QSGRenderContext *createRenderContext(QSGContext *) const override; - void releaseResources(QQuickWindow *) { } + void releaseResources(QQuickWindow *) override { } void render(); void renderWindow(QQuickWindow *window); - bool event(QEvent *event); + bool event(QEvent *event) override; bool anyoneShowing() const; - bool interleaveIncubation() const; + bool interleaveIncubation() const override; public Q_SLOTS: void started(); diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h index cd24645fcf..3dee539547 100644 --- a/src/quick/scenegraph/util/qsgatlastexture_p.h +++ b/src/quick/scenegraph/util/qsgatlastexture_p.h @@ -131,26 +131,26 @@ public: Texture(Atlas *atlas, const QRect &textureRect, const QImage &image); ~Texture(); - int textureId() const { return m_atlas->textureId(); } - QSize textureSize() const { return atlasSubRectWithoutPadding().size(); } + int textureId() const override { return m_atlas->textureId(); } + QSize textureSize() const override { return atlasSubRectWithoutPadding().size(); } void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; } - bool hasAlphaChannel() const { return m_has_alpha; } - bool hasMipmaps() const { return false; } - bool isAtlasTexture() const { return true; } + bool hasAlphaChannel() const override { return m_has_alpha; } + bool hasMipmaps() const override { return false; } + bool isAtlasTexture() const override { return true; } - QRectF normalizedTextureSubRect() const { return m_texture_coords_rect; } + QRectF normalizedTextureSubRect() const override { return m_texture_coords_rect; } QRect atlasSubRect() const { return m_allocated_rect; } QRect atlasSubRectWithoutPadding() const { return m_allocated_rect.adjusted(1, 1, -1, -1); } bool isTexture() const { return true; } - QSGTexture *removedFromAtlas() const; + QSGTexture *removedFromAtlas() const override; void releaseImage() { m_image = QImage(); } const QImage &image() const { return m_image; } - void bind(); + void bind() override; private: QRect m_allocated_rect; diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h index 7488f7878d..084fc1e004 100644 --- a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h +++ b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h @@ -72,7 +72,7 @@ public: void setDirtyRect(const QRect &rect) { m_dirty_rect = rect; } - void bind(); + void bind() override; private: QRect m_dirty_rect; @@ -84,43 +84,43 @@ public: QSGDefaultPainterNode(QQuickPaintedItem *item); virtual ~QSGDefaultPainterNode(); - void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target); + void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) override; - void setSize(const QSize &size); + void setSize(const QSize &size) override; QSize size() const { return m_size; } - void setDirty(const QRect &dirtyRect = QRect()); + void setDirty(const QRect &dirtyRect = QRect()) override; - void setOpaquePainting(bool opaque); + void setOpaquePainting(bool opaque) override; bool opaquePainting() const { return m_opaquePainting; } - void setLinearFiltering(bool linearFiltering); + void setLinearFiltering(bool linearFiltering) override; bool linearFiltering() const { return m_linear_filtering; } - void setMipmapping(bool mipmapping); + void setMipmapping(bool mipmapping) override; bool mipmapping() const { return m_mipmapping; } - void setSmoothPainting(bool s); + void setSmoothPainting(bool s) override; bool smoothPainting() const { return m_smoothPainting; } - void setFillColor(const QColor &c); + void setFillColor(const QColor &c) override; QColor fillColor() const { return m_fillColor; } - void setContentsScale(qreal s); + void setContentsScale(qreal s) override; qreal contentsScale() const { return m_contentsScale; } - void setFastFBOResizing(bool fastResizing); + void setFastFBOResizing(bool fastResizing) override; bool fastFBOResizing() const { return m_fastFBOResizing; } - void setTextureSize(const QSize &textureSize); + void setTextureSize(const QSize &textureSize) override; QSize textureSize() const { return m_textureSize; } - QImage toImage() const; - void update(); + QImage toImage() const override; + void update() override; void paint(); - QSGTexture *texture() const { return m_texture; } + QSGTexture *texture() const override { return m_texture; } private: void updateTexture(); diff --git a/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h b/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h index c2d0590532..f7c6923021 100644 --- a/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h +++ b/src/quick/scenegraph/util/qsgdepthstencilbuffer_p.h @@ -119,7 +119,7 @@ public: virtual ~QSGDefaultDepthStencilBuffer(); protected: - virtual void free(); + void free() override; }; diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.h b/src/quick/scenegraph/util/qsgflatcolormaterial.h index 7f292a2a9b..4829ac3279 100644 --- a/src/quick/scenegraph/util/qsgflatcolormaterial.h +++ b/src/quick/scenegraph/util/qsgflatcolormaterial.h @@ -49,13 +49,13 @@ class Q_QUICK_EXPORT QSGFlatColorMaterial : public QSGMaterial { public: QSGFlatColorMaterial(); - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; void setColor(const QColor &color); const QColor &color() const { return m_color; } - int compare(const QSGMaterial *other) const; + int compare(const QSGMaterial *other) const override; private: QColor m_color; diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp index caa296451e..d8f92919cb 100644 --- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp @@ -217,11 +217,11 @@ void QSGShaderSourceBuilder::initializeProgramFromFiles(QOpenGLShaderProgram *pr QSGShaderSourceBuilder builder; builder.appendSourceFile(vertexShader); - program->addShaderFromSourceCode(QOpenGLShader::Vertex, builder.source()); + program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, builder.source()); builder.clear(); builder.appendSourceFile(fragmentShader); - program->addShaderFromSourceCode(QOpenGLShader::Fragment, builder.source()); + program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, builder.source()); } QByteArray QSGShaderSourceBuilder::source() const @@ -310,13 +310,10 @@ void QSGShaderSourceBuilder::addDefinition(const QByteArray &definition) const char *insertionPos = extensionPos ? extensionPos : (versionPos ? versionPos : input); // Construct a new shader string, inserting the definition - QByteArray newSource; - newSource.reserve(m_source.size() + definition.size() + 9); - newSource += QByteArray::fromRawData(input, insertionPos - input); - newSource += QByteArrayLiteral("#define ") + definition + QByteArrayLiteral("\n"); - newSource += QByteArray::fromRawData(insertionPos, m_source.size() - (insertionPos - input)); - - m_source = newSource; + QByteArray newSource = QByteArray::fromRawData(input, insertionPos - input) + + "#define " + definition + '\n' + + QByteArray::fromRawData(insertionPos, m_source.size() - (insertionPos - input)); + m_source = std::move(newSource); } void QSGShaderSourceBuilder::removeVersion() diff --git a/src/quick/scenegraph/util/qsgsimplematerial.h b/src/quick/scenegraph/util/qsgsimplematerial.h index 8f42599832..0e7219d7bd 100644 --- a/src/quick/scenegraph/util/qsgsimplematerial.h +++ b/src/quick/scenegraph/util/qsgsimplematerial.h @@ -48,7 +48,7 @@ template <typename State> class QSGSimpleMaterialShader : public QSGMaterialShader { public: - void initialize() { + void initialize() override { QSGMaterialShader::initialize(); #if QT_CONFIG(opengl) m_id_matrix = program()->uniformLocation(uniformMatrixName()); @@ -74,7 +74,7 @@ public: const char *uniformMatrixName() const { return "qt_Matrix"; } const char *uniformOpacityName() const { return "qt_Opacity"; } - void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); + void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; virtual void updateState(const State *newState, const State *oldState) = 0; @@ -82,7 +82,7 @@ public: virtual QList<QByteArray> attributes() const = 0; - char const *const *attributeNames() const + char const *const *attributeNames() const override { if (m_attribute_pointers.size()) return m_attribute_pointers.constData(); @@ -149,8 +149,8 @@ public: { } - QSGMaterialShader *createShader() const { return m_func(); } - QSGMaterialType *type() const { return &m_type; } + QSGMaterialShader *createShader() const override { return m_func(); } + QSGMaterialType *type() const override { return &m_type; } State *state() { return &m_state; } const State *state() const { return &m_state; } diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h index 13c862eb88..b6fcfc31c4 100644 --- a/src/quick/scenegraph/util/qsgtexture_p.h +++ b/src/quick/scenegraph/util/qsgtexture_p.h @@ -87,19 +87,19 @@ public: bool ownsTexture() const { return m_owns_texture; } void setTextureId(int id); - int textureId() const; + int textureId() const override; void setTextureSize(const QSize &size) { m_texture_size = size; } - QSize textureSize() const { return m_texture_size; } + QSize textureSize() const override { return m_texture_size; } void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; } - bool hasAlphaChannel() const { return m_has_alpha; } + bool hasAlphaChannel() const override { return m_has_alpha; } - bool hasMipmaps() const { return mipmapFiltering() != QSGTexture::None; } + bool hasMipmaps() const override { return mipmapFiltering() != QSGTexture::None; } void setImage(const QImage &image); const QImage &image() { return m_image; } - virtual void bind(); + void bind() override; static QSGPlainTexture *fromImage(const QImage &image) { QSGPlainTexture *t = new QSGPlainTexture(); diff --git a/src/quick/scenegraph/util/qsgtexturematerial.h b/src/quick/scenegraph/util/qsgtexturematerial.h index 02b59108b3..dc87131773 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.h +++ b/src/quick/scenegraph/util/qsgtexturematerial.h @@ -50,9 +50,9 @@ class Q_QUICK_EXPORT QSGOpaqueTextureMaterial : public QSGMaterial public: QSGOpaqueTextureMaterial(); - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; - virtual int compare(const QSGMaterial *other) const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; + int compare(const QSGMaterial *other) const override; void setTexture(QSGTexture *texture); QSGTexture *texture() const { return m_texture; } @@ -84,8 +84,8 @@ protected: class Q_QUICK_EXPORT QSGTextureMaterial : public QSGOpaqueTextureMaterial { public: - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgtexturematerial_p.h b/src/quick/scenegraph/util/qsgtexturematerial_p.h index 75e5877a72..093d820801 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial_p.h +++ b/src/quick/scenegraph/util/qsgtexturematerial_p.h @@ -61,13 +61,13 @@ class Q_QUICK_PRIVATE_EXPORT QSGOpaqueTextureMaterialShader : public QSGMaterial public: QSGOpaqueTextureMaterialShader(); - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect); - virtual char const *const *attributeNames() const; + void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; + char const *const *attributeNames() const override; static QSGMaterialType type; protected: - virtual void initialize(); + void initialize() override; int m_matrix_id; }; @@ -77,8 +77,8 @@ class QSGTextureMaterialShader : public QSGOpaqueTextureMaterialShader public: QSGTextureMaterialShader(); - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect); - virtual void initialize(); + void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override; + void initialize() override; static QSGMaterialType type; diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.h b/src/quick/scenegraph/util/qsgvertexcolormaterial.h index 68f32d8af0..65cb642d92 100644 --- a/src/quick/scenegraph/util/qsgvertexcolormaterial.h +++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.h @@ -49,11 +49,11 @@ class Q_QUICK_EXPORT QSGVertexColorMaterial : public QSGMaterial public: QSGVertexColorMaterial(); - int compare(const QSGMaterial *other) const; + int compare(const QSGMaterial *other) const override; protected: - virtual QSGMaterialType *type() const; - virtual QSGMaterialShader *createShader() const; + QSGMaterialType *type() const override; + QSGMaterialShader *createShader() const override; }; QT_END_NAMESPACE diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index 206b92eb81..9de474ac36 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -1198,14 +1198,14 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti struct QQuickSetPropertyAnimationAction : public QAbstractAnimationAction { QQuickStateActions actions; - virtual void doAction() + void doAction() override { for (int ii = 0; ii < actions.count(); ++ii) { const QQuickStateAction &action = actions.at(ii); QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding); } } - virtual void debugAction(QDebug d, int indentLevel) const { + void debugAction(QDebug d, int indentLevel) const override { QByteArray ind(indentLevel, ' '); for (int ii = 0; ii < actions.count(); ++ii) { const QQuickStateAction &action = actions.at(ii); diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h index 145f2656d2..e27871dcaa 100644 --- a/src/quick/util/qquickanimation_p.h +++ b/src/quick/util/qquickanimation_p.h @@ -114,8 +114,8 @@ public: void setDisableUserControl(); void setEnableUserControl(); bool userControlDisabled() const; - void classBegin(); - void componentComplete(); + void classBegin() override; + void componentComplete() override; virtual ThreadingModel threadingModel() const; @@ -150,7 +150,7 @@ public: private Q_SLOTS: void componentFinalized(); private: - virtual void setTarget(const QQmlProperty &); + void setTarget(const QQmlProperty &) override; void notifyRunningChanged(bool running); friend class QQuickBehavior; friend class QQuickBehaviorPrivate; @@ -179,7 +179,7 @@ protected: QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; }; class QQuickScriptActionPrivate; @@ -202,10 +202,10 @@ public: void setStateChangeScriptName(const QString &); protected: - virtual QAbstractAnimationJob* transition(QQuickStateActions &actions, + QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; }; class QQuickPropertyActionPrivate; @@ -247,10 +247,10 @@ Q_SIGNALS: void propertyChanged(); protected: - virtual QAbstractAnimationJob* transition(QQuickStateActions &actions, + QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; }; class QQuickPropertyAnimationPrivate; @@ -303,10 +303,10 @@ protected: QObject *defaultTarget = 0); QQuickPropertyAnimation(QQuickPropertyAnimationPrivate &dd, QObject *parent); - virtual QAbstractAnimationJob* transition(QQuickStateActions &actions, + QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; Q_SIGNALS: void durationChanged(int); void fromChanged(const QVariant &); @@ -438,11 +438,11 @@ public: virtual ~QQuickSequentialAnimation(); protected: - virtual ThreadingModel threadingModel() const; - virtual QAbstractAnimationJob* transition(QQuickStateActions &actions, + ThreadingModel threadingModel() const override; + QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; }; class Q_QUICK_PRIVATE_EXPORT QQuickParallelAnimation : public QQuickAnimationGroup @@ -455,11 +455,11 @@ public: virtual ~QQuickParallelAnimation(); protected: - virtual ThreadingModel threadingModel() const; - virtual QAbstractAnimationJob* transition(QQuickStateActions &actions, + ThreadingModel threadingModel() const override; + QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; }; diff --git a/src/quick/util/qquickanimation_p_p.h b/src/quick/util/qquickanimation_p_p.h index ea7bf62171..a7abc5a004 100644 --- a/src/quick/util/qquickanimation_p_p.h +++ b/src/quick/util/qquickanimation_p_p.h @@ -88,8 +88,8 @@ class QAnimationActionProxy : public QAbstractAnimationAction { public: QAnimationActionProxy(T *instance) : m_instance(instance) {} - virtual void doAction() { (m_instance->*method)(); } - virtual void debugAction(QDebug d, int indentLevel) const { (m_instance->*debugMethod)(d, indentLevel); } + void doAction() override { (m_instance->*method)(); } + void debugAction(QDebug d, int indentLevel) const override { (m_instance->*debugMethod)(d, indentLevel); } private: T *m_instance; }; @@ -104,13 +104,13 @@ public: QActionAnimation(QAbstractAnimationAction *action); ~QActionAnimation(); - virtual int duration() const; + int duration() const override; void setAnimAction(QAbstractAnimationAction *action); protected: - virtual void updateCurrentTime(int); - virtual void updateState(State newState, State oldState); - void debugAnimation(QDebug d) const; + void updateCurrentTime(int) override; + void updateState(State newState, State oldState) override; + void debugAnimation(QDebug d) const override; private: QAbstractAnimationAction *animAction; @@ -137,16 +137,16 @@ public: void setFromSourcedValue(bool *value) { fromSourced = value; } - int duration() const { return m_duration; } + int duration() const override { return m_duration; } void setDuration(int msecs) { m_duration = msecs; } QEasingCurve easingCurve() const { return easing; } void setEasingCurve(const QEasingCurve &curve) { easing = curve; } protected: - void updateCurrentTime(int currentTime); - void topLevelAnimationLoopChanged(); - void debugAnimation(QDebug d) const; + void updateCurrentTime(int currentTime) override; + void topLevelAnimationLoopChanged() override; + void debugAnimation(QDebug d) const override; private: QQuickBulkValueUpdater *animValue; @@ -162,9 +162,9 @@ class QTickAnimationProxy : public QAbstractAnimationJob Q_DISABLE_COPY(QTickAnimationProxy) public: QTickAnimationProxy(T *instance) : QAbstractAnimationJob(), m_instance(instance) {} - virtual int duration() const { return -1; } + int duration() const override { return -1; } protected: - virtual void updateCurrentTime(int msec) { (m_instance->*method)(msec); } + void updateCurrentTime(int msec) override { (m_instance->*method)(msec); } private: T *m_instance; @@ -192,7 +192,7 @@ public: int loopCount; void commence(); - virtual void animationFinished(QAbstractAnimationJob *); + void animationFinished(QAbstractAnimationJob *) override; QQmlProperty defaultProperty; @@ -309,9 +309,9 @@ public: QQuickAnimationPropertyUpdater() : interpolatorType(0), interpolator(0), prevInterpolatorType(0), reverse(false), fromSourced(false), fromDefined(false), wasDeleted(0) {} ~QQuickAnimationPropertyUpdater(); - void setValue(qreal v); + void setValue(qreal v) override; - void debugUpdater(QDebug d, int indentLevel) const; + void debugUpdater(QDebug d, int indentLevel) const override; QQuickStateActions actions; int interpolatorType; //for Number/ColorAnimation diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp index 8b6968ad98..4bc2d6319e 100644 --- a/src/quick/util/qquickanimationcontroller.cpp +++ b/src/quick/util/qquickanimationcontroller.cpp @@ -50,8 +50,8 @@ class QQuickAnimationControllerPrivate : public QObjectPrivate, QAnimationJobCha public: QQuickAnimationControllerPrivate() : progress(0.0), animation(0), animationInstance(0), finalized(false) {} - virtual void animationFinished(QAbstractAnimationJob *job); - virtual void animationCurrentTimeChanged(QAbstractAnimationJob *job, int currentTime); + void animationFinished(QAbstractAnimationJob *job) override; + void animationCurrentTimeChanged(QAbstractAnimationJob *job, int currentTime) override; qreal progress; diff --git a/src/quick/util/qquickanimationcontroller_p.h b/src/quick/util/qquickanimationcontroller_p.h index e37bb90a0a..43555ac1c1 100644 --- a/src/quick/util/qquickanimationcontroller_p.h +++ b/src/quick/util/qquickanimationcontroller_p.h @@ -78,8 +78,8 @@ public: QQuickAbstractAnimation *animation() const; void setAnimation(QQuickAbstractAnimation *animation); - void classBegin(); - void componentComplete() {} + void classBegin() override; + void componentComplete() override {} Q_SIGNALS: void progressChanged(); void animationChanged(); diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h index 0fc900c5ac..92c66299dc 100644 --- a/src/quick/util/qquickanimator_p.h +++ b/src/quick/util/qquickanimator_p.h @@ -86,13 +86,13 @@ public: void setFrom(qreal from); protected: - ThreadingModel threadingModel() const { return RenderThread; } + ThreadingModel threadingModel() const override { return RenderThread; } virtual QQuickAnimatorJob *createJob() const = 0; virtual QString propertyName() const = 0; QAbstractAnimationJob *transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection, - QObject *); + QObject *) override; QQuickAnimator(QQuickAnimatorPrivate &dd, QObject *parent = 0); QQuickAnimator(QObject *parent = 0); @@ -112,8 +112,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimator : public QQuickAnimator public: QQuickScaleAnimator(QObject *parent = 0); protected: - QQuickAnimatorJob *createJob() const; - QString propertyName() const { return QStringLiteral("scale"); } + QQuickAnimatorJob *createJob() const override; + QString propertyName() const override { return QStringLiteral("scale"); } }; class Q_QUICK_PRIVATE_EXPORT QQuickXAnimator : public QQuickAnimator @@ -122,8 +122,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickXAnimator : public QQuickAnimator public: QQuickXAnimator(QObject *parent = 0); protected: - QQuickAnimatorJob *createJob() const; - QString propertyName() const{ return QStringLiteral("x"); } + QQuickAnimatorJob *createJob() const override; + QString propertyName() const override { return QStringLiteral("x"); } }; class Q_QUICK_PRIVATE_EXPORT QQuickYAnimator : public QQuickAnimator @@ -132,8 +132,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickYAnimator : public QQuickAnimator public: QQuickYAnimator(QObject *parent = 0); protected: - QQuickAnimatorJob *createJob() const; - QString propertyName() const { return QStringLiteral("y"); } + QQuickAnimatorJob *createJob() const override; + QString propertyName() const override { return QStringLiteral("y"); } }; class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimator : public QQuickAnimator @@ -142,8 +142,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimator : public QQuickAnimator public: QQuickOpacityAnimator(QObject *parent = 0); protected: - QQuickAnimatorJob *createJob() const; - QString propertyName() const { return QStringLiteral("opacity"); } + QQuickAnimatorJob *createJob() const override; + QString propertyName() const override { return QStringLiteral("opacity"); } }; class QQuickRotationAnimatorPrivate; @@ -166,8 +166,8 @@ Q_SIGNALS: void directionChanged(RotationDirection dir); protected: - QQuickAnimatorJob *createJob() const; - QString propertyName() const { return QStringLiteral("rotation"); } + QQuickAnimatorJob *createJob() const override; + QString propertyName() const override { return QStringLiteral("rotation"); } }; #if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl) @@ -188,8 +188,8 @@ Q_SIGNALS: void uniformChanged(const QString &); protected: - QQuickAnimatorJob *createJob() const; - QString propertyName() const; + QQuickAnimatorJob *createJob() const override; + QString propertyName() const override; }; #endif diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp index 6d8167413e..2f96c511c0 100644 --- a/src/quick/util/qquickanimatorcontroller.cpp +++ b/src/quick/util/qquickanimatorcontroller.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Gunnar Sletta <gunnar@sletta.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -50,228 +51,116 @@ QT_BEGIN_NAMESPACE -QQuickAnimatorController::QQuickAnimatorController(QQuickWindow *window) - : m_window(window) - , m_nodesAreInvalid(false) -{ - m_guiEntity = new QQuickAnimatorControllerGuiThreadEntity(); - m_guiEntity->controller = this; - connect(window, SIGNAL(frameSwapped()), m_guiEntity, SLOT(frameSwapped())); -} - -void QQuickAnimatorControllerGuiThreadEntity::frameSwapped() +QQuickAnimatorController::~QQuickAnimatorController() { - if (!controller.isNull()) - controller->stopProxyJobs(); } -QQuickAnimatorController::~QQuickAnimatorController() +QQuickAnimatorController::QQuickAnimatorController(QQuickWindow *window) + : m_window(window) { - // The proxy job might already have been deleted, in which case we - // need to avoid calling functions on them. Then delete the job. - for (QAbstractAnimationJob *job : qAsConst(m_deleting)) { - m_starting.take(job); - m_stopping.take(job); - m_animatorRoots.take(job); - delete job; - } - - for (QQuickAnimatorProxyJob *proxy : qAsConst(m_animatorRoots)) - proxy->controllerWasDeleted(); - for (auto it = m_animatorRoots.keyBegin(), end = m_animatorRoots.keyEnd(); it != end; ++it) - delete *it; - - // Delete those who have been started, stopped and are now still - // pending for restart. - for (auto it = m_starting.keyBegin(), end = m_starting.keyEnd(); it != end; ++it) { - QAbstractAnimationJob *job = *it; - if (!m_animatorRoots.contains(job)) - delete job; - } - - delete m_guiEntity; } -static void qquickanimator_invalidate_node(QAbstractAnimationJob *job) +static void qquickanimator_invalidate_jobs(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { - static_cast<QQuickAnimatorJob *>(job)->nodeWasDestroyed(); + static_cast<QQuickAnimatorJob *>(job)->invalidate(); } else if (job->isGroup()) { QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) - qquickanimator_invalidate_node(a); + qquickanimator_invalidate_jobs(a); } } void QQuickAnimatorController::windowNodesDestroyed() { - m_nodesAreInvalid = true; - for (QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *>::const_iterator it = m_animatorRoots.constBegin(); - it != m_animatorRoots.constEnd(); ++it) { - qquickanimator_invalidate_node(it.key()); + for (const QSharedPointer<QAbstractAnimationJob> &toStop : qAsConst(m_rootsPendingStop)) { + qquickanimator_invalidate_jobs(toStop.data()); + toStop->stop(); } -} + m_rootsPendingStop.clear(); -void QQuickAnimatorController::itemDestroyed(QObject *o) -{ - m_deletedSinceLastFrame << (QQuickItem *) o; + // Clear animation roots and iterate over a temporary to avoid that job->stop() + // modifies the m_animationRoots and messes with our iteration + const auto roots = m_animationRoots; + m_animationRoots.clear(); + for (const QSharedPointer<QAbstractAnimationJob> &job : roots) { + qquickanimator_invalidate_jobs(job.data()); + + // Stop it and add it to the list of pending start so it might get + // started later on. + job->stop(); + m_rootsPendingStart.insert(job); + } } void QQuickAnimatorController::advance() { bool running = false; - for (QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *>::const_iterator it = m_animatorRoots.constBegin(); - !running && it != m_animatorRoots.constEnd(); ++it) { - if (it.key()->isRunning()) + for (const QSharedPointer<QAbstractAnimationJob> &job : qAsConst(m_animationRoots)) { + if (job->isRunning()) { running = true; + break; + } } - // It was tempting to only run over the active animations, but we need to push - // the values for the transforms that finished in the last frame and those will - // have been removed already... - lock(); - for (QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *>::const_iterator it = m_transforms.constBegin(); - it != m_transforms.constEnd(); ++it) { - QQuickTransformAnimatorJob::Helper *xform = *it; - // Set to zero when the item was deleted in beforeNodeSync(). - if (!xform->item) - continue; - (*it)->apply(); - } - unlock(); + for (QQuickAnimatorJob *job : qAsConst(m_runningAnimators)) + job->commit(); if (running) m_window->update(); } -static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorController *c, bool attachListener) +static void qquickanimator_sync_before_start(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { - QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job); - // Note: since a QQuickAnimatorJob::m_target is a QPointer, - // if m_target is destroyed between the time it was set - // as the target of the animator job and before this step, - // (e.g a Loader being set inactive just after starting the animator) - // we are sure it will be NULL and won't be dangling around - if (!j->target()) { - return; - } else if (c->m_deletedSinceLastFrame.contains(j->target())) { - j->targetWasDeleted(); - } else { - if (attachListener) - j->addAnimationChangeListener(c, QAbstractAnimationJob::StateChange); - j->initialize(c); - } + static_cast<QQuickAnimatorJob *>(job)->preSync(); } else if (job->isGroup()) { QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) - qquick_initialize_helper(a, c, attachListener); + qquickanimator_sync_before_start(a); } } void QQuickAnimatorController::beforeNodeSync() { - for (QAbstractAnimationJob *job : qAsConst(m_deleting)) { - m_starting.take(job); - m_stopping.take(job); - m_animatorRoots.take(job); - job->stop(); - delete job; - } - m_deleting.clear(); + for (const QSharedPointer<QAbstractAnimationJob> &toStop : qAsConst(m_rootsPendingStop)) + toStop->stop(); + m_rootsPendingStop.clear(); - if (m_starting.size()) - m_window->update(); - for (QQuickAnimatorProxyJob *proxy : qAsConst(m_starting)) { - QAbstractAnimationJob *job = proxy->job(); - job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion); - qquick_initialize_helper(job, this, true); - m_animatorRoots[job] = proxy; - job->start(); - proxy->startedByController(); - } - m_starting.clear(); - for (QQuickAnimatorProxyJob *proxy : qAsConst(m_stopping)) { - QAbstractAnimationJob *job = proxy->job(); - job->stop(); - } - m_stopping.clear(); - - // First sync after a window was hidden or otherwise invalidated. - // call initialize again to pick up new nodes.. - if (m_nodesAreInvalid) { - for (QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *>::const_iterator it = m_animatorRoots.constBegin(); - it != m_animatorRoots.constEnd(); ++it) { - qquick_initialize_helper(it.key(), this, false); - } - m_nodesAreInvalid = false; - } + for (QQuickAnimatorJob *job : qAsConst(m_runningAnimators)) + job->preSync(); - for (QQuickAnimatorJob *job : qAsConst(m_activeLeafAnimations)) { - if (!job->target()) - continue; - else if (m_deletedSinceLastFrame.contains(job->target())) - job->targetWasDeleted(); - else if (job->isTransform()) { - QQuickTransformAnimatorJob *xform = static_cast<QQuickTransformAnimatorJob *>(job); - xform->transformHelper()->sync(); - } - } - for (QQuickItem *wiped : qAsConst(m_deletedSinceLastFrame)) { - QQuickTransformAnimatorJob::Helper *helper = m_transforms.take(wiped); - // Helper will now already have been reset in all animators referencing it. - delete helper; - } + // Start pending jobs + for (const QSharedPointer<QAbstractAnimationJob> &job : qAsConst(m_rootsPendingStart)) { + Q_ASSERT(!job->isRunning()); - m_deletedSinceLastFrame.clear(); -} + // We want to make sure that presync is called before + // updateAnimationTime is called the very first time, so before + // starting a tree of jobs, we go through it and call preSync on all + // its animators. + qquickanimator_sync_before_start(job.data()); -void QQuickAnimatorController::afterNodeSync() -{ - for (QQuickAnimatorJob *job : qAsConst(m_activeLeafAnimations)) { - if (job->target()) - job->afterNodeSync(); + // The start the job.. + job->start(); + m_animationRoots.insert(job.data(), job); } -} + m_rootsPendingStart.clear(); -void QQuickAnimatorController::proxyWasDestroyed(QQuickAnimatorProxyJob *proxy) -{ - lock(); - m_proxiesToStop.remove(proxy); - unlock(); + // Issue an update directly on the window to force another render pass. + if (m_animationRoots.size()) + m_window->update(); } -void QQuickAnimatorController::stopProxyJobs() +void QQuickAnimatorController::afterNodeSync() { - // Need to make a copy under lock and then stop while unlocked. - // Stopping triggers writeBack which in turn may lock, so it needs - // to be outside the lock. It is also safe because deletion of - // proxies happens on the GUI thread, where this code is also executing. - lock(); - const QSet<QQuickAnimatorProxyJob *> jobs = m_proxiesToStop; - m_proxiesToStop.clear(); - unlock(); - for (QQuickAnimatorProxyJob *p : jobs) - p->stop(); + for (QQuickAnimatorJob *job : qAsConst(m_runningAnimators)) + job->postSync(); } void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job) { - /* We are currently on the render thread and m_deleting is primarily - * being written on the GUI Thread and read during sync. However, we don't - * need to lock here as this is a direct result of animationDriver->advance() - * which is already locked. For non-threaded render loops no locking is - * needed in any case. - */ - if (!m_deleting.contains(job)) { - QQuickAnimatorProxyJob *proxy = m_animatorRoots.value(job); - if (proxy) { - m_window->update(); - m_proxiesToStop << proxy; - } - // else already gone... - } + m_animationRoots.remove(job); } void QQuickAnimatorController::animationStateChanged(QAbstractAnimationJob *job, @@ -281,43 +170,52 @@ void QQuickAnimatorController::animationStateChanged(QAbstractAnimationJob *job, Q_ASSERT(job->isRenderThreadJob()); QQuickAnimatorJob *animator = static_cast<QQuickAnimatorJob *>(job); if (newState == QAbstractAnimationJob::Running) { - m_activeLeafAnimations << animator; - animator->setHasBeenRunning(true); + m_runningAnimators.insert(animator); } else if (oldState == QAbstractAnimationJob::Running) { - m_activeLeafAnimations.remove(animator); + animator->commit(); + m_runningAnimators.remove(animator); } } - void QQuickAnimatorController::requestSync() { // Force a "sync" pass as the newly started animation needs to sync properties from GUI. m_window->maybeUpdate(); } -// These functions are called on the GUI thread. -void QQuickAnimatorController::startJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job) +// All this is being executed on the GUI thread while the animator controller +// is locked. +void QQuickAnimatorController::start_helper(QAbstractAnimationJob *job) { - proxy->markJobManagedByController(); - m_starting[job] = proxy; - m_stopping.remove(job); - requestSync(); + if (job->isRenderThreadJob()) { + QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job); + j->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange); + j->initialize(this); + } else if (job->isGroup()) { + QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); + for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) + start_helper(a); + } } -void QQuickAnimatorController::stopJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job) +// Called by the proxy when it is time to kick off an animation job +void QQuickAnimatorController::start(const QSharedPointer<QAbstractAnimationJob> &job) { - m_stopping[job] = proxy; - m_starting.remove(job); + m_rootsPendingStart.insert(job); + m_rootsPendingStop.remove(job); + job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion); + start_helper(job.data()); requestSync(); } -void QQuickAnimatorController::deleteJob(QAbstractAnimationJob *job) + +// Called by the proxy when it is time to stop an animation job. +void QQuickAnimatorController::cancel(const QSharedPointer<QAbstractAnimationJob> &job) { - lock(); - m_deleting << job; - requestSync(); - unlock(); + m_rootsPendingStart.remove(job); + m_rootsPendingStop.insert(job); } + QT_END_NAMESPACE diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h index 0a9902cc30..428a6700d4 100644 --- a/src/quick/util/qquickanimatorcontroller_p.h +++ b/src/quick/util/qquickanimatorcontroller_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Gunnar Sletta <gunnar@sletta.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -60,8 +61,6 @@ QT_BEGIN_NAMESPACE -class QQuickAnimatorControllerGuiThreadEntity; - class QQuickAnimatorController : public QObject, public QAnimationJobChangeListener { Q_OBJECT @@ -74,54 +73,37 @@ public: void beforeNodeSync(); void afterNodeSync(); - void animationFinished(QAbstractAnimationJob *job); - void animationStateChanged(QAbstractAnimationJob *job, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState); + void animationFinished(QAbstractAnimationJob *job) override; + void animationStateChanged(QAbstractAnimationJob *job, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override; void requestSync(); // These are called from the GUI thread (the proxy) - void startJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job); - void stopJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job); - void deleteJob(QAbstractAnimationJob *job); + void start(const QSharedPointer<QAbstractAnimationJob> &job); + void cancel(const QSharedPointer<QAbstractAnimationJob> &job); + bool isPendingStart(const QSharedPointer<QAbstractAnimationJob> &job) const { return m_rootsPendingStart.contains(job); } void lock() { m_mutex.lock(); } void unlock() { m_mutex.unlock(); } - void proxyWasDestroyed(QQuickAnimatorProxyJob *proxy); void stopProxyJobs(); void windowNodesDestroyed(); -public Q_SLOTS: - void itemDestroyed(QObject *); + QQuickWindow *window() const { return m_window; } -public: - // These are manipulated from the GUI thread and should only - // be updated during the sync() phase. - QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *> m_starting; - QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *> m_stopping; - QSet<QAbstractAnimationJob *> m_deleting; - - QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *> m_animatorRoots; - QSet<QQuickAnimatorJob *> m_activeLeafAnimations; - QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *> m_transforms; - QSet<QQuickItem *> m_deletedSinceLastFrame; - QQuickWindow *m_window; - QQuickAnimatorControllerGuiThreadEntity *m_guiEntity; - QSet<QQuickAnimatorProxyJob *> m_proxiesToStop; - QMutex m_mutex; +private: + void start_helper(QAbstractAnimationJob *job); + void cancel_helper(QAbstractAnimationJob *job); - bool m_nodesAreInvalid; -}; - -class QQuickAnimatorControllerGuiThreadEntity : public QObject -{ - Q_OBJECT public: - QPointer<QQuickAnimatorController> controller; + QSet<QQuickAnimatorJob * > m_runningAnimators; + QHash<QAbstractAnimationJob *, QSharedPointer<QAbstractAnimationJob> > m_animationRoots; + QSet<QSharedPointer<QAbstractAnimationJob> > m_rootsPendingStop; + QSet<QSharedPointer<QAbstractAnimationJob> > m_rootsPendingStart; -public Q_SLOTS: - void frameSwapped(); + QQuickWindow *m_window; + QMutex m_mutex; }; diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 1176cf1ff7..5dd16407b8 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Gunnar Sletta <gunnar@sletta.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -54,12 +55,42 @@ QT_BEGIN_NAMESPACE +struct QQuickTransformAnimatorHelperStore +{ + QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *> store; + QMutex mutex; + + QQuickTransformAnimatorJob::Helper *acquire(QQuickItem *item) { + mutex.lock(); + QQuickTransformAnimatorJob::Helper *helper = store.value(item); + if (!helper) { + helper = new QQuickTransformAnimatorJob::Helper(); + helper->item = item; + store[item] = helper; + } else { + ++helper->ref; + } + mutex.unlock(); + return helper; + } + + void release(QQuickTransformAnimatorJob::Helper *helper) { + mutex.lock(); + if (--helper->ref == 0) { + store.remove(helper->item); + delete helper; + } + mutex.unlock(); + } +}; +Q_GLOBAL_STATIC(QQuickTransformAnimatorHelperStore, qquick_transform_animatorjob_helper_store); + QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObject *item) - : m_controller(0) - , m_job(job) + : m_controller(nullptr) , m_internalState(State_Stopped) - , m_jobManagedByController(false) { + m_job.reset(job); + m_isRenderThreadProxy = true; m_animation = qobject_cast<QQuickAbstractAnimation *>(item); @@ -87,57 +118,58 @@ QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObje QQuickItem *item = qobject_cast<QQuickItem *>(ctx); if (item->window()) setWindow(item->window()); - - qmlobject_connect(item, QQuickItem, SIGNAL(windowChanged(QQuickWindow*)), this, QQuickAnimatorProxyJob, SLOT(windowChanged(QQuickWindow*))); + connect(item, &QQuickItem::windowChanged, this, &QQuickAnimatorProxyJob::windowChanged); } } QQuickAnimatorProxyJob::~QQuickAnimatorProxyJob() { - deleteJob(); - if (m_controller) - m_controller->proxyWasDestroyed(this); -} - -void QQuickAnimatorProxyJob::deleteJob() -{ - if (m_job) { - // If we have a controller, we might have posted the job to be started - // so delete it through the controller to clean up properly. - if (m_controller) - m_controller->deleteJob(m_job); - - // We explicitly delete the job if the animator controller has never touched - // it. If it has, it will have ownership as well. - else if (!m_jobManagedByController) - delete m_job; - m_job = 0; - } + if (m_job && m_controller) + m_controller->cancel(m_job); + m_job.reset(); } QObject *QQuickAnimatorProxyJob::findAnimationContext(QQuickAbstractAnimation *a) { QObject *p = a->parent(); - while (p != 0 && qobject_cast<QQuickWindow *>(p) == 0 && qobject_cast<QQuickItem *>(p) == 0) + while (p != nullptr && qobject_cast<QQuickWindow *>(p) == nullptr && qobject_cast<QQuickItem *>(p) == nullptr) p = p->parent(); return p; } void QQuickAnimatorProxyJob::updateCurrentTime(int) { + // We do a simple check here to see if the animator has run and stopped on + // the render thread. isPendingStart() will perform a check against jobs + // that have been scheduled for start, but that will not yet have entered + // the actual running state. + // Secondly, we make an unprotected read of the job's state to figure out + // if it is running, but this is ok, since we're only reading the state + // and if the render thread should happen to be writing it concurrently, + // we might get the wrong value for this update, but then we'll simply + // pick it up on the next iterationm when the job is stopped and render + // thread is no longer using it. + if (m_internalState == State_Running + && !m_controller->isPendingStart(m_job) + && !m_job->isRunning()) { + stop(); + } } void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State) { if (m_state == Running) { m_internalState = State_Starting; - if (m_controller) - m_controller->startJob(this, m_job); + if (m_controller) { + m_internalState = State_Running; + m_controller->start(m_job); + } + } else if (newState == Stopped) { syncBackCurrentValues(); m_internalState = State_Stopped; if (m_controller) { - m_controller->stopJob(this, m_job); + m_controller->cancel(m_job); } } } @@ -154,69 +186,54 @@ void QQuickAnimatorProxyJob::windowChanged(QQuickWindow *window) setWindow(window); } -void QQuickAnimatorProxyJob::controllerWasDeleted() -{ - m_controller = 0; - m_job = 0; -} - void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window) { if (!window) { - stop(); - deleteJob(); - - // Upon leaving a window, we reset the controller. This means that - // animators will only enter the Starting phase and won't be making - // calls to QQuickAnimatorController::startjob(). - if (m_controller) - m_controller->proxyWasDestroyed(this); - m_controller = 0; + if (m_job && m_controller) + m_controller->cancel(m_job); + m_controller = nullptr; } else if (!m_controller && m_job) { m_controller = QQuickWindowPrivate::get(window)->animationController; if (window->isSceneGraphInitialized()) readyToAnimate(); else - connect(window, SIGNAL(sceneGraphInitialized()), this, SLOT(sceneGraphInitialized())); + connect(window, &QQuickWindow::sceneGraphInitialized, this, &QQuickAnimatorProxyJob::sceneGraphInitialized); } } void QQuickAnimatorProxyJob::sceneGraphInitialized() { + disconnect(m_controller->window(), &QQuickWindow::sceneGraphInitialized, this, &QQuickAnimatorProxyJob::sceneGraphInitialized); readyToAnimate(); - disconnect(this, SLOT(sceneGraphInitialized())); } void QQuickAnimatorProxyJob::readyToAnimate() { - if (m_internalState == State_Starting) - m_controller->startJob(this, m_job); -} - -void QQuickAnimatorProxyJob::startedByController() -{ - m_internalState = State_Running; + Q_ASSERT(m_controller); + if (m_internalState == State_Starting) { + m_internalState = State_Running; + m_controller->start(m_job); + } } static void qquick_syncback_helper(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { - QQuickAnimatorJob *a = static_cast<QQuickAnimatorJob *>(job); - // Sync back only those jobs that actually have been running - if (a->controller() && a->hasBeenRunning()) - a->writeBack(); + static_cast<QQuickAnimatorJob *>(job)->writeBack(); + } else if (job->isGroup()) { QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) qquick_syncback_helper(a); } + } void QQuickAnimatorProxyJob::syncBackCurrentValues() { if (m_job) - qquick_syncback_helper(m_job); + qquick_syncback_helper(m_job.data()); } QQuickAnimatorJob::QQuickAnimatorJob() @@ -228,7 +245,6 @@ QQuickAnimatorJob::QQuickAnimatorJob() , m_duration(0) , m_isTransform(false) , m_isUniform(false) - , m_hasBeenRunning(false) { m_isRenderThreadJob = true; } @@ -244,13 +260,16 @@ qreal QQuickAnimatorJob::progress(int time) const { return m_easing.valueForProgress((m_duration == 0) ? qreal(1) : qreal(time) / qreal(m_duration)); } + qreal QQuickAnimatorJob::value() const { - qreal v; - m_controller->lock(); - v = m_value; - m_controller->unlock(); - return v; + qreal value = m_to; + if (m_controller) { + m_controller->lock(); + value = m_value; + m_controller->unlock(); + } + return value; } void QQuickAnimatorJob::setTarget(QQuickItem *target) @@ -263,62 +282,81 @@ void QQuickAnimatorJob::initialize(QQuickAnimatorController *controller) m_controller = controller; } -void QQuickAnimatorJob::targetWasDeleted() -{ - m_target = 0; - m_controller = 0; -} - QQuickTransformAnimatorJob::QQuickTransformAnimatorJob() - : m_helper(0) + : m_helper(nullptr) { m_isTransform = true; } QQuickTransformAnimatorJob::~QQuickTransformAnimatorJob() { - if (m_helper && --m_helper->ref == 0) { - // The only condition for not having a controller is when target was - // destroyed, in which case we have neither m_helper nor m_contorller. - Q_ASSERT(m_controller); - Q_ASSERT(m_helper->item); - m_controller->m_transforms.remove(m_helper->item); - delete m_helper; - } + if (m_helper) + qquick_transform_animatorjob_helper_store()->release(m_helper); } -void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller) +void QQuickTransformAnimatorJob::setTarget(QQuickItem *item) { - QQuickAnimatorJob::initialize(controller); + // In the extremely unlikely event that the target of an animator has been + // changed into a new item that sits in the exact same pointer address, we + // want to force syncing it again. + if (m_helper && m_target) + m_helper->wasSynced = false; + QQuickAnimatorJob::setTarget(item); +} - if (m_controller) { - bool newHelper = m_helper == 0; - m_helper = m_controller->m_transforms.value(m_target); - if (!m_helper) { - m_helper = new Helper(); - m_helper->item = m_target; - m_controller->m_transforms.insert(m_target, m_helper); - QObject::connect(m_target, SIGNAL(destroyed(QObject*)), m_controller, SLOT(itemDestroyed(QObject*)), Qt::DirectConnection); - } else { - if (newHelper) // only add reference the first time around.. - ++m_helper->ref; - // Make sure leftovers from previous runs are being used... - m_helper->wasSynced = false; - } - m_helper->sync(); +void QQuickTransformAnimatorJob::preSync() +{ + // If the target has changed or become null, release and reset the helper + if (m_helper && (m_helper->item != m_target || !m_target)) { + qquick_transform_animatorjob_helper_store()->release(m_helper); + m_helper = nullptr; } + + if (!m_target) + return; + + if (!m_helper) { + m_helper = qquick_transform_animatorjob_helper_store()->acquire(m_target); + + // This is a bit superfluous, but it ends up being simpler than the + // alternative. When an item happens to land on the same address as a + // previous item, that helper might not have been fully cleaned up by + // the time it gets taken back into use. As an alternative to storing + // connections to each and every item's QObject::destroyed() and + // having to clean those up afterwards, we simply sync all helpers on + // the first run. The sync is only done once for the run of an + // animation and it is a fairly light function (compared to storing + // potentially thousands of connections and managing their lifetime. + m_helper->wasSynced = false; + } + + m_helper->sync(); } -void QQuickTransformAnimatorJob::nodeWasDestroyed() +void QQuickTransformAnimatorJob::postSync() { - if (m_helper) - m_helper->node = 0; + Q_ASSERT((m_helper != nullptr) == (m_target != nullptr)); // If there is a target, there should also be a helper, ref: preSync + Q_ASSERT(!m_helper || m_helper->item == m_target); // If there is a helper, it should point to our target + + if (!m_target || !m_helper) { + invalidate(); + return; + } + + QQuickItemPrivate *d = QQuickItemPrivate::get(m_target); + if (d->extra.isAllocated() + && d->extra->layer + && d->extra->layer->enabled()) { + d = QQuickItemPrivate::get(d->extra->layer->m_effectSource); + } + + m_helper->node = d->itemNode(); } -void QQuickTransformAnimatorJob::targetWasDeleted() +void QQuickTransformAnimatorJob::invalidate() { - m_helper = 0; - QQuickAnimatorJob::targetWasDeleted(); + if (m_helper) + m_helper->node = nullptr; } void QQuickTransformAnimatorJob::Helper::sync() @@ -366,7 +404,7 @@ void QQuickTransformAnimatorJob::Helper::sync() } } -void QQuickTransformAnimatorJob::Helper::apply() +void QQuickTransformAnimatorJob::Helper::commit() { if (!wasChanged || !node) return; @@ -382,7 +420,11 @@ void QQuickTransformAnimatorJob::Helper::apply() wasChanged = false; } - +void QQuickTransformAnimatorJob::commit() +{ + if (m_helper) + m_helper->commit(); +} void QQuickXAnimatorJob::writeBack() { @@ -392,7 +434,10 @@ void QQuickXAnimatorJob::writeBack() void QQuickXAnimatorJob::updateCurrentTime(int time) { - if (!m_controller) +#if QT_CONFIG(opengl) + Q_ASSERT(!m_controller || !m_controller->m_window->openglContext() || m_controller->m_window->openglContext()->thread() == QThread::currentThread()); +#endif + if (!m_helper) return; m_value = m_from + (m_to - m_from) * progress(time); @@ -408,7 +453,10 @@ void QQuickYAnimatorJob::writeBack() void QQuickYAnimatorJob::updateCurrentTime(int time) { - if (!m_controller) +#if QT_CONFIG(opengl) + Q_ASSERT(!m_controller || !m_controller->m_window->openglContext() || m_controller->m_window->openglContext()->thread() == QThread::currentThread()); +#endif + if (!m_helper) return; m_value = m_from + (m_to - m_from) * progress(time); @@ -416,14 +464,87 @@ void QQuickYAnimatorJob::updateCurrentTime(int time) m_helper->wasChanged = true; } +void QQuickScaleAnimatorJob::writeBack() +{ + if (m_target) + m_target->setScale(value()); +} + +void QQuickScaleAnimatorJob::updateCurrentTime(int time) +{ +#if QT_CONFIG(opengl) + Q_ASSERT(!m_controller || !m_controller->m_window->openglContext() || m_controller->m_window->openglContext()->thread() == QThread::currentThread()); +#endif + if (!m_helper) + return; + + m_value = m_from + (m_to - m_from) * progress(time); + m_helper->scale = m_value; + m_helper->wasChanged = true; +} + + +QQuickRotationAnimatorJob::QQuickRotationAnimatorJob() + : m_direction(QQuickRotationAnimator::Numerical) +{ +} + +extern QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress); +extern QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress); +extern QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress); + +void QQuickRotationAnimatorJob::updateCurrentTime(int time) +{ +#if QT_CONFIG(opengl) + Q_ASSERT(!m_controller || !m_controller->m_window->openglContext() || m_controller->m_window->openglContext()->thread() == QThread::currentThread()); +#endif + if (!m_helper) + return; + + float t = progress(time); + + switch (m_direction) { + case QQuickRotationAnimator::Clockwise: + m_value = _q_interpolateClockwiseRotation(m_from, m_to, t).toFloat(); + // The logic in _q_interpolateClockwise comes out a bit wrong + // for the case of X->0 where 0<X<360. It ends on 360 which it + // shouldn't. + if (t == 1) + m_value = m_to; + break; + case QQuickRotationAnimator::Counterclockwise: + m_value = _q_interpolateCounterclockwiseRotation(m_from, m_to, t).toFloat(); + break; + case QQuickRotationAnimator::Shortest: + m_value = _q_interpolateShortestRotation(m_from, m_to, t).toFloat(); + break; + case QQuickRotationAnimator::Numerical: + m_value = m_from + (m_to - m_from) * t; + break; + } + m_helper->rotation = m_value; + m_helper->wasChanged = true; +} + +void QQuickRotationAnimatorJob::writeBack() +{ + if (m_target) + m_target->setRotation(value()); +} + + QQuickOpacityAnimatorJob::QQuickOpacityAnimatorJob() - : m_opacityNode(0) + : m_opacityNode(nullptr) { } -void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller) +void QQuickOpacityAnimatorJob::postSync() { - QQuickAnimatorJob::initialize(controller); + if (!m_target) { + invalidate(); + return; + } + QQuickItemPrivate *d = QQuickItemPrivate::get(m_target); #if QT_CONFIG(quick_shadereffect) if (d->extra.isAllocated() @@ -434,6 +555,7 @@ void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller) #endif m_opacityNode = d->opacityNode(); + if (!m_opacityNode) { m_opacityNode = new QSGOpacityNode(); @@ -464,11 +586,12 @@ void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller) d->extra.value().opacityNode = m_opacityNode; } + Q_ASSERT(m_opacityNode); } -void QQuickOpacityAnimatorJob::nodeWasDestroyed() +void QQuickOpacityAnimatorJob::invalidate() { - m_opacityNode = 0; + m_opacityNode = nullptr; } void QQuickOpacityAnimatorJob::writeBack() @@ -479,77 +602,21 @@ void QQuickOpacityAnimatorJob::writeBack() void QQuickOpacityAnimatorJob::updateCurrentTime(int time) { - if (!m_controller || !m_opacityNode) - return; - - m_value = m_from + (m_to - m_from) * progress(time); - m_opacityNode->setOpacity(m_value); -} - -void QQuickScaleAnimatorJob::writeBack() -{ - if (m_target) - m_target->setScale(value()); -} +#if QT_CONFIG(opengl) + Q_ASSERT(!m_controller || !m_controller->m_window->openglContext() || m_controller->m_window->openglContext()->thread() == QThread::currentThread()); +#endif -void QQuickScaleAnimatorJob::updateCurrentTime(int time) -{ - if (!m_controller) + if (!m_opacityNode) return; m_value = m_from + (m_to - m_from) * progress(time); - m_helper->scale = m_value; - m_helper->wasChanged = true; -} - -QQuickRotationAnimatorJob::QQuickRotationAnimatorJob() - : m_direction(QQuickRotationAnimator::Numerical) -{ -} - -extern QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress); -extern QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress); -extern QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress); - -void QQuickRotationAnimatorJob::updateCurrentTime(int time) -{ - if (!m_controller) - return; - - float t = progress(time); - - switch (m_direction) { - case QQuickRotationAnimator::Clockwise: - m_value = _q_interpolateClockwiseRotation(m_from, m_to, t).toFloat(); - // The logic in _q_interpolateClockwise comes out a bit wrong - // for the case of X->0 where 0<X<360. It ends on 360 which it - // shouldn't. - if (t == 1) - m_value = m_to; - break; - case QQuickRotationAnimator::Counterclockwise: - m_value = _q_interpolateCounterclockwiseRotation(m_from, m_to, t).toFloat(); - break; - case QQuickRotationAnimator::Shortest: - m_value = _q_interpolateShortestRotation(m_from, m_to, t).toFloat(); - break; - case QQuickRotationAnimator::Numerical: - m_value = m_from + (m_to - m_from) * t; - break; - } - m_helper->rotation = m_value; - m_helper->wasChanged = true; + m_opacityNode->setOpacity(m_value); } -void QQuickRotationAnimatorJob::writeBack() -{ - if (m_target) - m_target->setRotation(value()); -} #if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl) QQuickUniformAnimatorJob::QQuickUniformAnimatorJob() - : m_node(0) + : m_node(nullptr) , m_uniformIndex(-1) , m_uniformType(-1) { @@ -558,19 +625,24 @@ QQuickUniformAnimatorJob::QQuickUniformAnimatorJob() void QQuickUniformAnimatorJob::setTarget(QQuickItem *target) { - if (qobject_cast<QQuickOpenGLShaderEffect *>(target) != 0) + if (qobject_cast<QQuickOpenGLShaderEffect *>(target) != nullptr) m_target = target; } -void QQuickUniformAnimatorJob::nodeWasDestroyed() +void QQuickUniformAnimatorJob::invalidate() { - m_node = 0; + m_node = nullptr; m_uniformIndex = -1; m_uniformType = -1; } -void QQuickUniformAnimatorJob::afterNodeSync() +void QQuickUniformAnimatorJob::postSync() { + if (!m_target) { + invalidate(); + return; + } + m_node = static_cast<QQuickOpenGLShaderEffectNode *>(QQuickItemPrivate::get(m_target)->paintNode); if (m_node && m_uniformIndex == -1 && m_uniformType == -1) { diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h index e891ebab72..a3ced4c21b 100644 --- a/src/quick/util/qquickanimatorjob_p.h +++ b/src/quick/util/qquickanimatorjob_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Gunnar Sletta <gunnar@sletta.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -80,25 +81,20 @@ public: QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObject *item); ~QQuickAnimatorProxyJob(); - int duration() const Q_DECL_OVERRIDE { return m_duration; } + int duration() const override { return m_duration; } - QAbstractAnimationJob *job() const { return m_job; } - - void startedByController(); - void controllerWasDeleted(); - void markJobManagedByController() { m_jobManagedByController = true; } + const QSharedPointer<QAbstractAnimationJob> &job() const { return m_job; } protected: - void updateCurrentTime(int) Q_DECL_OVERRIDE; - void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) Q_DECL_OVERRIDE; - void debugAnimation(QDebug d) const Q_DECL_OVERRIDE; + void updateCurrentTime(int) override; + void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override; + void debugAnimation(QDebug d) const override; public Q_SLOTS: void windowChanged(QQuickWindow *window); void sceneGraphInitialized(); private: - void deleteJob(); void syncBackCurrentValues(); void readyToAnimate(); void setWindow(QQuickWindow *window); @@ -106,7 +102,7 @@ private: QPointer<QQuickAnimatorController> m_controller; QQuickAbstractAnimation *m_animation; - QAbstractAnimationJob *m_job; + QSharedPointer<QAbstractAnimationJob> m_job; int m_duration; enum InternalState { @@ -117,7 +113,6 @@ private: }; InternalState m_internalState; - bool m_jobManagedByController; }; class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorJob : public QAbstractAnimationJob @@ -126,37 +121,53 @@ public: virtual void setTarget(QQuickItem *target); QQuickItem *target() const { return m_target; } - void setFrom(qreal scale) { m_from = scale; } + void setFrom(qreal from) { m_from = from; } qreal from() const { return m_from; } void setTo(qreal to) { m_to = to; } qreal to() const { return m_to; } void setDuration(int duration) { m_duration = duration; } - int duration() const Q_DECL_OVERRIDE { return m_duration; } + int duration() const override { return m_duration; } QEasingCurve easingCurve() const { return m_easing; } void setEasingCurve(const QEasingCurve &curve) { m_easing = curve; } - virtual void targetWasDeleted(); + // Initialize is called on the GUI thread just before it is started + // and taken over on the render thread. virtual void initialize(QQuickAnimatorController *controller); + + // Called on the render thread during SG shutdown. + virtual void invalidate() = 0; + + // Called on the GUI thread after a complete render thread animation job + // has been completed to write back a given animator's result to the + // source item. virtual void writeBack() = 0; - virtual void nodeWasDestroyed() = 0; - virtual void afterNodeSync() { } + + // Called before the SG sync on the render thread. The GUI thread is + // locked during this call. + virtual void preSync() { } + + // Called after the SG sync on the render thread. The GUI thread is + // locked during this call. + virtual void postSync() { } + + // Called after animations have ticked on the render thread. No locks are + // held at this time, so synchronization needs to be taken into account + // if applicable. + virtual void commit() { } bool isTransform() const { return m_isTransform; } bool isUniform() const { return m_isUniform; } - bool hasBeenRunning() const { return m_hasBeenRunning; } - void setHasBeenRunning(bool has) { m_hasBeenRunning = has; } - qreal value() const; QQuickAnimatorController *controller() const { return m_controller; } protected: QQuickAnimatorJob(); - void debugAnimation(QDebug d) const Q_DECL_OVERRIDE; + void debugAnimation(QDebug d) const override; qreal progress(int time) const; @@ -173,7 +184,6 @@ protected: uint m_isTransform : 1; uint m_isUniform : 1; - uint m_hasBeenRunning : 1; }; class QQuickTransformAnimatorJob : public QQuickAnimatorJob @@ -197,7 +207,7 @@ public: } void sync(); - void apply(); + void commit(); int ref; QQuickItem *item; @@ -217,13 +227,16 @@ public: }; ~QQuickTransformAnimatorJob(); - Helper *transformHelper() const { return m_helper; } + + void commit() override; + void preSync() override; + + void setTarget(QQuickItem *item) override; protected: QQuickTransformAnimatorJob(); - void initialize(QQuickAnimatorController *controller) Q_DECL_OVERRIDE; - void nodeWasDestroyed() Q_DECL_OVERRIDE; - void targetWasDeleted() Q_DECL_OVERRIDE; + void postSync() override; + void invalidate() override; Helper *m_helper; }; @@ -231,22 +244,22 @@ protected: class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimatorJob : public QQuickTransformAnimatorJob { public: - void updateCurrentTime(int time) Q_DECL_OVERRIDE; - void writeBack() Q_DECL_OVERRIDE; + void updateCurrentTime(int time) override; + void writeBack() override; }; class Q_QUICK_PRIVATE_EXPORT QQuickXAnimatorJob : public QQuickTransformAnimatorJob { public: - void updateCurrentTime(int time) Q_DECL_OVERRIDE; - void writeBack() Q_DECL_OVERRIDE; + void updateCurrentTime(int time) override; + void writeBack() override; }; class Q_QUICK_PRIVATE_EXPORT QQuickYAnimatorJob : public QQuickTransformAnimatorJob { public: - void updateCurrentTime(int time) Q_DECL_OVERRIDE; - void writeBack() Q_DECL_OVERRIDE; + void updateCurrentTime(int time) override; + void writeBack() override; }; class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimatorJob : public QQuickTransformAnimatorJob @@ -254,8 +267,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimatorJob : public QQuickTransformA public: QQuickRotationAnimatorJob(); - void updateCurrentTime(int time) Q_DECL_OVERRIDE; - void writeBack() Q_DECL_OVERRIDE; + void updateCurrentTime(int time) override; + void writeBack() override; void setDirection(QQuickRotationAnimator::RotationDirection direction) { m_direction = direction; } QQuickRotationAnimator::RotationDirection direction() const { return m_direction; } @@ -269,10 +282,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimatorJob : public QQuickAnimatorJob public: QQuickOpacityAnimatorJob(); - void initialize(QQuickAnimatorController *controller) Q_DECL_OVERRIDE; - void updateCurrentTime(int time) Q_DECL_OVERRIDE; - void writeBack() Q_DECL_OVERRIDE; - void nodeWasDestroyed() Q_DECL_OVERRIDE; + void invalidate() override; + void updateCurrentTime(int time) override; + void writeBack() override; + void postSync() override; private: QSGOpacityNode *m_opacityNode; @@ -283,16 +296,17 @@ class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimatorJob : public QQuickAnimatorJob public: QQuickUniformAnimatorJob(); - void setTarget(QQuickItem *target) Q_DECL_OVERRIDE; + void setTarget(QQuickItem *target) override; void setUniform(const QByteArray &uniform) { m_uniform = uniform; } QByteArray uniform() const { return m_uniform; } - void afterNodeSync() Q_DECL_OVERRIDE; + void postSync() override; + + void updateCurrentTime(int time) override; + void writeBack() override; - void updateCurrentTime(int time) Q_DECL_OVERRIDE; - void writeBack() Q_DECL_OVERRIDE; - void nodeWasDestroyed() Q_DECL_OVERRIDE; + void invalidate() override; private: QByteArray m_uniform; diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp index 5c26b23ff7..5c89275c5a 100644 --- a/src/quick/util/qquickapplication.cpp +++ b/src/quick/util/qquickapplication.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "qquickapplication_p.h" - +#include <private/qquickscreen_p.h> #include <private/qobject_p.h> #include <private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> @@ -63,6 +63,12 @@ QQuickApplication::QQuickApplication(QObject *parent) this, SIGNAL(stateChanged(Qt::ApplicationState))); connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SIGNAL(activeChanged())); + connect(qApp, SIGNAL(applicationDisplayNameChanged()), + this, SIGNAL(displayNameChanged())); + + connect(qApp, &QGuiApplication::screenAdded, this, &QQuickApplication::updateScreens); + connect(qApp, &QGuiApplication::screenRemoved, this, &QQuickApplication::updateScreens); + updateScreens(); } } @@ -95,4 +101,42 @@ QFont QQuickApplication::font() const return QGuiApplication::font(); } +QString QQuickApplication::displayName() const +{ + return QGuiApplication::applicationDisplayName(); +} + +void QQuickApplication::setDisplayName(const QString &displayName) +{ + return QGuiApplication::setApplicationDisplayName(displayName); +} + +int screens_count(QQmlListProperty<QQuickScreenInfo> *prop) +{ + return static_cast<QVector<QQuickScreenInfo *> *>(prop->data)->count(); +} + +QQuickScreenInfo *screens_at(QQmlListProperty<QQuickScreenInfo> *prop, int idx) +{ + return static_cast<QVector<QQuickScreenInfo *> *>(prop->data)->at(idx); +} + +QQmlListProperty<QQuickScreenInfo> QQuickApplication::screens() +{ + return QQmlListProperty<QQuickScreenInfo>(this, + const_cast<QVector<QQuickScreenInfo *> *>(&m_screens), &screens_count, &screens_at); +} + +void QQuickApplication::updateScreens() +{ + const QList<QScreen *> screenList = QGuiApplication::screens(); + m_screens.resize(screenList.count()); + for (int i = 0; i < screenList.count(); ++i) { + if (!m_screens[i]) + m_screens[i] = new QQuickScreenInfo(this); + m_screens[i]->setWrappedScreen(screenList[i]); + } + emit screensChanged(); +} + QT_END_NAMESPACE diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h index 091cb094ed..8ee203f0da 100644 --- a/src/quick/util/qquickapplication_p.h +++ b/src/quick/util/qquickapplication_p.h @@ -56,10 +56,10 @@ #include <qqml.h> #include <QtQml/private/qqmlglobal_p.h> #include <private/qtquickglobal_p.h> +#include "../items/qquickscreen_p.h" QT_BEGIN_NAMESPACE - class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication { Q_OBJECT @@ -68,6 +68,8 @@ class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication Q_PROPERTY(bool supportsMultipleWindows READ supportsMultipleWindows CONSTANT) Q_PROPERTY(Qt::ApplicationState state READ state NOTIFY stateChanged) Q_PROPERTY(QFont font READ font CONSTANT) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName NOTIFY displayNameChanged) + Q_PROPERTY(QQmlListProperty<QQuickScreenInfo> screens READ screens NOTIFY screensChanged) public: explicit QQuickApplication(QObject *parent = 0); @@ -77,14 +79,23 @@ public: bool supportsMultipleWindows() const; Qt::ApplicationState state() const; QFont font() const; + QQmlListProperty<QQuickScreenInfo> screens(); + QString displayName() const; + void setDisplayName(const QString &displayName); Q_SIGNALS: void activeChanged(); + void displayNameChanged(); void layoutDirectionChanged(); void stateChanged(Qt::ApplicationState state); + void screensChanged(); + +private Q_SLOTS: + void updateScreens(); private: Q_DISABLE_COPY(QQuickApplication) + QVector<QQuickScreenInfo *> m_screens; }; QT_END_NAMESPACE diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp index 1d3ee2c4be..9af1d41b29 100644 --- a/src/quick/util/qquickbehavior.cpp +++ b/src/quick/util/qquickbehavior.cpp @@ -60,7 +60,7 @@ public: QQuickBehaviorPrivate() : animation(0), animationInstance(0), enabled(true), finalized(false) , blockRunningChanged(false) {} - virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState); + void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override; QQmlProperty property; QVariant targetValue; diff --git a/src/quick/util/qquickbehavior_p.h b/src/quick/util/qquickbehavior_p.h index c3438d8c6d..b3fd2af400 100644 --- a/src/quick/util/qquickbehavior_p.h +++ b/src/quick/util/qquickbehavior_p.h @@ -75,8 +75,8 @@ public: QQuickBehavior(QObject *parent=0); ~QQuickBehavior(); - virtual void setTarget(const QQmlProperty &); - virtual void write(const QVariant &value); + void setTarget(const QQmlProperty &) override; + void write(const QVariant &value) override; QQuickAbstractAnimation *animation(); void setAnimation(QQuickAbstractAnimation *); diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index 0c245d2b23..c4182d9f93 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -44,13 +44,6 @@ QT_BEGIN_NAMESPACE -class QQuickImageProviderPrivate -{ -public: - QQuickImageProvider::ImageType type; - QQuickImageProvider::Flags flags; -}; - /*! \class QQuickTextureFactory \since 5.0 @@ -349,6 +342,7 @@ QQuickImageProvider::QQuickImageProvider(ImageType type, Flags flags) { d->type = type; d->flags = flags; + d->isProviderWithOptions = false; } /*! @@ -502,26 +496,165 @@ QQuickAsyncImageProvider::~QQuickAsyncImageProvider() implementation of this method is reentrant. */ + +class QQuickImageProviderOptionsPrivate : public QSharedData +{ +public: + QQuickImageProviderOptionsPrivate() + : autoTransform(QQuickImageProviderOptions::UsePluginDefaultTransform) + , preserveAspectRatioCrop(false) + , preserveAspectRatioFit(false) + { + } + + QQuickImageProviderOptions::AutoTransform autoTransform; + bool preserveAspectRatioCrop; + bool preserveAspectRatioFit; +}; + /*! - \fn QImage QQuickImageProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize, bool requestedAutoTransform); + \class QQuickImageProviderOptions + \since 5.9 + \brief The QQuickImageProviderOptions class provides options for QQuickImageProviderWithOptions image requests. + \inmodule QtQuick - \internal - For future reference. + \sa QQuickImageProviderWithOptions */ /*! - \fn QPixmap QQuickImageProvider::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, bool requestedAutoTransform); + \enum QQuickImageProviderOptions::AutoTransform - \internal - For future reference. + Whether the image provider should apply transformation metadata on read(). + + \value UsePluginDefaultTransform Image provider should do its default behavior on whether applying transformation metadata on read or not + \value ApplyTransform Image provider should apply transformation metadata on read + \value DoNotApplyTransform Image provider should not apply transformation metadata on read */ +QQuickImageProviderOptions::QQuickImageProviderOptions() + : d(new QQuickImageProviderOptionsPrivate()) +{ +} + +QQuickImageProviderOptions::~QQuickImageProviderOptions() +{ +} + +QQuickImageProviderOptions::QQuickImageProviderOptions(const QQuickImageProviderOptions &other) + : d(other.d) +{ +} + +QQuickImageProviderOptions& QQuickImageProviderOptions::operator=(const QQuickImageProviderOptions &other) +{ + d = other.d; + return *this; +} + +bool QQuickImageProviderOptions::operator==(const QQuickImageProviderOptions &other) const +{ + return d->autoTransform == other.d->autoTransform && + d->preserveAspectRatioCrop == other.d->preserveAspectRatioCrop && + d->preserveAspectRatioFit == other.d->preserveAspectRatioFit; +} + /*! - \fn QQuickTextureFactory *QQuickImageProvider::requestTexture(const QString &id, QSize *size, const QSize &requestedSize, bool requestedAutoTransform); + Returns whether the image provider should apply transformation metadata on read(). +*/ +QQuickImageProviderOptions::AutoTransform QQuickImageProviderOptions::autoTransform() const +{ + return d->autoTransform; +} + +void QQuickImageProviderOptions::setAutoTransform(QQuickImageProviderOptions::AutoTransform autoTransform) +{ + d->autoTransform = autoTransform; +} - \internal - For future reference. +/*! + Returns whether the image request is for a PreserveAspectCrop Image. + This allows the provider to better optimize the size of the returned image. */ +bool QQuickImageProviderOptions::preserveAspectRatioCrop() const +{ + return d->preserveAspectRatioCrop; +} + +void QQuickImageProviderOptions::setPreserveAspectRatioCrop(bool preserveAspectRatioCrop) +{ + d->preserveAspectRatioCrop = preserveAspectRatioCrop; +} + +/*! + Returns whether the image request is for a PreserveAspectFit Image. + This allows the provider to better optimize the size of the returned image. +*/ +bool QQuickImageProviderOptions::preserveAspectRatioFit() const +{ + return d->preserveAspectRatioFit; +} + +void QQuickImageProviderOptions::setPreserveAspectRatioFit(bool preserveAspectRatioFit) +{ + d->preserveAspectRatioFit = preserveAspectRatioFit; +} + + +QQuickImageProviderWithOptions::QQuickImageProviderWithOptions(ImageType type, Flags flags) + : QQuickAsyncImageProvider() +{ + QQuickImageProvider::d->type = type; + QQuickImageProvider::d->flags = flags; + QQuickImageProvider::d->isProviderWithOptions = true; +} + +QImage QQuickImageProviderWithOptions::requestImage(const QString &id, QSize *size, const QSize& requestedSize) +{ + return requestImage(id, size, requestedSize, QQuickImageProviderOptions()); +} + +QPixmap QQuickImageProviderWithOptions::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize) +{ + return requestPixmap(id, size, requestedSize, QQuickImageProviderOptions()); +} + +QQuickTextureFactory *QQuickImageProviderWithOptions::requestTexture(const QString &id, QSize *size, const QSize &requestedSize) +{ + return requestTexture(id, size, requestedSize, QQuickImageProviderOptions()); +} + +QImage QQuickImageProviderWithOptions::requestImage(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options) +{ + Q_UNUSED(options); + return QQuickAsyncImageProvider::requestImage(id, size, requestedSize); +} + +QPixmap QQuickImageProviderWithOptions::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options) +{ + Q_UNUSED(options); + return QQuickAsyncImageProvider::requestPixmap(id, size, requestedSize); +} + +QQuickTextureFactory *QQuickImageProviderWithOptions::requestTexture(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options) +{ + Q_UNUSED(options); + return QQuickAsyncImageProvider::requestTexture(id, size, requestedSize); +} + +QQuickImageResponse *QQuickImageProviderWithOptions::requestImageResponse(const QString &id, const QSize &requestedSize) +{ + Q_UNUSED(id); + Q_UNUSED(requestedSize); + if (imageType() == ImageResponse) + qWarning("ImageProvider is of ImageResponse type but has not implemented requestImageResponse()"); + return nullptr; +} + +QQuickImageResponse *QQuickImageProviderWithOptions::requestImageResponse(const QString &id, const QSize &requestedSize, const QQuickImageProviderOptions &options) +{ + Q_UNUSED(options); + return requestImageResponse(id, requestedSize); +} QT_END_NAMESPACE diff --git a/src/quick/util/qquickimageprovider.h b/src/quick/util/qquickimageprovider.h index d4719a7f5b..c77ff95f32 100644 --- a/src/quick/util/qquickimageprovider.h +++ b/src/quick/util/qquickimageprovider.h @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE class QQuickImageProviderPrivate; class QQuickAsyncImageProviderPrivate; +class QQuickImageProviderOptionsPrivate; class QSGTexture; class QQuickWindow; @@ -86,17 +87,19 @@ Q_SIGNALS: class Q_QUICK_EXPORT QQuickImageProvider : public QQmlImageProviderBase { + friend class QQuickImageProviderWithOptions; // ### Qt 6 Remove + friend class QQuickPixmapReader; // ### Qt 6 Remove public: QQuickImageProvider(ImageType type, Flags flags = Flags()); virtual ~QQuickImageProvider(); - ImageType imageType() const; - Flags flags() const; + ImageType imageType() const override; + Flags flags() const override; #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) - virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize, bool requestedAutoTransform); - virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, bool requestedAutoTransform); - virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize, bool requestedAutoTransform); + virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); + virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); + virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options); #else virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize); virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize); @@ -113,7 +116,11 @@ public: QQuickAsyncImageProvider(); virtual ~QQuickAsyncImageProvider(); +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize, const QQuickImageProviderOptions &options) = 0; +#else virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) = 0; +#endif private: QQuickAsyncImageProviderPrivate *d; diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index 457f69d20f..06ad389b49 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -156,7 +156,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathLine : public QQuickCurve public: QQuickPathLine(QObject *parent=0) : QQuickCurve(parent) {} - void addToPath(QPainterPath &path, const QQuickPathData &); + void addToPath(QPainterPath &path, const QQuickPathData &) override; }; class Q_QUICK_PRIVATE_EXPORT QQuickPathQuad : public QQuickCurve @@ -184,7 +184,7 @@ public: void setRelativeControlY(qreal y); bool hasRelativeControlY(); - void addToPath(QPainterPath &path, const QQuickPathData &); + void addToPath(QPainterPath &path, const QQuickPathData &) override; Q_SIGNALS: void controlXChanged(); @@ -242,7 +242,7 @@ public: void setRelativeControl2Y(qreal y); bool hasRelativeControl2Y(); - void addToPath(QPainterPath &path, const QQuickPathData &); + void addToPath(QPainterPath &path, const QQuickPathData &) override; Q_SIGNALS: void control1XChanged(); @@ -271,7 +271,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathCatmullRomCurve : public QQuickCurve public: QQuickPathCatmullRomCurve(QObject *parent=0) : QQuickCurve(parent) {} - void addToPath(QPainterPath &path, const QQuickPathData &); + void addToPath(QPainterPath &path, const QQuickPathData &) override; }; class Q_QUICK_PRIVATE_EXPORT QQuickPathArc : public QQuickCurve @@ -301,7 +301,7 @@ public: ArcDirection direction() const; void setDirection(ArcDirection direction); - void addToPath(QPainterPath &path, const QQuickPathData &); + void addToPath(QPainterPath &path, const QQuickPathData &) override; Q_SIGNALS: void radiusXChanged(); @@ -326,7 +326,7 @@ public: QString path() const; void setPath(const QString &path); - void addToPath(QPainterPath &path, const QQuickPathData &); + void addToPath(QPainterPath &path, const QQuickPathData &) override; Q_SIGNALS: void pathChanged(); @@ -405,8 +405,8 @@ Q_SIGNALS: void startYChanged(); protected: - virtual void componentComplete(); - virtual void classBegin(); + void componentComplete() override; + void classBegin() override; void disconnectPathElements(); void connectPathElements(); void gatherAttributes(); diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 96b88636fe..7b369a2d0f 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -140,18 +140,16 @@ public: QUrl url; bool loading; - AutoTransform autoTransform; int redirectCount; class Event : public QEvent { public: - Event(ReadError, const QString &, const QSize &, AutoTransform, QQuickTextureFactory *factory); + Event(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory); ~Event(); ReadError error; QString errorString; QSize implicitSize; - AutoTransform autoTransform; QQuickTextureFactory *textureFactory; }; void postReply(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory); @@ -177,7 +175,7 @@ class QQuickPixmapReaderThreadObject : public QObject { public: QQuickPixmapReaderThreadObject(QQuickPixmapReader *); void processJobs(); - virtual bool event(QEvent *e); + bool event(QEvent *e) override; private slots: void networkRequestDone(); void asyncResponseFinished(); @@ -205,7 +203,7 @@ protected: private: friend class QQuickPixmapReaderThreadObject; void processJobs(); - void processJob(QQuickPixmapReply *, const QUrl &, const QString &, AutoTransform, QQuickImageProvider::ImageType, QQuickImageProvider *); + void processJob(QQuickPixmapReply *, const QUrl &, const QString &, const QQuickImageProviderOptions &, QQuickImageProvider::ImageType, QQuickImageProvider *); #if QT_CONFIG(qml_network) void networkRequestDone(QNetworkReply *); #endif @@ -239,20 +237,20 @@ public: class QQuickPixmapData { public: - QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, AutoTransform transform, const QString &e) + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, const QQuickImageProviderOptions &po, const QString &e) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Error), url(u), errorString(e), requestSize(s), - requestedTransform(transform), appliedTransform(UsePluginDefault), + providerOptions(po), appliedTransform(QQuickImageProviderOptions::UsePluginDefaultTransform), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { declarativePixmaps.insert(pixmap); } - QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r, AutoTransform rTransform, AutoTransform aTransform) + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Loading), url(u), requestSize(r), - requestedTransform(rTransform), appliedTransform(aTransform), + providerOptions(po), appliedTransform(aTransform), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { @@ -260,10 +258,10 @@ public: } QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, QQuickTextureFactory *texture, - const QSize &s, const QSize &r, AutoTransform rTransform, AutoTransform aTransform) + const QSize &s, const QSize &r, const QQuickImageProviderOptions &po, QQuickImageProviderOptions::AutoTransform aTransform) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Ready), url(u), implicitSize(s), requestSize(r), - requestedTransform(rTransform), appliedTransform(aTransform), + providerOptions(po), appliedTransform(aTransform), textureFactory(texture), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { @@ -272,7 +270,7 @@ public: QQuickPixmapData(QQuickPixmap *pixmap, QQuickTextureFactory *texture) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Ready), - requestedTransform(UsePluginDefault), appliedTransform(UsePluginDefault), + appliedTransform(QQuickImageProviderOptions::UsePluginDefaultTransform), textureFactory(texture), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { @@ -306,8 +304,8 @@ public: QString errorString; QSize implicitSize; QSize requestSize; - AutoTransform requestedTransform; - AutoTransform appliedTransform; + QQuickImageProviderOptions providerOptions; + QQuickImageProviderOptions::AutoTransform appliedTransform; QQuickTextureFactory *textureFactory; @@ -336,11 +334,11 @@ void QQuickPixmapReply::postReply(ReadError error, const QString &errorString, const QSize &implicitSize, QQuickTextureFactory *factory) { loading = false; - QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, autoTransform, factory)); + QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, factory)); } -QQuickPixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, AutoTransform iTransformed, QQuickTextureFactory *factory) - : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), autoTransform(iTransformed), textureFactory(factory) +QQuickPixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, QQuickTextureFactory *factory) + : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), textureFactory(factory) { } @@ -384,25 +382,32 @@ static void maybeRemoveAlpha(QImage *image) } static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, - const QSize &requestSize, AutoTransform &autoTransform) + const QSize &requestSize, const QQuickImageProviderOptions &providerOptions, + QQuickImageProviderOptions::AutoTransform *appliedTransform = nullptr) { + const bool preserveAspectCropOrFit = providerOptions.preserveAspectRatioCrop() || providerOptions.preserveAspectRatioFit(); + QImageReader imgio(dev); - if (autoTransform != UsePluginDefault) - imgio.setAutoTransform(autoTransform == ApplyTransform); - else - autoTransform = imgio.autoTransform() ? ApplyTransform : DoNotApplyTransform; + if (providerOptions.autoTransform() != QQuickImageProviderOptions::UsePluginDefaultTransform) + imgio.setAutoTransform(providerOptions.autoTransform() == QQuickImageProviderOptions::ApplyTransform); + else if (appliedTransform) + *appliedTransform = imgio.autoTransform() ? QQuickImageProviderOptions::ApplyTransform : QQuickImageProviderOptions::DoNotApplyTransform; const bool force_scale = imgio.format() == "svg" || imgio.format() == "svgz"; if (requestSize.width() > 0 || requestSize.height() > 0) { QSize s = imgio.size(); qreal ratio = 0.0; - if (requestSize.width() && (force_scale || requestSize.width() < s.width())) { + if (requestSize.width() && (preserveAspectCropOrFit || force_scale || requestSize.width() < s.width())) { ratio = qreal(requestSize.width())/s.width(); } - if (requestSize.height() && (force_scale || requestSize.height() < s.height())) { + if (requestSize.height() && (preserveAspectCropOrFit || force_scale || requestSize.height() < s.height())) { qreal hr = qreal(requestSize.height())/s.height(); - if (ratio == 0.0 || hr < ratio) + if (ratio == 0.0) + ratio = hr; + else if (!preserveAspectCropOrFit && (hr < ratio)) + ratio = hr; + else if (preserveAspectCropOrFit && (hr > ratio)) ratio = hr; } if (ratio > 0.0) { @@ -512,7 +517,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) QByteArray all = reply->readAll(); QBuffer buff(&all); buff.open(QIODevice::ReadOnly); - if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize, job->autoTransform)) + if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize, job->data->providerOptions)) error = QQuickPixmapReply::Decoding; } // send completion event to the QQuickPixmapReply @@ -657,9 +662,8 @@ void QQuickPixmapReader::processJobs() PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url)); - AutoTransform autoTransform = job->autoTransform; locker.unlock(); - processJob(job, url, localFile, autoTransform, imageType, provider); + processJob(job, url, localFile, job->data->providerOptions, imageType, provider); locker.relock(); } } @@ -671,27 +675,50 @@ void QQuickPixmapReader::processJobs() } void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, const QString &localFile, - AutoTransform autoTransform, QQuickImageProvider::ImageType imageType, QQuickImageProvider *provider) + const QQuickImageProviderOptions &providerOptions, + QQuickImageProvider::ImageType imageType, QQuickImageProvider *provider) { // fetch if (url.scheme() == QLatin1String("image")) { // Use QQuickImageProvider QSize readSize; + if (imageType == QQuickImageProvider::Invalid) { + QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString()); + mutex.lock(); + if (!cancelled.contains(runningJob)) + runningJob->postReply(QQuickPixmapReply::Loading, errorStr, readSize, 0); + mutex.unlock(); + return; + } + + QQuickImageProviderWithOptions *providerV2 = provider->d->isProviderWithOptions ? static_cast<QQuickImageProviderWithOptions *>(provider) + : nullptr; + + if (!provider->d->isProviderWithOptions && + (providerOptions.autoTransform() != QQuickImageProviderOptions::UsePluginDefaultTransform + || providerOptions.preserveAspectRatioCrop() + || providerOptions.preserveAspectRatioFit()) + ) + { + qWarning() << "Trying to pass extra request flags to provider but it is not a QQuickImageProviderWithOptions"; + } + switch (imageType) { case QQuickImageProvider::Invalid: { - QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString()); - mutex.lock(); - if (!cancelled.contains(runningJob)) - runningJob->postReply(QQuickPixmapReply::Loading, errorStr, readSize, 0); - mutex.unlock(); + // Already handled break; } case QQuickImageProvider::Image: { - QImage image = provider->requestImage(imageId(url), &readSize, runningJob->requestSize); + QImage image; + if (providerV2) { + image = providerV2->requestImage(imageId(url), &readSize, runningJob->requestSize, providerOptions); + } else { + image = provider->requestImage(imageId(url), &readSize, runningJob->requestSize); + } QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; QString errorStr; if (image.isNull()) { @@ -707,7 +734,12 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u case QQuickImageProvider::Pixmap: { - const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, runningJob->requestSize); + QPixmap pixmap; + if (providerV2) { + pixmap = providerV2->requestPixmap(imageId(url), &readSize, runningJob->requestSize, providerOptions); + } else { + pixmap = provider->requestPixmap(imageId(url), &readSize, runningJob->requestSize); + } QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; QString errorStr; if (pixmap.isNull()) { @@ -723,7 +755,12 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u case QQuickImageProvider::Texture: { - QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, runningJob->requestSize); + QQuickTextureFactory *t; + if (providerV2) { + t = providerV2->requestTexture(imageId(url), &readSize, runningJob->requestSize, providerOptions); + } else { + t = provider->requestTexture(imageId(url), &readSize, runningJob->requestSize); + } QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; QString errorStr; if (!t) { @@ -741,8 +778,13 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u case QQuickImageProvider::ImageResponse: { - QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider); - QQuickImageResponse *response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize); + QQuickImageResponse *response; + if (providerV2) { + response = providerV2->requestImageResponse(imageId(url), runningJob->requestSize, providerOptions); + } else { + QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider); + response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize); + } QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished())); @@ -760,7 +802,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u QFile f(localFile); QSize readSize; if (f.open(QIODevice::ReadOnly)) { - if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, autoTransform)) + if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, providerOptions)) errorCode = QQuickPixmapReply::Loading; } else { errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); @@ -865,17 +907,17 @@ class QQuickPixmapKey public: const QUrl *url; const QSize *size; - AutoTransform autoTransform; + QQuickImageProviderOptions options; }; inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs) { - return *lhs.size == *rhs.size && *lhs.url == *rhs.url && lhs.autoTransform == rhs.autoTransform; + return *lhs.size == *rhs.size && *lhs.url == *rhs.url && lhs.options == rhs.options; } inline uint qHash(const QQuickPixmapKey &key) { - return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.autoTransform * 0x5c5c5c5c); + return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.options.autoTransform() * 0x5c5c5c5c); } class QQuickPixmapStore : public QObject @@ -891,7 +933,7 @@ public: void purgeCache(); protected: - virtual void timerEvent(QTimerEvent *); + void timerEvent(QTimerEvent *) override; public: QHash<QQuickPixmapKey, QQuickPixmapData *> m_cache; @@ -1041,7 +1083,7 @@ void QQuickPixmap::purgeCache() } QQuickPixmapReply::QQuickPixmapReply(QQuickPixmapData *d) -: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), autoTransform(d->appliedTransform), redirectCount(0) +: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0) { if (finishedIndex == -1) { finishedIndex = QMetaMethod::fromSignal(&QQuickPixmapReply::finished).methodIndex(); @@ -1066,7 +1108,6 @@ bool QQuickPixmapReply::event(QEvent *event) data->textureFactory = de->textureFactory; de->textureFactory = 0; data->implicitSize = de->implicitSize; - data->appliedTransform = de->autoTransform; PIXMAP_PROFILE(pixmapLoadingFinished(data->url, data->textureFactory != 0 && data->textureFactory->textureSize().isValid() ? data->textureFactory->textureSize() : @@ -1137,7 +1178,7 @@ void QQuickPixmapData::release() void QQuickPixmapData::addToCache() { if (!inCache) { - QQuickPixmapKey key = { &url, &requestSize, requestedTransform }; + QQuickPixmapKey key = { &url, &requestSize, providerOptions }; pixmapStore()->m_cache.insert(key, this); inCache = true; PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>( @@ -1148,7 +1189,7 @@ void QQuickPixmapData::addToCache() void QQuickPixmapData::removeFromCache() { if (inCache) { - QQuickPixmapKey key = { &url, &requestSize, requestedTransform }; + QQuickPixmapKey key = { &url, &requestSize, providerOptions }; pixmapStore()->m_cache.remove(key); inCache = false; PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>( @@ -1156,7 +1197,7 @@ void QQuickPixmapData::removeFromCache() } } -static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, AutoTransform autoTransform, bool *ok) +static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, const QQuickImageProviderOptions &providerOptions, bool *ok) { if (url.scheme() == QLatin1String("image")) { QSize readSize; @@ -1168,14 +1209,14 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q switch (imageType) { case QQuickImageProvider::Invalid: - return new QQuickPixmapData(declarativePixmap, url, requestSize, autoTransform, + return new QQuickPixmapData(declarativePixmap, url, requestSize, providerOptions, QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString())); case QQuickImageProvider::Texture: { QQuickTextureFactory *texture = provider->requestTexture(imageId(url), &readSize, requestSize); if (texture) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize, autoTransform, UsePluginDefault); + return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform); } break; } @@ -1185,7 +1226,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QImage image = provider->requestImage(imageId(url), &readSize, requestSize); if (!image.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform); } break; } @@ -1194,7 +1235,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize); if (!pixmap.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform); } break; } @@ -1206,7 +1247,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q } // provider has bad image type, or provider returned null image - return new QQuickPixmapData(declarativePixmap, url, requestSize, autoTransform, + return new QQuickPixmapData(declarativePixmap, url, requestSize, providerOptions, QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString())); } @@ -1220,15 +1261,15 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q if (f.open(QIODevice::ReadOnly)) { QImage image; - AutoTransform appliedTransform = autoTransform; - if (readImage(url, &f, &image, &errorString, &readSize, requestSize, appliedTransform)) { + QQuickImageProviderOptions::AutoTransform appliedTransform = providerOptions.autoTransform(); + if (readImage(url, &f, &image, &errorString, &readSize, requestSize, providerOptions, &appliedTransform)) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, appliedTransform); } } else { errorString = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); } - return new QQuickPixmapData(declarativePixmap, url, requestSize, autoTransform, errorString); + return new QQuickPixmapData(declarativePixmap, url, requestSize, providerOptions, errorString); } @@ -1257,7 +1298,7 @@ QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url, const QSize &siz QQuickPixmap::QQuickPixmap(const QUrl &url, const QImage &image) { - d = new QQuickPixmapData(this, url, new QQuickDefaultTextureFactory(image), image.size(), QSize(), UsePluginDefault, UsePluginDefault); + d = new QQuickPixmapData(this, url, new QQuickDefaultTextureFactory(image), image.size(), QSize(), QQuickImageProviderOptions(), QQuickImageProviderOptions::UsePluginDefaultTransform); d->addToCache(); } @@ -1330,12 +1371,12 @@ const QSize &QQuickPixmap::requestSize() const return nullPixmap()->size; } -AutoTransform QQuickPixmap::autoTransform() const +QQuickImageProviderOptions::AutoTransform QQuickPixmap::autoTransform() const { if (d) return d->appliedTransform; else - return UsePluginDefault; + return QQuickImageProviderOptions::UsePluginDefaultTransform; } QQuickTextureFactory *QQuickPixmap::textureFactory() const @@ -1413,10 +1454,10 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &size) void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options) { - load(engine, url, requestSize, options, UsePluginDefault); + load(engine, url, requestSize, options, QQuickImageProviderOptions()); } -void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options, AutoTransform requestAutoTransform) +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions) { if (d) { d->declarativePixmaps.remove(this); @@ -1424,7 +1465,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques d = 0; } - QQuickPixmapKey key = { &url, &requestSize, requestAutoTransform }; + QQuickPixmapKey key = { &url, &requestSize, providerOptions }; QQuickPixmapStore *store = pixmapStore(); QHash<QQuickPixmapKey, QQuickPixmapData *>::Iterator iter = store->m_cache.end(); @@ -1450,7 +1491,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques if (!(options & QQuickPixmap::Asynchronous)) { bool ok = false; PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url)); - d = createPixmapDataSync(this, engine, url, requestSize, requestAutoTransform, &ok); + d = createPixmapDataSync(this, engine, url, requestSize, providerOptions, &ok); if (ok) { PIXMAP_PROFILE(pixmapLoadingFinished(url, QSize(width(), height()))); if (options & QQuickPixmap::Cache) @@ -1466,7 +1507,8 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques if (!engine) return; - d = new QQuickPixmapData(this, url, requestSize, requestAutoTransform, requestAutoTransform); + + d = new QQuickPixmapData(this, url, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform); if (options & QQuickPixmap::Cache) d->addToCache(); @@ -1502,7 +1544,7 @@ void QQuickPixmap::clear(QObject *obj) bool QQuickPixmap::isCached(const QUrl &url, const QSize &requestSize) { - QQuickPixmapKey key = { &url, &requestSize, UsePluginDefault }; + QQuickPixmapKey key = { &url, &requestSize, QQuickImageProviderOptions() }; QQuickPixmapStore *store = pixmapStore(); return store->m_cache.contains(key); diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h index f53e847e00..eea6a7a454 100644 --- a/src/quick/util/qquickpixmapcache_p.h +++ b/src/quick/util/qquickpixmapcache_p.h @@ -65,28 +65,62 @@ QT_BEGIN_NAMESPACE class QQmlEngine; class QQuickPixmapData; class QQuickTextureFactory; - -enum AutoTransform { - UsePluginDefault = -1, - ApplyTransform = 0, - DoNotApplyTransform = 1 -}; +class QQuickImageProviderOptionsPrivate; class QQuickDefaultTextureFactory : public QQuickTextureFactory { Q_OBJECT public: QQuickDefaultTextureFactory(const QImage &i); - QSGTexture *createTexture(QQuickWindow *window) const; - QSize textureSize() const { return size; } - int textureByteCount() const { return size.width() * size.height() * 4; } - QImage image() const { return im; } + QSGTexture *createTexture(QQuickWindow *window) const override; + QSize textureSize() const override { return size; } + int textureByteCount() const override { return size.width() * size.height() * 4; } + QImage image() const override { return im; } private: QImage im; QSize size; }; +class QQuickImageProviderPrivate +{ +public: + QQuickImageProvider::ImageType type; + QQuickImageProvider::Flags flags; + bool isProviderWithOptions; +}; + +// ### Qt 6: Make public moving to qquickimageprovider.h +class Q_QUICK_EXPORT QQuickImageProviderOptions +{ +public: + enum AutoTransform { + UsePluginDefaultTransform = -1, + ApplyTransform = 0, + DoNotApplyTransform = 1 + }; + + QQuickImageProviderOptions(); + ~QQuickImageProviderOptions(); + + QQuickImageProviderOptions(const QQuickImageProviderOptions&); + QQuickImageProviderOptions& operator=(const QQuickImageProviderOptions&); + + bool operator==(const QQuickImageProviderOptions&) const; + + AutoTransform autoTransform() const; + void setAutoTransform(AutoTransform autoTransform); + + bool preserveAspectRatioCrop() const; + void setPreserveAspectRatioCrop(bool preserveAspectRatioCrop); + + bool preserveAspectRatioFit() const; + void setPreserveAspectRatioFit(bool preserveAspectRatioFit); + +private: + QSharedDataPointer<QQuickImageProviderOptionsPrivate> d; +}; + class Q_QUICK_PRIVATE_EXPORT QQuickPixmap { Q_DECLARE_TR_FUNCTIONS(QQuickPixmap) @@ -115,7 +149,7 @@ public: const QUrl &url() const; const QSize &implicitSize() const; const QSize &requestSize() const; - AutoTransform autoTransform() const; + QQuickImageProviderOptions::AutoTransform autoTransform() const; QImage image() const; void setImage(const QImage &); void setPixmap(const QQuickPixmap &other); @@ -130,7 +164,7 @@ public: void load(QQmlEngine *, const QUrl &, QQuickPixmap::Options options); void load(QQmlEngine *, const QUrl &, const QSize &); void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options); - void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options, AutoTransform autoTransform); + void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options, const QQuickImageProviderOptions &providerOptions); void clear(); void clear(QObject *); @@ -152,6 +186,24 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPixmap::Options) +// This class will disappear with Qt6 and will just be the regular QQuickImageProvider +// ### Qt 6: Remove this class and fold it with QQuickImageProvider +class Q_QUICK_EXPORT QQuickImageProviderWithOptions : public QQuickAsyncImageProvider +{ +public: + QQuickImageProviderWithOptions(ImageType type, Flags flags = Flags()); + + QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) override; + QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize) override; + QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize) override; + QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override; + + virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); + virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options); + virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options); + virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize, const QQuickImageProviderOptions &options); +}; + QT_END_NAMESPACE #endif // QQUICKPIXMAPCACHE_H diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 3d51269bc9..fafa2edd0b 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -142,29 +142,29 @@ public: QQuickReplaceSignalHandler() {} ~QQuickReplaceSignalHandler() {} - virtual EventType type() const { return SignalHandler; } + EventType type() const override { return SignalHandler; } QQmlProperty property; QQmlBoundSignalExpressionPointer expression; QQmlBoundSignalExpressionPointer reverseExpression; QQmlBoundSignalExpressionPointer rewindExpression; - virtual void execute() { + void execute() override { QQmlPropertyPrivate::setSignalExpression(property, expression); } - virtual bool isReversable() { return true; } - virtual void reverse() { + bool isReversable() override { return true; } + void reverse() override { QQmlPropertyPrivate::setSignalExpression(property, reverseExpression); } - virtual void saveOriginals() { + void saveOriginals() override { saveCurrentValues(); reverseExpression = rewindExpression; } - virtual bool needsCopy() { return true; } - virtual void copyOriginals(QQuickStateActionEvent *other) + bool needsCopy() override { return true; } + void copyOriginals(QQuickStateActionEvent *other) override { QQuickReplaceSignalHandler *rsh = static_cast<QQuickReplaceSignalHandler*>(other); saveCurrentValues(); @@ -173,14 +173,14 @@ public: reverseExpression = rsh->reverseExpression; } - virtual void rewind() { + void rewind() override { QQmlPropertyPrivate::setSignalExpression(property, rewindExpression); } - virtual void saveCurrentValues() { + void saveCurrentValues() override { rewindExpression = QQmlPropertyPrivate::signalExpression(property); } - virtual bool override(QQuickStateActionEvent*other) { + bool override(QQuickStateActionEvent *other) override { if (other == this) return true; if (other->type() != type()) diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h index 0537750338..35b37e84cb 100644 --- a/src/quick/util/qquickpropertychanges_p.h +++ b/src/quick/util/qquickpropertychanges_p.h @@ -78,7 +78,7 @@ public: bool isExplicit() const; void setIsExplicit(bool); - virtual ActionList actions(); + ActionList actions() override; bool containsProperty(const QString &name) const; bool containsValue(const QString &name) const; @@ -103,8 +103,8 @@ public: void verifyList(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding); - virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props); - virtual void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings); + void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props) override; + void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override; }; diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp index 3e04161639..72d9c889e3 100644 --- a/src/quick/util/qquickshortcut.cpp +++ b/src/quick/util/qquickshortcut.cpp @@ -70,7 +70,10 @@ } \endqml - \sa Keys + It is also possible to set multiple shortcut \l sequences, so that the shortcut + can be \l activated via several different sequences of key presses. + + \sa Keys, {Keys::}{shortcutOverride()} */ /*! \qmlsignal QtQuick::Shortcut::activated() @@ -121,14 +124,23 @@ Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher QT_BEGIN_NAMESPACE -QQuickShortcut::QQuickShortcut(QObject *parent) : QObject(parent), m_id(0), +static QKeySequence valueToKeySequence(const QVariant &value) +{ + if (value.type() == QVariant::Int) + return QKeySequence(static_cast<QKeySequence::StandardKey>(value.toInt())); + return QKeySequence::fromString(value.toString()); +} + +QQuickShortcut::QQuickShortcut(QObject *parent) : QObject(parent), m_enabled(true), m_completed(false), m_autorepeat(true), m_context(Qt::WindowShortcut) { } QQuickShortcut::~QQuickShortcut() { - ungrabShortcut(); + ungrabShortcut(m_shortcut); + for (Shortcut &shortcut : m_shortcuts) + ungrabShortcut(shortcut); } /*! @@ -147,31 +159,79 @@ QQuickShortcut::~QQuickShortcut() onActivated: edit.wrapMode = TextEdit.Wrap } \endqml + + \sa sequences */ QVariant QQuickShortcut::sequence() const { - return m_sequence; + return m_shortcut.userValue; } -void QQuickShortcut::setSequence(const QVariant &sequence) +void QQuickShortcut::setSequence(const QVariant &value) { - if (sequence == m_sequence) + if (value == m_shortcut.userValue) return; - QKeySequence shortcut; - if (sequence.type() == QVariant::Int) - shortcut = QKeySequence(static_cast<QKeySequence::StandardKey>(sequence.toInt())); - else - shortcut = QKeySequence::fromString(sequence.toString()); + QKeySequence keySequence = valueToKeySequence(value); - grabShortcut(shortcut, m_context); - - m_sequence = sequence; - m_shortcut = shortcut; + ungrabShortcut(m_shortcut); + m_shortcut.userValue = value; + m_shortcut.keySequence = keySequence; + grabShortcut(m_shortcut, m_context); emit sequenceChanged(); } /*! + \qmlproperty list<keysequence> QtQuick::Shortcut::sequences + \since 5.9 + + This property holds multiple key sequences for the shortcut. The key sequences + can be set to one of the \l{QKeySequence::StandardKey}{standard keyboard shortcuts}, + or they can be described with strings containing sequences of up to four key + presses that are needed to \l{Shortcut::activated}{activate} the shortcut. + + \qml + Shortcut { + sequences: [StandardKey.Cut, "Ctrl+X", "Shift+Del"] + onActivated: edit.cut() + } + \endqml +*/ +QVariantList QQuickShortcut::sequences() const +{ + QVariantList values; + for (const Shortcut &shortcut : m_shortcuts) + values += shortcut.userValue; + return values; +} + +void QQuickShortcut::setSequences(const QVariantList &values) +{ + QVector<Shortcut> remainder = m_shortcuts.mid(values.count()); + m_shortcuts.resize(values.count()); + + bool changed = !remainder.isEmpty(); + for (int i = 0; i < values.count(); ++i) { + QVariant value = values.at(i); + Shortcut& shortcut = m_shortcuts[i]; + if (value == shortcut.userValue) + continue; + + QKeySequence keySequence = valueToKeySequence(value); + + ungrabShortcut(shortcut); + shortcut.userValue = value; + shortcut.keySequence = keySequence; + grabShortcut(shortcut, m_context); + + changed = true; + } + + if (changed) + emit sequencesChanged(); +} + +/*! \qmlproperty string QtQuick::Shortcut::nativeText \since 5.6 @@ -184,7 +244,7 @@ void QQuickShortcut::setSequence(const QVariant &sequence) */ QString QQuickShortcut::nativeText() const { - return m_shortcut.toString(QKeySequence::NativeText); + return m_shortcut.keySequence.toString(QKeySequence::NativeText); } /*! @@ -199,7 +259,7 @@ QString QQuickShortcut::nativeText() const */ QString QQuickShortcut::portableText() const { - return m_shortcut.toString(QKeySequence::PortableText); + return m_shortcut.keySequence.toString(QKeySequence::PortableText); } /*! @@ -219,8 +279,9 @@ void QQuickShortcut::setEnabled(bool enabled) if (enabled == m_enabled) return; - if (m_id) - QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enabled, m_id, this); + setEnabled(m_shortcut, enabled); + for (Shortcut &shortcut : m_shortcuts) + setEnabled(shortcut, enabled); m_enabled = enabled; emit enabledChanged(); @@ -243,8 +304,9 @@ void QQuickShortcut::setAutoRepeat(bool repeat) if (repeat == m_autorepeat) return; - if (m_id) - QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(repeat, m_id, this); + setAutoRepeat(m_shortcut, repeat); + for (Shortcut &shortcut : m_shortcuts) + setAutoRepeat(shortcut, repeat); m_autorepeat = repeat; emit autoRepeatChanged(); @@ -279,9 +341,9 @@ void QQuickShortcut::setContext(Qt::ShortcutContext context) if (context == m_context) return; - grabShortcut(m_shortcut, context); - + ungrabShortcut(m_shortcut); m_context = context; + grabShortcut(m_shortcut, context); emit contextChanged(); } @@ -293,13 +355,19 @@ void QQuickShortcut::componentComplete() { m_completed = true; grabShortcut(m_shortcut, m_context); + for (Shortcut &shortcut : m_shortcuts) + grabShortcut(shortcut, m_context); } bool QQuickShortcut::event(QEvent *event) { if (m_enabled && event->type() == QEvent::Shortcut) { QShortcutEvent *se = static_cast<QShortcutEvent *>(event); - if (se->shortcutId() == m_id && se->key() == m_shortcut){ + bool match = m_shortcut.matches(se); + int i = 0; + while (!match && i < m_shortcuts.count()) + match |= m_shortcuts.at(i++).matches(se); + if (match) { if (se->isAmbiguous()) emit activatedAmbiguously(); else @@ -310,25 +378,40 @@ bool QQuickShortcut::event(QEvent *event) return false; } -void QQuickShortcut::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context) +bool QQuickShortcut::Shortcut::matches(QShortcutEvent *event) const { - ungrabShortcut(); + return event->shortcutId() == id && event->key() == keySequence; +} + +void QQuickShortcut::setEnabled(QQuickShortcut::Shortcut &shortcut, bool enabled) +{ + if (shortcut.id) + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enabled, shortcut.id, this); +} - if (m_completed && !sequence.isEmpty()) { +void QQuickShortcut::setAutoRepeat(QQuickShortcut::Shortcut &shortcut, bool repeat) +{ + if (shortcut.id) + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(repeat, shortcut.id, this); +} + +void QQuickShortcut::grabShortcut(Shortcut &shortcut, Qt::ShortcutContext context) +{ + if (m_completed && !shortcut.keySequence.isEmpty()) { QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance(); - m_id = pApp->shortcutMap.addShortcut(this, sequence, context, *ctxMatcher()); + shortcut.id = pApp->shortcutMap.addShortcut(this, shortcut.keySequence, context, *ctxMatcher()); if (!m_enabled) - pApp->shortcutMap.setShortcutEnabled(false, m_id, this); + pApp->shortcutMap.setShortcutEnabled(false, shortcut.id, this); if (!m_autorepeat) - pApp->shortcutMap.setShortcutAutoRepeat(false, m_id, this); + pApp->shortcutMap.setShortcutAutoRepeat(false, shortcut.id, this); } } -void QQuickShortcut::ungrabShortcut() +void QQuickShortcut::ungrabShortcut(Shortcut &shortcut) { - if (m_id) { - QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(m_id, this); - m_id = 0; + if (shortcut.id) { + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(shortcut.id, this); + shortcut.id = 0; } } diff --git a/src/quick/util/qquickshortcut_p.h b/src/quick/util/qquickshortcut_p.h index b3f33a33c1..93430ad893 100644 --- a/src/quick/util/qquickshortcut_p.h +++ b/src/quick/util/qquickshortcut_p.h @@ -52,17 +52,21 @@ // #include <QtCore/qobject.h> +#include <QtCore/qvector.h> #include <QtCore/qvariant.h> #include <QtGui/qkeysequence.h> #include <QtQml/qqmlparserstatus.h> QT_BEGIN_NAMESPACE +class QShortcutEvent; + class QQuickShortcut : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QVariant sequence READ sequence WRITE setSequence NOTIFY sequenceChanged FINAL) + Q_PROPERTY(QVariantList sequences READ sequences WRITE setSequences NOTIFY sequencesChanged FINAL REVISION 9) Q_PROPERTY(QString nativeText READ nativeText NOTIFY sequenceChanged FINAL REVISION 1) Q_PROPERTY(QString portableText READ portableText NOTIFY sequenceChanged FINAL REVISION 1) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL) @@ -76,6 +80,9 @@ public: QVariant sequence() const; void setSequence(const QVariant &sequence); + QVariantList sequences() const; + void setSequences(const QVariantList &sequences); + QString nativeText() const; QString portableText() const; @@ -90,6 +97,7 @@ public: Q_SIGNALS: void sequenceChanged(); + Q_REVISION(9) void sequencesChanged(); void enabledChanged(); void autoRepeatChanged(); void contextChanged(); @@ -102,17 +110,26 @@ protected: void componentComplete() Q_DECL_OVERRIDE; bool event(QEvent *event) Q_DECL_OVERRIDE; - void grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context); - void ungrabShortcut(); + struct Shortcut { + bool matches(QShortcutEvent *event) const; + int id; + QVariant userValue; + QKeySequence keySequence; + }; + + void setEnabled(Shortcut &shortcut, bool enabled); + void setAutoRepeat(Shortcut &shortcut, bool repeat); + + void grabShortcut(Shortcut &shortcut, Qt::ShortcutContext context); + void ungrabShortcut(Shortcut &shortcut); private: - int m_id; bool m_enabled; bool m_completed; bool m_autorepeat; - QKeySequence m_shortcut; Qt::ShortcutContext m_context; - QVariant m_sequence; + Shortcut m_shortcut; + QVector<Shortcut> m_shortcuts; }; QT_END_NAMESPACE diff --git a/src/quick/util/qquicksmoothedanimation_p.h b/src/quick/util/qquicksmoothedanimation_p.h index d640985b39..2f0e3bc0d8 100644 --- a/src/quick/util/qquicksmoothedanimation_p.h +++ b/src/quick/util/qquicksmoothedanimation_p.h @@ -79,8 +79,8 @@ public: ReversingMode reversingMode() const; void setReversingMode(ReversingMode); - virtual int duration() const; - virtual void setDuration(int); + int duration() const override; + void setDuration(int) override; qreal velocity() const; void setVelocity(qreal); @@ -88,10 +88,10 @@ public: int maximumEasingTime() const; void setMaximumEasingTime(int); - virtual QAbstractAnimationJob* transition(QQuickStateActions &actions, + QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; Q_SIGNALS: void velocityChanged(); void reversingModeChanged(); diff --git a/src/quick/util/qquicksmoothedanimation_p_p.h b/src/quick/util/qquicksmoothedanimation_p_p.h index 4a61599592..a415fdb55f 100644 --- a/src/quick/util/qquicksmoothedanimation_p_p.h +++ b/src/quick/util/qquicksmoothedanimation_p_p.h @@ -93,7 +93,7 @@ public: QQmlProperty target; - int duration() const; + int duration() const override; void restart(); void init(); @@ -101,9 +101,9 @@ public: void clearTemplate() { animationTemplate = 0; } protected: - virtual void updateCurrentTime(int); - virtual void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State); - void debugAnimation(QDebug d) const; + void updateCurrentTime(int) override; + void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State) override; + void debugAnimation(QDebug d) const override; private: qreal easeFollow(qreal); diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp index 294122150a..a9940959a0 100644 --- a/src/quick/util/qquickspringanimation.cpp +++ b/src/quick/util/qquickspringanimation.cpp @@ -61,7 +61,7 @@ public: QSpringAnimation(QQuickSpringAnimationPrivate * = 0); ~QSpringAnimation(); - int duration() const; + int duration() const override; void restart(); void init(); @@ -97,9 +97,9 @@ public: void clearTemplate() { animationTemplate = 0; } protected: - virtual void updateCurrentTime(int time); - virtual void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State); - void debugAnimation(QDebug d) const; + void updateCurrentTime(int time) override; + void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State) override; + void debugAnimation(QDebug d) const override; private: QQuickSpringAnimationPrivate *animationTemplate; diff --git a/src/quick/util/qquickspringanimation_p.h b/src/quick/util/qquickspringanimation_p.h index 141a2469d7..ffb2c41e6b 100644 --- a/src/quick/util/qquickspringanimation_p.h +++ b/src/quick/util/qquickspringanimation_p.h @@ -94,10 +94,10 @@ public: qreal modulus() const; void setModulus(qreal modulus); - virtual QAbstractAnimationJob* transition(QQuickStateActions &actions, + QAbstractAnimationJob* transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, - QObject *defaultTarget = 0); + QObject *defaultTarget = 0) override; Q_SIGNALS: void modulusChanged(); diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h index af97390efb..eba1dabecf 100644 --- a/src/quick/util/qquickstate_p_p.h +++ b/src/quick/util/qquickstate_p_p.h @@ -217,7 +217,7 @@ public: setObject(static_cast<QQuickStateOperation *>(obj)); } QList<OperationGuard> *list; - void objectDestroyed(QQuickStateOperation *) { + void objectDestroyed(QQuickStateOperation *) override { // we assume priv will always be destroyed after objectDestroyed calls list->removeOne(*this); } diff --git a/src/quick/util/qquickstatechangescript_p.h b/src/quick/util/qquickstatechangescript_p.h index 0c17b7c68c..a1315ae2ef 100644 --- a/src/quick/util/qquickstatechangescript_p.h +++ b/src/quick/util/qquickstatechangescript_p.h @@ -69,9 +69,9 @@ public: QQuickStateChangeScript(QObject *parent=0); ~QQuickStateChangeScript(); - virtual ActionList actions(); + ActionList actions() override; - virtual EventType type() const; + EventType type() const override; QQmlScriptString script() const; void setScript(const QQmlScriptString &); @@ -79,7 +79,7 @@ public: QString name() const; void setName(const QString &); - virtual void execute(); + void execute() override; }; diff --git a/src/quick/util/qquickstategroup_p.h b/src/quick/util/qquickstategroup_p.h index 78508ac166..eebe3a9e56 100644 --- a/src/quick/util/qquickstategroup_p.h +++ b/src/quick/util/qquickstategroup_p.h @@ -81,8 +81,8 @@ public: QQuickState *findState(const QString &name) const; void removeState(QQuickState *state); - virtual void classBegin(); - virtual void componentComplete(); + void classBegin() override; + void componentComplete() override; Q_SIGNALS: void stateChanged(const QString &); diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp index 4139c87eda..ae8719341d 100644 --- a/src/quick/util/qquickstyledtext.cpp +++ b/src/quick/util/qquickstyledtext.cpp @@ -721,8 +721,7 @@ void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QStri QString padding(qFloor(imgWidth / spaceWidth), QChar::Nbsp); if (!trailingSpace) textOut += QLatin1Char(' '); - textOut += padding; - textOut += QLatin1Char(' '); + textOut += padding + QLatin1Char(' '); } QPair<QStringRef,QStringRef> QQuickStyledTextPrivate::parseAttribute(const QChar *&ch, const QString &textIn) diff --git a/src/quick/util/qquicktimeline_p_p.h b/src/quick/util/qquicktimeline_p_p.h index 552f194b79..ae1087487b 100644 --- a/src/quick/util/qquicktimeline_p_p.h +++ b/src/quick/util/qquicktimeline_p_p.h @@ -100,14 +100,14 @@ public: int time() const; - virtual int duration() const; + int duration() const override; Q_SIGNALS: void updated(); void completed(); protected: - virtual void updateCurrentTime(int); - void debugAnimation(QDebug d) const; + void updateCurrentTime(int) override; + void debugAnimation(QDebug d) const override; private: void remove(QQuickTimeLineObject *); @@ -181,7 +181,7 @@ public: Q_ASSERT(_class); } - virtual void setValue(qreal v) + void setValue(qreal v) override { QQuickTimeLineValue::setValue(v); if (_setFunctionReal) (_class->*_setFunctionReal)(v); diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp index c8b5482c87..1d258d84bf 100644 --- a/src/quick/util/qquicktransition.cpp +++ b/src/quick/util/qquicktransition.cpp @@ -106,7 +106,7 @@ public: QQuickTransitionManager *manager; protected: - virtual void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState); + void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override; }; class QQuickTransitionPrivate : public QObjectPrivate, QAnimationJobChangeListener @@ -134,7 +134,7 @@ public: bool reversible; bool enabled; protected: - virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State); + void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override; static void append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a); static int animation_count(QQmlListProperty<QQuickAbstractAnimation> *list); diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp index c1bc3d60b8..77dae0d001 100644 --- a/src/quick/util/qquickutilmodule.cpp +++ b/src/quick/util/qquickutilmodule.cpp @@ -123,4 +123,6 @@ void QQuickUtilModule::defineModule() qmlRegisterType<QQuickShortcut>("QtQuick", 2, 5, "Shortcut"); qmlRegisterType<QQuickShortcut,1>("QtQuick", 2, 6, "Shortcut"); + + qmlRegisterType<QQuickShortcut,9>("QtQuick", 2, 9, "Shortcut"); } diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp index e673df0451..4afcb07a5c 100644 --- a/src/quick/util/qquickvaluetypes.cpp +++ b/src/quick/util/qquickvaluetypes.cpp @@ -56,8 +56,7 @@ namespace QQuickValueTypes { QString QQuickColorValueType::toString() const { - // to maintain behaviour with QtQuick 1.0, we just output normal toString() value. - return QVariant(v).toString(); + return v.name(v.alpha() != 255 ? QColor::HexArgb : QColor::HexRgb); } qreal QQuickColorValueType::r() const |