From 77d1dcca1b43ea38d7a6e58206d06004b77a8103 Mon Sep 17 00:00:00 2001 From: Caroline Chao <caroline.chao@digia.com> Date: Tue, 12 Feb 2013 17:12:28 +0100 Subject: [PATCH] SpinBox: Refactoring API Clean the SpinBox API Add new property decimals. Add missing documentation. Update autotests and manual test for SpinBox. Change-Id: Ia977ab5c142095a0dbb0ddc452b0dc77d7c133f8 Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com> --- src/qtdesktop/SpinBox.qml | 184 +++++++++----------- src/styles/Desktop/SpinBoxStyle.qml | 10 +- src/styles/SpinBoxStyle.qml | 8 +- tests/auto/qtdesktop/data/tst_spinbox.qml | 92 ++++++++-- tests/manual/controls/pages/SpinBoxPage.qml | 55 ++++-- tests/manual/controls/shared/SetupField.qml | 2 +- 6 files changed, 206 insertions(+), 145 deletions(-) diff --git a/src/qtdesktop/SpinBox.qml b/src/qtdesktop/SpinBox.qml index b98ce6d79..e8adce999 100644 --- a/src/qtdesktop/SpinBox.qml +++ b/src/qtdesktop/SpinBox.qml @@ -51,14 +51,20 @@ import "Styles/Settings.js" as Settings SpinBox allows the user to choose a value by clicking the up/down buttons or pressing up/down on the keyboard to increase/decrease the value currently displayed. The user can also type the value in manually. - By default the SpinBox provides discrete values in the range [0-99] with a stepSize of 1.0. + By default the SpinBox provides discrete values in the range [0-99] with a \l stepSize of 1 and 0 \l decimals. \code SpinBox { id: spinbox - minimumValue: 0 - maximumValue: 20 - stepSize: 1.0 + } + \endcode + + Note that if you require decimal values you will need to set the \l decimals to a non 0 value. + + \code + SpinBox { + id: spinbox + decimals: 2 } \endcode @@ -93,66 +99,81 @@ FocusScope { /*! The amount by which the \l value is incremented/decremented when a spin button is pressed. - */ - property real singleStep: 1.0 - - /*! - \qmlproperty string SpinBox::inputMask - The input mask for the text input. See \l TextInput + The default value is 1.0. */ - property alias inputMask: input.inputMask + property real stepSize: 1.0 - /*! - The suffix for the text content. - */ + /*! The suffix for the value. I.e "cm" */ property string suffix - //property string prefix ### not implemented - - /*! \internal */ - property var styleHints:[] - /*! - This property indicates if the up/increment button is currently enabled. - */ - readonly property bool upEnabled: value != maximumValue; + /*! The prefix for the value. I.e "$" */ + property string prefix - /*! - This property indicates if the down/decrement button is currently enabled. + /*! This property indicates the amount of decimals. + Note that if you enter more decimals than specified, they will + be truncated to the specified amount of decimal places. + The default value is \c 0 */ - readonly property bool downEnabled: value != minimumValue; + property int decimals: 0 - /*! - \qmlproperty bool SpinBox::upPressed + /*! \qmlproperty font SpinBox::font - This property indicates if the up/increment button is currently being pressed. + This property indicates the current font used by the SpinBox. */ - readonly property alias upPressed: mouseUp.pressed + property alias font: input.font - /*! - \qmlproperty bool SpinBox::downPressed - This property indicates if the down/decrement button is currently being pressed. - */ - readonly property alias downPressed: mouseDown.pressed + /*! \internal */ + property Component style: Qt.createComponent(Settings.THEME_PATH + "/SpinBoxStyle.qml", spinbox) - // These are currently only needed for styling + /*! \internal */ + function __increment() { + input.setValue(input.text) + value += stepSize + if (value > maximumValue) + value = maximumValue + input.text = value.toFixed(decimals) + } + /*! \internal */ + function __decrement() { + input.setValue(input.text) + value -= stepSize + if (value < minimumValue) + value = minimumValue + input.text = value.toFixed(decimals) + } + + /*! \internal */ + readonly property bool __upEnabled: value != maximumValue; + /*! \internal */ + readonly property bool __downEnabled: value != minimumValue; + /*! \internal */ + readonly property alias __upPressed: mouseUp.pressed + /*! \internal */ + readonly property alias __downPressed: mouseDown.pressed + /*! \internal */ + property var styleHints:[] /*! \internal */ property alias __upHovered: mouseUp.containsMouse /*! \internal */ property alias __downHovered: mouseDown.containsMouse /*! \internal */ property alias __containsMouse: mouseArea.containsMouse - - /*! \qmlproperty font SpinBox::font - - This property indicates the current font used by the SpinBox. - */ - property alias font: input.font + /*! \internal */ + property alias __text: input.text /*! \internal */ - property Component style: Qt.createComponent(Settings.THEME_PATH + "/SpinBoxStyle.qml", spinbox) + onDecimalsChanged: input.setValue(value) + /*! \internal */ + onMaximumValueChanged: input.setValue(value) + /*! \internal */ + onMinimumValueChanged: input.setValue(value) + /*! \internal */ + Component.onCompleted: input.setValue(value) + /*! \internal */ + onValueChanged: input.setValue(value) Accessible.name: input.text Accessible.role: Accessible.SpinBox @@ -163,54 +184,6 @@ FocusScope { implicitWidth: loader.item ? loader.item.implicitWidth : 0 implicitHeight: loader.item ? loader.item.implicitHeight : 0 - /*! - Increments \l value by \l singleStep, clamping to \l maximumValue - if the new value is too large. - */ - function increment() { - setValue(input.text) - value += singleStep - if (value > maximumValue) - value = maximumValue - input.text = value - } - - /*! - Increments \l value by \l singleStep, clamping to \l minimumValue - if the new value is too small. - */ - function decrement() { - setValue(input.text) - value -= singleStep - if (value < minimumValue) - value = minimumValue - input.text = value - } - - /*! - Sets \l value to \a v, clamping to \l minimumValue and \l maximumValue - if \a v is not within this range. - */ - function setValue(v) { - var newval = parseFloat(v) - if (newval > maximumValue) - newval = maximumValue - else if (v < minimumValue) - newval = minimumValue - value = newval - input.text = value - } - - /*! \internal */ - Component.onCompleted: setValue(value) - - /*! \internal */ - onValueChanged: { - input.valueUpdate = true - input.text = value - input.valueUpdate = false - } - Loader { id: loader property alias control: spinbox @@ -224,12 +197,25 @@ FocusScope { hoverEnabled: true } - // Spinbox input field - TextInput { id: input - property bool valueUpdate: false + function setValue(v) { + var newval = parseFloat(v) + + if (!isNaN(newval)) { + if (newval > maximumValue) + newval = maximumValue + else if (v < minimumValue) + newval = minimumValue + newval = newval.toFixed(decimals) + spinbox.value = parseFloat(newval) + input.text = newval + } else { + input.text = parseFloat(spinbox.value) + } + } + property Item styleItem: loader.item clip: true @@ -243,8 +229,8 @@ FocusScope { anchors.bottomMargin: styleItem ? styleItem.bottomMargin: 0 selectByMouse: true - // validator: DoubleValidator { bottom: minimumValue; top: maximumValue; } - onAccepted: {setValue(input.text)} + validator: DoubleValidator { bottom: minimumValue; top: maximumValue; } + onAccepted: setValue(input.text) onActiveFocusChanged: setValue(input.text) color: loader.item ? loader.item.foregroundColor : "black" selectionColor: loader.item ? loader.item.selectionColor : "black" @@ -278,7 +264,7 @@ FocusScope { width: upRect ? upRect.width : 0 height: upRect ? upRect.height : 0 - onClicked: increment() + onClicked: __increment() property bool autoincrement: false; onReleased: autoincrement = false @@ -292,7 +278,7 @@ FocusScope { id: mouseDown hoverEnabled: true - onClicked: decrement() + onClicked: __decrement() property var downRect: loader.item ? loader.item.downRect : null anchors.left: parent.left @@ -310,6 +296,6 @@ FocusScope { Timer { running: mouseDown.autoincrement; interval: 60 ; repeat: true ; onTriggered: decrement() } } - Keys.onUpPressed: increment() - Keys.onDownPressed: decrement() + Keys.onUpPressed: __increment() + Keys.onDownPressed: __decrement() } diff --git a/src/styles/Desktop/SpinBoxStyle.qml b/src/styles/Desktop/SpinBoxStyle.qml index 31ff0a6ab..dd372c855 100644 --- a/src/styles/Desktop/SpinBoxStyle.qml +++ b/src/styles/Desktop/SpinBoxStyle.qml @@ -111,15 +111,15 @@ Item { id: styleitem elementType: "spinbox" anchors.fill: parent - sunken: (downEnabled && downPressed) | (upEnabled && upPressed) + sunken: (control.__downEnabled && control.__downPressed) || (control.__upEnabled && control.__upPressed) hover: __containsMouse hints: control.styleHints hasFocus: control.focus enabled: control.enabled - value: (upPressed ? 1 : 0) | - (downPressed == 1 ? 1<<1 : 0) | - (upEnabled ? (1<<2) : 0) | - (downEnabled == 1 ? (1<<3) : 0) + value: (control.__upPressed ? 1 : 0) | + (control.__downPressed == 1 ? 1<<1 : 0) | + (control.__upEnabled ? (1<<2) : 0) | + (control.__downEnabled == 1 ? (1<<3) : 0) contentWidth: 200 contentHeight: 25 } diff --git a/src/styles/SpinBoxStyle.qml b/src/styles/SpinBoxStyle.qml index 5b3c2f9be..e08025786 100644 --- a/src/styles/SpinBoxStyle.qml +++ b/src/styles/SpinBoxStyle.qml @@ -75,8 +75,8 @@ Item { anchors.centerIn: parent implicitWidth: 12 gradient: Gradient { - GradientStop {color: control.upPressed ? "lightgray" : "white" ; position: 0} - GradientStop {color: control.upPressed ? "lightgray" : "lightgray" ; position: 1} + GradientStop {color: control.__upPressed ? "lightgray" : "white" ; position: 0} + GradientStop {color: control.__upPressed ? "lightgray" : "lightgray" ; position: 1} } border.color: Qt.darker(backgroundColor, 2) Image { @@ -88,8 +88,8 @@ Item { property Component downControl: Rectangle { implicitWidth: 12 gradient: Gradient { - GradientStop {color: control.downPressed ? "lightgray" : "white" ; position: 0} - GradientStop {color: control.downPressed ? "lightgray" : "lightgray" ; position: 1} + GradientStop {color: control.__downPressed ? "lightgray" : "white" ; position: 0} + GradientStop {color: control.__downPressed ? "lightgray" : "lightgray" ; position: 1} } border.color: Qt.darker(backgroundColor, 2) Image { diff --git a/tests/auto/qtdesktop/data/tst_spinbox.qml b/tests/auto/qtdesktop/data/tst_spinbox.qml index 058bec87e..4299b1b5b 100644 --- a/tests/auto/qtdesktop/data/tst_spinbox.qml +++ b/tests/auto/qtdesktop/data/tst_spinbox.qml @@ -60,7 +60,7 @@ Item { spinbox.forceActiveFocus() compare(spinbox.maximumValue, 50) - spinbox.setValue(spinbox.maximumValue - 3) + spinbox.value = spinbox.maximumValue - 3 keyPress(Qt.Key_Up) compare(spinbox.value, spinbox.maximumValue - 2) keyPress(Qt.Key_Up) @@ -75,7 +75,7 @@ Item { spinbox.forceActiveFocus() compare(spinbox.minimumValue, 10) - spinbox.setValue(spinbox.minimumValue + 3) + spinbox.value = spinbox.minimumValue + 3 keyPress(Qt.Key_Down) compare(spinbox.value, spinbox.minimumValue + 2) keyPress(Qt.Key_Down) @@ -90,7 +90,7 @@ Item { spinbox.forceActiveFocus() setCoordinates(spinbox) - spinbox.setValue(spinbox.maximumValue - 3) + spinbox.value = spinbox.maximumValue - 3 mouseClick(spinbox, upCoord.x, upCoord.y, Qt.LeftButton) compare(spinbox.value, spinbox.maximumValue - 2) mouseClick(spinbox, upCoord.x, upCoord.y, Qt.LeftButton) @@ -105,7 +105,7 @@ Item { spinbox.forceActiveFocus() setCoordinates(spinbox) - spinbox.setValue(spinbox.minimumValue + 3) + spinbox.value = spinbox.minimumValue + 3 mouseClick(spinbox, downCoord.x, downCoord.y, Qt.LeftButton) compare(spinbox.value, spinbox.minimumValue + 2) mouseClick(spinbox, downCoord.x, downCoord.y, Qt.LeftButton) @@ -141,42 +141,98 @@ Item { function test_maxvalue() { var spinbox = Qt.createQmlObject('import QtDesktop 1.0; SpinBox {}', container, '') - spinbox.setValue(spinbox.maximumValue + 1) + spinbox.value = spinbox.maximumValue + 1 compare(spinbox.value, spinbox.maximumValue) } function test_minvalue() { var spinbox = Qt.createQmlObject('import QtDesktop 1.0; SpinBox {}', container, '') - spinbox.setValue(spinbox.minimumValue - 1) + spinbox.value = spinbox.minimumValue - 1 compare(spinbox.value, spinbox.minimumValue) } - function test_invalidvalue() { + function test_nanvalue() { var spinbox = Qt.createQmlObject('import QtDesktop 1.0; SpinBox {}', container, '') - spinbox.setValue("hello") - compare(spinbox.value.toString().toLowerCase(), "nan") + // It is not possible to set a string to the spinbox value. + // Nan is a valid number though + spinbox.value = NaN + compare(spinbox.value, NaN) + compare(spinbox.__text, "nan") } - function test_negativesinglestep() + function test_decimals() { + var spinbox = Qt.createQmlObject('import QtDesktop 1.0; SpinBox {}', container, '') + + spinbox.decimals = 0 + spinbox.value = 1.00001 + compare(spinbox.value, 1) + compare(spinbox.__text, "1") + + spinbox.decimals = 1 + spinbox.value = 1.00001 + compare(spinbox.value, 1) + compare(spinbox.__text, "1.0") + spinbox.value = 1.1 + compare(spinbox.value, 1.1) + compare(spinbox.__text, "1.1") + + spinbox.decimals = 5 + spinbox.value = 1.00001 + compare(spinbox.value, 1.00001) + compare(spinbox.__text, "1.00001") + + spinbox.decimals = 6 + compare(spinbox.value, 1.00001) + compare(spinbox.__text, "1.000010") + } + + function test_stepsize() { var spinbox = Qt.createQmlObject('import QtDesktop 1.0; SpinBox {}', container, '') spinbox.forceActiveFocus() - spinbox.singleStep = -1 - spinbox.setValue(5) + spinbox.stepSize = 2 + spinbox.value = 10 - compare(spinbox.value, 5) + compare(spinbox.value, 10) + + keyPress(Qt.Key_Up) + compare(spinbox.value, 10 + spinbox.stepSize) var previousValue = spinbox.value + keyPress(Qt.Key_Down) + compare(spinbox.value, previousValue - spinbox.stepSize) + } + + function test_negativeStepSize() + { + var spinbox = Qt.createQmlObject('import QtDesktop 1.0; SpinBox {}', container, '') + spinbox.forceActiveFocus() + + spinbox.minimumValue = -50 + spinbox.maximumValue = 50 + + spinbox.stepSize = -2 + spinbox.value = 5 + + compare(spinbox.value, 5) + keyPress(Qt.Key_Up) + compare(spinbox.value, 5 + spinbox.stepSize) + + var previousValue = spinbox.value + keyPress(Qt.Key_Down) + compare(spinbox.value, previousValue - spinbox.stepSize) + + // test on the edges - expectFailContinue("", "QTCOMPONENTS-1284 - sign of singleStep should be ignored when incrementing value") - compare(spinbox.value, spinbox.value + Math.abs(spinbox.singleStep)) + spinbox.value = -49 keyPress(Qt.Key_Up) + compare(spinbox.value, spinbox.minimumValue) - previousValue = spinbox.value - expectFailContinue("", "QTCOMPONENTS-1284 - sign of singleStep should be ignored when decrementing value") - compare(spinbox.value, previousValue - Math.abs(spinbox.singleStep)) + spinbox.value = 49 + keyPress(Qt.Key_Down) + compare(spinbox.value, spinbox.maximumValue) } function setCoordinates(item) diff --git a/tests/manual/controls/pages/SpinBoxPage.qml b/tests/manual/controls/pages/SpinBoxPage.qml index 0573a621a..32b58c7d2 100644 --- a/tests/manual/controls/pages/SpinBoxPage.qml +++ b/tests/manual/controls/pages/SpinBoxPage.qml @@ -84,9 +84,9 @@ Page { SetupField { id: singleStep - property variant defaultValue: spinbox.singleStep + property variant defaultValue: spinbox.stepSize property string title: "Step" - onValidated: spinbox.singleStep = validatedValue + onValidated: spinbox.stepSize = validatedValue } SetupField { @@ -103,14 +103,7 @@ Page { property string title: "Prefix" property bool isText: true enabled: false // not yet implemented - // onValidated: spinbox.prefix = validatedValue - } - - SetupField { - id: inputmask - property variant defaultValue: spinbox.inputMask - property string title: "inputMask" - onValidated: spinbox.inputMask = validatedValue + onValidated: spinbox.prefix = validatedValue } SetupField { @@ -119,6 +112,32 @@ Page { property string title: "Value" onValidated: spinbox.value = validatedValue } + + SetupField { + id: font + property variant defaultValue: spinbox.font.pixelSize + property string title: "font" + onValidated: spinbox.font.pixelSize = validatedValue + } + + Item { + height: decimalSpinBox.height + width: parent.width + + Label { + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + text: "Decimals" + color: "white" + } + + SpinBox { + id: decimalSpinBox + anchors.right: parent.right + decimals: 0 + maximumValue: 5 + } + } } Column { @@ -141,7 +160,7 @@ Page { } CountField { - id: signalSingleStepChangedCount + id: signalStepSizeChangedCount property string title: "SingleStep" } @@ -173,12 +192,12 @@ Page { BooleanField { title: "UpEnabled" - status: spinbox.upEnabled + status: spinbox.__upEnabled } BooleanField { title: "DownEnabled" - status: spinbox.downEnabled + status: spinbox.__downEnabled } } @@ -188,12 +207,12 @@ Page { BooleanField { title: "UpPressed" - status: spinbox.upPressed + status: spinbox.__upPressed } BooleanField { title: "DownPressed" - status: spinbox.downPressed + status: spinbox.__downPressed } } @@ -201,14 +220,14 @@ Page { id: spinbox width: parent.width + decimals: decimalSpinBox.value onMaximumValueChanged: signalMaximumValueChangedCount.increment() onMinimumValueChanged: signalMinimumValueChangedCount.increment() - onSingleStepChanged: signalSingleStepChangedCount.increment() + onStepSizeChanged: signalStepSizeChangedCount.increment() onSuffixChanged: signalSuffixChangedCount.increment() onValueChanged: signalValueChangedCount.increment() - // onPrefixChanged: signalPrefixChangedCount.increment() // not yet implemented - onInputMaskChanged:signalInputMaskChangedCount.increment() + onPrefixChanged: signalPrefixChangedCount.increment() // not yet implemented } } } diff --git a/tests/manual/controls/shared/SetupField.qml b/tests/manual/controls/shared/SetupField.qml index 658b4f8ee..ea7041b19 100644 --- a/tests/manual/controls/shared/SetupField.qml +++ b/tests/manual/controls/shared/SetupField.qml @@ -58,7 +58,7 @@ FocusScope { anchors.left: parent.left anchors.right: field.left height: field.height - width: 60 + width: 80 verticalAlignment: Text.AlignVCenter color: enabled? "white" : "grey" text: setupField.label + ": " -- GitLab