From f4d5939ad613fda69aa750139ef929fac18b97ae Mon Sep 17 00:00:00 2001 From: Wang Chuan Date: Fri, 13 Dec 2019 21:50:03 +0800 Subject: QQuickToolTip: prevent closing after invisible tooltip created Since all items using ToolTip attached property share the same ToolTip item, a dynamically created invisible Tooltip may unexpectedly close the current visible ToolTip. Fix this issue by checking the parent of ToolTip when trying to close it Fixes: QTBUG-78202 Change-Id: I0f6558040c6b8bf22240b0c94af912a43d525ed9 Reviewed-by: Richard Moe Gustavsen --- src/quicktemplates2/qquicktooltip.cpp | 5 ++-- .../auto/qquickpopup/data/invisibleToolTipOpen.qml | 28 ++++++++++++++++++++++ tests/auto/qquickpopup/tst_qquickpopup.cpp | 28 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/auto/qquickpopup/data/invisibleToolTipOpen.qml 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/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 e852a61e..f55d42bc 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 invisibleToolTipOpen(); }; void tst_QQuickPopup::initTestCase() @@ -1299,6 +1300,33 @@ void tst_QQuickPopup::setOverlayParentToNull() // While nullifying the overlay parent doesn't make much sense, it shouldn't crash. } +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(window->property("mouseArea")); + QVERIFY(mouseArea); + QObject *loader = qvariant_cast(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" -- cgit v1.2.3 From 7be5d463e25218a2987d6c1735fd81bc226b29b6 Mon Sep 17 00:00:00 2001 From: Antti Kokko Date: Thu, 9 Jan 2020 10:28:05 +0200 Subject: Add changes file for Qt 5.14.1 + 8ee511bcd9f1376e9995ab3f30f6415ad60b7c05 Doc: Fix qdoc warnings + 463898f0765b83f6c391f6802a0ee06796f9f6d2 Respect user-set Accessible.name + 75b6ef710cddbf9395df35650438f0feb57ec076 SplitView: fix hoverable child items breaking handle hover state + aaec25a798352fc222f86ab3b299384575f51dc8 StackView: fix crash when recursively removing items + cb1c3528078659c297fb12ea6914978cec1d2614 ComboBox: change currentIndex (if applicable) when focus is lost + 06162b3712b6ff2e25e1b20a139fe5c42e95b123 StackView: fix an issue where the current item was hidden + bcdd38074be6828db41396bd3c0ec601993ed59b clang-tidy: fix cppcoreguidelines-pro-type-member-init + c23697e40881491ea218898bec08fb33dd7f5331 clang-tidy: fix readability-const-return-type + 0592dc1a4b4a16faeb1b622f10d56e77dba15776 Bump version + 090eab86b05478572485b3086c087a846fbae7fd Add binary compatibility file for qtquickcontrols2 Change-Id: Iab397951aac43f5581cbf27a09daf8233f28b2f4 Reviewed-by: Richard Moe Gustavsen --- dist/changes-5.14.1 | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 dist/changes-5.14.1 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. -- cgit v1.2.3 From a2443f0a34da85de014b9507926c4ac415543b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 23 Jan 2020 13:48:04 +0100 Subject: Blacklist tst_QQuickMenu::popup on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It relies on moving the cursor. Task-number: QTBUG-76312 Change-Id: I317083b974d3e9e8d6d616dc3248ee64e0f36021 Reviewed-by: Morten Johan Sørvig --- tests/auto/qquickmenu/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/auto/qquickmenu/BLACKLIST 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) -- cgit v1.2.3 From 28610e13e453c33d7118834a0effb7ac87427ffe Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 16 Jan 2020 10:22:39 +0100 Subject: Look for the fallback style in all of the style paths Fixes: QTBUG-81216 Change-Id: I9d3efeec7f9ec2beda24ff74e39d04104f5eb967 Reviewed-by: BogDan Vatra Reviewed-by: Richard Moe Gustavsen --- src/quickcontrols2/qquickstyle.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 7a3359ef..707e4730 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -384,7 +384,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; -- cgit v1.2.3 From 20b9437d54b16abfdd7528868dea2a6c6de0c349 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 10 Jan 2020 14:10:30 +0100 Subject: set placeholderText by default, not text Task-number: QDS-456 Change-Id: I05b7ce9efab851b99d12ba272a79bf9ba4443398 Reviewed-by: Thomas Hartmann Reviewed-by: Mitch Curtis --- src/imports/controls/designer/qtquickcontrols2.metainfo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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\")" } } } -- cgit v1.2.3 From c5c945006244b6bf5189f1949a009f70ebd51d7a Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 27 Jan 2020 10:58:50 +0100 Subject: Doc: fix RangeSlider errors When the RangeSlider was copied into another file as a child item, it would produce errors about first and second being undefined. Change-Id: I0ecc9f6830509183a1b2b35e3faed5f06e78a0ef Fixes: QTBUG-80970 Reviewed-by: Shawn Rutledge --- .../controls/doc/snippets/qtquickcontrols2-rangeslider-custom.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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" } } -- cgit v1.2.3 From 33474ce5f16f418a8f132ba88b8cbd5b5d1edcca Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Tue, 28 Jan 2020 15:11:55 +0000 Subject: Follow QML2_IMPORT_PATH in path search When searching for styles we include QLibraryInfo::Qml2ImportsPath so it makes sense to continue that to also include the runtime QML2_IMPORT_PATH when searching for QQC2 themes. It used to be included, but in 5.14 this behavior changed as a result of 7db4df2deca52a30b4c068abd4683a1720cf281e, so this line is restored. Change-Id: I185b29b323d870fc724e655104eaf42034707738 Reviewed-by: Andy Shaw Reviewed-by: Mitch Curtis --- src/quickcontrols2/qquickstyle.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 707e4730..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; -- cgit v1.2.3 From 1ee1fd16f09e72cbf3460904a1cf6314aa594927 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Sun, 2 Feb 2020 13:42:42 +0100 Subject: Bump version Change-Id: I9edcbf13f4fdd1f268dd71fa2b0c216c88483509 --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 32d4d650..7db332a6 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST QQC2_SOURCE_TREE = $$PWD -MODULE_VERSION = 5.14.1 +MODULE_VERSION = 5.14.2 -- cgit v1.2.3 From 91eb563b278ca9c831c444380030c458adbf02f0 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 31 Jan 2020 09:52:16 +0100 Subject: Copy Qt Quick Designer-related files also for static builds Make sure that the 'designer' directory is copied to the build directory, or installed, also for static builds. This reverts the !static condition introduced to fix a build breakage in 01d076d0e81e5 . Anyhow, I couldn't reproduce the original problem (QTBUG-51708), nor is it clear why it was caused by the static build. Fixes: QTBUG-75682 Change-Id: I47af3907e464d4fd9e9965ac28545b7350f450ee Reviewed-by: Qt CI Bot Reviewed-by: Andy Shaw --- src/imports/controls/controls.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 -- cgit v1.2.3 From b10912ba731144e8c41cbfa35fb1553ad04b2b88 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 3 Feb 2020 12:20:08 +0100 Subject: DialogButtonBox: don't change button text that has been explicitly set If a custom button is declared in a DialogButtonBox, qsTr() will take care of translation, and so we shouldn't touch it. Amends c18c7bd7f9596e5ad3d13876a91203e1ceba2544. Change-Id: I06221002cf850882f5318cf0a3ed86da35274d0c Fixes: QTBUG-81796 Reviewed-by: Andy Shaw --- src/quicktemplates2/qquickdialogbuttonbox.cpp | 7 +- .../data/dialogButtonBoxWithCustomButtons.qml | 75 ++++++++++++++++++++++ tests/auto/translation/tst_translation.cpp | 40 ++++++++++++ 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 tests/auto/translation/data/dialogButtonBoxWithCustomButtons.qml diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp index 33b720ed..d448aeed 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox.cpp +++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp @@ -455,8 +455,11 @@ void QQuickDialogButtonBoxPrivate::updateLanguage() qmlAttachedPropertiesObject(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/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 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(); + QVERIFY(dialog); + + QQuickDialogButtonBox *dialogButtonBox = qobject_cast(dialog->footer()); + QVERIFY(dialogButtonBox); + + auto okButton = dialogButtonBox->findChild("okButton"); + QVERIFY(okButton); + QCOMPARE(okButton->text(), QLatin1String("OK")); + + QQuickAbstractButton *cancelButton = dialogButtonBox->findChild("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" -- cgit v1.2.3 From 025f938c1b4676782674d54375e1e4e560e4b6cd Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 7 Feb 2020 11:33:50 +0100 Subject: Account for when a touch event is synthesized by Qt as a mouse event When a control is on a Flickable with a pressDelay then any press events sent from a touch device will be replayed as mouse events due to the delay. As a result we cannot depend on the fact that we got the first press as a touch event when checking if the id matches before accepting it. So we need to keep the previous pos when it is a synthesized mouse event so we can ensure the release is also accepted. Fixes: QTBUG-77202 Change-Id: I6f5d8506bd803daf834093e8fd412504150c4ca6 Reviewed-by: Shawn Rutledge Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickcontrol.cpp | 12 +++ src/quicktemplates2/qquickcontrol_p_p.h | 2 + tests/auto/qquickcontrol/data/flickable.qml | 71 ++++++++++++++++ tests/auto/qquickcontrol/qquickcontrol.pro | 14 ++++ tests/auto/qquickcontrol/tst_qquickcontrol.cpp | 110 +++++++++++++++++++++++++ 5 files changed, 209 insertions(+) create mode 100644 tests/auto/qquickcontrol/data/flickable.qml create mode 100644 tests/auto/qquickcontrol/qquickcontrol.pro create mode 100644 tests/auto/qquickcontrol/tst_qquickcontrol.cpp diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 7e249dae..838a841d 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -178,6 +178,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 @@ -213,6 +219,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() @@ -2103,6 +2111,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 a657307b..1b59f86d 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -224,7 +224,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/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 +#include +#include "../shared/util.h" +#include "../shared/visualtestutil.h" +#include "../shared/qtest_quickcontrols.h" +#include +#include + +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 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(); + 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" -- cgit v1.2.3 From 0b607bfe14048e32dd81855e1497dda3465b5183 Mon Sep 17 00:00:00 2001 From: Yulong Bai Date: Thu, 11 Apr 2019 17:30:49 +0200 Subject: Add HorizontalHeaderView and VerticalHeaderView [ChangeLog][Controls] Add HorizontalHeaderView and VerticalHeaderView. They are controls associated with TableView. Support flicking synchronization Support default, fusion, imagine, material and universal delegate styles. Fixes: QTPM-1300 Change-Id: Ie3f913dd616cda0d4e5a22a3d95baf71692370fe Reviewed-by: Volker Hilsheimer --- src/imports/controls/HorizontalHeaderView.qml | 59 ++++ src/imports/controls/VerticalHeaderView.qml | 59 ++++ src/imports/controls/controls.pri | 4 +- .../controls/fusion/HorizontalHeaderView.qml | 59 ++++ src/imports/controls/fusion/VerticalHeaderView.qml | 59 ++++ src/imports/controls/fusion/fusion.pri | 4 +- .../controls/imagine/HorizontalHeaderView.qml | 59 ++++ .../controls/imagine/VerticalHeaderView.qml | 59 ++++ src/imports/controls/imagine/imagine.pri | 4 +- .../controls/material/HorizontalHeaderView.qml | 60 ++++ .../controls/material/VerticalHeaderView.qml | 60 ++++ src/imports/controls/material/material.pri | 4 +- src/imports/controls/qtquickcontrols2plugin.cpp | 4 + .../controls/universal/HorizontalHeaderView.qml | 61 ++++ .../controls/universal/VerticalHeaderView.qml | 61 ++++ src/imports/controls/universal/universal.pri | 4 +- src/imports/templates/qtquicktemplates2plugin.cpp | 5 + src/quicktemplates2/qquickheaderview.cpp | 373 +++++++++++++++++++++ src/quicktemplates2/qquickheaderview_p.h | 125 +++++++ src/quicktemplates2/qquickheaderview_p_p.h | 136 ++++++++ src/quicktemplates2/quicktemplates2.pri | 3 + tests/auto/auto.pro | 1 + tests/auto/qquickheaderview/data/Window.qml | 121 +++++++ tests/auto/qquickheaderview/qquickheaderview.pro | 15 + .../auto/qquickheaderview/tst_qquickheaderview.cpp | 354 +++++++++++++++++++ tests/manual/headerview/headerview.pro | 10 + tests/manual/headerview/main.cpp | 218 ++++++++++++ tests/manual/headerview/main.qml | 130 +++++++ tests/manual/manual.pro | 1 + 29 files changed, 2107 insertions(+), 5 deletions(-) create mode 100644 src/imports/controls/HorizontalHeaderView.qml create mode 100644 src/imports/controls/VerticalHeaderView.qml create mode 100644 src/imports/controls/fusion/HorizontalHeaderView.qml create mode 100644 src/imports/controls/fusion/VerticalHeaderView.qml create mode 100644 src/imports/controls/imagine/HorizontalHeaderView.qml create mode 100644 src/imports/controls/imagine/VerticalHeaderView.qml create mode 100644 src/imports/controls/material/HorizontalHeaderView.qml create mode 100644 src/imports/controls/material/VerticalHeaderView.qml create mode 100644 src/imports/controls/universal/HorizontalHeaderView.qml create mode 100644 src/imports/controls/universal/VerticalHeaderView.qml create mode 100644 src/quicktemplates2/qquickheaderview.cpp create mode 100644 src/quicktemplates2/qquickheaderview_p.h create mode 100644 src/quicktemplates2/qquickheaderview_p_p.h create mode 100644 tests/auto/qquickheaderview/data/Window.qml create mode 100644 tests/auto/qquickheaderview/qquickheaderview.pro create mode 100644 tests/auto/qquickheaderview/tst_qquickheaderview.cpp create mode 100644 tests/manual/headerview/headerview.pro create mode 100644 tests/manual/headerview/main.cpp create mode 100644 tests/manual/headerview/main.qml diff --git a/src/imports/controls/HorizontalHeaderView.qml b/src/imports/controls/HorizontalHeaderView.qml new file mode 100644 index 00000000..946d3a75 --- /dev/null +++ b/src/imports/controls/HorizontalHeaderView.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T + +T.HorizontalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: "#f6f6f6" + border.color: "#e4e4e4" + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "#ff26282a" + } + } +} diff --git a/src/imports/controls/VerticalHeaderView.qml b/src/imports/controls/VerticalHeaderView.qml new file mode 100644 index 00000000..67d4c1ce --- /dev/null +++ b/src/imports/controls/VerticalHeaderView.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T + +T.VerticalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: "#f6f6f6" + border.color: "#e4e4e4" + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "#ff26282a" + } + } +} diff --git a/src/imports/controls/controls.pri b/src/imports/controls/controls.pri index fbf5d075..03fc0f4b 100644 --- a/src/imports/controls/controls.pri +++ b/src/imports/controls/controls.pri @@ -32,6 +32,7 @@ QML_FILES += \ $$PWD/Drawer.qml \ $$PWD/Frame.qml \ $$PWD/GroupBox.qml \ + $$PWD/HorizontalHeaderView.qml \ $$PWD/ItemDelegate.qml \ $$PWD/Label.qml \ $$PWD/Menu.qml \ @@ -67,4 +68,5 @@ QML_FILES += \ $$PWD/ToolButton.qml \ $$PWD/ToolSeparator.qml \ $$PWD/ToolTip.qml \ - $$PWD/Tumbler.qml + $$PWD/Tumbler.qml \ + $$PWD/VerticalHeaderView.qml diff --git a/src/imports/controls/fusion/HorizontalHeaderView.qml b/src/imports/controls/fusion/HorizontalHeaderView.qml new file mode 100644 index 00000000..946d3a75 --- /dev/null +++ b/src/imports/controls/fusion/HorizontalHeaderView.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T + +T.HorizontalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: "#f6f6f6" + border.color: "#e4e4e4" + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "#ff26282a" + } + } +} diff --git a/src/imports/controls/fusion/VerticalHeaderView.qml b/src/imports/controls/fusion/VerticalHeaderView.qml new file mode 100644 index 00000000..67d4c1ce --- /dev/null +++ b/src/imports/controls/fusion/VerticalHeaderView.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T + +T.VerticalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: "#f6f6f6" + border.color: "#e4e4e4" + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "#ff26282a" + } + } +} diff --git a/src/imports/controls/fusion/fusion.pri b/src/imports/controls/fusion/fusion.pri index 72978db5..bdc413fd 100644 --- a/src/imports/controls/fusion/fusion.pri +++ b/src/imports/controls/fusion/fusion.pri @@ -28,6 +28,7 @@ QML_FILES += \ $$PWD/Drawer.qml \ $$PWD/Frame.qml \ $$PWD/GroupBox.qml \ + $$PWD/HorizontalHeaderView.qml \ $$PWD/ItemDelegate.qml \ $$PWD/Label.qml \ $$PWD/Menu.qml \ @@ -64,4 +65,5 @@ QML_FILES += \ $$PWD/ToolButton.qml \ $$PWD/ToolSeparator.qml \ $$PWD/ToolTip.qml \ - $$PWD/Tumbler.qml + $$PWD/Tumbler.qml \ + $$PWD/VerticalHeaderView.qml diff --git a/src/imports/controls/imagine/HorizontalHeaderView.qml b/src/imports/controls/imagine/HorizontalHeaderView.qml new file mode 100644 index 00000000..946d3a75 --- /dev/null +++ b/src/imports/controls/imagine/HorizontalHeaderView.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T + +T.HorizontalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: "#f6f6f6" + border.color: "#e4e4e4" + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "#ff26282a" + } + } +} diff --git a/src/imports/controls/imagine/VerticalHeaderView.qml b/src/imports/controls/imagine/VerticalHeaderView.qml new file mode 100644 index 00000000..67d4c1ce --- /dev/null +++ b/src/imports/controls/imagine/VerticalHeaderView.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T + +T.VerticalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: "#f6f6f6" + border.color: "#e4e4e4" + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "#ff26282a" + } + } +} diff --git a/src/imports/controls/imagine/imagine.pri b/src/imports/controls/imagine/imagine.pri index 081a509e..4c6bcf1b 100644 --- a/src/imports/controls/imagine/imagine.pri +++ b/src/imports/controls/imagine/imagine.pri @@ -12,6 +12,7 @@ QML_FILES += \ $$PWD/Drawer.qml \ $$PWD/Frame.qml \ $$PWD/GroupBox.qml \ + $$PWD/HorizontalHeaderView.qml \ $$PWD/ItemDelegate.qml \ $$PWD/Label.qml \ $$PWD/Menu.qml \ @@ -44,7 +45,8 @@ QML_FILES += \ $$PWD/ToolButton.qml \ $$PWD/ToolSeparator.qml \ $$PWD/ToolTip.qml \ - $$PWD/Tumbler.qml + $$PWD/Tumbler.qml \ + $$PWD/VerticalHeaderView.qml HEADERS += \ $$PWD/qquickimageselector_p.h \ diff --git a/src/imports/controls/material/HorizontalHeaderView.qml b/src/imports/controls/material/HorizontalHeaderView.qml new file mode 100644 index 00000000..a1228cdc --- /dev/null +++ b/src/imports/controls/material/HorizontalHeaderView.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T +import QtQuick.Controls.Material 2.15 +import QtQuick.Controls.Material.impl 2.15 + +T.HorizontalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: control.Material.backgroundColor + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: enabled ? control.Material.foreground : control.Material.hintTextColor + } + } +} diff --git a/src/imports/controls/material/VerticalHeaderView.qml b/src/imports/controls/material/VerticalHeaderView.qml new file mode 100644 index 00000000..8acda3d7 --- /dev/null +++ b/src/imports/controls/material/VerticalHeaderView.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T +import QtQuick.Controls.Material 2.15 +import QtQuick.Controls.Material.impl 2.15 + +T.VerticalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: control.Material.backgroundColor + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: enabled ? control.Material.foreground : control.Material.hintTextColor + } + } +} diff --git a/src/imports/controls/material/material.pri b/src/imports/controls/material/material.pri index bda1fb21..457a8df1 100644 --- a/src/imports/controls/material/material.pri +++ b/src/imports/controls/material/material.pri @@ -30,6 +30,7 @@ QML_FILES += \ $$PWD/ElevationEffect.qml \ $$PWD/Frame.qml \ $$PWD/GroupBox.qml \ + $$PWD/HorizontalHeaderView.qml \ $$PWD/ItemDelegate.qml \ $$PWD/Label.qml \ $$PWD/Menu.qml \ @@ -68,4 +69,5 @@ QML_FILES += \ $$PWD/ToolButton.qml \ $$PWD/ToolSeparator.qml \ $$PWD/ToolTip.qml \ - $$PWD/Tumbler.qml + $$PWD/Tumbler.qml \ + $$PWD/VerticalHeaderView.qml diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp index 260e7297..9fe82ba2 100644 --- a/src/imports/controls/qtquickcontrols2plugin.cpp +++ b/src/imports/controls/qtquickcontrols2plugin.cpp @@ -198,6 +198,10 @@ void QtQuickControls2Plugin::registerTypes(const char *uri) qmlRegisterUncreatableType(uri, 2, 13, "SplitHandle", QStringLiteral("SplitHandle is only available as an attached property.")); + // QtQuick.Controls 2.15 (new types in Qt 5.15) + qmlRegisterType(resolvedUrl(QStringLiteral("HorizontalHeaderView.qml")), uri, 2, 15, "HorizontalHeaderView"); + qmlRegisterType(resolvedUrl(QStringLiteral("VerticalHeaderView.qml")), uri, 2, 15, "VerticalHeaderView"); + // Register the latest version, even if there are no new types or new revisions for existing types yet. // Before Qt 5.12, we would do the following: // diff --git a/src/imports/controls/universal/HorizontalHeaderView.qml b/src/imports/controls/universal/HorizontalHeaderView.qml new file mode 100644 index 00000000..6f48560e --- /dev/null +++ b/src/imports/controls/universal/HorizontalHeaderView.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.impl 2.15 +import QtQuick.Templates 2.15 as T +import QtQuick.Controls.Universal 2.15 +import QtQuick.Controls.Universal.impl 2.15 + +T.HorizontalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: control.Universal.background + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) + } + } +} diff --git a/src/imports/controls/universal/VerticalHeaderView.qml b/src/imports/controls/universal/VerticalHeaderView.qml new file mode 100644 index 00000000..80133dbd --- /dev/null +++ b/src/imports/controls/universal/VerticalHeaderView.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 module 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$ +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.impl 2.15 +import QtQuick.Templates 2.15 as T +import QtQuick.Controls.Universal 2.15 +import QtQuick.Controls.Universal.impl 2.15 + +T.VerticalHeaderView { + id: control + + delegate: Rectangle { + implicitWidth: 50 + implicitHeight: 25 + color: control.Universal.background + + Text { + text: model[control.textRole] + width: parent.width + height: parent.height + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) + } + } +} diff --git a/src/imports/controls/universal/universal.pri b/src/imports/controls/universal/universal.pri index 4440acbf..8f1b905c 100644 --- a/src/imports/controls/universal/universal.pri +++ b/src/imports/controls/universal/universal.pri @@ -13,6 +13,7 @@ QML_FILES += \ $$PWD/Drawer.qml \ $$PWD/Frame.qml \ $$PWD/GroupBox.qml \ + $$PWD/HorizontalHeaderView.qml \ $$PWD/ItemDelegate.qml \ $$PWD/Label.qml \ $$PWD/Menu.qml \ @@ -48,7 +49,8 @@ QML_FILES += \ $$PWD/ToolButton.qml \ $$PWD/ToolSeparator.qml \ $$PWD/ToolTip.qml \ - $$PWD/Tumbler.qml + $$PWD/Tumbler.qml \ + $$PWD/VerticalHeaderView.qml HEADERS += \ $$PWD/qquickuniversalbusyindicator_p.h \ diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp index 9645e4ce..3b085c56 100644 --- a/src/imports/templates/qtquicktemplates2plugin.cpp +++ b/src/imports/templates/qtquicktemplates2plugin.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -361,6 +362,10 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) // QtQuick.Templates 2.15 (new types and revisions in Qt 5.15) qmlRegisterType(uri, 2, 15, "ComboBox"); + // Register QQuickTableView here to expose headerView's base, with a irregular type name to 'hide' it. + qmlRegisterType(uri, 2, 15, "__TableView__"); + qmlRegisterType(uri, 2, 15, "HorizontalHeaderView"); + qmlRegisterType(uri, 2, 15, "VerticalHeaderView"); } QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickheaderview.cpp b/src/quicktemplates2/qquickheaderview.cpp new file mode 100644 index 00000000..b6569881 --- /dev/null +++ b/src/quicktemplates2/qquickheaderview.cpp @@ -0,0 +1,373 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +QT_BEGIN_NAMESPACE + +QQuickHeaderViewBasePrivate::QQuickHeaderViewBasePrivate() + : QQuickTableViewPrivate() +{ +} + +QQuickHeaderViewBasePrivate::~QQuickHeaderViewBasePrivate() +{ +} + +const QPointer QQuickHeaderViewBasePrivate::delegateItemAt(int row, int col) const +{ + return loadedTableItem(QPoint(col, row))->item; +} + +QVariant QQuickHeaderViewBasePrivate::modelImpl() const +{ + if (auto model = m_headerDataProxyModel.sourceModel()) + return QVariant::fromValue(model.data()); + if (auto model = m_transposeProxyModel.sourceModel()) + return QVariant::fromValue(model); + return QQuickTableViewPrivate::modelImpl(); +} + +template +inline bool proxyModelSetter(QQuickHeaderViewBase *const q, P &proxyModel, M *model) +{ + if (model) { + if (model == proxyModel.sourceModel()) + return true; + proxyModel.setSourceModel(model); + const auto &modelVariant = QVariant::fromValue(std::addressof(proxyModel)); + bool isProxyModelChanged = (modelVariant != QQuickTableViewPrivate::get(q)->QQuickTableViewPrivate::modelImpl()); + QQuickTableViewPrivate::get(q)->QQuickTableViewPrivate::setModelImpl(modelVariant); + //Necessary, since TableView's assigned model not changed, but proxy's source changed + if (!isProxyModelChanged) + emit q->modelChanged(); + return true; + } + proxyModel.setSourceModel(nullptr); + return false; +} + +void QQuickHeaderViewBasePrivate::setModelImpl(const QVariant &newModel) +{ + Q_Q(QQuickHeaderViewBase); + m_modelExplicitlySetByUser = true; + // Case 1: newModel is QAbstractTableModel + if (proxyModelSetter(q, m_headerDataProxyModel, newModel.value())) + return; + // Case 2: newModel is QAbstractItemModel but not QAbstractTableModel + if (orientation() == Qt::Horizontal + && proxyModelSetter(q, m_transposeProxyModel, newModel.value())) + return; + + QQuickTableViewPrivate::setModelImpl(newModel); +} + +void QQuickHeaderViewBasePrivate::syncModel() +{ + Q_Q(QQuickHeaderViewBase); + if (assignedSyncView && !m_modelExplicitlySetByUser) { + auto newModel = assignedSyncView->model(); + if (auto m = newModel.value()) { + proxyModelSetter(q, m_headerDataProxyModel, m); + } else if (orientation() == Qt::Horizontal) { + if (auto m = newModel.value()) + proxyModelSetter(q, m_transposeProxyModel, m); + } else { + QQuickTableViewPrivate::setModelImpl(newModel); + } + } + + QQuickTableViewPrivate::syncModel(); +} + +void QQuickHeaderViewBasePrivate::syncSyncView() +{ + Q_Q(QQuickHeaderViewBase); + if (assignedSyncDirection != orientation()) { + qmlWarning(q_func()) << "Setting syncDirection other than Qt::" + << QVariant::fromValue(orientation()).toString() + << " is invalid."; + assignedSyncDirection = orientation(); + } + if (assignedSyncView) { + QBoolBlocker fixupGuard(inUpdateContentSize, true); + if (orientation() == Qt::Horizontal) { + q->setLeftMargin(assignedSyncView->leftMargin()); + q->setRightMargin(assignedSyncView->rightMargin()); + } else { + q->setTopMargin(assignedSyncView->topMargin()); + q->setBottomMargin(assignedSyncView->bottomMargin()); + } + } + QQuickTableViewPrivate::syncSyncView(); +} + +QQuickHeaderViewBase::QQuickHeaderViewBase(Qt::Orientation orient, QQuickItem *parent) + : QQuickTableView(*(new QQuickHeaderViewBasePrivate), parent) +{ + d_func()->setOrientation(orient); + setSyncDirection(orient); +} + +QQuickHeaderViewBase::QQuickHeaderViewBase(QQuickHeaderViewBasePrivate &dd, QQuickItem *parent) + : QQuickTableView(dd, parent) +{ +} + +QQuickHeaderViewBase::~QQuickHeaderViewBase() +{ +} + +QString QQuickHeaderViewBase::textRole() const +{ + Q_D(const QQuickHeaderViewBase); + return d->m_textRole; +} + +void QQuickHeaderViewBase::setTextRole(const QString &role) +{ + Q_D(QQuickHeaderViewBase); + if (d->m_textRole == role) + return; + + d->m_textRole = role; + emit textRoleChanged(); +} + +Qt::Orientation QQuickHeaderViewBasePrivate::orientation() const +{ + return m_headerDataProxyModel.orientation(); +} + +void QQuickHeaderViewBasePrivate::setOrientation(Qt::Orientation orientation) +{ + if (QQuickHeaderViewBasePrivate::orientation() == orientation) + return; + m_headerDataProxyModel.setOrientation(orientation); +} + +QQuickVerticalHeaderView::QQuickVerticalHeaderView(QQuickVerticalHeaderViewPrivate &dd, QQuickItem *parent) + : QQuickHeaderViewBase(dd, parent) +{ +} + +/*! \internal + \class QHeaderDataProxyModel + \brief + QHeaderDataProxyModel is a proxy AbstractItemModel type that maps + source model's headerData() to correspondent data() + */ +QHeaderDataProxyModel::QHeaderDataProxyModel(QObject *parent) + : QAbstractItemModel(parent) +{ +} + +QHeaderDataProxyModel::~QHeaderDataProxyModel() = default; + +void QHeaderDataProxyModel::setSourceModel(QAbstractItemModel *newSourceModel) +{ + if (m_model == newSourceModel) + return; + beginResetModel(); + disconnectFromModel(); + m_model = newSourceModel; + connectToModel(); + endResetModel(); +} + +QModelIndex QHeaderDataProxyModel::index(int row, int column, const QModelIndex &parent) const +{ + return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex(); +} + +QModelIndex QHeaderDataProxyModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child) + return QModelIndex(); +} + +QModelIndex QHeaderDataProxyModel::sibling(int row, int column, const QModelIndex &idx) const +{ + return index(row, column, idx); +} + +int QHeaderDataProxyModel::rowCount(const QModelIndex &parent) const +{ + return m_model.isNull() ? -1 : (m_orientation == Qt::Horizontal ? 1 : m_model->rowCount(parent)); +} + +int QHeaderDataProxyModel::columnCount(const QModelIndex &parent) const +{ + return m_model.isNull() ? -1 : (m_orientation == Qt::Vertical ? 1 : m_model->columnCount(parent)); +} + +QVariant QHeaderDataProxyModel::data(const QModelIndex &index, int role) const +{ + if (m_model.isNull()) + return QVariant(); + if (!hasIndex(index.row(), index.column())) + return QModelIndex(); + auto section = m_orientation == Qt::Vertical ? index.row() : index.column(); + return m_model->headerData(section, m_orientation, role); +} + +bool QHeaderDataProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!hasIndex(index.row(), index.column())) + return false; + auto section = m_orientation == Qt::Vertical ? index.row() : index.column(); + auto ret = m_model->setHeaderData(section, m_orientation, value, role); + emit dataChanged(index, index, { role }); + return ret; +} + +bool QHeaderDataProxyModel::hasChildren(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return false; +} + +QVariant QHeaderDataProxyModel::variantValue() const +{ + return QVariant::fromValue(static_cast(const_cast(this))); +} + +void QHeaderDataProxyModel::setOrientation(Qt::Orientation o) +{ + if (o == m_orientation) + return; + beginResetModel(); + m_orientation = o; + endResetModel(); +} + +Qt::Orientation QHeaderDataProxyModel::orientation() const +{ + return m_orientation; +} + +QPointer QHeaderDataProxyModel::sourceModel() const +{ + return m_model; +} + +void QHeaderDataProxyModel::connectToModel() +{ + if (m_model.isNull()) + return; + connect(m_model, &QAbstractItemModel::headerDataChanged, + [this](Qt::Orientation orient, int first, int last) { + if (orient != orientation()) + return; + if (orient == Qt::Horizontal) { + emit dataChanged(createIndex(0, first), createIndex(0, last)); + } else { + emit dataChanged(createIndex(first, 0), createIndex(last, 0)); + } + }); + connect(m_model, &QAbstractItemModel::modelAboutToBeReset, + this, &QHeaderDataProxyModel::modelAboutToBeReset, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::modelReset, + this, &QHeaderDataProxyModel::modelReset, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsAboutToBeMoved, + this, &QHeaderDataProxyModel::rowsAboutToBeMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsMoved, + this, &QHeaderDataProxyModel::rowsMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsAboutToBeInserted, + this, &QHeaderDataProxyModel::rowsAboutToBeInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsInserted, + this, &QHeaderDataProxyModel::rowsInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &QHeaderDataProxyModel::rowsAboutToBeRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsRemoved, + this, &QHeaderDataProxyModel::rowsRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsAboutToBeMoved, + this, &QHeaderDataProxyModel::columnsAboutToBeMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsMoved, + this, &QHeaderDataProxyModel::columnsMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsAboutToBeInserted, + this, &QHeaderDataProxyModel::columnsAboutToBeInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsInserted, + this, &QHeaderDataProxyModel::columnsInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsAboutToBeRemoved, + this, &QHeaderDataProxyModel::columnsAboutToBeRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsRemoved, + this, &QHeaderDataProxyModel::columnsRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::layoutAboutToBeChanged, + this, &QHeaderDataProxyModel::layoutAboutToBeChanged, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::layoutChanged, + this, &QHeaderDataProxyModel::layoutChanged, Qt::UniqueConnection); +} + +void QHeaderDataProxyModel::disconnectFromModel() +{ + if (m_model.isNull()) + return; + m_model->disconnect(this); +} + +QQuickHorizontalHeaderView::QQuickHorizontalHeaderView(QQuickItem *parent) + : QQuickHeaderViewBase(Qt::Horizontal, parent) +{ + setFlickableDirection(FlickableDirection::HorizontalFlick); +} + +QQuickHorizontalHeaderView::~QQuickHorizontalHeaderView() +{ +} + +QQuickVerticalHeaderView::QQuickVerticalHeaderView(QQuickItem *parent) + : QQuickHeaderViewBase(Qt::Vertical, parent) +{ + setFlickableDirection(FlickableDirection::VerticalFlick); +} + +QQuickVerticalHeaderView::~QQuickVerticalHeaderView() +{ +} + +QQuickHorizontalHeaderViewPrivate::QQuickHorizontalHeaderViewPrivate() = default; + +QQuickHorizontalHeaderViewPrivate::~QQuickHorizontalHeaderViewPrivate() = default; + +QQuickVerticalHeaderViewPrivate::QQuickVerticalHeaderViewPrivate() = default; + +QQuickVerticalHeaderViewPrivate::~QQuickVerticalHeaderViewPrivate() = default; + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickheaderview_p.h b/src/quicktemplates2/qquickheaderview_p.h new file mode 100644 index 00000000..10c55c6e --- /dev/null +++ b/src/quicktemplates2/qquickheaderview_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKHEADERVIEW_P_H +#define QQUICKHEADERVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QQuickHeaderViewBase; +class QQuickHeaderViewBasePrivate; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickHeaderViewBase : public QQuickTableView +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickHeaderViewBase) + Q_PROPERTY(QString textRole READ textRole WRITE setTextRole NOTIFY textRoleChanged FINAL) + +public: + explicit QQuickHeaderViewBase(Qt::Orientation orient, QQuickItem *parent = nullptr); + ~QQuickHeaderViewBase(); + + QString textRole() const; + void setTextRole(const QString &role); + +protected: + QQuickHeaderViewBase(QQuickHeaderViewBasePrivate &dd, QQuickItem *parent); + +Q_SIGNALS: + void textRoleChanged(); + +private: + Q_DISABLE_COPY(QQuickHeaderViewBase) + friend class QQuickHorizontalHeaderView; + friend class QQuickVerticalHeaderView; +}; + +class QQuickHorizontalHeaderViewPrivate; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickHorizontalHeaderView : public QQuickHeaderViewBase +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickHorizontalHeaderView) + +public: + QQuickHorizontalHeaderView(QQuickItem *parent = nullptr); + ~QQuickHorizontalHeaderView() override; + +protected: + QQuickHorizontalHeaderView(QQuickHorizontalHeaderViewPrivate &dd, QQuickItem *parent); + +private: + Q_DISABLE_COPY(QQuickHorizontalHeaderView) +}; + +class QQuickVerticalHeaderViewPrivate; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickVerticalHeaderView : public QQuickHeaderViewBase +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickVerticalHeaderView) + +public: + QQuickVerticalHeaderView(QQuickItem *parent = nullptr); + ~QQuickVerticalHeaderView() override; + +protected: + QQuickVerticalHeaderView(QQuickVerticalHeaderViewPrivate &dd, QQuickItem *parent); + +private: + Q_DISABLE_COPY(QQuickVerticalHeaderView) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickHorizontalHeaderView) +QML_DECLARE_TYPE(QQuickVerticalHeaderView) + +#endif // QQUICKHEADERVIEW_P_H diff --git a/src/quicktemplates2/qquickheaderview_p_p.h b/src/quicktemplates2/qquickheaderview_p_p.h new file mode 100644 index 00000000..961c554b --- /dev/null +++ b/src/quicktemplates2/qquickheaderview_p_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module 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$ +** +****************************************************************************/ + +#ifndef QQUICKHEADERVIEW_P_P_H +#define QQUICKHEADERVIEW_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QHeaderDataProxyModel : public QAbstractItemModel +{ + Q_OBJECT + Q_DISABLE_COPY(QHeaderDataProxyModel) + Q_PROPERTY(QAbstractItemModel *sourceModel READ sourceModel) +public: + explicit QHeaderDataProxyModel(QObject *parent = nullptr); + ~QHeaderDataProxyModel(); + + void setSourceModel(QAbstractItemModel *newSourceModel); + QPointer sourceModel() const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &child) const override; + QModelIndex sibling(int row, int column, const QModelIndex &idx) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; + + inline QVariant variantValue() const; + inline Qt::Orientation orientation() const; + inline void setOrientation(Qt::Orientation o); + +private: + inline void connectToModel(); + inline void disconnectFromModel(); + QPointer m_model = nullptr; + Qt::Orientation m_orientation = Qt::Horizontal; +}; + +class QQuickHeaderViewBasePrivate : public QQuickTableViewPrivate +{ + Q_DECLARE_PUBLIC(QQuickHeaderViewBase) +public: + QQuickHeaderViewBasePrivate(); + ~QQuickHeaderViewBasePrivate(); + + Qt::Orientation orientation() const; + void setOrientation(Qt::Orientation orientation); + const QPointer delegateItemAt(int row, int col) const; + QVariant modelImpl() const override; + void setModelImpl(const QVariant &newModel) override; + void syncModel() override; + void syncSyncView() override; + +protected: + QHeaderDataProxyModel m_headerDataProxyModel; + QTransposeProxyModel m_transposeProxyModel; + struct SectionSize + { + int section; + qreal previousSize; + }; + QStack m_hiddenSectionSizes; + bool m_modelExplicitlySetByUser = false; + QString m_textRole = QStringLiteral("display"); +}; + +class QQuickHorizontalHeaderViewPrivate : public QQuickHeaderViewBasePrivate +{ + Q_DECLARE_PUBLIC(QQuickHorizontalHeaderView) +public: + QQuickHorizontalHeaderViewPrivate(); + ~QQuickHorizontalHeaderViewPrivate(); +}; + +class QQuickVerticalHeaderViewPrivate : public QQuickHeaderViewBasePrivate +{ + Q_DECLARE_PUBLIC(QQuickVerticalHeaderView) +public: + QQuickVerticalHeaderViewPrivate(); + ~QQuickVerticalHeaderViewPrivate(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKHEADERVIEW_P_P_H diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index c145c20f..fa6929f9 100644 --- a/src/quicktemplates2/quicktemplates2.pri +++ b/src/quicktemplates2/quicktemplates2.pri @@ -31,6 +31,8 @@ HEADERS += \ $$PWD/qquickframe_p.h \ $$PWD/qquickframe_p_p.h \ $$PWD/qquickgroupbox_p.h \ + $$PWD/qquickheaderview_p.h \ + $$PWD/qquickheaderview_p_p.h \ $$PWD/qquickicon_p.h \ $$PWD/qquickitemdelegate_p.h \ $$PWD/qquickitemdelegate_p_p.h \ @@ -120,6 +122,7 @@ SOURCES += \ $$PWD/qquickdrawer.cpp \ $$PWD/qquickframe.cpp \ $$PWD/qquickgroupbox.cpp \ + $$PWD/qquickheaderview.cpp \ $$PWD/qquickicon.cpp \ $$PWD/qquickitemdelegate.cpp \ $$PWD/qquicklabel.cpp \ diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 8612e2c1..853c84a8 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -14,6 +14,7 @@ SUBDIRS += \ qquickapplicationwindow \ qquickcolor \ qquickdrawer \ + qquickheaderview \ qquickiconimage \ qquickiconlabel \ qquickimaginestyle \ 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 +#include + +#include +#include +#include +#include +#include +#include + +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 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 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 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 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(new QObject(root)); + } +}; + +void tst_QQuickHeaderView::initTestCase() +{ + QQmlDataTest::initTestCase(); + qmlRegisterType("TestTableModel", 0, 1, "TestTableModel"); + qmlRegisterType("TestTableModelWithHeader", 0, 1, "TestTableModelWithHeader"); + qmlRegisterType("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 root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + + auto hhv = root->findChild("horizontalHeader"); + QVERIFY(hhv); + auto vhv = root->findChild("verticalHeader"); + QVERIFY(vhv); + auto tm = root->findChild("tableModel"); + QVERIFY(tm); + auto pm = root->findChild("proxyModel"); + QVERIFY(pm); + auto tv = root->findChild("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 root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + + auto hhv = root->findChild("horizontalHeader"); + QVERIFY(hhv); + QCOMPARE(hhv->columns(), 10); + QCOMPARE(hhv->rows(), 1); + auto vhv = root->findChild("verticalHeader"); + QVERIFY(vhv); + + hhv->setSyncDirection(Qt::Vertical); + hhv->flick(10, 20); + + vhv->setSyncDirection(Qt::Horizontal); + vhv->flick(20, 10); + + QVERIFY(QTest::qWaitForWindowActive(qobject_cast(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 root(component.create()); + QVERIFY2(root, qPrintable(component.errorString())); + + auto hhv = root->findChild("horizontalHeader"); + QVERIFY(hhv); + auto thm = root->findChild("tableHeaderModel"); + QVERIFY(thm); + auto pm = root->findChild("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/manual/headerview/headerview.pro b/tests/manual/headerview/headerview.pro new file mode 100644 index 00000000..474cc921 --- /dev/null +++ b/tests/manual/headerview/headerview.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = headerview +QT += qml quick quick-private quickcontrols2 quickcontrols2-private \ + quicktemplates2-private quicktemplates2 +SOURCES += main.cpp +RESOURCES += main.qml +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/tests/manual/headerview/main.cpp b/tests/manual/headerview/main.cpp new file mode 100644 index 00000000..4c1e611c --- /dev/null +++ b/tests/manual/headerview/main.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +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 QLatin1String("Foo"); + 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 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 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 + { + const bool isHorizontal = orientation == Qt::Horizontal; + auto sectionCount = isHorizontal ? columnCount() : rowCount(); + if (section < 0 || section >= sectionCount) + return QVariant(); + switch (role) { + case Qt::DisplayRole: + return (isHorizontal ? QString::fromLatin1("Column %1") : QString::fromLatin1("Row %1")).arg(section); + case Qt::EditRole: { + auto &data = isHorizontal ? 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 hData, vData; +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication app(argc, argv); + + qmlRegisterType("TestTableModel", 0, 1, "TestTableModel"); + qmlRegisterType("TestTableModelWithHeader", 0, 1, "TestTableModelWithHeader"); + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} + +#include "main.moc" diff --git a/tests/manual/headerview/main.qml b/tests/manual/headerview/main.qml new file mode 100644 index 00000000..2919f1b2 --- /dev/null +++ b/tests/manual/headerview/main.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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 QtQml.Models 2.15 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Shapes 1.15 +import QtQuick.Window 2.15 +import Qt.labs.qmlmodels 1.0 +import TestTableModelWithHeader 0.1 + +Window { + visible: true + width: 640 + height: 480 + title: qsTr("HeaderView Test") + + TestTableModelWithHeader { + id: tableModel + rowCount: 50 + columnCount: 80 + } + + TableView { + id: tableView + anchors.top: parent.top + anchors.topMargin: horizontalHeader.height + rowSpacing + anchors.left: parent.left + anchors.leftMargin: verticalHeader.width + columnSpacing + model: tableModel + rightMargin: 100 + bottomMargin: 100 + columnSpacing: 4 + rowSpacing: 4 + syncDirection: Qt.Vertical | Qt.Horizontal + implicitWidth: parent.width + columnSpacing + implicitHeight: parent.height + rowSpacing + clip: true + delegate: Rectangle { + implicitWidth: 150 + implicitHeight: 50 + color: "#e6ecf5" + + CheckBox { + anchors.fill: parent + text: model.display + checked: model.edit + leftPadding: 12 + onClicked: model.edit = checked + } + } + } + + HorizontalHeaderView { + id: horizontalHeader + objectName: "horizontalHeader" + height: contentHeight + width: syncView.width + anchors.top: parent.top + anchors.left: tableView.left + syncView: tableView + clip: true + } + + VerticalHeaderView { + id: verticalHeader + objectName: "verticalHeader" + width: contentWidth + height: syncView.height + anchors.top: tableView.top + syncView: tableView + clip: true + } + + ToolButton { + width: verticalHeader.width + height: horizontalHeader.height + onClicked: { + horizontalHeader.contentX = 0 + verticalHeader.contentY = 0 + } + } +} diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index d23b4494..fba3c12a 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -3,6 +3,7 @@ SUBDIRS += \ buttons \ gifs \ fonts \ + headerview \ screenshots \ styles \ testbench -- cgit v1.2.3 From df7d1e9ba08ef181eb42515a2cde36a8c05ce0c8 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 11 Feb 2020 14:15:50 +0100 Subject: Make Fusion style header views look more fusiony Change-Id: I659f177ed721b16db7342f37d47d9c062ba2ef97 Reviewed-by: Volker Hilsheimer --- src/imports/controls/fusion/HorizontalHeaderView.qml | 14 ++++++++++++-- src/imports/controls/fusion/VerticalHeaderView.qml | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/imports/controls/fusion/HorizontalHeaderView.qml b/src/imports/controls/fusion/HorizontalHeaderView.qml index 946d3a75..0be27642 100644 --- a/src/imports/controls/fusion/HorizontalHeaderView.qml +++ b/src/imports/controls/fusion/HorizontalHeaderView.qml @@ -44,8 +44,18 @@ T.HorizontalHeaderView { delegate: Rectangle { implicitWidth: 50 implicitHeight: 25 - color: "#f6f6f6" - border.color: "#e4e4e4" + border.color: "#cacaca" + + gradient: Gradient { + GradientStop { + position: 0 + color: "#fbfbfb" + } + GradientStop { + position: 1 + color: "#e0dfe0" + } + } Text { text: model[control.textRole] diff --git a/src/imports/controls/fusion/VerticalHeaderView.qml b/src/imports/controls/fusion/VerticalHeaderView.qml index 67d4c1ce..a9eadc23 100644 --- a/src/imports/controls/fusion/VerticalHeaderView.qml +++ b/src/imports/controls/fusion/VerticalHeaderView.qml @@ -44,8 +44,18 @@ T.VerticalHeaderView { delegate: Rectangle { implicitWidth: 50 implicitHeight: 25 - color: "#f6f6f6" - border.color: "#e4e4e4" + border.color: "#cacaca" + + gradient: Gradient { + GradientStop { + position: 0 + color: "#fbfbfb" + } + GradientStop { + position: 1 + color: "#e0dfe0" + } + } Text { text: model[control.textRole] -- cgit v1.2.3 From 4a2cbb213a90fd6125fc5eb583dfa1cde84ad307 Mon Sep 17 00:00:00 2001 From: Yulong Bai Date: Tue, 28 Jan 2020 11:27:41 +0100 Subject: Add documentation for HorizontalHeaderView and VerticalHeaderView The example snippet only shows how to lay things out; since TableModel doesn't support declaring header data from QML yet, we also can't show it. Change-Id: Iaf1c4fd39a23be7271d382d743dc30ac459e37cb Reviewed-by: Mitch Curtis --- .../qtquickcontrols2-headerview-simple.qml | 123 ++++++++++++++++++++ src/quicktemplates2/qquickheaderview.cpp | 127 +++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 src/imports/controls/doc/snippets/qtquickcontrols2-headerview-simple.qml diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-headerview-simple.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-headerview-simple.qml new file mode 100644 index 00000000..bea46bf3 --- /dev/null +++ b/src/imports/controls/doc/snippets/qtquickcontrols2-headerview-simple.qml @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +//![file] +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import Qt.labs.qmlmodels 1.0 + +ApplicationWindow { + visible: true + width: 640 + height: 480 + + //! [horizontal] + HorizontalHeaderView { + id: horizontalHeader + syncView: tableView + anchors.left: tableView.left + width: parent.width + height: contentHeight + } + //! [horizontal] + + //! [vertical] + VerticalHeaderView { + id: verticalHeader + syncView: tableView + anchors.top: tableView.top + width: contentWidth + height: parent.height + } + //! [vertical] + + TableView { + id: tableView + anchors.fill: parent + anchors.topMargin: horizontalHeader.height + anchors.leftMargin: verticalHeader.width + columnSpacing: 1 + rowSpacing: 1 + clip: true + + model: TableModel { + TableModelColumn { display: "name" } + TableModelColumn { display: "color" } + + rows: [ + { + "name": "cat", + "color": "black" + }, + { + "name": "dog", + "color": "brown" + }, + { + "name": "bird", + "color": "white" + } + ] + } + + delegate: Rectangle { + implicitWidth: 100 + implicitHeight: 50 + border.width: 1 + + Text { + text: display + anchors.centerIn: parent + } + } + } +} + +//![file] diff --git a/src/quicktemplates2/qquickheaderview.cpp b/src/quicktemplates2/qquickheaderview.cpp index b6569881..49463944 100644 --- a/src/quicktemplates2/qquickheaderview.cpp +++ b/src/quicktemplates2/qquickheaderview.cpp @@ -39,6 +39,133 @@ #include #include + +/*! + \qmltype HorizontalHeaderView + \inqmlmodule QtQuick.Controls + \ingroup qtquickcontrols2-containers + \inherits TableView + \brief Provides a horizontal header view to accompany a \l TableView. + + A HorizontalHeaderView provides labeling of the columns of a \l TableView. + To add a horizontal header to a TableView, bind the + \l {HorizontalHeaderView::syncView} {syncView} property to the TableView: + + \snippet qtquickcontrols2-headerview-simple.qml horizontal + + The header displays data from the {syncView}'s model by default, but can + also have its own model. If the model is a QAbstractTableModel, then + the header will display the model's horizontal headerData(); otherwise, + the model's data(). +*/ + +/*! + \qmltype VerticalHeaderView + \inqmlmodule QtQuick.Controls + \ingroup qtquickcontrols2-containers + \inherits TableView + \brief Provides a vertical header view to accompany a \l TableView. + + A VerticalHeaderView provides labeling of the rows of a \l TableView. + To add a vertical header to a TableView, bind the + \l {VerticalHeaderView::syncView} {syncView} property to the TableView: + + \snippet qtquickcontrols2-headerview-simple.qml vertical + + The header displays data from the {syncView}'s model by default, but can + also have its own model. If the model is a QAbstractTableModel, then + the header will display the model's vertical headerData(); otherwise, + the model's data(). +*/ + +/*! + \qmlproperty TableView QtQuick::HorizontalHeaderView::syncView + + This property holds the TableView to synchronize with. + + Once this property is bound to another TableView, both header and table + will synchronize with regard to column widths, column spacing, and flicking + horizontally. + + If the \l model is not explicitly set, then the header will use the syncView's + model to label the columns. + + \sa model TableView +*/ + +/*! + \qmlproperty TableView QtQuick::VerticalHeaderView::syncView + + This property holds the TableView to synchronize with. + + Once this property is bound to another TableView, both header and table + will synchronize with regard to row heights, row spacing, and flicking + vertically. + + If the \l model is not explicitly set, then the header will use the syncView's + model to label the rows. + + \sa model TableView +*/ + +/*! + \qmlproperty QVariant QtQuick::HorizontalHeaderView::model + + This property holds the model providing data for the horizontal header view. + + When model is not explicitly set, the header will use the syncView's + model once syncView is set. + + If model is a QAbstractTableModel, its horizontal headerData() will + be accessed. + + If model is a QAbstractItemModel other than QAbstractTableModel, model's data() + will be accessed. + + Otherwise, the behavior is same as setting TableView::model. + + \sa TableView {TableView::model} {model} QAbstractTableModel +*/ + +/*! + \qmlproperty QVariant QtQuick::VerticalHeaderView::model + + This property holds the model providing data for the vertical header view. + + When model is not explicitly set, it will be synchronized with syncView's model + once syncView is set. + + If model is a QAbstractTableModel, its vertical headerData() will + be accessed. + + If model is a QAbstractItemModel other than QAbstractTableModel, model's data() + will be accessed. + + Otherwise, the behavior is same as setting TableView::model. + + \sa TableView {TableView::model} {model} QAbstractTableModel +*/ + +/*! + \qmlproperty QString QtQuick::HorizontalHeaderView::textRole + + This property holds the model role used to display text in each header cell. + + The default value is the \c "display" role. + + \sa QAbstractItemModel::roleNames() +*/ + +/*! + \qmlproperty QString QtQuick::VerticalHeaderView::textRole + + This property holds the model role used to display text in each header cell. + + The default value is the \c "display" role. + + \sa QAbstractItemModel::roleNames() +*/ + QT_BEGIN_NAMESPACE QQuickHeaderViewBasePrivate::QQuickHeaderViewBasePrivate() -- cgit v1.2.3 From b7bbde88d0e38b8e3635c5dd0ff3cf3075f1047e Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 28 Jan 2020 13:59:11 +0100 Subject: Gallery: simplify the code for the help feature Use existing data from the model rather than adding new properties. Change-Id: I77f9b079d4ceefd1a0b9936b4250c2470c68836e Reviewed-by: Friedemann Kleint --- examples/quickcontrols2/gallery/gallery.qml | 12 +++++++----- examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml | 2 -- examples/quickcontrols2/gallery/pages/ButtonPage.qml | 2 -- examples/quickcontrols2/gallery/pages/CheckBoxPage.qml | 2 -- examples/quickcontrols2/gallery/pages/ComboBoxPage.qml | 2 -- examples/quickcontrols2/gallery/pages/DelayButtonPage.qml | 2 -- examples/quickcontrols2/gallery/pages/DelegatePage.qml | 2 -- examples/quickcontrols2/gallery/pages/DialPage.qml | 2 -- examples/quickcontrols2/gallery/pages/DialogPage.qml | 2 -- examples/quickcontrols2/gallery/pages/FramePage.qml | 2 -- examples/quickcontrols2/gallery/pages/GroupBoxPage.qml | 2 -- examples/quickcontrols2/gallery/pages/PageIndicatorPage.qml | 2 -- examples/quickcontrols2/gallery/pages/ProgressBarPage.qml | 2 -- examples/quickcontrols2/gallery/pages/RadioButtonPage.qml | 2 -- examples/quickcontrols2/gallery/pages/RangeSliderPage.qml | 2 -- examples/quickcontrols2/gallery/pages/ScrollBarPage.qml | 2 -- .../quickcontrols2/gallery/pages/ScrollIndicatorPage.qml | 2 -- examples/quickcontrols2/gallery/pages/ScrollablePage.qml | 2 -- examples/quickcontrols2/gallery/pages/SliderPage.qml | 2 -- examples/quickcontrols2/gallery/pages/SpinBoxPage.qml | 2 -- examples/quickcontrols2/gallery/pages/StackViewPage.qml | 2 -- examples/quickcontrols2/gallery/pages/SwipeViewPage.qml | 2 -- examples/quickcontrols2/gallery/pages/SwitchPage.qml | 2 -- examples/quickcontrols2/gallery/pages/TabBarPage.qml | 2 -- examples/quickcontrols2/gallery/pages/TextAreaPage.qml | 2 -- examples/quickcontrols2/gallery/pages/TextFieldPage.qml | 2 -- examples/quickcontrols2/gallery/pages/ToolTipPage.qml | 2 -- examples/quickcontrols2/gallery/pages/TumblerPage.qml | 2 -- 28 files changed, 7 insertions(+), 59 deletions(-) diff --git a/examples/quickcontrols2/gallery/gallery.qml b/examples/quickcontrols2/gallery/gallery.qml index 95fc739f..44090b8a 100644 --- a/examples/quickcontrols2/gallery/gallery.qml +++ b/examples/quickcontrols2/gallery/gallery.qml @@ -62,11 +62,13 @@ ApplicationWindow { visible: true title: "Qt Quick Controls 2" - function help() - { - var url = "https://doc.qt.io/qt-5/" - + (stackView.depth > 1 - ? "qml-qtquick-controls2-" + stackView.currentItem.control + ".html" + function help() { + let displayingControl = listView.currentIndex !== -1 + let currentControlName = displayingControl + ? listView.model.get(listView.currentIndex).title.toLowerCase() : "" + let url = "https://doc.qt.io/qt-5/" + + (displayingControl + ? "qml-qtquick-controls2-" + currentControlName + ".html" : "qtquick-controls2-qmlmodule.html"); Qt.openUrlExternally(url) } diff --git a/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml b/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml index 504993f2..b0aa6284 100644 --- a/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml +++ b/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "busyindicator" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/ButtonPage.qml b/examples/quickcontrols2/gallery/pages/ButtonPage.qml index dce39203..c77b41e4 100644 --- a/examples/quickcontrols2/gallery/pages/ButtonPage.qml +++ b/examples/quickcontrols2/gallery/pages/ButtonPage.qml @@ -55,8 +55,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "button" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/CheckBoxPage.qml b/examples/quickcontrols2/gallery/pages/CheckBoxPage.qml index ac1ed4b7..7795f814 100644 --- a/examples/quickcontrols2/gallery/pages/CheckBoxPage.qml +++ b/examples/quickcontrols2/gallery/pages/CheckBoxPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "checkbox" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml b/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml index b194da7f..ec75607c 100644 --- a/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml +++ b/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "combobox" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/DelayButtonPage.qml b/examples/quickcontrols2/gallery/pages/DelayButtonPage.qml index ea73e6a7..91110567 100644 --- a/examples/quickcontrols2/gallery/pages/DelayButtonPage.qml +++ b/examples/quickcontrols2/gallery/pages/DelayButtonPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - property string control : "delaybutton" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/DelegatePage.qml b/examples/quickcontrols2/gallery/pages/DelegatePage.qml index 4c3f0333..30f07be1 100644 --- a/examples/quickcontrols2/gallery/pages/DelegatePage.qml +++ b/examples/quickcontrols2/gallery/pages/DelegatePage.qml @@ -55,8 +55,6 @@ import QtQuick.Controls 2.12 Pane { padding: 0 - property string control : "swipedelegate" - property var delegateComponentMap: { "ItemDelegate": itemDelegateComponent, "SwipeDelegate": swipeDelegateComponent, diff --git a/examples/quickcontrols2/gallery/pages/DialPage.qml b/examples/quickcontrols2/gallery/pages/DialPage.qml index 8372d56f..3bb3bb28 100644 --- a/examples/quickcontrols2/gallery/pages/DialPage.qml +++ b/examples/quickcontrols2/gallery/pages/DialPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "dial" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/DialogPage.qml b/examples/quickcontrols2/gallery/pages/DialogPage.qml index 167fa186..9d23e260 100644 --- a/examples/quickcontrols2/gallery/pages/DialogPage.qml +++ b/examples/quickcontrols2/gallery/pages/DialogPage.qml @@ -55,8 +55,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "dialog" - readonly property int buttonWidth: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 2, page.availableWidth / 3)) Column { diff --git a/examples/quickcontrols2/gallery/pages/FramePage.qml b/examples/quickcontrols2/gallery/pages/FramePage.qml index 5d4b2f7b..4834d04d 100644 --- a/examples/quickcontrols2/gallery/pages/FramePage.qml +++ b/examples/quickcontrols2/gallery/pages/FramePage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "frame" - readonly property int itemWidth: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 3, page.availableWidth / 3 * 2)) Column { diff --git a/examples/quickcontrols2/gallery/pages/GroupBoxPage.qml b/examples/quickcontrols2/gallery/pages/GroupBoxPage.qml index 41f115a7..16f8762a 100644 --- a/examples/quickcontrols2/gallery/pages/GroupBoxPage.qml +++ b/examples/quickcontrols2/gallery/pages/GroupBoxPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "groupbox" - readonly property int itemWidth: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 3, page.availableWidth / 3 * 2)) Column { diff --git a/examples/quickcontrols2/gallery/pages/PageIndicatorPage.qml b/examples/quickcontrols2/gallery/pages/PageIndicatorPage.qml index dd0d3e9c..4f13ce33 100644 --- a/examples/quickcontrols2/gallery/pages/PageIndicatorPage.qml +++ b/examples/quickcontrols2/gallery/pages/PageIndicatorPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "pageindicator" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml b/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml index 89b951ee..1f3c81b9 100644 --- a/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml +++ b/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "progressbar" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/RadioButtonPage.qml b/examples/quickcontrols2/gallery/pages/RadioButtonPage.qml index 9685426e..b573731e 100644 --- a/examples/quickcontrols2/gallery/pages/RadioButtonPage.qml +++ b/examples/quickcontrols2/gallery/pages/RadioButtonPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "radiobutton" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml b/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml index d04e7cb4..b6c35766 100644 --- a/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml +++ b/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "rangeslider" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/ScrollBarPage.qml b/examples/quickcontrols2/gallery/pages/ScrollBarPage.qml index 8ebf65ac..d9e77fa4 100644 --- a/examples/quickcontrols2/gallery/pages/ScrollBarPage.qml +++ b/examples/quickcontrols2/gallery/pages/ScrollBarPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 Flickable { id: flickable - readonly property string control : "scrollbar" - contentHeight: pane.height Pane { diff --git a/examples/quickcontrols2/gallery/pages/ScrollIndicatorPage.qml b/examples/quickcontrols2/gallery/pages/ScrollIndicatorPage.qml index 4aa641a8..2adcbc6b 100644 --- a/examples/quickcontrols2/gallery/pages/ScrollIndicatorPage.qml +++ b/examples/quickcontrols2/gallery/pages/ScrollIndicatorPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 Flickable { id: flickable - readonly property string control : "scrollindicator" - contentHeight: pane.height Pane { diff --git a/examples/quickcontrols2/gallery/pages/ScrollablePage.qml b/examples/quickcontrols2/gallery/pages/ScrollablePage.qml index 2d525cf6..afb5ef5c 100644 --- a/examples/quickcontrols2/gallery/pages/ScrollablePage.qml +++ b/examples/quickcontrols2/gallery/pages/ScrollablePage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 Page { id: page - readonly property string control : "flickable" - default property alias content: pane.contentItem Flickable { diff --git a/examples/quickcontrols2/gallery/pages/SliderPage.qml b/examples/quickcontrols2/gallery/pages/SliderPage.qml index 9a2f3baf..93a1ebb1 100644 --- a/examples/quickcontrols2/gallery/pages/SliderPage.qml +++ b/examples/quickcontrols2/gallery/pages/SliderPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "slider" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml b/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml index 7ad62caa..9e458331 100644 --- a/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml +++ b/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/StackViewPage.qml b/examples/quickcontrols2/gallery/pages/StackViewPage.qml index d52cf85a..43ee5684 100644 --- a/examples/quickcontrols2/gallery/pages/StackViewPage.qml +++ b/examples/quickcontrols2/gallery/pages/StackViewPage.qml @@ -55,8 +55,6 @@ StackView { id: stackView initialItem: page - readonly property string control : "stackview" - Component { id: page diff --git a/examples/quickcontrols2/gallery/pages/SwipeViewPage.qml b/examples/quickcontrols2/gallery/pages/SwipeViewPage.qml index c55250e4..3c3bc56c 100644 --- a/examples/quickcontrols2/gallery/pages/SwipeViewPage.qml +++ b/examples/quickcontrols2/gallery/pages/SwipeViewPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 Pane { id: pane - readonly property string control : "swipeview" - SwipeView { id: view currentIndex: 1 diff --git a/examples/quickcontrols2/gallery/pages/SwitchPage.qml b/examples/quickcontrols2/gallery/pages/SwitchPage.qml index 9e3f03f8..53ee1660 100644 --- a/examples/quickcontrols2/gallery/pages/SwitchPage.qml +++ b/examples/quickcontrols2/gallery/pages/SwitchPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "switch" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/TabBarPage.qml b/examples/quickcontrols2/gallery/pages/TabBarPage.qml index 1bfda1c1..7c3cae44 100644 --- a/examples/quickcontrols2/gallery/pages/TabBarPage.qml +++ b/examples/quickcontrols2/gallery/pages/TabBarPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 Page { id: page - readonly property string control : "tabbar" - SwipeView { id: swipeView anchors.fill: parent diff --git a/examples/quickcontrols2/gallery/pages/TextAreaPage.qml b/examples/quickcontrols2/gallery/pages/TextAreaPage.qml index 4a6d25e7..7ed2b58b 100644 --- a/examples/quickcontrols2/gallery/pages/TextAreaPage.qml +++ b/examples/quickcontrols2/gallery/pages/TextAreaPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "textarea" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/TextFieldPage.qml b/examples/quickcontrols2/gallery/pages/TextFieldPage.qml index 527f7a64..37a5d605 100644 --- a/examples/quickcontrols2/gallery/pages/TextFieldPage.qml +++ b/examples/quickcontrols2/gallery/pages/TextFieldPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "textfield" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/ToolTipPage.qml b/examples/quickcontrols2/gallery/pages/ToolTipPage.qml index fea05551..295ea2c4 100644 --- a/examples/quickcontrols2/gallery/pages/ToolTipPage.qml +++ b/examples/quickcontrols2/gallery/pages/ToolTipPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "tooltip" - Column { spacing: 40 width: parent.width diff --git a/examples/quickcontrols2/gallery/pages/TumblerPage.qml b/examples/quickcontrols2/gallery/pages/TumblerPage.qml index a7c95d21..af4caee3 100644 --- a/examples/quickcontrols2/gallery/pages/TumblerPage.qml +++ b/examples/quickcontrols2/gallery/pages/TumblerPage.qml @@ -54,8 +54,6 @@ import QtQuick.Controls 2.12 ScrollablePage { id: page - readonly property string control : "tumbler" - Column { spacing: 40 width: parent.width -- cgit v1.2.3 From 8f9f0508e4f3469ae56874fcecc89023b51c2a75 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 13 Feb 2020 11:54:13 +0100 Subject: Fix warnings about deprecated QQmlListProperty API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the list by pointer, fixing: qquickplatformdialog.cpp:122:50: warning: ‘QQmlListProperty::QQmlListProperty(QObject*, QList&) [with T = QObject]’ is deprecated: Use constructor taking QList pointer, and gain improved performance [-Wdeprecated-declarations] Change-Id: Icad2c2fd6398b542405c0523d9169d72b8305cc8 Reviewed-by: Fabian Kosmale --- src/imports/platform/qquickplatformdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imports/platform/qquickplatformdialog.cpp b/src/imports/platform/qquickplatformdialog.cpp index fc3c0429..2a785bbc 100644 --- a/src/imports/platform/qquickplatformdialog.cpp +++ b/src/imports/platform/qquickplatformdialog.cpp @@ -119,7 +119,7 @@ QPlatformDialogHelper *QQuickPlatformDialog::handle() const */ QQmlListProperty QQuickPlatformDialog::data() { - return QQmlListProperty(this, m_data); + return QQmlListProperty(this, &m_data); } /*! -- cgit v1.2.3 From e7a9691481e4a0112138f442c53107aa9fbcb90a Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 12 Dec 2019 13:50:03 +0100 Subject: clang-tidy: fix bugprone-integer-division MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An example of one of the warnings: qquickfusiondial.cpp:87:15: warning: result of integer division used in a floating point context; possible loss of precision [bugprone-integer-division] Change-Id: I9d225e8149935a8f8dde6e8b0657c1406676b7f1 Reviewed-by: Jan Arve Sæther --- src/imports/controls/fusion/qquickfusiondial.cpp | 2 +- src/imports/controls/qquickdefaultbusyindicator.cpp | 2 +- src/imports/controls/qquickdefaultprogressbar.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/imports/controls/fusion/qquickfusiondial.cpp b/src/imports/controls/fusion/qquickfusiondial.cpp index 182f5c0f..50436634 100644 --- a/src/imports/controls/fusion/qquickfusiondial.cpp +++ b/src/imports/controls/fusion/qquickfusiondial.cpp @@ -84,7 +84,7 @@ void QQuickFusionDial::paint(QPainter *painter) QColor buttonColor = m_palette.button().color(); const bool enabled = isEnabled(); - qreal r = qMin(width, height) / 2; + qreal r = qMin(width, height) / 2.0; r -= r/50; const qreal penSize = r/20.0; diff --git a/src/imports/controls/qquickdefaultbusyindicator.cpp b/src/imports/controls/qquickdefaultbusyindicator.cpp index 98a3cae3..aca795d9 100644 --- a/src/imports/controls/qquickdefaultbusyindicator.cpp +++ b/src/imports/controls/qquickdefaultbusyindicator.cpp @@ -124,7 +124,7 @@ void QQuickDefaultBusyIndicatorNode::sync(QQuickItem *item) Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType); QPointF pos = QPointF(sz / 2 - circleRadius, sz / 2 - circleRadius); - pos = moveCircle(pos, 360 / CircleCount * i, sz / 2 - circleRadius); + pos = moveCircle(pos, 360.0 / CircleCount * i, sz / 2 - circleRadius); QMatrix4x4 m; m.translate(dx + pos.x(), dy + pos.y()); diff --git a/src/imports/controls/qquickdefaultprogressbar.cpp b/src/imports/controls/qquickdefaultprogressbar.cpp index e8657255..f44065e4 100644 --- a/src/imports/controls/qquickdefaultprogressbar.cpp +++ b/src/imports/controls/qquickdefaultprogressbar.cpp @@ -59,7 +59,7 @@ static inline qreal blockStartX(int blockIndex) static inline qreal blockRestX(int blockIndex, qreal availableWidth) { - const qreal spanRightEdgePos = availableWidth / 2 + BlockSpan / 2; + const qreal spanRightEdgePos = availableWidth / 2 + BlockSpan / 2.0; return spanRightEdgePos - (blockIndex + 1) * BlockWidth - (blockIndex * BlockRestingSpacing); } -- cgit v1.2.3 From c1420ee5423dfa104d5ff87bc529b4530dc998d6 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 19 Feb 2020 12:56:20 +0100 Subject: ToolTip: fix timeout not activating if opened during exit transition When a tooltip with an exit transition and a timeout is made visible during its exit transition, it would end up not timing out. This is because the change in the tooltip's visibility is what usually kicks off the timeout timer, but if there is no change in visibility (because the exit transition hadn't finished, so the tooltip was still visible), this won't happen. Fix the issue by calling startTimeout() in QQuickToolTip::setVisible(). Change-Id: I5f95a698e48f376c7597558572ac91625a276e53 Fixes: QTBUG-81935 Reviewed-by: Andy Shaw --- src/quicktemplates2/qquicktooltip.cpp | 15 ++++++++++++--- tests/auto/controls/data/tst_tooltip.qml | 26 +++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp index 9d733c94..8b61375e 100644 --- a/src/quicktemplates2/qquicktooltip.cpp +++ b/src/quicktemplates2/qquicktooltip.cpp @@ -252,9 +252,18 @@ void QQuickToolTip::setVisible(bool visible) { Q_D(QQuickToolTip); if (visible) { - if (!d->visible && d->delay > 0) { - d->startDelay(); - return; + if (!d->visible) { + // We are being made visible, and we weren't before. + if (d->delay > 0) { + d->startDelay(); + return; + } + } else { + // We are being made visible, even though we already were. + // We've probably been re-opened before our exit transition could finish. + // In that case, we need to manually start the timeout, as that is usually + // done in itemChange(), which won't be called in this situation. + d->startTimeout(); } } else { d->stopDelay(); diff --git a/tests/auto/controls/data/tst_tooltip.qml b/tests/auto/controls/data/tst_tooltip.qml index d98a7cc8..adea23ef 100644 --- a/tests/auto/controls/data/tst_tooltip.qml +++ b/tests/auto/controls/data/tst_tooltip.qml @@ -227,15 +227,39 @@ TestCase { id: toolTipWithExitTransition ToolTip { + Component.onCompleted: contentItem.objectName = "contentItem" + enter: Transition { NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 100 } } exit: Transition { - NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 1000 } + NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 500 } } } } + function test_openDuringExitTransitionWithTimeout() { + let control = createTemporaryObject(toolTipWithExitTransition, testCase, { timeout: 250 }) + verify(control) + 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) + + // Let it timeout and begin the exit transition. + tryCompare(control, "opened", false) + verify(control.visible) + tryCompare(control.exit, "running", true) + verify(control.visible) + + // Quickly open it again; it should still timeout eventually. + control.open() + tryCompare(control, "opened", true) + tryCompare(control.exit, "running", true) + } + function test_makeVisibleWhileExitTransitionRunning_data() { return [ { tag: "imperative", imperative: true }, -- cgit v1.2.3 From 09476c590ab13623130d5ac79045fa68e504be96 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 13 Feb 2020 14:24:36 +0100 Subject: Fix clicked() being emitted after doubleClicked() Do as MouseArea does, and keep track of double clicks ourselves, otherwise we think the second click is a regular click. This is for mouse events only; for touch we have bigger problems to solve first: QTBUG-82146 Change-Id: I46e816d0cfa1bab98a0a1685915842ebd176e762 Fixes: QTBUG-82032 Reviewed-by: Shawn Rutledge --- src/quicktemplates2/qquickabstractbutton.cpp | 7 ++++++- src/quicktemplates2/qquickabstractbutton_p_p.h | 1 + tests/auto/controls/data/tst_abstractbutton.qml | 23 +++++++++++++++++++++++ tests/auto/controls/data/tst_button.qml | 3 +-- tests/auto/controls/data/tst_delaybutton.qml | 3 +-- tests/auto/controls/data/tst_swipedelegate.qml | 3 +-- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 969ab173..5520e074 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -176,7 +176,7 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point) if (wasPressed) { emit q->released(); - if (!wasHeld) + if (!wasHeld && !wasDoubleClick) trigger(); } else { emit q->canceled(); @@ -186,6 +186,8 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point) stopPressRepeat(); else stopPressAndHold(); + + wasDoubleClick = false; } void QQuickAbstractButtonPrivate::handleUngrab() @@ -199,6 +201,7 @@ void QQuickAbstractButtonPrivate::handleUngrab() q->setPressed(false); stopPressRepeat(); stopPressAndHold(); + wasDoubleClick = false; emit q->canceled(); } @@ -1078,8 +1081,10 @@ void QQuickAbstractButton::mousePressEvent(QMouseEvent *event) void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event) { + Q_D(QQuickAbstractButton); QQuickControl::mouseDoubleClickEvent(event); emit doubleClicked(); + d->wasDoubleClick = true; } void QQuickAbstractButton::timerEvent(QTimerEvent *event) diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h index 7394f115..e079836d 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -122,6 +122,7 @@ public: bool autoExclusive = false; bool autoRepeat = false; bool wasHeld = false; + bool wasDoubleClick = false; int holdTimer = 0; int delayTimer = 0; int repeatTimer = 0; diff --git a/tests/auto/controls/data/tst_abstractbutton.qml b/tests/auto/controls/data/tst_abstractbutton.qml index ee26a6d6..da5642cc 100644 --- a/tests/auto/controls/data/tst_abstractbutton.qml +++ b/tests/auto/controls/data/tst_abstractbutton.qml @@ -887,4 +887,27 @@ TestCase { mouseRelease(control) compare(clickedSpy.count, 1) } + + function test_doubleClick() { + let control = createTemporaryObject(button, testCase, { text: "Hello" }) + verify(control) + + let pressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" }) + verify(pressedSpy.valid) + + let releasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" }) + verify(releasedSpy.valid) + + let clickedSpy = signalSpy.createObject(control, { target: control, signalName: "clicked" }) + verify(clickedSpy.valid) + + let doubleClickedSpy = signalSpy.createObject(control, { target: control, signalName: "doubleClicked" }) + verify(doubleClickedSpy.valid) + + mouseDoubleClickSequence(control) + compare(pressedSpy.count, 2) + compare(releasedSpy.count, 2) + compare(clickedSpy.count, 1) + compare(doubleClickedSpy.count, 1) + } } diff --git a/tests/auto/controls/data/tst_button.qml b/tests/auto/controls/data/tst_button.qml index bd4fe80e..83a6ea61 100644 --- a/tests/auto/controls/data/tst_button.qml +++ b/tests/auto/controls/data/tst_button.qml @@ -152,8 +152,7 @@ TestCase { "doubleClicked", ["pressedChanged", { "pressed": false }], ["downChanged", { "down": false }], - "released", - "clicked"] + "released"] mouseDoubleClickSequence(control, control.width / 2, control.height / 2, Qt.LeftButton) verify(sequenceSpy.success) } diff --git a/tests/auto/controls/data/tst_delaybutton.qml b/tests/auto/controls/data/tst_delaybutton.qml index 2560177d..e965b5ef 100644 --- a/tests/auto/controls/data/tst_delaybutton.qml +++ b/tests/auto/controls/data/tst_delaybutton.qml @@ -173,8 +173,7 @@ TestCase { "doubleClicked", ["pressedChanged", { "pressed": false }], ["downChanged", { "down": false }], - "released", - "clicked"] + "released"] mouseDoubleClickSequence(control, control.width / 2, control.height / 2, Qt.LeftButton) verify(sequenceSpy.success) } diff --git a/tests/auto/controls/data/tst_swipedelegate.qml b/tests/auto/controls/data/tst_swipedelegate.qml index 3e2ff460..71eb0b99 100644 --- a/tests/auto/controls/data/tst_swipedelegate.qml +++ b/tests/auto/controls/data/tst_swipedelegate.qml @@ -654,8 +654,7 @@ TestCase { "pressed", "doubleClicked", ["pressedChanged", { "pressed": false }], - "released", - "clicked" + "released" ]; mouseDoubleClickSequence(control, control.width / 2, control.height / 2, Qt.LeftButton); verify(mouseSignalSequenceSpy.success); -- cgit v1.2.3 From 1f7959d3dd5942fe7f7553bba16583c37a4969a8 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 25 Feb 2020 13:32:54 +0100 Subject: Imagine: fix Dial being squished - Since we probably don't want to wrap the background in an Item, use "fillMode: Image.PreserveAspectFit" on it to ensure that the background isn't squished. - Use the same binding for the Translate's y property as we do in all of the other styles. Fixes: QTBUG-82463 Change-Id: I43129959e03ad489a8c231a7a42c192264b380ac Reviewed-by: Richard Moe Gustavsen --- src/imports/controls/imagine/Dial.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/imports/controls/imagine/Dial.qml b/src/imports/controls/imagine/Dial.qml index f10634e6..f8c394f3 100644 --- a/src/imports/controls/imagine/Dial.qml +++ b/src/imports/controls/imagine/Dial.qml @@ -74,7 +74,7 @@ T.Dial { transform: [ Translate { - y: -background.height * 0.4 + handle.height / 2 + y: -Math.min(control.background.width, control.background.height) * 0.4 + control.handle.height / 2 }, Rotation { angle: control.angle @@ -89,6 +89,7 @@ T.Dial { y: control.height / 2 - height / 2 width: Math.max(64, Math.min(control.width, control.height)) height: width + fillMode: Image.PreserveAspectFit source: Imagine.url + "dial-background" NinePatchImageSelector on source { -- cgit v1.2.3 From 32cbd7556dfbf4deb20c704b8ac6a481ddd047ae Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 3 Mar 2020 16:27:17 +0100 Subject: Prepare for internal QML API change DiagnosticMessage is getting its loc member back :) Change-Id: I07fd8b2b506bebb0acdbc20d6294d0f4b0e0214f Reviewed-by: Fabian Kosmale --- tests/auto/sanity/tst_sanity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); -- cgit v1.2.3 From 20c35f9a2b5fd970d43efc98c324e1e4c9dd153d Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 4 Mar 2020 15:15:28 +0100 Subject: Attempt to stabilize test_openDuringExitTransitionWithTimeout() I was unable to reproduce the failure, but this patch should hopefully make the test more resilient to timing issues by not requiring that the popup's opened property is true, but rather that it was true at some point. Change-Id: Icbb0407683959b9fc01b3c0d66d632922363b5d9 Fixes: QTBUG-82643 Reviewed-by: Andy Shaw --- tests/auto/controls/data/tst_tooltip.qml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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) } -- cgit v1.2.3 From 814682bb9a5c9ccaff30662dd757cd827f39aad0 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 11 Feb 2020 09:47:12 +0100 Subject: Update the current text after a translator is installed This ensures that if the model is updated due to a retranslate that it gets the updated string and the ComboBox shows it correctly. Change-Id: Iecbc18a1051d6db13035b3efa393d9bf97788dd9 Fixes: QTBUG-82020 Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickcombobox.cpp | 8 ++++ src/quicktemplates2/qquickcombobox_p.h | 1 + tests/auto/auto.pro | 6 +-- tests/auto/translation/data/comboBox.qml | 65 +++++++++++++++++++++++++++++ tests/auto/translation/qml_jp.qm | Bin 0 -> 135 bytes tests/auto/translation/qml_jp.ts | 28 +++++++++++++ tests/auto/translation/qtbase_fr.qm | Bin 0 -> 259 bytes tests/auto/translation/qtbase_fr.ts | 1 + tests/auto/translation/translation.pro | 5 +-- tests/auto/translation/tst_translation.cpp | 27 +++++++++++- 10 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 tests/auto/translation/data/comboBox.qml create mode 100644 tests/auto/translation/qml_jp.qm create mode 100644 tests/auto/translation/qml_jp.ts create mode 100644 tests/auto/translation/qtbase_fr.qm diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index 5f3f1cfc..d9bbd2bd 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -1865,6 +1865,14 @@ void QQuickComboBox::wheelEvent(QWheelEvent *event) } #endif +bool QQuickComboBox::event(QEvent *e) +{ + Q_D(QQuickComboBox); + if (e->type() == QEvent::LanguageChange) + d->updateCurrentText(); + return QQuickControl::event(e); +} + void QQuickComboBox::componentComplete() { Q_D(QQuickComboBox); diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h index b52d7545..282f3d23 100644 --- a/src/quicktemplates2/qquickcombobox_p.h +++ b/src/quicktemplates2/qquickcombobox_p.h @@ -227,6 +227,7 @@ protected: #if QT_CONFIG(wheelevent) void wheelEvent(QWheelEvent *event) override; #endif + bool event(QEvent *e) override; void componentComplete() override; void itemChange(ItemChange change, const ItemChangeData &value) override; diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 853c84a8..6059cf7b 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -30,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/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 new file mode 100644 index 00000000..a3712e99 Binary files /dev/null and b/tests/auto/translation/qml_jp.qm differ 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 @@ + + + + + main + + + Hello World + こんにちは世界 + + + + Hello Text + ハローテキスト + + + + Hello + こんにちは + + + + ListView + リストビュー + + + + diff --git a/tests/auto/translation/qtbase_fr.qm b/tests/auto/translation/qtbase_fr.qm new file mode 100644 index 00000000..176675a8 Binary files /dev/null and b/tests/auto/translation/qtbase_fr.qm differ 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 @@ + 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 #include #include +#include #include #include +#include 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 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(view.rootObject()); + QVERIFY(comboBox); + QCOMPARE(comboBox->displayText(), QLatin1String("Hello")); + + QQuickTextField *contentItem = qobject_cast(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" -- cgit v1.2.3 From 9f093c8e491b647928d01580761238e931d3ea13 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 25 Feb 2020 15:36:49 +0100 Subject: Use Qt::SplitBehavior in preference to QString::SplitBehavior The Qt version was added in 5.14 "for use as eventual replacement for QString::SplitBehavior." Move another step closer to that goal. Change-Id: I3ed1abd00bf54da654c9ccade427f5756b99b595 Reviewed-by: Simon Hausmann --- src/imports/platform/qquickplatformfiledialog.cpp | 2 +- src/quickcontrols2/qquickstyle.cpp | 4 ++-- tests/auto/customization/tst_customization.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/imports/platform/qquickplatformfiledialog.cpp b/src/imports/platform/qquickplatformfiledialog.cpp index 4c8a0192..2ef08ef6 100644 --- a/src/imports/platform/qquickplatformfiledialog.cpp +++ b/src/imports/platform/qquickplatformfiledialog.cpp @@ -623,7 +623,7 @@ static QStringList extractExtensions(const QString &filter) const int to = filter.lastIndexOf(QLatin1Char(')')) - 1; if (from >= 0 && from < to) { const QStringRef ref = filter.midRef(from + 1, to - from); - const QVector exts = ref.split(QLatin1Char(' '), QString::SkipEmptyParts); + const QVector exts = ref.split(QLatin1Char(' '), Qt::SkipEmptyParts); for (const QStringRef &ref : exts) extensions += extractExtension(ref.toString()); } diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 61632b11..0d7b44c6 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -110,7 +110,7 @@ static QStringList envPathList(const QByteArray &var) QStringList paths; if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty(var))) { const QByteArray value = qgetenv(var); - paths += QString::fromLocal8Bit(value).split(QDir::listSeparator(), QString::SkipEmptyParts); + paths += QString::fromLocal8Bit(value).split(QDir::listSeparator(), Qt::SkipEmptyParts); } return paths; } @@ -347,7 +347,7 @@ QStringList QQuickStylePrivate::stylePaths(bool resolve) } else { // Fast/simpler path for systems where something other than : is used as // the list separator (such as ';'). - const QStringList customPaths = value.split(listSeparator, QString::SkipEmptyParts); + const QStringList customPaths = value.split(listSeparator, Qt::SkipEmptyParts); paths += customPaths; } } diff --git a/tests/auto/customization/tst_customization.cpp b/tests/auto/customization/tst_customization.cpp index cce74b41..498a9e60 100644 --- a/tests/auto/customization/tst_customization.cpp +++ b/tests/auto/customization/tst_customization.cpp @@ -311,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); // --