diff options
author | Liang Qi <liang.qi@qt.io> | 2016-11-23 10:49:37 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-11-23 10:49:37 +0100 |
commit | 5d4cbf4094c9b290626aab89e4bd92edd29ce49f (patch) | |
tree | eac893652c724f057fba493688b16e212fd844dd | |
parent | 13cf5f02ce788f19a73e5d5c3da76e57291761a5 (diff) | |
parent | 07cde200e55ee03bf9e2f9af89c20f91072deccc (diff) |
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts:
src/qml/jsruntime/qv4object_p.h
Change-Id: Iff4d3aba7710a999b8befdc493cbe959e1ce02f9
75 files changed, 768 insertions, 535 deletions
diff --git a/examples/quick/demos/stocqt/content/StockListModel.qml b/examples/quick/demos/stocqt/content/StockListModel.qml index be00e7bb1c..9b48124bda 100644 --- a/examples/quick/demos/stocqt/content/StockListModel.qml +++ b/examples/quick/demos/stocqt/content/StockListModel.qml @@ -42,6 +42,72 @@ import QtQuick 2.0 ListModel { id: stocks + + // pre-fetch data for all entries + Component.onCompleted: { + for (var idx = 0; idx < count; ++idx) { + getCloseValue(idx) + } + } + + function requestUrl(stockId) { + var endDate = new Date(""); // today + var startDate = new Date() + startDate.setDate(startDate.getDate() - 5); + + var request = "http://ichart.finance.yahoo.com/table.csv?"; + request += "s=" + stockId; + request += "&g=d"; + request += "&a=" + startDate.getMonth(); + request += "&b=" + startDate.getDate(); + request += "&c=" + startDate.getFullYear(); + request += "&d=" + endDate.getMonth(); + request += "&e=" + endDate.getDate(); + request += "&f=" + endDate.getFullYear(); + request += "&g=d"; + request += "&ignore=.csv"; + return request; + } + + function getCloseValue(index) { + var req = requestUrl(get(index).stockId); + + if (!req) + return; + + var xhr = new XMLHttpRequest; + + xhr.open("GET", req, true); + + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.LOADING || xhr.readyState === XMLHttpRequest.DONE) { + var records = xhr.responseText.split('\n'); + if (records.length > 0 && xhr.status == 200) { + var r = records[1].split(','); + var today = parseFloat(r[4]); + setProperty(index, "value", today.toFixed(2)); + + r = records[2].split(','); + var yesterday = parseFloat(r[4]); + var change = today - yesterday; + if (change >= 0.0) + setProperty(index, "change", "+" + change.toFixed(2)); + else + setProperty(index, "change", change.toFixed(2)); + + var changePercentage = (change / yesterday) * 100.0; + if (changePercentage >= 0.0) + setProperty(index, "changePercentage", "+" + changePercentage.toFixed(2) + "%"); + else + setProperty(index, "changePercentage", changePercentage.toFixed(2) + "%"); + } else { + var unknown = "n/a"; + set(index, {"value": unknown, "change": unknown, "changePercentage": unknown}); + } + } + } + xhr.send() + } // Uncomment to test invalid entries // ListElement {name: "The Qt Company"; stockId: "TQTC"; value: "999.0"; change: "0.0"; changePercentage: "0.0"} diff --git a/examples/quick/demos/stocqt/content/StockListView.qml b/examples/quick/demos/stocqt/content/StockListView.qml index 59f36b42cc..d2bd52a69d 100644 --- a/examples/quick/demos/stocqt/content/StockListView.qml +++ b/examples/quick/demos/stocqt/content/StockListView.qml @@ -64,65 +64,6 @@ Rectangle { model: StockListModel{} currentIndex: -1 // Don't pre-select any item - function requestUrl(stockId) { - var endDate = new Date(""); //today - var startDate = new Date() - startDate.setDate(startDate.getDate() - 5); - - var request = "http://ichart.finance.yahoo.com/table.csv?"; - request += "s=" + stockId; - request += "&g=d"; - request += "&a=" + startDate.getMonth(); - request += "&b=" + startDate.getDate(); - request += "&c=" + startDate.getFullYear(); - request += "&d=" + endDate.getMonth(); - request += "&e=" + endDate.getDate(); - request += "&f=" + endDate.getFullYear(); - request += "&g=d"; - request += "&ignore=.csv"; - return request; - } - - function getCloseValue(index) { - var req = requestUrl(model.get(index).stockId); - - if (!req) - return; - - var xhr = new XMLHttpRequest; - - xhr.open("GET", req, true); - - xhr.onreadystatechange = function() { - if (xhr.readyState === XMLHttpRequest.LOADING || xhr.readyState === XMLHttpRequest.DONE) { - var records = xhr.responseText.split('\n'); - if (records.length > 0 && xhr.status == 200) { - var r = records[1].split(','); - var today = parseFloat(r[4]); - model.setProperty(index, "value", today.toFixed(2)); - - r = records[2].split(','); - var yesterday = parseFloat(r[4]); - var change = today - yesterday; - if (change >= 0.0) - model.setProperty(index, "change", "+" + change.toFixed(2)); - else - model.setProperty(index, "change", change.toFixed(2)); - - var changePercentage = (change / yesterday) * 100.0; - if (changePercentage >= 0.0) - model.setProperty(index, "changePercentage", "+" + changePercentage.toFixed(2) + "%"); - else - model.setProperty(index, "changePercentage", changePercentage.toFixed(2) + "%"); - } else { - var unknown = "n/a"; - model.set(index, {"value": unknown, "change": unknown, "changePercentage": unknown}); - } - } - } - xhr.send() - } - onCurrentIndexChanged: { if (currentItem) { root.currentStockId = model.get(currentIndex).stockId; @@ -175,7 +116,6 @@ Rectangle { horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter text: value - Component.onCompleted: view.getCloseValue(index); } Text { diff --git a/examples/quick/positioners/positioners-attachedproperties.qml b/examples/quick/positioners/positioners-attachedproperties.qml index ac2c76db47..e7fa59bb9a 100644 --- a/examples/quick/positioners/positioners-attachedproperties.qml +++ b/examples/quick/positioners/positioners-attachedproperties.qml @@ -66,14 +66,14 @@ Rectangle { anchors.left: parent.left anchors.leftMargin: page.width / 32 anchors.topMargin: page.height / 48 - spacing: elementSpacing + spacing: page.elementSpacing //! [0] Rectangle { id: green color: "#80c342" - width: 100 * ratio - height: 100 * ratio + width: 100 * page.ratio + height: 100 * page.ratio Text { anchors.left: parent.right @@ -95,8 +95,8 @@ Rectangle { Rectangle { id: blue color: "#14aaff" - width: 100 * ratio - height: 100 * ratio + width: 100 * page.ratio + height: 100 * page.ratio Text { anchors.left: parent.right @@ -117,8 +117,8 @@ Rectangle { Rectangle { id: purple color: "#6400aa" - width: 100 * ratio - height: 100 * ratio + width: 100 * page.ratio + height: 100 * page.ratio Text { anchors.left: parent.right @@ -140,8 +140,8 @@ Rectangle { Rectangle { id: hidingRect color: "#006325" - width: 100 * ratio - height: 100 * ratio + width: 100 * page.ratio + height: 100 * page.ratio visible: false Text { diff --git a/examples/quick/positioners/positioners-transitions.qml b/examples/quick/positioners/positioners-transitions.qml index 0d283f7301..17fe41a7e2 100644 --- a/examples/quick/positioners/positioners-transitions.qml +++ b/examples/quick/positioners/positioners-transitions.qml @@ -55,7 +55,7 @@ Item { interval: 2000 running: true repeat: true - onTriggered: effectiveOpacity = (effectiveOpacity == 1.0 ? 0.0 : 1.0); + onTriggered: page.effectiveOpacity = (page.effectiveOpacity == 1.0 ? 0.0 : 1.0); } Column { @@ -65,7 +65,7 @@ Item { top: parent.top topMargin: page.height / 48 } - spacing: elementSpacing + spacing: page.elementSpacing populate: Transition { NumberAnimation { properties: "x,y"; from: 200; duration: 100; easing.type: Easing.OutBounce } @@ -77,32 +77,32 @@ Item { NumberAnimation { properties: "y"; easing.type: Easing.OutBounce } } - Rectangle { color: "#80c342"; width: bigSize; height: smallSize } + Rectangle { color: "#80c342"; width: page.bigSize; height: page.smallSize } Rectangle { id: greenV1 visible: opacity != 0 - width: bigSize; height: smallSize + width: page.bigSize; height: page.smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#14aaff"; width: bigSize; height: smallSize } + Rectangle { color: "#14aaff"; width: page.bigSize; height: page.smallSize } Rectangle { id: greenV2 visible: opacity != 0 - width: bigSize; height: smallSize + width: page.bigSize; height: page.smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#6400aa"; width: bigSize; height: smallSize } - Rectangle { color: "#80c342"; width: bigSize; height: smallSize } + Rectangle { color: "#6400aa"; width: page.bigSize; height: page.smallSize } + Rectangle { color: "#80c342"; width: page.bigSize; height: page.smallSize } } Row { @@ -112,7 +112,7 @@ Item { bottom: page.bottom bottomMargin: page.height / 48 } - spacing: elementSpacing + spacing: page.elementSpacing populate: Transition { NumberAnimation { properties: "x,y"; from: 200; duration: 100; easing.type: Easing.OutBounce } @@ -124,40 +124,40 @@ Item { NumberAnimation { properties: "x"; easing.type: Easing.OutBounce } } - Rectangle { color: "#80c342"; width: smallSize; height: bigSize } + Rectangle { color: "#80c342"; width: page.smallSize; height: page.bigSize } Rectangle { id: blueH1 visible: opacity != 0 - width: smallSize; height: bigSize + width: page.smallSize; height: page.bigSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#14aaff"; width: smallSize; height: bigSize } + Rectangle { color: "#14aaff"; width: page.smallSize; height: page.bigSize } Rectangle { id: greenH2 visible: opacity != 0 - width: smallSize; height: bigSize + width: page.smallSize; height: page.bigSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#6400aa"; width: smallSize; height: bigSize } - Rectangle { color: "#80c342"; width: smallSize; height: bigSize } + Rectangle { color: "#6400aa"; width: page.smallSize; height: page.bigSize } + Rectangle { color: "#80c342"; width: page.smallSize; height: page.bigSize } } Grid { anchors.top: parent.top anchors.topMargin: page.height / 48 - anchors.left: flow.left + anchors.left: flowItem.left columns: 3 - spacing: elementSpacing + spacing: page.elementSpacing populate: Transition { NumberAnimation { properties: "x,y"; from: 200; duration: 100; easing.type: Easing.OutBounce } @@ -169,55 +169,55 @@ Item { NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } } - Rectangle { color: "#80c342"; width: smallSize; height: smallSize } + Rectangle { color: "#80c342"; width: page.smallSize; height: page.smallSize } Rectangle { id: greenG1 visible: opacity != 0 - width: smallSize; height: smallSize + width: page.smallSize; height: page.smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#14aaff"; width: smallSize; height: smallSize } + Rectangle { color: "#14aaff"; width: page.smallSize; height: page.smallSize } Rectangle { id: greenG2 visible: opacity != 0 - width: smallSize; height: smallSize + width: page.smallSize; height:page. smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#6400aa"; width: smallSize; height: smallSize } + Rectangle { color: "#6400aa"; width: page.smallSize; height: page.smallSize } Rectangle { id: greenG3 visible: opacity != 0 - width: smallSize; height: smallSize + width: page.smallSize; height: page.smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#80c342"; width: smallSize; height: smallSize } - Rectangle { color: "#14aaff"; width: smallSize; height: smallSize } - Rectangle { color: "#6400aa"; width: smallSize; height: smallSize } + Rectangle { color: "#80c342"; width:page. smallSize; height: page.smallSize } + Rectangle { color: "#14aaff"; width: smallSize; height: page.smallSize } + Rectangle { color: "#6400aa"; width: page.page.smallSize; height: page.smallSize } } Flow { - id: flow + id: flowItem anchors.right: page.right anchors.rightMargin: page.width / 32 - y: 2 * bigSize - width: 1.8 * bigSize - spacing: elementSpacing + y: 2 * page.bigSize + width: 1.8 * page.bigSize + spacing: page.elementSpacing //! [move] move: Transition { @@ -237,42 +237,42 @@ Item { } //! [populate] - Rectangle { color: "#80c342"; width: smallSize; height: smallSize } + Rectangle { color: "#80c342"; width: page.smallSize; height: page.smallSize } Rectangle { id: greenF1 visible: opacity != 0 - width: 0.6 * bigSize; height: smallSize + width: 0.6 * page.bigSize; height: page.smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#14aaff"; width: 0.3 * bigSize; height: smallSize } + Rectangle { color: "#14aaff"; width: 0.3 * page.bigSize; height: page.smallSize } Rectangle { id: greenF2 visible: opacity != 0 - width: 0.6 * bigSize; height: smallSize + width: 0.6 * page.bigSize; height: page.smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#6400aa"; width: smallSize; height: smallSize } + Rectangle { color: "#6400aa"; width: page.smallSize; height: page.smallSize } Rectangle { id: greenF3 visible: opacity != 0 - width: 0.4 * bigSize; height: smallSize + width: 0.4 * page.bigSize; height: page.smallSize color: "#006325" border.color: "transparent" Behavior on opacity { NumberAnimation {} } - opacity: effectiveOpacity + opacity: page.effectiveOpacity } - Rectangle { color: "#80c342"; width: 0.8 * bigSize; height: smallSize } + Rectangle { color: "#80c342"; width: 0.8 * page.bigSize; height: page.smallSize } } } diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp index 3b377f1cb1..9916769241 100644 --- a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp +++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp @@ -42,12 +42,10 @@ #include <QQuickItem> #include <QQuickWindow> #include <QSGRendererInterface> +#include <QFile> #if QT_CONFIG(d3d12) -#include "vs_shader.hlslh" -#include "ps_shader.hlslh" - D3D12RenderNode::D3D12RenderNode(QQuickItem *item) : m_item(item) { @@ -78,7 +76,7 @@ void D3D12RenderNode::releaseResources() void D3D12RenderNode::init() { QSGRendererInterface *rif = m_item->window()->rendererInterface(); - m_device = static_cast<ID3D12Device *>(rif->getResource(m_item->window(), QSGRendererInterface::Device)); + m_device = static_cast<ID3D12Device *>(rif->getResource(m_item->window(), QSGRendererInterface::DeviceResource)); Q_ASSERT(m_device); D3D12_ROOT_PARAMETER rootParameter; @@ -111,12 +109,25 @@ void D3D12RenderNode::init() { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; + QFile f(QStringLiteral(":/scenegraph/rendernode/shader_vert.cso")); + if (!f.open(QIODevice::ReadOnly)) { + qWarning("Failed to open file with vertex shader bytecode"); + return; + } + QByteArray vshader_cso = f.readAll(); + f.close(); + f.setFileName(QStringLiteral(":/scenegraph/rendernode/shader_frag.cso")); + if (!f.open(QIODevice::ReadOnly)) { + qWarning("Failed to open file with fragment shader bytecode"); + return; + } + QByteArray fshader_cso = f.readAll(); D3D12_SHADER_BYTECODE vshader; - vshader.pShaderBytecode = g_VS_Simple; - vshader.BytecodeLength = sizeof(g_VS_Simple); + vshader.pShaderBytecode = vshader_cso.constData(); + vshader.BytecodeLength = vshader_cso.size(); D3D12_SHADER_BYTECODE pshader; - pshader.pShaderBytecode = g_PS_Simple; - pshader.BytecodeLength = sizeof(g_PS_Simple); + pshader.pShaderBytecode = fshader_cso.constData(); + pshader.BytecodeLength = fshader_cso.size(); D3D12_RASTERIZER_DESC rastDesc = {}; rastDesc.FillMode = D3D12_FILL_MODE_SOLID; @@ -235,7 +246,8 @@ void D3D12RenderNode::render(const RenderState *state) init(); QSGRendererInterface *rif = m_item->window()->rendererInterface(); - ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>(rif->getResource(m_item->window(), QSGRendererInterface::CommandList)); + ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>( + rif->getResource(m_item->window(), QSGRendererInterface::CommandListResource)); Q_ASSERT(commandList); const int msize = 16 * sizeof(float); diff --git a/examples/quick/scenegraph/rendernode/rendernode.pro b/examples/quick/scenegraph/rendernode/rendernode.pro index 968902a5be..76e498042b 100644 --- a/examples/quick/scenegraph/rendernode/rendernode.pro +++ b/examples/quick/scenegraph/rendernode/rendernode.pro @@ -15,24 +15,10 @@ target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/rendernode INSTALLS += target OTHER_FILES += \ - main.qml \ - shader.hlsl + main.qml qtConfig(d3d12) { HEADERS += d3d12renderer.h SOURCES += d3d12renderer.cpp LIBS += -ld3d12 - - VSPS = shader.hlsl - vshader.input = VSPS - vshader.header = vs_shader.hlslh - vshader.entry = VS_Simple - vshader.type = vs_5_0 - pshader.input = VSPS - pshader.header = ps_shader.hlslh - pshader.entry = PS_Simple - pshader.type = ps_5_0 - - HLSL_SHADERS = vshader pshader - load(hlsl_bytecode_header) } diff --git a/examples/quick/scenegraph/rendernode/rendernode.qrc b/examples/quick/scenegraph/rendernode/rendernode.qrc index 3674baccd8..049adcf8a6 100644 --- a/examples/quick/scenegraph/rendernode/rendernode.qrc +++ b/examples/quick/scenegraph/rendernode/rendernode.qrc @@ -1,5 +1,7 @@ <RCC> <qresource prefix="/scenegraph/rendernode"> <file>main.qml</file> + <file>shader_vert.cso</file> + <file>shader_frag.cso</file> </qresource> </RCC> diff --git a/examples/quick/scenegraph/rendernode/shader_frag.cso b/examples/quick/scenegraph/rendernode/shader_frag.cso Binary files differnew file mode 100644 index 0000000000..686c6af3fc --- /dev/null +++ b/examples/quick/scenegraph/rendernode/shader_frag.cso diff --git a/examples/quick/scenegraph/rendernode/shader_vert.cso b/examples/quick/scenegraph/rendernode/shader_vert.cso Binary files differnew file mode 100644 index 0000000000..fa13be5160 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/shader_vert.cso diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp index 06e406874a..d303b9ef13 100644 --- a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp +++ b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp @@ -61,7 +61,7 @@ void SoftwareRenderNode::releaseResources() void SoftwareRenderNode::render(const RenderState *renderState) { QSGRendererInterface *rif = m_item->window()->rendererInterface(); - QPainter *p = static_cast<QPainter *>(rif->getResource(m_item->window(), QSGRendererInterface::Painter)); + QPainter *p = static_cast<QPainter *>(rif->getResource(m_item->window(), QSGRendererInterface::PainterResource)); Q_ASSERT(p); p->setTransform(matrix()->toTransform()); diff --git a/examples/quick/shared/shared.h b/examples/quick/shared/shared.h index d8fb80b97e..0eed618d9d 100644 --- a/examples/quick/shared/shared.h +++ b/examples/quick/shared/shared.h @@ -44,6 +44,7 @@ #include <QQuickView> //Not using QQmlApplicationEngine because many examples don't have a Window{} #define DECLARATIVE_EXAMPLE_MAIN(NAME) int main(int argc, char* argv[]) \ {\ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);\ QGuiApplication app(argc,argv);\ app.setOrganizationName("QtProject");\ app.setOrganizationDomain("qt-project.org");\ diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml index 683200a259..d22ec7c44f 100644 --- a/src/imports/testlib/TestCase.qml +++ b/src/imports/testlib/TestCase.qml @@ -221,7 +221,7 @@ Item { \qmlproperty string TestCase::name This property defines the name of the test case for result reporting. - The default is the empty string. + The default value is an empty string. \code TestCase { @@ -835,7 +835,7 @@ Item { \c{QEXPECT_FAIL(tag, message, Abort)} in C++. If the test is not data-driven, then \a tag must be set to - the empty string. + an empty string. \sa expectFailContinue() */ @@ -861,7 +861,7 @@ Item { \c{QEXPECT_FAIL(tag, message, Continue)} in C++. If the test is not data-driven, then \a tag must be set to - the empty string. + an empty string. \sa expectFail() */ diff --git a/src/imports/window/plugins.qmltypes b/src/imports/window/plugins.qmltypes index 6a8dbfa024..a79bd8c332 100644 --- a/src/imports/window/plugins.qmltypes +++ b/src/imports/window/plugins.qmltypes @@ -55,8 +55,12 @@ Module { name: "QQuickWindow" defaultProperty: "data" prototype: "QWindow" - exports: ["QtQuick.Window/Window 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Window/Window 2.0", + "QtQuick.Window/Window 2.1", + "QtQuick.Window/Window 2.2" + ] + exportMetaObjectRevisions: [0, 1, 2] Enum { name: "SceneGraphError" values: { diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index c68153aca8..e6b921792f 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1292,14 +1292,16 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node) // OS X 10.8.3 introduced a bug in the AMD drivers, for at least the 2011 macbook pros, // causing point sprites who read gl_PointCoord in the frag shader to come out as // green-red blobs. - if (perfLevel < Deformable && strstr((char *) glGetString(GL_VENDOR), "ATI")) { + const GLubyte *glVendor = QOpenGLContext::currentContext()->functions()->glGetString(GL_VENDOR); + if (perfLevel < Deformable && glVendor && strstr((char *) glVendor, "ATI")) { perfLevel = Deformable; } #endif #ifdef Q_OS_LINUX // Nouveau drivers can potentially freeze a machine entirely when taking the point-sprite path. - if (perfLevel < Deformable && strstr((const char *) glGetString(GL_VENDOR), "nouveau")) + const GLubyte *glVendor = QOpenGLContext::currentContext()->functions()->glGetString(GL_VENDOR); + if (perfLevel < Deformable && glVendor && strstr((const char *) glVendor, "nouveau")) perfLevel = Deformable; #endif diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp index a318ce23f7..44f79ebea7 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp @@ -3236,11 +3236,11 @@ void QSGD3D12EnginePrivate::DeviceLossTester::killDevice() void *QSGD3D12EnginePrivate::getResource(QSGRendererInterface::Resource resource) const { switch (resource) { - case QSGRendererInterface::Device: + case QSGRendererInterface::DeviceResource: return device; - case QSGRendererInterface::CommandQueue: + case QSGRendererInterface::CommandQueueResource: return commandQueue.Get(); - case QSGRendererInterface::CommandList: + case QSGRendererInterface::CommandListResource: return commandList; default: break; diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp index 783caa280f..1f01c440e5 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12publicnodes.cpp @@ -39,10 +39,6 @@ #include "qsgd3d12publicnodes_p.h" -// for rebuildGeometry -#include <private/qsgdefaultninepatchnode_p.h> -#include <private/qsgdefaultimagenode_p.h> - QT_BEGIN_NAMESPACE QSGD3D12RectangleNode::QSGD3D12RectangleNode() @@ -138,7 +134,7 @@ void QSGD3D12ImageNode::setRect(const QRectF &r) return; m_rect = r; - QSGDefaultImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); + QSGImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); markDirty(DirtyGeometry); } @@ -153,7 +149,7 @@ void QSGD3D12ImageNode::setSourceRect(const QRectF &r) return; m_sourceRect = r; - QSGDefaultImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); + QSGImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); markDirty(DirtyGeometry); } @@ -170,7 +166,7 @@ void QSGD3D12ImageNode::setTexture(QSGTexture *texture) delete m_material.texture(); m_material.setTexture(texture); - QSGDefaultImageNode::rebuildGeometry(&m_geometry, texture, m_rect, m_sourceRect, m_texCoordMode); + QSGImageNode::rebuildGeometry(&m_geometry, texture, m_rect, m_sourceRect, m_texCoordMode); DirtyState dirty = DirtyMaterial; const bool wasAtlas = m_isAtlasTexture; @@ -192,7 +188,7 @@ void QSGD3D12ImageNode::setTextureCoordinatesTransform(TextureCoordinatesTransfo return; m_texCoordMode = mode; - QSGDefaultImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); + QSGImageNode::rebuildGeometry(&m_geometry, texture(), m_rect, m_sourceRect, m_texCoordMode); markDirty(DirtyMaterial); } @@ -247,7 +243,7 @@ void QSGD3D12NinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal void QSGD3D12NinePatchNode::update() { - QSGDefaultNinePatchNode::rebuildGeometry(m_material.texture(), &m_geometry, m_padding, m_bounds, m_devicePixelRatio); + QSGNinePatchNode::rebuildGeometry(m_material.texture(), &m_geometry, m_padding, m_bounds, m_devicePixelRatio); markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial); } diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 4fa0cf421b..46de24c264 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -2692,6 +2692,7 @@ void convertConst(Const *c, Type targetType) case UndefinedType: c->value = qt_qnan(); c->type = targetType; + break; default: Q_UNIMPLEMENTED(); Q_ASSERT(!"Unimplemented!"); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 843a6f4d94..a46066bde4 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -131,7 +131,8 @@ public: Value *jsAlloca(int nValues) { Value *ptr = jsStackTop; jsStackTop = ptr + nValues; - memset(ptr, 0, nValues*sizeof(Value)); + for (int i = 0; i < nValues; ++i) + ptr[i] = Primitive::undefinedValue(); return ptr; } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 1fff5a45da..28b255bd9a 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -107,13 +107,20 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} (classname::func == QV4::Managed::func ? 0 : classname::func) // Q_VTABLE_FUNCTION triggers a bogus tautological-compare warning in GCC6+ -#if defined(Q_CC_GNU) && Q_CC_GNU >= 600 +#if (defined(Q_CC_GNU) && Q_CC_GNU >= 600) #define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ QT_WARNING_PUSH; \ QT_WARNING_DISABLE_GCC("-Wtautological-compare") #define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF \ ;QT_WARNING_POP +#elif defined(Q_CC_CLANG) && Q_CC_CLANG >= 306 +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ + QT_WARNING_PUSH; \ + QT_WARNING_DISABLE_CLANG("-Wtautological-compare") + +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF \ + ;QT_WARNING_POP #else #define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON #define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 161c7746da..00a004ef5f 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -58,8 +58,6 @@ #include "qv4value_p.h" #include "qv4internalclass_p.h" -#include <type_traits> - QT_BEGIN_NAMESPACE @@ -147,7 +145,7 @@ struct ObjectVTable #define DEFINE_OBJECT_VTABLE_BASE(classname) \ const QV4::ObjectVTable classname::static_vtbl = \ { \ - DEFINE_MANAGED_VTABLE_INT(classname, (std::is_same<classname::SuperClass, Object>::value) ? Q_NULLPTR : &classname::SuperClass::static_vtbl.vTable), \ + DEFINE_MANAGED_VTABLE_INT(classname, (std::is_same<classname::SuperClass, Object>::value) ? nullptr : &classname::SuperClass::static_vtbl.vTable), \ call, \ construct, \ get, \ diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 3365ffe637..1efd8cb714 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -46,6 +46,7 @@ #include "qv4stringobject_p.h" #endif #include <QtCore/QHash> +#include <QtCore/private/qnumeric_p.h> using namespace QV4; diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index aac2a42a33..562aa1c88a 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -1100,6 +1100,13 @@ QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QStringRef &n return qQmlPropertyCacheProperty<const QStringRef &>(engine, obj, name, context, local); } +QQmlPropertyData * +QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QLatin1String &name, + QQmlContextData *context, QQmlPropertyData &local) +{ + return qQmlPropertyCacheProperty<const QLatin1String &>(engine, obj, name, context, local); +} + // these two functions are copied from qmetaobject.cpp static inline const QMetaObjectPrivate *priv(const uint* data) { return reinterpret_cast<const QMetaObjectPrivate*>(data); } diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index d34d1bf387..64be1cb206 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -408,6 +408,8 @@ public: static QQmlPropertyData *property(QJSEngine *, QObject *, const QStringRef &, QQmlContextData *, QQmlPropertyData &); + static QQmlPropertyData *property(QJSEngine *, QObject *, const QLatin1String &, + QQmlContextData *, QQmlPropertyData &); static QQmlPropertyData *property(QJSEngine *, QObject *, const QV4::String *, QQmlContextData *, QQmlPropertyData &); diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 1e9e0149dc..2aed4d9972 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -165,9 +165,9 @@ private: void QQmlConnections::setTarget(QObject *obj) { Q_D(QQmlConnections); - d->targetSet = true; // even if setting to 0, it is *set* - if (d->target == obj) + if (d->targetSet && d->target == obj) return; + d->targetSet = true; // even if setting to 0, it is *set* foreach (QQmlBoundSignal *s, d->boundsignals) { // It is possible that target is being changed due to one of our signal // handlers -> use deleteLater(). diff --git a/src/qmltest/quicktestevent.cpp b/src/qmltest/quicktestevent.cpp index 7a2ec30a5a..26f0521cdf 100644 --- a/src/qmltest/quicktestevent.cpp +++ b/src/qmltest/quicktestevent.cpp @@ -183,6 +183,7 @@ namespace QtQuickTest case MouseMove: // with move event the button is NoButton, but 'buttons' holds the currently pressed buttons me = QMouseEvent(QEvent::MouseMove, pos, window->mapToGlobal(pos), Qt::NoButton, button, stateKey); + me.setTimestamp(++lastMouseTimestamp); break; default: QTEST_ASSERT(false); diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index a7a4a2b882..4162314cd3 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -617,74 +617,75 @@ void QQuickAnchorsPrivate::updateVerticalAnchors() if (fill || centerIn || !isItemComplete()) return; - if (updatingVerticalAnchor < 2) { - ++updatingVerticalAnchor; - if (usedAnchors & QQuickAnchors::TopAnchor) { - //Handle stretching - bool invalid = true; + if (Q_UNLIKELY(updatingVerticalAnchor > 1)) { + // ### Make this certain :) + qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor."); + return; + } + + ++updatingVerticalAnchor; + if (usedAnchors & QQuickAnchors::TopAnchor) { + //Handle stretching + bool invalid = true; + qreal height = 0.0; + if (usedAnchors & QQuickAnchors::BottomAnchor) { + invalid = calcStretch(topAnchorItem, topAnchorLine, + bottomAnchorItem, bottomAnchorLine, + topMargin, -bottomMargin, QQuickAnchors::TopAnchor, height); + } else if (usedAnchors & QQuickAnchors::VCenterAnchor) { + invalid = calcStretch(topAnchorItem, topAnchorLine, + vCenterAnchorItem, vCenterAnchorLine, + topMargin, vCenterOffset, QQuickAnchors::TopAnchor, height); + height *= 2; + } + if (!invalid) + setItemHeight(height); + + //Handle top + if (topAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(topAnchorItem, topAnchorLine) + topMargin); + } else if (readParentItem(topAnchorItem) == readParentItem(item)) { + setItemY(position(topAnchorItem, topAnchorLine) + topMargin); + } + } else if (usedAnchors & QQuickAnchors::BottomAnchor) { + //Handle stretching (top + bottom case is handled above) + if (usedAnchors & QQuickAnchors::VCenterAnchor) { qreal height = 0.0; - if (usedAnchors & QQuickAnchors::BottomAnchor) { - invalid = calcStretch(topAnchorItem, topAnchorLine, - bottomAnchorItem, bottomAnchorLine, - topMargin, -bottomMargin, QQuickAnchors::TopAnchor, height); - } else if (usedAnchors & QQuickAnchors::VCenterAnchor) { - invalid = calcStretch(topAnchorItem, topAnchorLine, - vCenterAnchorItem, vCenterAnchorLine, - topMargin, vCenterOffset, QQuickAnchors::TopAnchor, height); - height *= 2; - } + bool invalid = calcStretch(vCenterAnchorItem, vCenterAnchorLine, + bottomAnchorItem, bottomAnchorLine, + vCenterOffset, -bottomMargin, QQuickAnchors::TopAnchor, + height); if (!invalid) - setItemHeight(height); - - //Handle top - if (topAnchorItem == readParentItem(item)) { - setItemY(adjustedPosition(topAnchorItem, topAnchorLine) + topMargin); - } else if (readParentItem(topAnchorItem) == readParentItem(item)) { - setItemY(position(topAnchorItem, topAnchorLine) + topMargin); - } - } else if (usedAnchors & QQuickAnchors::BottomAnchor) { - //Handle stretching (top + bottom case is handled above) - if (usedAnchors & QQuickAnchors::VCenterAnchor) { - qreal height = 0.0; - bool invalid = calcStretch(vCenterAnchorItem, vCenterAnchorLine, - bottomAnchorItem, bottomAnchorLine, - vCenterOffset, -bottomMargin, QQuickAnchors::TopAnchor, - height); - if (!invalid) - setItemHeight(height*2); - } + setItemHeight(height*2); + } - //Handle bottom - if (bottomAnchorItem == readParentItem(item)) { - setItemY(adjustedPosition(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin); - } else if (readParentItem(bottomAnchorItem) == readParentItem(item)) { - setItemY(position(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin); - } - } else if (usedAnchors & QQuickAnchors::VCenterAnchor) { - //(stetching handled above) - - //Handle vCenter - if (vCenterAnchorItem == readParentItem(item)) { - setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine) - - vcenter(item) + vCenterOffset); - } else if (readParentItem(vCenterAnchorItem) == readParentItem(item)) { - setItemY(position(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset); - } - } else if (usedAnchors & QQuickAnchors::BaselineAnchor) { - //Handle baseline - if (baselineAnchorItem == readParentItem(item)) { - setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine) - - readBaselineOffset(item) + baselineOffset); - } else if (readParentItem(baselineAnchorItem) == readParentItem(item)) { - setItemY(position(baselineAnchorItem, baselineAnchorLine) - - readBaselineOffset(item) + baselineOffset); - } + //Handle bottom + if (bottomAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin); + } else if (readParentItem(bottomAnchorItem) == readParentItem(item)) { + setItemY(position(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin); + } + } else if (usedAnchors & QQuickAnchors::VCenterAnchor) { + //(stetching handled above) + + //Handle vCenter + if (vCenterAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine) + - vcenter(item) + vCenterOffset); + } else if (readParentItem(vCenterAnchorItem) == readParentItem(item)) { + setItemY(position(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset); + } + } else if (usedAnchors & QQuickAnchors::BaselineAnchor) { + //Handle baseline + if (baselineAnchorItem == readParentItem(item)) { + setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine) + - readBaselineOffset(item) + baselineOffset); + } else if (readParentItem(baselineAnchorItem) == readParentItem(item)) { + setItemY(position(baselineAnchorItem, baselineAnchorLine) + - readBaselineOffset(item) + baselineOffset); } - --updatingVerticalAnchor; - } else { - // ### Make this certain :) - qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor."); } + --updatingVerticalAnchor; } static inline QQuickAnchors::Anchor reverseAnchorLine(QQuickAnchors::Anchor anchorLine) diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h index 221b4ccb40..906f607302 100644 --- a/src/quick/items/qquickanchors_p_p.h +++ b/src/quick/items/qquickanchors_p_p.h @@ -113,12 +113,12 @@ public: , inDestructor(false) , baselineAnchorLine(QQuickAnchors::InvalidAnchor) , centerAligned(true) + , usedAnchors(QQuickAnchors::InvalidAnchor) + , componentComplete(true) , updatingFill(0) , updatingCenterIn(0) , updatingHorizontalAnchor(0) , updatingVerticalAnchor(0) - , componentComplete(true) - , usedAnchors(QQuickAnchors::InvalidAnchor) { } @@ -198,13 +198,16 @@ public: uint inDestructor : 1; QQuickAnchors::Anchor baselineAnchorLine : 7; uint centerAligned : 1; - uint updatingFill : 2; - uint updatingCenterIn : 2; - uint updatingHorizontalAnchor : 2; - uint updatingVerticalAnchor : 2; - - uint componentComplete : 1; uint usedAnchors : 7; // QQuickAnchors::Anchors + uint componentComplete : 1; + + // Instead of using a mostly empty bit field, we can stretch the following fields up to be full + // bytes. The advantage is that incrementing/decrementing does not need any combining ands/ors. + qint8 updatingFill; + qint8 updatingCenterIn; + qint8 updatingHorizontalAnchor; + qint8 updatingVerticalAnchor; + static inline QQuickAnchorsPrivate *get(QQuickAnchors *o) { return static_cast<QQuickAnchorsPrivate *>(QObjectPrivate::get(o)); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index a05bb1617e..274bfbf6d4 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2308,29 +2308,31 @@ QQuickItem::~QQuickItem() while (!d->childItems.isEmpty()) d->childItems.constFirst()->setParentItem(0); - const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); - if (anchor) - anchor->clearItem(this); - } + if (!d->changeListeners.isEmpty()) { + const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); + if (anchor) + anchor->clearItem(this); + } - /* + /* update item anchors that depended on us unless they are our child (and will also be destroyed), or our sibling, and our parent is also being destroyed. */ - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); - if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this) - anchor->update(); - } + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); + if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this) + anchor->update(); + } - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Destroyed) - change.listener->itemDestroyed(this); - } + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Destroyed) + change.listener->itemDestroyed(this); + } - d->changeListeners.clear(); + d->changeListeners.clear(); + } /* Remove any references our transforms have to us, in case they try to @@ -2601,7 +2603,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) if (parentItem) { QQuickItem *itemAncestor = parentItem; while (itemAncestor != 0) { - if (itemAncestor == this) { + if (Q_UNLIKELY(itemAncestor == this)) { qWarning() << "QQuickItem::setParentItem: Parent" << parentItem << "is already part of the subtree of" << this; return; } @@ -3549,10 +3551,12 @@ QQuickAnchors *QQuickItemPrivate::anchors() const void QQuickItemPrivate::siblingOrderChanged() { Q_Q(QQuickItem); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::SiblingOrder) { - change.listener->itemSiblingOrderChanged(q); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::SiblingOrder) { + change.listener->itemSiblingOrderChanged(q); + } } } } @@ -3654,20 +3658,18 @@ void QQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo QQuickAnchorsPrivate::get(d->_anchors)->updateMe(); QQuickGeometryChange change; - QRectF diff(newGeometry.x() - oldGeometry.x(), - newGeometry.y() - oldGeometry.y(), - newGeometry.width() - oldGeometry.width(), - newGeometry.height() - oldGeometry.height()); - change.setXChange(diff.x() != 0); - change.setYChange(diff.y() != 0); - change.setWidthChange(diff.width() != 0); - change.setHeightChange(diff.height() != 0); - - const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &listener : listeners) { - if (listener.types & QQuickItemPrivate::Geometry) { - if (change.matches(listener.gTypes)) - listener.listener->itemGeometryChanged(this, change, diff); + change.setXChange(newGeometry.x() != oldGeometry.x()); + change.setYChange(newGeometry.y() != oldGeometry.y()); + change.setWidthChange(newGeometry.width() != oldGeometry.width()); + change.setHeightChange(newGeometry.height() != oldGeometry.height()); + + if (!d->changeListeners.isEmpty()) { + const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &listener : listeners) { + if (listener.types & QQuickItemPrivate::Geometry) { + if (change.matches(listener.gTypes)) + listener.listener->itemGeometryChanged(this, change, oldGeometry); + } } } @@ -4224,12 +4226,14 @@ void QQuickItem::setBaselineOffset(qreal offset) d->baselineOffset = offset; - const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Geometry) { - QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); - if (anchor) - anchor->updateVerticalAnchors(); + if (!d->changeListeners.isEmpty()) { + const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Geometry) { + QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate(); + if (anchor) + anchor->updateVerticalAnchors(); + } } } @@ -5977,20 +5981,24 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt switch (change) { case QQuickItem::ItemChildAddedChange: { q->itemChange(change, data); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Children) { - change.listener->itemChildAdded(q, data.item); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Children) { + change.listener->itemChildAdded(q, data.item); + } } } break; } case QQuickItem::ItemChildRemovedChange: { q->itemChange(change, data); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Children) { - change.listener->itemChildRemoved(q, data.item); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Children) { + change.listener->itemChildRemoved(q, data.item); + } } } break; @@ -6000,30 +6008,36 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt break; case QQuickItem::ItemVisibleHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Visibility) { - change.listener->itemVisibilityChanged(q); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Visibility) { + change.listener->itemVisibilityChanged(q); + } } } break; } case QQuickItem::ItemParentHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Parent) { - change.listener->itemParentChanged(q, data.item); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Parent) { + change.listener->itemParentChanged(q, data.item); + } } } break; } case QQuickItem::ItemOpacityHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Opacity) { - change.listener->itemOpacityChanged(q); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Opacity) { + change.listener->itemOpacityChanged(q); + } } } break; @@ -6033,10 +6047,12 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt break; case QQuickItem::ItemRotationHasChanged: { q->itemChange(change, data); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::Rotation) { - change.listener->itemRotationChanged(q); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::Rotation) { + change.listener->itemRotationChanged(q); + } } } break; @@ -6395,10 +6411,12 @@ void QQuickItem::resetWidth() void QQuickItemPrivate::implicitWidthChanged() { Q_Q(QQuickItem); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::ImplicitWidth) { - change.listener->itemImplicitWidthChanged(q); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::ImplicitWidth) { + change.listener->itemImplicitWidthChanged(q); + } } } emit q->implicitWidthChanged(); @@ -6559,10 +6577,12 @@ void QQuickItem::resetHeight() void QQuickItemPrivate::implicitHeightChanged() { Q_Q(QQuickItem); - const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) - for (const QQuickItemPrivate::ChangeListener &change : listeners) { - if (change.types & QQuickItemPrivate::ImplicitHeight) { - change.listener->itemImplicitHeightChanged(q); + if (!changeListeners.isEmpty()) { + const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732) + for (const QQuickItemPrivate::ChangeListener &change : listeners) { + if (change.types & QQuickItemPrivate::ImplicitHeight) { + change.listener->itemImplicitHeightChanged(q); + } } } emit q->implicitHeightChanged(); diff --git a/src/quick/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h index 19ff73056b..83c69a9330 100644 --- a/src/quick/items/qquickitemchangelistener_p.h +++ b/src/quick/items/qquickitemchangelistener_p.h @@ -115,12 +115,14 @@ private: int kind; }; +#define QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING + class QQuickItemChangeListener { public: virtual ~QQuickItemChangeListener() {} - virtual void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF & /* diff */) {} + virtual void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF & /* oldGeometry */) {} virtual void itemSiblingOrderChanged(QQuickItem *) {} virtual void itemVisibilityChanged(QQuickItem *) {} virtual void itemOpacityChanged(QQuickItem *) {} diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index d02ed07de0..7d98cc2693 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1207,10 +1207,10 @@ void QQuickItemViewPrivate::showVisibleItems() const } void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, - const QRectF &diff) + const QRectF &oldGeometry) { Q_Q(QQuickItemView); - QQuickFlickablePrivate::itemGeometryChanged(item, change, diff); + QQuickFlickablePrivate::itemGeometryChanged(item, change, oldGeometry); if (!q->isComponentComplete()) return; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 30625c7ea8..f89a995e76 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -131,7 +131,7 @@ public: void updateAverage(); - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) Q_DECL_OVERRIDE; void fixupPosition() Q_DECL_OVERRIDE; void fixup(AxisData &data, qreal minExtent, qreal maxExtent) Q_DECL_OVERRIDE; bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, @@ -1401,11 +1401,11 @@ bool QQuickListViewPrivate::hasStickyFooter() const } void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, - const QRectF &diff) + const QRectF &oldGeometry) { Q_Q(QQuickListView); - QQuickItemViewPrivate::itemGeometryChanged(item, change, diff); + QQuickItemViewPrivate::itemGeometryChanged(item, change, oldGeometry); if (!q->isComponentComplete()) return; @@ -1426,24 +1426,22 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometry // position all subsequent items if (visibleItems.count() && item == visibleItems.constFirst()->item) { FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.constFirst()); - const QRectF oldGeometry(item->x() - diff.x(), - item->y() - diff.y(), - item->width() - diff.width(), - item->height() - diff.height()); if (listItem->transitionScheduledOrRunning()) return; if (orient == QQuickListView::Vertical) { const qreal oldItemEndPosition = verticalLayoutDirection == QQuickItemView::BottomToTop ? -oldGeometry.y() : oldGeometry.y() + oldGeometry.height(); + const qreal heightDiff = item->height() - oldGeometry.height(); if (verticalLayoutDirection == QQuickListView::TopToBottom && oldItemEndPosition < q->contentY()) - listItem->setPosition(listItem->position() - diff.height(), true); + listItem->setPosition(listItem->position() - heightDiff, true); else if (verticalLayoutDirection == QQuickListView::BottomToTop && oldItemEndPosition > q->contentY()) - listItem->setPosition(listItem->position() + diff.height(), true); + listItem->setPosition(listItem->position() + heightDiff, true); } else { const qreal oldItemEndPosition = q->effectiveLayoutDirection() == Qt::RightToLeft ? -oldGeometry.x() : oldGeometry.x() + oldGeometry.width(); + const qreal widthDiff = item->width() - oldGeometry.width(); if (q->effectiveLayoutDirection() == Qt::LeftToRight && oldItemEndPosition < q->contentX()) - listItem->setPosition(listItem->position() - diff.width(), true); + listItem->setPosition(listItem->position() - widthDiff, true); else if (q->effectiveLayoutDirection() == Qt::RightToLeft && oldItemEndPosition > q->contentX()) - listItem->setPosition(listItem->position() + diff.width(), true); + listItem->setPosition(listItem->position() + widthDiff, true); } } forceLayoutPolish(); diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 9aea9c50df..eeec562e3c 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -65,12 +65,12 @@ QQuickLoaderPrivate::~QQuickLoaderPrivate() disposeInitialPropertyValues(); } -void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change - , const QRectF &diff) +void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change, + const QRectF &oldGeometry) { if (resizeItem == item) _q_updateSize(false); - QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, diff); + QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, oldGeometry); } void QQuickLoaderPrivate::itemImplicitWidthChanged(QQuickItem *) diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index a0a9ca0601..9b6267e011 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -84,7 +84,7 @@ public: QQuickLoaderPrivate(); ~QQuickLoaderPrivate(); - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) Q_DECL_OVERRIDE; void itemImplicitWidthChanged(QQuickItem *) Q_DECL_OVERRIDE; void itemImplicitHeightChanged(QQuickItem *) Q_DECL_OVERRIDE; void clear(); diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 4a5358faae..b53bf064b6 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -892,7 +892,7 @@ void QQuickTextEdit::setWrapMode(WrapMode mode) /*! \qmlproperty int QtQuick::TextEdit::lineCount - Returns the total number of lines in the textEdit item. + Returns the total number of lines in the TextEdit item. */ int QQuickTextEdit::lineCount() const { @@ -2350,6 +2350,7 @@ void QQuickTextEdit::moveCursorDelegate() QRectF cursorRect = cursorRectangle(); d->cursorItem->setX(cursorRect.x()); d->cursorItem->setY(cursorRect.y()); + d->cursorItem->setHeight(cursorRect.height()); } void QQuickTextEdit::updateSelection() diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp index 8716f98bff..6cfc1d0313 100644 --- a/src/quick/items/qquicktextnode.cpp +++ b/src/quick/items/qquicktextnode.cpp @@ -160,18 +160,14 @@ void QQuickTextNode::addImage(const QRectF &rect, const QImage &image) QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); QSGInternalImageNode *node = sg->sceneGraphContext()->createInternalImageNode(); QSGTexture *texture = sg->createTexture(image); - if (m_ownerElement->smooth()) { + if (m_ownerElement->smooth()) texture->setFiltering(QSGTexture::Linear); - texture->setMipmapFiltering(QSGTexture::Linear); - } m_textures.append(texture); node->setTargetRect(rect); node->setInnerTargetRect(rect); node->setTexture(texture); - if (m_ownerElement->smooth()) { + if (m_ownerElement->smooth()) node->setFiltering(QSGTexture::Linear); - node->setMipmapFiltering(QSGTexture::Linear); - } appendChildNode(node); node->update(); } diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index 4631b2e724..538356e679 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -423,7 +423,10 @@ void QQuickTextNodeEngine::addImage(const QRectF &rect, const QImage &image, qre QRectF searchRect = rect; if (layoutPosition == QTextFrameFormat::InFlow) { if (m_currentLineTree.isEmpty()) { - searchRect.moveTopLeft(m_position + m_currentLine.position() + QPointF(0,1)); + if (m_currentTextDirection == Qt::RightToLeft) + searchRect.moveTopRight(m_position + m_currentLine.rect().topRight() + QPointF(0, 1)); + else + searchRect.moveTopLeft(m_position + m_currentLine.position() + QPointF(0,1)); } else { const BinaryTreeNode *lastNode = m_currentLineTree.data() + m_currentLineTree.size() - 1; if (lastNode->glyphRun.isRightToLeft()) { @@ -952,6 +955,8 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1; #endif + setCurrentTextDirection(block.textDirection()); + QVarLengthArray<QTextLayout::FormatRange> colorChanges; mergeFormats(block.layout(), &colorChanges); diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h index 91ed6f4430..18c624513a 100644 --- a/src/quick/items/qquicktextnodeengine_p.h +++ b/src/quick/items/qquicktextnodeengine_p.h @@ -144,7 +144,11 @@ public: int selectionState; }; - QQuickTextNodeEngine() : m_hasSelection(false), m_hasContents(false) {} + QQuickTextNodeEngine() + : m_currentTextDirection(Qt::LeftToRight) + , m_hasSelection(false) + , m_hasContents(false) + {} bool hasContents() const { return m_hasContents; } void addTextBlock(QTextDocument *, const QTextBlock &, const QPointF &position, const QColor &textColor, const QColor& anchorColor, int selectionStart, int selectionEnd); @@ -158,6 +162,11 @@ public: m_currentLine = currentLine; } + void setCurrentTextDirection(Qt::LayoutDirection textDirection) + { + m_currentTextDirection = textDirection; + } + void addBorder(const QRectF &rect, qreal border, QTextFrameFormat::BorderStyle borderStyle, const QBrush &borderBrush); void addFrameDecorations(QTextDocument *document, QTextFrame *frame); @@ -247,6 +256,7 @@ private: QPointF m_position; QTextLine m_currentLine; + Qt::LayoutDirection m_currentTextDirection; QList<QPair<QRectF, QColor> > m_backgrounds; QList<QRectF> m_selectionRects; diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index a167f01484..573440ff7f 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -111,14 +111,14 @@ void QQuickViewPrivate::execute() } void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change, - const QRectF &diff) + const QRectF &oldGeometry) { Q_Q(QQuickView); if (resizeItem == root && resizeMode == QQuickView::SizeViewToRootObject) { // wait for both width and height to be changed resizetimer.start(0,q); } - QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, diff); + QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, oldGeometry); } /*! diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index dec5b44e2a..722e634fc0 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -3125,10 +3125,12 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) { QSGNode *before = qquickitem_before_paintNode(itemPriv); - if (before) + if (before && before->parent()) { + Q_ASSERT(before->parent() == itemPriv->childContainerNode()); itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, before); - else + } else { itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode); + } } } else if (itemPriv->paintNode) { delete itemPriv->paintNode; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp index 05d5daa686..d71b0c3e2a 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp @@ -215,7 +215,7 @@ QSGRendererInterface::ShaderSourceTypes QSGSoftwareContext::shaderSourceType() c void *QSGSoftwareContext::getResource(QQuickWindow *window, Resource resource) const { - if (resource == Painter && window && window->isSceneGraphInitialized()) + if (resource == PainterResource && window && window->isSceneGraphInitialized()) return static_cast<QSGSoftwareRenderContext *>(QQuickWindowPrivate::get(window)->context)->m_activePainter; return nullptr; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 49bbbf0ba8..81aa641e03 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -90,7 +90,7 @@ DECLARE_DEBUG_VAR(noclip) static QElapsedTimer qsg_renderer_timer; #define QSGNODE_TRAVERSE(NODE) for (QSGNode *child = NODE->firstChild(); child; child = child->nextSibling()) -#define SHADOWNODE_TRAVERSE(NODE) for (Node *child = NODE->firstChild; child; child = child->nextSibling) +#define SHADOWNODE_TRAVERSE(NODE) for (Node *child = NODE->firstChild(); child; child = child->sibling()) static inline int size_of_type(GLenum type) { @@ -510,7 +510,7 @@ void Updater::updateRootTransforms(Node *node, Node *root, const QMatrix4x4 &com while (n != root) { if (n->type() == QSGNode::TransformNodeType) m = static_cast<QSGTransformNode *>(n->sgNode)->matrix() * m; - n = n->parent; + n = n->parent(); } m = combined * m; @@ -1013,16 +1013,8 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent) Node *snode = m_nodeAllocator.allocate(); snode->sgNode = node; m_nodes.insert(node, snode); - if (shadowParent) { - snode->parent = shadowParent; - if (shadowParent->lastChild) { - shadowParent->lastChild->nextSibling = snode; - shadowParent->lastChild = snode; - } else { - shadowParent->firstChild = snode; - shadowParent->lastChild = snode; - } - } + if (shadowParent) + shadowParent->append(snode); if (node->type() == QSGNode::GeometryNodeType) { snode->data = m_elementAllocator.allocate(); @@ -1054,17 +1046,12 @@ void Renderer::nodeWasRemoved(Node *node) // here, because we delete 'child' (when recursed, down below), so we'd // have a use-after-free. { - Node *child = node->firstChild; - Node *nextChild = 0; - + Node *child = node->firstChild(); while (child) { - // Get the next child now before we proceed - nextChild = child->nextSibling; - // Remove (and delete) child + node->remove(child); nodeWasRemoved(child); - - child = nextChild; + child = node->firstChild(); } } @@ -1110,6 +1097,7 @@ void Renderer::nodeWasRemoved(Node *node) } Q_ASSERT(m_nodes.contains(node->sgNode)); + m_nodeAllocator.release(m_nodes.take(node->sgNode)); } @@ -1120,13 +1108,13 @@ void Renderer::turnNodeIntoBatchRoot(Node *node) node->isBatchRoot = true; node->becameBatchRoot = true; - Node *p = node->parent; + Node *p = node->parent(); while (p) { if (p->type() == QSGNode::ClipNodeType || p->isBatchRoot) { registerBatchRoot(node, p); break; } - p = p->parent; + p = p->parent(); } SHADOWNODE_TRAVERSE(node) @@ -1255,33 +1243,18 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) | QSGNode::DirtyForceUpdate); if (dirtyChain != 0) { dirtyChain = QSGNode::DirtyState(dirtyChain << 16); - Node *sn = shadowNode->parent; + Node *sn = shadowNode->parent(); while (sn) { sn->dirtyState |= dirtyChain; - sn = sn->parent; + sn = sn->parent(); } } // Delete happens at the very end because it deletes the shadownode. if (state & QSGNode::DirtyNodeRemoved) { - Node *parent = shadowNode->parent; - if (parent) { - Q_ASSERT(parent->firstChild); - Q_ASSERT(parent->lastChild); - shadowNode->parent = 0; - Node *child = parent->firstChild; - if (child == shadowNode) { - parent->firstChild = shadowNode->nextSibling; - if (parent->lastChild == shadowNode) - parent->lastChild = 0; - } else { - while (child->nextSibling != shadowNode) - child = child->nextSibling; - child->nextSibling = shadowNode->nextSibling; - if (shadowNode == parent->lastChild) - parent->lastChild = child; - } - } + Node *parent = shadowNode->parent(); + if (parent) + parent->remove(shadowNode); nodeWasRemoved(shadowNode); Q_ASSERT(m_nodes.value(node) == 0); } diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index d5e94cea3e..322192944b 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -451,11 +451,73 @@ struct Batch struct Node { QSGNode *sgNode; - Node *parent; void *data; - Node *firstChild; - Node *nextSibling; - Node *lastChild; + + Node *m_parent; + Node *m_child; + Node *m_next; + Node *m_prev; + + Node *parent() const { return m_parent; } + + void append(Node *child) { + Q_ASSERT(child); + Q_ASSERT(!hasChild(child)); + Q_ASSERT(child->m_parent == 0); + Q_ASSERT(child->m_next == 0); + Q_ASSERT(child->m_prev == 0); + + if (!m_child) { + child->m_next = child; + child->m_prev = child; + m_child = child; + } else { + m_child->m_prev->m_next = child; + child->m_prev = m_child->m_prev; + m_child->m_prev = child; + child->m_next = m_child; + } + child->setParent(this); + } + + void remove(Node *child) { + Q_ASSERT(child); + Q_ASSERT(hasChild(child)); + + // only child.. + if (child->m_next == child) { + m_child = 0; + } else { + if (m_child == child) + m_child = child->m_next; + child->m_next->m_prev = child->m_prev; + child->m_prev->m_next = child->m_next; + } + child->m_next = 0; + child->m_prev = 0; + child->setParent(0); + } + + Node *firstChild() const { return m_child; } + + Node *sibling() const { + Q_ASSERT(m_parent); + return m_next == m_parent->m_child ? 0 : m_next; + } + + void setParent(Node *p) { + Q_ASSERT(m_parent == 0 || p == 0); + m_parent = p; + } + + bool hasChild(Node *child) const { + Node *n = m_child; + while (n && n != child) + n = n->sibling(); + return n; + } + + QSGNode::DirtyState dirtyState; diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp index fa543aecad..d309044e8f 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp @@ -81,10 +81,10 @@ QT_BEGIN_NAMESPACE /*! \enum QSGRendererInterface::Resource - \value Device The graphics device, when applicable. - \value CommandQueue The graphics command queue used by the scenegraph, when applicable. - \value CommandList The command list or buffer used by the scenegraph, when applicable. - \value Painter The active QPainter used by the scenegraph, when running with the software backend. + \value DeviceResource The graphics device, when applicable. + \value CommandQueueResource The graphics command queue used by the scenegraph, when applicable. + \value CommandListResource The command list or buffer used by the scenegraph, when applicable. + \value PainterResource The active QPainter used by the scenegraph, when running with the software backend. */ /*! diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.h b/src/quick/scenegraph/coreapi/qsgrendererinterface.h index a50b362aeb..cf8fcf9015 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.h +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.h @@ -57,10 +57,10 @@ public: }; enum Resource { - Device, - CommandQueue, - CommandList, - Painter + DeviceResource, + CommandQueueResource, + CommandListResource, + PainterResource }; enum ShaderType { diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 40c3293c7b..b6abb55bd3 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -117,8 +117,9 @@ QSGTexture *Manager::create(const QImage &image, bool hasAlphaChannel) if (image.width() < m_atlas_size_limit && image.height() < m_atlas_size_limit) { if (!m_atlas) m_atlas = new Atlas(m_atlas_size); + // t may be null for atlas allocation failure t = m_atlas->create(image); - if (!hasAlphaChannel && t->hasAlphaChannel()) + if (t && !hasAlphaChannel && t->hasAlphaChannel()) t->setHasAlphaChannel(false); } return t; diff --git a/src/quick/scenegraph/util/qsgdefaultimagenode.cpp b/src/quick/scenegraph/util/qsgdefaultimagenode.cpp index 6afe591dca..63773887a0 100644 --- a/src/quick/scenegraph/util/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/util/qsgdefaultimagenode.cpp @@ -173,33 +173,4 @@ bool QSGDefaultImageNode::ownsTexture() const return m_ownsTexture; } -void QSGDefaultImageNode::rebuildGeometry(QSGGeometry *g, - QSGTexture *texture, - const QRectF &rect, - QRectF sourceRect, - TextureCoordinatesTransformMode texCoordMode) -{ - if (!texture) - return; - - if (!sourceRect.width() || !sourceRect.height()) { - QSize ts = texture->textureSize(); - sourceRect = QRectF(0, 0, ts.width(), ts.height()); - } - - // Maybe transform the texture coordinates - if (texCoordMode.testFlag(QSGImageNode::MirrorHorizontally)) { - float tmp = sourceRect.left(); - sourceRect.setLeft(sourceRect.right()); - sourceRect.setRight(tmp); - } - if (texCoordMode.testFlag(QSGImageNode::MirrorVertically)) { - float tmp = sourceRect.top(); - sourceRect.setTop(sourceRect.bottom()); - sourceRect.setBottom(tmp); - } - - QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect)); -} - QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgdefaultimagenode_p.h b/src/quick/scenegraph/util/qsgdefaultimagenode_p.h index eb6c487c18..bb9ebec885 100644 --- a/src/quick/scenegraph/util/qsgdefaultimagenode_p.h +++ b/src/quick/scenegraph/util/qsgdefaultimagenode_p.h @@ -85,12 +85,6 @@ public: void setOwnsTexture(bool owns) override; bool ownsTexture() const override; - static void rebuildGeometry(QSGGeometry *g, - QSGTexture *texture, - const QRectF &rect, - QRectF sourceRect, - TextureCoordinatesTransformMode texCoordMode); - private: QSGGeometry m_geometry; QSGOpaqueTextureMaterial m_opaque_material; diff --git a/src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp b/src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp index e5a53a3617..6023a9af93 100644 --- a/src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp +++ b/src/quick/scenegraph/util/qsgdefaultninepatchnode.cpp @@ -81,56 +81,4 @@ void QSGDefaultNinePatchNode::update() markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial); } -void QSGDefaultNinePatchNode::rebuildGeometry(QSGTexture *texture, QSGGeometry *geometry, const QVector4D &padding, - const QRectF &bounds, qreal dpr) -{ - if (padding.x() <= 0 && padding.y() <= 0 && padding.z() <= 0 && padding.w() <= 0) { - geometry->allocate(4, 0); - QSGGeometry::updateTexturedRectGeometry(geometry, bounds, texture->normalizedTextureSubRect()); - return; - } - - QRectF tc = texture->normalizedTextureSubRect(); - QSize ts = texture->textureSize(); - ts.setHeight(ts.height() / dpr); - ts.setWidth(ts.width() / dpr); - - qreal invtw = tc.width() / ts.width(); - qreal invth = tc.height() / ts.height(); - - struct Coord { qreal p; qreal t; }; - Coord cx[4] = { { bounds.left(), tc.left() }, - { bounds.left() + padding.x(), tc.left() + padding.x() * invtw }, - { bounds.right() - padding.z(), tc.right() - padding.z() * invtw }, - { bounds.right(), tc.right() } - }; - Coord cy[4] = { { bounds.top(), tc.top() }, - { bounds.top() + padding.y(), tc.top() + padding.y() * invth }, - { bounds.bottom() - padding.w(), tc.bottom() - padding.w() * invth }, - { bounds.bottom(), tc.bottom() } - }; - - geometry->allocate(16, 28); - QSGGeometry::TexturedPoint2D *v = geometry->vertexDataAsTexturedPoint2D(); - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - v->set(cx[x].p, cy[y].p, cx[x].t, cy[y].t); - ++v; - } - } - - quint16 *i = geometry->indexDataAsUShort(); - for (int r = 0; r < 3; ++r) { - if (r > 0) - *i++ = 4 * r; - for (int c = 0; c < 4; ++c) { - i[0] = 4 * r + c; - i[1] = 4 * r + c + 4; - i += 2; - } - if (r < 2) - *i++ = 4 * r + 3 + 4; - } -} - QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h b/src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h index 675cf48f47..3752a75ac6 100644 --- a/src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h +++ b/src/quick/scenegraph/util/qsgdefaultninepatchnode_p.h @@ -70,9 +70,6 @@ public: void setPadding(qreal left, qreal top, qreal right, qreal bottom) override; void update() override; - static void rebuildGeometry(QSGTexture *texture, QSGGeometry *geometry, const QVector4D &padding, - const QRectF &bounds, qreal dpr); - private: QRectF m_bounds; qreal m_devicePixelRatio; diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp index 65a6bcd52c..79e43e3820 100644 --- a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp +++ b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp @@ -84,32 +84,12 @@ QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager() QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawFont &font) { - return m_caches.value(fontKey(font), 0); + return m_caches.value(font, 0); } void QSGDistanceFieldGlyphCacheManager::insertCache(const QRawFont &font, QSGDistanceFieldGlyphCache *cache) { - m_caches.insert(fontKey(font), cache); -} - -QString QSGDistanceFieldGlyphCacheManager::fontKey(const QRawFont &font) -{ - QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine; - if (!fe->faceId().filename.isEmpty()) { - QByteArray keyName = fe->faceId().filename; - if (font.style() != QFont::StyleNormal) - keyName += QByteArray(" I"); - if (font.weight() != QFont::Normal) - keyName += ' ' + QByteArray::number(font.weight()); - keyName += QByteArray(" DF"); - return QString::fromUtf8(keyName); - } else { - return QString::fromLatin1("%1_%2_%3_%4") - .arg(font.familyName()) - .arg(font.styleName()) - .arg(font.weight()) - .arg(font.style()); - } + m_caches.insert(font, cache); } QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h index 354a48a81e..ad366cb4d4 100644 --- a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h +++ b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h @@ -80,9 +80,7 @@ public: void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; } private: - static QString fontKey(const QRawFont &font); - - QHash<QString, QSGDistanceFieldGlyphCache *> m_caches; + QHash<QRawFont, QSGDistanceFieldGlyphCache *> m_caches; ThresholdFunc m_threshold_func; AntialiasingSpreadFunc m_antialiasingSpread_func; diff --git a/src/quick/scenegraph/util/qsgimagenode.cpp b/src/quick/scenegraph/util/qsgimagenode.cpp index a78bfc1c66..c03c91d1cb 100644 --- a/src/quick/scenegraph/util/qsgimagenode.cpp +++ b/src/quick/scenegraph/util/qsgimagenode.cpp @@ -187,4 +187,33 @@ QT_BEGIN_NAMESPACE \return \c true if the node takes ownership of the texture; otherwise \c false. */ +void QSGImageNode::rebuildGeometry(QSGGeometry *g, + QSGTexture *texture, + const QRectF &rect, + QRectF sourceRect, + TextureCoordinatesTransformMode texCoordMode) +{ + if (!texture) + return; + + if (!sourceRect.width() || !sourceRect.height()) { + QSize ts = texture->textureSize(); + sourceRect = QRectF(0, 0, ts.width(), ts.height()); + } + + // Maybe transform the texture coordinates + if (texCoordMode.testFlag(QSGImageNode::MirrorHorizontally)) { + float tmp = sourceRect.left(); + sourceRect.setLeft(sourceRect.right()); + sourceRect.setRight(tmp); + } + if (texCoordMode.testFlag(QSGImageNode::MirrorVertically)) { + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + } + + QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect)); +} + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgimagenode.h b/src/quick/scenegraph/util/qsgimagenode.h index 7eab42c4e6..d25e732e4b 100644 --- a/src/quick/scenegraph/util/qsgimagenode.h +++ b/src/quick/scenegraph/util/qsgimagenode.h @@ -79,6 +79,12 @@ public: virtual void setOwnsTexture(bool owns) = 0; virtual bool ownsTexture() const = 0; + + static void rebuildGeometry(QSGGeometry *g, + QSGTexture *texture, + const QRectF &rect, + QRectF sourceRect, + TextureCoordinatesTransformMode texCoordMode); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QSGImageNode::TextureCoordinatesTransformMode) diff --git a/src/quick/scenegraph/util/qsgninepatchnode.cpp b/src/quick/scenegraph/util/qsgninepatchnode.cpp index 9c167ca76f..33568b5488 100644 --- a/src/quick/scenegraph/util/qsgninepatchnode.cpp +++ b/src/quick/scenegraph/util/qsgninepatchnode.cpp @@ -74,4 +74,56 @@ QT_BEGIN_NAMESPACE \internal */ +void QSGNinePatchNode::rebuildGeometry(QSGTexture *texture, QSGGeometry *geometry, const QVector4D &padding, + const QRectF &bounds, qreal dpr) +{ + if (padding.x() <= 0 && padding.y() <= 0 && padding.z() <= 0 && padding.w() <= 0) { + geometry->allocate(4, 0); + QSGGeometry::updateTexturedRectGeometry(geometry, bounds, texture->normalizedTextureSubRect()); + return; + } + + QRectF tc = texture->normalizedTextureSubRect(); + QSize ts = texture->textureSize(); + ts.setHeight(ts.height() / dpr); + ts.setWidth(ts.width() / dpr); + + qreal invtw = tc.width() / ts.width(); + qreal invth = tc.height() / ts.height(); + + struct Coord { qreal p; qreal t; }; + Coord cx[4] = { { bounds.left(), tc.left() }, + { bounds.left() + padding.x(), tc.left() + padding.x() * invtw }, + { bounds.right() - padding.z(), tc.right() - padding.z() * invtw }, + { bounds.right(), tc.right() } + }; + Coord cy[4] = { { bounds.top(), tc.top() }, + { bounds.top() + padding.y(), tc.top() + padding.y() * invth }, + { bounds.bottom() - padding.w(), tc.bottom() - padding.w() * invth }, + { bounds.bottom(), tc.bottom() } + }; + + geometry->allocate(16, 28); + QSGGeometry::TexturedPoint2D *v = geometry->vertexDataAsTexturedPoint2D(); + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + v->set(cx[x].p, cy[y].p, cx[x].t, cy[y].t); + ++v; + } + } + + quint16 *i = geometry->indexDataAsUShort(); + for (int r = 0; r < 3; ++r) { + if (r > 0) + *i++ = 4 * r; + for (int c = 0; c < 4; ++c) { + i[0] = 4 * r + c; + i[1] = 4 * r + c + 4; + i += 2; + } + if (r < 2) + *i++ = 4 * r + 3 + 4; + } +} + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgninepatchnode.h b/src/quick/scenegraph/util/qsgninepatchnode.h index 8677a432ba..8509cbd326 100644 --- a/src/quick/scenegraph/util/qsgninepatchnode.h +++ b/src/quick/scenegraph/util/qsgninepatchnode.h @@ -55,6 +55,10 @@ public: virtual void setDevicePixelRatio(qreal ratio) = 0; virtual void setPadding(qreal left, qreal top, qreal right, qreal bottom) = 0; virtual void update() = 0; + + static void rebuildGeometry(QSGTexture *texture, QSGGeometry *geometry, + const QVector4D &padding, + const QRectF &bounds, qreal dpr); }; QT_END_NAMESPACE diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index de3692afb0..1d617f5098 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -245,14 +245,14 @@ void QQuickWidgetPrivate::execute() } void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeometryChange change, - const QRectF &diff) + const QRectF &oldGeometry) { Q_Q(QQuickWidget); if (resizeItem == root && resizeMode == QQuickWidget::SizeViewToRootObject) { // wait for both width and height to be changed resizetimer.start(0,q); } - QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, diff); + QQuickItemChangeListener::itemGeometryChanged(resizeItem, change, oldGeometry); } void QQuickWidgetPrivate::render(bool needsSync) diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h index 3d64981797..0ba86172e6 100644 --- a/src/quickwidgets/qquickwidget_p.h +++ b/src/quickwidgets/qquickwidget_p.h @@ -87,7 +87,7 @@ public: ~QQuickWidgetPrivate(); void execute(); - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) Q_DECL_OVERRIDE; void initResize(); void updateSize(); void updatePosition(); diff --git a/sync.profile b/sync.profile index 46280ade96..6cab0ae358 100644 --- a/sync.profile +++ b/sync.profile @@ -13,14 +13,3 @@ ); %deprecatedheaders = ( ); -# Module dependencies. -# Every module that is required to build this module should have one entry. -# Each of the module version specifiers can take one of the following values: -# - A specific Git revision. -# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch) -# - an empty string to use the same branch under test (dependencies will become "refs/heads/master" if we are in the master branch) -# -%dependencies = ( - "qtbase" => "", - "qtxmlpatterns" => "", -); diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index d28bbc1ffa..12c33909cf 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -1372,6 +1372,33 @@ void tst_QJSValue::hasProperty_changePrototype() QVERIFY(obj.hasOwnProperty("foo")); } +void tst_QJSValue::hasProperty_QTBUG56830_data() +{ + QTest::addColumn<QString>("key"); + QTest::addColumn<QString>("lookup"); + + QTest::newRow("bugreport-1") << QStringLiteral("240000000000") << QStringLiteral("3776798720"); + QTest::newRow("bugreport-2") << QStringLiteral("240000000001") << QStringLiteral("3776798721"); + QTest::newRow("biggest-ok-before-bug") << QStringLiteral("238609294221") << QStringLiteral("2386092941"); + QTest::newRow("smallest-bugged") << QStringLiteral("238609294222") << QStringLiteral("2386092942"); + QTest::newRow("biggest-bugged") << QStringLiteral("249108103166") << QStringLiteral("12884901886"); + QTest::newRow("smallest-ok-after-bug") << QStringLiteral("249108103167") << QStringLiteral("12884901887"); +} + +void tst_QJSValue::hasProperty_QTBUG56830() +{ + QFETCH(QString, key); + QFETCH(QString, lookup); + + QJSEngine eng; + const QJSValue value(42); + + QJSValue obj = eng.newObject(); + obj.setProperty(key, value); + QVERIFY(obj.hasProperty(key)); + QVERIFY(!obj.hasProperty(lookup)); +} + void tst_QJSValue::deleteProperty_basic() { QJSEngine eng; diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.h b/tests/auto/qml/qjsvalue/tst_qjsvalue.h index 6ed880c865..b8b9f4403c 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.h +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.h @@ -92,6 +92,8 @@ private slots: void hasProperty_basic(); void hasProperty_globalObject(); void hasProperty_changePrototype(); + void hasProperty_QTBUG56830_data(); + void hasProperty_QTBUG56830(); void deleteProperty_basic(); void deleteProperty_globalObject(); diff --git a/tests/auto/qml/qqmlconnections/data/test-connection-implicit.qml b/tests/auto/qml/qqmlconnections/data/test-connection-implicit.qml new file mode 100644 index 0000000000..d5aa0f102a --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/test-connection-implicit.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 + +Item { + width: 50 + + property bool tested: false + + Connections { onWidthChanged: tested = true } +} diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index 615de0885a..b3ac1ce958 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -52,6 +52,7 @@ private slots: void rewriteErrors(); void singletonTypeTarget(); void enableDisable_QTBUG_36350(); + void clearImplicitTarget(); private: QQmlEngine engine; @@ -352,6 +353,32 @@ void tst_qqmlconnections::enableDisable_QTBUG_36350() delete item; } +//QTBUG-56499 +void tst_qqmlconnections::clearImplicitTarget() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("test-connection-implicit.qml")); + QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + + QVERIFY(item != 0); + + // normal case: fire Connections + item->setWidth(100.); + QCOMPARE(item->property("tested").toBool(), true); + + item->setProperty("tested", false); + // clear the implicit target + QQmlConnections *connections = item->findChild<QQmlConnections*>(); + QVERIFY(connections); + connections->setTarget(0); + + // target cleared: no longer fire Connections + item->setWidth(150.); + QCOMPARE(item->property("tested").toBool(), false); + + delete item; +} + QTEST_MAIN(tst_qqmlconnections) #include "tst_qqmlconnections.moc" diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index 6554d749dd..78322b44a1 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -2726,9 +2726,9 @@ struct TestListener : public QQuickItemChangeListener { TestListener(bool remove = false) : remove(remove) { } - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange, const QRectF &diff) override + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange, const QRectF &oldGeometry) override { - record(item, QQuickItemPrivate::Geometry, diff); + record(item, QQuickItemPrivate::Geometry, oldGeometry); } void itemSiblingOrderChanged(QQuickItem *item) override { @@ -2810,20 +2810,20 @@ void tst_QQuickItem::changeListener() item->setImplicitWidth(10); QCOMPARE(itemListener.count(QQuickItemPrivate::ImplicitWidth), 1); QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 1); - QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,10,0))); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,0,0))); item->setImplicitHeight(20); QCOMPARE(itemListener.count(QQuickItemPrivate::ImplicitHeight), 1); QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 2); - QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,0,20))); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,10,0))); item->setWidth(item->width() + 30); QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 3); - QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,30,0))); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,10,20))); item->setHeight(item->height() + 40); QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 4); - QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,0,40))); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,40,20))); item->setOpacity(0.5); QCOMPARE(itemListener.count(QQuickItemPrivate::Opacity), 1); diff --git a/tests/auto/quick/qquicktextedit/data/cursorHeight.qml b/tests/auto/quick/qquicktextedit/data/cursorHeight.qml new file mode 100644 index 0000000000..b831a9eb6f --- /dev/null +++ b/tests/auto/quick/qquicktextedit/data/cursorHeight.qml @@ -0,0 +1,20 @@ +import QtQuick 2.0 + +Rectangle { + width: 300 + height: 300 + color: "white" + + TextEdit { + objectName: "textEditObject" + width: 300 + height: 300 + text: "<span style=\"font-size:20pt;\">Blah</span><br>blah" + textFormat: TextEdit.RichText + cursorDelegate: Rectangle { + objectName: "cursorInstance" + color: "red" + width: 2 + } + } +} diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 5ed0e9eea7..5d30cc8c94 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -140,6 +140,7 @@ private slots: void cursorVisible(); void delegateLoading_data(); void delegateLoading(); + void cursorDelegateHeight(); void navigation(); void readOnly(); #ifndef QT_NO_CLIPBOARD @@ -2848,6 +2849,43 @@ void tst_qquicktextedit::delegateLoading() //QVERIFY(!delegate); } +void tst_qquicktextedit::cursorDelegateHeight() +{ + QQuickView view(testFileUrl("cursorHeight.qml")); + view.show(); + view.requestActivate(); + QTest::qWaitForWindowActive(&view); + QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject"); + QVERIFY(textEditObject); + // Delegate creation is deferred until focus in or cursor visibility is forced. + QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance")); + QVERIFY(!textEditObject->isCursorVisible()); + + // Test that the delegate gets created. + textEditObject->setFocus(true); + QVERIFY(textEditObject->isCursorVisible()); + QQuickItem* delegateObject = textEditObject->findChild<QQuickItem*>("cursorInstance"); + QVERIFY(delegateObject); + + const int largerHeight = textEditObject->cursorRectangle().height(); + + textEditObject->setCursorPosition(0); + QCOMPARE(delegateObject->x(), textEditObject->cursorRectangle().x()); + QCOMPARE(delegateObject->y(), textEditObject->cursorRectangle().y()); + QCOMPARE(delegateObject->height(), textEditObject->cursorRectangle().height()); + + // Move the cursor to the next line, which has a smaller font. + textEditObject->setCursorPosition(5); + QCOMPARE(delegateObject->x(), textEditObject->cursorRectangle().x()); + QCOMPARE(delegateObject->y(), textEditObject->cursorRectangle().y()); + QVERIFY(textEditObject->cursorRectangle().height() < largerHeight); + QCOMPARE(delegateObject->height(), textEditObject->cursorRectangle().height()); + + // Test that the delegate gets deleted + textEditObject->setCursorDelegate(0); + QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance")); +} + /* TextEdit element should only handle left/right keys until the cursor reaches the extent of the text, then they should ignore the keys. diff --git a/tests/manual/scenegraph_lancelot/data/text/text_flow_image_start_ltr.qml b/tests/manual/scenegraph_lancelot/data/text/text_flow_image_start_ltr.qml new file mode 100644 index 0000000000..b8f0458818 --- /dev/null +++ b/tests/manual/scenegraph_lancelot/data/text/text_flow_image_start_ltr.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Item { + width: 320 + height: 480 + + Text { + anchors.centerIn: parent + font.family: "Arial" + font.pixelSize: 16 + textFormat: Text.RichText + text: "<img width=16 height=16 src=\"data/logo.png\" />This image is in the start of the text" + } +} diff --git a/tests/manual/scenegraph_lancelot/data/text/text_flow_image_start_rtl.qml b/tests/manual/scenegraph_lancelot/data/text/text_flow_image_start_rtl.qml new file mode 100644 index 0000000000..e5bea08e62 --- /dev/null +++ b/tests/manual/scenegraph_lancelot/data/text/text_flow_image_start_rtl.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Item { + width: 320 + height: 480 + + Text { + anchors.centerIn: parent + font.family: "Arial" + font.pixelSize: 16 + textFormat: Text.RichText + text: "<img width=16 height=16 src=\"data/logo.png\" />هو أمّا حكومة" + } +} diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index fdfc66f3a6..e185fc41a9 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -453,6 +453,7 @@ int main(int argc, char *argv[]) app->setApplicationName("Qml Runtime"); app->setOrganizationName("QtProject"); app->setOrganizationDomain("qt-project.org"); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); qmlRegisterType<Config>("QmlRuntime.Config", 1, 0, "Configuration"); qmlRegisterType<PartialScene>("QmlRuntime.Config", 1, 0, "PartialScene"); diff --git a/tools/qmleasing/main.cpp b/tools/qmleasing/main.cpp index ab137d5eb4..389503507e 100644 --- a/tools/qmleasing/main.cpp +++ b/tools/qmleasing/main.cpp @@ -33,6 +33,7 @@ int main(int argc, char ** argv) { QApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); MainWindow mainWindow; mainWindow.show(); diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp index 8f476649e9..b65783f1aa 100644 --- a/tools/qmlimportscanner/main.cpp +++ b/tools/qmlimportscanner/main.cpp @@ -485,6 +485,7 @@ QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QString int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); QStringList args = app.arguments(); const QString appName = QFileInfo(app.applicationFilePath()).baseName(); if (args.size() < 2) { @@ -529,7 +530,12 @@ int main(int argc, char *argv[]) if (arg.startsWith(QLatin1Char('-')) && arg != QLatin1String("-")) break; ++i; - *argReceiver += arg; + if (!QFile::exists(arg)) { + std::cerr << "No such file or directory: \"" << qPrintable(arg) << "\"\n"; + return 1; + } else { + *argReceiver += arg; + } } } diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp index d09d2f7d0c..850b9a9a0a 100644 --- a/tools/qmljs/qmljs.cpp +++ b/tools/qmljs/qmljs.cpp @@ -135,6 +135,7 @@ static void showException(QV4::ExecutionContext *ctx, const QV4::Value &exceptio int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); QStringList args = app.arguments(); args.removeFirst(); diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp index d2bad9d0d5..6877ca7442 100644 --- a/tools/qmlmin/main.cpp +++ b/tools/qmlmin/main.cpp @@ -533,6 +533,7 @@ static void usage(bool showHelp = false) int runQmlmin(int argc, char *argv[]) { QCoreApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); const QStringList args = app.arguments(); diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index 3294fa1e87..88660e46bb 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -987,6 +987,7 @@ int main(int argc, char *argv[]) QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QGuiApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); const QStringList args = app.arguments(); const QString appName = QFileInfo(app.applicationFilePath()).baseName(); if (args.size() < 2) { diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index 9e1002166d..db0af1d071 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -467,6 +467,7 @@ int main(int argc, char ** argv) app.setApplicationName("QtQmlViewer"); app.setOrganizationName("QtProject"); app.setOrganizationDomain("qt-project.org"); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); const QStringList arguments = QCoreApplication::arguments(); for (int i = 1, size = arguments.size(); i < size; ++i) { diff --git a/tools/qmltime/qmltime.cpp b/tools/qmltime/qmltime.cpp index 8afaebc413..4c282dd8f4 100644 --- a/tools/qmltime/qmltime.cpp +++ b/tools/qmltime/qmltime.cpp @@ -205,6 +205,7 @@ void usage(const char *name) int main(int argc, char ** argv) { QGuiApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); qmlRegisterType<Timer>("QmlTime", 1, 0, "Timer"); |