diff options
Diffstat (limited to 'tests/auto')
23 files changed, 1017 insertions, 22 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 8612e2c1..6059cf7b 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -14,6 +14,7 @@ SUBDIRS += \ qquickapplicationwindow \ qquickcolor \ qquickdrawer \ + qquickheaderview \ qquickiconimage \ qquickiconlabel \ qquickimaginestyle \ @@ -29,7 +30,5 @@ SUBDIRS += \ qquickuniversalstyleconf \ revisions \ sanity \ - snippets - -# Requires lrelease, which isn't always available in CI. -qtHaveModule(tools): translation + snippets \ + translation diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml index 634d70a8..2d5069b3 100644 --- a/tests/auto/controls/data/tst_combobox.qml +++ b/tests/auto/controls/data/tst_combobox.qml @@ -1854,6 +1854,22 @@ TestCase { compare(closedSpy.count, 1) } + function test_comboBoxSelectTextByMouse() { + let control = createTemporaryObject(comboBox, testCase, + { editable: true, selectTextByMouse: true, model: [ "Some text" ], width: parent.width }) + verify(control) + waitForRendering(control) + control.forceActiveFocus() + + // Position the text cursor at the beginning of the text. + mouseClick(control, control.leftPadding, control.height / 2) + // Select all of the text. + mousePress(control, control.leftPadding, control.height / 2) + mouseMove(control, control.leftPadding + control.contentItem.width, control.height / 2) + mouseRelease(control, control.leftPadding + control.contentItem.width, control.height / 2) + compare(control.contentItem.selectedText, "Some text") + } + // QTBUG-78885: When the edit text is changed on an editable ComboBox, // and then that ComboBox loses focus, its currentIndex should change // to the index of the edit text (assuming a match is found). diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml index d3a0d8bb..22dbb352 100644 --- a/tests/auto/controls/data/tst_spinbox.qml +++ b/tests/auto/controls/data/tst_spinbox.qml @@ -658,4 +658,20 @@ TestCase { compare(control.displayText, data.displayTexts[i]) } } + + Component { + id: overriddenSpinBox + SpinBox { + value: 50 + up.indicator: Rectangle { + property string s: "this is the one" + } + } + } + + function test_indicatorOverridden() { + var control = createTemporaryObject(overriddenSpinBox, testCase) + verify(control) + compare(control.up.indicator.s, "this is the one"); + } } diff --git a/tests/auto/controls/data/tst_splitview.qml b/tests/auto/controls/data/tst_splitview.qml index 74e4c68e..ae8179b2 100644 --- a/tests/auto/controls/data/tst_splitview.qml +++ b/tests/auto/controls/data/tst_splitview.qml @@ -148,6 +148,7 @@ TestCase { color: "#444" Text { + objectName: "handleText_" + text text: parent.x + "," + parent.y + " " + parent.width + "x" + parent.height color: "white" anchors.centerIn: parent @@ -871,6 +872,42 @@ TestCase { } } + Component { + id: hiddenItemSplitViewComponent + + SplitView { + anchors.fill: parent + handle: handleComponent + + Rectangle { + objectName: "steelblue" + color: objectName + + SplitView.minimumWidth: 50 + } + Rectangle { + objectName: "tomato" + color: objectName + + SplitView.fillWidth: true + SplitView.preferredWidth: 200 + } + Rectangle { + objectName: "navajowhite" + color: objectName + visible: false + + SplitView.minimumWidth: visible ? 100 : 0 + } + Rectangle { + objectName: "mediumseagreen" + color: objectName + + SplitView.minimumWidth: 50 + } + } + } + function test_dragHandle_data() { var splitViewWidth = testCase.width - splitViewMargins * 2 var splitViewHeight = testCase.height - splitViewMargins * 2 @@ -1151,6 +1188,36 @@ TestCase { { x: 140, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, { x: 150, y: 0, width: 150, height: splitViewHeight } ] + }, + { + tag: "hiddenItemSplitViewComponent", + // [50] | [200 (fill)] | [hidden] | [50] + component: hiddenItemSplitViewComponent, + orientation: Qt.Horizontal, + fillIndex: 1, + handleIndex: 1, + // Drag to the horizontal centre of the SplitView. + newHandlePos: Qt.point(splitViewMargins + 150, testCase.height / 2), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: 50, height: splitViewHeight }, + { x: 50, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 50 + defaultHorizontalHandleWidth, y: 0, width: 200 - defaultHorizontalHandleWidth * 2, height: splitViewHeight }, + { x: 250 - (defaultHorizontalHandleWidth * 2) + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { hidden: true }, // Third item should be hidden. + { hidden: true }, // Handle for third item should be hidden. + { x: 250 - (defaultHorizontalHandleWidth * 2) + defaultHorizontalHandleWidth * 2, y: 0, width: 50, height: splitViewHeight } + ], + expectedGeometriesAfterDrag: [ + { x: 0, y: 0, width: 50, height: splitViewHeight }, + { x: 50, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // Width of the fill item should end up smaller. + { x: 50 + defaultHorizontalHandleWidth, y: 0, width: 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight }, + { x: 150 - (defaultHorizontalHandleWidth * 2) + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { hidden: true }, // Third item should be hidden. + { hidden: true }, // Handle for third item should be hidden. + // Width of the last item should grow. + { x: 150 - (defaultHorizontalHandleWidth * 2) + defaultHorizontalHandleWidth * 2, y: 0, width: 150, height: splitViewHeight } + ] } ] return data @@ -1171,7 +1238,7 @@ TestCase { else fillItem.SplitView.fillHeight = true - // Check the sizes of the items before the drag. + // Check the sizes (and visibility) of the items before the drag. verify(isPolishScheduled(control)) verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesBeforeDrag, "before drag") @@ -1179,6 +1246,7 @@ TestCase { // Drag the handle. var handles = findHandles(control) var targetHandle = handles[data.handleIndex] + verify(targetHandle.visible) mousePress(targetHandle) verify(control.resizing) // newHandlePos is in scene coordinates, so map it to coordinates local to the handle. diff --git a/tests/auto/controls/data/tst_tooltip.qml b/tests/auto/controls/data/tst_tooltip.qml index adea23ef..6d45b09d 100644 --- a/tests/auto/controls/data/tst_tooltip.qml +++ b/tests/auto/controls/data/tst_tooltip.qml @@ -241,12 +241,19 @@ TestCase { function test_openDuringExitTransitionWithTimeout() { let control = createTemporaryObject(toolTipWithExitTransition, testCase, { timeout: 250 }) verify(control) + + let openedSpy = signalSpy.createObject(control, { target: control, signalName: "opened" }) + verify(openedSpy.valid) + control.open() verify(control.visible) // Can't be fully open yet because the enter transition has only just started. compare(control.opened, false) compare(control.enter.running, true) - tryCompare(control, "opened", true) + // Wait for it to have opened. We don't check that the opened property is still true + // because it can result in hard-to-reproduce flakiness. Instead we just check that + // it was opened at some point. + tryCompare(openedSpy, "count", 1) // Let it timeout and begin the exit transition. tryCompare(control, "opened", false) @@ -256,7 +263,7 @@ TestCase { // Quickly open it again; it should still timeout eventually. control.open() - tryCompare(control, "opened", true) + tryCompare(openedSpy, "count", 2) tryCompare(control.exit, "running", true) } diff --git a/tests/auto/customization/data/styles/identified/AbstractButton.qml b/tests/auto/customization/data/styles/identified/AbstractButton.qml index b9656f7a..cd2b5bdc 100644 --- a/tests/auto/customization/data/styles/identified/AbstractButton.qml +++ b/tests/auto/customization/data/styles/identified/AbstractButton.qml @@ -58,15 +58,18 @@ T.AbstractButton { indicator: Item { id: indicator objectName: "abstractbutton-indicator-identified" + Accessible.name: objectName } contentItem: Item { id: contentItem objectName: "abstractbutton-contentItem-identified" + Accessible.name: objectName } background: Item { id: background objectName: "abstractbutton-background-identified" + Accessible.name: objectName } } diff --git a/tests/auto/customization/tst_customization.cpp b/tests/auto/customization/tst_customization.cpp index 41efc2a6..498a9e60 100644 --- a/tests/auto/customization/tst_customization.cpp +++ b/tests/auto/customization/tst_customization.cpp @@ -42,6 +42,7 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickwindow.h> #include <QtQuickControls2/qquickstyle.h> +#include <QtQuickTemplates2/private/qquickcontrol_p_p.h> #include "../shared/visualtestutil.h" using namespace QQuickVisualTestUtil; @@ -310,7 +311,7 @@ void tst_customization::creation() QVERIFY2(qt_createdQObjects()->removeOne(controlName), qPrintable(controlName + " was not created as expected")); for (QString delegate : qAsConst(delegates)) { - QStringList properties = delegate.split(".", QString::SkipEmptyParts); + QStringList properties = delegate.split(".", Qt::SkipEmptyParts); // <control>-<delegate>-<style>(-<override>) delegate.append("-" + style); @@ -411,7 +412,7 @@ void tst_customization::override() QVERIFY2(qt_createdQObjects()->removeOne(controlName), qPrintable(controlName + " was not created as expected")); for (QString delegate : qAsConst(delegates)) { - QStringList properties = delegate.split(".", QString::SkipEmptyParts); + QStringList properties = delegate.split(".", Qt::SkipEmptyParts); // <control>-<delegate>-<style>(-override) delegate.append("-" + style); @@ -439,11 +440,36 @@ void tst_customization::override() QVERIFY2(qt_createdQObjects()->isEmpty(), qPrintable("unexpectedly created: " + qt_createdQObjects->join(", "))); if (!nonDeferred.isEmpty()) { - for (QString delegate : qAsConst(delegates)) { - if (!delegate.contains("-")) - delegate.append("-" + nonDeferred); - delegate.prepend(type.toLower() + "-"); - QVERIFY2(qt_destroyedQObjects()->removeOne(delegate), qPrintable(delegate + " was not destroyed as expected")); + // There were items for which deferred execution was not possible. + for (QString delegateName : qAsConst(delegates)) { + if (!delegateName.contains("-")) + delegateName.append("-" + nonDeferred); + delegateName.prepend(type.toLower() + "-"); + + const int delegateIndex = qt_destroyedQObjects()->indexOf(delegateName); + QVERIFY2(delegateIndex == -1, qPrintable(delegateName + " was unexpectedly destroyed")); + + const auto controlChildren = control->children(); + const auto childIt = std::find_if(controlChildren.constBegin(), controlChildren.constEnd(), [delegateName](const QObject *child) { + return child->objectName() == delegateName; + }); + // We test other delegates (like the background) here, so make sure we don't end up with XPASSes by using the wrong delegate. + if (delegateName.contains(QLatin1String("handle"))) { + QEXPECT_FAIL("identified:RangeSlider", "For some reason, items that are belong to grouped properties fail here", Abort); + QEXPECT_FAIL("overidentified:RangeSlider", "For some reason, items that are belong to grouped properties fail here", Abort); + } + if (delegateName.contains(QLatin1String("indicator"))) { + QEXPECT_FAIL("identified:SpinBox", "For some reason, items that are belong to grouped properties fail here", Abort); + QEXPECT_FAIL("overidentified:SpinBox", "For some reason, items that are belong to grouped properties fail here", Abort); + } + QVERIFY2(childIt != controlChildren.constEnd(), qPrintable(QString::fromLatin1( + "Expected delegate \"%1\" to still be a QObject child of \"%2\"").arg(delegateName).arg(controlName))); + + const auto *delegate = qobject_cast<QQuickItem*>(*childIt); + // Ensure that the item is hidden, etc. + QVERIFY(delegate); + QCOMPARE(delegate->isVisible(), false); + QCOMPARE(delegate->parentItem(), nullptr); } } diff --git a/tests/auto/qquickheaderview/data/Window.qml b/tests/auto/qquickheaderview/data/Window.qml new file mode 100644 index 00000000..3811904e --- /dev/null +++ b/tests/auto/qquickheaderview/data/Window.qml @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import TestTableModel 0.1 +import TestTableModelWithHeader 0.1 +import HeaderDataProxyModel 0.1 + +Window { + objectName: "window" + width: 400 + height: 400 + visible: true + + Component { + id: cellDelegate + Rectangle { + implicitHeight: 25 + implicitWidth: 50 + color: "red" + Text { + text: row + "," + column + } + } + } + + HeaderDataProxyModel { + id: pm + objectName: "proxyModel" + } + + TestTableModel { + id: tm + objectName: "tableModel" + rowCount: 5 + columnCount: 10 + } + + TestTableModelWithHeader { + id: thm + objectName: "tableHeaderModel" + rowCount: 5 + columnCount: 10 + } + + HorizontalHeaderView { + id: hhv + objectName: "horizontalHeader" + width: 200 + height: 200 + model: thm + delegate: cellDelegate + } + + VerticalHeaderView { + id: vhv + objectName: "verticalHeader" + width: 200 + height: 200 + model: thm + delegate: cellDelegate + } + + TableView { + id: tv + objectName: "tableView" + width: 400 + height: 400 + model: thm + delegate:cellDelegate + } +} diff --git a/tests/auto/qquickheaderview/qquickheaderview.pro b/tests/auto/qquickheaderview/qquickheaderview.pro new file mode 100644 index 00000000..4410c888 --- /dev/null +++ b/tests/auto/qquickheaderview/qquickheaderview.pro @@ -0,0 +1,15 @@ +CONFIG += testcase +TARGET = tst_qquickheaderview +SOURCES += tst_qquickheaderview.cpp + +macos:CONFIG -= app_bundle + +QT += core-private gui-private qml-private quick-private testlib quickcontrols2 \ + quickcontrols2-private quicktemplates2-private quicktemplates2 + +include (../shared/util.pri) + +TESTDATA = data/* + +OTHER_FILES += \ + data/*.qml diff --git a/tests/auto/qquickheaderview/tst_qquickheaderview.cpp b/tests/auto/qquickheaderview/tst_qquickheaderview.cpp new file mode 100644 index 00000000..5ce5439d --- /dev/null +++ b/tests/auto/qquickheaderview/tst_qquickheaderview.cpp @@ -0,0 +1,354 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../shared/qtest_quickcontrols.h" +#include "../shared/util.h" +#include <QtTest/qsignalspy.h> +#include <QtTest/qtest.h> + +#include <QAbstractItemModelTester> +#include <QtQml/QQmlEngine> +#include <QtQuick/private/qquickwindow_p.h> +#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> +#include <QtQuickTemplates2/private/qquickheaderview_p.h> +#include <private/qquickheaderview_p_p.h> + +class TestTableModel : public QAbstractTableModel { + Q_OBJECT + Q_PROPERTY(int rowCount READ rowCount WRITE setRowCount NOTIFY rowCountChanged) + Q_PROPERTY(int columnCount READ columnCount WRITE setColumnCount NOTIFY columnCountChanged) + +public: + TestTableModel(QObject *parent = nullptr) + : QAbstractTableModel(parent) + { + } + + int rowCount(const QModelIndex & = QModelIndex()) const override + { + return m_rows; + } + virtual void setRowCount(int count) + { + beginResetModel(); + m_rows = count; + emit rowCountChanged(); + endResetModel(); + } + + int columnCount(const QModelIndex & = QModelIndex()) const override + { + return m_cols; + } + virtual void setColumnCount(int count) + { + beginResetModel(); + m_cols = count; + emit columnCountChanged(); + endResetModel(); + } + + int indexValue(const QModelIndex &index) const + { + return index.row() + (index.column() * rowCount()); + } + + Q_INVOKABLE QModelIndex toQModelIndex(int serialIndex) + { + return createIndex(serialIndex % rowCount(), serialIndex / rowCount()); + } + + Q_INVOKABLE QVariant data(int row, int col) + { + return data(createIndex(row, col), Qt::DisplayRole); + } + QVariant data(const QModelIndex &index, int role) const override + { + if (!index.isValid()) + return QVariant(); + + switch (role) { + case Qt::DisplayRole: + return QString("%1, %2, checked: %3 ") + .arg(index.row()) + .arg(index.column()) + .arg(m_checkedCells.contains(indexValue(index))); + case Qt::EditRole: + return m_checkedCells.contains(indexValue(index)); + default: + return QVariant(); + } + } + + bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::EditRole) override + { + + if (role != Qt::EditRole) + return false; + + int i = indexValue(index); + bool checked = value.toBool(); + if (checked == m_checkedCells.contains(i)) + return false; + + if (checked) + m_checkedCells.insert(i); + else + m_checkedCells.remove(i); + + emit dataChanged(index, index, { role }); + return true; + } + + Q_INVOKABLE QHash<int, QByteArray> roleNames() const override + { + return { + { Qt::DisplayRole, "display" }, + { Qt::EditRole, "edit" } + }; + } + +signals: + void rowCountChanged(); + void columnCountChanged(); + +private: + int m_rows = 0; + int m_cols = 0; + + QSet<int> m_checkedCells; +}; + +class TestTableModelWithHeader : public TestTableModel { + + Q_OBJECT +public: + void setRowCount(int count) override + { + vData.resize(count); + TestTableModel::setRowCount(count); + } + + void setColumnCount(int count) override + { + hData.resize(count); + TestTableModel::setColumnCount(count); + } + Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const override + { + auto sectionCount = orientation == Qt::Horizontal ? columnCount() : rowCount(); + if (section < 0 || section >= sectionCount) + return QVariant(); + switch (role) { + case Qt::DisplayRole: + case Qt::EditRole: { + auto &data = orientation == Qt::Horizontal ? hData : vData; + return data[section].toString(); + } + default: + return QVariant(); + } + } + Q_INVOKABLE bool setHeaderData(int section, Qt::Orientation orientation, + const QVariant &value, int role = Qt::EditRole) override + { + qDebug() << Q_FUNC_INFO + << "section:" << section + << "orient:" << orientation + << "value:" << value + << "role:" << QAbstractItemModel::roleNames()[role]; + auto sectionCount = orientation == Qt::Horizontal ? columnCount() : rowCount(); + if (section < 0 || section >= sectionCount) + return false; + auto &data = orientation == Qt::Horizontal ? hData : vData; + data[section] = value; + emit headerDataChanged(orientation, section, section); + return true; + } + +private: + QVector<QVariant> hData, vData; +}; + +class tst_QQuickHeaderView : public QQmlDataTest { + Q_OBJECT + +private slots: + void initTestCase() override; + void cleanupTestCase(); + void init(); + void cleanup(); + + void defaults(); + void testHeaderDataProxyModel(); + void testOrientation(); + void testModel(); + +private: + QQmlEngine *engine; + QString errorString; + + std::unique_ptr<QObject> rootObjectFromQml(const char *file) + { + auto component = new QQmlComponent(engine); + component->loadUrl(testFileUrl(file)); + auto root = component->create(); + if (!root) + errorString = component->errorString(); + return std::unique_ptr<QObject>(new QObject(root)); + } +}; + +void tst_QQuickHeaderView::initTestCase() +{ + QQmlDataTest::initTestCase(); + qmlRegisterType<TestTableModel>("TestTableModel", 0, 1, "TestTableModel"); + qmlRegisterType<TestTableModelWithHeader>("TestTableModelWithHeader", 0, 1, "TestTableModelWithHeader"); + qmlRegisterType<QHeaderDataProxyModel>("HeaderDataProxyModel", 0, 1, "HeaderDataProxyModel"); +} + +void tst_QQuickHeaderView::cleanupTestCase() +{ +} + +void tst_QQuickHeaderView::init() +{ + engine = new QQmlEngine(this); +} + +void tst_QQuickHeaderView::cleanup() +{ + if (engine) { + delete engine; + engine = nullptr; + } +} + +void tst_QQuickHeaderView::defaults() +{ + QQmlComponent component(engine); + component.loadUrl(testFileUrl("Window.qml")); + + QScopedPointer<QObject> root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + + auto hhv = root->findChild<QQuickHorizontalHeaderView *>("horizontalHeader"); + QVERIFY(hhv); + auto vhv = root->findChild<QQuickVerticalHeaderView *>("verticalHeader"); + QVERIFY(vhv); + auto tm = root->findChild<TestTableModel *>("tableModel"); + QVERIFY(tm); + auto pm = root->findChild<QHeaderDataProxyModel *>("proxyModel"); + QVERIFY(pm); + auto tv = root->findChild<QQuickTableView *>("tableView"); + QVERIFY(tv); +} + +void tst_QQuickHeaderView::testHeaderDataProxyModel() +{ + TestTableModel model; + model.setColumnCount(10); + model.setRowCount(7); + QHeaderDataProxyModel model2; + model2.setSourceModel(&model); + QAbstractItemModelTester tester(&model2, QAbstractItemModelTester::FailureReportingMode::QtTest); +} + +void tst_QQuickHeaderView::testOrientation() +{ + QQmlComponent component(engine); + component.loadUrl(testFileUrl("Window.qml")); + + QScopedPointer<QObject> root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + + auto hhv = root->findChild<QQuickHorizontalHeaderView *>("horizontalHeader"); + QVERIFY(hhv); + QCOMPARE(hhv->columns(), 10); + QCOMPARE(hhv->rows(), 1); + auto vhv = root->findChild<QQuickVerticalHeaderView *>("verticalHeader"); + QVERIFY(vhv); + + hhv->setSyncDirection(Qt::Vertical); + hhv->flick(10, 20); + + vhv->setSyncDirection(Qt::Horizontal); + vhv->flick(20, 10); + + QVERIFY(QTest::qWaitForWindowActive(qobject_cast<QWindow *>(root.data()))); + // Explicitly setting a different synDirection is ignored + QCOMPARE(hhv->syncDirection(), Qt::Horizontal); + QCOMPARE(hhv->flickableDirection(), QQuickFlickable::HorizontalFlick); + QCOMPARE(vhv->syncDirection(), Qt::Vertical); + QCOMPARE(vhv->flickableDirection(), QQuickFlickable::VerticalFlick); +} + +void tst_QQuickHeaderView::testModel() +{ + QQmlComponent component(engine); + component.loadUrl(testFileUrl("Window.qml")); + + QScopedPointer<QObject> root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + + auto hhv = root->findChild<QQuickHorizontalHeaderView *>("horizontalHeader"); + QVERIFY(hhv); + auto thm = root->findChild<TestTableModel *>("tableHeaderModel"); + QVERIFY(thm); + auto pm = root->findChild<QHeaderDataProxyModel *>("proxyModel"); + QVERIFY(pm); + + QSignalSpy modelChangedSpy(hhv, SIGNAL(modelChanged())); + QVERIFY(modelChangedSpy.isValid()); + + hhv->setModel(QVariant::fromValue(thm)); + QCOMPARE(modelChangedSpy.count(), 0); + + hhv->setModel(QVariant::fromValue(pm)); + QCOMPARE(modelChangedSpy.count(), 1); + + TestTableModel ttm2; + ttm2.setRowCount(100); + ttm2.setColumnCount(30); + hhv->setModel(QVariant::fromValue(&ttm2)); + QCOMPARE(modelChangedSpy.count(), 2); +} + +QTEST_MAIN(tst_QQuickHeaderView) + +#include "tst_qquickheaderview.moc" diff --git a/tests/auto/qquickmenu/data/scrollableWithPadding.qml b/tests/auto/qquickmenu/data/scrollableWithPadding.qml new file mode 100644 index 00000000..86405ccb --- /dev/null +++ b/tests/auto/qquickmenu/data/scrollableWithPadding.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Window 2.11 + +Window { + title: "Test Window" + width: 300 + height: dummyItem.height * 10 + + property alias menu: menu + MenuItem { + id: dummyItem + objectName: "Dummy" + text: objectName + } + + Menu { + id: menu + topPadding: 10 + Repeater { + model: 10 + + delegate: MenuItem { + objectName: text + text: (index + 1) + } + } + } +} diff --git a/tests/auto/qquickmenu/tst_qquickmenu.cpp b/tests/auto/qquickmenu/tst_qquickmenu.cpp index 2fe47477..22aece0c 100644 --- a/tests/auto/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/qquickmenu/tst_qquickmenu.cpp @@ -1588,6 +1588,7 @@ void tst_QQuickMenu::scrollable_data() QTest::addRow("Window") << QString::fromLatin1("windowScrollable.qml"); QTest::addRow("ApplicationWindow") << QString::fromLatin1("applicationWindowScrollable.qml"); + QTest::addRow("WithPadding") << QString::fromLatin1("scrollableWithPadding.qml"); } void tst_QQuickMenu::scrollable() diff --git a/tests/auto/qquickpopup/data/tabFence.qml b/tests/auto/qquickpopup/data/tabFence.qml new file mode 100644 index 00000000..2cf408e9 --- /dev/null +++ b/tests/auto/qquickpopup/data/tabFence.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 + +ApplicationWindow { + width: 400 + height: 400 + objectName: "Rectangle" + + property alias dialog: dialog + property alias outsideButton1: outsideButton1 + property alias outsideButton2: outsideButton2 + property alias dialogButton1: dialogButton1 + property alias dialogButton2: dialogButton2 + + ColumnLayout { + Button { + id: outsideButton1 + text: "Button1" + } + Button { + id: outsideButton2 + text: "Button2" + } + } + + Dialog { + id: dialog + objectName: "Dialog" + width: 200 + height: 200 + anchors.centerIn: parent + visible: true + + ColumnLayout { + Button { + id: dialogButton1 + text: "Button3" + } + Button { + id: dialogButton2 + text: "Button4" + } + } + } +} diff --git a/tests/auto/qquickpopup/tst_qquickpopup.cpp b/tests/auto/qquickpopup/tst_qquickpopup.cpp index f55d42bc..0b7d14bd 100644 --- a/tests/auto/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/qquickpopup/tst_qquickpopup.cpp @@ -93,6 +93,7 @@ private slots: void countChanged(); void toolTipCrashOnClose(); void setOverlayParentToNull(); + void tabFence(); void invisibleToolTipOpen(); }; @@ -794,7 +795,9 @@ void tst_QQuickPopup::wheel_data() static bool sendWheelEvent(QQuickItem *item, const QPoint &localPos, int degrees) { QQuickWindow *window = item->window(); - QWheelEvent wheelEvent(localPos, item->window()->mapToGlobal(localPos), QPoint(0, 0), QPoint(0, 8 * degrees), 0, Qt::Vertical, Qt::NoButton, 0); + QWheelEvent wheelEvent(localPos, item->window()->mapToGlobal(localPos), + QPoint(0, 0), QPoint(0, 8 * degrees), + 0, Qt::Vertical, Qt::NoButton, {}); QSpontaneKeyEvent::setSpontaneous(&wheelEvent); return qGuiApp->notify(window, &wheelEvent); } @@ -1300,6 +1303,62 @@ void tst_QQuickPopup::setOverlayParentToNull() // While nullifying the overlay parent doesn't make much sense, it shouldn't crash. } +void tst_QQuickPopup::tabFence() +{ + if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) + QSKIP("This platform only allows tab focus for text controls"); + + QQuickApplicationHelper helper(this, "tabFence.qml"); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickPopup *popup = window->property("dialog").value<QQuickPopup*>(); + QVERIFY(popup); + popup->open(); + popup->setModal(true); + + QQuickButton *outsideButton1 = window->property("outsideButton1").value<QQuickButton*>(); + QVERIFY(outsideButton1); + QQuickButton *outsideButton2 = window->property("outsideButton2").value<QQuickButton*>(); + QVERIFY(outsideButton2); + QQuickButton *dialogButton1 = window->property("dialogButton1").value<QQuickButton*>(); + QVERIFY(dialogButton1); + QQuickButton *dialogButton2 = window->property("dialogButton2").value<QQuickButton*>(); + QVERIFY(dialogButton2); + + // When modal, focus loops between the two external buttons + outsideButton1->forceActiveFocus(); + QVERIFY(outsideButton1->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(outsideButton2->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(outsideButton1->hasActiveFocus()); + + // Same thing for dialog's buttons + dialogButton1->forceActiveFocus(); + QVERIFY(dialogButton1->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(dialogButton2->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(dialogButton1->hasActiveFocus()); + + popup->setModal(false); + + // When not modal, focus goes in and out of the dialog + outsideButton1->forceActiveFocus(); + QVERIFY(outsideButton1->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(outsideButton2->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(dialogButton1->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(dialogButton2->hasActiveFocus()); + QTest::keyClick(window, Qt::Key_Tab); + QVERIFY(outsideButton1->hasActiveFocus()); +} + void tst_QQuickPopup::invisibleToolTipOpen() { QQuickApplicationHelper helper(this, "invisibleToolTipOpen.qml"); diff --git a/tests/auto/sanity/BLACKLIST b/tests/auto/sanity/BLACKLIST index 42ad3448..2a157b87 100644 --- a/tests/auto/sanity/BLACKLIST +++ b/tests/auto/sanity/BLACKLIST @@ -2,3 +2,23 @@ * [attachedObjects:material/SwitchDelegate.qml] * +[ids:controls/HorizontalHeaderView.qml] +* +[ids:controls/VerticalHeaderView.qml] +* +[ids:fusion/HorizontalHeaderView.qml] +* +[ids:fusion/VerticalHeaderView.qml] +* +[ids:imagine/HorizontalHeaderView.qml] +* +[ids:imagine/VerticalHeaderView.qml] +* +[ids:material/HorizontalHeaderView.qml] +* +[ids:material/VerticalHeaderView.qml] +* +[ids:universal/HorizontalHeaderView.qml] +* +[ids:universal/VerticalHeaderView.qml] +* diff --git a/tests/auto/sanity/tst_sanity.cpp b/tests/auto/sanity/tst_sanity.cpp index bfa1ecf1..1793ccfa 100644 --- a/tests/auto/sanity/tst_sanity.cpp +++ b/tests/auto/sanity/tst_sanity.cpp @@ -122,7 +122,7 @@ public: if (!parser.parse()) { const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &msg : diagnosticMessages) -#if Q_QML_PRIVATE_API_VERSION < 5 +#if Q_QML_PRIVATE_API_VERSION >= 8 m_errors += QString("%s:%d : %s").arg(m_fileName).arg(msg.loc.startLine).arg(msg.message); #else m_errors += QString("%s:%d : %s").arg(m_fileName).arg(msg.line).arg(msg.message); diff --git a/tests/auto/translation/data/comboBox.qml b/tests/auto/translation/data/comboBox.qml new file mode 100644 index 00000000..8bb8ed6f --- /dev/null +++ b/tests/auto/translation/data/comboBox.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.13 +import QtQuick.Controls 2.13 + +ComboBox { + objectName: "comboBox" + textRole: "label" + model: ListModel { + ListElement { + label: qsTr("Hello") + } + ListElement { + label: qsTr("ListView") + } + } +} diff --git a/tests/auto/translation/qml_jp.qm b/tests/auto/translation/qml_jp.qm Binary files differnew file mode 100644 index 00000000..a3712e99 --- /dev/null +++ b/tests/auto/translation/qml_jp.qm diff --git a/tests/auto/translation/qml_jp.ts b/tests/auto/translation/qml_jp.ts new file mode 100644 index 00000000..303c142f --- /dev/null +++ b/tests/auto/translation/qml_jp.ts @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ja_JP"> +<context> + <name>main</name> + <message> + <location filename="../main.qml" line="8"/> + <source>Hello World</source> + <translation>こんにちは世界</translation> + </message> + <message> + <location filename="../main.qml" line="12"/> + <source>Hello Text</source> + <translation>ハローテキスト</translation> + </message> + <message> + <location filename="../main.qml" line="35"/> + <source>Hello</source> + <translation>こんにちは</translation> + </message> + <message> + <location filename="../main.qml" line="38"/> + <source>ListView</source> + <translation>リストビュー</translation> + </message> +</context> +</TS> + diff --git a/tests/auto/translation/qtbase_fr.qm b/tests/auto/translation/qtbase_fr.qm Binary files differnew file mode 100644 index 00000000..176675a8 --- /dev/null +++ b/tests/auto/translation/qtbase_fr.qm diff --git a/tests/auto/translation/qtbase_fr.ts b/tests/auto/translation/qtbase_fr.ts index a2a05a07..7aff8bd7 100644 --- a/tests/auto/translation/qtbase_fr.ts +++ b/tests/auto/translation/qtbase_fr.ts @@ -20,3 +20,4 @@ </message> </context> </TS> + diff --git a/tests/auto/translation/translation.pro b/tests/auto/translation/translation.pro index d2d9d6ee..a33cf56a 100644 --- a/tests/auto/translation/translation.pro +++ b/tests/auto/translation/translation.pro @@ -13,7 +13,4 @@ TESTDATA = data/* OTHER_FILES += \ data/*.qml -# We only want to run lrelease, which is why we use EXTRA_TRANSLATIONS. -EXTRA_TRANSLATIONS = qtbase_fr.ts -# Embed the translations in a qrc file. -CONFIG += lrelease embed_translations +RESOURCES += qml_jp.qm qtbase_fr.qm diff --git a/tests/auto/translation/tst_translation.cpp b/tests/auto/translation/tst_translation.cpp index 992c30a2..ffb39f96 100644 --- a/tests/auto/translation/tst_translation.cpp +++ b/tests/auto/translation/tst_translation.cpp @@ -42,8 +42,10 @@ #include <QtGui/qpa/qplatformtheme.h> #include <QtQuick/qquickview.h> #include <QtQuickTemplates2/private/qquickabstractbutton_p.h> +#include <QtQuickTemplates2/private/qquickcombobox_p.h> #include <QtQuickTemplates2/private/qquickdialog_p.h> #include <QtQuickTemplates2/private/qquickdialogbuttonbox_p.h> +#include <QtQuickTemplates2/private/qquicktextfield_p.h> using namespace QQuickVisualTestUtil; @@ -54,6 +56,7 @@ class tst_translation : public QQmlDataTest private slots: void dialogButtonBox(); void dialogButtonBoxWithCustomButtons(); + void comboBox(); }; void tst_translation::dialogButtonBox() @@ -83,7 +86,7 @@ void tst_translation::dialogButtonBox() QCOMPARE(discardButton->text(), defaultDiscardText); QTranslator translator; - QVERIFY(translator.load(":/i18n/qtbase_fr.qm")); + QVERIFY(translator.load("qtbase_fr.qm", ":/")); QVERIFY(qApp->installTranslator(&translator)); view.engine()->retranslate(); @@ -104,7 +107,7 @@ void tst_translation::dialogButtonBoxWithCustomButtons() // after the QML has been loaded. QScopedPointer<QTranslator> translator(new QTranslator); // Doesn't matter which language it is, as we won't be using it anyway. - QVERIFY(translator->load(":/i18n/qtbase_fr.qm")); + QVERIFY(translator->load("qtbase_fr.qm", ":/")); QVERIFY(qApp->installTranslator(translator.data())); QQuickView view(testFileUrl("dialogButtonBoxWithCustomButtons.qml")); @@ -135,6 +138,26 @@ void tst_translation::dialogButtonBoxWithCustomButtons() QCOMPARE(cancelButton->text(), QLatin1String("Cancel")); } +void tst_translation::comboBox() +{ + QQuickView view(testFileUrl("comboBox.qml")); + + QQuickComboBox *comboBox = qobject_cast<QQuickComboBox*>(view.rootObject()); + QVERIFY(comboBox); + QCOMPARE(comboBox->displayText(), QLatin1String("Hello")); + + QQuickTextField *contentItem = qobject_cast<QQuickTextField*>(comboBox->contentItem()); + QVERIFY(contentItem); + QCOMPARE(contentItem->text(), QLatin1String("Hello")); + + QTranslator translator; + QVERIFY(translator.load("qml_jp.qm", ":/")); + QVERIFY(qApp->installTranslator(&translator)); + view.engine()->retranslate(); + QTRY_COMPARE(comboBox->displayText(), QString::fromUtf8("こんにちは")); + QCOMPARE(contentItem->text(), QString::fromUtf8("こんにちは")); +} + QTEST_MAIN(tst_translation) #include "tst_translation.moc" |