diff options
-rw-r--r-- | dist/changes-5.14.1 | 29 | ||||
-rw-r--r-- | src/imports/controls/controls.pro | 2 | ||||
-rw-r--r-- | src/imports/controls/designer/qtquickcontrols2.metainfo | 4 | ||||
-rw-r--r-- | src/imports/controls/doc/snippets/qtquickcontrols2-rangeslider-custom.qml | 8 | ||||
-rw-r--r-- | src/quickcontrols2/qquickstyle.cpp | 9 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol.cpp | 12 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol_p_p.h | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdialogbuttonbox.cpp | 7 | ||||
-rw-r--r-- | src/quicktemplates2/qquicktooltip.cpp | 5 | ||||
-rw-r--r-- | tests/auto/qquickcontrol/data/flickable.qml | 71 | ||||
-rw-r--r-- | tests/auto/qquickcontrol/qquickcontrol.pro | 14 | ||||
-rw-r--r-- | tests/auto/qquickcontrol/tst_qquickcontrol.cpp | 110 | ||||
-rw-r--r-- | tests/auto/qquickmenu/BLACKLIST | 2 | ||||
-rw-r--r-- | tests/auto/qquickpopup/data/invisibleToolTipOpen.qml | 28 | ||||
-rw-r--r-- | tests/auto/qquickpopup/tst_qquickpopup.cpp | 28 | ||||
-rw-r--r-- | tests/auto/translation/data/dialogButtonBoxWithCustomButtons.qml | 75 | ||||
-rw-r--r-- | tests/auto/translation/tst_translation.cpp | 40 |
17 files changed, 434 insertions, 12 deletions
diff --git a/dist/changes-5.14.1 b/dist/changes-5.14.1 new file mode 100644 index 00000000..e12ea637 --- /dev/null +++ b/dist/changes-5.14.1 @@ -0,0 +1,29 @@ +Qt 5.14.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Controls * +**************************************************************************** + + - StackView: + * [QTBUG-80353] fixed crash when recursively removing items. + * [QTBUG-57267] fix an issue where the current item became hidden. + + - SplitView: + * [QTBUG-79846] fixed hoverable child items breaking handle hover state. diff --git a/src/imports/controls/controls.pro b/src/imports/controls/controls.pro index 2aeaf9ab..66373d55 100644 --- a/src/imports/controls/controls.pro +++ b/src/imports/controls/controls.pro @@ -19,7 +19,7 @@ SOURCES += \ RESOURCES += \ $$PWD/qtquickcontrols2plugin.qrc -!static: qtConfig(quick-designer): include(designer/designer.pri) +qtConfig(quick-designer): include(designer/designer.pri) include(doc/doc.pri) CONFIG += no_cxx_module install_qml_files builtin_resources qtquickcompiler diff --git a/src/imports/controls/designer/qtquickcontrols2.metainfo b/src/imports/controls/designer/qtquickcontrols2.metainfo index 9e6030b1..d27f1b90 100644 --- a/src/imports/controls/designer/qtquickcontrols2.metainfo +++ b/src/imports/controls/designer/qtquickcontrols2.metainfo @@ -443,7 +443,7 @@ MetaInfo { version: "2.0" requiredImport: "QtQuick.Controls" - Property { name: "text"; type: "binding"; value: "qsTr(\"Text Area\")" } + Property { name: "placeholderText"; type: "binding"; value: "qsTr(\"Text Area\")" } } } @@ -458,7 +458,7 @@ MetaInfo { version: "2.0" requiredImport: "QtQuick.Controls" - Property { name: "text"; type: "binding"; value: "qsTr(\"Text Field\")" } + Property { name: "placeholderText"; type: "binding"; value: "qsTr(\"Text Field\")" } } } diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-rangeslider-custom.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-rangeslider-custom.qml index 1c5db214..b8510ddd 100644 --- a/src/imports/controls/doc/snippets/qtquickcontrols2-rangeslider-custom.qml +++ b/src/imports/controls/doc/snippets/qtquickcontrols2-rangeslider-custom.qml @@ -54,22 +54,22 @@ RangeSlider { } first.handle: Rectangle { - x: control.leftPadding + first.visualPosition * (control.availableWidth - width) + x: control.leftPadding + control.first.visualPosition * (control.availableWidth - width) y: control.topPadding + control.availableHeight / 2 - height / 2 implicitWidth: 26 implicitHeight: 26 radius: 13 - color: first.pressed ? "#f0f0f0" : "#f6f6f6" + color: control.first.pressed ? "#f0f0f0" : "#f6f6f6" border.color: "#bdbebf" } second.handle: Rectangle { - x: control.leftPadding + second.visualPosition * (control.availableWidth - width) + x: control.leftPadding + control.second.visualPosition * (control.availableWidth - width) y: control.topPadding + control.availableHeight / 2 - height / 2 implicitWidth: 26 implicitHeight: 26 radius: 13 - color: second.pressed ? "#f0f0f0" : "#f6f6f6" + color: control.second.pressed ? "#f0f0f0" : "#f6f6f6" border.color: "#bdbebf" } } diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 7a3359ef..61632b11 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -128,6 +128,7 @@ static QStringList defaultImportPathList() importPaths += QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); # endif #endif + importPaths += envPathList("QML2_IMPORT_PATH"); importPaths += QStringLiteral(":/qt-project.org/imports"); importPaths += QCoreApplication::applicationDirPath(); return importPaths; @@ -384,7 +385,13 @@ void QQuickStylePrivate::init(const QUrl &baseUrl) spec->resolve(baseUrl); if (!spec->fallbackStyle.isEmpty()) { - QString fallbackStyle = spec->findStyle(QQmlFile::urlToLocalFileOrQrc(baseUrl), spec->fallbackStyle); + QString fallbackStyle; + const QStringList stylePaths = QQuickStylePrivate::stylePaths(); + for (const QString &path : stylePaths) { + fallbackStyle = spec->findStyle(path, spec->fallbackStyle); + if (!fallbackStyle.isEmpty()) + break; + } if (fallbackStyle.isEmpty()) { if (spec->fallbackStyle.compare(QStringLiteral("Default")) != 0) { qWarning() << "ERROR: unable to locate fallback style" << spec->fallbackStyle; diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 6b845ae6..4eb411c2 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -180,6 +180,12 @@ bool QQuickControlPrivate::acceptTouch(const QTouchEvent::TouchPoint &point) return true; } + // If the control is on a Flickable that has a pressDelay, then the press is never + // sent as a touch event, therefore we need to check for this case. + if (touchId == -1 && pressWasTouch && point.state() == Qt::TouchPointReleased && + point.pos() == previousPressPos) { + return true; + } return false; } #endif @@ -215,6 +221,8 @@ void QQuickControlPrivate::handleRelease(const QPointF &) if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && QGuiApplication::styleHints()->setFocusOnTouchRelease()) setActiveFocus(q, Qt::MouseFocusReason); touchId = -1; + pressWasTouch = false; + previousPressPos = QPointF(); } void QQuickControlPrivate::handleUngrab() @@ -2121,6 +2129,10 @@ void QQuickControl::mousePressEvent(QMouseEvent *event) { Q_D(QQuickControl); d->handlePress(event->localPos()); + if (event->source() == Qt::MouseEventSynthesizedByQt) { + d->pressWasTouch = true; + d->previousPressPos = event->localPos(); + } event->accept(); } diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index b649db0a..fa06c97f 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -230,7 +230,9 @@ public: bool explicitHoverEnabled = false; #endif bool resizingBackground = false; + bool pressWasTouch = false; int touchId = -1; + QPointF previousPressPos; qreal padding = 0; qreal horizontalPadding = 0; qreal verticalPadding = 0; diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp index 2c09cd11..f3dd2da1 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox.cpp +++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp @@ -455,8 +455,11 @@ void QQuickDialogButtonBoxPrivate::updateLanguage() qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, true)); const auto boxAttachedPrivate = QQuickDialogButtonBoxAttachedPrivate::get(attached); const QPlatformDialogHelper::StandardButton standardButton = boxAttachedPrivate->standardButton; - const QString buttonText = QGuiApplicationPrivate::platformTheme()->standardButtonText(standardButton); - button->setText(QPlatformTheme::removeMnemonics(buttonText)); + // The button might be a custom one with explicitly specified text, so we shouldn't change it in that case. + if (standardButton != QPlatformDialogHelper::NoButton) { + const QString buttonText = QGuiApplicationPrivate::platformTheme()->standardButtonText(standardButton); + button->setText(QPlatformTheme::removeMnemonics(buttonText)); + } } --i; } diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp index 9ea0160e..9d733c94 100644 --- a/src/quicktemplates2/qquicktooltip.cpp +++ b/src/quicktemplates2/qquicktooltip.cpp @@ -557,8 +557,9 @@ void QQuickToolTipAttached::hide() QQuickToolTip *tip = d->instance(false); if (!tip) return; - - tip->close(); + // check the parent item to prevent unexpectedly closing tooltip by new created invisible tooltip + if (parent() == tip->parentItem()) + tip->close(); } QT_END_NAMESPACE diff --git a/tests/auto/qquickcontrol/data/flickable.qml b/tests/auto/qquickcontrol/data/flickable.qml new file mode 100644 index 00000000..f3a1c381 --- /dev/null +++ b/tests/auto/qquickcontrol/data/flickable.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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.14 +import QtQuick.Controls 2.14 + +ApplicationWindow { + width: 400 + height: 400 + + property alias flickable: flickable + property alias button: button + + Flickable { + id: flickable + width: 300 + height: 400 + pressDelay: 50 + Button { + id: button + text: "This is a test button" + } + } +} diff --git a/tests/auto/qquickcontrol/qquickcontrol.pro b/tests/auto/qquickcontrol/qquickcontrol.pro new file mode 100644 index 00000000..8641343d --- /dev/null +++ b/tests/auto/qquickcontrol/qquickcontrol.pro @@ -0,0 +1,14 @@ +CONFIG += testcase +TARGET = tst_qquickcontrol +SOURCES += tst_qquickcontrol.cpp + +macos:CONFIG -= app_bundle + +QT += core-private gui-private qml-private quick-private testlib quicktemplates2-private + +include (../shared/util.pri) + +TESTDATA = data/* + +OTHER_FILES += \ + data/*.qml diff --git a/tests/auto/qquickcontrol/tst_qquickcontrol.cpp b/tests/auto/qquickcontrol/tst_qquickcontrol.cpp new file mode 100644 index 00000000..c8d34756 --- /dev/null +++ b/tests/auto/qquickcontrol/tst_qquickcontrol.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** 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 <QtTest/qtest.h> +#include <QtTest/qsignalspy.h> +#include "../shared/util.h" +#include "../shared/visualtestutil.h" +#include "../shared/qtest_quickcontrols.h" +#include <QtGui/qpa/qwindowsysteminterface.h> +#include <QtQuickTemplates2/private/qquickbutton_p.h> + +using namespace QQuickVisualTestUtil; + +class tst_QQuickControl : public QQmlDataTest +{ + Q_OBJECT + +private slots: + void initTestCase(); + void flickable(); + +private: + struct TouchDeviceDeleter + { + static inline void cleanup(QTouchDevice *device) + { + QWindowSystemInterface::unregisterTouchDevice(device); + delete device; + } + }; + + QScopedPointer<QTouchDevice, TouchDeviceDeleter> touchDevice; +}; + + +void tst_QQuickControl::initTestCase() +{ + QQmlDataTest::initTestCase(); + qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + + touchDevice.reset(new QTouchDevice); + touchDevice->setType(QTouchDevice::TouchScreen); + QWindowSystemInterface::registerTouchDevice(touchDevice.data()); +} + +void tst_QQuickControl::flickable() +{ + // Check that when a Button that is inside a Flickable with a pressDelay + // still gets the released and clicked signals sent due to the fact that + // Flickable sends a mouse event for the delay and not a touch event + QQuickApplicationHelper helper(this, QStringLiteral("flickable.qml")); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickButton *button = window->property("button").value<QQuickButton *>(); + QVERIFY(button); + + QSignalSpy buttonPressedSpy(button, SIGNAL(pressed())); + QVERIFY(buttonPressedSpy.isValid()); + + QSignalSpy buttonReleasedSpy(button, SIGNAL(released())); + QVERIFY(buttonReleasedSpy.isValid()); + + QSignalSpy buttonClickedSpy(button, SIGNAL(clicked())); + QVERIFY(buttonClickedSpy.isValid()); + + QTest::touchEvent(window, touchDevice.data()).press(0, QPoint(button->width() / 2, button->height() / 2)); + QTRY_COMPARE(buttonPressedSpy.count(), 1); + QTest::touchEvent(window, touchDevice.data()).release(0, QPoint(button->width() / 2, button->height() / 2)); + QTRY_COMPARE(buttonReleasedSpy.count(), 1); + QTRY_COMPARE(buttonClickedSpy.count(), 1); +} + +QTEST_QUICKCONTROLS_MAIN(tst_QQuickControl) + +#include "tst_qquickcontrol.moc" diff --git a/tests/auto/qquickmenu/BLACKLIST b/tests/auto/qquickmenu/BLACKLIST new file mode 100644 index 00000000..71d96dfd --- /dev/null +++ b/tests/auto/qquickmenu/BLACKLIST @@ -0,0 +1,2 @@ +[popup] +macos # Can't control cursor (QTBUG-76312) diff --git a/tests/auto/qquickpopup/data/invisibleToolTipOpen.qml b/tests/auto/qquickpopup/data/invisibleToolTipOpen.qml new file mode 100644 index 00000000..2e58bb97 --- /dev/null +++ b/tests/auto/qquickpopup/data/invisibleToolTipOpen.qml @@ -0,0 +1,28 @@ +import QtQuick 2.13 +import QtQuick.Window 2.13 +import QtQuick.Controls 2.13 + +Window { + width: 400 + height: 400 + property alias mouseArea: mouseArea + property alias loader: loader + MouseArea { + id: mouseArea + property bool isToolTipVisible: false + width: 200 + height: 200 + hoverEnabled: true + ToolTip.text: "static tooltip" + ToolTip.visible: containsMouse + ToolTip.onVisibleChanged: isToolTipVisible = ToolTip.visible + } + Loader { + id: loader + active: false + sourceComponent: Rectangle { + ToolTip.text: "dynamic tooltip" + ToolTip.visible: false + } + } +} diff --git a/tests/auto/qquickpopup/tst_qquickpopup.cpp b/tests/auto/qquickpopup/tst_qquickpopup.cpp index a3683d6c..0b7d14bd 100644 --- a/tests/auto/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/qquickpopup/tst_qquickpopup.cpp @@ -94,6 +94,7 @@ private slots: void toolTipCrashOnClose(); void setOverlayParentToNull(); void tabFence(); + void invisibleToolTipOpen(); }; void tst_QQuickPopup::initTestCase() @@ -1358,6 +1359,33 @@ void tst_QQuickPopup::tabFence() QVERIFY(outsideButton1->hasActiveFocus()); } +void tst_QQuickPopup::invisibleToolTipOpen() +{ + QQuickApplicationHelper helper(this, "invisibleToolTipOpen.qml"); + + QQuickWindow *window = helper.window; + centerOnScreen(window); + moveMouseAway(window); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickItem *mouseArea = qvariant_cast<QQuickItem *>(window->property("mouseArea")); + QVERIFY(mouseArea); + QObject *loader = qvariant_cast<QObject *>(window->property("loader")); + QVERIFY(loader); + + QTest::mouseMove(window, QPoint(mouseArea->width() / 2, mouseArea->height() / 2)); + QTRY_VERIFY(mouseArea->property("isToolTipVisible").toBool()); + + QSignalSpy componentLoadedSpy(loader, SIGNAL(loaded())); + QVERIFY(componentLoadedSpy.isValid()); + + loader->setProperty("active", true); + QTRY_COMPARE(componentLoadedSpy.count(), 1); + + QTRY_VERIFY(mouseArea->property("isToolTipVisible").toBool()); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup) #include "tst_qquickpopup.moc" diff --git a/tests/auto/translation/data/dialogButtonBoxWithCustomButtons.qml b/tests/auto/translation/data/dialogButtonBoxWithCustomButtons.qml new file mode 100644 index 00000000..6f046cf1 --- /dev/null +++ b/tests/auto/translation/data/dialogButtonBoxWithCustomButtons.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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.14 +import QtQuick.Controls 2.14 + +Item { + property Dialog dialog: Dialog { + width: 300 + height: 300 + visible: true + + footer: DialogButtonBox { + Button { + objectName: "okButton" + text: qsTr("OK") + + DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole + } + Button { + objectName: "cancelButton" + text: qsTr("Cancel") + + DialogButtonBox.buttonRole: DialogButtonBox.RejectRole + } + } + } +} diff --git a/tests/auto/translation/tst_translation.cpp b/tests/auto/translation/tst_translation.cpp index 9cbca915..992c30a2 100644 --- a/tests/auto/translation/tst_translation.cpp +++ b/tests/auto/translation/tst_translation.cpp @@ -53,6 +53,7 @@ class tst_translation : public QQmlDataTest private slots: void dialogButtonBox(); + void dialogButtonBoxWithCustomButtons(); }; void tst_translation::dialogButtonBox() @@ -95,6 +96,45 @@ void tst_translation::dialogButtonBox() QCOMPARE(discardButton->text(), translatedDiscardText); } +// Test that custom buttons with explicitly specified text +// do not have that text overwritten on language changes. +void tst_translation::dialogButtonBoxWithCustomButtons() +{ + // This is just a way of simulating the translator going out of scope + // 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(qApp->installTranslator(translator.data())); + + QQuickView view(testFileUrl("dialogButtonBoxWithCustomButtons.qml")); + if (view.status() != QQuickView::Ready) + QFAIL("Failed to load QML file"); + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickDialog *dialog = view.rootObject()->property("dialog").value<QQuickDialog*>(); + QVERIFY(dialog); + + QQuickDialogButtonBox *dialogButtonBox = qobject_cast<QQuickDialogButtonBox*>(dialog->footer()); + QVERIFY(dialogButtonBox); + + auto okButton = dialogButtonBox->findChild<QQuickAbstractButton*>("okButton"); + QVERIFY(okButton); + QCOMPARE(okButton->text(), QLatin1String("OK")); + + QQuickAbstractButton *cancelButton = dialogButtonBox->findChild<QQuickAbstractButton*>("cancelButton"); + QVERIFY(cancelButton); + QCOMPARE(cancelButton->text(), QLatin1String("Cancel")); + + // Delete the translator and hence cause a LanguageChange event, + // but _without_ calling QQmlEngine::retranslate(), which would + // restore the original bindings and hence not reproduce the issue. + translator.reset(); + QCOMPARE(okButton->text(), QLatin1String("OK")); + QCOMPARE(cancelButton->text(), QLatin1String("Cancel")); +} + QTEST_MAIN(tst_translation) #include "tst_translation.moc" |