Browse Source

Make `SpinBox` a reusable component

Forgot to update Readonly `SpinBox`es to Qt 2 when implementing Cura
8684. As the spinbox is used in various places with the same
functionality it made sense to create a reusable component.

There is still a feature gap in the implementation; The `SpinBox`es
from QtControls 2.x value is defined as an integer. For some use-cases
we do require a fractional value in the `SpinBox`. The only two places
where this is required are the `material_diameter` and
`material_density` fields in the material prefference page.

Cura 8684
casper 3 years ago
parent
commit
1746e24dd9

+ 16 - 51
resources/qml/Preferences/Materials/MaterialsView.qml

@@ -234,30 +234,31 @@ Item
             Label { width: parent.width; height: parent.rowHeight; font.bold: true; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Properties") }
 
             Label { width: informationPage.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Density") }
-            ReadOnlySpinBox
+
+            Cura.SpinBox
             {
+                enabled: base.editingEnabled
                 id: densitySpinBox
                 width: informationPage.columnWidth
                 value: properties.density
                 decimals: 2
                 suffix: " g/cm³"
-                stepSize: 0.01
-                readOnly: !base.editingEnabled
+                stepSize: 0.01 // spinboxes can only cointain reals, a non-integer value can not be entered as the step size
 
                 onEditingFinished: base.setMetaDataEntry("properties/density", properties.density, value)
                 onValueChanged: updateCostPerMeter()
             }
 
             Label { width: informationPage.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Diameter") }
-            ReadOnlySpinBox
+            Cura.SpinBox
             {
+                enabled: base.editingEnabled
                 id: diameterSpinBox
                 width: informationPage.columnWidth
                 value: properties.diameter
                 decimals: 2
                 suffix: " mm"
-                stepSize: 0.01
-                readOnly: !base.editingEnabled
+                stepSize: 0.01 // spinboxes can only cointain reals, a non-integer value can not be entered as the step size
 
                 onEditingFinished:
                 {
@@ -283,44 +284,26 @@ Item
             }
 
             Label { width: informationPage.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament Cost") }
-            SpinBox
+
+            Cura.SpinBox
             {
                 id: spoolCostSpinBox
                 width: informationPage.columnWidth
                 value: base.getMaterialPreferenceValue(properties.guid, "spool_cost")
                 to: 100000000
                 editable: true
-
-                contentItem: TextField
-                {
-                    text: spoolCostSpinBox.textFromValue(spoolCostSpinBox.value, spoolCostSpinBox.locale)
-                    selectByMouse: true
-                    background: Item {}
-                    validator: RegExpValidator { regExp: new RegExp("^" + base.currency + " ([0-9]+[.]?[0-9]*)?$") }
-                }
-
-                property int decimals: 2
-
-                valueFromText: function(text) {
-                    // remove all non-number tokens from input string so value can be parsed correctly
-                    var value = Number(text.replace(",", ".").replace(/[^0-9.]+/g, ""));
-                    var precision = Math.pow(10, spoolCostSpinBox.decimals);
-                    return Math.round(value * precision) / precision;
-                }
-
-                textFromValue: function(value) {
-                    return base.currency + " " + value.toFixed(spoolCostSpinBox.decimals)
-                }
+                prefix: base.currency + " "
+                decimals: 2
 
                 onValueChanged:
                 {
-                    base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value, decimals))
+                    base.setMaterialPreferenceValue(properties.guid, "spool_cost", parseFloat(value))
                     updateCostPerMeter()
                 }
             }
 
             Label { width: informationPage.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Filament weight") }
-            SpinBox
+            Cura.SpinBox
             {
                 id: spoolWeightSpinBox
                 width: informationPage.columnWidth
@@ -328,24 +311,7 @@ Item
                 stepSize: 100
                 to: 10000
                 editable: true
-
-                contentItem: TextField
-                {
-                    text: spoolWeightSpinBox.textFromValue(spoolWeightSpinBox.value, spoolWeightSpinBox.locale)
-                    selectByMouse: true
-                    background: Item {}
-                    validator: RegExpValidator { regExp: new RegExp("^([0-9]+[.]?[0-9]*)? g$") }
-                }
-
-                valueFromText: function(text, locale) {
-                    // remove all non-number tokens from input string so value can be parsed correctly
-                    var value = Number(text.replace(",", ".").replace(/[^0-9.]+/g, ""));
-                    return Math.round(value);
-                }
-
-                textFromValue: function(value, locale) {
-                    return value + " g"
-                }
+                suffix: " g"
 
                 onValueChanged:
                 {
@@ -465,7 +431,7 @@ Item
                 elide: Text.ElideRight
                 verticalAlignment: Qt.AlignVCenter
             }
-            ReadOnlySpinBox
+            Cura.SpinBox
             {
                 id: spinBox
                 anchors.left: label.right
@@ -489,9 +455,8 @@ Item
                     return 0;
                 }
                 width: base.secondColumnWidth
-                readOnly: !base.editingEnabled
                 suffix: " " + model.unit
-                maximumValue: 99999
+                to: 99999
                 decimals: model.unit == "mm" ? 2 : 0
 
                 onEditingFinished: materialPropertyProvider.setPropertyValue("value", value)

+ 0 - 54
resources/qml/Preferences/ReadOnlySpinBox.qml

@@ -1,54 +0,0 @@
-// Copyright (c) 2016 Ultimaker B.V.
-// Cura is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.1
-import QtQuick.Controls 1.1
-import QtQuick.Dialogs 1.2
-
-Item
-{
-    id: base
-
-    property alias value: spinBox.value
-    property alias minimumValue: spinBox.minimumValue
-    property alias maximumValue: spinBox.maximumValue
-    property alias stepSize: spinBox.stepSize
-    property alias prefix: spinBox.prefix
-    property alias suffix: spinBox.suffix
-    property alias decimals: spinBox.decimals
-
-    signal editingFinished();
-
-    property bool readOnly: false
-
-    width: spinBox.width
-    height: spinBox.height
-
-    SpinBox
-    {
-        id: spinBox
-
-        enabled: !base.readOnly
-        opacity: base.readOnly ? 0.5 : 1.0
-
-        anchors.fill: parent
-
-        onEditingFinished: base.editingFinished()
-        Keys.onEnterPressed: spinBox.focus = false
-        Keys.onReturnPressed: spinBox.focus = false
-    }
-
-    Label
-    {
-        visible: base.readOnly
-        text: base.prefix + base.value.toFixed(spinBox.decimals) + base.suffix
-
-        anchors.verticalCenter: parent.verticalCenter
-        anchors.left: parent.left
-        anchors.leftMargin: spinBox.__style ? spinBox.__style.padding.left : 0
-
-        color: palette.buttonText
-    }
-
-    SystemPalette { id: palette }
-}

+ 47 - 0
resources/qml/SpinBox.qml

@@ -0,0 +1,47 @@
+// Copyright (c) 2022 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.15
+
+SpinBox
+{
+    id: base
+
+    property string prefix: ""
+    property string suffix: ""
+    property int decimals: 0
+
+    signal editingFinished()
+
+    valueFromText: function(text)
+    {
+        return parseFloat(text.substring(prefix.length, text.length - suffix.length), decimals);
+    }
+
+    textFromValue: function(value)
+    {
+        return prefix + value.toFixed(decimals) + suffix
+    }
+
+    validator: RegExpValidator
+    {
+        regExp: new RegExp("^" + prefix + "([0-9]+[.|,]?[0-9]*)?" + suffix + "$")
+    }
+
+    contentItem: TextField
+    {
+        text: base.textFromValue(base.value, base.locale)
+        selectByMouse: true
+        background: Item {}
+        validator: base.validator
+
+        onActiveFocusChanged:
+        {
+            if(!activeFocus)
+            {
+                base.editingFinished()
+            }
+        }
+    }
+}