Merge "Merge remote-tracking branch 'origin/4.10'"

This commit is contained in:
The Qt Project
2019-07-31 07:19:30 +00:00
28 changed files with 214 additions and 192 deletions

View File

@@ -25,9 +25,9 @@
import QtQuick 2.1 import QtQuick 2.1
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import QtQuick.Controls.Styles 1.1
Loader { Loader {
id: gradientDialogLoader id: gradientDialogLoader
@@ -93,33 +93,12 @@ Loader {
text: qsTr("Gradient Properties") text: qsTr("Gradient Properties")
} }
Button { StudioControls.AbstractButton {
width: 16 width: 16
height: 16 height: 16
style: ButtonStyle { buttonIcon: StudioTheme.Constants.closeCross
background: Item {
Image {
width: 16
height: 16
source: "image://icons/error"
opacity: {
if (control.pressed)
return 0.8
return 1.0
}
Rectangle {
z: -1
anchors.fill: parent
color: control.pressed
|| control.hovered ? Theme.qmlDesignerBackgroundColorDarker() : Theme.qmlDesignerButtonColor()
border.color: Theme.qmlDesignerBorderColor()
radius: 2
}
}
}
}
onClicked: gradientDialogLoader.visible = false onClicked: gradientDialogLoader.visible = false
backgroundRadius: 2
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.margins: 4 anchors.margins: 4

View File

@@ -25,7 +25,6 @@
import QtQuick 2.1 import QtQuick 2.1
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls
Image { Image {
id: root id: root

View File

@@ -25,6 +25,7 @@
import QtQuick 2.1 import QtQuick 2.1
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import StudioTheme 1.0 as StudioTheme
Item { Item {
width: grid.width width: grid.width
@@ -41,10 +42,19 @@ Item {
readonly property color selectedColor: Theme.qmlDesignerBackgroundColorDarkAlternate() readonly property color selectedColor: Theme.qmlDesignerBackgroundColorDarkAlternate()
readonly property color unselectedColor: Theme.qmlDesignerBackgroundColorDarker() readonly property color unselectedColor: Theme.qmlDesignerBackgroundColorDarker()
ExtendedFunctionButton { ExtendedFunctionLogic {
id: extFuncLogic
backendValue: originControl.backendValue backendValue: originControl.backendValue
visible: originControl.enabled }
ActionIndicator {
anchors.left: grid.right anchors.left: grid.right
anchors.leftMargin: grid.spacing
visible: originControl.enabled
icon.color: extFuncLogic.color
icon.text: extFuncLogic.glyph
onClicked: extFuncLogic.show()
} }
ColorLogic { ColorLogic {
@@ -100,8 +110,8 @@ Item {
Rectangle { Rectangle {
property bool selected: false property bool selected: false
id: topLeft id: topLeft
width: 15 width: StudioTheme.Values.height
height: 15 height: StudioTheme.Values.height
color: selected ? selectedColor : unselectedColor color: selected ? selectedColor : unselectedColor
border.width: selected ? 2 : 1 border.width: selected ? 2 : 1
border.color: selected ? originControl.borderColorSelected : originControl.borderColor border.color: selected ? originControl.borderColorSelected : originControl.borderColor

View File

@@ -33,6 +33,7 @@ T.AbstractButton {
property alias buttonIcon: buttonIcon.text property alias buttonIcon: buttonIcon.text
property alias iconColor: buttonIcon.color property alias iconColor: buttonIcon.color
property alias backgroundVisible: buttonBackground.visible property alias backgroundVisible: buttonBackground.visible
property alias backgroundRadius: buttonBackground.radius
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding) implicitContentWidth + leftPadding + rightPadding)

View File

@@ -60,7 +60,8 @@ Rectangle {
State { State {
name: "hovered" name: "hovered"
when: actionIndicator.hover && !actionIndicator.pressed when: actionIndicator.hover && !actionIndicator.pressed
&& !myControl.edit && !myControl.drag && myControl.enabled && (!myControl || (!myControl.edit && !myControl.drag))
&& actionIndicator.enabled
PropertyChanges { PropertyChanges {
target: actionIndicatorIcon target: actionIndicatorIcon
scale: 1.2 scale: 1.2
@@ -68,7 +69,7 @@ Rectangle {
}, },
State { State {
name: "disabled" name: "disabled"
when: !myControl.enabled when: !actionIndicator.enabled
PropertyChanges { PropertyChanges {
target: actionIndicatorIcon target: actionIndicatorIcon
color: StudioTheme.Values.themeTextColorDisabled color: StudioTheme.Values.themeTextColorDisabled

View File

@@ -24,20 +24,19 @@
****************************************************************************/ ****************************************************************************/
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 2.12 as Controls2
Menu { Menu {
id: contextMenu id: contextMenu
property Item myTextEdit property Item myTextEdit
Controls2.MenuItem { MenuItem {
text: "Undo" text: "Undo"
enabled: myTextEdit.canUndo enabled: myTextEdit.canUndo
onTriggered: myTextEdit.undo() onTriggered: myTextEdit.undo()
/* shortcut: StandardKey.Undo Shortcuts in QQC2 seem to override global shortcuts */ /* shortcut: StandardKey.Undo Shortcuts in QQC2 seem to override global shortcuts */
} }
Controls2.MenuItem { MenuItem {
text: "Redo" text: "Redo"
enabled: myTextEdit.canRedo enabled: myTextEdit.canRedo
onTriggered: myTextEdit.redo() onTriggered: myTextEdit.redo()
@@ -47,32 +46,32 @@ Menu {
MenuSeparator { MenuSeparator {
} }
Controls2.MenuItem { MenuItem {
text: "Copy" text: "Copy"
enabled: myTextEdit.selectedText !== "" enabled: myTextEdit.selectedText !== ""
onTriggered: myTextEdit.copy() onTriggered: myTextEdit.copy()
/* shortcut: StandardKey.Copy Shortcuts in QQC2 seem to override global shortcuts */ /* shortcut: StandardKey.Copy Shortcuts in QQC2 seem to override global shortcuts */
} }
Controls2.MenuItem { MenuItem {
text: "Cut" text: "Cut"
enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly
onTriggered: myTextEdit.cut() onTriggered: myTextEdit.cut()
/* shortcut: StandardKey.Cut Shortcuts in QQC2 seem to override global shortcuts */ /* shortcut: StandardKey.Cut Shortcuts in QQC2 seem to override global shortcuts */
} }
Controls2.MenuItem { MenuItem {
text: "Paste" text: "Paste"
enabled: myTextEdit.canPaste enabled: myTextEdit.canPaste
onTriggered: myTextEdit.paste() onTriggered: myTextEdit.paste()
/* shortcut: StandardKey.Paste Shortcuts in QQC2 seem to override global shortcuts */ /* shortcut: StandardKey.Paste Shortcuts in QQC2 seem to override global shortcuts */
} }
Controls2.MenuItem { MenuItem {
text: "Delete" text: "Delete"
enabled: myTextEdit.selectedText !== "" enabled: myTextEdit.selectedText !== ""
onTriggered: myTextEdit.remove(myTextEdit.selectionStart, onTriggered: myTextEdit.remove(myTextEdit.selectionStart,
myTextEdit.selectionEnd) myTextEdit.selectionEnd)
/* shortcut: StandardKey.Delete Shortcuts in QQC2 seem to override global shortcuts */ /* shortcut: StandardKey.Delete Shortcuts in QQC2 seem to override global shortcuts */
} }
Controls2.MenuItem { MenuItem {
text: "Clear" text: "Clear"
enabled: myTextEdit.text !== "" enabled: myTextEdit.text !== ""
onTriggered: myTextEdit.clear() onTriggered: myTextEdit.clear()
@@ -82,7 +81,7 @@ Menu {
MenuSeparator { MenuSeparator {
} }
Controls2.MenuItem { MenuItem {
text: "Select All" text: "Select All"
enabled: myTextEdit.text !== "" enabled: myTextEdit.text !== ""
&& myTextEdit.selectedText !== myTextEdit.text && myTextEdit.selectedText !== myTextEdit.text

View File

@@ -46,11 +46,6 @@ T.MenuItem {
action: Action {} action: Action {}
contentItem: Item { contentItem: Item {
id: menuItem
width: control.menu.width
height: StudioTheme.Values.height
Text { Text {
id: textLabel id: textLabel
text: control.text text: control.text
@@ -77,11 +72,11 @@ T.MenuItem {
background: Rectangle { background: Rectangle {
implicitWidth: textLabel.implicitWidth + control.labelSpacing + shortcutLabel.implicitWidth implicitWidth: textLabel.implicitWidth + control.labelSpacing + shortcutLabel.implicitWidth
+ control.leftPadding + control.rightPadding // TODO + control.leftPadding + control.rightPadding
implicitHeight: StudioTheme.Values.height implicitHeight: StudioTheme.Values.height
x: StudioTheme.Values.border x: StudioTheme.Values.border
y: StudioTheme.Values.border y: StudioTheme.Values.border
width: control.width - (StudioTheme.Values.border * 2) width: control.menu.width - (StudioTheme.Values.border * 2)
height: control.height - (StudioTheme.Values.border * 2) height: control.height - (StudioTheme.Values.border * 2)
color: control.down ? control.palette.midlight : control.highlighted ? StudioTheme.Values.themeInteraction : "transparent" color: control.down ? control.palette.midlight : control.highlighted ? StudioTheme.Values.themeInteraction : "transparent"
} }

View File

@@ -36,11 +36,10 @@ T.MenuSeparator {
implicitContentHeight + topPadding + bottomPadding) implicitContentHeight + topPadding + bottomPadding)
padding: 0 padding: 0
verticalPadding: padding
contentItem: Rectangle { contentItem: Rectangle {
implicitWidth: 10 width: control.parent.width
implicitHeight: StudioTheme.Values.border height: StudioTheme.Values.border
color: StudioTheme.Values.themeControlOutline color: StudioTheme.Values.themeControlOutline
} }
} }

View File

@@ -131,13 +131,13 @@ void AutoTestUnitTests::testCodeParser_data()
<< 1 << 0 << 0 << 0; << 1 << 0 << 0 << 0;
QTest::newRow("mixedAutoTestAndQuickTests") QTest::newRow("mixedAutoTestAndQuickTests")
<< QString(m_tmpDir->path() + "/mixed_atp/mixed_atp.pro") << QString(m_tmpDir->path() + "/mixed_atp/mixed_atp.pro")
<< 4 << 7 << 3 << 10; << 4 << 10 << 4 << 10;
QTest::newRow("plainAutoTestQbs") QTest::newRow("plainAutoTestQbs")
<< QString(m_tmpDir->path() + "/plain/plain.qbs") << QString(m_tmpDir->path() + "/plain/plain.qbs")
<< 1 << 0 << 0 << 0; << 1 << 0 << 0 << 0;
QTest::newRow("mixedAutoTestAndQuickTestsQbs") QTest::newRow("mixedAutoTestAndQuickTestsQbs")
<< QString(m_tmpDir->path() + "/mixed_atp/mixed_atp.qbs") << QString(m_tmpDir->path() + "/mixed_atp/mixed_atp.qbs")
<< 4 << 7 << 3 << 10; << 4 << 10 << 4 << 10;
} }
void AutoTestUnitTests::testCodeParserSwitchStartup() void AutoTestUnitTests::testCodeParserSwitchStartup()
@@ -183,8 +183,8 @@ void AutoTestUnitTests::testCodeParserSwitchStartup_data()
m_tmpDir->path() + "/mixed_atp/mixed_atp.qbs"}); m_tmpDir->path() + "/mixed_atp/mixed_atp.qbs"});
QList<int> expectedAutoTests = QList<int>() << 1 << 4 << 1 << 4; QList<int> expectedAutoTests = QList<int>() << 1 << 4 << 1 << 4;
QList<int> expectedNamedQuickTests = QList<int>() << 0 << 7 << 0 << 7; QList<int> expectedNamedQuickTests = QList<int>() << 0 << 10 << 0 << 10;
QList<int> expectedUnnamedQuickTests = QList<int>() << 0 << 3 << 0 << 3; QList<int> expectedUnnamedQuickTests = QList<int>() << 0 << 4 << 0 << 4;
QList<int> expectedDataTagsCount = QList<int>() << 0 << 10 << 0 << 10; QList<int> expectedDataTagsCount = QList<int>() << 0 << 10 << 0 << 10;
QTest::newRow("loadMultipleProjects") QTest::newRow("loadMultipleProjects")

View File

@@ -190,35 +190,36 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface<TestParseResultPtr
if (!qmlVisitor.isValid()) if (!qmlVisitor.isValid())
return false; return false;
const QString testCaseName = qmlVisitor.testCaseName(); const QVector<QuickTestCaseSpec> &testCases = qmlVisitor.testCases();
const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation();
const QMap<QString, TestCodeLocationAndType> &testFunctions = qmlVisitor.testFunctions();
QuickTestParseResult *parseResult = new QuickTestParseResult(id); for (const QuickTestCaseSpec &testCase : testCases) {
parseResult->proFile = proFile; const QString testCaseName = testCase.m_caseName;
parseResult->itemType = TestTreeItem::TestCase;
QMap<QString, TestCodeLocationAndType>::ConstIterator it = testFunctions.begin();
const QMap<QString, TestCodeLocationAndType>::ConstIterator end = testFunctions.end();
for ( ; it != end; ++it) {
const TestCodeLocationAndType &loc = it.value();
QuickTestParseResult *funcResult = new QuickTestParseResult(id);
funcResult->name = it.key();
funcResult->displayName = it.key();
funcResult->itemType = loc.m_type;
funcResult->fileName = loc.m_name;
funcResult->line = loc.m_line;
funcResult->column = loc.m_column;
funcResult->proFile = proFile;
parseResult->children.append(funcResult); QuickTestParseResult *parseResult = new QuickTestParseResult(id);
parseResult->proFile = proFile;
parseResult->itemType = TestTreeItem::TestCase;
if (!testCaseName.isEmpty()) {
parseResult->fileName = testCase.m_locationAndType.m_name;
parseResult->name = testCaseName;
parseResult->line = testCase.m_locationAndType.m_line;
parseResult->column = testCase.m_locationAndType.m_column;
}
for (auto function : testCase.m_functions) {
QuickTestParseResult *funcResult = new QuickTestParseResult(id);
funcResult->name = function.m_functionName;
funcResult->displayName = function.m_functionName;
funcResult->itemType = function.m_locationAndType.m_type;
funcResult->fileName = function.m_locationAndType.m_name;
funcResult->line = function.m_locationAndType.m_line;
funcResult->column = function.m_locationAndType.m_column;
funcResult->proFile = proFile;
parseResult->children.append(funcResult);
}
futureInterface.reportResult(TestParseResultPtr(parseResult));
} }
if (!testCaseName.isEmpty()) {
parseResult->fileName = tcLocationAndType.m_name;
parseResult->name = testCaseName;
parseResult->line = tcLocationAndType.m_line;
parseResult->column = tcLocationAndType.m_column;
}
futureInterface.reportResult(TestParseResultPtr(parseResult));
return true; return true;
} }

View File

@@ -323,11 +323,11 @@ TestTreeItem *QuickTestTreeItem::find(const TestParseResult *result)
TestTreeItem *group = findFirstLevelChild([path](TestTreeItem *group) { TestTreeItem *group = findFirstLevelChild([path](TestTreeItem *group) {
return group->filePath() == path; return group->filePath() == path;
}); });
return group ? group->findChildByFile(result->fileName) : nullptr; return group ? group->findChildByNameAndFile(result->name, result->fileName) : nullptr;
} }
return findChildByFile(result->fileName); return findChildByNameAndFile(result->name, result->fileName);
case GroupNode: case GroupNode:
return findChildByFile(result->fileName); return findChildByNameAndFile(result->name, result->fileName);
case TestCase: case TestCase:
return name().isEmpty() ? findChildByNameAndFile(result->name, result->fileName) return name().isEmpty() ? findChildByNameAndFile(result->name, result->fileName)
: findChildByName(result->name); : findChildByName(result->name);
@@ -345,9 +345,9 @@ TestTreeItem *QuickTestTreeItem::findChild(const TestTreeItem *other)
case Root: case Root:
if (otherType == TestCase && other->name().isEmpty()) if (otherType == TestCase && other->name().isEmpty())
return unnamedQuickTests(); return unnamedQuickTests();
return findChildByFileAndType(other->filePath(), otherType); return findChildByFileNameAndType(other->filePath(), other->name(), otherType);
case GroupNode: case GroupNode:
return findChildByFileAndType(other->filePath(), otherType); return findChildByFileNameAndType(other->filePath(), other->name(), otherType);
case TestCase: case TestCase:
if (otherType != TestFunction && otherType != TestDataFunction && otherType != TestSpecialFunction) if (otherType != TestFunction && otherType != TestDataFunction && otherType != TestSpecialFunction)
return nullptr; return nullptr;
@@ -444,6 +444,16 @@ void QuickTestTreeItem::markForRemovalRecursively(const QString &filePath)
} }
} }
TestTreeItem *QuickTestTreeItem::findChildByFileNameAndType(const QString &filePath,
const QString &name,
TestTreeItem::Type tType)
{
return findFirstLevelChild([filePath, name, tType](const TestTreeItem *other) {
return other->type() == tType && other->name() == name && other->filePath() == filePath;
});
}
TestTreeItem *QuickTestTreeItem::unnamedQuickTests() const TestTreeItem *QuickTestTreeItem::unnamedQuickTests() const
{ {
if (type() != Root) if (type() != Root)

View File

@@ -57,6 +57,8 @@ public:
QSet<QString> internalTargets() const override; QSet<QString> internalTargets() const override;
void markForRemovalRecursively(const QString &filePath) override; void markForRemovalRecursively(const QString &filePath) override;
private: private:
TestTreeItem *findChildByFileNameAndType(const QString &filePath, const QString &name,
Type tType);
TestTreeItem *unnamedQuickTests() const; TestTreeItem *unnamedQuickTests() const;
}; };

View File

@@ -31,6 +31,7 @@
#include <qmljs/qmljslink.h> #include <qmljs/qmljslink.h>
#include <qmljs/qmljsutils.h> #include <qmljs/qmljsutils.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h>
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
@@ -85,29 +86,29 @@ static bool isDerivedFromTestCase(QmlJS::AST::UiQualifiedId *id, const QmlJS::Do
bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
{ {
const QStringRef name = ast->qualifiedTypeNameId->name; const QStringRef name = ast->qualifiedTypeNameId->name;
m_objectStack.push(name.toString()); m_objectIsTestStack.push(false);
if (name != "TestCase") { if (name != "TestCase") {
m_insideTestCase = false;
if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot)) if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot))
return true; return true;
} else if (!documentImportsQtTest(m_currentDoc.data())) { } else if (!documentImportsQtTest(m_currentDoc.data())) {
return true; // find nested TestCase items as well return true; // find nested TestCase items as well
} }
m_typeIsTestCase = true; m_objectIsTestStack.top() = true;
m_insideTestCase = true;
m_currentTestCaseName.clear();
const auto sourceLocation = ast->firstSourceLocation(); const auto sourceLocation = ast->firstSourceLocation();
m_testCaseLocation.m_name = m_currentDoc->fileName(); QuickTestCaseSpec currentSpec;
m_testCaseLocation.m_line = sourceLocation.startLine; currentSpec.m_locationAndType.m_name = m_currentDoc->fileName();
m_testCaseLocation.m_column = sourceLocation.startColumn - 1; currentSpec.m_locationAndType.m_line = sourceLocation.startLine;
m_testCaseLocation.m_type = TestTreeItem::TestCase; currentSpec.m_locationAndType.m_column = sourceLocation.startColumn - 1;
currentSpec.m_locationAndType.m_type = TestTreeItem::TestCase;
m_caseParseStack.push(currentSpec);
return true; return true;
} }
void TestQmlVisitor::endVisit(QmlJS::AST::UiObjectDefinition *) void TestQmlVisitor::endVisit(QmlJS::AST::UiObjectDefinition *)
{ {
m_insideTestCase = m_objectStack.pop() == "TestCase"; if (!m_objectIsTestStack.isEmpty() && m_objectIsTestStack.pop() && !m_caseParseStack.isEmpty())
m_testCases << m_caseParseStack.pop();
} }
bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast) bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
@@ -118,7 +119,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast) bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast)
{ {
if (m_insideTestCase) if (m_objectIsTestStack.top())
m_expectTestCaseName = ast->qualifiedId->name == "name"; m_expectTestCaseName = ast->qualifiedId->name == "name";
return m_expectTestCaseName; return m_expectTestCaseName;
} }
@@ -131,6 +132,9 @@ void TestQmlVisitor::endVisit(QmlJS::AST::UiScriptBinding *)
bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
{ {
if (m_caseParseStack.isEmpty())
return false;
const QStringRef name = ast->name; const QStringRef name = ast->name;
if (name.startsWith("test_") if (name.startsWith("test_")
|| name.startsWith("benchmark_") || name.startsWith("benchmark_")
@@ -148,15 +152,17 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
else else
locationAndType.m_type = TestTreeItem::TestFunction; locationAndType.m_type = TestTreeItem::TestFunction;
m_testFunctions.insert(name.toString(), locationAndType); m_caseParseStack.top().m_functions.append(
QuickTestFunctionSpec{name.toString(), locationAndType});
} }
return false; return false;
} }
bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast) bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast)
{ {
if (m_expectTestCaseName && m_currentTestCaseName.isEmpty()) { if (m_expectTestCaseName) {
m_currentTestCaseName = ast->value.toString(); QTC_ASSERT(!m_caseParseStack.isEmpty(), return false);
m_caseParseStack.top().m_caseName = ast->value.toString();
m_expectTestCaseName = false; m_expectTestCaseName = false;
} }
return false; return false;

View File

@@ -37,6 +37,21 @@
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
class QuickTestFunctionSpec
{
public:
QString m_functionName;
TestCodeLocationAndType m_locationAndType;
};
class QuickTestCaseSpec
{
public:
QString m_caseName;
TestCodeLocationAndType m_locationAndType;
QVector<QuickTestFunctionSpec> m_functions;
};
class TestQmlVisitor : public QmlJS::AST::Visitor class TestQmlVisitor : public QmlJS::AST::Visitor
{ {
public: public:
@@ -50,20 +65,15 @@ public:
bool visit(QmlJS::AST::FunctionDeclaration *ast) override; bool visit(QmlJS::AST::FunctionDeclaration *ast) override;
bool visit(QmlJS::AST::StringLiteral *ast) override; bool visit(QmlJS::AST::StringLiteral *ast) override;
QString testCaseName() const { return m_currentTestCaseName; } QVector<QuickTestCaseSpec> testCases() const { return m_testCases; }
TestCodeLocationAndType testCaseLocation() const { return m_testCaseLocation; } bool isValid() const { return !m_testCases.isEmpty(); }
QMap<QString, TestCodeLocationAndType> testFunctions() const { return m_testFunctions; }
bool isValid() const { return m_typeIsTestCase; }
private: private:
QmlJS::Document::Ptr m_currentDoc; QmlJS::Document::Ptr m_currentDoc;
QmlJS::Snapshot m_snapshot; QmlJS::Snapshot m_snapshot;
QString m_currentTestCaseName; QStack<QuickTestCaseSpec> m_caseParseStack;
TestCodeLocationAndType m_testCaseLocation; QVector<QuickTestCaseSpec> m_testCases;
QMap<QString, TestCodeLocationAndType> m_testFunctions; QStack<bool> m_objectIsTestStack;
QStack<QString> m_objectStack;
bool m_typeIsTestCase = false;
bool m_insideTestCase = false;
bool m_expectTestCaseName = false; bool m_expectTestCaseName = false;
}; };

View File

@@ -34,21 +34,38 @@ TestCase {
verify(blubb == bla, "Comparing concat equality") verify(blubb == bla, "Comparing concat equality")
} }
// nested TestCases actually fail TestCase {
// TestCase { name: "boo"
// name: "boo"
// function test_boo() { function test_boo() {
// verify(true); verify(true);
// } }
// TestCase { TestCase {
// name: "far" name: "far"
// function test_far() { function test_far() {
// verify(true); verify(true);
// } }
// } }
// }
function test_boo2() { // should not get added to "far", but to "boo"
verify(false);
}
}
TestCase {
name: "secondBoo"
function test_bar() {
compare(1, 1);
}
}
TestCase { // unnamed
function test_func() {
verify(true);
}
}
} }

View File

@@ -357,10 +357,15 @@ Utils::CommandLine CMakeBuildStep::cmakeCommand(CMakeRunConfiguration *rc) const
QString target; QString target;
if (isCurrentExecutableTarget(m_buildTarget)) { if (isCurrentExecutableTarget(m_buildTarget)) {
if (rc) if (rc) {
target = rc->buildKey().section('\n', 0, 0); target = rc->buildKey();
else const int pos = target.indexOf("///::///");
if (pos >= 0) {
target = target.mid(pos + 8);
}
} else {
target = "<i>&lt;" + tr(ADD_RUNCONFIGURATION_TEXT) + "&gt;</i>"; target = "<i>&lt;" + tr(ADD_RUNCONFIGURATION_TEXT) + "&gt;</i>";
}
} else { } else {
target = m_buildTarget; target = m_buildTarget;
} }

View File

@@ -42,6 +42,7 @@ find_package(Qt5WebEngineWidgets QUIET)
extend_qtc_plugin(Help extend_qtc_plugin(Help
CONDITION TARGET Qt5::WebEngineWidgets CONDITION TARGET Qt5::WebEngineWidgets
DEPENDS Qt5::WebEngineWidgets DEPENDS Qt5::WebEngineWidgets
DEFINES QTC_WEBENGINE_HELPVIEWER
SOURCES SOURCES
webenginehelpviewer.cpp webenginehelpviewer.cpp
webenginehelpviewer.h webenginehelpviewer.h

View File

@@ -109,38 +109,4 @@
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PerfLoadDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PerfLoadDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui> </ui>

View File

@@ -162,6 +162,33 @@ QVariant FileResourcesModel::modelNodeBackend() const
return QVariant(); return QVariant();
} }
bool filterMetaIcons(const QString &fileName)
{
QFileInfo info(fileName);
if (info.dir().path().split("/").contains("designer")) {
QDir currentDir = info.dir();
int i = 0;
while (!currentDir.isRoot() && i < 3) {
if (currentDir.dirName() == "designer") {
if (!currentDir.entryList({"*.metainfo"}).isEmpty())
return false;
}
currentDir.cdUp();
++i;
}
if (info.dir().dirName() == "designer")
return false;
}
return true;
}
void FileResourcesModel::setupModel() void FileResourcesModel::setupModel()
{ {
m_lock = true; m_lock = true;
@@ -174,7 +201,8 @@ void FileResourcesModel::setupModel()
QDirIterator it(m_dirPath.absolutePath(), filterList, QDir::Files, QDirIterator::Subdirectories); QDirIterator it(m_dirPath.absolutePath(), filterList, QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) { while (it.hasNext()) {
QString absolutePath = it.next(); QString absolutePath = it.next();
m_model.append(m_dirPath.relativeFilePath(absolutePath)); if (filterMetaIcons(absolutePath))
m_model.append(m_dirPath.relativeFilePath(absolutePath));
} }
m_lock = false; m_lock = false;

View File

@@ -142,7 +142,7 @@ void ChangePropertyVisitor::replaceMemberValue(UiObjectMember *propertyMember, b
if (publicMember->semicolonToken.isValid()) if (publicMember->semicolonToken.isValid())
endOffset = publicMember->semicolonToken.end(); endOffset = publicMember->semicolonToken.end();
else else
endOffset = publicMember->statement->lastSourceLocation().offset; endOffset = publicMember->statement->lastSourceLocation().end();
} else { } else {
startOffset = publicMember->lastSourceLocation().end(); startOffset = publicMember->lastSourceLocation().end();
endOffset = startOffset; endOffset = startOffset;

View File

@@ -97,7 +97,8 @@ QStringList globalQtEnums()
QStringList knownEnumScopes() QStringList knownEnumScopes()
{ {
static const QStringList list = { static const QStringList list = {
"TextInput", "TextEdit", "Material", "Universal", "Font", "Shape", "ShapePath", "AbstractButton" "TextInput", "TextEdit", "Material", "Universal", "Font", "Shape", "ShapePath",
"AbstractButton", "Text"
}; };
return list; return list;
} }

View File

@@ -611,6 +611,8 @@ void tst_TestCore::testRewriterDynamicProperties()
const QString inThere = testRewriterView1->rootModelNode().variantProperty("vv").value().value<QString>(); const QString inThere = testRewriterView1->rootModelNode().variantProperty("vv").value().value<QString>();
QCOMPARE(inThere, QString("Hello")); QCOMPARE(inThere, QString("Hello"));
rootModelNode.variantProperty("vv").setDynamicTypeNameAndValue("variant", "hallo2");
// test model2text // test model2text
// QPlainTextEdit textEdit2; // QPlainTextEdit textEdit2;
// textEdit2.setPlainText("import QtQuick 1.1; Item{}"); // textEdit2.setPlainText("import QtQuick 1.1; Item{}");

View File

@@ -139,6 +139,7 @@ def main():
switchViewTo(ViewConstants.EDIT) switchViewTo(ViewConstants.EDIT)
# start debugging # start debugging
clickButton(fancyDebugButton) clickButton(fancyDebugButton)
progressBarWait()
waitForObject(":Locals and Expressions_Debugger::Internal::WatchTreeView") waitForObject(":Locals and Expressions_Debugger::Internal::WatchTreeView")
rootIndex = getQModelIndexStr("text='QQmlEngine'", rootIndex = getQModelIndexStr("text='QQmlEngine'",
":Locals and Expressions_Debugger::Internal::WatchTreeView") ":Locals and Expressions_Debugger::Internal::WatchTreeView")
@@ -147,7 +148,9 @@ def main():
doubleClick(waitForObject(mainRect)) doubleClick(waitForObject(mainRect))
if not object.exists(":DebugModeWidget_Debugger::Internal::ConsoleView"): if not object.exists(":DebugModeWidget_Debugger::Internal::ConsoleView"):
invokeMenuItem("Window", "Output Panes", "QML Debugger Console") invokeMenuItem("Window", "Output Panes", "QML Debugger Console")
progressBarWait() # Window might be too small to show Locals, so close what we don't need
for view in ("Stack", "Breakpoints", "Expressions"):
invokeMenuItem("Window", "Views", view)
# color and float values have additional ZERO WIDTH SPACE (\u200b), different usage of # color and float values have additional ZERO WIDTH SPACE (\u200b), different usage of
# whitespaces inside expressions is part of the test # whitespaces inside expressions is part of the test
checks = [("color", u"#\u200b008000"), ("width", "50"), checks = [("color", u"#\u200b008000"), ("width", "50"),

View File

@@ -94,7 +94,7 @@ def __processSubItems__(treeObjStr, section, parModelIndexStr, doneItems,
itObj = "%s occurrence='%d'}" % (itObj[:-1], alreadyDone + 1) itObj = "%s occurrence='%d'}" % (itObj[:-1], alreadyDone + 1)
currentSelectedTreeItem = waitForObject(itObj, 3000) currentSelectedTreeItem = waitForObject(itObj, 3000)
tree.scrollTo(it) tree.scrollTo(it)
mouseClick(currentSelectedTreeItem) mouseClick(currentSelectedTreeItem, 5, 5, 0, Qt.LeftButton)
additionalFunc(indexName, *additionalParameters) additionalFunc(indexName, *additionalParameters)
currentSelectedTreeItem = None currentSelectedTreeItem = None
if model.rowCount(it) > 0: if model.rowCount(it) > 0:
@@ -210,6 +210,7 @@ def __getExpectedCompilers__():
compilers = ["g++", "gcc"] compilers = ["g++", "gcc"]
if platform.system() in ('Linux', 'Darwin'): if platform.system() in ('Linux', 'Darwin'):
compilers.extend(["clang++", "clang", "afl-clang"]) compilers.extend(["clang++", "clang", "afl-clang"])
compilers.extend(findAllFilesInPATH("clang-[0-9]"))
compilers.extend(findAllFilesInPATH("clang-[0-9].[0-9]")) compilers.extend(findAllFilesInPATH("clang-[0-9].[0-9]"))
compilers.extend(findAllFilesInPATH("*g++*")) compilers.extend(findAllFilesInPATH("*g++*"))
compilers.extend(findAllFilesInPATH("*gcc*")) compilers.extend(findAllFilesInPATH("*gcc*"))

View File

@@ -4873,9 +4873,7 @@
"zoomin_overlay@2x.png" "7" "zoomin_overlay@2x.png" "7"
"zoomout_overlay.png" "7" "zoomout_overlay.png" "7"
"zoomout_overlay@2x.png" "7" "zoomout_overlay@2x.png" "7"
"tooltip" "6" "f1.png" "7"
"images" "7"
"f1.png" "8"
"utils_global.h" "4" "utils_global.h" "4"
"utilsicons.cpp" "4" "utilsicons.cpp" "4"
"utilsicons.h" "4" "utilsicons.h" "4"
@@ -7576,10 +7574,8 @@
"debugger.qbs:248" "5" "debugger.qbs:248" "5"
"debuggerunittests.qrc" "5" "debuggerunittests.qrc" "5"
"/" "6" "/" "6"
"unit-tests" "7" "main.cpp" "8"
"simple" "8" "simple.pro" "8"
"main.cpp" "9"
"simple.pro" "9"
"Debugger dev headers" "3" "Debugger dev headers" "3"
"debugger.qbs:6" "4" "debugger.qbs:6" "4"
"Group 1" "4" "Group 1" "4"
1 text nestinglevel
4873 zoomin_overlay@2x.png 7
4874 zoomout_overlay.png 7
4875 zoomout_overlay@2x.png 7
4876 tooltip f1.png 6 7
images 7
f1.png 8
4877 utils_global.h 4
4878 utilsicons.cpp 4
4879 utilsicons.h 4
7574 debugger.qbs:248 5
7575 debuggerunittests.qrc 5
7576 / 6
7577 unit-tests main.cpp 7 8
7578 simple simple.pro 8
main.cpp 9
simple.pro 9
7579 Debugger dev headers 3
7580 debugger.qbs:6 4
7581 Group 1 4

View File

@@ -62,12 +62,10 @@ def main():
if not test.verify(object.exists(":Qt Creator_Core::OutputWindow"), if not test.verify(object.exists(":Qt Creator_Core::OutputWindow"),
"Did the General Messages view show up?"): "Did the General Messages view show up?"):
openGeneralMessages() openGeneralMessages()
# Verify messages appear once, from using default kit before configuring # Verify message appears once, written before a kit was selected for qtcreator.pro
generalMessages = str(waitForObject(":Qt Creator_Core::OutputWindow").plainText) generalMessages = str(waitForObject(":Qt Creator_Core::OutputWindow").plainText)
test.compare(generalMessages.count("Project MESSAGE: Cannot build Qt Creator with Qt version 5.6.1."), 1, test.compare(generalMessages.count('Cannot parse project "qtcreator": No kit selected.'), 1,
"Warning about outdated Qt shown?") 'Warning about missing kit selection shown?')
test.compare(generalMessages.count("Project ERROR: Use at least Qt 5.9.0."), 1,
"Minimum Qt version shown (once when parsing with default kit, once with selected)?")
# Verify that qmljs.g is in the project even when we don't know where (QTCREATORBUG-17609) # Verify that qmljs.g is in the project even when we don't know where (QTCREATORBUG-17609)
selectFromLocator("p qmljs.g", "qmljs.g") selectFromLocator("p qmljs.g", "qmljs.g")

View File

@@ -4259,9 +4259,7 @@
"zoomin_overlay@2x.png" "8" "zoomin_overlay@2x.png" "8"
"zoomout_overlay.png" "8" "zoomout_overlay.png" "8"
"zoomout_overlay@2x.png" "8" "zoomout_overlay@2x.png" "8"
"tooltip" "7" "f1.png" "8"
"images" "8"
"f1.png" "9"
"Other files" "3" "Other files" "3"
"utils.qbs" "4" "utils.qbs" "4"
"utils_dependencies" "2" "utils_dependencies" "2"
@@ -7292,10 +7290,8 @@
"tracepointoverlay@2x.png" "7" "tracepointoverlay@2x.png" "7"
"debuggerunittests.qrc" "4" "debuggerunittests.qrc" "4"
"/" "5" "/" "5"
"unit-tests" "6" "main.cpp" "7"
"simple" "7" "simple.pro" "7"
"main.cpp" "8"
"simple.pro" "8"
"Other files" "3" "Other files" "3"
"debugger.qbs" "4" "debugger.qbs" "4"
"debugger_dependencies" "2" "debugger_dependencies" "2"
@@ -18043,9 +18039,7 @@
"zoomin_overlay@2x.png" "8" "zoomin_overlay@2x.png" "8"
"zoomout_overlay.png" "8" "zoomout_overlay.png" "8"
"zoomout_overlay@2x.png" "8" "zoomout_overlay@2x.png" "8"
"tooltip" "7" "f1.png" "8"
"images" "8"
"f1.png" "9"
"Headers" "3" "Headers" "3"
"echoclangcodemodelserver.h" "4" "echoclangcodemodelserver.h" "4"
"Sources" "3" "Sources" "3"
@@ -19279,9 +19273,7 @@
"zoomin_overlay@2x.png" "9" "zoomin_overlay@2x.png" "9"
"zoomout_overlay.png" "9" "zoomout_overlay.png" "9"
"zoomout_overlay@2x.png" "9" "zoomout_overlay@2x.png" "9"
"tooltip" "8" "f1.png" "9"
"images" "9"
"f1.png" "10"
"gmock_dependency" "3" "gmock_dependency" "3"
"gmock_dependency.pri" "4" "gmock_dependency.pri" "4"
"Headers" "4" "Headers" "4"
1 text nestinglevel
4259 zoomin_overlay@2x.png 8
4260 zoomout_overlay.png 8
4261 zoomout_overlay@2x.png 8
4262 tooltip f1.png 7 8
images 8
f1.png 9
4263 Other files 3
4264 utils.qbs 4
4265 utils_dependencies 2
7290 tracepointoverlay@2x.png 7
7291 debuggerunittests.qrc 4
7292 / 5
7293 unit-tests main.cpp 6 7
7294 simple simple.pro 7
main.cpp 8
simple.pro 8
7295 Other files 3
7296 debugger.qbs 4
7297 debugger_dependencies 2
18039 zoomin_overlay@2x.png 8
18040 zoomout_overlay.png 8
18041 zoomout_overlay@2x.png 8
18042 tooltip f1.png 7 8
images 8
f1.png 9
18043 Headers 3
18044 echoclangcodemodelserver.h 4
18045 Sources 3
19273 zoomin_overlay@2x.png 9
19274 zoomout_overlay.png 9
19275 zoomout_overlay@2x.png 9
19276 tooltip f1.png 8 9
images 9
f1.png 10
19277 gmock_dependency 3
19278 gmock_dependency.pri 4
19279 Headers 4