From d1186f9299f1351236269a0db39d43fdae28a944 Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Thu, 13 Feb 2020 12:56:07 +0100 Subject: Doc: Update description of QTextDocument::characterCount A QTextDocument always contains a QChar::ParagraphSeparator, so characterCount() will always return actual count + 1. The tests confirm this behavior, make it explicit in the docs. Fixes: QTBUG-80597 Change-Id: I91040fb6eb2c4fae5235458c695110f8f15bdfea Reviewed-by: Volker Hilsheimer Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Leena Miettinen --- src/gui/text/qtextdocument.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 1353568ec1..7d0a0b2168 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -904,6 +904,9 @@ int QTextDocument::lineCount() const Returns the number of characters of this document. + \note As a QTextDocument always contains at least one + QChar::ParagraphSeparator, this method will return at least 1. + \sa blockCount(), characterAt() */ int QTextDocument::characterCount() const -- cgit v1.2.1 From 8cf4ce0fea65db841bb5345169401aebbe0a5587 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Wed, 19 Feb 2020 19:24:53 +0100 Subject: QString: Add missing number() crosslinks to setNum() Change-Id: I22a4c86034b399782115bb078c298b211095476a Reviewed-by: Christian Ehrlicher Reviewed-by: Paul Wicking --- src/corelib/text/qstring.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index fa8b5cf3f8..65a85007f1 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -7505,6 +7505,8 @@ float QString::toFloat(bool *ok) const The formatting always uses QLocale::C, i.e., English/UnitedStates. To get a localized string representation of a number, use QLocale::toString() with the appropriate locale. + + \sa number() */ /*! \fn QString &QString::setNum(uint n, int base) @@ -7562,6 +7564,8 @@ QString &QString::setNum(qulonglong n, int base) The formatting always uses QLocale::C, i.e., English/UnitedStates. To get a localized string representation of a number, use QLocale::toString() with the appropriate locale. + + \sa number() */ QString &QString::setNum(double n, char f, int prec) @@ -7580,6 +7584,8 @@ QString &QString::setNum(double n, char f, int prec) The formatting always uses QLocale::C, i.e., English/UnitedStates. To get a localized string representation of a number, use QLocale::toString() with the appropriate locale. + + \sa number() */ -- cgit v1.2.1 From 39994e0705f11afc45e20872b95fb3a6e684c913 Mon Sep 17 00:00:00 2001 From: Nicolas Guichard Date: Tue, 18 Feb 2020 17:16:14 +0100 Subject: QShaderGenerator: Don't crash when a node has multiple outputs It was already possible to declare a node prototype with multiple outputs, but trying to assign to all those outputs was not possible and instead resulted in a crash. It is now possible to declare nodes like this without crashing: "SEPERATE_XYZ": { "inputs": ["vector"], "outputs": ["x", "y", "z"], "rules": [ { "substitution": "float $x = $vector.x; float $y = $vector.y; float $z = $vector.z;" } ] } Change-Id: I748e77e84c9120dc688c573eee33dc13c6bfbace Reviewed-by: Paul Lemire --- src/gui/util/qshadergenerator.cpp | 67 +++++++++++--------- .../util/qshadergenerator/tst_qshadergenerator.cpp | 73 ++++++++++++++++++++++ 2 files changed, 112 insertions(+), 28 deletions(-) diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp index 7ea42a7c9a..244b95605b 100644 --- a/src/gui/util/qshadergenerator.cpp +++ b/src/gui/util/qshadergenerator.cpp @@ -346,10 +346,10 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) code << QByteArrayLiteral("void main()"); code << QByteArrayLiteral("{"); - const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*((?:\\w+\\(.*\\))|(?:\\w+)).*;$")); - const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("^(.*\\s+(v\\d+))\\s*=\\s*(.*);$")); + const QRegularExpression localToGlobalRegExp(QStringLiteral("[^;]*\\s+(\\w+)\\s*=\\s*((?:\\w+\\(.*\\))|(?:\\w+))[^;]*;")); + const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("([^;]*\\s+(v\\d+))\\s*=\\s*([^;]*);")); const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*")); - const QRegularExpression outputToTemporaryAssignmentRegExp(QStringLiteral("^\\s*(\\w+)\\s*=\\s*(.*);$")); + const QRegularExpression outputToTemporaryAssignmentRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);")); struct Variable; @@ -517,14 +517,31 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) // Substitute variable names by generated vN variable names const QByteArray substitutionedLine = replaceParameters(line, node, format); - Variable *v = nullptr; + QRegularExpressionMatchIterator matches; switch (node.type()) { - // Record name of temporary variable that possibly references a global input - // We will replace the temporary variables by the matching global variables later - case QShaderNode::Input: { - const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine)); - if (match.hasMatch()) { + case QShaderNode::Input: + matches = localToGlobalRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); + break; + case QShaderNode::Function: + matches = temporaryVariableToAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); + break; + case QShaderNode::Output: + matches = outputToTemporaryAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); + break; + case QShaderNode::Invalid: + break; + } + + while (matches.hasNext()) { + QRegularExpressionMatch match = matches.next(); + + Variable *v = nullptr; + + switch (node.type()) { + // Record name of temporary variable that possibly references a global input + // We will replace the temporary variables by the matching global variables later + case QShaderNode::Input: { const QString localVariable = match.captured(1); const QString globalVariable = match.captured(2); @@ -535,13 +552,10 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) Assignment assignment; assignment.expression = globalVariable; v->assignment = assignment; + break; } - break; - } - case QShaderNode::Function: { - const QRegularExpressionMatch match = temporaryVariableToAssignmentRegExp.match(QString::fromUtf8(substitutionedLine)); - if (match.hasMatch()) { + case QShaderNode::Function: { const QString localVariableDeclaration = match.captured(1); const QString localVariableName = match.captured(2); const QString assignmentContent = match.captured(3); @@ -554,13 +568,10 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) // Find variables that may be referenced in the assignment gatherTemporaryVariablesFromAssignment(v, assignmentContent); + break; } - break; - } - case QShaderNode::Output: { - const QRegularExpressionMatch match = outputToTemporaryAssignmentRegExp.match(QString::fromUtf8(substitutionedLine)); - if (match.hasMatch()) { + case QShaderNode::Output: { const QString outputDeclaration = match.captured(1); const QString assignmentContent = match.captured(2); @@ -575,17 +586,17 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) // Find variables that may be referenced in the assignment gatherTemporaryVariablesFromAssignment(v, assignmentContent); + break; + } + case QShaderNode::Invalid: + break; } - break; - } - case QShaderNode::Invalid: - break; - } - LineContent lineContent; - lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine); - lineContent.var = v; - lines << lineContent; + LineContent lineContent; + lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine); + lineContent.var = v; + lines << lineContent; + } } // Go through all lines diff --git a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp index 2b9b08a18a..76211f8358 100644 --- a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp +++ b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp @@ -199,6 +199,7 @@ private slots: void shouldUseGlobalVariableRatherThanTemporaries(); void shouldGenerateTemporariesWisely(); void shouldHandlePortNamesPrefixingOneAnother(); + void shouldHandleNodesWithMultipleOutputPorts(); }; void tst_QShaderGenerator::shouldHaveDefaultState() @@ -1299,6 +1300,78 @@ void tst_QShaderGenerator::shouldHandlePortNamesPrefixingOneAnother() QCOMPARE(code, expected.join("\n")); } +void tst_QShaderGenerator::shouldHandleNodesWithMultipleOutputPorts() +{ + // GIVEN + const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); + + auto input = createNode({ + createPort(QShaderNodePort::Output, "output0"), + createPort(QShaderNodePort::Output, "output1") + }); + input.addRule(gl4, QShaderNode::Rule("vec4 $output0 = globalIn0;" + "float $output1 = globalIn1;", + QByteArrayList() << "in vec4 globalIn0;" << "in float globalIn1;")); + + auto function = createNode({ + createPort(QShaderNodePort::Input, "input0"), + createPort(QShaderNodePort::Input, "input1"), + createPort(QShaderNodePort::Output, "output0"), + createPort(QShaderNodePort::Output, "output1") + }); + function.addRule(gl4, QShaderNode::Rule("vec4 $output0 = $input0;" + "float $output1 = $input1;")); + + auto output = createNode({ + createPort(QShaderNodePort::Input, "input0"), + createPort(QShaderNodePort::Input, "input1") + }); + + output.addRule(gl4, QShaderNode::Rule("globalOut0 = $input0;" + "globalOut1 = $input1;", + QByteArrayList() << "out vec4 globalOut0;" << "out float globalOut1;")); + + // WHEN + const auto graph = [=] { + auto res = QShaderGraph(); + + res.addNode(input); + res.addNode(function); + res.addNode(output); + + res.addEdge(createEdge(input.uuid(), "output0", function.uuid(), "input0")); + res.addEdge(createEdge(input.uuid(), "output1", function.uuid(), "input1")); + + res.addEdge(createEdge(function.uuid(), "output0", output.uuid(), "input0")); + res.addEdge(createEdge(function.uuid(), "output1", output.uuid(), "input1")); + + return res; + }(); + + auto generator = QShaderGenerator(); + generator.graph = graph; + generator.format = gl4; + + const auto code = generator.createShaderCode(); + + // THEN + const auto expected = QByteArrayList() + << "#version 400 core" + << "" + << "in vec4 globalIn0;" + << "in float globalIn1;" + << "out vec4 globalOut0;" + << "out float globalOut1;" + << "" + << "void main()" + << "{" + << " globalOut0 = globalIn0;" + << " globalOut1 = globalIn1;" + << "}" + << ""; + QCOMPARE(code, expected.join("\n")); +} + QTEST_MAIN(tst_QShaderGenerator) #include "tst_qshadergenerator.moc" -- cgit v1.2.1 From f9086ebd0198c53e8a811af47e0ff0c84d78eb30 Mon Sep 17 00:00:00 2001 From: Nicolas Guichard Date: Tue, 18 Feb 2020 17:40:04 +0100 Subject: QShaderGenerator: Allow more expressions in input nodes Currently QShaderGenerator will crash when encountering some expressions in input nodes. For example, this node prototype would make it crash: "VERTEX_COLOR": { "outputs": ["color", "alpha"], "rules": [ "headerSnippets": ["in vec4 vertexColor;"], "substitution": "vec3 $color = vertexColor.rgb; float $alpha = vertexColor.a;" ] } Change-Id: I37abb8099d376843a4cb13228140467dc1b8f60c Reviewed-by: Paul Lemire --- src/gui/util/qshadergenerator.cpp | 9 ++-- .../util/qshadergenerator/tst_qshadergenerator.cpp | 50 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp index 244b95605b..1d47f51e84 100644 --- a/src/gui/util/qshadergenerator.cpp +++ b/src/gui/util/qshadergenerator.cpp @@ -346,10 +346,9 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) code << QByteArrayLiteral("void main()"); code << QByteArrayLiteral("{"); - const QRegularExpression localToGlobalRegExp(QStringLiteral("[^;]*\\s+(\\w+)\\s*=\\s*((?:\\w+\\(.*\\))|(?:\\w+))[^;]*;")); const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("([^;]*\\s+(v\\d+))\\s*=\\s*([^;]*);")); const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*")); - const QRegularExpression outputToTemporaryAssignmentRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);")); + const QRegularExpression statementRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);")); struct Variable; @@ -521,14 +520,12 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) switch (node.type()) { case QShaderNode::Input: - matches = localToGlobalRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); + case QShaderNode::Output: + matches = statementRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); break; case QShaderNode::Function: matches = temporaryVariableToAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); break; - case QShaderNode::Output: - matches = outputToTemporaryAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); - break; case QShaderNode::Invalid: break; } diff --git a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp index 76211f8358..56df69dde8 100644 --- a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp +++ b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp @@ -200,6 +200,7 @@ private slots: void shouldGenerateTemporariesWisely(); void shouldHandlePortNamesPrefixingOneAnother(); void shouldHandleNodesWithMultipleOutputPorts(); + void shouldHandleExpressionsInInputNodes(); }; void tst_QShaderGenerator::shouldHaveDefaultState() @@ -1372,6 +1373,55 @@ void tst_QShaderGenerator::shouldHandleNodesWithMultipleOutputPorts() QCOMPARE(code, expected.join("\n")); } +void tst_QShaderGenerator::shouldHandleExpressionsInInputNodes() +{ + // GIVEN + const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); + + auto input = createNode({ + createPort(QShaderNodePort::Output, "output") + }); + input.addRule(gl4, QShaderNode::Rule("float $output = 3 + 4;")); + + auto output = createNode({ + createPort(QShaderNodePort::Input, "input") + }); + + output.addRule(gl4, QShaderNode::Rule("globalOut = $input;", + QByteArrayList() << "out float globalOut;")); + + // WHEN + const auto graph = [=] { + auto res = QShaderGraph(); + + res.addNode(input); + res.addNode(output); + + res.addEdge(createEdge(input.uuid(), "output", output.uuid(), "input")); + + return res; + }(); + + auto generator = QShaderGenerator(); + generator.graph = graph; + generator.format = gl4; + + const auto code = generator.createShaderCode(); + + // THEN + const auto expected = QByteArrayList() + << "#version 400 core" + << "" + << "out float globalOut;" + << "" + << "void main()" + << "{" + << " globalOut = 3 + 4;" + << "}" + << ""; + QCOMPARE(code, expected.join("\n")); +} + QTEST_MAIN(tst_QShaderGenerator) #include "tst_qshadergenerator.moc" -- cgit v1.2.1 From fb6acf08bbd7a68d027282251747620b942bd1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 18 Feb 2020 10:13:22 +0100 Subject: Replace usage of std::result_of with decltype It's slated for removal in c++20 Fixes: QTBUG-82240 Change-Id: I7b35c151413b131ca49b2c09b6382efc3fc8ccb6 Reviewed-by: Timur Pocheptsov --- src/corelib/kernel/qobjectdefs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index dc2d832fe5..becbb90a61 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -532,7 +532,7 @@ struct Q_CORE_EXPORT QMetaObject static typename std::enable_if::IsPointerToMemberFunction && QtPrivate::FunctionPointer::ArgumentCount == -1 && !std::is_convertible::value, bool>::type - invokeMethod(QObject *context, Func function, typename std::result_of::type *ret) + invokeMethod(QObject *context, Func function, decltype(function()) *ret) { return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgs(std::move(function)), -- cgit v1.2.1 From 4e1c41a26eaa51ebb133e9c846e8e93bbe318a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 20 Feb 2020 11:25:49 +0100 Subject: QStyle: Use primary screen DPI as default DPI Change d603ee68 made the default DPI be 96, for cases where a style option is not provided. This causes inconsistencies, since there are in fact several cases where QStyle API is called without a style option. Restore historical Qt behavior of using the primary screen DPI. Single-screen systems should now be consistent, as before. Task-number: QTBUG-82356 Change-Id: I849934ca2e5604b9fb2f045ed4f6058f3e0426ff Reviewed-by: Friedemann Kleint --- src/widgets/styles/qstylehelper.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 9477ca86da..6016224faa 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -101,7 +101,13 @@ Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option) if (option) return option->fontMetrics.fontDpi(); + // Fall back to historical Qt behavior: hardocded 72 DPI on mac, + // primary screen DPI on other platforms. +#ifdef Q_OS_DARWIN return qstyleBaseDpi; +#else + return qt_defaultDpiX(); +#endif } Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, qreal dpi) -- cgit v1.2.1