diff options
author | Liang Qi <liang.qi@qt.io> | 2016-05-23 11:37:07 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-05-25 08:53:08 +0200 |
commit | 44ac831c51d248b115e594ae930c3bb359df68a1 (patch) | |
tree | 68cd02e4285ed74ed32e7300c8dbc361d7c6e7af | |
parent | 894f718b3aa1eaa9f27802c4544cbc235f8c7144 (diff) | |
parent | 1e65f0c1d2ceb59ba4f1a2b0564168c50f11a540 (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts:
tests/auto/material/data/tst_material.qml
Due to 1c51ae29 in qtdeclarative, some failures happened when
comparing colors. Just blacklist them for now.
Task-number: QTBUG-53556
Change-Id: I19b218157a69af5bc8c32f6fe89b5757ed411976
72 files changed, 918 insertions, 215 deletions
diff --git a/src/imports/calendar/qtlabscalendarplugin.cpp b/src/imports/calendar/qtlabscalendarplugin.cpp index 4ecd5ddb..b42f64f2 100644 --- a/src/imports/calendar/qtlabscalendarplugin.cpp +++ b/src/imports/calendar/qtlabscalendarplugin.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QtLabsCalendarPlugin: public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtLabsCalendarPlugin(QObject *parent = nullptr); diff --git a/src/imports/controls/Button.qml b/src/imports/controls/Button.qml index d9ca2910..f875a97a 100644 --- a/src/imports/controls/Button.qml +++ b/src/imports/controls/Button.qml @@ -47,14 +47,14 @@ T.Button { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 - leftPadding: 8 - rightPadding: 8 + leftPadding: padding + 2 + rightPadding: padding + 2 //! [contentItem] contentItem: Text { text: control.text font: control.font - opacity: enabled || highlighted ? 1 : 0.3 + opacity: enabled || control.highlighted || control.checked ? 1 : 0.3 color: control.checked || control.highlighted ? "#ffffff" : (control.visualFocus ? "#0066ff" : (control.down ? "#26282a" : "#353637")) horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -66,12 +66,13 @@ T.Button { background: Rectangle { implicitWidth: 100 implicitHeight: 40 - opacity: enabled ? 1 : (control.checked ? 0.2 : 0.3) + opacity: enabled ? 1 : 0.3 + visible: !control.flat || control.down || control.checked || control.highlighted color: control.checked || control.highlighted ? (control.visualFocus ? (control.down ? "#599bff" : "#0066ff") : (control.down ? "#585a5c" : "#353637")) : - (control.visualFocus ? (control.down ? "#cce0ff" : "#f0f6ff") : (control.down ? "#d6d6d6" : "#f6f6f6")) - border.color: control.visualFocus ? "#0066ff" : (control.down ? "#26282a" : "#353637") - border.width: control.checked || control.highlighted ? 0 : (control.visualFocus ? 2 : 1) + (control.visualFocus ? (control.down ? "#cce0ff" : "#f0f6ff") : (control.down ? "#d0d0d0" : "#e0e0e0")) + border.color: "#0066ff" + border.width: control.visualFocus ? 2 : 0 } //! [background] } diff --git a/src/imports/controls/CheckIndicator.qml b/src/imports/controls/CheckIndicator.qml index 5f75181e..d78e9e30 100644 --- a/src/imports/controls/CheckIndicator.qml +++ b/src/imports/controls/CheckIndicator.qml @@ -44,14 +44,16 @@ Rectangle { implicitWidth: 28 implicitHeight: 28 - color: control.enabled ? (control.down ? (control.visualFocus ? "#cce0ff" : "#e4e4e4") : "#f6f6f6") : "#353637" + color: control.enabled ? (control.down ? (control.visualFocus ? "#cce0ff" : "#f6f6f6") : "#ffffff") : "#353637" border.width: control.visualFocus ? 2 : 1 - border.color: control.enabled ? (control.visualFocus ? "#0066ff" : (control.down ? "#26282a" : "#353637")) : "transparent" + border.color: control.enabled ? (control.visualFocus ? "#0066ff" : (control.down ? "#808080" : "#909090")) : "transparent" Image { x: (parent.width - width) / 2 y: (parent.height - height) / 2 source: "image://default/check/" + (control.visualFocus ? "#0066ff" : "#353637") + sourceSize.width: width + sourceSize.height: height visible: control.checkState === Qt.Checked } diff --git a/src/imports/controls/ComboBox.qml b/src/imports/controls/ComboBox.qml index ed723c09..757af672 100644 --- a/src/imports/controls/ComboBox.qml +++ b/src/imports/controls/ComboBox.qml @@ -51,8 +51,8 @@ T.ComboBox { spacing: 8 padding: 6 - leftPadding: 12 - rightPadding: 12 + leftPadding: padding + 6 + rightPadding: padding + 6 opacity: enabled ? 1 : 0.3 @@ -70,6 +70,8 @@ T.ComboBox { x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding y: control.topPadding + (control.availableHeight - height) / 2 source: "image://default/double-arrow/" + (control.visualFocus ? "#0066ff" : "#353637") + sourceSize.width: width + sourceSize.height: height } //! [indicator] @@ -93,9 +95,9 @@ T.ComboBox { implicitHeight: 40 color: control.visualFocus ? (control.pressed ? "#cce0ff" : "#f0f6ff") : - (control.pressed || popup.visible ? "#d6d6d6" : "#f6f6f6") - border.color: control.visualFocus ? "#0066ff" : "#353637" - border.width: control.visualFocus ? 2 : 1 + (control.pressed || popup.visible ? "#d0d0d0" : "#e0e0e0") + border.color: "#0066ff" + border.width: control.visualFocus ? 2 : 0 } //! [background] @@ -119,7 +121,7 @@ T.ComboBox { width: listview.width height: listview.height color: "transparent" - border.color: "#353637" + border.color: "#bdbebf" } T.ScrollIndicator.vertical: ScrollIndicator { } diff --git a/src/imports/controls/Dial.qml b/src/imports/controls/Dial.qml index 9db51384..aa138126 100644 --- a/src/imports/controls/Dial.qml +++ b/src/imports/controls/Dial.qml @@ -63,6 +63,8 @@ T.Dial { width: 14 height: 10 source: "image://default/dial-indicator/" + (control.visualFocus ? "#0066ff" : "#353637") + sourceSize.width: width + sourceSize.height: height antialiasing: true opacity: control.enabled ? 1 : 0.3 transform: [ diff --git a/src/imports/controls/RadioIndicator.qml b/src/imports/controls/RadioIndicator.qml index b9a17dfe..08c24cc5 100644 --- a/src/imports/controls/RadioIndicator.qml +++ b/src/imports/controls/RadioIndicator.qml @@ -41,9 +41,9 @@ Rectangle { implicitHeight: 28 radius: width / 2 - color: control.down ? (control.visualFocus ? "#cce0ff" : "#e4e4e4") : (control.visualFocus ? "#f0f6ff" : "#f6f6f6") + color: control.down ? (control.visualFocus ? "#cce0ff" : "#f6f6f6") : (control.visualFocus ? "#f0f6ff" : "#ffffff") border.width: control.visualFocus ? 2 : 1 - border.color: control.visualFocus ? "#0066ff" : (control.down ? "#26282a" : "#353637") + border.color: control.visualFocus ? "#0066ff" : (control.down ? "#808080" : "#909090") property Item control @@ -53,7 +53,7 @@ Rectangle { width: 20 height: 20 radius: width / 2 - color: parent.border.color + color: control.down ? "#26282a" : "#353637" visible: control.checked } } diff --git a/src/imports/controls/RangeSlider.qml b/src/imports/controls/RangeSlider.qml index 096df0b6..8d285298 100644 --- a/src/imports/controls/RangeSlider.qml +++ b/src/imports/controls/RangeSlider.qml @@ -59,8 +59,8 @@ T.RangeSlider { implicitHeight: 28 radius: width / 2 border.width: activeFocus ? 2 : 1 - border.color: activeFocus ? "#0066ff" : (control.first.pressed ? "#26282a" : "#353637") - color: first.pressed ? (activeFocus ? "#cce0ff" : "#e4e4e4") : (activeFocus ? "#f0f6ff" : "#f6f6f6") + border.color: control.enabled ? (activeFocus ? "#0066ff" : (control.first.pressed ? "#808080" : "#909090")) : "#d6d6d6" + color: control.enabled ? (first.pressed ? (activeFocus ? "#cce0ff" : "#f6f6f6") : (activeFocus ? "#f0f6ff" : "#ffffff")) : "#fdfdfd" readonly property bool horizontal: control.orientation === Qt.Horizontal } @@ -74,8 +74,8 @@ T.RangeSlider { implicitHeight: 28 radius: width / 2 border.width: activeFocus ? 2 : 1 - border.color: activeFocus ? "#0066ff" : (control.second.pressed ? "#26282a" : "#353637") - color: second.pressed ? (activeFocus ? "#cce0ff" : "#e4e4e4") : (activeFocus ? "#f0f6ff" : "#f6f6f6") + border.color: control.enabled ? (activeFocus ? "#0066ff" : (control.first.pressed ? "#808080" : "#909090")) : "#d6d6d6" + color: control.enabled ? (second.pressed ? (activeFocus ? "#cce0ff" : "#f6f6f6") : (activeFocus ? "#f0f6ff" : "#ffffff")) : "#fdfdfd" readonly property bool horizontal: control.orientation === Qt.Horizontal } @@ -90,8 +90,8 @@ T.RangeSlider { width: horizontal ? control.availableWidth : implicitWidth height: horizontal ? implicitHeight : control.availableHeight radius: 3 - border.color: "#353637" - color: "#ffffff" + opacity: control.enabled ? 1 : 0.3 + color: "#e0e0e0" scale: horizontal && control.mirrored ? -1 : 1 readonly property bool horizontal: control.orientation === Qt.Horizontal diff --git a/src/imports/controls/Slider.qml b/src/imports/controls/Slider.qml index fd83d8e5..a44a6c80 100644 --- a/src/imports/controls/Slider.qml +++ b/src/imports/controls/Slider.qml @@ -56,9 +56,9 @@ T.Slider { implicitWidth: 28 implicitHeight: 28 radius: width / 2 - color: control.pressed ? (control.visualFocus ? "#cce0ff" : "#e4e4e4") : (control.visualFocus ? "#f0f6ff" : "#f6f6f6") + color: control.enabled ? (control.pressed ? (control.visualFocus ? "#cce0ff" : "#f6f6f6") : (control.visualFocus ? "#f0f6ff" : "#ffffff")) : "#fdfdfd" border.width: control.visualFocus ? 2 : 1 - border.color: control.visualFocus ? "#0066ff" : (control.pressed ? "#26282a" : "#353637") + border.color: control.enabled ? (control.visualFocus ? "#0066ff" : (control.pressed ? "#808080" : "#909090")) : "#d6d6d6" readonly property bool horizontal: control.orientation === Qt.Horizontal } @@ -73,8 +73,8 @@ T.Slider { width: horizontal ? control.availableWidth : implicitWidth height: horizontal ? implicitHeight : control.availableHeight radius: 3 - border.color: "#353637" - color: "#ffffff" + opacity: control.enabled ? 1 : 0.3 + color: "#e0e0e0" scale: horizontal && control.mirrored ? -1 : 1 readonly property bool horizontal: control.orientation === Qt.Horizontal diff --git a/src/imports/controls/SpinBox.qml b/src/imports/controls/SpinBox.qml index 9ea9d5ef..93db1c8e 100644 --- a/src/imports/controls/SpinBox.qml +++ b/src/imports/controls/SpinBox.qml @@ -51,8 +51,8 @@ T.SpinBox { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 - leftPadding: 6 + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0)) - rightPadding: 6 + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0)) + leftPadding: padding + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0)) + rightPadding: padding + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0)) opacity: control.enabled ? 1 : 0.3 //! [validator] @@ -98,8 +98,7 @@ T.SpinBox { height: parent.height implicitWidth: 40 implicitHeight: 40 - color: up.pressed ? "#e4e4e4" : "#f6f6f6" - border.color: control.enabled ? "#353637" : "#bdbebf" + color: up.pressed ? "#d0d0d0" : "#e0e0e0" Rectangle { x: (parent.width - width) / 2 @@ -124,8 +123,7 @@ T.SpinBox { height: parent.height implicitWidth: 40 implicitHeight: 40 - color: down.pressed ? "#e4e4e4" : "#f6f6f6" - border.color: control.enabled ? "#353637" : "#bdbebf" + color: down.pressed ? "#d0d0d0" : "#e0e0e0" Rectangle { x: (parent.width - width) / 2 @@ -140,7 +138,7 @@ T.SpinBox { //! [background] background: Rectangle { implicitWidth: 140 - border.color: "#bdbebf" + border.color: "#e0e0e0" } //! [background] } diff --git a/src/imports/controls/SwipeDelegate.qml b/src/imports/controls/SwipeDelegate.qml index 6060fcb2..7ffd5a29 100644 --- a/src/imports/controls/SwipeDelegate.qml +++ b/src/imports/controls/SwipeDelegate.qml @@ -75,7 +75,7 @@ T.SwipeDelegate { //! [background] background: Rectangle { - color: control.down ? "#bdbebf" : "#eeeeee" + color: control.visualFocus ? (control.down ? "#cce0ff" : "#e5efff") : (control.down ? "#bdbebf" : "#ffffff") Behavior on x { enabled: !control.down diff --git a/src/imports/controls/SwitchIndicator.qml b/src/imports/controls/SwitchIndicator.qml index ead6b64c..f11f7147 100644 --- a/src/imports/controls/SwitchIndicator.qml +++ b/src/imports/controls/SwitchIndicator.qml @@ -47,9 +47,10 @@ Item { width: 56 height: 16 radius: 8 - color: control.checked ? (control.visualFocus ? "#0066ff" : "#353637") : "#ffffff" - border.width: control.visualFocus ? 2 : 1 - border.color: control.checked ? "transparent" : (control.visualFocus ? "#0066ff" : "#353637") + opacity: control.enabled ? 1 : 0.3 + color: control.checked ? (control.visualFocus ? "#0066ff" : "#353637") : "#e0e0e0" + border.width: control.visualFocus ? 2 : 0 + border.color: "#0066ff" } Rectangle { @@ -58,12 +59,12 @@ Item { width: 28 height: 28 radius: 16 - color: control.pressed ? (control.visualFocus ? "#cce0ff" : "#e4e4e4") : (control.visualFocus ? "#f0f6ff" : "#f6f6f6") + color: control.enabled ? (control.down ? (control.visualFocus ? "#cce0ff" : "#f6f6f6") : (control.visualFocus ? "#f0f6ff" : "#ffffff")) : "#fdfdfd" border.width: control.visualFocus ? 2 : 1 - border.color: control.visualFocus ? "#0066ff" : (control.pressed ? "#26282a" : "#353637") + border.color: control.enabled ? (control.visualFocus ? "#0066ff" : (control.down ? "#808080" : "#909090")) : "#d6d6d6" Behavior on x { - enabled: !control.pressed + enabled: !control.down SmoothedAnimation { velocity: 200 } } } diff --git a/src/imports/controls/TextArea.qml b/src/imports/controls/TextArea.qml index a109cb8d..f1ec6dfa 100644 --- a/src/imports/controls/TextArea.qml +++ b/src/imports/controls/TextArea.qml @@ -48,7 +48,7 @@ T.TextArea { placeholder.implicitHeight + topPadding + bottomPadding) padding: 6 - leftPadding: 10 + leftPadding: padding + 4 opacity: enabled ? 1 : 0.2 color: "#353637" diff --git a/src/imports/controls/TextField.qml b/src/imports/controls/TextField.qml index 742c3a28..aea83dde 100644 --- a/src/imports/controls/TextField.qml +++ b/src/imports/controls/TextField.qml @@ -46,7 +46,7 @@ T.TextField { placeholder.implicitHeight + topPadding + bottomPadding) padding: 6 - leftPadding: 10 + leftPadding: padding + 4 opacity: enabled ? 1 : 0.2 color: "#353637" @@ -74,9 +74,9 @@ T.TextField { background: Rectangle { implicitWidth: 200 implicitHeight: 40 -// border.width: control.activeFocus ? 2 : 1 + border.width: control.activeFocus ? 2 : 1 color: control.enabled ? "transparent" : "#353637" - border.color: control.enabled ? "#bdbebf" : "transparent" + border.color: control.activeFocus ? "#0066ff" : (control.enabled ? "#bdbebf" : "transparent") } //! [background] } diff --git a/src/imports/controls/doc/images/qtquickcontrols2-spinbox-double.png b/src/imports/controls/doc/images/qtquickcontrols2-spinbox-double.png Binary files differnew file mode 100644 index 00000000..fcfaa472 --- /dev/null +++ b/src/imports/controls/doc/images/qtquickcontrols2-spinbox-double.png diff --git a/src/imports/controls/doc/qtquickcontrols2.qdocconf b/src/imports/controls/doc/qtquickcontrols2.qdocconf index 8f059281..25eb8e9c 100644 --- a/src/imports/controls/doc/qtquickcontrols2.qdocconf +++ b/src/imports/controls/doc/qtquickcontrols2.qdocconf @@ -41,7 +41,7 @@ exampledirs += ../../../../examples/quickcontrols2 \ ../../../../tests/auto/controls/data \ snippets -examplesinstallpath = qtquickcontrols2/quickcontrols2 +examplesinstallpath = quickcontrols2 headerdirs += ../../../quicktemplates2 \ ../../calendar \ diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-spinbox-double.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-spinbox-double.qml new file mode 100644 index 00000000..15af31ae --- /dev/null +++ b/src/imports/controls/doc/snippets/qtquickcontrols2-spinbox-double.qml @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 2.0 + +//! [1] +SpinBox { + id: spinbox + from: 0 + value: 110 + to: 100 * 100 + stepSize: 100 + anchors.centerIn: parent + + property int decimals: 2 + property real realValue: value / 100 + + validator: DoubleValidator { + bottom: Math.min(spinbox.from, spinbox.to) + top: Math.max(spinbox.from, spinbox.to) + } + + textFromValue: function(value, locale) { + return Number(value / 100).toLocaleString(locale, 'f', spinbox.decimals) + } + + valueFromText: function(text, locale) { + return Number.fromLocaleString(locale, text) * 100 + } +} +//! [1] diff --git a/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc index 47666b8d..ef084fcf 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc @@ -33,47 +33,133 @@ \annotatedlist qtquickcontrols2-buttons - Each type of button has its own specific target use case. The following + Each type of button has its own specific use case. The following sections offer guidelines for choosing the appropriate type of button, depending on the use case. \section1 Button Control - \image qtquickcontrols2-button.png - \l Button presents a push-button control that can be pushed or clicked - by the user. Buttons are normally used to perform an action, or to answer - a question. Typical buttons are \e OK, \e Apply, \e Cancel, \e Close, - \e Yes, \e No, and \e Help. + \l Button is a clickable control that starts an action, or opens or + closes a popup. A button usually has a text label but it can also + contain an icon. + + Button is a very suitable control when a popup or dialog needs + to perform an action. The most common examples are Apply, Cancel, + Save, Close and Help. + + \table + \row \li \image qtquickcontrols2-button-normal.png + \li A button in its normal state. + \row \li \image qtquickcontrols2-button-pressed.png + \li A button that is pressed. + \row \li \image qtquickcontrols2-button-focused.png + \li A button that has active focus. + \row \li \image qtquickcontrols2-button-disabled.png + \li A button that is disabled. + \endtable + + Recommendations: + + \list + \li The button's text should be a verb describing the action, or a noun matching + the title of the popup that will be opened. + \li Don't use a button to set state. \l Switch is more suitable for that. + \li Use the default font unless you have UI guidelines specifying otherwise. + \li If the text is localized, consider the influence of a longer text on the layout. + \endlist + + \b {See also} \l Button and \l AbstractButton \section1 CheckBox Control \image qtquickcontrols2-checkbox.png - \l CheckBox presents an option button that can be toggled on (checked) - or off (unchecked). Check boxes are typically used to select one or more - options from a set of options. + \l CheckBox is used to build multi-selection option lists. Any number of + options can be selected, including none, but the options should + not be mutually exclusive. + + Use a single CheckBox for a yes/no choice, such as when you have + to accept the terms of service agreement in a form. + + For a single yes/no choice, it is also possible to use a switch. If the choice + concerns an option, it is best to use a CheckBox. If it concerns action to + be taken, a switch is recommended. + + When options can be grouped, you can use a partially checked CheckBox to + represent the whole group. Use the checkbox's indeterminate state when + a user selects some, but not all, sub-items in the group. + + The three availables statuses are: checked, unchecked and disabled. + "Disabled" is useful when the user should not be able to check or uncheck + a checkbox. + + The checkable options are often listed vertically. + + Recommendations: + \list + \li The checkbox label should be a statement that the check mark makes true, + and that the absence of a check mark makes false. + \li The checkbox label should not contain a negative statement. + \li Use the default font, unless you have UI guidelines specifying otherwise. + \li If the text is localized, consider the influence of a longer text on the layout. + \endlist + + \b {See also} \l CheckBox \section1 RadioButton Control \image qtquickcontrols2-radiobutton.png - \l RadioButton presents an option button that can be toggled on (checked) - or off (unchecked). Radio buttons are typically used to select one option - from a set of options. + \l RadioButton is used to select only one option from a set of options. + Selecting one option automatically deselects the one selected before. + + The set of options should not be too large, otherwise it starts taking too much + space on the screen. In that case it would be more practical to use a \l ComboBox. + + If there are only two mutually exclusive options, combine them into a + single checkbox or a switch. + + Recommendations: + + \list + \li Limit the label text to one line. + \li Ensure that a sensible default option is checked. + \li List RadioButton options vertically. + \li If the text is localized, consider the influence of a longer text on the layout. + \li Use the default font, unless you have UI guidelines that specify otherwise. + \li Just like with CheckBox, do not make the list too large. + \li In order to avoid confusion, do not put two groups of radio buttons next to each + other. + \endlist + + \b {See also} \l RadioButton \section1 Switch Control \image qtquickcontrols2-switch.png - \l Switch is an option button that can be dragged or toggled on (checked) - or off (unchecked). Switches are typically used to select between two - states. + \l Switch represents a physical switch that allows users to choose between an "on" + or "off" state. + Use a switch for binary operations that take effect immediately after it has been + switched on. For example, a switch to turn WIFI on or off. + + Recommendations: + + \list + \li Keep labels short and concise. + \li If the text is localized, consider the influence of a longer text on the layout. + \endlist + + \b {See also} \l Switch \section1 ToolButton Control \image qtquickcontrols2-toolbutton.png - \l ToolButton is functionally similar to \l Button, but provides a look - that is more suitable within a \l ToolBar. + \l ToolButton is nearly identical to \l Button, but it has a graphical + appearance that makes it more suitable for insertion into a \l ToolBar. + + \b {See also} \l ToolButton + */ diff --git a/src/imports/controls/material/Button.qml b/src/imports/controls/material/Button.qml index 984a2ece..a7d99106 100644 --- a/src/imports/controls/material/Button.qml +++ b/src/imports/controls/material/Button.qml @@ -42,15 +42,6 @@ import QtQuick.Controls.Material.impl 2.0 T.Button { id: control - // TODO: Add a flat property to T.Button, and make this: - // flat ? control.down || control.hovered ? 2 : 0 - // : control.down ? 8 : 2 - // See https://bugreports.qt.io/browse/QTBUG-51054 - // NOTE: Flat buttons should be transparent by default and have no elevation when pressed - // However, on the desktop, flat buttons can be colored and have a 2dp when pressed - // This is called a flat raised button - Material.elevation: control.down ? 8 : 2 - implicitWidth: Math.max(background ? background.implicitWidth : 0, contentItem.implicitWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, @@ -59,14 +50,19 @@ T.Button { // external vertical padding is 6 (to increase touch area) padding: 12 - leftPadding: 8 - rightPadding: 8 + leftPadding: padding - 4 + rightPadding: padding - 4 + + Material.elevation: flat ? control.down || control.hovered ? 2 : 0 + : control.down ? 8 : 2 + Material.background: flat ? "transparent" : undefined //! [contentItem] contentItem: Text { text: control.text font: control.font color: !control.enabled ? control.Material.hintTextColor : + control.flat && control.highlighted ? control.Material.accentColor : control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.primaryTextColor horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -90,7 +86,7 @@ T.Button { : control.down ? control.highlighted ? control.Material.highlightedButtonPressColor : control.Material.buttonPressColor - : control.visualFocus + : control.visualFocus || control.checked ? control.highlighted ? control.Material.highlightedButtonHoverColor : control.Material.buttonHoverColor : control.highlighted ? control.Material.highlightedButtonColor diff --git a/src/imports/controls/material/CheckBox.qml b/src/imports/controls/material/CheckBox.qml index d2e58347..0163e37d 100644 --- a/src/imports/controls/material/CheckBox.qml +++ b/src/imports/controls/material/CheckBox.qml @@ -50,10 +50,9 @@ T.CheckBox { baselineOffset: contentItem.y + contentItem.baselineOffset spacing: 8 - topPadding: 15 - leftPadding: 8 - rightPadding: 8 - bottomPadding: 15 + padding: 8 + topPadding: padding + 7 + bottomPadding: padding + 7 //! [indicator] indicator: CheckIndicator { diff --git a/src/imports/controls/material/RadioButton.qml b/src/imports/controls/material/RadioButton.qml index 02687315..ddf496ab 100644 --- a/src/imports/controls/material/RadioButton.qml +++ b/src/imports/controls/material/RadioButton.qml @@ -50,10 +50,9 @@ T.RadioButton { baselineOffset: contentItem.y + contentItem.baselineOffset spacing: 8 - topPadding: 14 - leftPadding: 8 - rightPadding: 8 - bottomPadding: 14 + padding: 8 + topPadding: padding + 6 + bottomPadding: padding + 6 //! [indicator] indicator: RadioIndicator { diff --git a/src/imports/controls/material/SwipeDelegate.qml b/src/imports/controls/material/SwipeDelegate.qml index 4879f09f..e1375f76 100644 --- a/src/imports/controls/material/SwipeDelegate.qml +++ b/src/imports/controls/material/SwipeDelegate.qml @@ -81,9 +81,16 @@ T.SwipeDelegate { background: Rectangle { implicitHeight: 48 - color: !control.enabled ? control.Material.swipeDelegateDisabledColor : - (control.down ? control.Material.swipeDelegatePressColor : - (control.visualFocus || control.hovered ? control.Material.swipeDelegateHoverColor : control.Material.swipeDelegateColor)) + color: control.Material.backgroundColor + + Rectangle { + width: parent.width + height: parent.height + visible: control.down || control.highlighted || control.visualFocus + color: control.down ? control.Material.buttonPressColor : + control.visualFocus || control.hovered ? control.Material.swipeDelegateHoverColor : + control.Material.listHighlightColor + } Behavior on x { enabled: !control.down diff --git a/src/imports/controls/material/ToolTip.qml b/src/imports/controls/material/ToolTip.qml index 0674c7d9..5b1b9667 100644 --- a/src/imports/controls/material/ToolTip.qml +++ b/src/imports/controls/material/ToolTip.qml @@ -50,10 +50,9 @@ T.ToolTip { contentItem.implicitHeight + topPadding + bottomPadding) margins: 12 - topPadding: 8 - leftPadding: 16 - rightPadding: 16 - bottomPadding: 8 + padding: 8 + leftPadding: padding + 8 + rightPadding: padding + 8 closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnReleaseOutsideParent diff --git a/src/imports/controls/material/qquickmaterialtheme.cpp b/src/imports/controls/material/qquickmaterialtheme.cpp index 379a30fc..0d2f8a70 100644 --- a/src/imports/controls/material/qquickmaterialtheme.cpp +++ b/src/imports/controls/material/qquickmaterialtheme.cpp @@ -37,6 +37,7 @@ #include "qquickmaterialtheme_p.h" #include <QtGui/qfont.h> +#include <QtGui/qfontinfo.h> QT_BEGIN_NAMESPACE @@ -45,11 +46,14 @@ QQuickMaterialTheme::QQuickMaterialTheme(QPlatformTheme *theme) { QFont font; font.setFamily(QStringLiteral("Roboto")); - if (!font.exactMatch()) + QString family = QFontInfo(font).family(); + + if (family != QStringLiteral("Roboto")) { font.setFamily(QStringLiteral("Noto")); + family = QFontInfo(font).family(); + } - if (font.exactMatch()) { - const QString family = font.family(); + if (family == QStringLiteral("Roboto") || family == QStringLiteral("Noto")) { systemFont.setFamily(family); buttonFont.setFamily(family); toolTipFont.setFamily(family); diff --git a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp index 5ee6e767..ac11e95b 100644 --- a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp +++ b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE class QtQuickControls2MaterialStylePlugin : public QQuickStylePlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuickControls2MaterialStylePlugin(QObject *parent = nullptr); diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp index eca84812..1982b392 100644 --- a/src/imports/controls/qtquickcontrols2plugin.cpp +++ b/src/imports/controls/qtquickcontrols2plugin.cpp @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE class QtQuickControls2Plugin: public QQuickStylePlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuickControls2Plugin(QObject *parent = nullptr); diff --git a/src/imports/controls/universal/Button.qml b/src/imports/controls/universal/Button.qml index fbe79b6b..60a2ac51 100644 --- a/src/imports/controls/universal/Button.qml +++ b/src/imports/controls/universal/Button.qml @@ -47,10 +47,9 @@ T.Button { contentItem.implicitHeight + topPadding + bottomPadding) baselineOffset: contentItem.y + contentItem.baselineOffset - topPadding: 4 - leftPadding: 8 - rightPadding: 8 - bottomPadding: 4 + padding: 8 + topPadding: padding - 4 + bottomPadding: padding - 4 property bool useSystemFocusVisuals: true @@ -72,6 +71,7 @@ T.Button { implicitWidth: 32 implicitHeight: 32 + visible: !control.flat || control.down || control.checked || control.highlighted color: control.down ? control.Universal.baseMediumLowColor : control.enabled && (control.highlighted || control.checked) ? control.Universal.accent : control.Universal.baseLowColor diff --git a/src/imports/controls/universal/CheckDelegate.qml b/src/imports/controls/universal/CheckDelegate.qml index d693ead1..9441c7b0 100644 --- a/src/imports/controls/universal/CheckDelegate.qml +++ b/src/imports/controls/universal/CheckDelegate.qml @@ -50,10 +50,9 @@ T.CheckDelegate { spacing: 12 - topPadding: 11 - leftPadding: 12 - rightPadding: 12 - bottomPadding: 13 + padding: 12 + topPadding: padding - 1 + bottomPadding: padding + 1 //! [indicator] indicator: CheckIndicator { diff --git a/src/imports/controls/universal/CheckIndicator.qml b/src/imports/controls/universal/CheckIndicator.qml index a508ad18..eeecf264 100644 --- a/src/imports/controls/universal/CheckIndicator.qml +++ b/src/imports/controls/universal/CheckIndicator.qml @@ -58,6 +58,8 @@ Rectangle { visible: control.checkState === Qt.Checked source: "image://universal/checkmark/" + (!control.enabled ? control.Universal.baseLowColor : control.Universal.chromeWhiteColor) + sourceSize.width: width + sourceSize.height: height } Rectangle { diff --git a/src/imports/controls/universal/ComboBox.qml b/src/imports/controls/universal/ComboBox.qml index 633abf47..6d550aa2 100644 --- a/src/imports/controls/universal/ComboBox.qml +++ b/src/imports/controls/universal/ComboBox.qml @@ -51,10 +51,10 @@ T.ComboBox { baselineOffset: contentItem.y + contentItem.baselineOffset spacing: 10 - topPadding: 5 - leftPadding: 12 - rightPadding: 10 - bottomPadding: 7 + padding: 12 + topPadding: padding - 7 + rightPadding: padding - 2 + bottomPadding: padding - 5 //! [delegate] delegate: ItemDelegate { @@ -69,6 +69,8 @@ T.ComboBox { x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding y: control.topPadding + (control.availableHeight - height) / 2 source: "image://universal/downarrow/" + (!control.enabled ? control.Universal.baseLowColor : control.Universal.baseMediumHighColor) + sourceSize.width: width + sourceSize.height: height } //! [indicator] diff --git a/src/imports/controls/universal/ItemDelegate.qml b/src/imports/controls/universal/ItemDelegate.qml index e02eac69..af239e4c 100644 --- a/src/imports/controls/universal/ItemDelegate.qml +++ b/src/imports/controls/universal/ItemDelegate.qml @@ -50,10 +50,9 @@ T.ItemDelegate { spacing: 12 - topPadding: 11 - leftPadding: 12 - rightPadding: 12 - bottomPadding: 13 + padding: 12 + topPadding: padding - 1 + bottomPadding: padding + 1 //! [contentItem] contentItem: Text { diff --git a/src/imports/controls/universal/MenuItem.qml b/src/imports/controls/universal/MenuItem.qml index c8561cbf..342c0d70 100644 --- a/src/imports/controls/universal/MenuItem.qml +++ b/src/imports/controls/universal/MenuItem.qml @@ -48,10 +48,9 @@ T.MenuItem { indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) baselineOffset: contentItem.y + contentItem.baselineOffset - topPadding: 11 - leftPadding: 12 - rightPadding: 12 - bottomPadding: 13 + padding: 12 + topPadding: padding - 1 + bottomPadding: padding + 1 spacing: 12 //! [contentItem] @@ -76,6 +75,8 @@ T.MenuItem { visible: control.checked source: !control.checkable ? "" : "image://universal/checkmark/" + (!control.enabled ? control.Universal.baseLowColor : control.down ? control.Universal.baseHighColor : control.Universal.baseMediumHighColor) + sourceSize.width: width + sourceSize.height: height } //! [indicator] diff --git a/src/imports/controls/universal/RadioDelegate.qml b/src/imports/controls/universal/RadioDelegate.qml index 9fe984bd..8bf05d2d 100644 --- a/src/imports/controls/universal/RadioDelegate.qml +++ b/src/imports/controls/universal/RadioDelegate.qml @@ -50,10 +50,9 @@ T.RadioDelegate { spacing: 12 - topPadding: 11 - leftPadding: 12 - rightPadding: 12 - bottomPadding: 13 + padding: 12 + topPadding: padding - 1 + bottomPadding: padding + 1 property Item control diff --git a/src/imports/controls/universal/SpinBox.qml b/src/imports/controls/universal/SpinBox.qml index 4b9b4810..49fa6954 100644 --- a/src/imports/controls/universal/SpinBox.qml +++ b/src/imports/controls/universal/SpinBox.qml @@ -52,10 +52,11 @@ T.SpinBox { baselineOffset: contentItem.y + contentItem.baselineOffset // TextControlThemePadding + 2 (border) - topPadding: 5 - bottomPadding: 7 - leftPadding: 12 + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0)) - rightPadding: 8 + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0)) + padding: 12 + topPadding: padding - 7 + leftPadding: padding + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0)) + rightPadding: padding - 4 + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0)) + bottomPadding: padding - 5 Universal.theme: activeFocus ? Universal.Light : undefined @@ -107,6 +108,8 @@ T.SpinBox { source: "image://universal/" + (control.mirrored ? "left" : "right") + "arrow/" + (!control.enabled ? control.Universal.chromeDisabledLowColor : control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor) + sourceSize.width: width + sourceSize.height: height } } //! [up.indicator] @@ -133,6 +136,8 @@ T.SpinBox { source: "image://universal/" + (control.mirrored ? "right" : "left") + "arrow/" + (!control.enabled ? control.Universal.chromeDisabledLowColor : control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor) + sourceSize.width: width + sourceSize.height: height } } //! [down.indicator] diff --git a/src/imports/controls/universal/SwipeDelegate.qml b/src/imports/controls/universal/SwipeDelegate.qml index 02a2fa65..d11983e3 100644 --- a/src/imports/controls/universal/SwipeDelegate.qml +++ b/src/imports/controls/universal/SwipeDelegate.qml @@ -50,10 +50,9 @@ T.SwipeDelegate { spacing: 12 - topPadding: 11 - leftPadding: 12 - rightPadding: 12 - bottomPadding: 13 + padding: 12 + topPadding: padding - 1 + bottomPadding: padding + 1 //! [contentItem] contentItem: Text { @@ -83,16 +82,19 @@ T.SwipeDelegate { //! [background] background: Rectangle { - color: !control.enabled ? control.Universal.chromeDisabledHighColor : - (control.down ? control.Universal.chromeHighColor : - (control.visualFocus || control.hovered ? control.Universal.chromeLowColor : control.Universal.chromeMediumColor)) + color: control.Universal.background Rectangle { width: parent.width height: parent.height - visible: control.visualFocus || control.highlighted - color: control.Universal.accent - opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6 + color: control.down ? control.Universal.listMediumColor : control.Universal.altMediumLowColor + Rectangle { + width: parent.width + height: parent.height + visible: control.visualFocus || control.highlighted + color: control.Universal.accent + opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6 + } } Behavior on x { diff --git a/src/imports/controls/universal/SwitchDelegate.qml b/src/imports/controls/universal/SwitchDelegate.qml index 25652f1b..43a1c4e2 100644 --- a/src/imports/controls/universal/SwitchDelegate.qml +++ b/src/imports/controls/universal/SwitchDelegate.qml @@ -50,10 +50,9 @@ T.SwitchDelegate { spacing: 12 - topPadding: 11 - leftPadding: 12 - rightPadding: 12 - bottomPadding: 13 + padding: 12 + topPadding: padding - 1 + bottomPadding: padding + 1 //! [indicator] indicator: SwitchIndicator { diff --git a/src/imports/controls/universal/TextArea.qml b/src/imports/controls/universal/TextArea.qml index e326512b..b4c38135 100644 --- a/src/imports/controls/universal/TextArea.qml +++ b/src/imports/controls/universal/TextArea.qml @@ -49,10 +49,10 @@ T.TextArea { placeholder.implicitHeight + topPadding + bottomPadding) // TextControlThemePadding + 2 (border) - topPadding: 5 - leftPadding: 12 - rightPadding: 8 - bottomPadding: 7 + padding: 12 + topPadding: padding - 7 + rightPadding: padding - 4 + bottomPadding: padding - 5 Universal.theme: activeFocus ? Universal.Light : undefined diff --git a/src/imports/controls/universal/TextField.qml b/src/imports/controls/universal/TextField.qml index 69046e48..041cf0e8 100644 --- a/src/imports/controls/universal/TextField.qml +++ b/src/imports/controls/universal/TextField.qml @@ -49,10 +49,10 @@ T.TextField { placeholder.implicitHeight + topPadding + bottomPadding) // TextControlThemePadding + 2 (border) - topPadding: 5 - leftPadding: 12 - rightPadding: 8 - bottomPadding: 7 + padding: 12 + topPadding: padding - 7 + rightPadding: padding - 4 + bottomPadding: padding - 5 Universal.theme: activeFocus ? Universal.Light : undefined diff --git a/src/imports/controls/universal/ToolTip.qml b/src/imports/controls/universal/ToolTip.qml index 705800c8..16576811 100644 --- a/src/imports/controls/universal/ToolTip.qml +++ b/src/imports/controls/universal/ToolTip.qml @@ -50,10 +50,9 @@ T.ToolTip { contentItem.implicitHeight + topPadding + bottomPadding) margins: 8 - topPadding: 5 - leftPadding: 8 - rightPadding: 8 - bottomPadding: 7 + padding: 8 + topPadding: padding - 3 + bottomPadding: padding - 1 closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnReleaseOutsideParent diff --git a/src/imports/controls/universal/qquickuniversaltheme.cpp b/src/imports/controls/universal/qquickuniversaltheme.cpp index 856242b3..51642c4a 100644 --- a/src/imports/controls/universal/qquickuniversaltheme.cpp +++ b/src/imports/controls/universal/qquickuniversaltheme.cpp @@ -37,6 +37,7 @@ #include "qquickuniversaltheme_p.h" #include <QtGui/qfont.h> +#include <QtGui/qfontinfo.h> QT_BEGIN_NAMESPACE @@ -44,7 +45,7 @@ QQuickUniversalTheme::QQuickUniversalTheme(QPlatformTheme *theme) : QQuickProxyTheme(theme) { const QFont font(QStringLiteral("Segoe UI")); - if (font.exactMatch()) { + if (QFontInfo(font).family() == QStringLiteral("Segoe UI")) { const QString family = font.family(); systemFont.setFamily(family); groupBoxTitleFont.setFamily(family); diff --git a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp index 1ec5a75a..ddad6548 100644 --- a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp +++ b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE class QtQuickControls2UniversalStylePlugin: public QQuickStylePlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuickControls2UniversalStylePlugin(QObject *parent = nullptr); diff --git a/src/imports/templates/plugins.qmltypes b/src/imports/templates/plugins.qmltypes index 434aee4d..c96dd2dc 100644 --- a/src/imports/templates/plugins.qmltypes +++ b/src/imports/templates/plugins.qmltypes @@ -72,6 +72,7 @@ Module { Property { name: "checkable"; type: "bool" } Property { name: "autoRepeat"; type: "bool" } Property { name: "highlighted"; type: "bool" } + Property { name: "flat"; type: "bool" } } Component { name: "QQuickCheckBox" @@ -117,8 +118,8 @@ Module { name: "highlighted" Parameter { name: "index"; type: "int" } } - Method { name: "increase" } - Method { name: "decrease" } + Method { name: "incrementCurrentIndex" } + Method { name: "decrementCurrentIndex" } Method { name: "textAt" type: "string" diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp index ab46c7ab..3f05d31e 100644 --- a/src/imports/templates/qtquicktemplates2plugin.cpp +++ b/src/imports/templates/qtquicktemplates2plugin.cpp @@ -92,7 +92,7 @@ QT_BEGIN_NAMESPACE class QtQuickTemplates2Plugin: public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: QtQuickTemplates2Plugin(QObject *parent = nullptr); diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 1f599323..99764976 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -38,6 +38,7 @@ #include "qquickstyleattached_p.h" #include <QtCore/qdir.h> +#include <QtCore/qdebug.h> #include <QtCore/qsettings.h> #include <QtGui/private/qguiapplication_p.h> #include <QtQml/private/qqmlmetatype_p.h> diff --git a/src/quickcontrols2/qquickstyleattached.cpp b/src/quickcontrols2/qquickstyleattached.cpp index 8b035455..d0df79c5 100644 --- a/src/quickcontrols2/qquickstyleattached.cpp +++ b/src/quickcontrols2/qquickstyleattached.cpp @@ -39,6 +39,7 @@ #include <QtCore/qfile.h> #include <QtCore/qsettings.h> #include <QtCore/qfileselector.h> +#include <QtQuick/qquickwindow.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuickTemplates2/private/qquickpopup_p.h> @@ -154,15 +155,19 @@ QQuickStyleAttached::QQuickStyleAttached(QObject *parent) : QObject(parent) item = popup->popupItem(); } - if (item) + if (item) { + connect(item, &QQuickItem::windowChanged, this, &QQuickStyleAttached::itemWindowChanged); QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Parent); + } } QQuickStyleAttached::~QQuickStyleAttached() { QQuickItem *item = qobject_cast<QQuickItem *>(parent()); - if (item) + if (item) { + disconnect(item, &QQuickItem::windowChanged, this, &QQuickStyleAttached::itemWindowChanged); QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent); + } setParentStyle(nullptr); } @@ -222,6 +227,14 @@ void QQuickStyleAttached::parentStyleChange(QQuickStyleAttached *newParent, QQui Q_UNUSED(oldParent); } +void QQuickStyleAttached::itemWindowChanged(QQuickWindow *window) +{ + Q_UNUSED(window); + QQuickItem *item = qobject_cast<QQuickItem *>(sender()); + if (item) + setParentStyle(findParentStyle(metaObject(), item)); +} + void QQuickStyleAttached::itemParentChanged(QQuickItem *item, QQuickItem *parent) { Q_UNUSED(parent); diff --git a/src/quickcontrols2/qquickstyleattached_p.h b/src/quickcontrols2/qquickstyleattached_p.h index 67938290..13b816f2 100644 --- a/src/quickcontrols2/qquickstyleattached_p.h +++ b/src/quickcontrols2/qquickstyleattached_p.h @@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE class QSettings; +class QQuickWindow; class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickStyleAttached : public QObject, public QQuickItemChangeListener { @@ -80,6 +81,7 @@ protected: virtual void parentStyleChange(QQuickStyleAttached *newParent, QQuickStyleAttached *oldParent); + void itemWindowChanged(QQuickWindow *window); void itemParentChanged(QQuickItem *item, QQuickItem *parent) override; private: diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index 401313d8..940e5eeb 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -424,6 +424,8 @@ QQuickItem *QQuickApplicationWindow::contentItem() const QQuickApplicationWindowPrivate *d = const_cast<QQuickApplicationWindowPrivate *>(d_func()); if (!d->contentItem) { d->contentItem = new QQuickItem(QQuickWindow::contentItem()); + d->contentItem->setFlag(QQuickItem::ItemIsFocusScope); + d->contentItem->setFocus(true); d->relayout(); } return d->contentItem; diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp index cb5b2963..465e82de 100644 --- a/src/quicktemplates2/qquickbutton.cpp +++ b/src/quicktemplates2/qquickbutton.cpp @@ -97,11 +97,12 @@ class QQuickButtonPrivate : public QQuickAbstractButtonPrivate public: QQuickButtonPrivate(); + bool flat; bool highlighted; }; QQuickButtonPrivate::QQuickButtonPrivate() : - highlighted(false) + flat(false), highlighted(false) { } @@ -166,4 +167,29 @@ void QQuickButton::setHighlighted(bool highlighted) emit highlightedChanged(); } +/*! + \qmlproperty bool QtQuick.Controls::Button::flat + + This property holds whether the button is flat. + + A flat button typically does not draw a background unless it is pressed or checked. + + The default value is \c false. +*/ +bool QQuickButton::isFlat() const +{ + Q_D(const QQuickButton); + return d->flat; +} + +void QQuickButton::setFlat(bool flat) +{ + Q_D(QQuickButton); + if (flat == d->flat) + return; + + d->flat = flat; + emit flatChanged(); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickbutton_p.h b/src/quicktemplates2/qquickbutton_p.h index 36eb4359..fafce150 100644 --- a/src/quicktemplates2/qquickbutton_p.h +++ b/src/quicktemplates2/qquickbutton_p.h @@ -60,6 +60,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickButton : public QQuickAbstractButto Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL) Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL) Q_PROPERTY(bool highlighted READ isHighlighted WRITE setHighlighted NOTIFY highlightedChanged FINAL) + Q_PROPERTY(bool flat READ isFlat WRITE setFlat NOTIFY flatChanged FINAL) public: explicit QQuickButton(QQuickItem *parent = nullptr); @@ -67,10 +68,14 @@ public: bool isHighlighted() const; void setHighlighted(bool highlighted); + bool isFlat() const; + void setFlat(bool flat); + Q_SIGNALS: void checkableChanged(); void autoRepeatChanged(); void highlightedChanged(); + void flatChanged(); protected: void checkableChange() override; diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index cf64ae95..a5c94b48 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -166,8 +166,8 @@ public: void createdItem(int index, QObject *object); void countChanged(); void updateCurrentText(); - void increase(); - void decrease(); + void incrementCurrentIndex(); + void decrementCurrentIndex(); void setHighlightedIndex(int index); void createDelegateModel(); @@ -269,7 +269,7 @@ void QQuickComboBoxPrivate::updateCurrentText() } } -void QQuickComboBoxPrivate::increase() +void QQuickComboBoxPrivate::incrementCurrentIndex() { Q_Q(QQuickComboBox); if (isPopupVisible()) { @@ -285,7 +285,7 @@ void QQuickComboBoxPrivate::increase() } } -void QQuickComboBoxPrivate::decrease() +void QQuickComboBoxPrivate::decrementCurrentIndex() { Q_Q(QQuickComboBox); if (isPopupVisible()) { @@ -737,31 +737,31 @@ int QQuickComboBox::find(const QString &text, Qt::MatchFlags flags) const } /*! - \qmlmethod void QtQuick.Controls::ComboBox::increase() + \qmlmethod void QtQuick.Controls::ComboBox::incrementCurrentIndex() - Increases the current index of the combo box, or the highlighted + Increments the current index of the combo box, or the highlighted index if the popup list when it is visible. \sa currentIndex, highlightedIndex */ -void QQuickComboBox::increase() +void QQuickComboBox::incrementCurrentIndex() { Q_D(QQuickComboBox); - d->increase(); + d->incrementCurrentIndex(); } /*! - \qmlmethod void QtQuick.Controls::ComboBox::decrease() + \qmlmethod void QtQuick.Controls::ComboBox::decrementCurrentIndex() - Decreases the current index of the combo box, or the highlighted + Decrements the current index of the combo box, or the highlighted index if the popup list when it is visible. \sa currentIndex, highlightedIndex */ -void QQuickComboBox::decrease() +void QQuickComboBox::decrementCurrentIndex() { Q_D(QQuickComboBox); - d->decrease(); + d->decrementCurrentIndex(); } void QQuickComboBox::focusOutEvent(QFocusEvent *event) @@ -781,6 +781,7 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event) switch (event->key()) { case Qt::Key_Escape: + case Qt::Key_Back: if (d->isPopupVisible()) event->accept(); break; @@ -796,11 +797,11 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event) event->accept(); break; case Qt::Key_Up: - d->decrease(); + d->decrementCurrentIndex(); event->accept(); break; case Qt::Key_Down: - d->increase(); + d->incrementCurrentIndex(); event->accept(); break; default: @@ -828,6 +829,7 @@ void QQuickComboBox::keyReleaseEvent(QKeyEvent *event) event->accept(); break; case Qt::Key_Escape: + case Qt::Key_Back: d->hidePopup(false); setPressed(false); event->accept(); @@ -872,9 +874,9 @@ void QQuickComboBox::wheelEvent(QWheelEvent *event) if (d->wheelEnabled && !d->isPopupVisible()) { const int oldIndex = d->currentIndex; if (event->angleDelta().y() > 0) - d->decrease(); + d->decrementCurrentIndex(); else - d->increase(); + d->incrementCurrentIndex(); event->setAccepted(d->currentIndex != oldIndex); } } diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h index 8b25c616..26b7688e 100644 --- a/src/quicktemplates2/qquickcombobox_p.h +++ b/src/quicktemplates2/qquickcombobox_p.h @@ -112,8 +112,8 @@ public: Q_INVOKABLE int find(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly) const; public Q_SLOTS: - void increase(); - void decrease(); + void incrementCurrentIndex(); + void decrementCurrentIndex(); Q_SIGNALS: void countChanged(); diff --git a/src/quicktemplates2/qquickdrawer.cpp b/src/quicktemplates2/qquickdrawer.cpp index e08bb278..74d79b28 100644 --- a/src/quicktemplates2/qquickdrawer.cpp +++ b/src/quicktemplates2/qquickdrawer.cpp @@ -217,7 +217,10 @@ bool QQuickDrawerPrivate::handleMousePressEvent(QQuickItem *item, QMouseEvent *e break; } } else { - event->setAccepted(item->isAncestorOf(popupItem)); + if (modal) + event->setAccepted(item->isAncestorOf(popupItem)); + else + event->setAccepted(false); } velocityCalculator.startMeasuring(pressPoint, event->timestamp()); diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index f85dd207..d47c7571 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -42,7 +42,7 @@ #include <QtQml/private/qqmlobjectmodel_p.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquickitemchangelistener_p.h> -#include <QtQuick/private/qquickflickable_p.h> +#include <QtQuick/private/qquickitemview_p.h> #include <QtQuick/private/qquickevents_p_p.h> #include <QtQuick/private/qquickwindow_p.h> @@ -108,6 +108,8 @@ void QQuickMenuPrivate::insertItem(int index, QQuickItem *item) { contentData.append(item); item->setParentItem(contentItem); + if (qobject_cast<QQuickItemView *>(contentItem)) + QQuickItemPrivate::get(item)->setCulled(true); // QTBUG-53262 if (complete) resizeItem(item); QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent); diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp index 04ed8470..0fb9f3ca 100644 --- a/src/quicktemplates2/qquickoverlay.cpp +++ b/src/quicktemplates2/qquickoverlay.cpp @@ -68,14 +68,14 @@ void QQuickOverlayPrivate::popupAboutToShow() { Q_Q(QQuickOverlay); QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender()); - if (!popup) + if (!popup || !popup->dim()) return; // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors if (popup->isModal()) { if (modal) QQmlProperty::write(modal, QStringLiteral("opacity"), 1.0); - } else if (popup->dim()) { + } else { if (modeless) QQmlProperty::write(modeless, QStringLiteral("opacity"), 1.0); } @@ -85,14 +85,14 @@ void QQuickOverlayPrivate::popupAboutToHide() { Q_Q(QQuickOverlay); QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender()); - if (!popup) + if (!popup || !popup->dim()) return; // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors if (popup->isModal()) { if (modal && modalPopups <= 1) QQmlProperty::write(modal, QStringLiteral("opacity"), 0.0); - } else if (popup->dim()) { + } else { if (modeless) QQmlProperty::write(modeless, QStringLiteral("opacity"), 0.0); } @@ -102,7 +102,7 @@ void QQuickOverlayPrivate::drawerPositionChange() { Q_Q(QQuickOverlay); QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(q->sender()); - if (!drawer) + if (!drawer || !drawer->dim()) return; // call QQuickItem::setOpacity() directly to avoid triggering QML Behaviors @@ -110,7 +110,7 @@ void QQuickOverlayPrivate::drawerPositionChange() if (drawer->isModal()) { if (modal) modal->setOpacity(drawer->position()); - } else if (drawer->dim()) { + } else { if (modeless) modeless->setOpacity(drawer->position()); } @@ -133,10 +133,13 @@ void QQuickOverlayPrivate::restackOverlay() QQuickPopup *modelessPopup = nullptr; for (auto it = popups.crbegin(), end = popups.crend(); it != end; ++it) { QQuickPopup *popup = (*it); + if (!popup->dim()) + continue; + if (popup->isModal()) { if (!modalPopup || modalPopup->z() >= popup->z()) modalPopup = popup; - } else if (popup->dim()) { + } else { if (!modelessPopup) modelessPopup = popup; } diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 94cf5d76..cb13d7b6 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -131,8 +131,11 @@ QQuickPopupPrivate::QQuickPopupPrivate() , hasBottomMargin(false) , allowVerticalFlip(false) , allowHorizontalFlip(false) + , hadActiveFocusBeforeExitTransition(false) , x(0) , y(0) + , effectiveX(0) + , effectiveY(0) , margins(-1) , topMargin(0) , leftMargin(0) @@ -179,17 +182,16 @@ bool QQuickPopupPrivate::tryClose(QQuickItem *item, QMouseEvent *event) void QQuickPopupPrivate::prepareEnterTransition(bool notify) { Q_Q(QQuickPopup); - QQuickWindow *quickWindow = q->window(); - if (!quickWindow) { + if (!window) { qmlInfo(q) << "cannot find any window to open popup in."; return; } - QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(quickWindow); + QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(window); if (!applicationWindow) { - quickWindow->installEventFilter(q); + window->installEventFilter(q); popupItem->setZ(10001); // DefaultWindowDecoration+1 - popupItem->setParentItem(quickWindow->contentItem()); + popupItem->setParentItem(window->contentItem()); } else { popupItem->setParentItem(applicationWindow->overlay()); } @@ -205,11 +207,14 @@ void QQuickPopupPrivate::prepareEnterTransition(bool notify) void QQuickPopupPrivate::prepareExitTransition() { Q_Q(QQuickPopup); - QQuickWindow *quickWindow = q->window(); - if (quickWindow && !qobject_cast<QQuickApplicationWindow *>(quickWindow)) - quickWindow->removeEventFilter(q); - if (focus) + if (window && !qobject_cast<QQuickApplicationWindow *>(window)) + window->removeEventFilter(q); + if (focus) { + // The setFocus(false) call below removes any active focus before we're + // able to check it in finalizeExitTransition. + hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus(); popupItem->setFocus(false); + } emit q->aboutToHide(); } @@ -230,7 +235,16 @@ void QQuickPopupPrivate::finalizeExitTransition(bool hide) popupItem->setVisible(false); } + if (hadActiveFocusBeforeExitTransition) { + QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(window); + if (applicationWindow) + applicationWindow->contentItem()->setFocus(true); + else if (window) + window->contentItem()->setFocus(true); + } + visible = false; + hadActiveFocusBeforeExitTransition = false; emit q->visibleChanged(); emit q->closed(); } @@ -543,6 +557,9 @@ void QQuickPopupPositioner::itemDestroyed(QQuickItem *item) void QQuickPopupPrivate::reposition() { Q_Q(QQuickPopup); + if (!popupItem->isVisible()) + return; + const qreal w = popupItem->width(); const qreal h = popupItem->height(); const qreal iw = popupItem->implicitWidth(); @@ -555,7 +572,6 @@ void QQuickPopupPrivate::reposition() if (parentItem) { rect = parentItem->mapRectToScene(rect); - QQuickWindow *window = q->window(); if (window) { const QMarginsF margins = getMargins(); const QRectF bounds = QRectF(0, 0, window->width(), window->height()).marginsRemoved(margins); @@ -601,6 +617,11 @@ void QQuickPopupPrivate::reposition() rect.setRight(bounds.right()); widthAdjusted = true; } + } else if (iw > 0 && rect.left() >= bounds.left() && rect.right() <= bounds.right() + && iw != w) { + // restore original width + rect.setWidth(iw); + widthAdjusted = true; } if (ih > 0 && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) { @@ -620,11 +641,27 @@ void QQuickPopupPrivate::reposition() rect.setBottom(bounds.bottom()); heightAdjusted = true; } + } else if (ih > 0 && rect.top() >= bounds.top() && rect.bottom() <= bounds.bottom() + && ih != h) { + // restore original height + rect.setHeight(ih); + heightAdjusted = true; } } } popupItem->setPosition(rect.topLeft()); + + const QPointF effectivePos = parentItem ? parentItem->mapFromScene(rect.topLeft()) : rect.topLeft(); + if (!qFuzzyCompare(effectiveX, effectivePos.x())) { + effectiveX = effectivePos.x(); + emit q->xChanged(); + } + if (!qFuzzyCompare(effectiveY, effectivePos.y())) { + effectiveY = effectivePos.y(); + emit q->yChanged(); + } + if (widthAdjusted && rect.width() > 0) popupItem->setWidth(rect.width()); if (heightAdjusted && rect.height() > 0) @@ -766,7 +803,8 @@ void QQuickPopup::close() */ qreal QQuickPopup::x() const { - return position().x(); + Q_D(const QQuickPopup); + return d->effectiveX; } void QQuickPopup::setX(qreal x) @@ -782,7 +820,8 @@ void QQuickPopup::setX(qreal x) */ qreal QQuickPopup::y() const { - return position().y(); + Q_D(const QQuickPopup); + return d->effectiveY; } void QQuickPopup::setY(qreal y) @@ -794,10 +833,7 @@ void QQuickPopup::setY(qreal y) QPointF QQuickPopup::position() const { Q_D(const QQuickPopup); - QPointF pos = d->popupItem->position(); - if (d->parentItem) - pos = d->parentItem->mapFromScene(pos); - return pos; + return QPointF(d->effectiveX, d->effectiveY); } void QQuickPopup::setPosition(const QPointF &pos) @@ -1336,10 +1372,7 @@ void QQuickPopup::resetFont() QQuickWindow *QQuickPopup::window() const { Q_D(const QQuickPopup); - if (!d->parentItem) - return nullptr; - - return d->parentItem->window(); + return d->window; } QQuickItem *QQuickPopup::popupItem() const @@ -1806,7 +1839,7 @@ void QQuickPopup::keyPressEvent(QKeyEvent *event) if (hasActiveFocus() && (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab)) QQuickItemPrivate::focusNextPrev(d->popupItem, event->key() == Qt::Key_Tab); - if (event->key() != Qt::Key_Escape) + if (event->key() != Qt::Key_Escape && event->key() != Qt::Key_Back) return; if (d->closePolicy.testFlag(CloseOnEscape)) @@ -1889,10 +1922,6 @@ void QQuickPopup::geometryChanged(const QRectF &newGeometry, const QRectF &oldGe { Q_D(QQuickPopup); d->reposition(); - if (!qFuzzyCompare(newGeometry.x(), oldGeometry.x())) - emit xChanged(); - if (!qFuzzyCompare(newGeometry.y(), oldGeometry.y())) - emit yChanged(); if (!qFuzzyCompare(newGeometry.width(), oldGeometry.width())) { emit widthChanged(); emit availableWidthChanged(); diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 3ff55129..9ea5a7f0 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -190,8 +190,11 @@ public: bool hasBottomMargin; bool allowVerticalFlip; bool allowHorizontalFlip; + bool hadActiveFocusBeforeExitTransition; qreal x; qreal y; + qreal effectiveX; + qreal effectiveY; qreal margins; qreal topMargin; qreal leftMargin; diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index c5a8f661..2b58acf2 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -81,6 +81,13 @@ static const int AUTO_REPEAT_INTERVAL = 100; \snippet qtquickcontrols2-spinbox-textual.qml 1 + In the same manner, SpinBox can be customized to accept floating point + numbers: + + \image qtquickcontrols2-spinbox-double.png + + \snippet qtquickcontrols2-spinbox-double.qml 1 + \sa Tumbler, {Customizing SpinBox} */ diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp index 7158ce41..b0998604 100644 --- a/src/quicktemplates2/qquickstackview.cpp +++ b/src/quicktemplates2/qquickstackview.cpp @@ -41,6 +41,9 @@ #include <QtQml/qqmlengine.h> #include <QtQml/qqmlinfo.h> +#include <private/qv4qobjectwrapper_p.h> +#include <private/qqmlengine_p.h> + QT_BEGIN_NAMESPACE /*! diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp index d91c229d..809f7386 100644 --- a/src/quicktemplates2/qquickstackview_p.cpp +++ b/src/quicktemplates2/qquickstackview_p.cpp @@ -41,6 +41,7 @@ #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> #include <QtQml/qqmlincubator.h> +#include <QtQml/private/qv4qobjectwrapper_p.h> #include <QtQml/private/qqmlcomponent_p.h> #include <QtQml/private/qqmlengine_p.h> #include <QtQuick/private/qquickanimation_p.h> @@ -91,6 +92,10 @@ QQuickStackElement::~QQuickStackElement() item = nullptr; } else { item->setVisible(false); + if (!widthValid) + item->resetWidth(); + if (!heightValid) + item->resetHeight(); if (item->parentItem() != originalParent) { item->setParentItem(originalParent); } else { @@ -179,7 +184,8 @@ void QQuickStackElement::initialize() Q_ASSERT(v4); QV4::Scope scope(v4); QV4::ScopedValue ipv(scope, properties.value()); - d->initializeObjectWithInitialProperties(ipv, item); + QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value()); + d->initializeObjectWithInitialProperties(qmlContext, ipv, item); properties.clear(); } @@ -278,6 +284,7 @@ static bool initProperties(QQuickStackElement *element, const QV4::Value &props, if (!wrapper) { QV4::ExecutionEngine *v4 = args->v4engine(); element->properties.set(v4, props); + element->qmlCallingContext.set(v4, v4->qmlContext()); return true; } } diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h index 2c9e6f35..679cee09 100644 --- a/src/quicktemplates2/qquickstackview_p_p.h +++ b/src/quicktemplates2/qquickstackview_p_p.h @@ -98,6 +98,7 @@ public: QPointer<QQuickItem> originalParent; QQuickStackView::Status status; QV4::PersistentValue properties; + QV4::PersistentValue qmlCallingContext; }; class QQuickStackViewPrivate : public QQuickControlPrivate, public QQuickItemViewTransitionChangeListener diff --git a/tests/auto/applicationwindow/data/focusAfterPopupClosed.qml b/tests/auto/applicationwindow/data/focusAfterPopupClosed.qml new file mode 100644 index 00000000..629e0cf9 --- /dev/null +++ b/tests/auto/applicationwindow/data/focusAfterPopupClosed.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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:BSD$ +** 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.6 +import QtQuick.Controls 2.0 + +ApplicationWindow { + width: 200 + height: 200 + visible: true + + signal focusScopeKeyPressed + + property alias toolButton: toolButton + property alias focusScope: focusScope + + header: ToolBar { + ToolButton { + id: toolButton + text: qsTr("File") + onClicked: fileMenu.open() + focusPolicy: Qt.TabFocus + + Menu { + id: fileMenu + y: parent.height + + MenuItem { + text: qsTr("New") + } + MenuItem { + text: qsTr("Open") + } + MenuItem { + text: qsTr("Close") + } + } + } + } + + FocusScope { + id: focusScope + focus: true + anchors.fill: parent + + Keys.onSpacePressed: focusScopeKeyPressed() + } +} + diff --git a/tests/auto/applicationwindow/tst_applicationwindow.cpp b/tests/auto/applicationwindow/tst_applicationwindow.cpp index 954f80d8..bec8aa81 100644 --- a/tests/auto/applicationwindow/tst_applicationwindow.cpp +++ b/tests/auto/applicationwindow/tst_applicationwindow.cpp @@ -71,6 +71,7 @@ private slots: void locale(); void activeFocusControl_data(); void activeFocusControl(); + void focusAfterPopupClosed(); }; void tst_applicationwindow::qmlCreation() @@ -639,6 +640,50 @@ void tst_applicationwindow::activeFocusControl() QCOMPARE(window->activeFocusControl(), activeFocusControl); } +void tst_applicationwindow::focusAfterPopupClosed() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("focusAfterPopupClosed.qml")); + QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow*>(component.create())); + QVERIFY(window); + + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + QVERIFY(QGuiApplication::focusWindow() == window.data()); + + QQuickItem* contentItem = window->contentItem(); + QVERIFY(contentItem); + QVERIFY(contentItem->hasActiveFocus()); + + QQuickItem* focusScope = window->property("focusScope").value<QQuickItem*>(); + QVERIFY(focusScope); + QVERIFY(focusScope->hasActiveFocus()); + + QSignalSpy spy(window.data(), SIGNAL(focusScopeKeyPressed())); + QTest::keyClick(window.data(), Qt::Key_Space); + QCOMPARE(spy.count(), 1); + + // Open the menu. + QQuickItem* toolButton = window->property("toolButton").value<QQuickItem*>(); + QVERIFY(toolButton); + QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, + toolButton->mapFromScene(QPointF(toolButton->width() / 2, toolButton->height() / 2)).toPoint()); + QVERIFY(!focusScope->hasActiveFocus()); + + // The FocusScope shouldn't receive any key events while the menu is open. + QTest::keyClick(window.data(), Qt::Key_Space); + QCOMPARE(spy.count(), 1); + + // Close the menu. The FocusScope should regain focus. + QTest::keyClick(window.data(), Qt::Key_Escape); + QVERIFY(focusScope->hasActiveFocus()); + + QTest::keyClick(window.data(), Qt::Key_Space); + QCOMPARE(spy.count(), 2); +} + QTEST_MAIN(tst_applicationwindow) #include "tst_applicationwindow.moc" diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml index 156bc652..20b5a551 100644 --- a/tests/auto/controls/data/tst_popup.qml +++ b/tests/auto/controls/data/tst_popup.qml @@ -334,6 +334,24 @@ TestCase { compare(xSpy.count, 1) compare(ySpy.count, 1) + // re-parent and reset the position + control.parent = rect.createObject(testCase, {color: "red", width: 100, height: 100}) + control.x = 0 + control.y = 0 + compare(xSpy.count, 2) + compare(ySpy.count, 2) + + // moving parent outside margins triggers change notifiers + control.parent.x = -50 + compare(control.x, 50 + control.leftMargin) + compare(xSpy.count, 3) + compare(ySpy.count, 2) + + control.parent.y = -60 + compare(control.y, 60 + control.topMargin) + compare(xSpy.count, 3) + compare(ySpy.count, 3) + control.destroy() } @@ -953,6 +971,7 @@ TestCase { property alias modalPopup: modalPopup property alias modelessPopup: modelessPopup property alias plainPopup: plainPopup + property alias modalPopupWithoutDim: modalPopupWithoutDim visible: true Drawer { z: 5 @@ -984,6 +1003,13 @@ TestCase { enter: Transition { PauseAnimation { duration: 200 } } exit: Transition { PauseAnimation { duration: 200 } } } + Popup { + id: modalPopupWithoutDim + z: 5 + dim: false + modal: true + exit: Transition { PauseAnimation { duration: 200 } } + } } } @@ -1049,6 +1075,16 @@ TestCase { compare(window.overlay.modal.opacity, 0.0) compare(window.overlay.modeless.opacity, 0.0) + window.modalPopupWithoutDim.open() + tryCompare(window.modalPopupWithoutDim, "visible", true) + compare(window.overlay.modal.opacity, 0.0) + compare(window.overlay.modeless.opacity, 0.0) + + window.modalPopupWithoutDim.close() + tryCompare(window.modalPopupWithoutDim, "visible", false) + compare(window.overlay.modal.opacity, 0.0) + compare(window.overlay.modeless.opacity, 0.0) + window.upperDrawer.open() compare(window.overlay.modal.z, 1.0) tryCompare(window.overlay.modal, "opacity", 1.0) diff --git a/tests/auto/controls/data/tst_stackview.qml b/tests/auto/controls/data/tst_stackview.qml index d8e1e722..9966fa47 100644 --- a/tests/auto/controls/data/tst_stackview.qml +++ b/tests/auto/controls/data/tst_stackview.qml @@ -243,10 +243,31 @@ TestCase { verify(container) var control = stackView.createObject(container, {width: 100, height: 100}) verify(control) + container.width += 10 container.height += 20 compare(control.width, 100) compare(control.height, 100) + + control.push(item, StackView.Immediate) + compare(item.width, control.width) + compare(item.height, control.height) + + control.width = 200 + control.height = 200 + compare(item.width, control.width) + compare(item.height, control.height) + + control.clear() + control.width += 10 + control.height += 20 + verify(item.width !== control.width) + verify(item.height !== control.height) + + control.push(item, StackView.Immediate) + compare(item.width, control.width) + compare(item.height, control.height) + container.destroy() } diff --git a/tests/auto/focus/tst_focus.cpp b/tests/auto/focus/tst_focus.cpp index 6c184851..2c9573c6 100644 --- a/tests/auto/focus/tst_focus.cpp +++ b/tests/auto/focus/tst_focus.cpp @@ -228,7 +228,7 @@ void tst_focus::reason() QEXPECT_FAIL("TextField", "TODO: TextField::visualFocus?", Continue); QCOMPARE(control->property("visualFocus"), QVariant(false)); - window->contentItem()->forceActiveFocus(Qt::TabFocusReason); + window->contentItem()->setFocus(false, Qt::TabFocusReason); QVERIFY(!control->hasActiveFocus()); QCOMPARE(control->property("focusReason").toInt(), int(Qt::TabFocusReason)); diff --git a/tests/auto/material/data/tst_material.qml b/tests/auto/material/data/tst_material.qml index 25b4ec98..5d98a707 100644 --- a/tests/auto/material/data/tst_material.qml +++ b/tests/auto/material/data/tst_material.qml @@ -183,6 +183,7 @@ TestCase { control.Material.foreground = Material.Blue control.Material.theme = Material.Dark compare(control.Material.primary, Material.color(Material.Green)) + expectFail("", "QTBUG-53556") compare(control.Material.accent, Material.color(Material.Brown)) compare(control.Material.background, Material.color(Material.Red)) compare(control.Material.foreground, Material.color(Material.Blue)) @@ -194,6 +195,7 @@ TestCase { var control = styledButton.createObject(testCase) verify(control) compare(control.Material.primary, Material.color(Material.DeepOrange)) + expectFail("", "QTBUG-53556") compare(control.Material.accent, Material.color(Material.DeepPurple)) compare(control.Material.background, Material.color(Material.Green)) compare(control.Material.foreground, Material.color(Material.Blue)) @@ -250,6 +252,8 @@ TestCase { var grandChild1 = button.createObject(child1) var grandChild2 = button.createObject(child2) + if (data.tag == "primary" || data.tag == "accent") + expectFail("", "QTBUG-53556") compare(grandChild1.Material[prop], child1.Material[prop]) compare(grandChild2.Material[prop], child2.Material[prop]) @@ -396,6 +400,7 @@ TestCase { compare(container.menu.Material.primary, Material.color(Material.Blue)) compare(child.Material.primary, Material.color(Material.Blue)) compare(container.Material.accent, Material.color(Material.Red)) + expectFail("", "QTBUG-53556") compare(container.menu.Material.accent, Material.color(Material.Red)) compare(child.Material.accent, Material.color(Material.Red)) container.destroy() @@ -421,11 +426,31 @@ TestCase { compare(window.combo.Material.primary, Material.color(Material.Blue)) compare(child.Material.primary, Material.color(Material.Blue)) compare(window.Material.accent, Material.color(Material.Red)) + expectFail("", "QTBUG-53556") compare(window.combo.Material.accent, Material.color(Material.Red)) compare(child.Material.accent, Material.color(Material.Red)) window.destroy() } + function test_windowChange() { + var ldr = loader.createObject() + verify(ldr) + + var wnd = window.createObject() + verify(wnd) + + wnd.Material.theme = Material.Dark + compare(wnd.Material.theme, Material.Dark) + + ldr.active = true + verify(ldr.item) + compare(ldr.item.Material.theme, Material.Light) + + ldr.parent = wnd.contentItem + compare(ldr.item.Material.theme, Material.Dark) + + wnd.destroy() + } function test_colors_data() { return [ diff --git a/tests/auto/menu/tst_menu.cpp b/tests/auto/menu/tst_menu.cpp index 0d72814c..dc9c296a 100644 --- a/tests/auto/menu/tst_menu.cpp +++ b/tests/auto/menu/tst_menu.cpp @@ -261,11 +261,15 @@ void tst_menu::addItem() QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); QVERIFY(menu); menu->open(); + QVERIFY(menu->isVisible()); QQuickItem *menuItem = menu->itemAt(0); + QVERIFY(menuItem); + QTRY_VERIFY(!QQuickItemPrivate::get(menuItem)->culled); // QTBUG-53262 + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, menuItem->mapToScene(QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint()); - QVERIFY(!menu->isVisible()); + QTRY_VERIFY(!menu->isVisible()); } QTEST_MAIN(tst_menu) diff --git a/tests/auto/popup/data/activeFocusOnClose1.qml b/tests/auto/popup/data/activeFocusOnClose1.qml new file mode 100644 index 00000000..e1a4cec2 --- /dev/null +++ b/tests/auto/popup/data/activeFocusOnClose1.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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:BSD$ +** 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.6 +import QtQuick.Controls 2.0 + +ApplicationWindow { + width: 400 + height: 400 + + property alias focusedPopup: focusedPopup + property alias nonFocusedPopup: nonFocusedPopup + + Popup { + id: focusedPopup + focus: true + } + + Popup { + id: nonFocusedPopup + } +} diff --git a/tests/auto/popup/data/activeFocusOnClose2.qml b/tests/auto/popup/data/activeFocusOnClose2.qml new file mode 100644 index 00000000..9418d521 --- /dev/null +++ b/tests/auto/popup/data/activeFocusOnClose2.qml @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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:BSD$ +** 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.6 +import QtQuick.Controls 2.0 + +ApplicationWindow { + width: 400 + height: 400 + + property alias popup1: popup1 + property alias popup2: popup2 + property alias closePopup2Button: closePopup2Button + + Popup { + id: popup1 + focus: true + } + + Popup { + id: popup2 + focus: true + + Button { + id: closePopup2Button + onClicked: { + popup1.contentItem.forceActiveFocus(); + popup2.close(); + } + } + } +} diff --git a/tests/auto/popup/tst_popup.cpp b/tests/auto/popup/tst_popup.cpp index fe0717d2..97cbb474 100644 --- a/tests/auto/popup/tst_popup.cpp +++ b/tests/auto/popup/tst_popup.cpp @@ -56,6 +56,8 @@ private slots: void windowChange(); void closePolicy_data(); void closePolicy(); + void activeFocusOnClose1(); + void activeFocusOnClose2(); }; void tst_popup::visible() @@ -247,6 +249,70 @@ void tst_popup::closePolicy() QVERIFY(popup->isVisible()); } +void tst_popup::activeFocusOnClose1() +{ + // Test that a popup that never sets focus: true (e.g. ToolTip) doesn't affect + // the active focus item when it closes. + QQuickApplicationHelper helper(this, QStringLiteral("activeFocusOnClose1.qml")); + QQuickApplicationWindow *window = helper.window; + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickPopup *focusedPopup = helper.window->property("focusedPopup").value<QQuickPopup*>(); + QVERIFY(focusedPopup); + + QQuickPopup *nonFocusedPopup = helper.window->property("nonFocusedPopup").value<QQuickPopup*>(); + QVERIFY(nonFocusedPopup); + + focusedPopup->open(); + QVERIFY(focusedPopup->isVisible()); + QVERIFY(focusedPopup->hasActiveFocus()); + + nonFocusedPopup->open(); + QVERIFY(nonFocusedPopup->isVisible()); + QVERIFY(focusedPopup->hasActiveFocus()); + + nonFocusedPopup->close(); + QVERIFY(!nonFocusedPopup->isVisible()); + QVERIFY(focusedPopup->hasActiveFocus()); +} + +void tst_popup::activeFocusOnClose2() +{ + // Test that a popup that sets focus: true but relinquishes focus (e.g. by + // calling forceActiveFocus() on another item) before it closes doesn't + // affect the active focus item when it closes. + QQuickApplicationHelper helper(this, QStringLiteral("activeFocusOnClose2.qml")); + QQuickApplicationWindow *window = helper.window; + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickPopup *popup1 = helper.window->property("popup1").value<QQuickPopup*>(); + QVERIFY(popup1); + + QQuickPopup *popup2 = helper.window->property("popup2").value<QQuickPopup*>(); + QVERIFY(popup2); + + QQuickButton *closePopup2Button = helper.window->property("closePopup2Button").value<QQuickButton*>(); + QVERIFY(closePopup2Button); + + popup1->open(); + QVERIFY(popup1->isVisible()); + QVERIFY(popup1->hasActiveFocus()); + + popup2->open(); + QVERIFY(popup2->isVisible()); + QVERIFY(popup2->hasActiveFocus()); + + // Causes popup1.contentItem.forceActiveFocus() to be called, then closes popup2. + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, + closePopup2Button->mapToScene(QPointF(closePopup2Button->width() / 2, closePopup2Button->height() / 2)).toPoint()); + QVERIFY(!popup2->isVisible()); + QVERIFY(popup1->hasActiveFocus()); +} + QTEST_MAIN(tst_popup) #include "tst_popup.moc" diff --git a/tests/auto/snippets/tst_snippets.cpp b/tests/auto/snippets/tst_snippets.cpp index cc473a3d..fb581b90 100644 --- a/tests/auto/snippets/tst_snippets.cpp +++ b/tests/auto/snippets/tst_snippets.cpp @@ -64,7 +64,7 @@ void tst_Snippets::initTestCase() qInfo() << datadir; - QDirIterator it(datadir, QStringList() << "qtquick*-custom.qml" << "qtlabs-custom*.qml", QDir::Files | QDir::Readable, QDirIterator::Subdirectories); + QDirIterator it(datadir, QStringList() << "qtquick*.qml" << "qtlabs*.qml", QDir::Files | QDir::Readable, QDirIterator::Subdirectories); while (it.hasNext()) { QFileInfo fi(it.next()); filePaths.insert(fi.baseName(), qMakePair(fi.filePath(), outdir.filePath(fi.baseName() + ".png"))); diff --git a/tests/auto/universal/data/tst_universal.qml b/tests/auto/universal/data/tst_universal.qml index a88f2c49..0bc0d09d 100644 --- a/tests/auto/universal/data/tst_universal.qml +++ b/tests/auto/universal/data/tst_universal.qml @@ -318,6 +318,26 @@ TestCase { window.destroy() } + function test_windowChange() { + var ldr = loader.createObject() + verify(ldr) + + var wnd = window.createObject() + verify(wnd) + + wnd.Universal.theme = Universal.Dark + compare(wnd.Universal.theme, Universal.Dark) + + ldr.active = true + verify(ldr.item) + compare(ldr.item.Universal.theme, Universal.Light) + + ldr.parent = wnd.contentItem + compare(ldr.item.Universal.theme, Universal.Dark) + + wnd.destroy() + } + function test_colors_data() { return [ { tag: "accent" }, { tag: "background" }, { tag: "foreground" } diff --git a/tests/manual/testbench/main.qml b/tests/manual/testbench/main.qml index 492dddc4..bbeb795b 100644 --- a/tests/manual/testbench/main.qml +++ b/tests/manual/testbench/main.qml @@ -48,6 +48,8 @@ import QtQuick.Controls.Universal 2.0 ApplicationWindow { id: window visible: true + x: Screen.width / 2 - width / 2 + y: Screen.height / 2 - height / 2 width: 750 height: 1000 |