diff --git a/resources/qml/Menus/ContextMenu.qml b/resources/qml/Menus/ContextMenu.qml index 4ca51c0974..aeb6eb47f9 100644 --- a/resources/qml/Menus/ContextMenu.qml +++ b/resources/qml/Menus/ContextMenu.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Ultimaker B.V. +// Copyright (c) 2022 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -120,9 +120,10 @@ Menu anchors.verticalCenter: copiesField.verticalCenter } - SpinBox + Cura.SpinBox { id: copiesField + editable: true focus: true from: 1 to: 99 diff --git a/resources/qml/Preferences/Materials/MaterialsView.qml b/resources/qml/Preferences/Materials/MaterialsView.qml index d1ea251ab8..6511812057 100644 --- a/resources/qml/Preferences/Materials/MaterialsView.qml +++ b/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 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 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: { @@ -423,12 +389,6 @@ Item Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } } - - function updateCostPerMeter() - { - base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value); - base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value); - } } ListView @@ -465,7 +425,7 @@ Item elide: Text.ElideRight verticalAlignment: Qt.AlignVCenter } - ReadOnlySpinBox + Cura.SpinBox { id: spinBox anchors.left: label.right @@ -489,9 +449,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) @@ -641,4 +600,10 @@ Item base.setMetaDataEntry("brand", old_brand, new_brand) properties.brand = new_brand } + + function updateCostPerMeter() + { + base.spoolLength = calculateSpoolLength(diameterSpinBox.value, densitySpinBox.value, spoolWeightSpinBox.value); + base.costPerMeter = calculateCostPerMeter(spoolCostSpinBox.value); + } } diff --git a/resources/qml/Preferences/ReadOnlySpinBox.qml b/resources/qml/Preferences/ReadOnlySpinBox.qml deleted file mode 100644 index 11e47b38b2..0000000000 --- a/resources/qml/Preferences/ReadOnlySpinBox.qml +++ /dev/null @@ -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 } -} diff --git a/resources/qml/SpinBox.qml b/resources/qml/SpinBox.qml new file mode 100644 index 0000000000..7f30109380 --- /dev/null +++ b/resources/qml/SpinBox.qml @@ -0,0 +1,85 @@ +// 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 + +// This component extends the funtionality of QtControls 2.x Spinboxes to +// - be able to contain fractional values +// - hava a "prefix" and a "suffix". A validator is added that recognizes this pre-, suf-fix combo. When adding a custom +// validator the pre-, suf-fix should be added (e.g. new RegExp("^" + prefix + \regex\ + suffix + "$") + +Item +{ + id: base + + height: spinBox.height + + property string prefix: "" + property string suffix: "" + property int decimals: 0 + property real stepSize: 1 + property real value: 0 + property real from: 0 + property real to: 99 + + property alias wrap: spinBox.wrap + + property bool editable: true + + property var validator: RegExpValidator + { + regExp: new RegExp("^" + prefix + "([0-9]+[.|,]?[0-9]*)?" + suffix + "$") + } + + signal editingFinished() + + SpinBox + { + id: spinBox + anchors.fill: base + editable: base.editable + + // The stepSize of the SpinBox is intentionally set to be always `1` + // As SpinBoxes can only contain integer values the `base.stepSize` is concidered the precision/resolution + // increasing the spinBox.value by one increases the actual/real value of the component by `base.stepSize` + // as such spinBox.value * base.stepSizes produces the real value of the component + stepSize: 1 + value: Math.floor(base.value / base.stepSize) + from: Math.floor(base.from / base.stepSize) + to: Math.floor(base.to / base.stepSize) + + valueFromText: function(text) + { + return parseFloat(text.substring(prefix.length, text.length - suffix.length).replace(",", ".")) / base.stepSize; + } + + textFromValue: function(value) + { + return prefix + (value * base.stepSize).toFixed(decimals) + suffix; + } + + validator: base.validator + + onValueModified: + { + base.value = value * base.stepSize; + } + + contentItem: TextField + { + text: spinBox.textFromValue(spinBox.value, spinBox.locale) + selectByMouse: base.editable + background: Item {} + validator: base.validator + + onActiveFocusChanged: + { + if(!activeFocus) + { + base.editingFinished(); + } + } + } + } +}