Index: leahi.qrc =================================================================== diff -u -rd948f4557217f1f0258e027a81e0b939a72fcae6 -r863764371ec0a4569403135975a0a3f44e516163 --- leahi.qrc (.../leahi.qrc) (revision d948f4557217f1f0258e027a81e0b939a72fcae6) +++ leahi.qrc (.../leahi.qrc) (revision 863764371ec0a4569403135975a0a3f44e516163) @@ -164,6 +164,7 @@ sources/gui/qml/components/AlarmButtonRow.qml sources/gui/qml/components/BaseComboBox.qml sources/gui/qml/components/VitalsButton.qml + sources/gui/qml/components/RangedValue.qml sources/gui/qml/compounds/PressureRangeSlider.qml Index: sources/gui/qml/components/RangedValue.qml =================================================================== diff -u --- sources/gui/qml/components/RangedValue.qml (revision 0) +++ sources/gui/qml/components/RangedValue.qml (revision 863764371ec0a4569403135975a0a3f44e516163) @@ -0,0 +1,106 @@ +/*! + * + * Copyright (c) 2021-2026 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file RangedValue.qml + * \author (last) Stephen Quong + * \date (last) 06-Jan-2026 + * \author (original) Stephen Quong + * \date (original) 06-Jan-2026 + * + */ + +import QtQuick 2.12 + +Item { id: _root + objectName : "_rangedValue" + + // fix floating-point precision issue + readonly property real step : _private.calculatePrecisionValue(rawStep) + readonly property real min : rawMin !== undefined ? _private.calculatePrecisionValue(rawMin) : 0 + readonly property real max : rawMax !== undefined ? _private.calculatePrecisionValue(rawMax) : 0 + readonly property real value : rawValue !== undefined ? _private.calculatePrecisionValue(rawValue) : 0 + readonly property bool isValueInRange : (canOff && value == 0) || (value >= min && value <= max) + + readonly property bool canIncrement : value < _private.calculateMaximum() + readonly property bool canDecrement : canOff ? value > 0 : value > _private.calculateMinimum() + + property int precision : 0 + property real rawValue : undefined + property real rawMin : rawValue + property real rawMax : rawValue + property real rawStep : 1 + property bool canOff : false + + function incrementedValue() { + let tValue = value + // if value can be 'off' and value is below the min, then just set value to min + if (canOff && value < min) { + tValue = min + } + else { + let fixedVal = _private.fixedValue(value) + let fixedStep = _private.fixedValue(step) + // if value is not step aligned, then fixedDelta will be amount to next higher step + // otherwise fixedDelta will be a whole step + let fixedDelta = fixedStep - (fixedVal % fixedStep) + tValue = (fixedVal + fixedDelta) / _private.multiplier + // clamp tValue between [min, max] + // e.g. if value is 2 and range is [5, 10], incrementing will return 5 + tValue = Math.max(min, Math.min(max, tValue)) + } + return tValue + } + + function decrementedValue() { + let tValue = value + // if value can be 'off' and value is already at minimum, just set value to 0 + if (canOff && value === min) { + tValue = 0 + } + else { + let fixedVal = _private.fixedValue(value) + let fixedStep = _private.fixedValue(step) + // if value is not step aligned, then fixedDelta will be amount to next lower step + // otherwise fixedDelta will be a whole step + let fixedDelta = fixedVal % fixedStep + tValue = (fixedVal - (fixedDelta > 0 ? fixedDelta : fixedStep)) / _private.multiplier + // clamp tValue between [minimum, maxVal] + // e.g. if value is 13 and range is [5, 10], decrementing will return 10 + tValue = Math.min(max, Math.max(min, tValue)) + } + return tValue + } + + QtObject { id: _private + objectName: "_private" + readonly property int multiplier : Math.pow(10, precision) + + // round the value based on the given precision (not step) + function calculatePrecisionValue(value) { + return Math.round(value * _private.multiplier) / _private.multiplier + } + + // calculate the minimum value rounded up to the next lower step size + function calculateMinimum() { + let fixedMin = _private.fixedValue(min) + let fixedStep = _private.fixedValue(step) + return (Math.ceil(fixedMin / fixedStep) * fixedStep) / _private.multiplier + } + + // calculate the maximum value rounded down to the next higher step size + function calculateMaximum() { + let fixedMax = _private.fixedValue(max) + let fixedStep = _private.fixedValue(step) + return (Math.floor(fixedMax / fixedStep) * fixedStep) / _private.multiplier + } + + // return a fixed point int from the inputted float (using the set precision) + function fixedValue(value) { + return Math.round(value * _private.multiplier) + } + } +} Index: sources/gui/qml/compounds/ValueAdjuster.qml =================================================================== diff -u -r3948dd9dd1189b47bbeedf08c351dece2662d600 -r863764371ec0a4569403135975a0a3f44e516163 --- sources/gui/qml/compounds/ValueAdjuster.qml (.../ValueAdjuster.qml) (revision 3948dd9dd1189b47bbeedf08c351dece2662d600) +++ sources/gui/qml/compounds/ValueAdjuster.qml (.../ValueAdjuster.qml) (revision 863764371ec0a4569403135975a0a3f44e516163) @@ -20,99 +20,19 @@ import QtQuick.Controls 2.2 Item { id: _root - property real decimal : 0 - property real minimum : 0 - property real maximum : 0 - property real value : 0 + property string extraText : "" + property alias value : _rangedValue.rawValue + property alias minimum : _rangedValue.rawMin + property alias maximum : _rangedValue.rawMax + property alias step : _rangedValue.rawStep + property alias decimal : _rangedValue.precision + property alias canOff : _rangedValue.canOff property real defaultValue: 0 - property real step : 0 property bool isActive : false property bool editable : true - property bool canOff : false property bool canRefresh : false property alias textColor : _text.color - QtObject { id: _private - // fix floating-point precision issue - readonly property int multiplier : Math.pow(10, decimal) - readonly property real stepVal : calculatePrecisionValue(step) - readonly property real minVal : calculatePrecisionValue(minimum) - readonly property real maxVal : calculatePrecisionValue(maximum) - readonly property real val : calculatePrecisionValue(value) - - readonly property bool canIncrement : isActive ? val < calculateMaximum() : true - readonly property bool canDecrement : isActive ? canOff ? val > 0 : - val > calculateMinimum() : true - - // round the value based on the given precision (not step) - function calculatePrecisionValue(value) { - return Math.round(value * _private.multiplier) / _private.multiplier - } - - // calculate the minimum value rounded up to the next lower step size - function calculateMinimum() { - let fixedMin = _private.fixedValue(_private.minVal) - let fixedStep = _private.fixedValue(_private.stepVal) - return (Math.ceil(fixedMin / fixedStep) * fixedStep) / _private.multiplier - } - - // calculate the maximum value rounded down to the next higher step size - function calculateMaximum() { - let fixedMax = _private.fixedValue(_private.maxVal) - let fixedStep = _private.fixedValue(_private.stepVal) - return (Math.floor(fixedMax / fixedStep) * fixedStep) / _private.multiplier - } - - // return a fixed point int from the inputted float (using the set precision) - function fixedValue(value) { - return Math.round(value * _private.multiplier) - } - - function increment() { - if ( ! isActive ) { didActiveChange(true); return } - - let tValue = _private.val - // if value can be 'off' and value is below the min, then just set value to min - if (canOff && _private.val < _private.minVal) { - tValue = _private.minVal - } - else { - let fixedVal = _private.fixedValue(_private.val) - let fixedStep = _private.fixedValue(_private.stepVal) - // if value is not step aligned, then fixedDelta will be next higher step, - // otherwise fixedDelta will be a whole step - let fixedDelta = fixedStep - (fixedVal % fixedStep) - tValue = (fixedVal + fixedDelta) / _private.multiplier - // clamp tValue between [minVal, maxVal] - tValue = Math.max(_private.minVal, Math.min(_private.maxVal, tValue)) - } - - didChange(tValue) - } - - function decrement() { - if ( ! isActive ) { didActiveChange(true); return } - - let tValue = _private.val - // if value can be 'off' and value is already at minimum, just set value to 0 - if (canOff && _private.val === _private.minVal) { - tValue = 0 - } - else { - let fixedVal = _private.fixedValue(_private.val) - let fixedStep = _private.fixedValue(_private.stepVal) - let fixedDelta = fixedVal % fixedStep - // if value is not step aligned, decrement to the next lowest step, - // otherwise decrement by a whole step - tValue = (fixedVal - (fixedDelta > 0 ? fixedDelta : fixedStep)) / _private.multiplier - // clamp tValue between [minVal, maxVal] - tValue = Math.min(_private.maxVal, Math.max(_private.minVal, tValue)) - } - - didChange(tValue) - } - } - signal didChange (real vValue) signal didActiveChange (bool vState) @@ -126,13 +46,17 @@ function clear() { didActiveChange(false) } + RangedValue { id: _rangedValue + objectName: "_rangedValue" + } + Text { id: _text anchors.centerIn: parent text : _root.isActive ? _root.canOff ? _root.value === 0 ? qsTr("OFF") : _root.value.toFixed( _root.decimal ) : _root.value.toFixed( _root.decimal ) : Variables.emptyEntry - color : Colors.offWhite + color : _rangedValue.isValueInRange ? Colors.offWhite : Colors.red font.pixelSize : Fonts.fontPixelValueControl } @@ -236,11 +160,11 @@ leftMargin : Variables.defaultMargin } iconSize : Variables.circleButtonDefaultDiameter - enabled : _private.canDecrement + enabled : _rangedValue.canDecrement visible : _root.editable iconImageSource : enabled ? "qrc:/images/iArrowLeft" : "qrc:/images/iArrowLeftDisabled" - onClicked : _private.decrement() + onClicked : { didChange(_rangedValue.decrementedValue()) } } IconButton { id: _rightArrow @@ -250,10 +174,10 @@ rightMargin : Variables.defaultMargin } iconSize : Variables.circleButtonDefaultDiameter - enabled : _private.canIncrement + enabled : _rangedValue.canIncrement visible : _root.editable iconImageSource : enabled ? "qrc:/images/iArrowRight" : "qrc:/images/iArrowRightDisabled" - onClicked : _private.increment() + onClicked : { didChange(_rangedValue.incrementedValue()) } } } Index: sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentSetPoints.qml =================================================================== diff -u -r74f5045bacbaa145905184b727a41b6d9f2c703e -r863764371ec0a4569403135975a0a3f44e516163 --- sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentSetPoints.qml (.../TreatmentAdjustmentSetPoints.qml) (revision 74f5045bacbaa145905184b727a41b6d9f2c703e) +++ sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentSetPoints.qml (.../TreatmentAdjustmentSetPoints.qml) (revision 863764371ec0a4569403135975a0a3f44e516163) @@ -36,15 +36,17 @@ readonly property alias acidConcentrate : _acidConcentrateComboBox.currentIndex readonly property alias bicarbConcentrate : _bicarbConcentrateComboBox.currentIndex + width : 1540 + height : 865 + titleText : qsTr("Treatment Parameters") + QtObject { id: _private objectName: "_private" readonly property int containerWidth : (_root.width - (Variables.defaultMargin * 5))/2 readonly property int titleFontPixelSize : Fonts.fontPixelContainerTitleSmall readonly property int unitFontPixelSize : Fonts.fontPixelContainerUnitSmall } - titleText: qsTr("Treatment Parameters") - onAboutToShow: { _bloodFlowRate.value = vTreatmentParametersSetPoint.bloodFlow _dialysateFlowRate.value = vTreatmentParametersSetPoint.dialysateFlow.toFixed(Variables.dialysateFlowPrecision) Index: sources/gui/qml/pages/treatment/sections/TreatmentFlowsComponent.qml =================================================================== diff -u -r271e773cd388dd98dc1342b7865f9e3e8ba30e90 -r863764371ec0a4569403135975a0a3f44e516163 --- sources/gui/qml/pages/treatment/sections/TreatmentFlowsComponent.qml (.../TreatmentFlowsComponent.qml) (revision 271e773cd388dd98dc1342b7865f9e3e8ba30e90) +++ sources/gui/qml/pages/treatment/sections/TreatmentFlowsComponent.qml (.../TreatmentFlowsComponent.qml) (revision 863764371ec0a4569403135975a0a3f44e516163) @@ -16,11 +16,11 @@ property string title : "" property string unitText : "" property string extraText : "" - property real value : undefined - property real precision : 0 - property real minimum : value - property real maximum : value - property real step : 1 + property alias value : _rangedValue.rawValue + property alias minimum : _rangedValue.rawMin + property alias maximum : _rangedValue.rawMax + property alias step : _rangedValue.rawStep + property alias precision : _rangedValue.precision property bool showButtons : true property bool buttonsEnabled : true property bool dropShadowEnabled : true @@ -31,60 +31,8 @@ signal increment(real newValue) signal decrement(real newValue) - QtObject { id: _private - // fix floating-point precision issue - readonly property int multiplier : Math.pow(10, precision) - readonly property real stepVal : calculatePrecisionValue(step) - readonly property real minVal : minimum !== undefined ? calculatePrecisionValue(minimum) : 0 - readonly property real maxVal : maximum !== undefined ? calculatePrecisionValue(maximum) : 0 - readonly property real val : value !== undefined ? calculatePrecisionValue(value) : 0 - - readonly property bool canDecrement : val > calculateMinimum() - readonly property bool canIncrement : val < calculateMaximum() - - // round the value based on the given precision (not step) - function calculatePrecisionValue(value) { - return Math.round(value * _private.multiplier) / _private.multiplier - } - - // calculate the minimum value rounded up to the next higher step size - function calculateMinimum() { - let fixedMin = _private.fixedValue(_private.minVal) - let fixedStep = _private.fixedValue(_private.stepVal) - return (Math.ceil(fixedMin / fixedStep) * fixedStep) / _private.multiplier - } - - // calculate the maximum value rounded down to the next higher step size - function calculateMaximum() { - let fixedMax = _private.fixedValue(_private.maxVal) - let fixedStep = _private.fixedValue(_private.stepVal) - return (Math.floor(fixedMax / fixedStep) * fixedStep) / _private.multiplier - } - - // return a fixed point int from the inputted float (using the set precision) - function fixedValue(value) { - return Math.round(value * _private.multiplier) - } - - function incrementedValue() { - let fixedVal = _private.fixedValue(_private.val) - let fixedStep = _private.fixedValue(_private.stepVal) - let fixedDelta = fixedStep - (fixedVal % fixedStep) - return Math.max( - _private.minVal, - Math.min(_private.maxVal, (fixedVal + fixedDelta) / _private.multiplier) - ) - } - - function decrementedValue() { - let fixedVal = _private.fixedValue(_private.val) - let fixedStep = _private.fixedValue(_private.stepVal) - let fixedDelta = fixedVal % fixedStep - return Math.min( - _private.maxVal, - Math.max(_private.minVal, (fixedVal - (fixedDelta > 0 ? fixedDelta : fixedStep)) / _private.multiplier) - ) - } + RangedValue { id: _rangedValue + objectName: "_rangedValue" } Text { id: _title @@ -163,17 +111,17 @@ ArrowButton {id : _upArrowIcon objectName : "upArrowIcon" upArrow : true - enabled : buttonsEnabled && _private.canIncrement + enabled : buttonsEnabled && _rangedValue.canIncrement - onClicked : { _root.increment(_private.incrementedValue()) } + onClicked : { _root.increment(_rangedValue.incrementedValue()) } } ArrowButton {id : _downArrowIcon objectName : "downArrowIcon" downArrow : true - enabled : buttonsEnabled && _private.canDecrement + enabled : buttonsEnabled && _rangedValue.canDecrement - onClicked : { _root.decrement(_private.decrementedValue()) } + onClicked : { _root.decrement(_rangedValue.decrementedValue()) } } } }